Annotation of XML/xmlIO.c, revision 1.32

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) {
                    647:     xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
                    648:                              xmlFileRead, xmlFileClose);
                    649: #ifdef HAVE_ZLIB_H
                    650:     xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
                    651:                              xmlGzfileRead, xmlGzfileClose);
                    652: #endif /* HAVE_ZLIB_H */
                    653: 
                    654: #ifdef LIBXML_HTTP_ENABLED
                    655:     xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
                    656:                              xmlIOHTTPRead, xmlIOHTTPClose);
                    657: #endif /* LIBXML_HTTP_ENABLED */
                    658: 
                    659: #ifdef LIBXML_FTP_ENABLED
                    660:     xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
                    661:                              xmlIOFTPRead, xmlIOFTPClose);
                    662: #endif /* LIBXML_FTP_ENABLED */
                    663: }
1.22      daniel    664: 
1.1       daniel    665: /**
1.27      daniel    666:  * xmlRegisterDefaultOutputCallbacks:
                    667:  *
                    668:  * Registers the default compiled-in I/O handlers.
                    669:  */
                    670: void
                    671: xmlRegisterDefaultOutputCallbacks(void) {
1.28      daniel    672:     xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
1.27      daniel    673:                              xmlFileWrite, xmlFileClose);
                    674: /*********************************
                    675:  No way a-priori to distinguish between gzipped files from
                    676:  uncompressed ones except opening if existing then closing
                    677:  and saving with same compression ratio ... a pain.
                    678: 
                    679: #ifdef HAVE_ZLIB_H
                    680:     xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
                    681:                               xmlGzfileWrite, xmlGzfileClose);
                    682: #endif
                    683:  No HTTP PUT support yet, patches welcome
                    684: 
                    685: #ifdef LIBXML_HTTP_ENABLED
                    686:     xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
                    687:                               xmlIOHTTPWrite, xmlIOHTTPClose);
                    688: #endif
                    689: 
                    690:  Nor FTP PUT ....
                    691: #ifdef LIBXML_FTP_ENABLED
                    692:     xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
                    693:                               xmlIOFTPWrite, xmlIOFTPClose);
                    694: #endif
                    695:  **********************************/
                    696: }
                    697: 
                    698: /**
1.1       daniel    699:  * xmlAllocParserInputBuffer:
                    700:  * @enc:  the charset encoding if known
                    701:  *
                    702:  * Create a buffered parser input for progressive parsing
                    703:  *
                    704:  * Returns the new parser input or NULL
                    705:  */
                    706: xmlParserInputBufferPtr
                    707: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
                    708:     xmlParserInputBufferPtr ret;
                    709: 
1.8       daniel    710:     ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1.1       daniel    711:     if (ret == NULL) {
                    712:         fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
                    713:        return(NULL);
                    714:     }
1.3       veillard  715:     memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
1.1       daniel    716:     ret->buffer = xmlBufferCreate();
1.17      daniel    717:     if (ret->buffer == NULL) {
                    718:         xmlFree(ret);
                    719:        return(NULL);
                    720:     }
                    721:     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
1.1       daniel    722:     ret->encoder = xmlGetCharEncodingHandler(enc);
1.26      daniel    723:     if (ret->encoder != NULL)
                    724:         ret->raw = xmlBufferCreate();
                    725:     else
                    726:         ret->raw = NULL;
1.23      daniel    727:     ret->readcallback = NULL;
                    728:     ret->closecallback = NULL;
                    729:     ret->context = NULL;
1.1       daniel    730: 
                    731:     return(ret);
                    732: }
                    733: 
                    734: /**
1.27      daniel    735:  * xmlAllocOutputBuffer:
                    736:  * @encoder:  the encoding converter or NULL
                    737:  *
                    738:  * Create a buffered parser output
                    739:  *
                    740:  * Returns the new parser output or NULL
                    741:  */
                    742: xmlOutputBufferPtr
                    743: xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
                    744:     xmlOutputBufferPtr ret;
                    745: 
                    746:     ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
                    747:     if (ret == NULL) {
                    748:         fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
                    749:        return(NULL);
                    750:     }
                    751:     memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
                    752:     ret->buffer = xmlBufferCreate();
                    753:     if (ret->buffer == NULL) {
                    754:         xmlFree(ret);
                    755:        return(NULL);
                    756:     }
                    757:     ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
                    758:     ret->encoder = encoder;
1.28      daniel    759:     if (encoder != NULL) {
                    760:         ret->conv = xmlBufferCreateSize(4000);
                    761:        /*
                    762:         * This call is designed to initiate the encoder state
                    763:         */
                    764:        xmlCharEncOutFunc(encoder, ret->conv, NULL); 
                    765:     } else
                    766:         ret->conv = NULL;
1.27      daniel    767:     ret->writecallback = NULL;
                    768:     ret->closecallback = NULL;
                    769:     ret->context = NULL;
1.28      daniel    770:     ret->written = 0;
1.27      daniel    771: 
                    772:     return(ret);
                    773: }
                    774: 
                    775: /**
1.1       daniel    776:  * xmlFreeParserInputBuffer:
                    777:  * @in:  a buffered parser input
                    778:  *
                    779:  * Free up the memory used by a buffered parser input
                    780:  */
                    781: void
                    782: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1.26      daniel    783:     if (in->raw) {
                    784:         xmlBufferFree(in->raw);
                    785:        in->raw = NULL;
                    786:     }
1.25      daniel    787:     if (in->encoder != NULL) {
                    788:         xmlCharEncCloseFunc(in->encoder);
                    789:     }
                    790:     if (in->closecallback != NULL) {
                    791:        in->closecallback(in->context);
                    792:     }
1.1       daniel    793:     if (in->buffer != NULL) {
                    794:         xmlBufferFree(in->buffer);
                    795:        in->buffer = NULL;
                    796:     }
1.23      daniel    797: 
1.3       veillard  798:     memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
1.8       daniel    799:     xmlFree(in);
1.1       daniel    800: }
                    801: 
                    802: /**
1.28      daniel    803:  * xmlOutputBufferClose:
                    804:  * @out:  a buffered output
                    805:  *
                    806:  * flushes and close the output I/O channel
                    807:  * and free up all the associated resources
                    808:  *
                    809:  * Returns the number of byte written or -1 in case of error.
                    810:  */
                    811: int
                    812: xmlOutputBufferClose(xmlOutputBufferPtr out) {
                    813:     int written;
                    814: 
                    815:     if (out == NULL)
                    816:         return(-1);
                    817:     xmlOutputBufferFlush(out);
                    818:     if (out->closecallback != NULL) {
                    819:        out->closecallback(out->context);
                    820:     }
                    821:     written = out->written;
                    822:     if (out->conv) {
                    823:         xmlBufferFree(out->conv);
                    824:        out->conv = NULL;
                    825:     }
                    826:     if (out->encoder != NULL) {
                    827:         xmlCharEncCloseFunc(out->encoder);
                    828:     }
                    829:     if (out->buffer != NULL) {
                    830:         xmlBufferFree(out->buffer);
                    831:        out->buffer = NULL;
                    832:     }
                    833: 
                    834:     memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
                    835:     xmlFree(out);
                    836:     return(written);
                    837: }
                    838: 
                    839: /**
1.1       daniel    840:  * xmlParserInputBufferCreateFilename:
1.23      daniel    841:  * @URI:  a C string containing the URI or filename
1.1       daniel    842:  * @enc:  the charset encoding if known
                    843:  *
                    844:  * Create a buffered parser input for the progressive parsing of a file
                    845:  * If filename is "-' then we use stdin as the input.
                    846:  * Automatic support for ZLIB/Compress compressed document is provided
                    847:  * by default if found at compile-time.
1.20      daniel    848:  * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1.1       daniel    849:  *
                    850:  * Returns the new parser input or NULL
                    851:  */
                    852: xmlParserInputBufferPtr
1.23      daniel    853: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1.1       daniel    854:     xmlParserInputBufferPtr ret;
1.23      daniel    855:     int i;
                    856:     void *context = NULL;
                    857: 
                    858:     if (xmlInputCallbackInitialized == 0)
                    859:        xmlRegisterDefaultInputCallbacks();
1.1       daniel    860: 
1.23      daniel    861:     if (URI == NULL) return(NULL);
1.1       daniel    862: 
1.23      daniel    863:     /*
                    864:      * Try to find one of the input accept method accepting taht scheme
                    865:      * Go in reverse to give precedence to user defined handlers.
                    866:      */
                    867:     for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
                    868:        if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
                    869:            (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
                    870:            context = xmlInputCallbackTable[i].opencallback(URI);
                    871:            if (context != NULL)
                    872:                break;
1.1       daniel    873:        }
1.23      daniel    874:     }
                    875:     if (context == NULL) {
                    876: #ifdef DEBUG_INPUT
                    877:        fprintf(stderr, "No input filter matching \"%s\"\n", URI);
1.1       daniel    878: #endif
1.23      daniel    879:        return(NULL);
1.1       daniel    880:     }
1.20      daniel    881: 
                    882:     /*
                    883:      * Allocate the Input buffer front-end.
1.1       daniel    884:      */
                    885:     ret = xmlAllocParserInputBuffer(enc);
                    886:     if (ret != NULL) {
1.23      daniel    887:        ret->context = context;
                    888:        ret->readcallback = xmlInputCallbackTable[i].readcallback;
                    889:        ret->closecallback = xmlInputCallbackTable[i].closecallback;
1.1       daniel    890:     }
                    891:     return(ret);
                    892: }
                    893: 
                    894: /**
1.27      daniel    895:  * xmlOutputBufferCreateFilename:
                    896:  * @URI:  a C string containing the URI or filename
                    897:  * @encoder:  the encoding converter or NULL
1.28      daniel    898:  * @compression:  the compression ration (0 none, 9 max).
1.27      daniel    899:  *
                    900:  * Create a buffered  output for the progressive saving of a file
                    901:  * If filename is "-' then we use stdout as the output.
                    902:  * Automatic support for ZLIB/Compress compressed document is provided
                    903:  * by default if found at compile-time.
1.28      daniel    904:  * TODO: currently if compression is set, the library only support
                    905:  *       writing to a local file.
1.27      daniel    906:  *
                    907:  * Returns the new output or NULL
                    908:  */
                    909: xmlOutputBufferPtr
                    910: xmlOutputBufferCreateFilename(const char *URI,
1.28      daniel    911:                               xmlCharEncodingHandlerPtr encoder,
                    912:                              int compression) {
1.27      daniel    913:     xmlOutputBufferPtr ret;
                    914:     int i;
                    915:     void *context = NULL;
                    916: 
                    917:     if (xmlOutputCallbackInitialized == 0)
                    918:        xmlRegisterDefaultOutputCallbacks();
                    919: 
                    920:     if (URI == NULL) return(NULL);
                    921: 
1.28      daniel    922: #ifdef HAVE_ZLIB_H
                    923:     if ((compression > 0) && (compression <= 9)) {
                    924:         context = xmlGzfileOpenW(URI, compression);
                    925:        if (context != NULL) {
                    926:            ret = xmlAllocOutputBuffer(encoder);
                    927:            if (ret != NULL) {
                    928:                ret->context = context;
                    929:                ret->writecallback = xmlGzfileWrite;
                    930:                ret->closecallback = xmlGzfileClose;
                    931:            }
                    932:            return(ret);
                    933:        }
                    934:     }
                    935: #endif
                    936: 
1.27      daniel    937:     /*
                    938:      * Try to find one of the output accept method accepting taht scheme
                    939:      * Go in reverse to give precedence to user defined handlers.
                    940:      */
                    941:     for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
                    942:        if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
                    943:            (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
                    944:            context = xmlOutputCallbackTable[i].opencallback(URI);
                    945:            if (context != NULL)
                    946:                break;
                    947:        }
                    948:     }
                    949:     if (context == NULL) {
                    950: #ifdef DEBUG_INPUT
                    951:        fprintf(stderr, "No output filter matching \"%s\"\n", URI);
                    952: #endif
                    953:        return(NULL);
                    954:     }
                    955: 
                    956:     /*
                    957:      * Allocate the Output buffer front-end.
                    958:      */
                    959:     ret = xmlAllocOutputBuffer(encoder);
                    960:     if (ret != NULL) {
                    961:        ret->context = context;
                    962:        ret->writecallback = xmlOutputCallbackTable[i].writecallback;
                    963:        ret->closecallback = xmlOutputCallbackTable[i].closecallback;
                    964:     }
                    965:     return(ret);
                    966: }
                    967: 
                    968: /**
1.1       daniel    969:  * xmlParserInputBufferCreateFile:
                    970:  * @file:  a FILE* 
                    971:  * @enc:  the charset encoding if known
                    972:  *
                    973:  * Create a buffered parser input for the progressive parsing of a FILE *
                    974:  * buffered C I/O
                    975:  *
                    976:  * Returns the new parser input or NULL
                    977:  */
                    978: xmlParserInputBufferPtr
                    979: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
                    980:     xmlParserInputBufferPtr ret;
                    981: 
1.23      daniel    982:     if (xmlInputCallbackInitialized == 0)
                    983:        xmlRegisterDefaultInputCallbacks();
                    984: 
1.1       daniel    985:     if (file == NULL) return(NULL);
                    986: 
                    987:     ret = xmlAllocParserInputBuffer(enc);
1.23      daniel    988:     if (ret != NULL) {
                    989:         ret->context = file;
                    990:        ret->readcallback = xmlFileRead;
                    991:        ret->closecallback = xmlFileClose;
                    992:     }
1.1       daniel    993: 
                    994:     return(ret);
                    995: }
                    996: 
                    997: /**
1.27      daniel    998:  * xmlOutputBufferCreateFile:
                    999:  * @file:  a FILE* 
                   1000:  * @encoder:  the encoding converter or NULL
                   1001:  *
                   1002:  * Create a buffered output for the progressive saving to a FILE *
                   1003:  * buffered C I/O
                   1004:  *
                   1005:  * Returns the new parser output or NULL
                   1006:  */
                   1007: xmlOutputBufferPtr
                   1008: xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
                   1009:     xmlOutputBufferPtr ret;
                   1010: 
                   1011:     if (xmlOutputCallbackInitialized == 0)
                   1012:        xmlRegisterDefaultOutputCallbacks();
                   1013: 
                   1014:     if (file == NULL) return(NULL);
                   1015: 
                   1016:     ret = xmlAllocOutputBuffer(encoder);
                   1017:     if (ret != NULL) {
                   1018:         ret->context = file;
                   1019:        ret->writecallback = xmlFileWrite;
                   1020:        ret->closecallback = xmlFileClose;
                   1021:     }
                   1022: 
                   1023:     return(ret);
                   1024: }
                   1025: 
                   1026: /**
1.1       daniel   1027:  * xmlParserInputBufferCreateFd:
                   1028:  * @fd:  a file descriptor number
                   1029:  * @enc:  the charset encoding if known
                   1030:  *
                   1031:  * Create a buffered parser input for the progressive parsing for the input
                   1032:  * from a file descriptor
                   1033:  *
                   1034:  * Returns the new parser input or NULL
                   1035:  */
                   1036: xmlParserInputBufferPtr
                   1037: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
                   1038:     xmlParserInputBufferPtr ret;
                   1039: 
                   1040:     if (fd < 0) return(NULL);
                   1041: 
                   1042:     ret = xmlAllocParserInputBuffer(enc);
1.23      daniel   1043:     if (ret != NULL) {
                   1044:         ret->context = (void *) fd;
                   1045:        ret->readcallback = xmlFdRead;
                   1046:        ret->closecallback = xmlFdClose;
                   1047:     }
1.1       daniel   1048: 
                   1049:     return(ret);
                   1050: }
                   1051: 
                   1052: /**
1.31      veillard 1053:  * xmlParserInputBufferCreateMem:
                   1054:  * @mem:  the memory input
                   1055:  * @size:  the length of the memory block
                   1056:  * @enc:  the charset encoding if known
                   1057:  *
                   1058:  * Create a buffered parser input for the progressive parsing for the input
                   1059:  * from a file descriptor
                   1060:  *
                   1061:  * Returns the new parser input or NULL
                   1062:  */
                   1063: xmlParserInputBufferPtr
                   1064: xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
                   1065:     xmlParserInputBufferPtr ret;
                   1066: 
                   1067:     if (size <= 0) return(NULL);
                   1068:     if (mem == NULL) return(NULL);
                   1069: 
                   1070:     ret = xmlAllocParserInputBuffer(enc);
                   1071:     if (ret != NULL) {
                   1072:         ret->context = (void *) mem;
1.32    ! veillard 1073:        ret->readcallback = (xmlInputReadCallback) xmlNop;
1.31      veillard 1074:        ret->closecallback = NULL;
                   1075:        xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
                   1076:     }
                   1077: 
                   1078:     return(ret);
                   1079: }
                   1080: 
                   1081: /**
1.27      daniel   1082:  * xmlOutputBufferCreateFd:
                   1083:  * @fd:  a file descriptor number
                   1084:  * @encoder:  the encoding converter or NULL
                   1085:  *
                   1086:  * Create a buffered output for the progressive saving 
                   1087:  * to a file descriptor
                   1088:  *
                   1089:  * Returns the new parser output or NULL
                   1090:  */
                   1091: xmlOutputBufferPtr
                   1092: xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
                   1093:     xmlOutputBufferPtr ret;
                   1094: 
                   1095:     if (fd < 0) return(NULL);
                   1096: 
                   1097:     ret = xmlAllocOutputBuffer(encoder);
                   1098:     if (ret != NULL) {
                   1099:         ret->context = (void *) fd;
                   1100:        ret->writecallback = xmlFdWrite;
                   1101:        ret->closecallback = xmlFdClose;
                   1102:     }
                   1103: 
                   1104:     return(ret);
                   1105: }
                   1106: 
                   1107: /**
1.24      daniel   1108:  * xmlParserInputBufferCreateIO:
                   1109:  * @ioread:  an I/O read function
                   1110:  * @ioclose:  an I/O close function
                   1111:  * @ioctx:  an I/O handler
                   1112:  * @enc:  the charset encoding if known
                   1113:  *
                   1114:  * Create a buffered parser input for the progressive parsing for the input
1.27      daniel   1115:  * from an I/O handler
1.24      daniel   1116:  *
                   1117:  * Returns the new parser input or NULL
                   1118:  */
                   1119: xmlParserInputBufferPtr
                   1120: xmlParserInputBufferCreateIO(xmlInputReadCallback   ioread,
                   1121:         xmlInputCloseCallback  ioclose, void *ioctx, xmlCharEncoding enc) {
                   1122:     xmlParserInputBufferPtr ret;
                   1123: 
                   1124:     if (ioread == NULL) return(NULL);
                   1125: 
                   1126:     ret = xmlAllocParserInputBuffer(enc);
                   1127:     if (ret != NULL) {
                   1128:         ret->context = (void *) ioctx;
                   1129:        ret->readcallback = ioread;
                   1130:        ret->closecallback = ioclose;
                   1131:     }
                   1132: 
                   1133:     return(ret);
                   1134: }
                   1135: 
                   1136: /**
1.27      daniel   1137:  * xmlOutputBufferCreateIO:
                   1138:  * @iowrite:  an I/O write function
                   1139:  * @ioclose:  an I/O close function
                   1140:  * @ioctx:  an I/O handler
                   1141:  * @enc:  the charset encoding if known
                   1142:  *
                   1143:  * Create a buffered output for the progressive saving
                   1144:  * to an I/O handler
                   1145:  *
                   1146:  * Returns the new parser output or NULL
                   1147:  */
                   1148: xmlOutputBufferPtr
                   1149: xmlOutputBufferCreateIO(xmlOutputWriteCallback   iowrite,
                   1150:         xmlOutputCloseCallback  ioclose, void *ioctx,
                   1151:         xmlCharEncodingHandlerPtr encoder) {
                   1152:     xmlOutputBufferPtr ret;
                   1153: 
                   1154:     if (iowrite == NULL) return(NULL);
                   1155: 
                   1156:     ret = xmlAllocOutputBuffer(encoder);
                   1157:     if (ret != NULL) {
                   1158:         ret->context = (void *) ioctx;
                   1159:        ret->writecallback = iowrite;
                   1160:        ret->closecallback = ioclose;
                   1161:     }
                   1162: 
                   1163:     return(ret);
                   1164: }
                   1165: 
                   1166: /**
1.14      daniel   1167:  * xmlParserInputBufferPush:
                   1168:  * @in:  a buffered parser input
1.27      daniel   1169:  * @len:  the size in bytes of the array.
1.14      daniel   1170:  * @buf:  an char array
                   1171:  *
                   1172:  * Push the content of the arry in the input buffer
                   1173:  * This routine handle the I18N transcoding to internal UTF-8
                   1174:  * This is used when operating the parser in progressive (push) mode.
                   1175:  *
                   1176:  * Returns the number of chars read and stored in the buffer, or -1
                   1177:  *         in case of error.
                   1178:  */
                   1179: int
1.15      daniel   1180: xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
1.14      daniel   1181:     int nbchars = 0;
                   1182: 
                   1183:     if (len < 0) return(0);
                   1184:     if (in->encoder != NULL) {
1.26      daniel   1185:         /*
                   1186:         * Store the data in the incoming raw buffer
                   1187:         */
                   1188:         if (in->raw == NULL) {
                   1189:            in->raw = xmlBufferCreate();
                   1190:        }
                   1191:        xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
1.14      daniel   1192: 
                   1193:        /*
1.26      daniel   1194:         * convert as much as possible to the parser reading buffer.
1.14      daniel   1195:         */
1.26      daniel   1196:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1.20      daniel   1197:        if (nbchars < 0) {
                   1198:            fprintf(stderr, "xmlParserInputBufferPush: encoder error\n");
                   1199:            return(-1);
                   1200:        }
1.14      daniel   1201:     } else {
                   1202:        nbchars = len;
1.17      daniel   1203:         xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
1.14      daniel   1204:     }
                   1205: #ifdef DEBUG_INPUT
                   1206:     fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
                   1207:             nbchars, in->buffer->use, in->buffer->size);
                   1208: #endif
                   1209:     return(nbchars);
                   1210: }
                   1211: 
                   1212: /**
1.1       daniel   1213:  * xmlParserInputBufferGrow:
                   1214:  * @in:  a buffered parser input
                   1215:  * @len:  indicative value of the amount of chars to read
                   1216:  *
                   1217:  * Grow up the content of the input buffer, the old data are preserved
                   1218:  * This routine handle the I18N transcoding to internal UTF-8
1.14      daniel   1219:  * This routine is used when operating the parser in normal (pull) mode
1.26      daniel   1220:  *
                   1221:  * TODO: one should be able to remove one extra copy by copying directy
                   1222:  *       onto in->buffer or in->raw
1.1       daniel   1223:  *
                   1224:  * Returns the number of chars read and stored in the buffer, or -1
                   1225:  *         in case of error.
                   1226:  */
                   1227: int
                   1228: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
                   1229:     char *buffer = NULL;
                   1230:     int res = 0;
                   1231:     int nbchars = 0;
                   1232:     int buffree;
                   1233: 
                   1234:     if ((len <= MINLEN) && (len != 4)) 
                   1235:         len = MINLEN;
                   1236:     buffree = in->buffer->size - in->buffer->use;
                   1237:     if (buffree <= 0) {
                   1238:         fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
                   1239:        return(0);
                   1240:     }
                   1241:     if (len > buffree) 
                   1242:         len = buffree;
                   1243: 
1.30      veillard 1244:     buffer = (char *) xmlMalloc((len + 1) * sizeof(char));
1.1       daniel   1245:     if (buffer == NULL) {
                   1246:         fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
                   1247:        return(-1);
                   1248:     }
1.23      daniel   1249: 
                   1250:     /*
                   1251:      * Call the read method for this I/O type.
                   1252:      */
                   1253:     if (in->readcallback != NULL) {
                   1254:        res = in->readcallback(in->context, &buffer[0], len);
1.1       daniel   1255:     } else {
                   1256:         fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
1.8       daniel   1257:        xmlFree(buffer);
1.1       daniel   1258:        return(-1);
                   1259:     }
                   1260:     if (res < 0) {
                   1261:        perror ("read error");
1.8       daniel   1262:        xmlFree(buffer);
1.1       daniel   1263:        return(-1);
                   1264:     }
1.29      daniel   1265:     len = res;
1.1       daniel   1266:     if (in->encoder != NULL) {
1.26      daniel   1267:         /*
                   1268:         * Store the data in the incoming raw buffer
                   1269:         */
                   1270:         if (in->raw == NULL) {
                   1271:            in->raw = xmlBufferCreate();
1.1       daniel   1272:        }
1.26      daniel   1273:        xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
1.20      daniel   1274: 
                   1275:        /*
1.26      daniel   1276:         * convert as much as possible to the parser reading buffer.
1.20      daniel   1277:         */
1.26      daniel   1278:        nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
                   1279:        if (nbchars < 0) {
                   1280:            fprintf(stderr, "xmlParserInputBufferGrow: encoder error\n");
                   1281:            return(-1);
1.20      daniel   1282:        }
1.1       daniel   1283:     } else {
1.29      daniel   1284:        nbchars = len;
1.3       veillard 1285:         buffer[nbchars] = 0;
1.13      daniel   1286:         xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
1.1       daniel   1287:     }
                   1288: #ifdef DEBUG_INPUT
                   1289:     fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
                   1290:             nbchars, in->buffer->use, in->buffer->size);
                   1291: #endif
1.8       daniel   1292:     xmlFree(buffer);
1.1       daniel   1293:     return(nbchars);
                   1294: }
                   1295: 
                   1296: /**
                   1297:  * xmlParserInputBufferRead:
                   1298:  * @in:  a buffered parser input
                   1299:  * @len:  indicative value of the amount of chars to read
                   1300:  *
                   1301:  * Refresh the content of the input buffer, the old data are considered
                   1302:  * consumed
                   1303:  * This routine handle the I18N transcoding to internal UTF-8
                   1304:  *
                   1305:  * Returns the number of chars read and stored in the buffer, or -1
                   1306:  *         in case of error.
                   1307:  */
                   1308: int
                   1309: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
                   1310:     /* xmlBufferEmpty(in->buffer); */
1.23      daniel   1311:     if (in->readcallback != NULL)
1.17      daniel   1312:        return(xmlParserInputBufferGrow(in, len));
                   1313:     else
1.27      daniel   1314:         return(-1);
                   1315: }
                   1316: 
                   1317: /**
                   1318:  * xmlOutputBufferWrite:
                   1319:  * @out:  a buffered parser output
                   1320:  * @len:  the size in bytes of the array.
                   1321:  * @buf:  an char array
                   1322:  *
                   1323:  * Write the content of the array in the output I/O buffer
                   1324:  * This routine handle the I18N transcoding from internal UTF-8
                   1325:  * The buffer is lossless, i.e. will store in case of partial
                   1326:  * or delayed writes.
                   1327:  *
                   1328:  * Returns the number of chars immediately written, or -1
                   1329:  *         in case of error.
                   1330:  */
                   1331: int
                   1332: xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
                   1333:     int nbchars = 0, ret;
                   1334: 
                   1335:     if (len < 0) return(0);
                   1336: 
                   1337:     /*
                   1338:      * first handle encoding stuff.
                   1339:      */
                   1340:     if (out->encoder != NULL) {
                   1341:         /*
                   1342:         * Store the data in the incoming raw buffer
                   1343:         */
1.28      daniel   1344:         if (out->conv == NULL) {
                   1345:            out->conv = xmlBufferCreate();
1.27      daniel   1346:        }
1.28      daniel   1347:        xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.27      daniel   1348: 
1.28      daniel   1349:         if (out->buffer->use < MINLEN)
1.27      daniel   1350:            return(0);
                   1351: 
                   1352:        /*
                   1353:         * convert as much as possible to the parser reading buffer.
                   1354:         */
1.28      daniel   1355:        nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
1.27      daniel   1356:        if (nbchars < 0) {
                   1357:            fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
                   1358:            return(-1);
                   1359:        }
1.28      daniel   1360:        nbchars = out->conv->use;
1.27      daniel   1361:     } else {
                   1362:        xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.28      daniel   1363:        nbchars = out->buffer->use;
1.27      daniel   1364:     }
                   1365:     if (nbchars < MINLEN)
                   1366:        return(0);
                   1367: 
                   1368:     /*
                   1369:      * second write the stuff to the I/O channel
                   1370:      */
1.28      daniel   1371:     if (out->encoder != NULL) {
                   1372:        ret = out->writecallback(out->context, 
                   1373:                              (const char *)out->conv->content, nbchars);
                   1374:        if (ret >= 0)
                   1375:            xmlBufferShrink(out->conv, nbchars);
                   1376:     } else {
                   1377:        ret = out->writecallback(out->context, 
1.27      daniel   1378:                              (const char *)out->buffer->content, nbchars);
1.28      daniel   1379:        if (ret >= 0)
                   1380:            xmlBufferShrink(out->buffer, nbchars);
                   1381:     }
1.27      daniel   1382:     if (ret < 0) {
                   1383:         fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
                   1384:        return(ret);
                   1385:     }
1.28      daniel   1386:     out->written += ret;
1.27      daniel   1387: 
                   1388: #ifdef DEBUG_INPUT
                   1389:     fprintf(stderr, "I/O: wrote %d chars\n", ret);
                   1390: #endif
                   1391:     return(nbchars);
1.28      daniel   1392: }
                   1393: 
                   1394: /**
                   1395:  * xmlOutputBufferWriteString:
                   1396:  * @out:  a buffered parser output
                   1397:  * @str:  a zero terminated C string
                   1398:  *
                   1399:  * Write the content of the string in the output I/O buffer
                   1400:  * This routine handle the I18N transcoding from internal UTF-8
                   1401:  * The buffer is lossless, i.e. will store in case of partial
                   1402:  * or delayed writes.
                   1403:  *
                   1404:  * Returns the number of chars immediately written, or -1
                   1405:  *         in case of error.
                   1406:  */
                   1407: int
                   1408: xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
                   1409:     int len;
                   1410:     
                   1411:     if (str == NULL)
                   1412:         return(-1);
                   1413:     len = strlen(str);
                   1414: 
                   1415:     if (len > 0)
                   1416:        return(xmlOutputBufferWrite(out, len, str));
                   1417:     return(len);
                   1418: }
                   1419: 
                   1420: /**
                   1421:  * xmlOutputBufferFlush:
                   1422:  * @out:  a buffered output
                   1423:  *
                   1424:  * flushes the output I/O channel
                   1425:  *
                   1426:  * Returns the number of byte written or -1 in case of error.
                   1427:  */
                   1428: int
                   1429: xmlOutputBufferFlush(xmlOutputBufferPtr out) {
                   1430:     int nbchars = 0, ret;
                   1431: 
                   1432:     /*
                   1433:      * first handle encoding stuff.
                   1434:      */
                   1435:     if ((out->conv != NULL) && (out->encoder != NULL)) {
                   1436:        /*
                   1437:         * convert as much as possible to the parser reading buffer.
                   1438:         */
                   1439:        nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
                   1440:        if (nbchars < 0) {
                   1441:            fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
                   1442:            return(-1);
                   1443:        }
                   1444:     }
                   1445: 
                   1446:     /*
                   1447:      * second flush the stuff to the I/O channel
                   1448:      */
                   1449:     if ((out->conv != NULL) && (out->encoder != NULL)) {
                   1450:        ret = out->writecallback(out->context,
                   1451:                   (const char *)out->conv->content, out->conv->use);
                   1452:        if (ret >= 0)
                   1453:            xmlBufferShrink(out->conv, ret);
                   1454:     } else {
                   1455:        ret = out->writecallback(out->context,
                   1456:                   (const char *)out->buffer->content, out->buffer->use);
                   1457:        if (ret >= 0)
                   1458:            xmlBufferShrink(out->buffer, ret);
                   1459:     }
                   1460:     if (ret < 0) {
                   1461:         fprintf(stderr, "I/O: error %d flushing %d bytes\n", ret, nbchars);
                   1462:        return(ret);
                   1463:     }
                   1464:     out->written += ret;
                   1465: 
                   1466: #ifdef DEBUG_INPUT
                   1467:     fprintf(stderr, "I/O: flushed %d chars\n", ret);
                   1468: #endif
                   1469:     return(ret);
1.4       daniel   1470: }
                   1471: 
                   1472: /*
                   1473:  * xmlParserGetDirectory:
                   1474:  * @filename:  the path to a file
                   1475:  *
                   1476:  * lookup the directory for that file
                   1477:  *
                   1478:  * Returns a new allocated string containing the directory, or NULL.
                   1479:  */
                   1480: char *
                   1481: xmlParserGetDirectory(const char *filename) {
                   1482:     char *ret = NULL;
                   1483:     char dir[1024];
                   1484:     char *cur;
                   1485:     char sep = '/';
1.23      daniel   1486: 
                   1487:     if (xmlInputCallbackInitialized == 0)
                   1488:        xmlRegisterDefaultInputCallbacks();
1.4       daniel   1489: 
                   1490:     if (filename == NULL) return(NULL);
                   1491: #ifdef WIN32
                   1492:     sep = '\\';
                   1493: #endif
                   1494: 
                   1495:     strncpy(dir, filename, 1023);
                   1496:     dir[1023] = 0;
                   1497:     cur = &dir[strlen(dir)];
                   1498:     while (cur > dir) {
                   1499:          if (*cur == sep) break;
                   1500:         cur --;
                   1501:     }
                   1502:     if (*cur == sep) {
                   1503:         if (cur == dir) dir[1] = 0;
                   1504:        else *cur = 0;
1.8       daniel   1505:        ret = xmlMemStrdup(dir);
1.4       daniel   1506:     } else {
                   1507:         if (getcwd(dir, 1024) != NULL) {
                   1508:            dir[1023] = 0;
1.8       daniel   1509:            ret = xmlMemStrdup(dir);
1.4       daniel   1510:        }
                   1511:     }
                   1512:     return(ret);
1.5       daniel   1513: }
                   1514: 
                   1515: /****************************************************************
                   1516:  *                                                             *
                   1517:  *             External entities loading                       *
                   1518:  *                                                             *
                   1519:  ****************************************************************/
                   1520: 
                   1521: /*
                   1522:  * xmlDefaultExternalEntityLoader:
                   1523:  * @URL:  the URL for the entity to load
                   1524:  * @ID:  the System ID for the entity to load
1.18      daniel   1525:  * @ctxt:  the context in which the entity is called or NULL
1.5       daniel   1526:  *
                   1527:  * By default we don't load external entitites, yet.
                   1528:  *
                   1529:  * Returns a new allocated xmlParserInputPtr, or NULL.
                   1530:  */
                   1531: static
                   1532: xmlParserInputPtr
                   1533: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
1.18      daniel   1534:                                xmlParserCtxtPtr ctxt) {
                   1535:     xmlParserInputPtr ret = NULL;
1.5       daniel   1536: #ifdef DEBUG_EXTERNAL_ENTITIES
                   1537:     fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
                   1538: #endif
1.18      daniel   1539:     if (URL == NULL) {
                   1540:         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   1541:            ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
                   1542:                               ID);
                   1543:         return(NULL);
                   1544:     }
                   1545:     ret = xmlNewInputFromFile(ctxt, URL);
                   1546:     if (ret == NULL) {
                   1547:         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   1548:            ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
                   1549:                               URL);
                   1550:     }
                   1551:     return(ret);
1.5       daniel   1552: }
                   1553: 
                   1554: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
                   1555:        xmlDefaultExternalEntityLoader;
                   1556: 
                   1557: /*
                   1558:  * xmlSetExternalEntityLoader:
                   1559:  * @f:  the new entity resolver function
                   1560:  *
                   1561:  * Changes the defaultexternal entity resolver function for the application
                   1562:  */
                   1563: void
                   1564: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
                   1565:     xmlCurrentExternalEntityLoader = f;
                   1566: }
                   1567: 
                   1568: /*
                   1569:  * xmlGetExternalEntityLoader:
                   1570:  *
                   1571:  * Get the default external entity resolver function for the application
                   1572:  *
                   1573:  * Returns the xmlExternalEntityLoader function pointer
                   1574:  */
                   1575: xmlExternalEntityLoader
                   1576: xmlGetExternalEntityLoader(void) {
                   1577:     return(xmlCurrentExternalEntityLoader);
                   1578: }
                   1579: 
                   1580: /*
                   1581:  * xmlLoadExternalEntity:
                   1582:  * @URL:  the URL for the entity to load
                   1583:  * @ID:  the System ID for the entity to load
1.18      daniel   1584:  * @ctxt:  the context in which the entity is called or NULL
1.5       daniel   1585:  *
                   1586:  * Load an external entity, note that the use of this function for
                   1587:  * unparsed entities may generate problems
1.6       daniel   1588:  * TODO: a more generic External entitiy API must be designed
1.5       daniel   1589:  *
                   1590:  * Returns the xmlParserInputPtr or NULL
                   1591:  */
                   1592: xmlParserInputPtr
                   1593: xmlLoadExternalEntity(const char *URL, const char *ID,
1.18      daniel   1594:                       xmlParserCtxtPtr ctxt) {
                   1595:     return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
1.1       daniel   1596: }
                   1597: 

Webmaster