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