Annotation of XML/xmlIO.c, revision 1.26
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:
44: /* #define DEBUG_INPUT */
1.2 daniel 45: /* #define VERBOSE_FAILURE */
1.5 daniel 46: /* #define DEBUG_EXTERNAL_ENTITIES */
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:
70: /************************************************************************
71: * *
72: * Standard I/O for file accesses *
73: * *
74: ************************************************************************/
1.22 daniel 75:
76: /**
1.23 daniel 77: * xmlFdMatch:
1.22 daniel 78: * @filename: the URI for matching
79: *
80: * input from file descriptor
81: *
82: * Returns 1 if matches, 0 otherwise
83: */
1.23 daniel 84: int
85: xmlFdMatch (const char *filename) {
86: return(1);
87: }
88:
89: /**
90: * xmlFdOpen:
91: * @filename: the URI for matching
92: *
93: * input from file descriptor, supports compressed input
94: * if @filename is " " then the standard input is used
95: *
96: * Returns an I/O context or NULL in case of error
97: */
98: void *
99: xmlFdOpen (const char *filename) {
100: const char *path = NULL;
101: int fd;
102:
103: if (!strcmp(filename, "-")) {
104: fd = 0;
105: return((void *) fd);
106: }
107:
1.22 daniel 108: if (!strncmp(filename, "file://localhost", 16))
1.23 daniel 109: path = &filename[16];
110: else if (!strncmp(filename, "file:///", 8))
111: path = &filename[8];
112: else if (filename[0] == '/')
113: path = filename;
114: if (path == NULL)
115: return(NULL);
116:
117: #ifdef WIN32
118: fd = _open (filename, O_RDONLY | _O_BINARY);
119: #else
120: fd = open (filename, O_RDONLY);
121: #endif
122:
123: return((void *) fd);
124: }
125:
126: /**
127: * xmlFdRead:
128: * @context: the I/O context
129: * @buffer: where to drop data
130: * @len: number of bytes to write
131: *
132: * Read @len bytes to @buffer from the I/O channel.
133: *
134: * Returns the number of bytes written
135: */
136: int
137: xmlFdRead (void * context, char * buffer, int len) {
138: return(read((int) context, &buffer[0], len));
139: }
140:
141: /**
142: * xmlFdClose:
143: * @context: the I/O context
144: *
145: * Close an I/O channel
146: */
147: void
148: xmlFdClose (void * context) {
149: close((int) context);
1.22 daniel 150: }
1.23 daniel 151:
1.22 daniel 152: /**
1.23 daniel 153: * xmlFileMatch:
1.22 daniel 154: * @filename: the URI for matching
155: *
1.23 daniel 156: * input from FILE *
1.22 daniel 157: *
158: * Returns 1 if matches, 0 otherwise
159: */
1.23 daniel 160: int
161: xmlFileMatch (const char *filename) {
162: return(1);
163: }
164:
165: /**
166: * xmlFileOpen:
167: * @filename: the URI for matching
168: *
169: * input from FILE *, supports compressed input
170: * if @filename is " " then the standard input is used
171: *
172: * Returns an I/O context or NULL in case of error
173: */
174: void *
175: xmlFileOpen (const char *filename) {
1.22 daniel 176: const char *path = NULL;
1.23 daniel 177: FILE *fd;
178:
179: if (!strcmp(filename, "-")) {
180: fd = stdin;
181: return((void *) fd);
182: }
1.22 daniel 183:
184: if (!strncmp(filename, "file://localhost", 16))
185: path = &filename[16];
186: else if (!strncmp(filename, "file:///", 8))
1.23 daniel 187: path = &filename[8];
188: else
1.22 daniel 189: path = filename;
190: if (path == NULL)
1.23 daniel 191: return(NULL);
192:
1.22 daniel 193: #ifdef WIN32
1.23 daniel 194: fd = fopen(path, "rb");
1.22 daniel 195: #else
1.23 daniel 196: fd = fopen(path, "r");
197: #endif /* WIN32 */
198: return((void *) fd);
199: }
200:
201: /**
202: * xmlFileRead:
203: * @context: the I/O context
204: * @buffer: where to drop data
205: * @len: number of bytes to write
206: *
207: * Read @len bytes to @buffer from the I/O channel.
208: *
209: * Returns the number of bytes written
210: */
211: int
212: xmlFileRead (void * context, char * buffer, int len) {
213: return(fread(&buffer[0], 1, len, (FILE *) context));
214: }
215:
216: /**
217: * xmlFileClose:
218: * @context: the I/O context
219: *
220: * Close an I/O channel
221: */
222: void
223: xmlFileClose (void * context) {
224: fclose((FILE *) context);
225: }
226:
227: #ifdef HAVE_ZLIB_H
228: /************************************************************************
229: * *
230: * I/O for compressed file accesses *
231: * *
232: ************************************************************************/
233: /**
234: * xmlGzfileMatch:
235: * @filename: the URI for matching
236: *
237: * input from compressed file test
238: *
239: * Returns 1 if matches, 0 otherwise
240: */
241: int
242: xmlGzfileMatch (const char *filename) {
243: return(1);
244: }
245:
246: /**
247: * xmlGzfileOpen:
248: * @filename: the URI for matching
249: *
250: * input from compressed file open
251: * if @filename is " " then the standard input is used
252: *
253: * Returns an I/O context or NULL in case of error
254: */
255: void *
256: xmlGzfileOpen (const char *filename) {
257: const char *path = NULL;
258: gzFile fd;
259:
260: if (!strcmp(filename, "-")) {
261: fd = gzdopen (fileno(stdin), "r");
262: return((void *) fd);
263: }
264:
265: if (!strncmp(filename, "file://localhost", 16))
266: path = &filename[16];
267: else if (!strncmp(filename, "file:///", 8))
268: path = &filename[8];
269: else
270: path = filename;
271:
272: fd = gzopen(filename, "r");
273: return((void *) fd);
274: }
275:
276: /**
277: * xmlGzfileRead:
278: * @context: the I/O context
279: * @buffer: where to drop data
280: * @len: number of bytes to write
281: *
282: * Read @len bytes to @buffer from the compressed I/O channel.
283: *
284: * Returns the number of bytes written
285: */
286: int
287: xmlGzfileRead (void * context, char * buffer, int len) {
288: return(gzread((gzFile) context, &buffer[0], len));
289: }
290:
291: /**
292: * xmlGzfileClose:
293: * @context: the I/O context
294: *
295: * Close a compressed I/O channel
296: */
297: void
298: xmlGzfileClose (void * context) {
299: gzclose((gzFile) context);
300: }
301: #endif /* HAVE_ZLIB_H */
302:
303: #ifdef LIBXML_HTTP_ENABLED
304: /************************************************************************
305: * *
306: * I/O for HTTP file accesses *
307: * *
308: ************************************************************************/
309: /**
310: * xmlIOHTTPMatch:
311: * @filename: the URI for matching
312: *
313: * check if the URI matches an HTTP one
314: *
315: * Returns 1 if matches, 0 otherwise
316: */
317: int
318: xmlIOHTTPMatch (const char *filename) {
319: if (!strncmp(filename, "http://", 7))
320: return(1);
321: return(0);
322: }
323:
324: /**
325: * xmlIOHTTPOpen:
326: * @filename: the URI for matching
327: *
328: * open an HTTP I/O channel
329: *
330: * Returns an I/O context or NULL in case of error
331: */
332: void *
333: xmlIOHTTPOpen (const char *filename) {
334: return(xmlNanoHTTPOpen(filename, NULL));
335: }
336:
337: /**
338: * xmlIOHTTPRead:
339: * @context: the I/O context
340: * @buffer: where to drop data
341: * @len: number of bytes to write
342: *
343: * Read @len bytes to @buffer from the I/O channel.
344: *
345: * Returns the number of bytes written
346: */
347: int
348: xmlIOHTTPRead(void * context, char * buffer, int len) {
349: return(xmlNanoHTTPRead(context, &buffer[0], len));
1.22 daniel 350: }
351:
1.23 daniel 352: /**
353: * xmlIOHTTPClose:
354: * @context: the I/O context
355: *
356: * Close an HTTP I/O channel
357: */
358: void
359: xmlIOHTTPClose (void * context) {
360: xmlNanoHTTPClose(context);
1.22 daniel 361: }
1.23 daniel 362: #endif /* LIBXML_HTTP_ENABLED */
363:
364: #ifdef LIBXML_FTP_ENABLED
365: /************************************************************************
366: * *
367: * I/O for FTP file accesses *
368: * *
369: ************************************************************************/
370: /**
371: * xmlIOFTPMatch:
372: * @filename: the URI for matching
373: *
374: * check if the URI matches an FTP one
375: *
376: * Returns 1 if matches, 0 otherwise
377: */
378: int
379: xmlIOFTPMatch (const char *filename) {
380: if (!strncmp(filename, "ftp://", 6))
381: return(1);
382: return(0);
1.22 daniel 383: }
384:
1.23 daniel 385: /**
386: * xmlIOFTPOpen:
387: * @filename: the URI for matching
388: *
389: * open an FTP I/O channel
390: *
391: * Returns an I/O context or NULL in case of error
392: */
393: void *
394: xmlIOFTPOpen (const char *filename) {
395: return(xmlNanoFTPOpen(filename));
1.22 daniel 396: }
1.23 daniel 397:
398: /**
399: * xmlIOFTPRead:
400: * @context: the I/O context
401: * @buffer: where to drop data
402: * @len: number of bytes to write
403: *
404: * Read @len bytes to @buffer from the I/O channel.
405: *
406: * Returns the number of bytes written
407: */
408: int
409: xmlIOFTPRead(void * context, char * buffer, int len) {
410: return(xmlNanoFTPRead(context, &buffer[0], len));
1.22 daniel 411: }
1.23 daniel 412:
413: /**
414: * xmlIOFTPClose:
415: * @context: the I/O context
416: *
417: * Close an FTP I/O channel
418: */
419: void
420: xmlIOFTPClose (void * context) {
421: xmlNanoFTPClose(context);
1.22 daniel 422: }
1.23 daniel 423: #endif /* LIBXML_FTP_ENABLED */
424:
425:
426: /**
427: * xmlRegisterInputCallbacks:
428: * @match: the xmlInputMatchCallback
429: * @open: the xmlInputOpenCallback
430: * @read: the xmlInputReadCallback
431: * @close: the xmlInputCloseCallback
432: *
433: * Register a new set of I/O callback for handling parser input.
434: *
435: * Returns the registered handler number or -1 in case of error
436: */
437: int
438: xmlRegisterInputCallbacks(xmlInputMatchCallback match,
439: xmlInputOpenCallback open, xmlInputReadCallback read,
440: xmlInputCloseCallback close) {
441: if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
442: return(-1);
443: }
444: xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = match;
445: xmlInputCallbackTable[xmlInputCallbackNr].opencallback = open;
446: xmlInputCallbackTable[xmlInputCallbackNr].readcallback = read;
447: xmlInputCallbackTable[xmlInputCallbackNr].closecallback = close;
448: return(xmlInputCallbackNr++);
1.22 daniel 449: }
450:
1.23 daniel 451: /**
452: * xmlRegisterDefaultInputCallbacks:
453: *
454: * Registers the default compiled-in I/O handlers.
455: */
456: void
457: xmlRegisterDefaultInputCallbacks(void) {
458: xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
459: xmlFileRead, xmlFileClose);
460: #ifdef HAVE_ZLIB_H
461: xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
462: xmlGzfileRead, xmlGzfileClose);
463: #endif /* HAVE_ZLIB_H */
464:
465: #ifdef LIBXML_HTTP_ENABLED
466: xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
467: xmlIOHTTPRead, xmlIOHTTPClose);
468: #endif /* LIBXML_HTTP_ENABLED */
469:
470: #ifdef LIBXML_FTP_ENABLED
471: xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
472: xmlIOFTPRead, xmlIOFTPClose);
473: #endif /* LIBXML_FTP_ENABLED */
474: }
1.22 daniel 475:
1.1 daniel 476: /**
477: * xmlAllocParserInputBuffer:
478: * @enc: the charset encoding if known
479: *
480: * Create a buffered parser input for progressive parsing
481: *
482: * Returns the new parser input or NULL
483: */
484: xmlParserInputBufferPtr
485: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
486: xmlParserInputBufferPtr ret;
487:
1.8 daniel 488: ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1.1 daniel 489: if (ret == NULL) {
490: fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
491: return(NULL);
492: }
1.3 veillard 493: memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
1.1 daniel 494: ret->buffer = xmlBufferCreate();
1.17 daniel 495: if (ret->buffer == NULL) {
496: xmlFree(ret);
497: return(NULL);
498: }
499: ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
1.1 daniel 500: ret->encoder = xmlGetCharEncodingHandler(enc);
1.26 ! daniel 501: if (ret->encoder != NULL)
! 502: ret->raw = xmlBufferCreate();
! 503: else
! 504: ret->raw = NULL;
1.23 daniel 505: ret->readcallback = NULL;
506: ret->closecallback = NULL;
507: ret->context = NULL;
1.1 daniel 508:
509: return(ret);
510: }
511:
512: /**
513: * xmlFreeParserInputBuffer:
514: * @in: a buffered parser input
515: *
516: * Free up the memory used by a buffered parser input
517: */
518: void
519: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1.26 ! daniel 520: if (in->raw) {
! 521: xmlBufferFree(in->raw);
! 522: in->raw = NULL;
! 523: }
1.25 daniel 524: if (in->encoder != NULL) {
525: xmlCharEncCloseFunc(in->encoder);
526: }
527: if (in->closecallback != NULL) {
528: in->closecallback(in->context);
529: }
1.1 daniel 530: if (in->buffer != NULL) {
531: xmlBufferFree(in->buffer);
532: in->buffer = NULL;
533: }
1.23 daniel 534:
1.3 veillard 535: memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
1.8 daniel 536: xmlFree(in);
1.1 daniel 537: }
538:
539: /**
540: * xmlParserInputBufferCreateFilename:
1.23 daniel 541: * @URI: a C string containing the URI or filename
1.1 daniel 542: * @enc: the charset encoding if known
543: *
544: * Create a buffered parser input for the progressive parsing of a file
545: * If filename is "-' then we use stdin as the input.
546: * Automatic support for ZLIB/Compress compressed document is provided
547: * by default if found at compile-time.
1.20 daniel 548: * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1.1 daniel 549: *
550: * Returns the new parser input or NULL
551: */
552: xmlParserInputBufferPtr
1.23 daniel 553: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1.1 daniel 554: xmlParserInputBufferPtr ret;
1.23 daniel 555: int i;
556: void *context = NULL;
557:
558: if (xmlInputCallbackInitialized == 0)
559: xmlRegisterDefaultInputCallbacks();
1.1 daniel 560:
1.23 daniel 561: if (URI == NULL) return(NULL);
1.1 daniel 562:
1.23 daniel 563: /*
564: * Try to find one of the input accept method accepting taht scheme
565: * Go in reverse to give precedence to user defined handlers.
566: */
567: for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
568: if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
569: (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
570: context = xmlInputCallbackTable[i].opencallback(URI);
571: if (context != NULL)
572: break;
1.1 daniel 573: }
1.23 daniel 574: }
575: if (context == NULL) {
576: #ifdef DEBUG_INPUT
577: fprintf(stderr, "No input filter matching \"%s\"\n", URI);
1.1 daniel 578: #endif
1.23 daniel 579: return(NULL);
1.1 daniel 580: }
1.20 daniel 581:
582: /*
583: * Allocate the Input buffer front-end.
1.1 daniel 584: */
585: ret = xmlAllocParserInputBuffer(enc);
586: if (ret != NULL) {
1.23 daniel 587: ret->context = context;
588: ret->readcallback = xmlInputCallbackTable[i].readcallback;
589: ret->closecallback = xmlInputCallbackTable[i].closecallback;
1.1 daniel 590: }
591: return(ret);
592: }
593:
594: /**
595: * xmlParserInputBufferCreateFile:
596: * @file: a FILE*
597: * @enc: the charset encoding if known
598: *
599: * Create a buffered parser input for the progressive parsing of a FILE *
600: * buffered C I/O
601: *
602: * Returns the new parser input or NULL
603: */
604: xmlParserInputBufferPtr
605: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
606: xmlParserInputBufferPtr ret;
607:
1.23 daniel 608: if (xmlInputCallbackInitialized == 0)
609: xmlRegisterDefaultInputCallbacks();
610:
1.1 daniel 611: if (file == NULL) return(NULL);
612:
613: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 614: if (ret != NULL) {
615: ret->context = file;
616: ret->readcallback = xmlFileRead;
617: ret->closecallback = xmlFileClose;
618: }
1.1 daniel 619:
620: return(ret);
621: }
622:
623: /**
624: * xmlParserInputBufferCreateFd:
625: * @fd: a file descriptor number
626: * @enc: the charset encoding if known
627: *
628: * Create a buffered parser input for the progressive parsing for the input
629: * from a file descriptor
630: *
631: * Returns the new parser input or NULL
632: */
633: xmlParserInputBufferPtr
634: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
635: xmlParserInputBufferPtr ret;
636:
637: if (fd < 0) return(NULL);
638:
639: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 640: if (ret != NULL) {
641: ret->context = (void *) fd;
642: ret->readcallback = xmlFdRead;
643: ret->closecallback = xmlFdClose;
644: }
1.1 daniel 645:
646: return(ret);
647: }
648:
649: /**
1.24 daniel 650: * xmlParserInputBufferCreateIO:
651: * @ioread: an I/O read function
652: * @ioclose: an I/O close function
653: * @ioctx: an I/O handler
654: * @enc: the charset encoding if known
655: *
656: * Create a buffered parser input for the progressive parsing for the input
657: * from a file descriptor
658: *
659: * Returns the new parser input or NULL
660: */
661: xmlParserInputBufferPtr
662: xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
663: xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
664: xmlParserInputBufferPtr ret;
665:
666: if (ioread == NULL) return(NULL);
667:
668: ret = xmlAllocParserInputBuffer(enc);
669: if (ret != NULL) {
670: ret->context = (void *) ioctx;
671: ret->readcallback = ioread;
672: ret->closecallback = ioclose;
673: }
674:
675: return(ret);
676: }
677:
678: /**
1.14 daniel 679: * xmlParserInputBufferPush:
680: * @in: a buffered parser input
681: * @buf: an char array
682: * @len: the size in bytes of the array.
683: *
684: * Push the content of the arry in the input buffer
685: * This routine handle the I18N transcoding to internal UTF-8
686: * This is used when operating the parser in progressive (push) mode.
687: *
688: * Returns the number of chars read and stored in the buffer, or -1
689: * in case of error.
690: */
691: int
1.15 daniel 692: xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
1.14 daniel 693: int nbchars = 0;
694:
695: if (len < 0) return(0);
696: if (in->encoder != NULL) {
1.26 ! daniel 697: /*
! 698: * Store the data in the incoming raw buffer
! 699: */
! 700: if (in->raw == NULL) {
! 701: in->raw = xmlBufferCreate();
! 702: }
! 703: xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
1.14 daniel 704:
705: /*
1.26 ! daniel 706: * convert as much as possible to the parser reading buffer.
1.14 daniel 707: */
1.26 ! daniel 708: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1.20 daniel 709: if (nbchars < 0) {
710: fprintf(stderr, "xmlParserInputBufferPush: encoder error\n");
711: return(-1);
712: }
1.14 daniel 713: } else {
714: nbchars = len;
1.17 daniel 715: xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
1.14 daniel 716: }
717: #ifdef DEBUG_INPUT
718: fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
719: nbchars, in->buffer->use, in->buffer->size);
720: #endif
721: return(nbchars);
722: }
723:
724: /**
1.1 daniel 725: * xmlParserInputBufferGrow:
726: * @in: a buffered parser input
727: * @len: indicative value of the amount of chars to read
728: *
729: * Grow up the content of the input buffer, the old data are preserved
730: * This routine handle the I18N transcoding to internal UTF-8
1.14 daniel 731: * This routine is used when operating the parser in normal (pull) mode
1.26 ! daniel 732: *
! 733: * TODO: one should be able to remove one extra copy by copying directy
! 734: * onto in->buffer or in->raw
1.1 daniel 735: *
736: * Returns the number of chars read and stored in the buffer, or -1
737: * in case of error.
738: */
739: int
740: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
741: char *buffer = NULL;
742: int res = 0;
743: int nbchars = 0;
744: int buffree;
745:
746: if ((len <= MINLEN) && (len != 4))
747: len = MINLEN;
748: buffree = in->buffer->size - in->buffer->use;
749: if (buffree <= 0) {
750: fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
751: return(0);
752: }
753: if (len > buffree)
754: len = buffree;
755:
1.8 daniel 756: buffer = xmlMalloc((len + 1) * sizeof(char));
1.1 daniel 757: if (buffer == NULL) {
758: fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
759: return(-1);
760: }
1.23 daniel 761:
762: /*
763: * Call the read method for this I/O type.
764: */
765: if (in->readcallback != NULL) {
766: res = in->readcallback(in->context, &buffer[0], len);
1.1 daniel 767: } else {
768: fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
1.8 daniel 769: xmlFree(buffer);
1.1 daniel 770: return(-1);
771: }
1.23 daniel 772:
1.1 daniel 773: if (res == 0) {
1.8 daniel 774: xmlFree(buffer);
1.1 daniel 775: return(0);
776: }
777: if (res < 0) {
778: perror ("read error");
1.8 daniel 779: xmlFree(buffer);
1.1 daniel 780: return(-1);
781: }
782: if (in->encoder != NULL) {
1.26 ! daniel 783: /*
! 784: * Store the data in the incoming raw buffer
! 785: */
! 786: if (in->raw == NULL) {
! 787: in->raw = xmlBufferCreate();
1.1 daniel 788: }
1.26 ! daniel 789: xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
1.20 daniel 790:
791: /*
1.26 ! daniel 792: * convert as much as possible to the parser reading buffer.
1.20 daniel 793: */
1.26 ! daniel 794: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
! 795: if (nbchars < 0) {
! 796: fprintf(stderr, "xmlParserInputBufferGrow: encoder error\n");
! 797: return(-1);
1.20 daniel 798: }
1.1 daniel 799: } else {
800: nbchars = res;
1.3 veillard 801: buffer[nbchars] = 0;
1.13 daniel 802: xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
1.1 daniel 803: }
804: #ifdef DEBUG_INPUT
805: fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
806: nbchars, in->buffer->use, in->buffer->size);
807: #endif
1.8 daniel 808: xmlFree(buffer);
1.1 daniel 809: return(nbchars);
810: }
811:
812: /**
813: * xmlParserInputBufferRead:
814: * @in: a buffered parser input
815: * @len: indicative value of the amount of chars to read
816: *
817: * Refresh the content of the input buffer, the old data are considered
818: * consumed
819: * This routine handle the I18N transcoding to internal UTF-8
820: *
821: * Returns the number of chars read and stored in the buffer, or -1
822: * in case of error.
823: */
824: int
825: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
826: /* xmlBufferEmpty(in->buffer); */
1.23 daniel 827: if (in->readcallback != NULL)
1.17 daniel 828: return(xmlParserInputBufferGrow(in, len));
829: else
830: return(0);
1.4 daniel 831: }
832:
833: /*
834: * xmlParserGetDirectory:
835: * @filename: the path to a file
836: *
837: * lookup the directory for that file
838: *
839: * Returns a new allocated string containing the directory, or NULL.
840: */
841: char *
842: xmlParserGetDirectory(const char *filename) {
843: char *ret = NULL;
844: char dir[1024];
845: char *cur;
846: char sep = '/';
1.23 daniel 847:
848: if (xmlInputCallbackInitialized == 0)
849: xmlRegisterDefaultInputCallbacks();
1.4 daniel 850:
851: if (filename == NULL) return(NULL);
852: #ifdef WIN32
853: sep = '\\';
854: #endif
855:
856: strncpy(dir, filename, 1023);
857: dir[1023] = 0;
858: cur = &dir[strlen(dir)];
859: while (cur > dir) {
860: if (*cur == sep) break;
861: cur --;
862: }
863: if (*cur == sep) {
864: if (cur == dir) dir[1] = 0;
865: else *cur = 0;
1.8 daniel 866: ret = xmlMemStrdup(dir);
1.4 daniel 867: } else {
868: if (getcwd(dir, 1024) != NULL) {
869: dir[1023] = 0;
1.8 daniel 870: ret = xmlMemStrdup(dir);
1.4 daniel 871: }
872: }
873: return(ret);
1.5 daniel 874: }
875:
876: /****************************************************************
877: * *
878: * External entities loading *
879: * *
880: ****************************************************************/
881:
882: /*
883: * xmlDefaultExternalEntityLoader:
884: * @URL: the URL for the entity to load
885: * @ID: the System ID for the entity to load
1.18 daniel 886: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 887: *
888: * By default we don't load external entitites, yet.
889: *
890: * Returns a new allocated xmlParserInputPtr, or NULL.
891: */
892: static
893: xmlParserInputPtr
894: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
1.18 daniel 895: xmlParserCtxtPtr ctxt) {
896: xmlParserInputPtr ret = NULL;
1.5 daniel 897: #ifdef DEBUG_EXTERNAL_ENTITIES
898: fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
899: #endif
1.18 daniel 900: if (URL == NULL) {
901: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
902: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
903: ID);
904: return(NULL);
905: }
906: ret = xmlNewInputFromFile(ctxt, URL);
907: if (ret == NULL) {
908: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
909: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
910: URL);
911: }
912: return(ret);
1.5 daniel 913: }
914:
915: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
916: xmlDefaultExternalEntityLoader;
917:
918: /*
919: * xmlSetExternalEntityLoader:
920: * @f: the new entity resolver function
921: *
922: * Changes the defaultexternal entity resolver function for the application
923: */
924: void
925: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
926: xmlCurrentExternalEntityLoader = f;
927: }
928:
929: /*
930: * xmlGetExternalEntityLoader:
931: *
932: * Get the default external entity resolver function for the application
933: *
934: * Returns the xmlExternalEntityLoader function pointer
935: */
936: xmlExternalEntityLoader
937: xmlGetExternalEntityLoader(void) {
938: return(xmlCurrentExternalEntityLoader);
939: }
940:
941: /*
942: * xmlLoadExternalEntity:
943: * @URL: the URL for the entity to load
944: * @ID: the System ID for the entity to load
1.18 daniel 945: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 946: *
947: * Load an external entity, note that the use of this function for
948: * unparsed entities may generate problems
1.6 daniel 949: * TODO: a more generic External entitiy API must be designed
1.5 daniel 950: *
951: * Returns the xmlParserInputPtr or NULL
952: */
953: xmlParserInputPtr
954: xmlLoadExternalEntity(const char *URL, const char *ID,
1.18 daniel 955: xmlParserCtxtPtr ctxt) {
956: return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
1.1 daniel 957: }
958:
Webmaster