Annotation of XML/xmlIO.c, revision 1.39

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

Webmaster