1 /*
2 * xmlIO.c : implementation of the I/O interfaces used by the parser
3 *
4 * See Copyright for the status of this software.
5 *
6 * [email protected]
7 */
8
9 #define IN_LIBXML
10 #include "libxml.h"
11
12 #include <string.h>
13 #include <stdlib.h>
14 #include <errno.h>
15
16 #include <fcntl.h>
17 #include <sys/stat.h>
18
19 #if defined(_WIN32)
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <io.h>
23 #include <direct.h>
24 #else
25 #include <unistd.h>
26 #endif
27
28 #ifdef LIBXML_ZLIB_ENABLED
29 #include <zlib.h>
30 #endif
31 #ifdef LIBXML_LZMA_ENABLED
32 #include <lzma.h>
33 #endif
34
35 #include <libxml/xmlIO.h>
36 #include <libxml/xmlmemory.h>
37 #include <libxml/uri.h>
38 #include <libxml/nanohttp.h>
39 #include <libxml/parserInternals.h>
40 #include <libxml/xmlerror.h>
41 #ifdef LIBXML_CATALOG_ENABLED
42 #include <libxml/catalog.h>
43 #endif
44
45 #include "private/buf.h"
46 #include "private/enc.h"
47 #include "private/entities.h"
48 #include "private/error.h"
49 #include "private/io.h"
50
51 #ifndef SIZE_MAX
52 #define SIZE_MAX ((size_t) -1)
53 #endif
54
55 /* #define VERBOSE_FAILURE */
56
57 #define MINLEN 4000
58
59 #ifndef STDOUT_FILENO
60 #define STDOUT_FILENO 1
61 #endif
62
63 #ifndef S_ISDIR
64 # ifdef _S_ISDIR
65 # define S_ISDIR(x) _S_ISDIR(x)
66 # elif defined(S_IFDIR)
67 # ifdef S_IFMT
68 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
69 # elif defined(_S_IFMT)
70 # define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR)
71 # endif
72 # endif
73 #endif
74
75 /*
76 * Input I/O callback sets
77 */
78 typedef struct _xmlInputCallback {
79 xmlInputMatchCallback matchcallback;
80 xmlInputOpenCallback opencallback;
81 xmlInputReadCallback readcallback;
82 xmlInputCloseCallback closecallback;
83 } xmlInputCallback;
84
85 /* This dummy function only marks default IO in the callback table */
86 static int
87 xmlIODefaultMatch(const char *filename);
88
89 #define MAX_INPUT_CALLBACK 10
90
91 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
92 static int xmlInputCallbackNr;
93
94 #ifdef LIBXML_OUTPUT_ENABLED
95 /*
96 * Output I/O callback sets
97 */
98 typedef struct _xmlOutputCallback {
99 xmlOutputMatchCallback matchcallback;
100 xmlOutputOpenCallback opencallback;
101 xmlOutputWriteCallback writecallback;
102 xmlOutputCloseCallback closecallback;
103 } xmlOutputCallback;
104
105 #define MAX_OUTPUT_CALLBACK 10
106
107 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
108 static int xmlOutputCallbackNr;
109 #endif /* LIBXML_OUTPUT_ENABLED */
110
111 /************************************************************************
112 * *
113 * Error handling *
114 * *
115 ************************************************************************/
116
117 /**
118 * xmlIOErr:
119 * @code: the error number
120 *
121 * Convert errno to xmlParserErrors.
122 *
123 * Returns an xmlParserErrors code.
124 */
125 static int
xmlIOErr(int err)126 xmlIOErr(int err)
127 {
128 int code;
129
130 if (err == 0) code = XML_IO_UNKNOWN;
131 #ifdef EACCES
132 else if (err == EACCES) code = XML_IO_EACCES;
133 #endif
134 #ifdef EAGAIN
135 else if (err == EAGAIN) code = XML_IO_EAGAIN;
136 #endif
137 #ifdef EBADF
138 else if (err == EBADF) code = XML_IO_EBADF;
139 #endif
140 #ifdef EBADMSG
141 else if (err == EBADMSG) code = XML_IO_EBADMSG;
142 #endif
143 #ifdef EBUSY
144 else if (err == EBUSY) code = XML_IO_EBUSY;
145 #endif
146 #ifdef ECANCELED
147 else if (err == ECANCELED) code = XML_IO_ECANCELED;
148 #endif
149 #ifdef ECHILD
150 else if (err == ECHILD) code = XML_IO_ECHILD;
151 #endif
152 #ifdef EDEADLK
153 else if (err == EDEADLK) code = XML_IO_EDEADLK;
154 #endif
155 #ifdef EDOM
156 else if (err == EDOM) code = XML_IO_EDOM;
157 #endif
158 #ifdef EEXIST
159 else if (err == EEXIST) code = XML_IO_EEXIST;
160 #endif
161 #ifdef EFAULT
162 else if (err == EFAULT) code = XML_IO_EFAULT;
163 #endif
164 #ifdef EFBIG
165 else if (err == EFBIG) code = XML_IO_EFBIG;
166 #endif
167 #ifdef EINPROGRESS
168 else if (err == EINPROGRESS) code = XML_IO_EINPROGRESS;
169 #endif
170 #ifdef EINTR
171 else if (err == EINTR) code = XML_IO_EINTR;
172 #endif
173 #ifdef EINVAL
174 else if (err == EINVAL) code = XML_IO_EINVAL;
175 #endif
176 #ifdef EIO
177 else if (err == EIO) code = XML_IO_EIO;
178 #endif
179 #ifdef EISDIR
180 else if (err == EISDIR) code = XML_IO_EISDIR;
181 #endif
182 #ifdef EMFILE
183 else if (err == EMFILE) code = XML_IO_EMFILE;
184 #endif
185 #ifdef EMLINK
186 else if (err == EMLINK) code = XML_IO_EMLINK;
187 #endif
188 #ifdef EMSGSIZE
189 else if (err == EMSGSIZE) code = XML_IO_EMSGSIZE;
190 #endif
191 #ifdef ENAMETOOLONG
192 else if (err == ENAMETOOLONG) code = XML_IO_ENAMETOOLONG;
193 #endif
194 #ifdef ENFILE
195 else if (err == ENFILE) code = XML_IO_ENFILE;
196 #endif
197 #ifdef ENODEV
198 else if (err == ENODEV) code = XML_IO_ENODEV;
199 #endif
200 #ifdef ENOENT
201 else if (err == ENOENT) code = XML_IO_ENOENT;
202 #endif
203 #ifdef ENOEXEC
204 else if (err == ENOEXEC) code = XML_IO_ENOEXEC;
205 #endif
206 #ifdef ENOLCK
207 else if (err == ENOLCK) code = XML_IO_ENOLCK;
208 #endif
209 #ifdef ENOMEM
210 else if (err == ENOMEM) code = XML_IO_ENOMEM;
211 #endif
212 #ifdef ENOSPC
213 else if (err == ENOSPC) code = XML_IO_ENOSPC;
214 #endif
215 #ifdef ENOSYS
216 else if (err == ENOSYS) code = XML_IO_ENOSYS;
217 #endif
218 #ifdef ENOTDIR
219 else if (err == ENOTDIR) code = XML_IO_ENOTDIR;
220 #endif
221 #ifdef ENOTEMPTY
222 else if (err == ENOTEMPTY) code = XML_IO_ENOTEMPTY;
223 #endif
224 #ifdef ENOTSUP
225 else if (err == ENOTSUP) code = XML_IO_ENOTSUP;
226 #endif
227 #ifdef ENOTTY
228 else if (err == ENOTTY) code = XML_IO_ENOTTY;
229 #endif
230 #ifdef ENXIO
231 else if (err == ENXIO) code = XML_IO_ENXIO;
232 #endif
233 #ifdef EPERM
234 else if (err == EPERM) code = XML_IO_EPERM;
235 #endif
236 #ifdef EPIPE
237 else if (err == EPIPE) code = XML_IO_EPIPE;
238 #endif
239 #ifdef ERANGE
240 else if (err == ERANGE) code = XML_IO_ERANGE;
241 #endif
242 #ifdef EROFS
243 else if (err == EROFS) code = XML_IO_EROFS;
244 #endif
245 #ifdef ESPIPE
246 else if (err == ESPIPE) code = XML_IO_ESPIPE;
247 #endif
248 #ifdef ESRCH
249 else if (err == ESRCH) code = XML_IO_ESRCH;
250 #endif
251 #ifdef ETIMEDOUT
252 else if (err == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
253 #endif
254 #ifdef EXDEV
255 else if (err == EXDEV) code = XML_IO_EXDEV;
256 #endif
257 #ifdef ENOTSOCK
258 else if (err == ENOTSOCK) code = XML_IO_ENOTSOCK;
259 #endif
260 #ifdef EISCONN
261 else if (err == EISCONN) code = XML_IO_EISCONN;
262 #endif
263 #ifdef ECONNREFUSED
264 else if (err == ECONNREFUSED) code = XML_IO_ECONNREFUSED;
265 #endif
266 #ifdef ETIMEDOUT
267 else if (err == ETIMEDOUT) code = XML_IO_ETIMEDOUT;
268 #endif
269 #ifdef ENETUNREACH
270 else if (err == ENETUNREACH) code = XML_IO_ENETUNREACH;
271 #endif
272 #ifdef EADDRINUSE
273 else if (err == EADDRINUSE) code = XML_IO_EADDRINUSE;
274 #endif
275 #ifdef EINPROGRESS
276 else if (err == EINPROGRESS) code = XML_IO_EINPROGRESS;
277 #endif
278 #ifdef EALREADY
279 else if (err == EALREADY) code = XML_IO_EALREADY;
280 #endif
281 #ifdef EAFNOSUPPORT
282 else if (err == EAFNOSUPPORT) code = XML_IO_EAFNOSUPPORT;
283 #endif
284 else code = XML_IO_UNKNOWN;
285
286 return(code);
287 }
288
289 /************************************************************************
290 * *
291 * Standard I/O for file accesses *
292 * *
293 ************************************************************************/
294
295 #if defined(_WIN32)
296
297 /**
298 * __xmlIOWin32UTF8ToWChar:
299 * @u8String: uft-8 string
300 *
301 * Convert a string from utf-8 to wchar (WINDOWS ONLY!)
302 */
303 static wchar_t *
__xmlIOWin32UTF8ToWChar(const char * u8String)304 __xmlIOWin32UTF8ToWChar(const char *u8String)
305 {
306 wchar_t *wString = NULL;
307 int i;
308
309 if (u8String) {
310 int wLen =
311 MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String,
312 -1, NULL, 0);
313 if (wLen) {
314 wString = xmlMalloc(wLen * sizeof(wchar_t));
315 if (wString) {
316 if (MultiByteToWideChar
317 (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) {
318 xmlFree(wString);
319 wString = NULL;
320 }
321 }
322
323 /*
324 * Convert to backward slash
325 */
326 for (i = 0; wString[i] != 0; i++) {
327 if (wString[i] == '/')
328 wString[i] = '\\';
329 }
330 }
331 }
332
333 return wString;
334 }
335
336 #endif
337
338 /**
339 * xmlNormalizeWindowsPath:
340 * @path: the input file path
341 *
342 * DEPRECATED: This never really worked.
343 *
344 * Returns a copy of path.
345 */
346 xmlChar *
xmlNormalizeWindowsPath(const xmlChar * path)347 xmlNormalizeWindowsPath(const xmlChar *path)
348 {
349 return xmlStrdup(path);
350 }
351
352 /**
353 * xmlCheckFilename:
354 * @path: the path to check
355 *
356 * DEPRECATED: Internal function, don't use.
357 *
358 * if stat is not available on the target machine,
359 * returns 1. if stat fails, returns 0 (if calling
360 * stat on the filename fails, it can't be right).
361 * if stat succeeds and the file is a directory,
362 * returns 2. otherwise returns 1.
363 */
364 int
xmlCheckFilename(const char * path)365 xmlCheckFilename(const char *path)
366 {
367 #if defined(_WIN32)
368 struct _stat stat_buffer;
369 #else
370 struct stat stat_buffer;
371 #endif
372 int res;
373
374 if (path == NULL)
375 return(0);
376
377 #if defined(_WIN32)
378 {
379 wchar_t *wpath;
380
381 /*
382 * On Windows stat and wstat do not work with long pathname,
383 * which start with '\\?\'
384 */
385 if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
386 (path[3] == '\\') )
387 return 1;
388
389 wpath = __xmlIOWin32UTF8ToWChar(path);
390 if (wpath == NULL)
391 return(0);
392 res = _wstat(wpath, &stat_buffer);
393 xmlFree(wpath);
394 }
395 #else
396 res = stat(path, &stat_buffer);
397 #endif
398
399 if (res < 0)
400 return 0;
401
402 #ifdef S_ISDIR
403 if (S_ISDIR(stat_buffer.st_mode))
404 return 2;
405 #endif
406
407 return 1;
408 }
409
410 static int
xmlConvertUriToPath(const char * uri,char ** out)411 xmlConvertUriToPath(const char *uri, char **out) {
412 const char *escaped;
413 char *unescaped;
414
415 *out = NULL;
416
417 if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file://localhost/", 17)) {
418 escaped = &uri[16];
419 } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:///", 8)) {
420 escaped = &uri[7];
421 } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:/", 6)) {
422 /* lots of generators seems to lazy to read RFC 1738 */
423 escaped = &uri[5];
424 } else {
425 return(1);
426 }
427
428 #ifdef _WIN32
429 /* Ignore slash like in file:///C:/file.txt */
430 escaped += 1;
431 #endif
432
433 unescaped = xmlURIUnescapeString(escaped, 0, NULL);
434 if (unescaped == NULL)
435 return(-1);
436
437 *out = unescaped;
438 return(0);
439 }
440
441 /**
442 * xmlFdOpen:
443 * @filename: the URI for matching
444 * @out: pointer to resulting context
445 *
446 * Returns an xmlParserErrors code
447 */
448 static int
xmlFdOpen(const char * filename,int write,int * out)449 xmlFdOpen(const char *filename, int write, int *out) {
450 char *fromUri = NULL;
451 int flags;
452 int fd;
453 int ret;
454
455 *out = -1;
456 if (filename == NULL)
457 return(XML_ERR_ARGUMENT);
458
459 if (xmlConvertUriToPath(filename, &fromUri) < 0)
460 return(XML_ERR_NO_MEMORY);
461
462 if (fromUri != NULL)
463 filename = fromUri;
464
465 #if defined(_WIN32)
466 {
467 wchar_t *wpath;
468
469 wpath = __xmlIOWin32UTF8ToWChar(filename);
470 if (wpath == NULL) {
471 xmlFree(fromUri);
472 return(XML_ERR_NO_MEMORY);
473 }
474 if (write)
475 flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
476 else
477 flags = _O_RDONLY;
478 fd = _wopen(wpath, flags | _O_BINARY, 0666);
479 xmlFree(wpath);
480 }
481 #else
482 if (write)
483 flags = O_WRONLY | O_CREAT | O_TRUNC;
484 else
485 flags = O_RDONLY;
486 fd = open(filename, flags, 0666);
487 #endif /* WIN32 */
488
489 if (fd < 0) {
490 /*
491 * Windows and possibly other platforms return EINVAL
492 * for invalid filenames.
493 */
494 if ((errno == ENOENT) || (errno == EINVAL)) {
495 ret = XML_IO_ENOENT;
496 } else {
497 ret = xmlIOErr(errno);
498 }
499 } else {
500 *out = fd;
501 ret = XML_ERR_OK;
502 }
503
504 xmlFree(fromUri);
505 return(ret);
506 }
507
508 /**
509 * xmlFdRead:
510 * @context: the I/O context
511 * @buffer: where to drop data
512 * @len: number of bytes to read
513 *
514 * Read @len bytes to @buffer from the I/O channel.
515 *
516 * Returns the number of bytes read
517 */
518 static int
xmlFdRead(void * context,char * buffer,int len)519 xmlFdRead(void *context, char *buffer, int len) {
520 int fd = (int) (ptrdiff_t) context;
521 int ret = 0;
522 int bytes;
523
524 while (len > 0) {
525 bytes = read(fd, buffer, len);
526 if (bytes < 0) {
527 /*
528 * If we already got some bytes, return them without
529 * raising an error.
530 */
531 if (ret > 0)
532 break;
533 return(-xmlIOErr(errno));
534 }
535 if (bytes == 0)
536 break;
537 ret += bytes;
538 buffer += bytes;
539 len -= bytes;
540 }
541
542 return(ret);
543 }
544
545 #ifdef LIBXML_OUTPUT_ENABLED
546 /**
547 * xmlFdWrite:
548 * @context: the I/O context
549 * @buffer: where to get data
550 * @len: number of bytes to write
551 *
552 * Write @len bytes from @buffer to the I/O channel.
553 *
554 * Returns the number of bytes written
555 */
556 static int
xmlFdWrite(void * context,const char * buffer,int len)557 xmlFdWrite(void *context, const char *buffer, int len) {
558 int fd = (int) (ptrdiff_t) context;
559 int ret = 0;
560 int bytes;
561
562 while (len > 0) {
563 bytes = write(fd, buffer, len);
564 if (bytes < 0)
565 return(-xmlIOErr(errno));
566 ret += bytes;
567 buffer += bytes;
568 len -= bytes;
569 }
570
571 return(ret);
572 }
573 #endif /* LIBXML_OUTPUT_ENABLED */
574
575 /**
576 * xmlFdClose:
577 * @context: the I/O context
578 *
579 * Close an I/O channel
580 *
581 * Returns 0 in case of success and error code otherwise
582 */
583 static int
xmlFdClose(void * context)584 xmlFdClose (void * context) {
585 int ret;
586
587 ret = close((int) (ptrdiff_t) context);
588 if (ret < 0)
589 return(xmlIOErr(errno));
590
591 return(XML_ERR_OK);
592 }
593
594 /**
595 * xmlFileMatch:
596 * @filename: the URI for matching
597 *
598 * DEPRECATED: Internal function, don't use.
599 *
600 * Returns 1 if matches, 0 otherwise
601 */
602 int
xmlFileMatch(const char * filename ATTRIBUTE_UNUSED)603 xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) {
604 return(1);
605 }
606
607 /**
608 * xmlFileOpenSafe:
609 * @filename: the URI for matching
610 * @out: pointer to resulting context
611 *
612 * input from FILE *
613 *
614 * Returns an I/O context or NULL in case of error
615 */
616 static int
xmlFileOpenSafe(const char * filename,int write,void ** out)617 xmlFileOpenSafe(const char *filename, int write, void **out) {
618 char *fromUri = NULL;
619 FILE *fd;
620 int ret = XML_ERR_OK;
621
622 *out = NULL;
623 if (filename == NULL)
624 return(XML_ERR_ARGUMENT);
625
626 if (xmlConvertUriToPath(filename, &fromUri) < 0)
627 return(XML_ERR_NO_MEMORY);
628
629 if (fromUri != NULL)
630 filename = fromUri;
631
632 #if defined(_WIN32)
633 {
634 wchar_t *wpath;
635
636 wpath = __xmlIOWin32UTF8ToWChar(filename);
637 if (wpath == NULL) {
638 xmlFree(fromUri);
639 return(XML_ERR_NO_MEMORY);
640 }
641 fd = _wfopen(wpath, write ? L"wb" : L"rb");
642 xmlFree(wpath);
643 }
644 #else
645 fd = fopen(filename, write ? "wb" : "rb");
646 #endif /* WIN32 */
647
648 if (fd == NULL) {
649 /*
650 * Windows and possibly other platforms return EINVAL
651 * for invalid filenames.
652 */
653 if ((errno == ENOENT) || (errno == EINVAL)) {
654 ret = XML_IO_ENOENT;
655 } else {
656 /*
657 * This error won't be forwarded to the parser context
658 * which will report it a second time.
659 */
660 ret = xmlIOErr(errno);
661 }
662 }
663
664 *out = fd;
665 xmlFree(fromUri);
666 return(ret);
667 }
668
669 /**
670 * xmlFileOpen:
671 * @filename: the URI for matching
672 *
673 * DEPRECATED: Internal function, don't use.
674 *
675 * Returns an IO context or NULL in case or failure
676 */
677 void *
xmlFileOpen(const char * filename)678 xmlFileOpen(const char *filename) {
679 void *context;
680
681 xmlFileOpenSafe(filename, 0, &context);
682 return(context);
683 }
684
685 /**
686 * xmlFileRead:
687 * @context: the I/O context
688 * @buffer: where to drop data
689 * @len: number of bytes to write
690 *
691 * DEPRECATED: Internal function, don't use.
692 *
693 * Returns the number of bytes read or < 0 in case of failure
694 */
695 int
xmlFileRead(void * context,char * buffer,int len)696 xmlFileRead(void * context, char * buffer, int len) {
697 FILE *file = context;
698 size_t bytes;
699
700 if ((context == NULL) || (buffer == NULL))
701 return(-1);
702
703 /*
704 * The C standard doesn't mandate that fread sets errno, only
705 * POSIX does. The Windows documentation isn't really clear.
706 * Set errno to zero which will be reported as unknown error
707 * if fread fails without setting errno.
708 */
709 errno = 0;
710 bytes = fread(buffer, 1, len, file);
711 if ((bytes < (size_t) len) && (ferror(file)))
712 return(-xmlIOErr(errno));
713
714 return(bytes);
715 }
716
717 #ifdef LIBXML_OUTPUT_ENABLED
718 /**
719 * xmlFileWrite:
720 * @context: the I/O context
721 * @buffer: where to drop data
722 * @len: number of bytes to write
723 *
724 * Write @len bytes from @buffer to the I/O channel.
725 *
726 * Returns the number of bytes written
727 */
728 static int
xmlFileWrite(void * context,const char * buffer,int len)729 xmlFileWrite(void *context, const char *buffer, int len) {
730 FILE *file = context;
731 size_t bytes;
732
733 if ((context == NULL) || (buffer == NULL))
734 return(-1);
735
736 errno = 0;
737 bytes = fwrite(buffer, 1, len, file);
738 if (bytes < (size_t) len)
739 return(-xmlIOErr(errno));
740
741 return(len);
742 }
743 #endif /* LIBXML_OUTPUT_ENABLED */
744
745 /**
746 * xmlFileFlush:
747 * @context: the I/O context
748 *
749 * Flush an I/O channel
750 */
751 static int
xmlFileFlush(void * context)752 xmlFileFlush (void * context) {
753 FILE *file = context;
754
755 if (file == NULL)
756 return(-1);
757
758 if (fflush(file) != 0)
759 return(xmlIOErr(errno));
760
761 return(XML_ERR_OK);
762 }
763
764 /**
765 * xmlFileClose:
766 * @context: the I/O context
767 *
768 * DEPRECATED: Internal function, don't use.
769 *
770 * Returns 0 or -1 an error code case of error
771 */
772 int
xmlFileClose(void * context)773 xmlFileClose (void * context) {
774 FILE *file = context;
775
776 if (context == NULL)
777 return(-1);
778
779 if (file == stdin)
780 return(0);
781 if ((file == stdout) || (file == stderr))
782 return(xmlFileFlush(file));
783
784 if (fclose(file) != 0)
785 return(xmlIOErr(errno));
786
787 return(0);
788 }
789
790 #ifdef LIBXML_OUTPUT_ENABLED
791 /**
792 * xmlBufferWrite:
793 * @context: the xmlBuffer
794 * @buffer: the data to write
795 * @len: number of bytes to write
796 *
797 * Write @len bytes from @buffer to the xml buffer
798 *
799 * Returns the number of bytes written or a negative xmlParserErrors
800 * value.
801 */
802 static int
xmlBufferWrite(void * context,const char * buffer,int len)803 xmlBufferWrite (void * context, const char * buffer, int len) {
804 int ret;
805
806 ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len);
807 if (ret != 0)
808 return(-XML_ERR_NO_MEMORY);
809 return(len);
810 }
811 #endif
812
813 #ifdef LIBXML_ZLIB_ENABLED
814 /************************************************************************
815 * *
816 * I/O for compressed file accesses *
817 * *
818 ************************************************************************/
819
820 /**
821 * xmlGzfileRead:
822 * @context: the I/O context
823 * @buffer: where to drop data
824 * @len: number of bytes to write
825 *
826 * Read @len bytes to @buffer from the compressed I/O channel.
827 *
828 * Returns the number of bytes read.
829 */
830 static int
xmlGzfileRead(void * context,char * buffer,int len)831 xmlGzfileRead (void * context, char * buffer, int len) {
832 int ret;
833
834 ret = gzread((gzFile) context, &buffer[0], len);
835 if (ret < 0)
836 return(-XML_IO_UNKNOWN);
837 return(ret);
838 }
839
840 #ifdef LIBXML_OUTPUT_ENABLED
841 /**
842 * xmlGzfileWrite:
843 * @context: the I/O context
844 * @buffer: where to drop data
845 * @len: number of bytes to write
846 *
847 * Write @len bytes from @buffer to the compressed I/O channel.
848 *
849 * Returns the number of bytes written
850 */
851 static int
xmlGzfileWrite(void * context,const char * buffer,int len)852 xmlGzfileWrite (void * context, const char * buffer, int len) {
853 int ret;
854
855 ret = gzwrite((gzFile) context, (char *) &buffer[0], len);
856 if (ret < 0)
857 return(-XML_IO_UNKNOWN);
858 return(ret);
859 }
860 #endif /* LIBXML_OUTPUT_ENABLED */
861
862 /**
863 * xmlGzfileClose:
864 * @context: the I/O context
865 *
866 * Close a compressed I/O channel
867 */
868 static int
xmlGzfileClose(void * context)869 xmlGzfileClose (void * context) {
870 if (gzclose((gzFile) context) != Z_OK)
871 return(XML_IO_UNKNOWN);
872 return(0);
873 }
874 #endif /* LIBXML_ZLIB_ENABLED */
875
876 /************************************************************************
877 * *
878 * I/O for compressed file accesses *
879 * *
880 ************************************************************************/
881
882 #ifdef LIBXML_LZMA_ENABLED
883
884 #include "private/xzlib.h"
885
886 /**
887 * xmlXzfileRead:
888 * @context: the I/O context
889 * @buffer: where to drop data
890 * @len: number of bytes to write
891 *
892 * Read @len bytes to @buffer from the compressed I/O channel.
893 *
894 * Returns the number of bytes written
895 */
896 static int
xmlXzfileRead(void * context,char * buffer,int len)897 xmlXzfileRead (void * context, char * buffer, int len) {
898 int ret;
899
900 ret = __libxml2_xzread((xzFile) context, &buffer[0], len);
901 if (ret < 0)
902 return(-XML_IO_UNKNOWN);
903 return(ret);
904 }
905
906 /**
907 * xmlXzfileClose:
908 * @context: the I/O context
909 *
910 * Close a compressed I/O channel
911 */
912 static int
xmlXzfileClose(void * context)913 xmlXzfileClose (void * context) {
914 if (__libxml2_xzclose((xzFile) context) != LZMA_OK)
915 return(XML_IO_UNKNOWN);
916 return(0);
917 }
918 #endif /* LIBXML_LZMA_ENABLED */
919
920 /************************************************************************
921 * *
922 * I/O for HTTP file accesses *
923 * *
924 ************************************************************************/
925
926 #ifdef LIBXML_HTTP_ENABLED
927 /**
928 * xmlIOHTTPMatch:
929 * @filename: the URI for matching
930 *
931 * DEPRECATED: Internal function, don't use.
932 *
933 * check if the URI matches an HTTP one
934 *
935 * Returns 1 if matches, 0 otherwise
936 */
937 int
xmlIOHTTPMatch(const char * filename)938 xmlIOHTTPMatch (const char *filename) {
939 if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "http://", 7))
940 return(1);
941 return(0);
942 }
943
944 /**
945 * xmlIOHTTPOpen:
946 * @filename: the URI for matching
947 *
948 * DEPRECATED: Internal function, don't use.
949 *
950 * open an HTTP I/O channel
951 *
952 * Returns an I/O context or NULL in case of error
953 */
954 void *
xmlIOHTTPOpen(const char * filename)955 xmlIOHTTPOpen (const char *filename) {
956 return(xmlNanoHTTPOpen(filename, NULL));
957 }
958
959 #ifdef LIBXML_OUTPUT_ENABLED
960 /**
961 * xmlIOHTTPOpenW:
962 * @post_uri: The destination URI for the document
963 * @compression: The compression desired for the document.
964 *
965 * DEPRECATED: Support for HTTP POST has been removed.
966 *
967 * Returns NULL.
968 */
969 void *
xmlIOHTTPOpenW(const char * post_uri ATTRIBUTE_UNUSED,int compression ATTRIBUTE_UNUSED)970 xmlIOHTTPOpenW(const char *post_uri ATTRIBUTE_UNUSED,
971 int compression ATTRIBUTE_UNUSED)
972 {
973 return(NULL);
974 }
975 #endif /* LIBXML_OUTPUT_ENABLED */
976
977 /**
978 * xmlIOHTTPRead:
979 * @context: the I/O context
980 * @buffer: where to drop data
981 * @len: number of bytes to write
982 *
983 * DEPRECATED: Internal function, don't use.
984 *
985 * Read @len bytes to @buffer from the I/O channel.
986 *
987 * Returns the number of bytes written
988 */
989 int
xmlIOHTTPRead(void * context,char * buffer,int len)990 xmlIOHTTPRead(void * context, char * buffer, int len) {
991 if ((buffer == NULL) || (len < 0)) return(-1);
992 return(xmlNanoHTTPRead(context, &buffer[0], len));
993 }
994
995 /**
996 * xmlIOHTTPClose:
997 * @context: the I/O context
998 *
999 * DEPRECATED: Internal function, don't use.
1000 *
1001 * Close an HTTP I/O channel
1002 *
1003 * Returns 0
1004 */
1005 int
xmlIOHTTPClose(void * context)1006 xmlIOHTTPClose (void * context) {
1007 xmlNanoHTTPClose(context);
1008 return 0;
1009 }
1010 #endif /* LIBXML_HTTP_ENABLED */
1011
1012 /************************************************************************
1013 * *
1014 * Input/output buffers *
1015 * *
1016 ************************************************************************/
1017
1018 static int
xmlIODefaultMatch(const char * filename ATTRIBUTE_UNUSED)1019 xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) {
1020 return(1);
1021 }
1022
1023 /**
1024 * xmlInputDefaultOpen:
1025 * @buf: input buffer to be filled
1026 * @filename: filename or URI
1027 * @flags: XML_INPUT flags
1028 *
1029 * Returns an xmlParserErrors code.
1030 */
1031 static int
xmlInputDefaultOpen(xmlParserInputBufferPtr buf,const char * filename,int flags)1032 xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename,
1033 int flags) {
1034 int ret;
1035 int fd;
1036
1037 /* Avoid unused variable warning */
1038 (void) flags;
1039
1040 #ifdef LIBXML_HTTP_ENABLED
1041 if (xmlIOHTTPMatch(filename)) {
1042 if ((flags & XML_INPUT_NETWORK) == 0)
1043 return(XML_IO_NETWORK_ATTEMPT);
1044
1045 buf->context = xmlIOHTTPOpen(filename);
1046
1047 if (buf->context != NULL) {
1048 buf->readcallback = xmlIOHTTPRead;
1049 buf->closecallback = xmlIOHTTPClose;
1050 return(XML_ERR_OK);
1051 }
1052 }
1053 #endif /* LIBXML_HTTP_ENABLED */
1054
1055 if (!xmlFileMatch(filename))
1056 return(XML_IO_ENOENT);
1057
1058 #ifdef LIBXML_LZMA_ENABLED
1059 if (flags & XML_INPUT_UNZIP) {
1060 xzFile xzStream;
1061
1062 ret = xmlFdOpen(filename, 0, &fd);
1063 if (ret != XML_ERR_OK)
1064 return(ret);
1065
1066 xzStream = __libxml2_xzdopen(filename, fd, "rb");
1067
1068 if (xzStream == NULL) {
1069 close(fd);
1070 } else {
1071 if (__libxml2_xzcompressed(xzStream) > 0) {
1072 buf->context = xzStream;
1073 buf->readcallback = xmlXzfileRead;
1074 buf->closecallback = xmlXzfileClose;
1075 buf->compressed = 1;
1076
1077 return(XML_ERR_OK);
1078 }
1079
1080 xmlXzfileClose(xzStream);
1081 }
1082 }
1083 #endif /* LIBXML_LZMA_ENABLED */
1084
1085 #ifdef LIBXML_ZLIB_ENABLED
1086 if (flags & XML_INPUT_UNZIP) {
1087 gzFile gzStream;
1088
1089 ret = xmlFdOpen(filename, 0, &fd);
1090 if (ret != XML_ERR_OK)
1091 return(ret);
1092
1093 gzStream = gzdopen(fd, "rb");
1094
1095 if (gzStream == NULL) {
1096 close(fd);
1097 } else {
1098 char buff4[4];
1099
1100 if ((gzread(gzStream, buff4, 4) > 0) &&
1101 (gzdirect(gzStream) == 0)) {
1102 gzrewind(gzStream);
1103
1104 buf->context = gzStream;
1105 buf->readcallback = xmlGzfileRead;
1106 buf->closecallback = xmlGzfileClose;
1107 buf->compressed = 1;
1108
1109 return(XML_ERR_OK);
1110 }
1111
1112 xmlGzfileClose(gzStream);
1113 }
1114 }
1115 #endif /* LIBXML_ZLIB_ENABLED */
1116
1117 ret = xmlFdOpen(filename, 0, &fd);
1118 if (ret != XML_ERR_OK)
1119 return(ret);
1120
1121 buf->context = (void *) (ptrdiff_t) fd;
1122 buf->readcallback = xmlFdRead;
1123 buf->closecallback = xmlFdClose;
1124 return(XML_ERR_OK);
1125 }
1126
1127 #ifdef LIBXML_OUTPUT_ENABLED
1128 /**
1129 * xmlOutputDefaultOpen:
1130 * @buf: input buffer to be filled
1131 * @filename: filename or URI
1132 * @compression: compression level or 0
1133 * @is_file_uri: whether filename is a file URI
1134 *
1135 * Returns an xmlParserErrors code.
1136 */
1137 static int
xmlOutputDefaultOpen(xmlOutputBufferPtr buf,const char * filename,int compression)1138 xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename,
1139 int compression) {
1140 int fd;
1141
1142 (void) compression;
1143
1144 if (!strcmp(filename, "-")) {
1145 fd = dup(STDOUT_FILENO);
1146
1147 if (fd < 0)
1148 return(xmlIOErr(errno));
1149 } else {
1150 int ret;
1151
1152 ret = xmlFdOpen(filename, /* write */ 1, &fd);
1153 if (ret != XML_ERR_OK)
1154 return(ret);
1155 }
1156
1157 #ifdef LIBXML_ZLIB_ENABLED
1158 if ((compression > 0) && (compression <= 9)) {
1159 gzFile gzStream;
1160 char mode[15];
1161
1162 snprintf(mode, sizeof(mode), "wb%d", compression);
1163 gzStream = gzdopen(fd, mode);
1164
1165 if (gzStream == NULL) {
1166 close(fd);
1167 return(XML_IO_UNKNOWN);
1168 }
1169
1170 buf->context = gzStream;
1171 buf->writecallback = xmlGzfileWrite;
1172 buf->closecallback = xmlGzfileClose;
1173
1174 return(XML_ERR_OK);
1175 }
1176 #endif /* LIBXML_ZLIB_ENABLED */
1177
1178 buf->context = (void *) (ptrdiff_t) fd;
1179 buf->writecallback = xmlFdWrite;
1180 buf->closecallback = xmlFdClose;
1181 return(XML_ERR_OK);
1182 }
1183 #endif
1184
1185 /**
1186 * xmlAllocParserInputBuffer:
1187 * @enc: the charset encoding if known (deprecated)
1188 *
1189 * DEPRECATED: Use xmlNewInputFrom*.
1190 *
1191 * Create a buffered parser input for progressive parsing.
1192 *
1193 * The encoding argument is deprecated and should be set to
1194 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1195 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1196 *
1197 * Returns the new parser input or NULL
1198 */
1199 xmlParserInputBufferPtr
xmlAllocParserInputBuffer(xmlCharEncoding enc)1200 xmlAllocParserInputBuffer(xmlCharEncoding enc) {
1201 xmlParserInputBufferPtr ret;
1202
1203 ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1204 if (ret == NULL) {
1205 return(NULL);
1206 }
1207 memset(ret, 0, sizeof(xmlParserInputBuffer));
1208 ret->buffer = xmlBufCreate(XML_IO_BUFFER_SIZE);
1209 if (ret->buffer == NULL) {
1210 xmlFree(ret);
1211 return(NULL);
1212 }
1213 if (enc != XML_CHAR_ENCODING_NONE) {
1214 if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != 0) {
1215 /* We can't handle errors properly here. */
1216 xmlFreeParserInputBuffer(ret);
1217 return(NULL);
1218 }
1219 }
1220 if (ret->encoder != NULL)
1221 ret->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
1222 else
1223 ret->raw = NULL;
1224 ret->readcallback = NULL;
1225 ret->closecallback = NULL;
1226 ret->context = NULL;
1227 ret->compressed = -1;
1228 ret->rawconsumed = 0;
1229
1230 return(ret);
1231 }
1232
1233 #ifdef LIBXML_OUTPUT_ENABLED
1234 /**
1235 * xmlAllocOutputBuffer:
1236 * @encoder: the encoding converter or NULL
1237 *
1238 * Create a buffered parser output
1239 *
1240 * Consumes @encoder even in error case.
1241 *
1242 * Returns the new parser output or NULL
1243 */
1244 xmlOutputBufferPtr
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder)1245 xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
1246 xmlOutputBufferPtr ret;
1247
1248 ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
1249 if (ret == NULL) {
1250 xmlCharEncCloseFunc(encoder);
1251 return(NULL);
1252 }
1253 memset(ret, 0, sizeof(xmlOutputBuffer));
1254 ret->buffer = xmlBufCreate(MINLEN);
1255 if (ret->buffer == NULL) {
1256 xmlCharEncCloseFunc(encoder);
1257 xmlFree(ret);
1258 return(NULL);
1259 }
1260
1261 ret->encoder = encoder;
1262 if (encoder != NULL) {
1263 ret->conv = xmlBufCreate(MINLEN);
1264 if (ret->conv == NULL) {
1265 xmlOutputBufferClose(ret);
1266 return(NULL);
1267 }
1268
1269 /*
1270 * This call is designed to initiate the encoder state
1271 */
1272 xmlCharEncOutput(ret, 1);
1273 } else
1274 ret->conv = NULL;
1275 ret->writecallback = NULL;
1276 ret->closecallback = NULL;
1277 ret->context = NULL;
1278 ret->written = 0;
1279
1280 return(ret);
1281 }
1282 #endif /* LIBXML_OUTPUT_ENABLED */
1283
1284 /**
1285 * xmlFreeParserInputBuffer:
1286 * @in: a buffered parser input
1287 *
1288 * Free up the memory used by a buffered parser input
1289 */
1290 void
xmlFreeParserInputBuffer(xmlParserInputBufferPtr in)1291 xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1292 if (in == NULL) return;
1293
1294 if (in->raw) {
1295 xmlBufFree(in->raw);
1296 in->raw = NULL;
1297 }
1298 if (in->encoder != NULL) {
1299 xmlCharEncCloseFunc(in->encoder);
1300 }
1301 if (in->closecallback != NULL) {
1302 in->closecallback(in->context);
1303 }
1304 if (in->buffer != NULL) {
1305 xmlBufFree(in->buffer);
1306 in->buffer = NULL;
1307 }
1308
1309 xmlFree(in);
1310 }
1311
1312 #ifdef LIBXML_OUTPUT_ENABLED
1313 /**
1314 * xmlOutputBufferClose:
1315 * @out: a buffered output
1316 *
1317 * flushes and close the output I/O channel
1318 * and free up all the associated resources
1319 *
1320 * Returns the number of byte written or a negative xmlParserErrors
1321 * code in case of error.
1322 */
1323 int
xmlOutputBufferClose(xmlOutputBufferPtr out)1324 xmlOutputBufferClose(xmlOutputBufferPtr out)
1325 {
1326 int ret;
1327
1328 if (out == NULL)
1329 return (-1);
1330
1331 if (out->writecallback != NULL)
1332 xmlOutputBufferFlush(out);
1333
1334 if (out->closecallback != NULL) {
1335 int code = out->closecallback(out->context);
1336
1337 if ((code != XML_ERR_OK) && (out->error == XML_ERR_OK)) {
1338 if (code < 0)
1339 out->error = XML_IO_UNKNOWN;
1340 else
1341 out->error = code;
1342 }
1343 }
1344
1345 if (out->error != XML_ERR_OK)
1346 ret = -out->error;
1347 else
1348 ret = out->written;
1349
1350 if (out->conv) {
1351 xmlBufFree(out->conv);
1352 out->conv = NULL;
1353 }
1354 if (out->encoder != NULL) {
1355 xmlCharEncCloseFunc(out->encoder);
1356 }
1357 if (out->buffer != NULL) {
1358 xmlBufFree(out->buffer);
1359 out->buffer = NULL;
1360 }
1361
1362 xmlFree(out);
1363
1364 return(ret);
1365 }
1366 #endif /* LIBXML_OUTPUT_ENABLED */
1367
1368 /**
1369 * xmlParserInputBufferCreateUrl:
1370 * @URI: the filename or URI
1371 * @enc: encoding enum (deprecated)
1372 * @flags: XML_INPUT flags
1373 * @out: pointer to resulting input buffer
1374 *
1375 * Returns an xmlParserErrors code.
1376 */
1377 int
xmlParserInputBufferCreateUrl(const char * URI,xmlCharEncoding enc,int flags,xmlParserInputBufferPtr * out)1378 xmlParserInputBufferCreateUrl(const char *URI, xmlCharEncoding enc,
1379 int flags, xmlParserInputBufferPtr *out) {
1380 xmlParserInputBufferPtr buf;
1381 int ret;
1382 int i;
1383
1384 xmlInitParser();
1385
1386 *out = NULL;
1387 if (URI == NULL)
1388 return(XML_ERR_ARGUMENT);
1389
1390 /*
1391 * Allocate the Input buffer front-end.
1392 */
1393 buf = xmlAllocParserInputBuffer(enc);
1394 if (buf == NULL)
1395 return(XML_ERR_NO_MEMORY);
1396
1397 /*
1398 * Try to find one of the input accept method accepting that scheme
1399 * Go in reverse to give precedence to user defined handlers.
1400 */
1401 ret = XML_IO_ENOENT;
1402 for (i = xmlInputCallbackNr - 1; i >= 0; i--) {
1403 xmlInputCallback *cb = &xmlInputCallbackTable[i];
1404
1405 if (cb->matchcallback == xmlIODefaultMatch) {
1406 ret = xmlInputDefaultOpen(buf, URI, flags);
1407
1408 if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT))
1409 break;
1410 } else if ((cb->matchcallback != NULL) &&
1411 (cb->matchcallback(URI) != 0)) {
1412 buf->context = cb->opencallback(URI);
1413 if (buf->context != NULL) {
1414 buf->readcallback = cb->readcallback;
1415 buf->closecallback = cb->closecallback;
1416 ret = XML_ERR_OK;
1417 break;
1418 }
1419 }
1420 }
1421 if (ret != XML_ERR_OK) {
1422 xmlFreeParserInputBuffer(buf);
1423 *out = NULL;
1424 return(ret);
1425 }
1426
1427 *out = buf;
1428 return(ret);
1429 }
1430
1431 xmlParserInputBufferPtr
__xmlParserInputBufferCreateFilename(const char * URI,xmlCharEncoding enc)1432 __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1433 xmlParserInputBufferPtr ret;
1434
1435 xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1436 return(ret);
1437 }
1438
1439 /**
1440 * xmlParserInputBufferCreateFilename:
1441 * @URI: a C string containing the URI or filename
1442 * @enc: the charset encoding if known
1443 *
1444 * DEPRECATED: Use xmlNewInputFromUrl.
1445 *
1446 * Create a buffered parser input for the progressive parsing of a file
1447 * Automatic support for ZLIB/Compress compressed document is provided
1448 * by default if found at compile-time.
1449 * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1450 *
1451 * Returns the new parser input or NULL
1452 */
1453 xmlParserInputBufferPtr
xmlParserInputBufferCreateFilename(const char * URI,xmlCharEncoding enc)1454 xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1455 xmlParserInputBufferPtr ret;
1456
1457 if (xmlParserInputBufferCreateFilenameValue != NULL)
1458 return(xmlParserInputBufferCreateFilenameValue(URI, enc));
1459
1460 xmlParserInputBufferCreateUrl(URI, enc, 0, &ret);
1461 return(ret);
1462 }
1463
1464 #ifdef LIBXML_OUTPUT_ENABLED
1465 xmlOutputBufferPtr
__xmlOutputBufferCreateFilename(const char * URI,xmlCharEncodingHandlerPtr encoder,int compression)1466 __xmlOutputBufferCreateFilename(const char *URI,
1467 xmlCharEncodingHandlerPtr encoder,
1468 int compression) {
1469 xmlOutputBufferPtr ret;
1470 xmlURIPtr puri;
1471 int i = 0;
1472 char *unescaped = NULL;
1473
1474 xmlInitParser();
1475
1476 if (URI == NULL)
1477 return(NULL);
1478
1479 puri = xmlParseURI(URI);
1480 if (puri != NULL) {
1481 /*
1482 * try to limit the damages of the URI unescaping code.
1483 */
1484 if (puri->scheme == NULL) {
1485 unescaped = xmlURIUnescapeString(URI, 0, NULL);
1486 if (unescaped == NULL) {
1487 xmlFreeURI(puri);
1488 xmlCharEncCloseFunc(encoder);
1489 return(NULL);
1490 }
1491 URI = unescaped;
1492 }
1493 xmlFreeURI(puri);
1494 }
1495
1496 /*
1497 * Allocate the Output buffer front-end.
1498 */
1499 ret = xmlAllocOutputBuffer(encoder);
1500 if (ret == NULL) {
1501 xmlFree(unescaped);
1502 return(NULL);
1503 }
1504
1505 /*
1506 * Try to find one of the output accept method accepting that scheme
1507 * Go in reverse to give precedence to user defined handlers.
1508 */
1509 for (i = xmlOutputCallbackNr - 1; i >= 0; i--) {
1510 xmlOutputCallback *cb = &xmlOutputCallbackTable[i];
1511 int code;
1512
1513 if (cb->matchcallback == xmlIODefaultMatch) {
1514 code = xmlOutputDefaultOpen(ret, URI, compression);
1515 /* TODO: Handle other errors */
1516 if (code == XML_ERR_OK)
1517 break;
1518 } else if ((cb->matchcallback != NULL) &&
1519 (cb->matchcallback(URI) != 0)) {
1520 ret->context = cb->opencallback(URI);
1521 if (ret->context != NULL) {
1522 ret->writecallback = cb->writecallback;
1523 ret->closecallback = cb->closecallback;
1524 break;
1525 }
1526 }
1527 }
1528
1529 if (ret->context == NULL) {
1530 xmlOutputBufferClose(ret);
1531 ret = NULL;
1532 }
1533
1534 xmlFree(unescaped);
1535 return(ret);
1536 }
1537
1538 /**
1539 * xmlOutputBufferCreateFilename:
1540 * @URI: a C string containing the URI or filename
1541 * @encoder: the encoding converter or NULL
1542 * @compression: the compression ration (0 none, 9 max).
1543 *
1544 * Create a buffered output for the progressive saving of a file
1545 * If filename is "-' then we use stdout as the output.
1546 * Automatic support for ZLIB/Compress compressed document is provided
1547 * by default if found at compile-time.
1548 * TODO: currently if compression is set, the library only support
1549 * writing to a local file.
1550 *
1551 * Consumes @encoder even in error case.
1552 *
1553 * Returns the new output or NULL
1554 */
1555 xmlOutputBufferPtr
xmlOutputBufferCreateFilename(const char * URI,xmlCharEncodingHandlerPtr encoder,int compression ATTRIBUTE_UNUSED)1556 xmlOutputBufferCreateFilename(const char *URI,
1557 xmlCharEncodingHandlerPtr encoder,
1558 int compression ATTRIBUTE_UNUSED) {
1559 if ((xmlOutputBufferCreateFilenameValue)) {
1560 return xmlOutputBufferCreateFilenameValue(URI, encoder, compression);
1561 }
1562 return __xmlOutputBufferCreateFilename(URI, encoder, compression);
1563 }
1564 #endif /* LIBXML_OUTPUT_ENABLED */
1565
1566 /**
1567 * xmlParserInputBufferCreateFile:
1568 * @file: a FILE*
1569 * @enc: the charset encoding if known (deprecated)
1570 *
1571 * DEPRECATED: Don't use.
1572 *
1573 * Create a buffered parser input for the progressive parsing of a FILE *
1574 * buffered C I/O
1575 *
1576 * The encoding argument is deprecated and should be set to
1577 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1578 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1579 *
1580 * Returns the new parser input or NULL
1581 */
1582 xmlParserInputBufferPtr
xmlParserInputBufferCreateFile(FILE * file,xmlCharEncoding enc)1583 xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
1584 xmlParserInputBufferPtr ret;
1585
1586 if (file == NULL) return(NULL);
1587
1588 ret = xmlAllocParserInputBuffer(enc);
1589 if (ret != NULL) {
1590 ret->context = file;
1591 ret->readcallback = xmlFileRead;
1592 ret->closecallback = NULL;
1593 }
1594
1595 return(ret);
1596 }
1597
1598 #ifdef LIBXML_OUTPUT_ENABLED
1599 /**
1600 * xmlOutputBufferCreateFile:
1601 * @file: a FILE*
1602 * @encoder: the encoding converter or NULL
1603 *
1604 * Create a buffered output for the progressive saving to a FILE *
1605 * buffered C I/O
1606 *
1607 * Consumes @encoder even in error case.
1608 *
1609 * Returns the new parser output or NULL
1610 */
1611 xmlOutputBufferPtr
xmlOutputBufferCreateFile(FILE * file,xmlCharEncodingHandlerPtr encoder)1612 xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1613 xmlOutputBufferPtr ret;
1614
1615 if (file == NULL) return(NULL);
1616
1617 ret = xmlAllocOutputBuffer(encoder);
1618 if (ret != NULL) {
1619 ret->context = file;
1620 ret->writecallback = xmlFileWrite;
1621 ret->closecallback = xmlFileFlush;
1622 }
1623
1624 return(ret);
1625 }
1626
1627 /**
1628 * xmlOutputBufferCreateBuffer:
1629 * @buffer: a xmlBufferPtr
1630 * @encoder: the encoding converter or NULL
1631 *
1632 * Create a buffered output for the progressive saving to a xmlBuffer
1633 *
1634 * Consumes @encoder even in error case.
1635 *
1636 * Returns the new parser output or NULL
1637 */
1638 xmlOutputBufferPtr
xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,xmlCharEncodingHandlerPtr encoder)1639 xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
1640 xmlCharEncodingHandlerPtr encoder) {
1641 xmlOutputBufferPtr ret;
1642
1643 if (buffer == NULL) return(NULL);
1644
1645 ret = xmlOutputBufferCreateIO(xmlBufferWrite, NULL, (void *) buffer,
1646 encoder);
1647
1648 return(ret);
1649 }
1650
1651 /**
1652 * xmlOutputBufferGetContent:
1653 * @out: an xmlOutputBufferPtr
1654 *
1655 * Gives a pointer to the data currently held in the output buffer
1656 *
1657 * Returns a pointer to the data or NULL in case of error
1658 */
1659 const xmlChar *
xmlOutputBufferGetContent(xmlOutputBufferPtr out)1660 xmlOutputBufferGetContent(xmlOutputBufferPtr out) {
1661 if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1662 return(NULL);
1663
1664 return(xmlBufContent(out->buffer));
1665 }
1666
1667 /**
1668 * xmlOutputBufferGetSize:
1669 * @out: an xmlOutputBufferPtr
1670 *
1671 * Gives the length of the data currently held in the output buffer
1672 *
1673 * Returns 0 in case or error or no data is held, the size otherwise
1674 */
1675 size_t
xmlOutputBufferGetSize(xmlOutputBufferPtr out)1676 xmlOutputBufferGetSize(xmlOutputBufferPtr out) {
1677 if ((out == NULL) || (out->buffer == NULL) || (out->error != 0))
1678 return(0);
1679
1680 return(xmlBufUse(out->buffer));
1681 }
1682
1683
1684 #endif /* LIBXML_OUTPUT_ENABLED */
1685
1686 /**
1687 * xmlParserInputBufferCreateFd:
1688 * @fd: a file descriptor number
1689 * @enc: the charset encoding if known (deprecated)
1690 *
1691 * DEPRECATED: Use xmlNewInputFromFd.
1692 *
1693 * Create a buffered parser input for the progressive parsing for the input
1694 * from a file descriptor
1695 *
1696 * The encoding argument is deprecated and should be set to
1697 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1698 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1699 *
1700 * Returns the new parser input or NULL
1701 */
1702 xmlParserInputBufferPtr
xmlParserInputBufferCreateFd(int fd,xmlCharEncoding enc)1703 xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1704 xmlParserInputBufferPtr ret;
1705
1706 if (fd < 0) return(NULL);
1707
1708 ret = xmlAllocParserInputBuffer(enc);
1709 if (ret != NULL) {
1710 ret->context = (void *) (ptrdiff_t) fd;
1711 ret->readcallback = xmlFdRead;
1712 }
1713
1714 return(ret);
1715 }
1716
1717 typedef struct {
1718 const char *cur;
1719 size_t size;
1720 } xmlMemIOCtxt;
1721
1722 static int
xmlMemRead(void * vctxt,char * buf,int size)1723 xmlMemRead(void *vctxt, char *buf, int size) {
1724 xmlMemIOCtxt *ctxt = vctxt;
1725
1726 if ((size_t) size > ctxt->size)
1727 size = ctxt->size;
1728
1729 memcpy(buf, ctxt->cur, size);
1730 ctxt->cur += size;
1731 ctxt->size -= size;
1732
1733 return size;
1734 }
1735
1736 static int
xmlMemClose(void * vctxt)1737 xmlMemClose(void *vctxt) {
1738 xmlMemIOCtxt *ctxt = vctxt;
1739
1740 xmlFree(ctxt);
1741 return(0);
1742 }
1743
1744 /**
1745 * xmlNewInputBufferMemory:
1746 * @mem: memory buffer
1747 * @size: size of buffer
1748 * @flags: flags
1749 * @enc: the charset encoding if known (deprecated)
1750 *
1751 * Create an input buffer for memory.
1752 *
1753 * Returns the new input buffer or NULL.
1754 */
1755 xmlParserInputBufferPtr
xmlNewInputBufferMemory(const void * mem,size_t size,int flags,xmlCharEncoding enc)1756 xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
1757 xmlCharEncoding enc) {
1758 xmlParserInputBufferPtr ret;
1759
1760 if ((flags & XML_INPUT_BUF_STATIC) &&
1761 ((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
1762 xmlMemIOCtxt *ctxt;
1763
1764 /*
1765 * Static buffer without zero terminator.
1766 * Stream memory to avoid a copy.
1767 */
1768 ret = xmlAllocParserInputBuffer(enc);
1769 if (ret == NULL)
1770 return(NULL);
1771
1772 ctxt = xmlMalloc(sizeof(*ctxt));
1773 if (ctxt == NULL) {
1774 xmlFreeParserInputBuffer(ret);
1775 return(NULL);
1776 }
1777
1778 ctxt->cur = mem;
1779 ctxt->size = size;
1780
1781 ret->context = ctxt;
1782 ret->readcallback = xmlMemRead;
1783 ret->closecallback = xmlMemClose;
1784 } else {
1785 ret = xmlMalloc(sizeof(*ret));
1786 if (ret == NULL)
1787 return(NULL);
1788 memset(ret, 0, sizeof(xmlParserInputBuffer));
1789 ret->compressed = -1;
1790
1791 ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
1792 (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1793 if (ret->buffer == NULL) {
1794 xmlFree(ret);
1795 return(NULL);
1796 }
1797 }
1798
1799 return(ret);
1800 }
1801
1802 /**
1803 * xmlParserInputBufferCreateMem:
1804 * @mem: the memory input
1805 * @size: the length of the memory block
1806 * @enc: the charset encoding if known (deprecated)
1807 *
1808 * DEPRECATED: Use xmlNewInputFromMemory.
1809 *
1810 * Create a parser input buffer for parsing from a memory area.
1811 *
1812 * This function makes a copy of the whole input buffer. If you are sure
1813 * that the contents of the buffer will remain valid until the document
1814 * was parsed, you can avoid the copy by using
1815 * xmlParserInputBufferCreateStatic.
1816 *
1817 * The encoding argument is deprecated and should be set to
1818 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1819 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1820 *
1821 * Returns the new parser input or NULL in case of error.
1822 */
1823 xmlParserInputBufferPtr
xmlParserInputBufferCreateMem(const char * mem,int size,xmlCharEncoding enc)1824 xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1825 if ((mem == NULL) || (size < 0))
1826 return(NULL);
1827
1828 return(xmlNewInputBufferMemory(mem, size, 0, enc));
1829 }
1830
1831 /**
1832 * xmlParserInputBufferCreateStatic:
1833 * @mem: the memory input
1834 * @size: the length of the memory block
1835 * @enc: the charset encoding if known
1836 *
1837 * DEPRECATED: Use xmlNewInputFromMemory.
1838 *
1839 * Create a parser input buffer for parsing from a memory area.
1840 *
1841 * This functions assumes that the contents of the input buffer remain
1842 * valid until the document was parsed. Use xmlParserInputBufferCreateMem
1843 * otherwise.
1844 *
1845 * The encoding argument is deprecated and should be set to
1846 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1847 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1848 *
1849 * Returns the new parser input or NULL in case of error.
1850 */
1851 xmlParserInputBufferPtr
xmlParserInputBufferCreateStatic(const char * mem,int size,xmlCharEncoding enc)1852 xmlParserInputBufferCreateStatic(const char *mem, int size,
1853 xmlCharEncoding enc) {
1854 if ((mem == NULL) || (size < 0))
1855 return(NULL);
1856
1857 return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
1858 }
1859
1860 /**
1861 * xmlNewInputBufferString:
1862 * @str: C string
1863 * @flags: flags
1864 *
1865 * DEPRECATED: Use xmlNewInputFromString.
1866 *
1867 * Create an input buffer for a null-terminated C string.
1868 *
1869 * Returns the new input buffer or NULL.
1870 */
1871 xmlParserInputBufferPtr
xmlNewInputBufferString(const char * str,int flags)1872 xmlNewInputBufferString(const char *str, int flags) {
1873 xmlParserInputBufferPtr ret;
1874
1875 ret = xmlMalloc(sizeof(*ret));
1876 if (ret == NULL)
1877 return(NULL);
1878 memset(ret, 0, sizeof(xmlParserInputBuffer));
1879 ret->compressed = -1;
1880
1881 ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
1882 (flags & XML_INPUT_BUF_STATIC ? 1 : 0));
1883 if (ret->buffer == NULL) {
1884 xmlFree(ret);
1885 return(NULL);
1886 }
1887
1888 return(ret);
1889 }
1890
1891 #ifdef LIBXML_OUTPUT_ENABLED
1892 /**
1893 * xmlOutputBufferCreateFd:
1894 * @fd: a file descriptor number
1895 * @encoder: the encoding converter or NULL
1896 *
1897 * Create a buffered output for the progressive saving
1898 * to a file descriptor
1899 *
1900 * Consumes @encoder even in error case.
1901 *
1902 * Returns the new parser output or NULL
1903 */
1904 xmlOutputBufferPtr
xmlOutputBufferCreateFd(int fd,xmlCharEncodingHandlerPtr encoder)1905 xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
1906 xmlOutputBufferPtr ret;
1907
1908 if (fd < 0) return(NULL);
1909
1910 ret = xmlAllocOutputBuffer(encoder);
1911 if (ret != NULL) {
1912 ret->context = (void *) (ptrdiff_t) fd;
1913 ret->writecallback = xmlFdWrite;
1914 ret->closecallback = NULL;
1915 }
1916
1917 return(ret);
1918 }
1919 #endif /* LIBXML_OUTPUT_ENABLED */
1920
1921 /**
1922 * xmlParserInputBufferCreateIO:
1923 * @ioread: an I/O read function
1924 * @ioclose: an I/O close function
1925 * @ioctx: an I/O handler
1926 * @enc: the charset encoding if known (deprecated)
1927 *
1928 * DEPRECATED: Use xmlNewInputFromIO.
1929 *
1930 * Create a buffered parser input for the progressive parsing for the input
1931 * from an I/O handler
1932 *
1933 * The encoding argument is deprecated and should be set to
1934 * XML_CHAR_ENCODING_NONE. The encoding can be changed with
1935 * xmlSwitchEncoding or xmlSwitchEncodingName later on.
1936 *
1937 * Returns the new parser input or NULL
1938 */
1939 xmlParserInputBufferPtr
xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,xmlInputCloseCallback ioclose,void * ioctx,xmlCharEncoding enc)1940 xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
1941 xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
1942 xmlParserInputBufferPtr ret;
1943
1944 if (ioread == NULL) return(NULL);
1945
1946 ret = xmlAllocParserInputBuffer(enc);
1947 if (ret != NULL) {
1948 ret->context = (void *) ioctx;
1949 ret->readcallback = ioread;
1950 ret->closecallback = ioclose;
1951 }
1952
1953 return(ret);
1954 }
1955
1956 #ifdef LIBXML_OUTPUT_ENABLED
1957 /**
1958 * xmlOutputBufferCreateIO:
1959 * @iowrite: an I/O write function
1960 * @ioclose: an I/O close function
1961 * @ioctx: an I/O handler
1962 * @encoder: the charset encoding if known
1963 *
1964 * Create a buffered output for the progressive saving
1965 * to an I/O handler
1966 *
1967 * Consumes @encoder even in error case.
1968 *
1969 * Returns the new parser output or NULL
1970 */
1971 xmlOutputBufferPtr
xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,xmlOutputCloseCallback ioclose,void * ioctx,xmlCharEncodingHandlerPtr encoder)1972 xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
1973 xmlOutputCloseCallback ioclose, void *ioctx,
1974 xmlCharEncodingHandlerPtr encoder) {
1975 xmlOutputBufferPtr ret;
1976
1977 if (iowrite == NULL) {
1978 xmlCharEncCloseFunc(encoder);
1979 return(NULL);
1980 }
1981
1982 ret = xmlAllocOutputBuffer(encoder);
1983 if (ret != NULL) {
1984 ret->context = (void *) ioctx;
1985 ret->writecallback = iowrite;
1986 ret->closecallback = ioclose;
1987 }
1988
1989 return(ret);
1990 }
1991 #endif /* LIBXML_OUTPUT_ENABLED */
1992
1993 /**
1994 * xmlParserInputBufferCreateFilenameDefault:
1995 * @func: function pointer to the new ParserInputBufferCreateFilenameFunc
1996 *
1997 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
1998 *
1999 * Registers a callback for URI input file handling
2000 *
2001 * Returns the old value of the registration function
2002 */
2003 xmlParserInputBufferCreateFilenameFunc
xmlParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)2004 xmlParserInputBufferCreateFilenameDefault(
2005 xmlParserInputBufferCreateFilenameFunc func)
2006 {
2007 xmlParserInputBufferCreateFilenameFunc old;
2008
2009 old = xmlParserInputBufferCreateFilenameValue;
2010 if (old == NULL)
2011 old = __xmlParserInputBufferCreateFilename;
2012
2013 if (func == __xmlParserInputBufferCreateFilename)
2014 func = NULL;
2015 xmlParserInputBufferCreateFilenameValue = func;
2016 return(old);
2017 }
2018
2019 /**
2020 * xmlOutputBufferCreateFilenameDefault:
2021 * @func: function pointer to the new OutputBufferCreateFilenameFunc
2022 *
2023 * Registers a callback for URI output file handling
2024 *
2025 * Returns the old value of the registration function
2026 */
2027 xmlOutputBufferCreateFilenameFunc
xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)2028 xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
2029 {
2030 xmlOutputBufferCreateFilenameFunc old = xmlOutputBufferCreateFilenameValue;
2031 #ifdef LIBXML_OUTPUT_ENABLED
2032 if (old == NULL) {
2033 old = __xmlOutputBufferCreateFilename;
2034 }
2035 #endif
2036 xmlOutputBufferCreateFilenameValue = func;
2037 return(old);
2038 }
2039
2040 /**
2041 * xmlParserInputBufferPush:
2042 * @in: a buffered parser input
2043 * @len: the size in bytes of the array.
2044 * @buf: an char array
2045 *
2046 * DEPRECATED: Internal function, don't use.
2047 *
2048 * Push the content of the arry in the input buffer
2049 * This routine handle the I18N transcoding to internal UTF-8
2050 * This is used when operating the parser in progressive (push) mode.
2051 *
2052 * Returns the number of chars read and stored in the buffer, or -1
2053 * in case of error.
2054 */
2055 int
xmlParserInputBufferPush(xmlParserInputBufferPtr in,int len,const char * buf)2056 xmlParserInputBufferPush(xmlParserInputBufferPtr in,
2057 int len, const char *buf) {
2058 size_t nbchars = 0;
2059 int ret;
2060
2061 if (len < 0) return(0);
2062 if ((in == NULL) || (in->error)) return(-1);
2063 if (in->encoder != NULL) {
2064 /*
2065 * Store the data in the incoming raw buffer
2066 */
2067 if (in->raw == NULL) {
2068 in->raw = xmlBufCreate(50);
2069 if (in->raw == NULL) {
2070 in->error = XML_ERR_NO_MEMORY;
2071 return(-1);
2072 }
2073 }
2074 ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
2075 if (ret != 0) {
2076 in->error = XML_ERR_NO_MEMORY;
2077 return(-1);
2078 }
2079
2080 /*
2081 * convert as much as possible to the parser reading buffer.
2082 */
2083 nbchars = SIZE_MAX;
2084 if (xmlCharEncInput(in, &nbchars) < 0)
2085 return(-1);
2086 if (nbchars > INT_MAX)
2087 nbchars = INT_MAX;
2088 } else {
2089 nbchars = len;
2090 ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
2091 if (ret != 0) {
2092 in->error = XML_ERR_NO_MEMORY;
2093 return(-1);
2094 }
2095 }
2096 return(nbchars);
2097 }
2098
2099 /**
2100 * endOfInput:
2101 *
2102 * When reading from an Input channel indicated end of file or error
2103 * don't reread from it again.
2104 */
2105 static int
endOfInput(void * context ATTRIBUTE_UNUSED,char * buffer ATTRIBUTE_UNUSED,int len ATTRIBUTE_UNUSED)2106 endOfInput (void * context ATTRIBUTE_UNUSED,
2107 char * buffer ATTRIBUTE_UNUSED,
2108 int len ATTRIBUTE_UNUSED) {
2109 return(0);
2110 }
2111
2112 /**
2113 * xmlParserInputBufferGrow:
2114 * @in: a buffered parser input
2115 * @len: indicative value of the amount of chars to read
2116 *
2117 * DEPRECATED: Internal function, don't use.
2118 *
2119 * Grow up the content of the input buffer, the old data are preserved
2120 * This routine handle the I18N transcoding to internal UTF-8
2121 * This routine is used when operating the parser in normal (pull) mode
2122 *
2123 * Returns the number of chars read and stored in the buffer, or -1
2124 * in case of error.
2125 */
2126 int
xmlParserInputBufferGrow(xmlParserInputBufferPtr in,int len)2127 xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
2128 int res = 0;
2129
2130 if ((in == NULL) || (in->error))
2131 return(-1);
2132
2133 if (len < MINLEN)
2134 len = MINLEN;
2135
2136 /*
2137 * Call the read method for this I/O type.
2138 */
2139 if (in->readcallback != NULL) {
2140 xmlBufPtr buf;
2141
2142 if (in->encoder == NULL) {
2143 buf = in->buffer;
2144 } else {
2145 /*
2146 * Some users only set 'encoder' and expect us to create
2147 * the raw buffer lazily.
2148 */
2149 if (in->raw == NULL) {
2150 in->raw = xmlBufCreate(XML_IO_BUFFER_SIZE);
2151 if (in->raw == NULL) {
2152 in->error = XML_ERR_NO_MEMORY;
2153 return(-1);
2154 }
2155 }
2156 buf = in->raw;
2157 }
2158
2159 if (xmlBufGrow(buf, len) < 0) {
2160 in->error = XML_ERR_NO_MEMORY;
2161 return(-1);
2162 }
2163
2164 res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
2165 if (res <= 0)
2166 in->readcallback = endOfInput;
2167 if (res < 0) {
2168 if (res == -1)
2169 in->error = XML_IO_UNKNOWN;
2170 else
2171 in->error = -res;
2172 return(-1);
2173 }
2174
2175 if (xmlBufAddLen(buf, res) < 0) {
2176 in->error = XML_ERR_NO_MEMORY;
2177 return(-1);
2178 }
2179 }
2180
2181 /*
2182 * Handle encoding.
2183 */
2184 if (in->encoder != NULL) {
2185 size_t sizeOut;
2186
2187 /*
2188 * Don't convert whole buffer when reading from memory.
2189 */
2190 if (in->readcallback == NULL)
2191 sizeOut = len;
2192 else
2193 sizeOut = SIZE_MAX;
2194
2195 if (xmlCharEncInput(in, &sizeOut) < 0)
2196 return(-1);
2197 res = sizeOut;
2198 }
2199 return(res);
2200 }
2201
2202 /**
2203 * xmlParserInputBufferRead:
2204 * @in: a buffered parser input
2205 * @len: indicative value of the amount of chars to read
2206 *
2207 * DEPRECATED: Internal function, don't use.
2208 *
2209 * Same as xmlParserInputBufferGrow.
2210 *
2211 * Returns the number of chars read and stored in the buffer, or -1
2212 * in case of error.
2213 */
2214 int
xmlParserInputBufferRead(xmlParserInputBufferPtr in,int len)2215 xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
2216 return(xmlParserInputBufferGrow(in, len));
2217 }
2218
2219 #ifdef LIBXML_OUTPUT_ENABLED
2220 /**
2221 * xmlOutputBufferWrite:
2222 * @out: a buffered parser output
2223 * @len: the size in bytes of the array.
2224 * @data: an char array
2225 *
2226 * Write the content of the array in the output I/O buffer
2227 * This routine handle the I18N transcoding from internal UTF-8
2228 * The buffer is lossless, i.e. will store in case of partial
2229 * or delayed writes.
2230 *
2231 * Returns the number of chars immediately written, or -1
2232 * in case of error.
2233 */
2234 int
xmlOutputBufferWrite(xmlOutputBufferPtr out,int len,const char * data)2235 xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *data) {
2236 xmlBufPtr buf = NULL;
2237 size_t written = 0;
2238 int ret;
2239
2240 if ((out == NULL) || (out->error))
2241 return(-1);
2242 if (len < 0)
2243 return(0);
2244
2245 ret = xmlBufAdd(out->buffer, (const xmlChar *) data, len);
2246 if (ret != 0) {
2247 out->error = XML_ERR_NO_MEMORY;
2248 return(-1);
2249 }
2250
2251 /*
2252 * first handle encoding stuff.
2253 */
2254 if (out->encoder != NULL) {
2255 /*
2256 * Store the data in the incoming raw buffer
2257 */
2258 if (out->conv == NULL) {
2259 out->conv = xmlBufCreate(MINLEN);
2260 if (out->conv == NULL) {
2261 out->error = XML_ERR_NO_MEMORY;
2262 return(-1);
2263 }
2264 }
2265
2266 /*
2267 * convert as much as possible to the parser reading buffer.
2268 */
2269 if (xmlBufUse(out->buffer) < 256) {
2270 ret = 0;
2271 } else {
2272 ret = xmlCharEncOutput(out, 0);
2273 if (ret < 0)
2274 return(-1);
2275 }
2276
2277 if (out->writecallback)
2278 buf = out->conv;
2279 else
2280 written = ret;
2281 } else {
2282 if (out->writecallback)
2283 buf = out->buffer;
2284 else
2285 written = len;
2286 }
2287
2288 if ((buf != NULL) && (out->writecallback)) {
2289 /*
2290 * second write the stuff to the I/O channel
2291 */
2292 while (1) {
2293 size_t nbchars = xmlBufUse(buf);
2294
2295 if (nbchars < MINLEN)
2296 break;
2297
2298 ret = out->writecallback(out->context,
2299 (const char *)xmlBufContent(buf), nbchars);
2300 if (ret < 0) {
2301 out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2302 return(-1);
2303 }
2304 if ((ret == 0) || ((size_t) ret > nbchars)) {
2305 out->error = XML_ERR_INTERNAL_ERROR;
2306 return(-1);
2307 }
2308
2309 xmlBufShrink(buf, ret);
2310 written += ret;
2311 if (out->written > INT_MAX - ret)
2312 out->written = INT_MAX;
2313 else
2314 out->written += ret;
2315 }
2316 }
2317
2318 return(written <= INT_MAX ? written : INT_MAX);
2319 }
2320
2321 /**
2322 * xmlOutputBufferWriteEscape:
2323 * @out: a buffered parser output
2324 * @str: a zero terminated UTF-8 string
2325 * @escaping: an optional escaping function (or NULL)
2326 *
2327 * Write the content of the string in the output I/O buffer
2328 * This routine escapes the characters and then handle the I18N
2329 * transcoding from internal UTF-8
2330 * The buffer is lossless, i.e. will store in case of partial
2331 * or delayed writes.
2332 *
2333 * Returns the number of chars immediately written, or -1
2334 * in case of error.
2335 */
2336 int
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out,const xmlChar * str,xmlCharEncodingOutputFunc escaping)2337 xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
2338 xmlCharEncodingOutputFunc escaping) {
2339 int ret;
2340 int written = 0;
2341 size_t len;
2342
2343 if ((out == NULL) || (out->error) || (str == NULL))
2344 return(-1);
2345
2346 len = strlen((const char *) str);
2347 if (len >= INT_MAX) {
2348 out->error = XML_ERR_RESOURCE_LIMIT;
2349 return(-1);
2350 }
2351
2352 if (escaping == NULL) {
2353 char *escaped = (char *) xmlEscapeText(str, XML_ESCAPE_ALLOW_INVALID);
2354
2355 if (escaped == NULL) {
2356 out->error = XML_ERR_NO_MEMORY;
2357 return(-1);
2358 }
2359
2360 len = strlen(escaped);
2361 if (len >= INT_MAX) {
2362 out->error = XML_ERR_RESOURCE_LIMIT;
2363 return(-1);
2364 }
2365
2366 ret = xmlOutputBufferWrite(out, len, escaped);
2367
2368 xmlFree(escaped);
2369 return(ret);
2370 }
2371
2372 while (len > 0) {
2373 xmlChar buf[1024];
2374 int c_out;
2375 int c_in;
2376
2377 c_out = 1024;
2378 c_in = len;
2379
2380 ret = escaping(buf, &c_out, str, &c_in);
2381 if (ret < 0) {
2382 out->error = XML_ERR_NO_MEMORY;
2383 return(-1);
2384 }
2385 str += c_in;
2386 len -= c_in;
2387
2388 ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
2389 if (ret < 0)
2390 return(ret);
2391 written += ret;
2392 }
2393
2394 return(written);
2395 }
2396
2397 /**
2398 * xmlOutputBufferWriteString:
2399 * @out: a buffered parser output
2400 * @str: a zero terminated C string
2401 *
2402 * Write the content of the string in the output I/O buffer
2403 * This routine handle the I18N transcoding from internal UTF-8
2404 * The buffer is lossless, i.e. will store in case of partial
2405 * or delayed writes.
2406 *
2407 * Returns the number of chars immediately written, or -1
2408 * in case of error.
2409 */
2410 int
xmlOutputBufferWriteString(xmlOutputBufferPtr out,const char * str)2411 xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
2412 int len;
2413
2414 if ((out == NULL) || (out->error)) return(-1);
2415 if (str == NULL)
2416 return(-1);
2417 len = strlen(str);
2418
2419 if (len > 0)
2420 return(xmlOutputBufferWrite(out, len, str));
2421 return(len);
2422 }
2423
2424 /**
2425 * xmlOutputBufferWriteQuotedString:
2426 * @buf: output buffer
2427 * @string: the string to add
2428 *
2429 * routine which manage and grows an output buffer. This one writes
2430 * a quoted or double quoted #xmlChar string, checking first if it holds
2431 * quote or double-quotes internally
2432 */
2433 void
xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,const xmlChar * string)2434 xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf,
2435 const xmlChar *string) {
2436 const xmlChar *cur, *base;
2437
2438 if ((buf == NULL) || (buf->error))
2439 return;
2440
2441 if (xmlStrchr(string, '\"')) {
2442 if (xmlStrchr(string, '\'')) {
2443 xmlOutputBufferWrite(buf, 1, "\"");
2444 base = cur = string;
2445 while(*cur != 0){
2446 if(*cur == '"'){
2447 if (base != cur)
2448 xmlOutputBufferWrite(buf, cur - base,
2449 (const char *) base);
2450 xmlOutputBufferWrite(buf, 6, """);
2451 cur++;
2452 base = cur;
2453 }
2454 else {
2455 cur++;
2456 }
2457 }
2458 if (base != cur)
2459 xmlOutputBufferWrite(buf, cur - base, (const char *) base);
2460 xmlOutputBufferWrite(buf, 1, "\"");
2461 }
2462 else{
2463 xmlOutputBufferWrite(buf, 1, "'");
2464 xmlOutputBufferWriteString(buf, (const char *) string);
2465 xmlOutputBufferWrite(buf, 1, "'");
2466 }
2467 } else {
2468 xmlOutputBufferWrite(buf, 1, "\"");
2469 xmlOutputBufferWriteString(buf, (const char *) string);
2470 xmlOutputBufferWrite(buf, 1, "\"");
2471 }
2472 }
2473
2474 /**
2475 * xmlOutputBufferFlush:
2476 * @out: a buffered output
2477 *
2478 * flushes the output I/O channel
2479 *
2480 * Returns the number of byte written or -1 in case of error.
2481 */
2482 int
xmlOutputBufferFlush(xmlOutputBufferPtr out)2483 xmlOutputBufferFlush(xmlOutputBufferPtr out) {
2484 int nbchars = 0, ret = 0;
2485
2486 if ((out == NULL) || (out->error)) return(-1);
2487 /*
2488 * first handle encoding stuff.
2489 */
2490 if ((out->conv != NULL) && (out->encoder != NULL)) {
2491 /*
2492 * convert as much as possible to the parser output buffer.
2493 */
2494 do {
2495 nbchars = xmlCharEncOutput(out, 0);
2496 if (nbchars < 0)
2497 return(-1);
2498 } while (nbchars);
2499 }
2500
2501 /*
2502 * second flush the stuff to the I/O channel
2503 */
2504 if ((out->conv != NULL) && (out->encoder != NULL) &&
2505 (out->writecallback != NULL)) {
2506 ret = out->writecallback(out->context,
2507 (const char *)xmlBufContent(out->conv),
2508 xmlBufUse(out->conv));
2509 if (ret >= 0)
2510 xmlBufShrink(out->conv, ret);
2511 } else if (out->writecallback != NULL) {
2512 ret = out->writecallback(out->context,
2513 (const char *)xmlBufContent(out->buffer),
2514 xmlBufUse(out->buffer));
2515 if (ret >= 0)
2516 xmlBufShrink(out->buffer, ret);
2517 }
2518 if (ret < 0) {
2519 out->error = (ret == -1) ? XML_IO_WRITE : -ret;
2520 return(ret);
2521 }
2522 if (out->written > INT_MAX - ret)
2523 out->written = INT_MAX;
2524 else
2525 out->written += ret;
2526
2527 return(ret);
2528 }
2529 #endif /* LIBXML_OUTPUT_ENABLED */
2530
2531 /**
2532 * xmlParserGetDirectory:
2533 * @filename: the path to a file
2534 *
2535 * lookup the directory for that file
2536 *
2537 * Returns a new allocated string containing the directory, or NULL.
2538 */
2539 char *
xmlParserGetDirectory(const char * filename)2540 xmlParserGetDirectory(const char *filename) {
2541 char *ret = NULL;
2542 char dir[1024];
2543 char *cur;
2544
2545 if (filename == NULL) return(NULL);
2546
2547 #if defined(_WIN32)
2548 # define IS_XMLPGD_SEP(ch) ((ch=='/')||(ch=='\\'))
2549 #else
2550 # define IS_XMLPGD_SEP(ch) (ch=='/')
2551 #endif
2552
2553 strncpy(dir, filename, 1023);
2554 dir[1023] = 0;
2555 cur = &dir[strlen(dir)];
2556 while (cur > dir) {
2557 if (IS_XMLPGD_SEP(*cur)) break;
2558 cur --;
2559 }
2560 if (IS_XMLPGD_SEP(*cur)) {
2561 if (cur == dir) dir[1] = 0;
2562 else *cur = 0;
2563 ret = xmlMemStrdup(dir);
2564 } else {
2565 ret = xmlMemStrdup(".");
2566 }
2567 return(ret);
2568 #undef IS_XMLPGD_SEP
2569 }
2570
2571 /**
2572 * xmlNoNetExists:
2573 * @filename: the path to check
2574 *
2575 * DEPRECATED: Internal function, don't use.
2576 *
2577 * Like xmlCheckFilename but handles file URIs.
2578 *
2579 * Returns 0, 1, or 2.
2580 */
2581 int
xmlNoNetExists(const char * filename)2582 xmlNoNetExists(const char *filename) {
2583 char *fromUri;
2584 int ret;
2585
2586 if (filename == NULL)
2587 return(0);
2588
2589 if (xmlConvertUriToPath(filename, &fromUri) < 0)
2590 return(0);
2591
2592 if (fromUri != NULL)
2593 filename = fromUri;
2594
2595 ret = xmlCheckFilename(filename);
2596
2597 xmlFree(fromUri);
2598 return(ret);
2599 }
2600
2601 /************************************************************************
2602 * *
2603 * Input/output callbacks *
2604 * *
2605 ************************************************************************/
2606
2607 /**
2608 * xmlInitIOCallbacks:
2609 *
2610 * Initialize callback tables.
2611 */
2612 void
xmlInitIOCallbacks(void)2613 xmlInitIOCallbacks(void)
2614 {
2615 xmlInputCallbackNr = 1;
2616 xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2617
2618 #ifdef LIBXML_OUTPUT_ENABLED
2619 xmlOutputCallbackNr = 1;
2620 xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch;
2621 #endif
2622 }
2623
2624 /**
2625 * xmlRegisterInputCallbacks:
2626 * @matchFunc: the xmlInputMatchCallback
2627 * @openFunc: the xmlInputOpenCallback
2628 * @readFunc: the xmlInputReadCallback
2629 * @closeFunc: the xmlInputCloseCallback
2630 *
2631 * DEPRECATED: Use xmlCtxtSetResourceLoader or similar functions.
2632 *
2633 * Register a new set of I/O callback for handling parser input.
2634 *
2635 * Returns the registered handler number or -1 in case of error
2636 */
2637 int
xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,xmlInputOpenCallback openFunc,xmlInputReadCallback readFunc,xmlInputCloseCallback closeFunc)2638 xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc,
2639 xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc,
2640 xmlInputCloseCallback closeFunc) {
2641 xmlInitParser();
2642
2643 if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
2644 return(-1);
2645 }
2646 xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc;
2647 xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc;
2648 xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc;
2649 xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc;
2650 return(xmlInputCallbackNr++);
2651 }
2652
2653 /**
2654 * xmlRegisterDefaultInputCallbacks:
2655 *
2656 * Registers the default compiled-in I/O handlers.
2657 */
2658 void
xmlRegisterDefaultInputCallbacks(void)2659 xmlRegisterDefaultInputCallbacks(void) {
2660 xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2661 }
2662
2663 /**
2664 * xmlPopInputCallbacks:
2665 *
2666 * Clear the top input callback from the input stack. this includes the
2667 * compiled-in I/O.
2668 *
2669 * Returns the number of input callback registered or -1 in case of error.
2670 */
2671 int
xmlPopInputCallbacks(void)2672 xmlPopInputCallbacks(void)
2673 {
2674 xmlInitParser();
2675
2676 if (xmlInputCallbackNr <= 0)
2677 return(-1);
2678
2679 xmlInputCallbackNr--;
2680
2681 return(xmlInputCallbackNr);
2682 }
2683
2684 /**
2685 * xmlCleanupInputCallbacks:
2686 *
2687 * clears the entire input callback table. this includes the
2688 * compiled-in I/O.
2689 */
2690 void
xmlCleanupInputCallbacks(void)2691 xmlCleanupInputCallbacks(void)
2692 {
2693 xmlInitParser();
2694
2695 xmlInputCallbackNr = 0;
2696 }
2697
2698 #ifdef LIBXML_OUTPUT_ENABLED
2699 /**
2700 * xmlRegisterOutputCallbacks:
2701 * @matchFunc: the xmlOutputMatchCallback
2702 * @openFunc: the xmlOutputOpenCallback
2703 * @writeFunc: the xmlOutputWriteCallback
2704 * @closeFunc: the xmlOutputCloseCallback
2705 *
2706 * Register a new set of I/O callback for handling output.
2707 *
2708 * Returns the registered handler number or -1 in case of error
2709 */
2710 int
xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,xmlOutputOpenCallback openFunc,xmlOutputWriteCallback writeFunc,xmlOutputCloseCallback closeFunc)2711 xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc,
2712 xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc,
2713 xmlOutputCloseCallback closeFunc) {
2714 xmlInitParser();
2715
2716 if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) {
2717 return(-1);
2718 }
2719 xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc;
2720 xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc;
2721 xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc;
2722 xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc;
2723 return(xmlOutputCallbackNr++);
2724 }
2725
2726 /**
2727 * xmlRegisterDefaultOutputCallbacks:
2728 *
2729 * Registers the default compiled-in I/O handlers.
2730 */
2731 void
xmlRegisterDefaultOutputCallbacks(void)2732 xmlRegisterDefaultOutputCallbacks (void) {
2733 xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL);
2734 }
2735
2736 /**
2737 * xmlPopOutputCallbacks:
2738 *
2739 * Remove the top output callbacks from the output stack. This includes the
2740 * compiled-in I/O.
2741 *
2742 * Returns the number of output callback registered or -1 in case of error.
2743 */
2744 int
xmlPopOutputCallbacks(void)2745 xmlPopOutputCallbacks(void)
2746 {
2747 xmlInitParser();
2748
2749 if (xmlOutputCallbackNr <= 0)
2750 return(-1);
2751
2752 xmlOutputCallbackNr--;
2753
2754 return(xmlOutputCallbackNr);
2755 }
2756
2757 /**
2758 * xmlCleanupOutputCallbacks:
2759 *
2760 * clears the entire output callback table. this includes the
2761 * compiled-in I/O callbacks.
2762 */
2763 void
xmlCleanupOutputCallbacks(void)2764 xmlCleanupOutputCallbacks(void)
2765 {
2766 xmlInitParser();
2767
2768 xmlOutputCallbackNr = 0;
2769 }
2770
2771 #ifdef LIBXML_HTTP_ENABLED
2772 /**
2773 * xmlRegisterHTTPPostCallbacks:
2774 *
2775 * DEPRECATED: Support for HTTP POST has been removed.
2776 */
2777 void
xmlRegisterHTTPPostCallbacks(void)2778 xmlRegisterHTTPPostCallbacks(void) {
2779 xmlRegisterDefaultOutputCallbacks();
2780 }
2781 #endif
2782 #endif /* LIBXML_OUTPUT_ENABLED */
2783
2784