Annotation of XML/xmlIO.c, revision 1.32
1.1 daniel 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@w3.org
7: */
8:
1.10 daniel 9: #ifdef WIN32
1.16 daniel 10: #include "win32config.h"
1.10 daniel 11: #else
1.12 daniel 12: #include "config.h"
1.10 daniel 13: #endif
14:
15: #include <stdio.h>
16: #include <string.h>
1.1 daniel 17:
1.10 daniel 18: #ifdef HAVE_SYS_TYPES_H
1.1 daniel 19: #include <sys/types.h>
1.10 daniel 20: #endif
21: #ifdef HAVE_SYS_STAT_H
1.1 daniel 22: #include <sys/stat.h>
1.10 daniel 23: #endif
24: #ifdef HAVE_FCNTL_H
1.1 daniel 25: #include <fcntl.h>
1.10 daniel 26: #endif
1.1 daniel 27: #ifdef HAVE_UNISTD_H
28: #include <unistd.h>
29: #endif
1.10 daniel 30: #ifdef HAVE_STDLIB_H
31: #include <stdlib.h>
32: #endif
1.1 daniel 33: #ifdef HAVE_ZLIB_H
34: #include <zlib.h>
35: #endif
36:
1.21 daniel 37: #include <libxml/xmlmemory.h>
38: #include <libxml/parser.h>
39: #include <libxml/parserInternals.h>
40: #include <libxml/xmlIO.h>
41: #include <libxml/nanohttp.h>
42: #include <libxml/nanoftp.h>
1.1 daniel 43:
1.2 daniel 44: /* #define VERBOSE_FAILURE */
1.5 daniel 45: /* #define DEBUG_EXTERNAL_ENTITIES */
1.28 daniel 46: /* #define DEBUG_INPUT */
1.1 daniel 47:
48: #ifdef DEBUG_INPUT
49: #define MINLEN 40
50: #else
51: #define MINLEN 4000
52: #endif
53:
1.22 daniel 54: /*
55: * Input I/O callback sets
56: */
57: typedef struct _xmlInputCallback {
58: xmlInputMatchCallback matchcallback;
59: xmlInputOpenCallback opencallback;
60: xmlInputReadCallback readcallback;
61: xmlInputCloseCallback closecallback;
62: } xmlInputCallback;
63:
1.23 daniel 64: #define MAX_INPUT_CALLBACK 15
1.22 daniel 65:
1.23 daniel 66: xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
67: int xmlInputCallbackNr = 0;
68: int xmlInputCallbackInitialized = 0;
69:
1.27 daniel 70: /*
71: * Output I/O callback sets
72: */
73: typedef struct _xmlOutputCallback {
74: xmlOutputMatchCallback matchcallback;
75: xmlOutputOpenCallback opencallback;
76: xmlOutputWriteCallback writecallback;
77: xmlOutputCloseCallback closecallback;
78: } xmlOutputCallback;
79:
80: #define MAX_OUTPUT_CALLBACK 15
81:
82: xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
83: int xmlOutputCallbackNr = 0;
84: int xmlOutputCallbackInitialized = 0;
85:
1.23 daniel 86: /************************************************************************
87: * *
88: * Standard I/O for file accesses *
89: * *
90: ************************************************************************/
1.22 daniel 91:
1.32 ! veillard 92: int
! 93: xmlNop(void) {
! 94: return(0);
! 95: }
! 96:
1.22 daniel 97: /**
1.23 daniel 98: * xmlFdMatch:
1.22 daniel 99: * @filename: the URI for matching
100: *
101: * input from file descriptor
102: *
103: * Returns 1 if matches, 0 otherwise
104: */
1.23 daniel 105: int
106: xmlFdMatch (const char *filename) {
107: return(1);
108: }
109:
110: /**
111: * xmlFdOpen:
112: * @filename: the URI for matching
113: *
114: * input from file descriptor, supports compressed input
115: * if @filename is " " then the standard input is used
116: *
117: * Returns an I/O context or NULL in case of error
118: */
119: void *
120: xmlFdOpen (const char *filename) {
121: const char *path = NULL;
122: int fd;
123:
124: if (!strcmp(filename, "-")) {
125: fd = 0;
126: return((void *) fd);
127: }
128:
1.22 daniel 129: if (!strncmp(filename, "file://localhost", 16))
1.23 daniel 130: path = &filename[16];
131: else if (!strncmp(filename, "file:///", 8))
132: path = &filename[8];
133: else if (filename[0] == '/')
134: path = filename;
135: if (path == NULL)
136: return(NULL);
137:
138: #ifdef WIN32
139: fd = _open (filename, O_RDONLY | _O_BINARY);
140: #else
141: fd = open (filename, O_RDONLY);
142: #endif
143:
144: return((void *) fd);
145: }
146:
147: /**
1.28 daniel 148: * xmlFdOpenW:
149: * @filename: the URI for matching
150: *
151: * input from file descriptor,
152: * if @filename is "-" then the standard output is used
153: *
154: * Returns an I/O context or NULL in case of error
155: */
156: void *
157: xmlFdOpenW (const char *filename) {
158: const char *path = NULL;
159: int fd;
160:
161: if (!strcmp(filename, "-")) {
162: fd = 1;
163: return((void *) fd);
164: }
165:
166: if (!strncmp(filename, "file://localhost", 16))
167: path = &filename[16];
168: else if (!strncmp(filename, "file:///", 8))
169: path = &filename[8];
170: else if (filename[0] == '/')
171: path = filename;
172: if (path == NULL)
173: return(NULL);
174:
175: fd = open (filename, O_WRONLY);
176:
177: return((void *) fd);
178: }
179:
180: /**
1.23 daniel 181: * xmlFdRead:
182: * @context: the I/O context
183: * @buffer: where to drop data
1.27 daniel 184: * @len: number of bytes to read
1.23 daniel 185: *
186: * Read @len bytes to @buffer from the I/O channel.
187: *
188: * Returns the number of bytes written
189: */
190: int
191: xmlFdRead (void * context, char * buffer, int len) {
192: return(read((int) context, &buffer[0], len));
193: }
194:
195: /**
1.27 daniel 196: * xmlFdWrite:
197: * @context: the I/O context
198: * @buffer: where to get data
199: * @len: number of bytes to write
200: *
201: * Write @len bytes from @buffer to the I/O channel.
202: *
203: * Returns the number of bytes written
204: */
205: int
206: xmlFdWrite (void * context, const char * buffer, int len) {
207: return(write((int) context, &buffer[0], len));
208: }
209:
210: /**
1.23 daniel 211: * xmlFdClose:
212: * @context: the I/O context
213: *
214: * Close an I/O channel
215: */
216: void
217: xmlFdClose (void * context) {
218: close((int) context);
1.22 daniel 219: }
1.23 daniel 220:
1.22 daniel 221: /**
1.23 daniel 222: * xmlFileMatch:
1.22 daniel 223: * @filename: the URI for matching
224: *
1.23 daniel 225: * input from FILE *
1.22 daniel 226: *
227: * Returns 1 if matches, 0 otherwise
228: */
1.23 daniel 229: int
230: xmlFileMatch (const char *filename) {
231: return(1);
232: }
233:
234: /**
235: * xmlFileOpen:
236: * @filename: the URI for matching
237: *
238: * input from FILE *, supports compressed input
239: * if @filename is " " then the standard input is used
240: *
241: * Returns an I/O context or NULL in case of error
242: */
243: void *
244: xmlFileOpen (const char *filename) {
1.22 daniel 245: const char *path = NULL;
1.23 daniel 246: FILE *fd;
247:
248: if (!strcmp(filename, "-")) {
249: fd = stdin;
250: return((void *) fd);
251: }
1.22 daniel 252:
253: if (!strncmp(filename, "file://localhost", 16))
254: path = &filename[16];
255: else if (!strncmp(filename, "file:///", 8))
1.23 daniel 256: path = &filename[8];
257: else
1.22 daniel 258: path = filename;
259: if (path == NULL)
1.23 daniel 260: return(NULL);
261:
1.22 daniel 262: #ifdef WIN32
1.23 daniel 263: fd = fopen(path, "rb");
1.22 daniel 264: #else
1.23 daniel 265: fd = fopen(path, "r");
266: #endif /* WIN32 */
267: return((void *) fd);
268: }
269:
270: /**
1.28 daniel 271: * xmlFileOpenW:
272: * @filename: the URI for matching
273: *
274: * output to from FILE *,
275: * if @filename is "-" then the standard output is used
276: *
277: * Returns an I/O context or NULL in case of error
278: */
279: void *
280: xmlFileOpenW (const char *filename) {
281: const char *path = NULL;
282: FILE *fd;
283:
284: if (!strcmp(filename, "-")) {
285: fd = stdout;
286: return((void *) fd);
287: }
288:
289: if (!strncmp(filename, "file://localhost", 16))
290: path = &filename[16];
291: else if (!strncmp(filename, "file:///", 8))
292: path = &filename[8];
293: else
294: path = filename;
295: if (path == NULL)
296: return(NULL);
297:
298: fd = fopen(path, "w");
299: return((void *) fd);
300: }
301:
302: /**
1.23 daniel 303: * xmlFileRead:
304: * @context: the I/O context
305: * @buffer: where to drop data
306: * @len: number of bytes to write
307: *
308: * Read @len bytes to @buffer from the I/O channel.
309: *
310: * Returns the number of bytes written
311: */
312: int
313: xmlFileRead (void * context, char * buffer, int len) {
314: return(fread(&buffer[0], 1, len, (FILE *) context));
315: }
316:
317: /**
1.27 daniel 318: * xmlFileWrite:
319: * @context: the I/O context
320: * @buffer: where to drop data
321: * @len: number of bytes to write
322: *
323: * Write @len bytes from @buffer to the I/O channel.
324: *
325: * Returns the number of bytes written
326: */
327: int
328: xmlFileWrite (void * context, const char * buffer, int len) {
329: return(fwrite(&buffer[0], 1, len, (FILE *) context));
330: }
331:
332: /**
1.23 daniel 333: * xmlFileClose:
334: * @context: the I/O context
335: *
336: * Close an I/O channel
337: */
338: void
339: xmlFileClose (void * context) {
340: fclose((FILE *) context);
341: }
342:
343: #ifdef HAVE_ZLIB_H
344: /************************************************************************
345: * *
346: * I/O for compressed file accesses *
347: * *
348: ************************************************************************/
349: /**
350: * xmlGzfileMatch:
351: * @filename: the URI for matching
352: *
353: * input from compressed file test
354: *
355: * Returns 1 if matches, 0 otherwise
356: */
357: int
358: xmlGzfileMatch (const char *filename) {
359: return(1);
360: }
361:
362: /**
363: * xmlGzfileOpen:
364: * @filename: the URI for matching
365: *
366: * input from compressed file open
367: * if @filename is " " then the standard input is used
368: *
369: * Returns an I/O context or NULL in case of error
370: */
371: void *
372: xmlGzfileOpen (const char *filename) {
373: const char *path = NULL;
374: gzFile fd;
375:
376: if (!strcmp(filename, "-")) {
377: fd = gzdopen (fileno(stdin), "r");
378: return((void *) fd);
379: }
380:
381: if (!strncmp(filename, "file://localhost", 16))
382: path = &filename[16];
383: else if (!strncmp(filename, "file:///", 8))
384: path = &filename[8];
385: else
386: path = filename;
387:
388: fd = gzopen(filename, "r");
389: return((void *) fd);
390: }
391:
392: /**
1.28 daniel 393: * xmlGzfileOpenW:
394: * @filename: the URI for matching
395: * @compression: the compression factor (0 - 9 included)
396: *
397: * input from compressed file open
398: * if @filename is " " then the standard input is used
399: *
400: * Returns an I/O context or NULL in case of error
401: */
402: void *
403: xmlGzfileOpenW (const char *filename, int compression) {
404: const char *path = NULL;
405: char mode[15];
406: gzFile fd;
407:
408: sprintf(mode, "w%d", compression);
409: if (!strcmp(filename, "-")) {
410: fd = gzdopen(1, mode);
411: return((void *) fd);
412: }
413:
414: if (!strncmp(filename, "file://localhost", 16))
415: path = &filename[16];
416: else if (!strncmp(filename, "file:///", 8))
417: path = &filename[8];
418: else
419: path = filename;
420:
421: fd = gzopen(filename, mode);
422: return((void *) fd);
423: }
424:
425: /**
1.23 daniel 426: * xmlGzfileRead:
427: * @context: the I/O context
428: * @buffer: where to drop data
429: * @len: number of bytes to write
430: *
431: * Read @len bytes to @buffer from the compressed I/O channel.
432: *
433: * Returns the number of bytes written
434: */
435: int
436: xmlGzfileRead (void * context, char * buffer, int len) {
437: return(gzread((gzFile) context, &buffer[0], len));
438: }
439:
440: /**
1.28 daniel 441: * xmlGzfileWrite:
442: * @context: the I/O context
443: * @buffer: where to drop data
444: * @len: number of bytes to write
445: *
446: * Write @len bytes from @buffer to the compressed I/O channel.
447: *
448: * Returns the number of bytes written
449: */
450: int
451: xmlGzfileWrite (void * context, const char * buffer, int len) {
452: return(gzwrite((gzFile) context, (char *) &buffer[0], len));
453: }
454:
455: /**
1.23 daniel 456: * xmlGzfileClose:
457: * @context: the I/O context
458: *
459: * Close a compressed I/O channel
460: */
461: void
462: xmlGzfileClose (void * context) {
463: gzclose((gzFile) context);
464: }
465: #endif /* HAVE_ZLIB_H */
466:
467: #ifdef LIBXML_HTTP_ENABLED
468: /************************************************************************
469: * *
470: * I/O for HTTP file accesses *
471: * *
472: ************************************************************************/
473: /**
474: * xmlIOHTTPMatch:
475: * @filename: the URI for matching
476: *
477: * check if the URI matches an HTTP one
478: *
479: * Returns 1 if matches, 0 otherwise
480: */
481: int
482: xmlIOHTTPMatch (const char *filename) {
483: if (!strncmp(filename, "http://", 7))
484: return(1);
485: return(0);
486: }
487:
488: /**
489: * xmlIOHTTPOpen:
490: * @filename: the URI for matching
491: *
492: * open an HTTP I/O channel
493: *
494: * Returns an I/O context or NULL in case of error
495: */
496: void *
497: xmlIOHTTPOpen (const char *filename) {
498: return(xmlNanoHTTPOpen(filename, NULL));
499: }
500:
501: /**
502: * xmlIOHTTPRead:
503: * @context: the I/O context
504: * @buffer: where to drop data
505: * @len: number of bytes to write
506: *
507: * Read @len bytes to @buffer from the I/O channel.
508: *
509: * Returns the number of bytes written
510: */
511: int
512: xmlIOHTTPRead(void * context, char * buffer, int len) {
513: return(xmlNanoHTTPRead(context, &buffer[0], len));
1.22 daniel 514: }
515:
1.23 daniel 516: /**
517: * xmlIOHTTPClose:
518: * @context: the I/O context
519: *
520: * Close an HTTP I/O channel
521: */
522: void
523: xmlIOHTTPClose (void * context) {
524: xmlNanoHTTPClose(context);
1.22 daniel 525: }
1.23 daniel 526: #endif /* LIBXML_HTTP_ENABLED */
527:
528: #ifdef LIBXML_FTP_ENABLED
529: /************************************************************************
530: * *
531: * I/O for FTP file accesses *
532: * *
533: ************************************************************************/
534: /**
535: * xmlIOFTPMatch:
536: * @filename: the URI for matching
537: *
538: * check if the URI matches an FTP one
539: *
540: * Returns 1 if matches, 0 otherwise
541: */
542: int
543: xmlIOFTPMatch (const char *filename) {
544: if (!strncmp(filename, "ftp://", 6))
545: return(1);
546: return(0);
1.22 daniel 547: }
548:
1.23 daniel 549: /**
550: * xmlIOFTPOpen:
551: * @filename: the URI for matching
552: *
553: * open an FTP I/O channel
554: *
555: * Returns an I/O context or NULL in case of error
556: */
557: void *
558: xmlIOFTPOpen (const char *filename) {
559: return(xmlNanoFTPOpen(filename));
1.22 daniel 560: }
1.23 daniel 561:
562: /**
563: * xmlIOFTPRead:
564: * @context: the I/O context
565: * @buffer: where to drop data
566: * @len: number of bytes to write
567: *
568: * Read @len bytes to @buffer from the I/O channel.
569: *
570: * Returns the number of bytes written
571: */
572: int
573: xmlIOFTPRead(void * context, char * buffer, int len) {
574: return(xmlNanoFTPRead(context, &buffer[0], len));
1.22 daniel 575: }
1.23 daniel 576:
577: /**
578: * xmlIOFTPClose:
579: * @context: the I/O context
580: *
581: * Close an FTP I/O channel
582: */
583: void
584: xmlIOFTPClose (void * context) {
585: xmlNanoFTPClose(context);
1.22 daniel 586: }
1.23 daniel 587: #endif /* LIBXML_FTP_ENABLED */
588:
589:
590: /**
591: * xmlRegisterInputCallbacks:
592: * @match: the xmlInputMatchCallback
593: * @open: the xmlInputOpenCallback
594: * @read: the xmlInputReadCallback
595: * @close: the xmlInputCloseCallback
596: *
597: * Register a new set of I/O callback for handling parser input.
598: *
599: * Returns the registered handler number or -1 in case of error
600: */
601: int
602: xmlRegisterInputCallbacks(xmlInputMatchCallback match,
603: xmlInputOpenCallback open, xmlInputReadCallback read,
604: xmlInputCloseCallback close) {
605: if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
606: return(-1);
607: }
608: xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = match;
609: xmlInputCallbackTable[xmlInputCallbackNr].opencallback = open;
610: xmlInputCallbackTable[xmlInputCallbackNr].readcallback = read;
611: xmlInputCallbackTable[xmlInputCallbackNr].closecallback = close;
612: return(xmlInputCallbackNr++);
1.22 daniel 613: }
614:
1.23 daniel 615: /**
1.27 daniel 616: * xmlRegisterOutputCallbacks:
617: * @match: the xmlOutputMatchCallback
618: * @open: the xmlOutputOpenCallback
619: * @write: the xmlOutputWriteCallback
620: * @close: the xmlOutputCloseCallback
621: *
622: * Register a new set of I/O callback for handling output.
623: *
624: * Returns the registered handler number or -1 in case of error
625: */
626: int
627: xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
628: xmlOutputOpenCallback open, xmlOutputWriteCallback write,
629: xmlOutputCloseCallback close) {
630: if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
631: return(-1);
632: }
633: xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
634: xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
635: xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
636: xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
637: return(xmlOutputCallbackNr++);
638: }
639:
640: /**
1.23 daniel 641: * xmlRegisterDefaultInputCallbacks:
642: *
643: * Registers the default compiled-in I/O handlers.
644: */
645: void
646: xmlRegisterDefaultInputCallbacks(void) {
647: xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
648: xmlFileRead, xmlFileClose);
649: #ifdef HAVE_ZLIB_H
650: xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
651: xmlGzfileRead, xmlGzfileClose);
652: #endif /* HAVE_ZLIB_H */
653:
654: #ifdef LIBXML_HTTP_ENABLED
655: xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
656: xmlIOHTTPRead, xmlIOHTTPClose);
657: #endif /* LIBXML_HTTP_ENABLED */
658:
659: #ifdef LIBXML_FTP_ENABLED
660: xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
661: xmlIOFTPRead, xmlIOFTPClose);
662: #endif /* LIBXML_FTP_ENABLED */
663: }
1.22 daniel 664:
1.1 daniel 665: /**
1.27 daniel 666: * xmlRegisterDefaultOutputCallbacks:
667: *
668: * Registers the default compiled-in I/O handlers.
669: */
670: void
671: xmlRegisterDefaultOutputCallbacks(void) {
1.28 daniel 672: xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
1.27 daniel 673: xmlFileWrite, xmlFileClose);
674: /*********************************
675: No way a-priori to distinguish between gzipped files from
676: uncompressed ones except opening if existing then closing
677: and saving with same compression ratio ... a pain.
678:
679: #ifdef HAVE_ZLIB_H
680: xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
681: xmlGzfileWrite, xmlGzfileClose);
682: #endif
683: No HTTP PUT support yet, patches welcome
684:
685: #ifdef LIBXML_HTTP_ENABLED
686: xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
687: xmlIOHTTPWrite, xmlIOHTTPClose);
688: #endif
689:
690: Nor FTP PUT ....
691: #ifdef LIBXML_FTP_ENABLED
692: xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
693: xmlIOFTPWrite, xmlIOFTPClose);
694: #endif
695: **********************************/
696: }
697:
698: /**
1.1 daniel 699: * xmlAllocParserInputBuffer:
700: * @enc: the charset encoding if known
701: *
702: * Create a buffered parser input for progressive parsing
703: *
704: * Returns the new parser input or NULL
705: */
706: xmlParserInputBufferPtr
707: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
708: xmlParserInputBufferPtr ret;
709:
1.8 daniel 710: ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1.1 daniel 711: if (ret == NULL) {
712: fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
713: return(NULL);
714: }
1.3 veillard 715: memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
1.1 daniel 716: ret->buffer = xmlBufferCreate();
1.17 daniel 717: if (ret->buffer == NULL) {
718: xmlFree(ret);
719: return(NULL);
720: }
721: ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
1.1 daniel 722: ret->encoder = xmlGetCharEncodingHandler(enc);
1.26 daniel 723: if (ret->encoder != NULL)
724: ret->raw = xmlBufferCreate();
725: else
726: ret->raw = NULL;
1.23 daniel 727: ret->readcallback = NULL;
728: ret->closecallback = NULL;
729: ret->context = NULL;
1.1 daniel 730:
731: return(ret);
732: }
733:
734: /**
1.27 daniel 735: * xmlAllocOutputBuffer:
736: * @encoder: the encoding converter or NULL
737: *
738: * Create a buffered parser output
739: *
740: * Returns the new parser output or NULL
741: */
742: xmlOutputBufferPtr
743: xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
744: xmlOutputBufferPtr ret;
745:
746: ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
747: if (ret == NULL) {
748: fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
749: return(NULL);
750: }
751: memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
752: ret->buffer = xmlBufferCreate();
753: if (ret->buffer == NULL) {
754: xmlFree(ret);
755: return(NULL);
756: }
757: ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
758: ret->encoder = encoder;
1.28 daniel 759: if (encoder != NULL) {
760: ret->conv = xmlBufferCreateSize(4000);
761: /*
762: * This call is designed to initiate the encoder state
763: */
764: xmlCharEncOutFunc(encoder, ret->conv, NULL);
765: } else
766: ret->conv = NULL;
1.27 daniel 767: ret->writecallback = NULL;
768: ret->closecallback = NULL;
769: ret->context = NULL;
1.28 daniel 770: ret->written = 0;
1.27 daniel 771:
772: return(ret);
773: }
774:
775: /**
1.1 daniel 776: * xmlFreeParserInputBuffer:
777: * @in: a buffered parser input
778: *
779: * Free up the memory used by a buffered parser input
780: */
781: void
782: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1.26 daniel 783: if (in->raw) {
784: xmlBufferFree(in->raw);
785: in->raw = NULL;
786: }
1.25 daniel 787: if (in->encoder != NULL) {
788: xmlCharEncCloseFunc(in->encoder);
789: }
790: if (in->closecallback != NULL) {
791: in->closecallback(in->context);
792: }
1.1 daniel 793: if (in->buffer != NULL) {
794: xmlBufferFree(in->buffer);
795: in->buffer = NULL;
796: }
1.23 daniel 797:
1.3 veillard 798: memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
1.8 daniel 799: xmlFree(in);
1.1 daniel 800: }
801:
802: /**
1.28 daniel 803: * xmlOutputBufferClose:
804: * @out: a buffered output
805: *
806: * flushes and close the output I/O channel
807: * and free up all the associated resources
808: *
809: * Returns the number of byte written or -1 in case of error.
810: */
811: int
812: xmlOutputBufferClose(xmlOutputBufferPtr out) {
813: int written;
814:
815: if (out == NULL)
816: return(-1);
817: xmlOutputBufferFlush(out);
818: if (out->closecallback != NULL) {
819: out->closecallback(out->context);
820: }
821: written = out->written;
822: if (out->conv) {
823: xmlBufferFree(out->conv);
824: out->conv = NULL;
825: }
826: if (out->encoder != NULL) {
827: xmlCharEncCloseFunc(out->encoder);
828: }
829: if (out->buffer != NULL) {
830: xmlBufferFree(out->buffer);
831: out->buffer = NULL;
832: }
833:
834: memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
835: xmlFree(out);
836: return(written);
837: }
838:
839: /**
1.1 daniel 840: * xmlParserInputBufferCreateFilename:
1.23 daniel 841: * @URI: a C string containing the URI or filename
1.1 daniel 842: * @enc: the charset encoding if known
843: *
844: * Create a buffered parser input for the progressive parsing of a file
845: * If filename is "-' then we use stdin as the input.
846: * Automatic support for ZLIB/Compress compressed document is provided
847: * by default if found at compile-time.
1.20 daniel 848: * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1.1 daniel 849: *
850: * Returns the new parser input or NULL
851: */
852: xmlParserInputBufferPtr
1.23 daniel 853: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1.1 daniel 854: xmlParserInputBufferPtr ret;
1.23 daniel 855: int i;
856: void *context = NULL;
857:
858: if (xmlInputCallbackInitialized == 0)
859: xmlRegisterDefaultInputCallbacks();
1.1 daniel 860:
1.23 daniel 861: if (URI == NULL) return(NULL);
1.1 daniel 862:
1.23 daniel 863: /*
864: * Try to find one of the input accept method accepting taht scheme
865: * Go in reverse to give precedence to user defined handlers.
866: */
867: for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
868: if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
869: (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
870: context = xmlInputCallbackTable[i].opencallback(URI);
871: if (context != NULL)
872: break;
1.1 daniel 873: }
1.23 daniel 874: }
875: if (context == NULL) {
876: #ifdef DEBUG_INPUT
877: fprintf(stderr, "No input filter matching \"%s\"\n", URI);
1.1 daniel 878: #endif
1.23 daniel 879: return(NULL);
1.1 daniel 880: }
1.20 daniel 881:
882: /*
883: * Allocate the Input buffer front-end.
1.1 daniel 884: */
885: ret = xmlAllocParserInputBuffer(enc);
886: if (ret != NULL) {
1.23 daniel 887: ret->context = context;
888: ret->readcallback = xmlInputCallbackTable[i].readcallback;
889: ret->closecallback = xmlInputCallbackTable[i].closecallback;
1.1 daniel 890: }
891: return(ret);
892: }
893:
894: /**
1.27 daniel 895: * xmlOutputBufferCreateFilename:
896: * @URI: a C string containing the URI or filename
897: * @encoder: the encoding converter or NULL
1.28 daniel 898: * @compression: the compression ration (0 none, 9 max).
1.27 daniel 899: *
900: * Create a buffered output for the progressive saving of a file
901: * If filename is "-' then we use stdout as the output.
902: * Automatic support for ZLIB/Compress compressed document is provided
903: * by default if found at compile-time.
1.28 daniel 904: * TODO: currently if compression is set, the library only support
905: * writing to a local file.
1.27 daniel 906: *
907: * Returns the new output or NULL
908: */
909: xmlOutputBufferPtr
910: xmlOutputBufferCreateFilename(const char *URI,
1.28 daniel 911: xmlCharEncodingHandlerPtr encoder,
912: int compression) {
1.27 daniel 913: xmlOutputBufferPtr ret;
914: int i;
915: void *context = NULL;
916:
917: if (xmlOutputCallbackInitialized == 0)
918: xmlRegisterDefaultOutputCallbacks();
919:
920: if (URI == NULL) return(NULL);
921:
1.28 daniel 922: #ifdef HAVE_ZLIB_H
923: if ((compression > 0) && (compression <= 9)) {
924: context = xmlGzfileOpenW(URI, compression);
925: if (context != NULL) {
926: ret = xmlAllocOutputBuffer(encoder);
927: if (ret != NULL) {
928: ret->context = context;
929: ret->writecallback = xmlGzfileWrite;
930: ret->closecallback = xmlGzfileClose;
931: }
932: return(ret);
933: }
934: }
935: #endif
936:
1.27 daniel 937: /*
938: * Try to find one of the output accept method accepting taht scheme
939: * Go in reverse to give precedence to user defined handlers.
940: */
941: for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
942: if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
943: (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
944: context = xmlOutputCallbackTable[i].opencallback(URI);
945: if (context != NULL)
946: break;
947: }
948: }
949: if (context == NULL) {
950: #ifdef DEBUG_INPUT
951: fprintf(stderr, "No output filter matching \"%s\"\n", URI);
952: #endif
953: return(NULL);
954: }
955:
956: /*
957: * Allocate the Output buffer front-end.
958: */
959: ret = xmlAllocOutputBuffer(encoder);
960: if (ret != NULL) {
961: ret->context = context;
962: ret->writecallback = xmlOutputCallbackTable[i].writecallback;
963: ret->closecallback = xmlOutputCallbackTable[i].closecallback;
964: }
965: return(ret);
966: }
967:
968: /**
1.1 daniel 969: * xmlParserInputBufferCreateFile:
970: * @file: a FILE*
971: * @enc: the charset encoding if known
972: *
973: * Create a buffered parser input for the progressive parsing of a FILE *
974: * buffered C I/O
975: *
976: * Returns the new parser input or NULL
977: */
978: xmlParserInputBufferPtr
979: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
980: xmlParserInputBufferPtr ret;
981:
1.23 daniel 982: if (xmlInputCallbackInitialized == 0)
983: xmlRegisterDefaultInputCallbacks();
984:
1.1 daniel 985: if (file == NULL) return(NULL);
986:
987: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 988: if (ret != NULL) {
989: ret->context = file;
990: ret->readcallback = xmlFileRead;
991: ret->closecallback = xmlFileClose;
992: }
1.1 daniel 993:
994: return(ret);
995: }
996:
997: /**
1.27 daniel 998: * xmlOutputBufferCreateFile:
999: * @file: a FILE*
1000: * @encoder: the encoding converter or NULL
1001: *
1002: * Create a buffered output for the progressive saving to a FILE *
1003: * buffered C I/O
1004: *
1005: * Returns the new parser output or NULL
1006: */
1007: xmlOutputBufferPtr
1008: xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1009: xmlOutputBufferPtr ret;
1010:
1011: if (xmlOutputCallbackInitialized == 0)
1012: xmlRegisterDefaultOutputCallbacks();
1013:
1014: if (file == NULL) return(NULL);
1015:
1016: ret = xmlAllocOutputBuffer(encoder);
1017: if (ret != NULL) {
1018: ret->context = file;
1019: ret->writecallback = xmlFileWrite;
1020: ret->closecallback = xmlFileClose;
1021: }
1022:
1023: return(ret);
1024: }
1025:
1026: /**
1.1 daniel 1027: * xmlParserInputBufferCreateFd:
1028: * @fd: a file descriptor number
1029: * @enc: the charset encoding if known
1030: *
1031: * Create a buffered parser input for the progressive parsing for the input
1032: * from a file descriptor
1033: *
1034: * Returns the new parser input or NULL
1035: */
1036: xmlParserInputBufferPtr
1037: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1038: xmlParserInputBufferPtr ret;
1039:
1040: if (fd < 0) return(NULL);
1041:
1042: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 1043: if (ret != NULL) {
1044: ret->context = (void *) fd;
1045: ret->readcallback = xmlFdRead;
1046: ret->closecallback = xmlFdClose;
1047: }
1.1 daniel 1048:
1049: return(ret);
1050: }
1051:
1052: /**
1.31 veillard 1053: * xmlParserInputBufferCreateMem:
1054: * @mem: the memory input
1055: * @size: the length of the memory block
1056: * @enc: the charset encoding if known
1057: *
1058: * Create a buffered parser input for the progressive parsing for the input
1059: * from a file descriptor
1060: *
1061: * Returns the new parser input or NULL
1062: */
1063: xmlParserInputBufferPtr
1064: xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1065: xmlParserInputBufferPtr ret;
1066:
1067: if (size <= 0) return(NULL);
1068: if (mem == NULL) return(NULL);
1069:
1070: ret = xmlAllocParserInputBuffer(enc);
1071: if (ret != NULL) {
1072: ret->context = (void *) mem;
1.32 ! veillard 1073: ret->readcallback = (xmlInputReadCallback) xmlNop;
1.31 veillard 1074: ret->closecallback = NULL;
1075: xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
1076: }
1077:
1078: return(ret);
1079: }
1080:
1081: /**
1.27 daniel 1082: * xmlOutputBufferCreateFd:
1083: * @fd: a file descriptor number
1084: * @encoder: the encoding converter or NULL
1085: *
1086: * Create a buffered output for the progressive saving
1087: * to a file descriptor
1088: *
1089: * Returns the new parser output or NULL
1090: */
1091: xmlOutputBufferPtr
1092: xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
1093: xmlOutputBufferPtr ret;
1094:
1095: if (fd < 0) return(NULL);
1096:
1097: ret = xmlAllocOutputBuffer(encoder);
1098: if (ret != NULL) {
1099: ret->context = (void *) fd;
1100: ret->writecallback = xmlFdWrite;
1101: ret->closecallback = xmlFdClose;
1102: }
1103:
1104: return(ret);
1105: }
1106:
1107: /**
1.24 daniel 1108: * xmlParserInputBufferCreateIO:
1109: * @ioread: an I/O read function
1110: * @ioclose: an I/O close function
1111: * @ioctx: an I/O handler
1112: * @enc: the charset encoding if known
1113: *
1114: * Create a buffered parser input for the progressive parsing for the input
1.27 daniel 1115: * from an I/O handler
1.24 daniel 1116: *
1117: * Returns the new parser input or NULL
1118: */
1119: xmlParserInputBufferPtr
1120: xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
1121: xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
1122: xmlParserInputBufferPtr ret;
1123:
1124: if (ioread == NULL) return(NULL);
1125:
1126: ret = xmlAllocParserInputBuffer(enc);
1127: if (ret != NULL) {
1128: ret->context = (void *) ioctx;
1129: ret->readcallback = ioread;
1130: ret->closecallback = ioclose;
1131: }
1132:
1133: return(ret);
1134: }
1135:
1136: /**
1.27 daniel 1137: * xmlOutputBufferCreateIO:
1138: * @iowrite: an I/O write function
1139: * @ioclose: an I/O close function
1140: * @ioctx: an I/O handler
1141: * @enc: the charset encoding if known
1142: *
1143: * Create a buffered output for the progressive saving
1144: * to an I/O handler
1145: *
1146: * Returns the new parser output or NULL
1147: */
1148: xmlOutputBufferPtr
1149: xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
1150: xmlOutputCloseCallback ioclose, void *ioctx,
1151: xmlCharEncodingHandlerPtr encoder) {
1152: xmlOutputBufferPtr ret;
1153:
1154: if (iowrite == NULL) return(NULL);
1155:
1156: ret = xmlAllocOutputBuffer(encoder);
1157: if (ret != NULL) {
1158: ret->context = (void *) ioctx;
1159: ret->writecallback = iowrite;
1160: ret->closecallback = ioclose;
1161: }
1162:
1163: return(ret);
1164: }
1165:
1166: /**
1.14 daniel 1167: * xmlParserInputBufferPush:
1168: * @in: a buffered parser input
1.27 daniel 1169: * @len: the size in bytes of the array.
1.14 daniel 1170: * @buf: an char array
1171: *
1172: * Push the content of the arry in the input buffer
1173: * This routine handle the I18N transcoding to internal UTF-8
1174: * This is used when operating the parser in progressive (push) mode.
1175: *
1176: * Returns the number of chars read and stored in the buffer, or -1
1177: * in case of error.
1178: */
1179: int
1.15 daniel 1180: xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
1.14 daniel 1181: int nbchars = 0;
1182:
1183: if (len < 0) return(0);
1184: if (in->encoder != NULL) {
1.26 daniel 1185: /*
1186: * Store the data in the incoming raw buffer
1187: */
1188: if (in->raw == NULL) {
1189: in->raw = xmlBufferCreate();
1190: }
1191: xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
1.14 daniel 1192:
1193: /*
1.26 daniel 1194: * convert as much as possible to the parser reading buffer.
1.14 daniel 1195: */
1.26 daniel 1196: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1.20 daniel 1197: if (nbchars < 0) {
1198: fprintf(stderr, "xmlParserInputBufferPush: encoder error\n");
1199: return(-1);
1200: }
1.14 daniel 1201: } else {
1202: nbchars = len;
1.17 daniel 1203: xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
1.14 daniel 1204: }
1205: #ifdef DEBUG_INPUT
1206: fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
1207: nbchars, in->buffer->use, in->buffer->size);
1208: #endif
1209: return(nbchars);
1210: }
1211:
1212: /**
1.1 daniel 1213: * xmlParserInputBufferGrow:
1214: * @in: a buffered parser input
1215: * @len: indicative value of the amount of chars to read
1216: *
1217: * Grow up the content of the input buffer, the old data are preserved
1218: * This routine handle the I18N transcoding to internal UTF-8
1.14 daniel 1219: * This routine is used when operating the parser in normal (pull) mode
1.26 daniel 1220: *
1221: * TODO: one should be able to remove one extra copy by copying directy
1222: * onto in->buffer or in->raw
1.1 daniel 1223: *
1224: * Returns the number of chars read and stored in the buffer, or -1
1225: * in case of error.
1226: */
1227: int
1228: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
1229: char *buffer = NULL;
1230: int res = 0;
1231: int nbchars = 0;
1232: int buffree;
1233:
1234: if ((len <= MINLEN) && (len != 4))
1235: len = MINLEN;
1236: buffree = in->buffer->size - in->buffer->use;
1237: if (buffree <= 0) {
1238: fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
1239: return(0);
1240: }
1241: if (len > buffree)
1242: len = buffree;
1243:
1.30 veillard 1244: buffer = (char *) xmlMalloc((len + 1) * sizeof(char));
1.1 daniel 1245: if (buffer == NULL) {
1246: fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
1247: return(-1);
1248: }
1.23 daniel 1249:
1250: /*
1251: * Call the read method for this I/O type.
1252: */
1253: if (in->readcallback != NULL) {
1254: res = in->readcallback(in->context, &buffer[0], len);
1.1 daniel 1255: } else {
1256: fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
1.8 daniel 1257: xmlFree(buffer);
1.1 daniel 1258: return(-1);
1259: }
1260: if (res < 0) {
1261: perror ("read error");
1.8 daniel 1262: xmlFree(buffer);
1.1 daniel 1263: return(-1);
1264: }
1.29 daniel 1265: len = res;
1.1 daniel 1266: if (in->encoder != NULL) {
1.26 daniel 1267: /*
1268: * Store the data in the incoming raw buffer
1269: */
1270: if (in->raw == NULL) {
1271: in->raw = xmlBufferCreate();
1.1 daniel 1272: }
1.26 daniel 1273: xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
1.20 daniel 1274:
1275: /*
1.26 daniel 1276: * convert as much as possible to the parser reading buffer.
1.20 daniel 1277: */
1.26 daniel 1278: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1279: if (nbchars < 0) {
1280: fprintf(stderr, "xmlParserInputBufferGrow: encoder error\n");
1281: return(-1);
1.20 daniel 1282: }
1.1 daniel 1283: } else {
1.29 daniel 1284: nbchars = len;
1.3 veillard 1285: buffer[nbchars] = 0;
1.13 daniel 1286: xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
1.1 daniel 1287: }
1288: #ifdef DEBUG_INPUT
1289: fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
1290: nbchars, in->buffer->use, in->buffer->size);
1291: #endif
1.8 daniel 1292: xmlFree(buffer);
1.1 daniel 1293: return(nbchars);
1294: }
1295:
1296: /**
1297: * xmlParserInputBufferRead:
1298: * @in: a buffered parser input
1299: * @len: indicative value of the amount of chars to read
1300: *
1301: * Refresh the content of the input buffer, the old data are considered
1302: * consumed
1303: * This routine handle the I18N transcoding to internal UTF-8
1304: *
1305: * Returns the number of chars read and stored in the buffer, or -1
1306: * in case of error.
1307: */
1308: int
1309: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
1310: /* xmlBufferEmpty(in->buffer); */
1.23 daniel 1311: if (in->readcallback != NULL)
1.17 daniel 1312: return(xmlParserInputBufferGrow(in, len));
1313: else
1.27 daniel 1314: return(-1);
1315: }
1316:
1317: /**
1318: * xmlOutputBufferWrite:
1319: * @out: a buffered parser output
1320: * @len: the size in bytes of the array.
1321: * @buf: an char array
1322: *
1323: * Write the content of the array in the output I/O buffer
1324: * This routine handle the I18N transcoding from internal UTF-8
1325: * The buffer is lossless, i.e. will store in case of partial
1326: * or delayed writes.
1327: *
1328: * Returns the number of chars immediately written, or -1
1329: * in case of error.
1330: */
1331: int
1332: xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
1333: int nbchars = 0, ret;
1334:
1335: if (len < 0) return(0);
1336:
1337: /*
1338: * first handle encoding stuff.
1339: */
1340: if (out->encoder != NULL) {
1341: /*
1342: * Store the data in the incoming raw buffer
1343: */
1.28 daniel 1344: if (out->conv == NULL) {
1345: out->conv = xmlBufferCreate();
1.27 daniel 1346: }
1.28 daniel 1347: xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.27 daniel 1348:
1.28 daniel 1349: if (out->buffer->use < MINLEN)
1.27 daniel 1350: return(0);
1351:
1352: /*
1353: * convert as much as possible to the parser reading buffer.
1354: */
1.28 daniel 1355: nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
1.27 daniel 1356: if (nbchars < 0) {
1357: fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
1358: return(-1);
1359: }
1.28 daniel 1360: nbchars = out->conv->use;
1.27 daniel 1361: } else {
1362: xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.28 daniel 1363: nbchars = out->buffer->use;
1.27 daniel 1364: }
1365: if (nbchars < MINLEN)
1366: return(0);
1367:
1368: /*
1369: * second write the stuff to the I/O channel
1370: */
1.28 daniel 1371: if (out->encoder != NULL) {
1372: ret = out->writecallback(out->context,
1373: (const char *)out->conv->content, nbchars);
1374: if (ret >= 0)
1375: xmlBufferShrink(out->conv, nbchars);
1376: } else {
1377: ret = out->writecallback(out->context,
1.27 daniel 1378: (const char *)out->buffer->content, nbchars);
1.28 daniel 1379: if (ret >= 0)
1380: xmlBufferShrink(out->buffer, nbchars);
1381: }
1.27 daniel 1382: if (ret < 0) {
1383: fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
1384: return(ret);
1385: }
1.28 daniel 1386: out->written += ret;
1.27 daniel 1387:
1388: #ifdef DEBUG_INPUT
1389: fprintf(stderr, "I/O: wrote %d chars\n", ret);
1390: #endif
1391: return(nbchars);
1.28 daniel 1392: }
1393:
1394: /**
1395: * xmlOutputBufferWriteString:
1396: * @out: a buffered parser output
1397: * @str: a zero terminated C string
1398: *
1399: * Write the content of the string in the output I/O buffer
1400: * This routine handle the I18N transcoding from internal UTF-8
1401: * The buffer is lossless, i.e. will store in case of partial
1402: * or delayed writes.
1403: *
1404: * Returns the number of chars immediately written, or -1
1405: * in case of error.
1406: */
1407: int
1408: xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
1409: int len;
1410:
1411: if (str == NULL)
1412: return(-1);
1413: len = strlen(str);
1414:
1415: if (len > 0)
1416: return(xmlOutputBufferWrite(out, len, str));
1417: return(len);
1418: }
1419:
1420: /**
1421: * xmlOutputBufferFlush:
1422: * @out: a buffered output
1423: *
1424: * flushes the output I/O channel
1425: *
1426: * Returns the number of byte written or -1 in case of error.
1427: */
1428: int
1429: xmlOutputBufferFlush(xmlOutputBufferPtr out) {
1430: int nbchars = 0, ret;
1431:
1432: /*
1433: * first handle encoding stuff.
1434: */
1435: if ((out->conv != NULL) && (out->encoder != NULL)) {
1436: /*
1437: * convert as much as possible to the parser reading buffer.
1438: */
1439: nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
1440: if (nbchars < 0) {
1441: fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
1442: return(-1);
1443: }
1444: }
1445:
1446: /*
1447: * second flush the stuff to the I/O channel
1448: */
1449: if ((out->conv != NULL) && (out->encoder != NULL)) {
1450: ret = out->writecallback(out->context,
1451: (const char *)out->conv->content, out->conv->use);
1452: if (ret >= 0)
1453: xmlBufferShrink(out->conv, ret);
1454: } else {
1455: ret = out->writecallback(out->context,
1456: (const char *)out->buffer->content, out->buffer->use);
1457: if (ret >= 0)
1458: xmlBufferShrink(out->buffer, ret);
1459: }
1460: if (ret < 0) {
1461: fprintf(stderr, "I/O: error %d flushing %d bytes\n", ret, nbchars);
1462: return(ret);
1463: }
1464: out->written += ret;
1465:
1466: #ifdef DEBUG_INPUT
1467: fprintf(stderr, "I/O: flushed %d chars\n", ret);
1468: #endif
1469: return(ret);
1.4 daniel 1470: }
1471:
1472: /*
1473: * xmlParserGetDirectory:
1474: * @filename: the path to a file
1475: *
1476: * lookup the directory for that file
1477: *
1478: * Returns a new allocated string containing the directory, or NULL.
1479: */
1480: char *
1481: xmlParserGetDirectory(const char *filename) {
1482: char *ret = NULL;
1483: char dir[1024];
1484: char *cur;
1485: char sep = '/';
1.23 daniel 1486:
1487: if (xmlInputCallbackInitialized == 0)
1488: xmlRegisterDefaultInputCallbacks();
1.4 daniel 1489:
1490: if (filename == NULL) return(NULL);
1491: #ifdef WIN32
1492: sep = '\\';
1493: #endif
1494:
1495: strncpy(dir, filename, 1023);
1496: dir[1023] = 0;
1497: cur = &dir[strlen(dir)];
1498: while (cur > dir) {
1499: if (*cur == sep) break;
1500: cur --;
1501: }
1502: if (*cur == sep) {
1503: if (cur == dir) dir[1] = 0;
1504: else *cur = 0;
1.8 daniel 1505: ret = xmlMemStrdup(dir);
1.4 daniel 1506: } else {
1507: if (getcwd(dir, 1024) != NULL) {
1508: dir[1023] = 0;
1.8 daniel 1509: ret = xmlMemStrdup(dir);
1.4 daniel 1510: }
1511: }
1512: return(ret);
1.5 daniel 1513: }
1514:
1515: /****************************************************************
1516: * *
1517: * External entities loading *
1518: * *
1519: ****************************************************************/
1520:
1521: /*
1522: * xmlDefaultExternalEntityLoader:
1523: * @URL: the URL for the entity to load
1524: * @ID: the System ID for the entity to load
1.18 daniel 1525: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 1526: *
1527: * By default we don't load external entitites, yet.
1528: *
1529: * Returns a new allocated xmlParserInputPtr, or NULL.
1530: */
1531: static
1532: xmlParserInputPtr
1533: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
1.18 daniel 1534: xmlParserCtxtPtr ctxt) {
1535: xmlParserInputPtr ret = NULL;
1.5 daniel 1536: #ifdef DEBUG_EXTERNAL_ENTITIES
1537: fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
1538: #endif
1.18 daniel 1539: if (URL == NULL) {
1540: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1541: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
1542: ID);
1543: return(NULL);
1544: }
1545: ret = xmlNewInputFromFile(ctxt, URL);
1546: if (ret == NULL) {
1547: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1548: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
1549: URL);
1550: }
1551: return(ret);
1.5 daniel 1552: }
1553:
1554: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
1555: xmlDefaultExternalEntityLoader;
1556:
1557: /*
1558: * xmlSetExternalEntityLoader:
1559: * @f: the new entity resolver function
1560: *
1561: * Changes the defaultexternal entity resolver function for the application
1562: */
1563: void
1564: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
1565: xmlCurrentExternalEntityLoader = f;
1566: }
1567:
1568: /*
1569: * xmlGetExternalEntityLoader:
1570: *
1571: * Get the default external entity resolver function for the application
1572: *
1573: * Returns the xmlExternalEntityLoader function pointer
1574: */
1575: xmlExternalEntityLoader
1576: xmlGetExternalEntityLoader(void) {
1577: return(xmlCurrentExternalEntityLoader);
1578: }
1579:
1580: /*
1581: * xmlLoadExternalEntity:
1582: * @URL: the URL for the entity to load
1583: * @ID: the System ID for the entity to load
1.18 daniel 1584: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 1585: *
1586: * Load an external entity, note that the use of this function for
1587: * unparsed entities may generate problems
1.6 daniel 1588: * TODO: a more generic External entitiy API must be designed
1.5 daniel 1589: *
1590: * Returns the xmlParserInputPtr or NULL
1591: */
1592: xmlParserInputPtr
1593: xmlLoadExternalEntity(const char *URL, const char *ID,
1.18 daniel 1594: xmlParserCtxtPtr ctxt) {
1595: return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
1.1 daniel 1596: }
1597:
Webmaster