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