Annotation of XML/xmlIO.c, revision 1.41

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

Webmaster