Annotation of XML/xmlIO.c, revision 1.27

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: 
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: 
                     92: /**
1.23      daniel     93:  * xmlFdMatch:
1.22      daniel     94:  * @filename:  the URI for matching
                     95:  *
                     96:  * input from file descriptor
                     97:  *
                     98:  * Returns 1 if matches, 0 otherwise
                     99:  */
1.23      daniel    100: int
                    101: xmlFdMatch (const char *filename) {
                    102:     return(1);
                    103: }
                    104: 
                    105: /**
                    106:  * xmlFdOpen:
                    107:  * @filename:  the URI for matching
                    108:  *
                    109:  * input from file descriptor, supports compressed input
                    110:  * if @filename is " " then the standard input is used
                    111:  *
                    112:  * Returns an I/O context or NULL in case of error
                    113:  */
                    114: void *
                    115: xmlFdOpen (const char *filename) {
                    116:     const char *path = NULL;
                    117:     int fd;
                    118: 
                    119:     if (!strcmp(filename, "-")) {
                    120:        fd = 0;
                    121:        return((void *) fd);
                    122:     }
                    123: 
1.22      daniel    124:     if (!strncmp(filename, "file://localhost", 16))
1.23      daniel    125:        path = &filename[16];
                    126:     else if (!strncmp(filename, "file:///", 8))
                    127:        path = &filename[8];
                    128:     else if (filename[0] == '/')
                    129:        path = filename;
                    130:     if (path == NULL)
                    131:        return(NULL);
                    132: 
                    133: #ifdef WIN32
                    134:     fd = _open (filename, O_RDONLY | _O_BINARY);
                    135: #else
                    136:     fd = open (filename, O_RDONLY);
                    137: #endif
                    138: 
                    139:     return((void *) fd);
                    140: }
                    141: 
                    142: /**
                    143:  * xmlFdRead:
                    144:  * @context:  the I/O context
                    145:  * @buffer:  where to drop data
1.27    ! daniel    146:  * @len:  number of bytes to read
1.23      daniel    147:  *
                    148:  * Read @len bytes to @buffer from the I/O channel.
                    149:  *
                    150:  * Returns the number of bytes written
                    151:  */
                    152: int
                    153: xmlFdRead (void * context, char * buffer, int len) {
                    154:     return(read((int) context, &buffer[0], len));
                    155: }
                    156: 
                    157: /**
1.27    ! daniel    158:  * xmlFdWrite:
        !           159:  * @context:  the I/O context
        !           160:  * @buffer:  where to get data
        !           161:  * @len:  number of bytes to write
        !           162:  *
        !           163:  * Write @len bytes from @buffer to the I/O channel.
        !           164:  *
        !           165:  * Returns the number of bytes written
        !           166:  */
        !           167: int
        !           168: xmlFdWrite (void * context, const char * buffer, int len) {
        !           169:     return(write((int) context, &buffer[0], len));
        !           170: }
        !           171: 
        !           172: /**
1.23      daniel    173:  * xmlFdClose:
                    174:  * @context:  the I/O context
                    175:  *
                    176:  * Close an I/O channel
                    177:  */
                    178: void
                    179: xmlFdClose (void * context) {
                    180:     close((int) context);
1.22      daniel    181: }
1.23      daniel    182: 
1.22      daniel    183: /**
1.23      daniel    184:  * xmlFileMatch:
1.22      daniel    185:  * @filename:  the URI for matching
                    186:  *
1.23      daniel    187:  * input from FILE *
1.22      daniel    188:  *
                    189:  * Returns 1 if matches, 0 otherwise
                    190:  */
1.23      daniel    191: int
                    192: xmlFileMatch (const char *filename) {
                    193:     return(1);
                    194: }
                    195: 
                    196: /**
                    197:  * xmlFileOpen:
                    198:  * @filename:  the URI for matching
                    199:  *
                    200:  * input from FILE *, supports compressed input
                    201:  * if @filename is " " then the standard input is used
                    202:  *
                    203:  * Returns an I/O context or NULL in case of error
                    204:  */
                    205: void *
                    206: xmlFileOpen (const char *filename) {
1.22      daniel    207:     const char *path = NULL;
1.23      daniel    208:     FILE *fd;
                    209: 
                    210:     if (!strcmp(filename, "-")) {
                    211:        fd = stdin;
                    212:        return((void *) fd);
                    213:     }
1.22      daniel    214: 
                    215:     if (!strncmp(filename, "file://localhost", 16))
                    216:        path = &filename[16];
                    217:     else if (!strncmp(filename, "file:///", 8))
1.23      daniel    218:        path = &filename[8];
                    219:     else 
1.22      daniel    220:        path = filename;
                    221:     if (path == NULL)
1.23      daniel    222:        return(NULL);
                    223: 
1.22      daniel    224: #ifdef WIN32
1.23      daniel    225:     fd = fopen(path, "rb");
1.22      daniel    226: #else
1.23      daniel    227:     fd = fopen(path, "r");
                    228: #endif /* WIN32 */
                    229:     return((void *) fd);
                    230: }
                    231: 
                    232: /**
                    233:  * xmlFileRead:
                    234:  * @context:  the I/O context
                    235:  * @buffer:  where to drop data
                    236:  * @len:  number of bytes to write
                    237:  *
                    238:  * Read @len bytes to @buffer from the I/O channel.
                    239:  *
                    240:  * Returns the number of bytes written
                    241:  */
                    242: int
                    243: xmlFileRead (void * context, char * buffer, int len) {
                    244:     return(fread(&buffer[0], 1,  len, (FILE *) context));
                    245: }
                    246: 
                    247: /**
1.27    ! daniel    248:  * xmlFileWrite:
        !           249:  * @context:  the I/O context
        !           250:  * @buffer:  where to drop data
        !           251:  * @len:  number of bytes to write
        !           252:  *
        !           253:  * Write @len bytes from @buffer to the I/O channel.
        !           254:  *
        !           255:  * Returns the number of bytes written
        !           256:  */
        !           257: int
        !           258: xmlFileWrite (void * context, const char * buffer, int len) {
        !           259:     return(fwrite(&buffer[0], 1,  len, (FILE *) context));
        !           260: }
        !           261: 
        !           262: /**
1.23      daniel    263:  * xmlFileClose:
                    264:  * @context:  the I/O context
                    265:  *
                    266:  * Close an I/O channel
                    267:  */
                    268: void
                    269: xmlFileClose (void * context) {
                    270:     fclose((FILE *) context);
                    271: }
                    272: 
                    273: #ifdef HAVE_ZLIB_H
                    274: /************************************************************************
                    275:  *                                                                     *
                    276:  *             I/O for compressed file accesses                        *
                    277:  *                                                                     *
                    278:  ************************************************************************/
                    279: /**
                    280:  * xmlGzfileMatch:
                    281:  * @filename:  the URI for matching
                    282:  *
                    283:  * input from compressed file test
                    284:  *
                    285:  * Returns 1 if matches, 0 otherwise
                    286:  */
                    287: int
                    288: xmlGzfileMatch (const char *filename) {
                    289:     return(1);
                    290: }
                    291: 
                    292: /**
                    293:  * xmlGzfileOpen:
                    294:  * @filename:  the URI for matching
                    295:  *
                    296:  * input from compressed file open
                    297:  * if @filename is " " then the standard input is used
                    298:  *
                    299:  * Returns an I/O context or NULL in case of error
                    300:  */
                    301: void *
                    302: xmlGzfileOpen (const char *filename) {
                    303:     const char *path = NULL;
                    304:     gzFile fd;
                    305: 
                    306:     if (!strcmp(filename, "-")) {
                    307:         fd = gzdopen (fileno(stdin), "r");
                    308:        return((void *) fd);
                    309:     }
                    310: 
                    311:     if (!strncmp(filename, "file://localhost", 16))
                    312:        path = &filename[16];
                    313:     else if (!strncmp(filename, "file:///", 8))
                    314:        path = &filename[8];
                    315:     else 
                    316:        path = filename;
                    317: 
                    318:     fd = gzopen(filename, "r");
                    319:     return((void *) fd);
                    320: }
                    321: 
                    322: /**
                    323:  * xmlGzfileRead:
                    324:  * @context:  the I/O context
                    325:  * @buffer:  where to drop data
                    326:  * @len:  number of bytes to write
                    327:  *
                    328:  * Read @len bytes to @buffer from the compressed I/O channel.
                    329:  *
                    330:  * Returns the number of bytes written
                    331:  */
                    332: int
                    333: xmlGzfileRead (void * context, char * buffer, int len) {
                    334:     return(gzread((gzFile) context, &buffer[0], len));
                    335: }
                    336: 
                    337: /**
                    338:  * xmlGzfileClose:
                    339:  * @context:  the I/O context
                    340:  *
                    341:  * Close a compressed I/O channel
                    342:  */
                    343: void
                    344: xmlGzfileClose (void * context) {
                    345:     gzclose((gzFile) context);
                    346: }
                    347: #endif /* HAVE_ZLIB_H */
                    348: 
                    349: #ifdef LIBXML_HTTP_ENABLED
                    350: /************************************************************************
                    351:  *                                                                     *
                    352:  *                     I/O for HTTP file accesses                      *
                    353:  *                                                                     *
                    354:  ************************************************************************/
                    355: /**
                    356:  * xmlIOHTTPMatch:
                    357:  * @filename:  the URI for matching
                    358:  *
                    359:  * check if the URI matches an HTTP one
                    360:  *
                    361:  * Returns 1 if matches, 0 otherwise
                    362:  */
                    363: int
                    364: xmlIOHTTPMatch (const char *filename) {
                    365:     if (!strncmp(filename, "http://", 7))
                    366:        return(1);
                    367:     return(0);
                    368: }
                    369: 
                    370: /**
                    371:  * xmlIOHTTPOpen:
                    372:  * @filename:  the URI for matching
                    373:  *
                    374:  * open an HTTP I/O channel
                    375:  *
                    376:  * Returns an I/O context or NULL in case of error
                    377:  */
                    378: void *
                    379: xmlIOHTTPOpen (const char *filename) {
                    380:     return(xmlNanoHTTPOpen(filename, NULL));
                    381: }
                    382: 
                    383: /**
                    384:  * xmlIOHTTPRead:
                    385:  * @context:  the I/O context
                    386:  * @buffer:  where to drop data
                    387:  * @len:  number of bytes to write
                    388:  *
                    389:  * Read @len bytes to @buffer from the I/O channel.
                    390:  *
                    391:  * Returns the number of bytes written
                    392:  */
                    393: int 
                    394: xmlIOHTTPRead(void * context, char * buffer, int len) {
                    395:     return(xmlNanoHTTPRead(context, &buffer[0], len));
1.22      daniel    396: }
                    397: 
1.23      daniel    398: /**
                    399:  * xmlIOHTTPClose:
                    400:  * @context:  the I/O context
                    401:  *
                    402:  * Close an HTTP I/O channel
                    403:  */
                    404: void
                    405: xmlIOHTTPClose (void * context) {
                    406:     xmlNanoHTTPClose(context);
1.22      daniel    407: }
1.23      daniel    408: #endif /* LIBXML_HTTP_ENABLED */
                    409: 
                    410: #ifdef LIBXML_FTP_ENABLED
                    411: /************************************************************************
                    412:  *                                                                     *
                    413:  *                     I/O for FTP file accesses                       *
                    414:  *                                                                     *
                    415:  ************************************************************************/
                    416: /**
                    417:  * xmlIOFTPMatch:
                    418:  * @filename:  the URI for matching
                    419:  *
                    420:  * check if the URI matches an FTP one
                    421:  *
                    422:  * Returns 1 if matches, 0 otherwise
                    423:  */
                    424: int
                    425: xmlIOFTPMatch (const char *filename) {
                    426:     if (!strncmp(filename, "ftp://", 6))
                    427:        return(1);
                    428:     return(0);
1.22      daniel    429: }
                    430: 
1.23      daniel    431: /**
                    432:  * xmlIOFTPOpen:
                    433:  * @filename:  the URI for matching
                    434:  *
                    435:  * open an FTP I/O channel
                    436:  *
                    437:  * Returns an I/O context or NULL in case of error
                    438:  */
                    439: void *
                    440: xmlIOFTPOpen (const char *filename) {
                    441:     return(xmlNanoFTPOpen(filename));
1.22      daniel    442: }
1.23      daniel    443: 
                    444: /**
                    445:  * xmlIOFTPRead:
                    446:  * @context:  the I/O context
                    447:  * @buffer:  where to drop data
                    448:  * @len:  number of bytes to write
                    449:  *
                    450:  * Read @len bytes to @buffer from the I/O channel.
                    451:  *
                    452:  * Returns the number of bytes written
                    453:  */
                    454: int 
                    455: xmlIOFTPRead(void * context, char * buffer, int len) {
                    456:     return(xmlNanoFTPRead(context, &buffer[0], len));
1.22      daniel    457: }
1.23      daniel    458: 
                    459: /**
                    460:  * xmlIOFTPClose:
                    461:  * @context:  the I/O context
                    462:  *
                    463:  * Close an FTP I/O channel
                    464:  */
                    465: void
                    466: xmlIOFTPClose (void * context) {
                    467:     xmlNanoFTPClose(context);
1.22      daniel    468: }
1.23      daniel    469: #endif /* LIBXML_FTP_ENABLED */
                    470: 
                    471: 
                    472: /**
                    473:  * xmlRegisterInputCallbacks:
                    474:  * @match:  the xmlInputMatchCallback
                    475:  * @open:  the xmlInputOpenCallback
                    476:  * @read:  the xmlInputReadCallback
                    477:  * @close:  the xmlInputCloseCallback
                    478:  *
                    479:  * Register a new set of I/O callback for handling parser input.
                    480:  *
                    481:  * Returns the registered handler number or -1 in case of error
                    482:  */
                    483: int
                    484: xmlRegisterInputCallbacks(xmlInputMatchCallback match,
                    485:        xmlInputOpenCallback open, xmlInputReadCallback read,
                    486:        xmlInputCloseCallback close) {
                    487:     if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
                    488:        return(-1);
                    489:     }
                    490:     xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = match;
                    491:     xmlInputCallbackTable[xmlInputCallbackNr].opencallback = open;
                    492:     xmlInputCallbackTable[xmlInputCallbackNr].readcallback = read;
                    493:     xmlInputCallbackTable[xmlInputCallbackNr].closecallback = close;
                    494:     return(xmlInputCallbackNr++);
1.22      daniel    495: }
                    496: 
1.23      daniel    497: /**
1.27    ! daniel    498:  * xmlRegisterOutputCallbacks:
        !           499:  * @match:  the xmlOutputMatchCallback
        !           500:  * @open:  the xmlOutputOpenCallback
        !           501:  * @write:  the xmlOutputWriteCallback
        !           502:  * @close:  the xmlOutputCloseCallback
        !           503:  *
        !           504:  * Register a new set of I/O callback for handling output.
        !           505:  *
        !           506:  * Returns the registered handler number or -1 in case of error
        !           507:  */
        !           508: int
        !           509: xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
        !           510:        xmlOutputOpenCallback open, xmlOutputWriteCallback write,
        !           511:        xmlOutputCloseCallback close) {
        !           512:     if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
        !           513:        return(-1);
        !           514:     }
        !           515:     xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
        !           516:     xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
        !           517:     xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
        !           518:     xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
        !           519:     return(xmlOutputCallbackNr++);
        !           520: }
        !           521: 
        !           522: /**
1.23      daniel    523:  * xmlRegisterDefaultInputCallbacks:
                    524:  *
                    525:  * Registers the default compiled-in I/O handlers.
                    526:  */
                    527: void
                    528: xmlRegisterDefaultInputCallbacks(void) {
                    529:     xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
                    530:                              xmlFileRead, xmlFileClose);
                    531: #ifdef HAVE_ZLIB_H
                    532:     xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
                    533:                              xmlGzfileRead, xmlGzfileClose);
                    534: #endif /* HAVE_ZLIB_H */
                    535: 
                    536: #ifdef LIBXML_HTTP_ENABLED
                    537:     xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
                    538:                              xmlIOHTTPRead, xmlIOHTTPClose);
                    539: #endif /* LIBXML_HTTP_ENABLED */
                    540: 
                    541: #ifdef LIBXML_FTP_ENABLED
                    542:     xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
                    543:                              xmlIOFTPRead, xmlIOFTPClose);
                    544: #endif /* LIBXML_FTP_ENABLED */
                    545: }
1.22      daniel    546: 
1.1       daniel    547: /**
1.27    ! daniel    548:  * xmlRegisterDefaultOutputCallbacks:
        !           549:  *
        !           550:  * Registers the default compiled-in I/O handlers.
        !           551:  */
        !           552: void
        !           553: xmlRegisterDefaultOutputCallbacks(void) {
        !           554:     xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpen,
        !           555:                              xmlFileWrite, xmlFileClose);
        !           556: /*********************************
        !           557:  No way a-priori to distinguish between gzipped files from
        !           558:  uncompressed ones except opening if existing then closing
        !           559:  and saving with same compression ratio ... a pain.
        !           560: 
        !           561: #ifdef HAVE_ZLIB_H
        !           562:     xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
        !           563:                               xmlGzfileWrite, xmlGzfileClose);
        !           564: #endif
        !           565:  No HTTP PUT support yet, patches welcome
        !           566: 
        !           567: #ifdef LIBXML_HTTP_ENABLED
        !           568:     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
        !           569:                               xmlIOHTTPWrite, xmlIOHTTPClose);
        !           570: #endif
        !           571: 
        !           572:  Nor FTP PUT ....
        !           573: #ifdef LIBXML_FTP_ENABLED
        !           574:     xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
        !           575:                               xmlIOFTPWrite, xmlIOFTPClose);
        !           576: #endif
        !           577:  **********************************/
        !           578: }
        !           579: 
        !           580: /**
1.1       daniel    581:  * xmlAllocParserInputBuffer:
                    582:  * @enc:  the charset encoding if known
                    583:  *
                    584:  * Create a buffered parser input for progressive parsing
                    585:  *
                    586:  * Returns the new parser input or NULL
                    587:  */
                    588: xmlParserInputBufferPtr
                    589: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
                    590:     xmlParserInputBufferPtr ret;
                    591: 
1.8       daniel    592:     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1.1       daniel    593:     if (ret == NULL) {
                    594:         fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
                    595:        return(NULL);
                    596:     }
1.3       veillard  597:     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
1.1       daniel    598:     ret->buffer = xmlBufferCreate();
1.17      daniel    599:     if (ret->buffer == NULL) {
                    600:         xmlFree(ret);
                    601:        return(NULL);
                    602:     }
                    603:     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
1.1       daniel    604:     ret->encoder = xmlGetCharEncodingHandler(enc);
1.26      daniel    605:     if (ret->encoder != NULL)
                    606:         ret->raw = xmlBufferCreate();
                    607:     else
                    608:         ret->raw = NULL;
1.23      daniel    609:     ret->readcallback = NULL;
                    610:     ret->closecallback = NULL;
                    611:     ret->context = NULL;
1.1       daniel    612: 
                    613:     return(ret);
                    614: }
                    615: 
                    616: /**
1.27    ! daniel    617:  * xmlAllocOutputBuffer:
        !           618:  * @encoder:  the encoding converter or NULL
        !           619:  *
        !           620:  * Create a buffered parser output
        !           621:  *
        !           622:  * Returns the new parser output or NULL
        !           623:  */
        !           624: xmlOutputBufferPtr
        !           625: xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
        !           626:     xmlOutputBufferPtr ret;
        !           627: 
        !           628:     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
        !           629:     if (ret == NULL) {
        !           630:         fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
        !           631:        return(NULL);
        !           632:     }
        !           633:     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
        !           634:     ret->buffer = xmlBufferCreate();
        !           635:     if (ret->buffer == NULL) {
        !           636:         xmlFree(ret);
        !           637:        return(NULL);
        !           638:     }
        !           639:     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
        !           640:     ret->encoder = encoder;
        !           641:     if (encoder != NULL)
        !           642:         ret->raw = xmlBufferCreate();
        !           643:     else
        !           644:         ret->raw = NULL;
        !           645:     ret->writecallback = NULL;
        !           646:     ret->closecallback = NULL;
        !           647:     ret->context = NULL;
        !           648: 
        !           649:     return(ret);
        !           650: }
        !           651: 
        !           652: /**
1.1       daniel    653:  * xmlFreeParserInputBuffer:
                    654:  * @in:  a buffered parser input
                    655:  *
                    656:  * Free up the memory used by a buffered parser input
                    657:  */
                    658: void
                    659: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1.26      daniel    660:     if (in->raw) {
                    661:         xmlBufferFree(in->raw);
                    662:        in->raw = NULL;
                    663:     }
1.25      daniel    664:     if (in->encoder != NULL) {
                    665:         xmlCharEncCloseFunc(in->encoder);
                    666:     }
                    667:     if (in->closecallback != NULL) {
                    668:        in->closecallback(in->context);
                    669:     }
1.1       daniel    670:     if (in->buffer != NULL) {
                    671:         xmlBufferFree(in->buffer);
                    672:        in->buffer = NULL;
                    673:     }
1.23      daniel    674: 
1.3       veillard  675:     memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
1.8       daniel    676:     xmlFree(in);
1.1       daniel    677: }
                    678: 
                    679: /**
                    680:  * xmlParserInputBufferCreateFilename:
1.23      daniel    681:  * @URI:  a C string containing the URI or filename
1.1       daniel    682:  * @enc:  the charset encoding if known
                    683:  *
                    684:  * Create a buffered parser input for the progressive parsing of a file
                    685:  * If filename is "-' then we use stdin as the input.
                    686:  * Automatic support for ZLIB/Compress compressed document is provided
                    687:  * by default if found at compile-time.
1.20      daniel    688:  * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1.1       daniel    689:  *
                    690:  * Returns the new parser input or NULL
                    691:  */
                    692: xmlParserInputBufferPtr
1.23      daniel    693: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1.1       daniel    694:     xmlParserInputBufferPtr ret;
1.23      daniel    695:     int i;
                    696:     void *context = NULL;
                    697: 
                    698:     if (xmlInputCallbackInitialized == 0)
                    699:        xmlRegisterDefaultInputCallbacks();
1.1       daniel    700: 
1.23      daniel    701:     if (URI == NULL) return(NULL);
1.1       daniel    702: 
1.23      daniel    703:     /*
                    704:      * Try to find one of the input accept method accepting taht scheme
                    705:      * Go in reverse to give precedence to user defined handlers.
                    706:      */
                    707:     for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
                    708:        if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
                    709:            (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
                    710:            context = xmlInputCallbackTable[i].opencallback(URI);
                    711:            if (context != NULL)
                    712:                break;
1.1       daniel    713:        }
1.23      daniel    714:     }
                    715:     if (context == NULL) {
                    716: #ifdef DEBUG_INPUT
                    717:        fprintf(stderr, "No input filter matching \"%s\"\n", URI);
1.1       daniel    718: #endif
1.23      daniel    719:        return(NULL);
1.1       daniel    720:     }
1.20      daniel    721: 
                    722:     /*
                    723:      * Allocate the Input buffer front-end.
1.1       daniel    724:      */
                    725:     ret = xmlAllocParserInputBuffer(enc);
                    726:     if (ret != NULL) {
1.23      daniel    727:        ret->context = context;
                    728:        ret->readcallback = xmlInputCallbackTable[i].readcallback;
                    729:        ret->closecallback = xmlInputCallbackTable[i].closecallback;
1.1       daniel    730:     }
                    731:     return(ret);
                    732: }
                    733: 
                    734: /**
1.27    ! daniel    735:  * xmlOutputBufferCreateFilename:
        !           736:  * @URI:  a C string containing the URI or filename
        !           737:  * @encoder:  the encoding converter or NULL
        !           738:  *
        !           739:  * Create a buffered  output for the progressive saving of a file
        !           740:  * If filename is "-' then we use stdout as the output.
        !           741:  * Automatic support for ZLIB/Compress compressed document is provided
        !           742:  * by default if found at compile-time.
        !           743:  *
        !           744:  * Returns the new output or NULL
        !           745:  */
        !           746: xmlOutputBufferPtr
        !           747: xmlOutputBufferCreateFilename(const char *URI,
        !           748:                               xmlCharEncodingHandlerPtr encoder) {
        !           749:     xmlOutputBufferPtr ret;
        !           750:     int i;
        !           751:     void *context = NULL;
        !           752: 
        !           753:     if (xmlOutputCallbackInitialized == 0)
        !           754:        xmlRegisterDefaultOutputCallbacks();
        !           755: 
        !           756:     if (URI == NULL) return(NULL);
        !           757: 
        !           758:     /*
        !           759:      * Try to find one of the output accept method accepting taht scheme
        !           760:      * Go in reverse to give precedence to user defined handlers.
        !           761:      */
        !           762:     for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
        !           763:        if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
        !           764:            (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
        !           765:            context = xmlOutputCallbackTable[i].opencallback(URI);
        !           766:            if (context != NULL)
        !           767:                break;
        !           768:        }
        !           769:     }
        !           770:     if (context == NULL) {
        !           771: #ifdef DEBUG_INPUT
        !           772:        fprintf(stderr, "No output filter matching \"%s\"\n", URI);
        !           773: #endif
        !           774:        return(NULL);
        !           775:     }
        !           776: 
        !           777:     /*
        !           778:      * Allocate the Output buffer front-end.
        !           779:      */
        !           780:     ret = xmlAllocOutputBuffer(encoder);
        !           781:     if (ret != NULL) {
        !           782:        ret->context = context;
        !           783:        ret->writecallback = xmlOutputCallbackTable[i].writecallback;
        !           784:        ret->closecallback = xmlOutputCallbackTable[i].closecallback;
        !           785:     }
        !           786:     return(ret);
        !           787: }
        !           788: 
        !           789: /**
1.1       daniel    790:  * xmlParserInputBufferCreateFile:
                    791:  * @file:  a FILE* 
                    792:  * @enc:  the charset encoding if known
                    793:  *
                    794:  * Create a buffered parser input for the progressive parsing of a FILE *
                    795:  * buffered C I/O
                    796:  *
                    797:  * Returns the new parser input or NULL
                    798:  */
                    799: xmlParserInputBufferPtr
                    800: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
                    801:     xmlParserInputBufferPtr ret;
                    802: 
1.23      daniel    803:     if (xmlInputCallbackInitialized == 0)
                    804:        xmlRegisterDefaultInputCallbacks();
                    805: 
1.1       daniel    806:     if (file == NULL) return(NULL);
                    807: 
                    808:     ret = xmlAllocParserInputBuffer(enc);
1.23      daniel    809:     if (ret != NULL) {
                    810:         ret->context = file;
                    811:        ret->readcallback = xmlFileRead;
                    812:        ret->closecallback = xmlFileClose;
                    813:     }
1.1       daniel    814: 
                    815:     return(ret);
                    816: }
                    817: 
                    818: /**
1.27    ! daniel    819:  * xmlOutputBufferCreateFile:
        !           820:  * @file:  a FILE* 
        !           821:  * @encoder:  the encoding converter or NULL
        !           822:  *
        !           823:  * Create a buffered output for the progressive saving to a FILE *
        !           824:  * buffered C I/O
        !           825:  *
        !           826:  * Returns the new parser output or NULL
        !           827:  */
        !           828: xmlOutputBufferPtr
        !           829: xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
        !           830:     xmlOutputBufferPtr ret;
        !           831: 
        !           832:     if (xmlOutputCallbackInitialized == 0)
        !           833:        xmlRegisterDefaultOutputCallbacks();
        !           834: 
        !           835:     if (file == NULL) return(NULL);
        !           836: 
        !           837:     ret = xmlAllocOutputBuffer(encoder);
        !           838:     if (ret != NULL) {
        !           839:         ret->context = file;
        !           840:        ret->writecallback = xmlFileWrite;
        !           841:        ret->closecallback = xmlFileClose;
        !           842:     }
        !           843: 
        !           844:     return(ret);
        !           845: }
        !           846: 
        !           847: /**
1.1       daniel    848:  * xmlParserInputBufferCreateFd:
                    849:  * @fd:  a file descriptor number
                    850:  * @enc:  the charset encoding if known
                    851:  *
                    852:  * Create a buffered parser input for the progressive parsing for the input
                    853:  * from a file descriptor
                    854:  *
                    855:  * Returns the new parser input or NULL
                    856:  */
                    857: xmlParserInputBufferPtr
                    858: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
                    859:     xmlParserInputBufferPtr ret;
                    860: 
                    861:     if (fd < 0) return(NULL);
                    862: 
                    863:     ret = xmlAllocParserInputBuffer(enc);
1.23      daniel    864:     if (ret != NULL) {
                    865:         ret->context = (void *) fd;
                    866:        ret->readcallback = xmlFdRead;
                    867:        ret->closecallback = xmlFdClose;
                    868:     }
1.1       daniel    869: 
                    870:     return(ret);
                    871: }
                    872: 
                    873: /**
1.27    ! daniel    874:  * xmlOutputBufferCreateFd:
        !           875:  * @fd:  a file descriptor number
        !           876:  * @encoder:  the encoding converter or NULL
        !           877:  *
        !           878:  * Create a buffered output for the progressive saving 
        !           879:  * to a file descriptor
        !           880:  *
        !           881:  * Returns the new parser output or NULL
        !           882:  */
        !           883: xmlOutputBufferPtr
        !           884: xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
        !           885:     xmlOutputBufferPtr ret;
        !           886: 
        !           887:     if (fd < 0) return(NULL);
        !           888: 
        !           889:     ret = xmlAllocOutputBuffer(encoder);
        !           890:     if (ret != NULL) {
        !           891:         ret->context = (void *) fd;
        !           892:        ret->writecallback = xmlFdWrite;
        !           893:        ret->closecallback = xmlFdClose;
        !           894:     }
        !           895: 
        !           896:     return(ret);
        !           897: }
        !           898: 
        !           899: /**
1.24      daniel    900:  * xmlParserInputBufferCreateIO:
                    901:  * @ioread:  an I/O read function
                    902:  * @ioclose:  an I/O close function
                    903:  * @ioctx:  an I/O handler
                    904:  * @enc:  the charset encoding if known
                    905:  *
                    906:  * Create a buffered parser input for the progressive parsing for the input
1.27    ! daniel    907:  * from an I/O handler
1.24      daniel    908:  *
                    909:  * Returns the new parser input or NULL
                    910:  */
                    911: xmlParserInputBufferPtr
                    912: xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
                    913:         xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
                    914:     xmlParserInputBufferPtr ret;
                    915: 
                    916:     if (ioread == NULL) return(NULL);
                    917: 
                    918:     ret = xmlAllocParserInputBuffer(enc);
                    919:     if (ret != NULL) {
                    920:         ret->context = (void *) ioctx;
                    921:        ret->readcallback = ioread;
                    922:        ret->closecallback = ioclose;
                    923:     }
                    924: 
                    925:     return(ret);
                    926: }
                    927: 
                    928: /**
1.27    ! daniel    929:  * xmlOutputBufferCreateIO:
        !           930:  * @iowrite:  an I/O write function
        !           931:  * @ioclose:  an I/O close function
        !           932:  * @ioctx:  an I/O handler
        !           933:  * @enc:  the charset encoding if known
        !           934:  *
        !           935:  * Create a buffered output for the progressive saving
        !           936:  * to an I/O handler
        !           937:  *
        !           938:  * Returns the new parser output or NULL
        !           939:  */
        !           940: xmlOutputBufferPtr
        !           941: xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
        !           942:         xmlOutputCloseCallback  ioclose, void *ioctx,
        !           943:         xmlCharEncodingHandlerPtr encoder) {
        !           944:     xmlOutputBufferPtr ret;
        !           945: 
        !           946:     if (iowrite == NULL) return(NULL);
        !           947: 
        !           948:     ret = xmlAllocOutputBuffer(encoder);
        !           949:     if (ret != NULL) {
        !           950:         ret->context = (void *) ioctx;
        !           951:        ret->writecallback = iowrite;
        !           952:        ret->closecallback = ioclose;
        !           953:     }
        !           954: 
        !           955:     return(ret);
        !           956: }
        !           957: 
        !           958: /**
1.14      daniel    959:  * xmlParserInputBufferPush:
                    960:  * @in:  a buffered parser input
1.27    ! daniel    961:  * @len:  the size in bytes of the array.
1.14      daniel    962:  * @buf:  an char array
                    963:  *
                    964:  * Push the content of the arry in the input buffer
                    965:  * This routine handle the I18N transcoding to internal UTF-8
                    966:  * This is used when operating the parser in progressive (push) mode.
                    967:  *
                    968:  * Returns the number of chars read and stored in the buffer, or -1
                    969:  *         in case of error.
                    970:  */
                    971: int
1.15      daniel    972: xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
1.14      daniel    973:     int nbchars = 0;
                    974: 
                    975:     if (len < 0) return(0);
                    976:     if (in->encoder != NULL) {
1.26      daniel    977:         /*
                    978:         * Store the data in the incoming raw buffer
                    979:         */
                    980:         if (in->raw == NULL) {
                    981:            in->raw = xmlBufferCreate();
                    982:        }
                    983:        xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
1.14      daniel    984: 
                    985:        /*
1.26      daniel    986:         * convert as much as possible to the parser reading buffer.
1.14      daniel    987:         */
1.26      daniel    988:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1.20      daniel    989:        if (nbchars < 0) {
                    990:            fprintf(stderr, "xmlParserInputBufferPush: encoder error\n");
                    991:            return(-1);
                    992:        }
1.14      daniel    993:     } else {
                    994:        nbchars = len;
1.17      daniel    995:         xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
1.14      daniel    996:     }
                    997: #ifdef DEBUG_INPUT
                    998:     fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
                    999:             nbchars, in->buffer->use, in->buffer->size);
                   1000: #endif
                   1001:     return(nbchars);
                   1002: }
                   1003: 
                   1004: /**
1.1       daniel   1005:  * xmlParserInputBufferGrow:
                   1006:  * @in:  a buffered parser input
                   1007:  * @len:  indicative value of the amount of chars to read
                   1008:  *
                   1009:  * Grow up the content of the input buffer, the old data are preserved
                   1010:  * This routine handle the I18N transcoding to internal UTF-8
1.14      daniel   1011:  * This routine is used when operating the parser in normal (pull) mode
1.26      daniel   1012:  *
                   1013:  * TODO: one should be able to remove one extra copy by copying directy
                   1014:  *       onto in->buffer or in->raw
1.1       daniel   1015:  *
                   1016:  * Returns the number of chars read and stored in the buffer, or -1
                   1017:  *         in case of error.
                   1018:  */
                   1019: int
                   1020: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
                   1021:     char *buffer = NULL;
                   1022:     int res = 0;
                   1023:     int nbchars = 0;
                   1024:     int buffree;
                   1025: 
                   1026:     if ((len <= MINLEN) && (len != 4)) 
                   1027:         len = MINLEN;
                   1028:     buffree = in->buffer->size - in->buffer->use;
                   1029:     if (buffree <= 0) {
                   1030:         fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
                   1031:        return(0);
                   1032:     }
                   1033:     if (len > buffree) 
                   1034:         len = buffree;
                   1035: 
1.8       daniel   1036:     buffer = xmlMalloc((len + 1) * sizeof(char));
1.1       daniel   1037:     if (buffer == NULL) {
                   1038:         fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
                   1039:        return(-1);
                   1040:     }
1.23      daniel   1041: 
                   1042:     /*
                   1043:      * Call the read method for this I/O type.
                   1044:      */
                   1045:     if (in->readcallback != NULL) {
                   1046:        res = in->readcallback(in->context, &buffer[0], len);
1.1       daniel   1047:     } else {
                   1048:         fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
1.8       daniel   1049:        xmlFree(buffer);
1.1       daniel   1050:        return(-1);
                   1051:     }
1.23      daniel   1052: 
1.1       daniel   1053:     if (res == 0) {
1.8       daniel   1054:        xmlFree(buffer);
1.1       daniel   1055:         return(0);
                   1056:     }
                   1057:     if (res < 0) {
                   1058:        perror ("read error");
1.8       daniel   1059:        xmlFree(buffer);
1.1       daniel   1060:        return(-1);
                   1061:     }
                   1062:     if (in->encoder != NULL) {
1.26      daniel   1063:         /*
                   1064:         * Store the data in the incoming raw buffer
                   1065:         */
                   1066:         if (in->raw == NULL) {
                   1067:            in->raw = xmlBufferCreate();
1.1       daniel   1068:        }
1.26      daniel   1069:        xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
1.20      daniel   1070: 
                   1071:        /*
1.26      daniel   1072:         * convert as much as possible to the parser reading buffer.
1.20      daniel   1073:         */
1.26      daniel   1074:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
                   1075:        if (nbchars < 0) {
                   1076:            fprintf(stderr, "xmlParserInputBufferGrow: encoder error\n");
                   1077:            return(-1);
1.20      daniel   1078:        }
1.1       daniel   1079:     } else {
                   1080:        nbchars = res;
1.3       veillard 1081:         buffer[nbchars] = 0;
1.13      daniel   1082:         xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
1.1       daniel   1083:     }
                   1084: #ifdef DEBUG_INPUT
                   1085:     fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
                   1086:             nbchars, in->buffer->use, in->buffer->size);
                   1087: #endif
1.8       daniel   1088:     xmlFree(buffer);
1.1       daniel   1089:     return(nbchars);
                   1090: }
                   1091: 
                   1092: /**
                   1093:  * xmlParserInputBufferRead:
                   1094:  * @in:  a buffered parser input
                   1095:  * @len:  indicative value of the amount of chars to read
                   1096:  *
                   1097:  * Refresh the content of the input buffer, the old data are considered
                   1098:  * consumed
                   1099:  * This routine handle the I18N transcoding to internal UTF-8
                   1100:  *
                   1101:  * Returns the number of chars read and stored in the buffer, or -1
                   1102:  *         in case of error.
                   1103:  */
                   1104: int
                   1105: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
                   1106:     /* xmlBufferEmpty(in->buffer); */
1.23      daniel   1107:     if (in->readcallback != NULL)
1.17      daniel   1108:        return(xmlParserInputBufferGrow(in, len));
                   1109:     else
1.27    ! daniel   1110:         return(-1);
        !          1111: }
        !          1112: 
        !          1113: /**
        !          1114:  * xmlOutputBufferWrite:
        !          1115:  * @out:  a buffered parser output
        !          1116:  * @len:  the size in bytes of the array.
        !          1117:  * @buf:  an char array
        !          1118:  *
        !          1119:  * Write the content of the array in the output I/O buffer
        !          1120:  * This routine handle the I18N transcoding from internal UTF-8
        !          1121:  * The buffer is lossless, i.e. will store in case of partial
        !          1122:  * or delayed writes.
        !          1123:  *
        !          1124:  * Returns the number of chars immediately written, or -1
        !          1125:  *         in case of error.
        !          1126:  */
        !          1127: int
        !          1128: xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
        !          1129:     int nbchars = 0, ret;
        !          1130: 
        !          1131:     if (len < 0) return(0);
        !          1132: 
        !          1133:     /*
        !          1134:      * first handle encoding stuff.
        !          1135:      */
        !          1136:     if (out->encoder != NULL) {
        !          1137:         /*
        !          1138:         * Store the data in the incoming raw buffer
        !          1139:         */
        !          1140:         if (out->raw == NULL) {
        !          1141:            out->raw = xmlBufferCreate();
        !          1142:        }
        !          1143:        xmlBufferAdd(out->raw, (const xmlChar *) buf, len);
        !          1144: 
        !          1145:         if (out->raw->use < MINLEN)
        !          1146:            return(0);
        !          1147: 
        !          1148:        /*
        !          1149:         * convert as much as possible to the parser reading buffer.
        !          1150:         */
        !          1151:        nbchars = xmlCharEncOutFunc(out->encoder, out->buffer, out->raw);
        !          1152:        if (nbchars < 0) {
        !          1153:            fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
        !          1154:            return(-1);
        !          1155:        }
        !          1156:     } else {
        !          1157:        xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
        !          1158:     }
        !          1159:     nbchars = out->buffer->use;
        !          1160:     if (nbchars < MINLEN)
        !          1161:        return(0);
        !          1162: 
        !          1163:     /*
        !          1164:      * second write the stuff to the I/O channel
        !          1165:      */
        !          1166:     ret = out->writecallback(out->context, 
        !          1167:                              (const char *)out->buffer->content, nbchars);
        !          1168:     if (ret >= 0)
        !          1169:        xmlBufferShrink(out->buffer, nbchars);
        !          1170:     if (ret < 0) {
        !          1171:         fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
        !          1172:        return(ret);
        !          1173:     }
        !          1174: 
        !          1175: #ifdef DEBUG_INPUT
        !          1176:     fprintf(stderr, "I/O: wrote %d chars\n", ret);
        !          1177: #endif
        !          1178:     return(nbchars);
1.4       daniel   1179: }
                   1180: 
                   1181: /*
                   1182:  * xmlParserGetDirectory:
                   1183:  * @filename:  the path to a file
                   1184:  *
                   1185:  * lookup the directory for that file
                   1186:  *
                   1187:  * Returns a new allocated string containing the directory, or NULL.
                   1188:  */
                   1189: char *
                   1190: xmlParserGetDirectory(const char *filename) {
                   1191:     char *ret = NULL;
                   1192:     char dir[1024];
                   1193:     char *cur;
                   1194:     char sep = '/';
1.23      daniel   1195: 
                   1196:     if (xmlInputCallbackInitialized == 0)
                   1197:        xmlRegisterDefaultInputCallbacks();
1.4       daniel   1198: 
                   1199:     if (filename == NULL) return(NULL);
                   1200: #ifdef WIN32
                   1201:     sep = '\\';
                   1202: #endif
                   1203: 
                   1204:     strncpy(dir, filename, 1023);
                   1205:     dir[1023] = 0;
                   1206:     cur = &dir[strlen(dir)];
                   1207:     while (cur > dir) {
                   1208:          if (*cur == sep) break;
                   1209:         cur --;
                   1210:     }
                   1211:     if (*cur == sep) {
                   1212:         if (cur == dir) dir[1] = 0;
                   1213:        else *cur = 0;
1.8       daniel   1214:        ret = xmlMemStrdup(dir);
1.4       daniel   1215:     } else {
                   1216:         if (getcwd(dir, 1024) != NULL) {
                   1217:            dir[1023] = 0;
1.8       daniel   1218:            ret = xmlMemStrdup(dir);
1.4       daniel   1219:        }
                   1220:     }
                   1221:     return(ret);
1.5       daniel   1222: }
                   1223: 
                   1224: /****************************************************************
                   1225:  *                                                             *
                   1226:  *             External entities loading                       *
                   1227:  *                                                             *
                   1228:  ****************************************************************/
                   1229: 
                   1230: /*
                   1231:  * xmlDefaultExternalEntityLoader:
                   1232:  * @URL:  the URL for the entity to load
                   1233:  * @ID:  the System ID for the entity to load
1.18      daniel   1234:  * @ctxt:  the context in which the entity is called or NULL
1.5       daniel   1235:  *
                   1236:  * By default we don't load external entitites, yet.
                   1237:  *
                   1238:  * Returns a new allocated xmlParserInputPtr, or NULL.
                   1239:  */
                   1240: static
                   1241: xmlParserInputPtr
                   1242: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
1.18      daniel   1243:                                xmlParserCtxtPtr ctxt) {
                   1244:     xmlParserInputPtr ret = NULL;
1.5       daniel   1245: #ifdef DEBUG_EXTERNAL_ENTITIES
                   1246:     fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
                   1247: #endif
1.18      daniel   1248:     if (URL == NULL) {
                   1249:         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   1250:            ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
                   1251:                               ID);
                   1252:         return(NULL);
                   1253:     }
                   1254:     ret = xmlNewInputFromFile(ctxt, URL);
                   1255:     if (ret == NULL) {
                   1256:         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   1257:            ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
                   1258:                               URL);
                   1259:     }
                   1260:     return(ret);
1.5       daniel   1261: }
                   1262: 
                   1263: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
                   1264:        xmlDefaultExternalEntityLoader;
                   1265: 
                   1266: /*
                   1267:  * xmlSetExternalEntityLoader:
                   1268:  * @f:  the new entity resolver function
                   1269:  *
                   1270:  * Changes the defaultexternal entity resolver function for the application
                   1271:  */
                   1272: void
                   1273: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
                   1274:     xmlCurrentExternalEntityLoader = f;
                   1275: }
                   1276: 
                   1277: /*
                   1278:  * xmlGetExternalEntityLoader:
                   1279:  *
                   1280:  * Get the default external entity resolver function for the application
                   1281:  *
                   1282:  * Returns the xmlExternalEntityLoader function pointer
                   1283:  */
                   1284: xmlExternalEntityLoader
                   1285: xmlGetExternalEntityLoader(void) {
                   1286:     return(xmlCurrentExternalEntityLoader);
                   1287: }
                   1288: 
                   1289: /*
                   1290:  * xmlLoadExternalEntity:
                   1291:  * @URL:  the URL for the entity to load
                   1292:  * @ID:  the System ID for the entity to load
1.18      daniel   1293:  * @ctxt:  the context in which the entity is called or NULL
1.5       daniel   1294:  *
                   1295:  * Load an external entity, note that the use of this function for
                   1296:  * unparsed entities may generate problems
1.6       daniel   1297:  * TODO: a more generic External entitiy API must be designed
1.5       daniel   1298:  *
                   1299:  * Returns the xmlParserInputPtr or NULL
                   1300:  */
                   1301: xmlParserInputPtr
                   1302: xmlLoadExternalEntity(const char *URL, const char *ID,
1.18      daniel   1303:                       xmlParserCtxtPtr ctxt) {
                   1304:     return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
1.1       daniel   1305: }
                   1306: 

Webmaster