xmlIO.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:23k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

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