Annotation of XML/xmlIO.c, revision 1.34

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

Webmaster