Annotation of embedaddon/libxml2/xinclude.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * xinclude.c : Code to implement XInclude processing
                      3:  *
                      4:  * World Wide Web Consortium W3C Last Call Working Draft 10 November 2003
                      5:  * http://www.w3.org/TR/2003/WD-xinclude-20031110
                      6:  *
                      7:  * See Copyright for the status of this software.
                      8:  *
                      9:  * daniel@veillard.com
                     10:  */
                     11: 
                     12: #define IN_LIBXML
                     13: #include "libxml.h"
                     14: 
                     15: #include <string.h>
                     16: #include <libxml/xmlmemory.h>
                     17: #include <libxml/tree.h>
                     18: #include <libxml/parser.h>
                     19: #include <libxml/uri.h>
                     20: #include <libxml/xpointer.h>
                     21: #include <libxml/parserInternals.h>
                     22: #include <libxml/xmlerror.h>
                     23: #include <libxml/encoding.h>
                     24: #include <libxml/globals.h>
                     25: 
                     26: #ifdef LIBXML_XINCLUDE_ENABLED
                     27: #include <libxml/xinclude.h>
                     28: 
1.1.1.3 ! misho      29: #include "buf.h"
1.1       misho      30: 
                     31: #define XINCLUDE_MAX_DEPTH 40
                     32: 
                     33: /* #define DEBUG_XINCLUDE */
                     34: #ifdef DEBUG_XINCLUDE
                     35: #ifdef LIBXML_DEBUG_ENABLED
                     36: #include <libxml/debugXML.h>
                     37: #endif
                     38: #endif
                     39: 
                     40: /************************************************************************
                     41:  *                                                                     *
                     42:  *                     XInclude context handling                       *
                     43:  *                                                                     *
                     44:  ************************************************************************/
                     45: 
                     46: /*
                     47:  * An XInclude context
                     48:  */
                     49: typedef xmlChar *xmlURL;
                     50: 
                     51: typedef struct _xmlXIncludeRef xmlXIncludeRef;
                     52: typedef xmlXIncludeRef *xmlXIncludeRefPtr;
                     53: struct _xmlXIncludeRef {
                     54:     xmlChar              *URI; /* the fully resolved resource URL */
                     55:     xmlChar         *fragment; /* the fragment in the URI */
                     56:     xmlDocPtr            doc; /* the parsed document */
                     57:     xmlNodePtr            ref; /* the node making the reference in the source */
                     58:     xmlNodePtr            inc; /* the included copy */
                     59:     int                   xml; /* xml or txt */
                     60:     int                 count; /* how many refs use that specific doc */
                     61:     xmlXPathObjectPtr    xptr; /* the xpointer if needed */
                     62:     int                      emptyFb; /* flag to show fallback empty */
                     63: };
                     64: 
                     65: struct _xmlXIncludeCtxt {
                     66:     xmlDocPtr             doc; /* the source document */
                     67:     int               incBase; /* the first include for this document */
                     68:     int                 incNr; /* number of includes */
                     69:     int                incMax; /* size of includes tab */
                     70:     xmlXIncludeRefPtr *incTab; /* array of included references */
                     71: 
                     72:     int                 txtNr; /* number of unparsed documents */
                     73:     int                txtMax; /* size of unparsed documents tab */
                     74:     xmlNodePtr        *txtTab; /* array of unparsed text nodes */
                     75:     xmlURL         *txturlTab; /* array of unparsed text URLs */
                     76: 
                     77:     xmlChar *             url; /* the current URL processed */
                     78:     int                 urlNr; /* number of URLs stacked */
                     79:     int                urlMax; /* size of URL stack */
                     80:     xmlChar *         *urlTab; /* URL stack */
                     81: 
                     82:     int              nbErrors; /* the number of errors detected */
                     83:     int                legacy; /* using XINCLUDE_OLD_NS */
                     84:     int            parseFlags; /* the flags used for parsing XML documents */
                     85:     xmlChar *           base; /* the current xml:base */
                     86: 
                     87:     void            *_private; /* application data */
                     88: };
                     89: 
                     90: static int
                     91: xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
                     92: 
                     93: 
                     94: /************************************************************************
                     95:  *                                                                     *
1.1.1.3 ! misho      96:  *                     XInclude error handler                          *
1.1       misho      97:  *                                                                     *
                     98:  ************************************************************************/
                     99: 
                    100: /**
                    101:  * xmlXIncludeErrMemory:
                    102:  * @extra:  extra information
                    103:  *
                    104:  * Handle an out of memory condition
                    105:  */
                    106: static void
                    107: xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node,
                    108:                      const char *extra)
                    109: {
                    110:     if (ctxt != NULL)
                    111:        ctxt->nbErrors++;
                    112:     __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
                    113:                     XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0,
                    114:                    extra, NULL, NULL, 0, 0,
                    115:                    "Memory allocation failed : %s\n", extra);
                    116: }
                    117: 
                    118: /**
                    119:  * xmlXIncludeErr:
                    120:  * @ctxt: the XInclude context
                    121:  * @node: the context node
                    122:  * @msg:  the error message
                    123:  * @extra:  extra information
                    124:  *
                    125:  * Handle an XInclude error
                    126:  */
                    127: static void
                    128: xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
                    129:                const char *msg, const xmlChar *extra)
                    130: {
                    131:     if (ctxt != NULL)
                    132:        ctxt->nbErrors++;
                    133:     __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
                    134:                     error, XML_ERR_ERROR, NULL, 0,
                    135:                    (const char *) extra, NULL, NULL, 0, 0,
                    136:                    msg, (const char *) extra);
                    137: }
                    138: 
                    139: #if 0
                    140: /**
                    141:  * xmlXIncludeWarn:
                    142:  * @ctxt: the XInclude context
                    143:  * @node: the context node
                    144:  * @msg:  the error message
                    145:  * @extra:  extra information
                    146:  *
                    147:  * Emit an XInclude warning.
                    148:  */
                    149: static void
                    150: xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
                    151:                const char *msg, const xmlChar *extra)
                    152: {
                    153:     __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
                    154:                     error, XML_ERR_WARNING, NULL, 0,
                    155:                    (const char *) extra, NULL, NULL, 0, 0,
                    156:                    msg, (const char *) extra);
                    157: }
                    158: #endif
                    159: 
                    160: /**
                    161:  * xmlXIncludeGetProp:
                    162:  * @ctxt:  the XInclude context
                    163:  * @cur:  the node
                    164:  * @name:  the attribute name
                    165:  *
                    166:  * Get an XInclude attribute
                    167:  *
                    168:  * Returns the value (to be freed) or NULL if not found
                    169:  */
                    170: static xmlChar *
                    171: xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur,
                    172:                    const xmlChar *name) {
                    173:     xmlChar *ret;
                    174: 
                    175:     ret = xmlGetNsProp(cur, XINCLUDE_NS, name);
                    176:     if (ret != NULL)
                    177:         return(ret);
                    178:     if (ctxt->legacy != 0) {
                    179:        ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name);
                    180:        if (ret != NULL)
                    181:            return(ret);
                    182:     }
                    183:     ret = xmlGetProp(cur, name);
                    184:     return(ret);
                    185: }
                    186: /**
                    187:  * xmlXIncludeFreeRef:
                    188:  * @ref: the XInclude reference
                    189:  *
                    190:  * Free an XInclude reference
                    191:  */
                    192: static void
                    193: xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
                    194:     if (ref == NULL)
                    195:        return;
                    196: #ifdef DEBUG_XINCLUDE
                    197:     xmlGenericError(xmlGenericErrorContext, "Freeing ref\n");
                    198: #endif
                    199:     if (ref->doc != NULL) {
                    200: #ifdef DEBUG_XINCLUDE
                    201:        xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI);
                    202: #endif
                    203:        xmlFreeDoc(ref->doc);
                    204:     }
                    205:     if (ref->URI != NULL)
                    206:        xmlFree(ref->URI);
                    207:     if (ref->fragment != NULL)
                    208:        xmlFree(ref->fragment);
                    209:     if (ref->xptr != NULL)
                    210:        xmlXPathFreeObject(ref->xptr);
                    211:     xmlFree(ref);
                    212: }
                    213: 
                    214: /**
                    215:  * xmlXIncludeNewRef:
                    216:  * @ctxt: the XInclude context
                    217:  * @URI:  the resource URI
                    218:  *
                    219:  * Creates a new reference within an XInclude context
                    220:  *
                    221:  * Returns the new set
                    222:  */
                    223: static xmlXIncludeRefPtr
                    224: xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI,
                    225:                  xmlNodePtr ref) {
                    226:     xmlXIncludeRefPtr ret;
                    227: 
                    228: #ifdef DEBUG_XINCLUDE
                    229:     xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI);
                    230: #endif
                    231:     ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
                    232:     if (ret == NULL) {
                    233:         xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
                    234:        return(NULL);
                    235:     }
                    236:     memset(ret, 0, sizeof(xmlXIncludeRef));
                    237:     if (URI == NULL)
                    238:        ret->URI = NULL;
                    239:     else
                    240:        ret->URI = xmlStrdup(URI);
                    241:     ret->fragment = NULL;
                    242:     ret->ref = ref;
                    243:     ret->doc = NULL;
                    244:     ret->count = 0;
                    245:     ret->xml = 0;
                    246:     ret->inc = NULL;
                    247:     if (ctxt->incMax == 0) {
                    248:        ctxt->incMax = 4;
                    249:         ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax *
                    250:                                              sizeof(ctxt->incTab[0]));
                    251:         if (ctxt->incTab == NULL) {
                    252:            xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
                    253:            xmlXIncludeFreeRef(ret);
                    254:            return(NULL);
                    255:        }
                    256:     }
                    257:     if (ctxt->incNr >= ctxt->incMax) {
                    258:        ctxt->incMax *= 2;
                    259:         ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
                    260:                     ctxt->incMax * sizeof(ctxt->incTab[0]));
                    261:         if (ctxt->incTab == NULL) {
                    262:            xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
                    263:            xmlXIncludeFreeRef(ret);
                    264:            return(NULL);
                    265:        }
                    266:     }
                    267:     ctxt->incTab[ctxt->incNr++] = ret;
                    268:     return(ret);
                    269: }
                    270: 
                    271: /**
                    272:  * xmlXIncludeNewContext:
                    273:  * @doc:  an XML Document
                    274:  *
                    275:  * Creates a new XInclude context
                    276:  *
                    277:  * Returns the new set
                    278:  */
                    279: xmlXIncludeCtxtPtr
                    280: xmlXIncludeNewContext(xmlDocPtr doc) {
                    281:     xmlXIncludeCtxtPtr ret;
                    282: 
                    283: #ifdef DEBUG_XINCLUDE
                    284:     xmlGenericError(xmlGenericErrorContext, "New context\n");
                    285: #endif
                    286:     if (doc == NULL)
                    287:        return(NULL);
                    288:     ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
                    289:     if (ret == NULL) {
                    290:        xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc,
                    291:                             "creating XInclude context");
                    292:        return(NULL);
                    293:     }
                    294:     memset(ret, 0, sizeof(xmlXIncludeCtxt));
                    295:     ret->doc = doc;
                    296:     ret->incNr = 0;
                    297:     ret->incBase = 0;
                    298:     ret->incMax = 0;
                    299:     ret->incTab = NULL;
                    300:     ret->nbErrors = 0;
                    301:     return(ret);
                    302: }
                    303: 
                    304: /**
                    305:  * xmlXIncludeURLPush:
                    306:  * @ctxt:  the parser context
                    307:  * @value:  the url
                    308:  *
                    309:  * Pushes a new url on top of the url stack
                    310:  *
                    311:  * Returns -1 in case of error, the index in the stack otherwise
                    312:  */
                    313: static int
                    314: xmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt,
                    315:                   const xmlChar *value)
                    316: {
                    317:     if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) {
                    318:        xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION,
                    319:                       "detected a recursion in %s\n", value);
                    320:        return(-1);
                    321:     }
                    322:     if (ctxt->urlTab == NULL) {
                    323:        ctxt->urlMax = 4;
                    324:        ctxt->urlNr = 0;
                    325:        ctxt->urlTab = (xmlChar * *) xmlMalloc(
                    326:                        ctxt->urlMax * sizeof(ctxt->urlTab[0]));
                    327:         if (ctxt->urlTab == NULL) {
                    328:            xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
                    329:             return (-1);
                    330:         }
                    331:     }
                    332:     if (ctxt->urlNr >= ctxt->urlMax) {
                    333:         ctxt->urlMax *= 2;
                    334:         ctxt->urlTab =
                    335:             (xmlChar * *) xmlRealloc(ctxt->urlTab,
                    336:                                       ctxt->urlMax *
                    337:                                       sizeof(ctxt->urlTab[0]));
                    338:         if (ctxt->urlTab == NULL) {
                    339:            xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
                    340:             return (-1);
                    341:         }
                    342:     }
                    343:     ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value);
                    344:     return (ctxt->urlNr++);
                    345: }
                    346: 
                    347: /**
                    348:  * xmlXIncludeURLPop:
                    349:  * @ctxt: the parser context
                    350:  *
                    351:  * Pops the top URL from the URL stack
                    352:  */
                    353: static void
                    354: xmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt)
                    355: {
                    356:     xmlChar * ret;
                    357: 
                    358:     if (ctxt->urlNr <= 0)
                    359:         return;
                    360:     ctxt->urlNr--;
                    361:     if (ctxt->urlNr > 0)
                    362:         ctxt->url = ctxt->urlTab[ctxt->urlNr - 1];
                    363:     else
                    364:         ctxt->url = NULL;
                    365:     ret = ctxt->urlTab[ctxt->urlNr];
                    366:     ctxt->urlTab[ctxt->urlNr] = NULL;
                    367:     if (ret != NULL)
                    368:        xmlFree(ret);
                    369: }
                    370: 
                    371: /**
                    372:  * xmlXIncludeFreeContext:
                    373:  * @ctxt: the XInclude context
                    374:  *
                    375:  * Free an XInclude context
                    376:  */
                    377: void
                    378: xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
                    379:     int i;
                    380: 
                    381: #ifdef DEBUG_XINCLUDE
                    382:     xmlGenericError(xmlGenericErrorContext, "Freeing context\n");
                    383: #endif
                    384:     if (ctxt == NULL)
                    385:        return;
                    386:     while (ctxt->urlNr > 0)
                    387:        xmlXIncludeURLPop(ctxt);
                    388:     if (ctxt->urlTab != NULL)
                    389:        xmlFree(ctxt->urlTab);
                    390:     for (i = 0;i < ctxt->incNr;i++) {
                    391:        if (ctxt->incTab[i] != NULL)
                    392:            xmlXIncludeFreeRef(ctxt->incTab[i]);
                    393:     }
                    394:     if (ctxt->txturlTab != NULL) {
                    395:        for (i = 0;i < ctxt->txtNr;i++) {
                    396:            if (ctxt->txturlTab[i] != NULL)
                    397:                xmlFree(ctxt->txturlTab[i]);
                    398:        }
                    399:     }
                    400:     if (ctxt->incTab != NULL)
                    401:        xmlFree(ctxt->incTab);
                    402:     if (ctxt->txtTab != NULL)
                    403:        xmlFree(ctxt->txtTab);
                    404:     if (ctxt->txturlTab != NULL)
                    405:        xmlFree(ctxt->txturlTab);
                    406:     if (ctxt->base != NULL) {
                    407:         xmlFree(ctxt->base);
                    408:     }
                    409:     xmlFree(ctxt);
                    410: }
                    411: 
                    412: /**
                    413:  * xmlXIncludeParseFile:
                    414:  * @ctxt:  the XInclude context
                    415:  * @URL:  the URL or file path
1.1.1.3 ! misho     416:  *
1.1       misho     417:  * parse a document for XInclude
                    418:  */
                    419: static xmlDocPtr
                    420: xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
                    421:     xmlDocPtr ret;
                    422:     xmlParserCtxtPtr pctxt;
                    423:     xmlParserInputPtr inputStream;
                    424: 
                    425:     xmlInitParser();
                    426: 
                    427:     pctxt = xmlNewParserCtxt();
                    428:     if (pctxt == NULL) {
                    429:        xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context");
                    430:        return(NULL);
                    431:     }
                    432: 
                    433:     /*
                    434:      * pass in the application data to the parser context.
                    435:      */
                    436:     pctxt->_private = ctxt->_private;
1.1.1.3 ! misho     437: 
1.1       misho     438:     /*
                    439:      * try to ensure that new documents included are actually
                    440:      * built with the same dictionary as the including document.
                    441:      */
                    442:     if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL)) {
                    443:        if (pctxt->dict != NULL)
                    444:             xmlDictFree(pctxt->dict);
                    445:        pctxt->dict = ctxt->doc->dict;
                    446:        xmlDictReference(pctxt->dict);
                    447:     }
                    448: 
                    449:     xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
1.1.1.3 ! misho     450: 
1.1       misho     451:     inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
                    452:     if (inputStream == NULL) {
                    453:        xmlFreeParserCtxt(pctxt);
                    454:        return(NULL);
                    455:     }
                    456: 
                    457:     inputPush(pctxt, inputStream);
                    458: 
                    459:     if (pctxt->directory == NULL)
                    460:         pctxt->directory = xmlParserGetDirectory(URL);
                    461: 
                    462:     pctxt->loadsubset |= XML_DETECT_IDS;
                    463: 
                    464:     xmlParseDocument(pctxt);
                    465: 
                    466:     if (pctxt->wellFormed) {
                    467:         ret = pctxt->myDoc;
                    468:     }
                    469:     else {
                    470:         ret = NULL;
                    471:        if (pctxt->myDoc != NULL)
                    472:            xmlFreeDoc(pctxt->myDoc);
                    473:         pctxt->myDoc = NULL;
                    474:     }
                    475:     xmlFreeParserCtxt(pctxt);
1.1.1.3 ! misho     476: 
1.1       misho     477:     return(ret);
                    478: }
                    479: 
                    480: /**
                    481:  * xmlXIncludeAddNode:
                    482:  * @ctxt:  the XInclude context
                    483:  * @cur:  the new node
1.1.1.3 ! misho     484:  *
1.1       misho     485:  * Add a new node to process to an XInclude context
                    486:  */
                    487: static int
                    488: xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
                    489:     xmlXIncludeRefPtr ref;
                    490:     xmlURIPtr uri;
                    491:     xmlChar *URL;
                    492:     xmlChar *fragment = NULL;
                    493:     xmlChar *href;
                    494:     xmlChar *parse;
                    495:     xmlChar *base;
                    496:     xmlChar *URI;
                    497:     int xml = 1, i; /* default Issue 64 */
                    498:     int local = 0;
                    499: 
                    500: 
                    501:     if (ctxt == NULL)
                    502:        return(-1);
                    503:     if (cur == NULL)
                    504:        return(-1);
                    505: 
                    506: #ifdef DEBUG_XINCLUDE
                    507:     xmlGenericError(xmlGenericErrorContext, "Add node\n");
                    508: #endif
                    509:     /*
                    510:      * read the attributes
                    511:      */
                    512:     href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
                    513:     if (href == NULL) {
                    514:        href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
1.1.1.3 ! misho     515:        if (href == NULL)
1.1       misho     516:            return(-1);
                    517:     }
                    518:     if ((href[0] == '#') || (href[0] == 0))
                    519:        local = 1;
                    520:     parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
                    521:     if (parse != NULL) {
                    522:        if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
                    523:            xml = 1;
                    524:        else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
                    525:            xml = 0;
                    526:        else {
                    527:            xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
                    528:                           "invalid value %s for 'parse'\n", parse);
                    529:            if (href != NULL)
                    530:                xmlFree(href);
                    531:            if (parse != NULL)
                    532:                xmlFree(parse);
                    533:            return(-1);
                    534:        }
                    535:     }
                    536: 
                    537:     /*
                    538:      * compute the URI
                    539:      */
                    540:     base = xmlNodeGetBase(ctxt->doc, cur);
                    541:     if (base == NULL) {
                    542:        URI = xmlBuildURI(href, ctxt->doc->URL);
                    543:     } else {
                    544:        URI = xmlBuildURI(href, base);
                    545:     }
                    546:     if (URI == NULL) {
                    547:        xmlChar *escbase;
                    548:        xmlChar *eschref;
                    549:        /*
                    550:         * Some escaping may be needed
                    551:         */
                    552:        escbase = xmlURIEscape(base);
                    553:        eschref = xmlURIEscape(href);
                    554:        URI = xmlBuildURI(eschref, escbase);
                    555:        if (escbase != NULL)
                    556:            xmlFree(escbase);
                    557:        if (eschref != NULL)
                    558:            xmlFree(eschref);
                    559:     }
                    560:     if (parse != NULL)
                    561:        xmlFree(parse);
                    562:     if (href != NULL)
                    563:        xmlFree(href);
                    564:     if (base != NULL)
                    565:        xmlFree(base);
                    566:     if (URI == NULL) {
                    567:        xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
                    568:                       "failed build URL\n", NULL);
                    569:        return(-1);
                    570:     }
                    571:     fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
                    572: 
                    573:     /*
                    574:      * Check the URL and remove any fragment identifier
                    575:      */
                    576:     uri = xmlParseURI((const char *)URI);
                    577:     if (uri == NULL) {
                    578:        xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
                    579:                       "invalid value URI %s\n", URI);
                    580:        if (fragment != NULL)
                    581:            xmlFree(fragment);
                    582:        xmlFree(URI);
                    583:        return(-1);
                    584:     }
                    585: 
                    586:     if (uri->fragment != NULL) {
                    587:         if (ctxt->legacy != 0) {
                    588:            if (fragment == NULL) {
                    589:                fragment = (xmlChar *) uri->fragment;
                    590:            } else {
                    591:                xmlFree(uri->fragment);
                    592:            }
                    593:        } else {
                    594:            xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
                    595:        "Invalid fragment identifier in URI %s use the xpointer attribute\n",
                    596:                            URI);
                    597:            if (fragment != NULL)
                    598:                xmlFree(fragment);
                    599:            xmlFreeURI(uri);
                    600:            xmlFree(URI);
                    601:            return(-1);
                    602:        }
                    603:        uri->fragment = NULL;
                    604:     }
                    605:     URL = xmlSaveUri(uri);
                    606:     xmlFreeURI(uri);
                    607:     xmlFree(URI);
                    608:     if (URL == NULL) {
                    609:        xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
                    610:                       "invalid value URI %s\n", URI);
                    611:        if (fragment != NULL)
                    612:            xmlFree(fragment);
                    613:        return(-1);
                    614:     }
                    615: 
                    616:     /*
                    617:      * If local and xml then we need a fragment
                    618:      */
                    619:     if ((local == 1) && (xml == 1) &&
                    620:         ((fragment == NULL) || (fragment[0] == 0))) {
                    621:        xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
                    622:                       "detected a local recursion with no xpointer in %s\n",
                    623:                       URL);
                    624:        if (fragment != NULL)
                    625:            xmlFree(fragment);
                    626:        return(-1);
                    627:     }
                    628: 
                    629:     /*
                    630:      * Check the URL against the stack for recursions
                    631:      */
                    632:     if ((!local) && (xml == 1)) {
                    633:        for (i = 0;i < ctxt->urlNr;i++) {
                    634:            if (xmlStrEqual(URL, ctxt->urlTab[i])) {
                    635:                xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
                    636:                               "detected a recursion in %s\n", URL);
                    637:                return(-1);
                    638:            }
                    639:        }
                    640:     }
                    641: 
                    642:     ref = xmlXIncludeNewRef(ctxt, URL, cur);
                    643:     if (ref == NULL) {
                    644:        return(-1);
                    645:     }
                    646:     ref->fragment = fragment;
                    647:     ref->doc = NULL;
                    648:     ref->xml = xml;
                    649:     ref->count = 1;
                    650:     xmlFree(URL);
                    651:     return(0);
                    652: }
                    653: 
                    654: /**
                    655:  * xmlXIncludeRecurseDoc:
                    656:  * @ctxt:  the XInclude context
                    657:  * @doc:  the new document
                    658:  * @url:  the associated URL
1.1.1.3 ! misho     659:  *
1.1       misho     660:  * The XInclude recursive nature is handled at this point.
                    661:  */
                    662: static void
                    663: xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
                    664:                      const xmlURL url ATTRIBUTE_UNUSED) {
                    665:     xmlXIncludeCtxtPtr newctxt;
                    666:     int i;
                    667: 
                    668:     /*
                    669:      * Avoid recursion in already substitued resources
                    670:     for (i = 0;i < ctxt->urlNr;i++) {
                    671:        if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
                    672:            return;
                    673:     }
                    674:      */
                    675: 
                    676: #ifdef DEBUG_XINCLUDE
                    677:     xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
                    678: #endif
                    679:     /*
                    680:      * Handle recursion here.
                    681:      */
                    682: 
                    683:     newctxt = xmlXIncludeNewContext(doc);
                    684:     if (newctxt != NULL) {
                    685:        /*
                    686:         * Copy the private user data
                    687:         */
1.1.1.3 ! misho     688:        newctxt->_private = ctxt->_private;
1.1       misho     689:        /*
                    690:         * Copy the existing document set
                    691:         */
                    692:        newctxt->incMax = ctxt->incMax;
                    693:        newctxt->incNr = ctxt->incNr;
                    694:         newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
                    695:                                          sizeof(newctxt->incTab[0]));
                    696:         if (newctxt->incTab == NULL) {
                    697:            xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
                    698:            xmlFree(newctxt);
                    699:            return;
                    700:        }
                    701:        /*
                    702:         * copy the urlTab
                    703:         */
                    704:        newctxt->urlMax = ctxt->urlMax;
                    705:        newctxt->urlNr = ctxt->urlNr;
                    706:        newctxt->urlTab = ctxt->urlTab;
                    707: 
                    708:        /*
                    709:         * Inherit the existing base
                    710:         */
                    711:        newctxt->base = xmlStrdup(ctxt->base);
                    712: 
                    713:        /*
                    714:         * Inherit the documents already in use by other includes
                    715:         */
                    716:        newctxt->incBase = ctxt->incNr;
                    717:        for (i = 0;i < ctxt->incNr;i++) {
                    718:            newctxt->incTab[i] = ctxt->incTab[i];
                    719:            newctxt->incTab[i]->count++; /* prevent the recursion from
                    720:                                            freeing it */
                    721:        }
                    722:        /*
                    723:         * The new context should also inherit the Parse Flags
                    724:         * (bug 132597)
                    725:         */
                    726:        newctxt->parseFlags = ctxt->parseFlags;
                    727:        xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
                    728:        for (i = 0;i < ctxt->incNr;i++) {
                    729:            newctxt->incTab[i]->count--;
                    730:            newctxt->incTab[i] = NULL;
                    731:        }
                    732: 
                    733:        /* urlTab may have been reallocated */
                    734:        ctxt->urlTab = newctxt->urlTab;
                    735:        ctxt->urlMax = newctxt->urlMax;
                    736: 
                    737:        newctxt->urlMax = 0;
                    738:        newctxt->urlNr = 0;
                    739:        newctxt->urlTab = NULL;
                    740: 
                    741:        xmlXIncludeFreeContext(newctxt);
                    742:     }
                    743: #ifdef DEBUG_XINCLUDE
                    744:     xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
                    745: #endif
                    746: }
                    747: 
                    748: /**
                    749:  * xmlXIncludeAddTxt:
                    750:  * @ctxt:  the XInclude context
                    751:  * @txt:  the new text node
                    752:  * @url:  the associated URL
1.1.1.3 ! misho     753:  *
1.1       misho     754:  * Add a new txtument to the list
                    755:  */
                    756: static void
                    757: xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
                    758: #ifdef DEBUG_XINCLUDE
                    759:     xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
                    760: #endif
                    761:     if (ctxt->txtMax == 0) {
                    762:        ctxt->txtMax = 4;
                    763:         ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
                    764:                                          sizeof(ctxt->txtTab[0]));
                    765:         if (ctxt->txtTab == NULL) {
                    766:            xmlXIncludeErrMemory(ctxt, NULL, "processing text");
                    767:            return;
                    768:        }
                    769:         ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
                    770:                                          sizeof(ctxt->txturlTab[0]));
                    771:         if (ctxt->txturlTab == NULL) {
                    772:            xmlXIncludeErrMemory(ctxt, NULL, "processing text");
                    773:            return;
                    774:        }
                    775:     }
                    776:     if (ctxt->txtNr >= ctxt->txtMax) {
                    777:        ctxt->txtMax *= 2;
                    778:         ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
                    779:                     ctxt->txtMax * sizeof(ctxt->txtTab[0]));
                    780:         if (ctxt->txtTab == NULL) {
                    781:            xmlXIncludeErrMemory(ctxt, NULL, "processing text");
                    782:            return;
                    783:        }
                    784:         ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
                    785:                     ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
                    786:         if (ctxt->txturlTab == NULL) {
                    787:            xmlXIncludeErrMemory(ctxt, NULL, "processing text");
                    788:            return;
                    789:        }
                    790:     }
                    791:     ctxt->txtTab[ctxt->txtNr] = txt;
                    792:     ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
                    793:     ctxt->txtNr++;
                    794: }
                    795: 
                    796: /************************************************************************
                    797:  *                                                                     *
                    798:  *                     Node copy with specific semantic                *
                    799:  *                                                                     *
                    800:  ************************************************************************/
                    801: 
                    802: static xmlNodePtr
                    803: xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                    804:                        xmlDocPtr source, xmlNodePtr elem);
                    805: 
                    806: /**
                    807:  * xmlXIncludeCopyNode:
                    808:  * @ctxt:  the XInclude context
                    809:  * @target:  the document target
                    810:  * @source:  the document source
                    811:  * @elem:  the element
1.1.1.3 ! misho     812:  *
1.1       misho     813:  * Make a copy of the node while preserving the XInclude semantic
                    814:  * of the Infoset copy
                    815:  */
                    816: static xmlNodePtr
                    817: xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                    818:                    xmlDocPtr source, xmlNodePtr elem) {
                    819:     xmlNodePtr result = NULL;
                    820: 
                    821:     if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
                    822:        (elem == NULL))
                    823:        return(NULL);
                    824:     if (elem->type == XML_DTD_NODE)
                    825:        return(NULL);
                    826:     if (elem->type == XML_DOCUMENT_NODE)
                    827:        result = xmlXIncludeCopyNodeList(ctxt, target, source, elem->children);
                    828:     else
                    829:         result = xmlDocCopyNode(elem, target, 1);
                    830:     return(result);
                    831: }
                    832: 
                    833: /**
                    834:  * xmlXIncludeCopyNodeList:
                    835:  * @ctxt:  the XInclude context
                    836:  * @target:  the document target
                    837:  * @source:  the document source
                    838:  * @elem:  the element list
1.1.1.3 ! misho     839:  *
1.1       misho     840:  * Make a copy of the node list while preserving the XInclude semantic
                    841:  * of the Infoset copy
                    842:  */
                    843: static xmlNodePtr
                    844: xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                    845:                        xmlDocPtr source, xmlNodePtr elem) {
                    846:     xmlNodePtr cur, res, result = NULL, last = NULL;
                    847: 
                    848:     if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
                    849:        (elem == NULL))
                    850:        return(NULL);
                    851:     cur = elem;
                    852:     while (cur != NULL) {
                    853:        res = xmlXIncludeCopyNode(ctxt, target, source, cur);
                    854:        if (res != NULL) {
                    855:            if (result == NULL) {
                    856:                result = last = res;
                    857:            } else {
                    858:                last->next = res;
                    859:                res->prev = last;
                    860:                last = res;
                    861:            }
                    862:        }
                    863:        cur = cur->next;
                    864:     }
                    865:     return(result);
                    866: }
                    867: 
                    868: /**
                    869:  * xmlXIncludeGetNthChild:
                    870:  * @cur:  the node
                    871:  * @no:  the child number
                    872:  *
                    873:  * Returns the @n'th element child of @cur or NULL
                    874:  */
                    875: static xmlNodePtr
                    876: xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
                    877:     int i;
1.1.1.3 ! misho     878:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
        !           879:         return(NULL);
1.1       misho     880:     cur = cur->children;
                    881:     for (i = 0;i <= no;cur = cur->next) {
1.1.1.3 ! misho     882:        if (cur == NULL)
1.1       misho     883:            return(cur);
                    884:        if ((cur->type == XML_ELEMENT_NODE) ||
                    885:            (cur->type == XML_DOCUMENT_NODE) ||
                    886:            (cur->type == XML_HTML_DOCUMENT_NODE)) {
                    887:            i++;
                    888:            if (i == no)
                    889:                break;
                    890:        }
                    891:     }
                    892:     return(cur);
                    893: }
                    894: 
                    895: xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
                    896: /**
                    897:  * xmlXIncludeCopyRange:
                    898:  * @ctxt:  the XInclude context
                    899:  * @target:  the document target
                    900:  * @source:  the document source
                    901:  * @obj:  the XPointer result from the evaluation.
                    902:  *
                    903:  * Build a node list tree copy of the XPointer result.
                    904:  *
                    905:  * Returns an xmlNodePtr list or NULL.
                    906:  *         The caller has to free the node tree.
                    907:  */
                    908: static xmlNodePtr
                    909: xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                    910:                        xmlDocPtr source, xmlXPathObjectPtr range) {
                    911:     /* pointers to generated nodes */
                    912:     xmlNodePtr list = NULL, last = NULL, listParent = NULL;
                    913:     xmlNodePtr tmp, tmp2;
                    914:     /* pointers to traversal nodes */
                    915:     xmlNodePtr start, cur, end;
                    916:     int index1, index2;
                    917:     int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
                    918: 
                    919:     if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
                    920:        (range == NULL))
                    921:        return(NULL);
                    922:     if (range->type != XPATH_RANGE)
                    923:        return(NULL);
                    924:     start = (xmlNodePtr) range->user;
                    925: 
1.1.1.3 ! misho     926:     if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
1.1       misho     927:        return(NULL);
                    928:     end = range->user2;
                    929:     if (end == NULL)
                    930:        return(xmlDocCopyNode(start, target, 1));
1.1.1.3 ! misho     931:     if (end->type == XML_NAMESPACE_DECL)
        !           932:         return(NULL);
1.1       misho     933: 
                    934:     cur = start;
                    935:     index1 = range->index;
                    936:     index2 = range->index2;
                    937:     /*
                    938:      * level is depth of the current node under consideration
                    939:      * list is the pointer to the root of the output tree
                    940:      * listParent is a pointer to the parent of output tree (within
                    941:        the included file) in case we need to add another level
                    942:      * last is a pointer to the last node added to the output tree
                    943:      * lastLevel is the depth of last (relative to the root)
                    944:      */
                    945:     while (cur != NULL) {
                    946:        /*
                    947:         * Check if our output tree needs a parent
                    948:         */
                    949:        if (level < 0) {
                    950:            while (level < 0) {
                    951:                /* copy must include namespaces and properties */
                    952:                tmp2 = xmlDocCopyNode(listParent, target, 2);
                    953:                xmlAddChild(tmp2, list);
                    954:                list = tmp2;
                    955:                listParent = listParent->parent;
                    956:                level++;
                    957:            }
                    958:            last = list;
                    959:            lastLevel = 0;
                    960:        }
                    961:        /*
                    962:         * Check whether we need to change our insertion point
                    963:         */
                    964:        while (level < lastLevel) {
                    965:            last = last->parent;
                    966:            lastLevel --;
                    967:        }
                    968:        if (cur == end) {       /* Are we at the end of the range? */
                    969:            if (cur->type == XML_TEXT_NODE) {
                    970:                const xmlChar *content = cur->content;
                    971:                int len;
                    972: 
                    973:                if (content == NULL) {
                    974:                    tmp = xmlNewTextLen(NULL, 0);
                    975:                } else {
                    976:                    len = index2;
                    977:                    if ((cur == start) && (index1 > 1)) {
                    978:                        content += (index1 - 1);
                    979:                        len -= (index1 - 1);
                    980:                    } else {
                    981:                        len = index2;
                    982:                    }
                    983:                    tmp = xmlNewTextLen(content, len);
                    984:                }
                    985:                /* single sub text node selection */
                    986:                if (list == NULL)
                    987:                    return(tmp);
                    988:                /* prune and return full set */
                    989:                if (level == lastLevel)
                    990:                    xmlAddNextSibling(last, tmp);
1.1.1.3 ! misho     991:                else
1.1       misho     992:                    xmlAddChild(last, tmp);
                    993:                return(list);
                    994:            } else {    /* ending node not a text node */
                    995:                endLevel = level;       /* remember the level of the end node */
                    996:                endFlag = 1;
                    997:                /* last node - need to take care of properties + namespaces */
                    998:                tmp = xmlDocCopyNode(cur, target, 2);
                    999:                if (list == NULL) {
                   1000:                    list = tmp;
                   1001:                    listParent = cur->parent;
                   1002:                } else {
                   1003:                    if (level == lastLevel)
                   1004:                        xmlAddNextSibling(last, tmp);
                   1005:                    else {
                   1006:                        xmlAddChild(last, tmp);
                   1007:                        lastLevel = level;
                   1008:                    }
                   1009:                }
                   1010:                last = tmp;
                   1011: 
                   1012:                if (index2 > 1) {
                   1013:                    end = xmlXIncludeGetNthChild(cur, index2 - 1);
                   1014:                    index2 = 0;
                   1015:                }
                   1016:                if ((cur == start) && (index1 > 1)) {
                   1017:                    cur = xmlXIncludeGetNthChild(cur, index1 - 1);
                   1018:                    index1 = 0;
                   1019:                }  else {
                   1020:                    cur = cur->children;
                   1021:                }
                   1022:                level++;        /* increment level to show change */
                   1023:                /*
                   1024:                 * Now gather the remaining nodes from cur to end
                   1025:                 */
                   1026:                continue;       /* while */
                   1027:            }
                   1028:        } else if (cur == start) {      /* Not at the end, are we at start? */
                   1029:            if ((cur->type == XML_TEXT_NODE) ||
                   1030:                (cur->type == XML_CDATA_SECTION_NODE)) {
                   1031:                const xmlChar *content = cur->content;
                   1032: 
                   1033:                if (content == NULL) {
                   1034:                    tmp = xmlNewTextLen(NULL, 0);
                   1035:                } else {
                   1036:                    if (index1 > 1) {
                   1037:                        content += (index1 - 1);
                   1038:                        index1 = 0;
                   1039:                    }
                   1040:                    tmp = xmlNewText(content);
                   1041:                }
                   1042:                last = list = tmp;
                   1043:                listParent = cur->parent;
                   1044:            } else {            /* Not text node */
                   1045:                /*
                   1046:                 * start of the range - need to take care of
                   1047:                 * properties and namespaces
                   1048:                 */
                   1049:                tmp = xmlDocCopyNode(cur, target, 2);
                   1050:                list = last = tmp;
                   1051:                listParent = cur->parent;
                   1052:                if (index1 > 1) {       /* Do we need to position? */
                   1053:                    cur = xmlXIncludeGetNthChild(cur, index1 - 1);
                   1054:                    level = lastLevel = 1;
                   1055:                    index1 = 0;
                   1056:                    /*
                   1057:                     * Now gather the remaining nodes from cur to end
                   1058:                     */
                   1059:                    continue; /* while */
                   1060:                }
                   1061:            }
                   1062:        } else {
                   1063:            tmp = NULL;
                   1064:            switch (cur->type) {
                   1065:                case XML_DTD_NODE:
                   1066:                case XML_ELEMENT_DECL:
                   1067:                case XML_ATTRIBUTE_DECL:
                   1068:                case XML_ENTITY_NODE:
                   1069:                    /* Do not copy DTD informations */
                   1070:                    break;
                   1071:                case XML_ENTITY_DECL:
                   1072:                    /* handle crossing entities -> stack needed */
                   1073:                    break;
                   1074:                case XML_XINCLUDE_START:
                   1075:                case XML_XINCLUDE_END:
                   1076:                    /* don't consider it part of the tree content */
                   1077:                    break;
                   1078:                case XML_ATTRIBUTE_NODE:
                   1079:                    /* Humm, should not happen ! */
                   1080:                    break;
                   1081:                default:
                   1082:                    /*
                   1083:                     * Middle of the range - need to take care of
                   1084:                     * properties and namespaces
                   1085:                     */
                   1086:                    tmp = xmlDocCopyNode(cur, target, 2);
                   1087:                    break;
                   1088:            }
                   1089:            if (tmp != NULL) {
                   1090:                if (level == lastLevel)
                   1091:                    xmlAddNextSibling(last, tmp);
                   1092:                else {
                   1093:                    xmlAddChild(last, tmp);
                   1094:                    lastLevel = level;
                   1095:                }
                   1096:                last = tmp;
                   1097:            }
                   1098:        }
                   1099:        /*
                   1100:         * Skip to next node in document order
                   1101:         */
                   1102:        cur = xmlXPtrAdvanceNode(cur, &level);
                   1103:        if (endFlag && (level >= endLevel))
                   1104:            break;
                   1105:     }
                   1106:     return(list);
                   1107: }
                   1108: 
                   1109: /**
                   1110:  * xmlXIncludeBuildNodeList:
                   1111:  * @ctxt:  the XInclude context
                   1112:  * @target:  the document target
                   1113:  * @source:  the document source
                   1114:  * @obj:  the XPointer result from the evaluation.
                   1115:  *
                   1116:  * Build a node list tree copy of the XPointer result.
                   1117:  * This will drop Attributes and Namespace declarations.
                   1118:  *
                   1119:  * Returns an xmlNodePtr list or NULL.
                   1120:  *         the caller has to free the node tree.
                   1121:  */
                   1122: static xmlNodePtr
                   1123: xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
                   1124:                        xmlDocPtr source, xmlXPathObjectPtr obj) {
                   1125:     xmlNodePtr list = NULL, last = NULL;
                   1126:     int i;
                   1127: 
                   1128:     if (source == NULL)
                   1129:        source = ctxt->doc;
                   1130:     if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
                   1131:        (obj == NULL))
                   1132:        return(NULL);
                   1133:     switch (obj->type) {
                   1134:         case XPATH_NODESET: {
                   1135:            xmlNodeSetPtr set = obj->nodesetval;
                   1136:            if (set == NULL)
                   1137:                return(NULL);
                   1138:            for (i = 0;i < set->nodeNr;i++) {
                   1139:                if (set->nodeTab[i] == NULL)
                   1140:                    continue;
                   1141:                switch (set->nodeTab[i]->type) {
                   1142:                    case XML_TEXT_NODE:
                   1143:                    case XML_CDATA_SECTION_NODE:
                   1144:                    case XML_ELEMENT_NODE:
                   1145:                    case XML_ENTITY_REF_NODE:
                   1146:                    case XML_ENTITY_NODE:
                   1147:                    case XML_PI_NODE:
                   1148:                    case XML_COMMENT_NODE:
                   1149:                    case XML_DOCUMENT_NODE:
                   1150:                    case XML_HTML_DOCUMENT_NODE:
                   1151: #ifdef LIBXML_DOCB_ENABLED
                   1152:                    case XML_DOCB_DOCUMENT_NODE:
                   1153: #endif
                   1154:                    case XML_XINCLUDE_END:
                   1155:                        break;
                   1156:                    case XML_XINCLUDE_START: {
                   1157:                        xmlNodePtr tmp, cur = set->nodeTab[i];
                   1158: 
                   1159:                        cur = cur->next;
                   1160:                        while (cur != NULL) {
                   1161:                            switch(cur->type) {
                   1162:                                case XML_TEXT_NODE:
                   1163:                                case XML_CDATA_SECTION_NODE:
                   1164:                                case XML_ELEMENT_NODE:
                   1165:                                case XML_ENTITY_REF_NODE:
                   1166:                                case XML_ENTITY_NODE:
                   1167:                                case XML_PI_NODE:
                   1168:                                case XML_COMMENT_NODE:
                   1169:                                    tmp = xmlXIncludeCopyNode(ctxt, target,
                   1170:                                                              source, cur);
                   1171:                                    if (last == NULL) {
                   1172:                                        list = last = tmp;
                   1173:                                    } else {
                   1174:                                        xmlAddNextSibling(last, tmp);
                   1175:                                        last = tmp;
                   1176:                                    }
                   1177:                                    cur = cur->next;
                   1178:                                    continue;
                   1179:                                default:
                   1180:                                    break;
                   1181:                            }
                   1182:                            break;
                   1183:                        }
                   1184:                        continue;
                   1185:                    }
                   1186:                    case XML_ATTRIBUTE_NODE:
                   1187:                    case XML_NAMESPACE_DECL:
                   1188:                    case XML_DOCUMENT_TYPE_NODE:
                   1189:                    case XML_DOCUMENT_FRAG_NODE:
                   1190:                    case XML_NOTATION_NODE:
                   1191:                    case XML_DTD_NODE:
                   1192:                    case XML_ELEMENT_DECL:
                   1193:                    case XML_ATTRIBUTE_DECL:
                   1194:                    case XML_ENTITY_DECL:
                   1195:                        continue; /* for */
                   1196:                }
                   1197:                if (last == NULL)
                   1198:                    list = last = xmlXIncludeCopyNode(ctxt, target, source,
                   1199:                                                      set->nodeTab[i]);
                   1200:                else {
                   1201:                    xmlAddNextSibling(last,
                   1202:                            xmlXIncludeCopyNode(ctxt, target, source,
                   1203:                                                set->nodeTab[i]));
                   1204:                    if (last->next != NULL)
                   1205:                        last = last->next;
                   1206:                }
                   1207:            }
                   1208:            break;
                   1209:        }
                   1210:        case XPATH_LOCATIONSET: {
                   1211:            xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
                   1212:            if (set == NULL)
                   1213:                return(NULL);
                   1214:            for (i = 0;i < set->locNr;i++) {
                   1215:                if (last == NULL)
                   1216:                    list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
                   1217:                                                          set->locTab[i]);
                   1218:                else
                   1219:                    xmlAddNextSibling(last,
                   1220:                            xmlXIncludeCopyXPointer(ctxt, target, source,
                   1221:                                                    set->locTab[i]));
                   1222:                if (last != NULL) {
                   1223:                    while (last->next != NULL)
                   1224:                        last = last->next;
                   1225:                }
                   1226:            }
                   1227:            break;
                   1228:        }
                   1229: #ifdef LIBXML_XPTR_ENABLED
                   1230:        case XPATH_RANGE:
                   1231:            return(xmlXIncludeCopyRange(ctxt, target, source, obj));
                   1232: #endif
                   1233:        case XPATH_POINT:
                   1234:            /* points are ignored in XInclude */
                   1235:            break;
                   1236:        default:
                   1237:            break;
                   1238:     }
                   1239:     return(list);
                   1240: }
                   1241: /************************************************************************
                   1242:  *                                                                     *
                   1243:  *                     XInclude I/O handling                           *
                   1244:  *                                                                     *
                   1245:  ************************************************************************/
                   1246: 
                   1247: typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
                   1248: typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
                   1249: struct _xmlXIncludeMergeData {
                   1250:     xmlDocPtr doc;
                   1251:     xmlXIncludeCtxtPtr ctxt;
                   1252: };
                   1253: 
                   1254: /**
                   1255:  * xmlXIncludeMergeOneEntity:
                   1256:  * @ent: the entity
                   1257:  * @doc:  the including doc
                   1258:  * @nr: the entity name
                   1259:  *
                   1260:  * Inplements the merge of one entity
                   1261:  */
                   1262: static void
                   1263: xmlXIncludeMergeEntity(xmlEntityPtr ent, xmlXIncludeMergeDataPtr data,
                   1264:                       xmlChar *name ATTRIBUTE_UNUSED) {
                   1265:     xmlEntityPtr ret, prev;
                   1266:     xmlDocPtr doc;
                   1267:     xmlXIncludeCtxtPtr ctxt;
                   1268: 
                   1269:     if ((ent == NULL) || (data == NULL))
                   1270:        return;
                   1271:     ctxt = data->ctxt;
                   1272:     doc = data->doc;
                   1273:     if ((ctxt == NULL) || (doc == NULL))
                   1274:        return;
                   1275:     switch (ent->etype) {
                   1276:         case XML_INTERNAL_PARAMETER_ENTITY:
                   1277:         case XML_EXTERNAL_PARAMETER_ENTITY:
                   1278:         case XML_INTERNAL_PREDEFINED_ENTITY:
                   1279:            return;
                   1280:         case XML_INTERNAL_GENERAL_ENTITY:
                   1281:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                   1282:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   1283:            break;
                   1284:     }
                   1285:     ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
                   1286:                          ent->SystemID, ent->content);
                   1287:     if (ret != NULL) {
                   1288:        if (ent->URI != NULL)
                   1289:            ret->URI = xmlStrdup(ent->URI);
                   1290:     } else {
                   1291:        prev = xmlGetDocEntity(doc, ent->name);
                   1292:        if (prev != NULL) {
                   1293:            if (ent->etype != prev->etype)
                   1294:                goto error;
1.1.1.3 ! misho    1295: 
1.1       misho    1296:            if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
                   1297:                if (!xmlStrEqual(ent->SystemID, prev->SystemID))
                   1298:                    goto error;
                   1299:            } else if ((ent->ExternalID != NULL) &&
                   1300:                       (prev->ExternalID != NULL)) {
                   1301:                if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
                   1302:                    goto error;
                   1303:            } else if ((ent->content != NULL) && (prev->content != NULL)) {
                   1304:                if (!xmlStrEqual(ent->content, prev->content))
                   1305:                    goto error;
                   1306:            } else {
                   1307:                goto error;
                   1308:            }
                   1309: 
                   1310:        }
                   1311:     }
                   1312:     return;
                   1313: error:
                   1314:     switch (ent->etype) {
                   1315:         case XML_INTERNAL_PARAMETER_ENTITY:
                   1316:         case XML_EXTERNAL_PARAMETER_ENTITY:
                   1317:         case XML_INTERNAL_PREDEFINED_ENTITY:
                   1318:         case XML_INTERNAL_GENERAL_ENTITY:
                   1319:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                   1320:            return;
                   1321:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   1322:            break;
                   1323:     }
                   1324:     xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
                   1325:                    "mismatch in redefinition of entity %s\n",
                   1326:                   ent->name);
                   1327: }
                   1328: 
                   1329: /**
                   1330:  * xmlXIncludeMergeEntities:
                   1331:  * @ctxt: an XInclude context
                   1332:  * @doc:  the including doc
                   1333:  * @from:  the included doc
                   1334:  *
                   1335:  * Inplements the entity merge
                   1336:  *
                   1337:  * Returns 0 if merge succeeded, -1 if some processing failed
                   1338:  */
                   1339: static int
                   1340: xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
                   1341:                         xmlDocPtr from) {
                   1342:     xmlNodePtr cur;
                   1343:     xmlDtdPtr target, source;
                   1344: 
                   1345:     if (ctxt == NULL)
                   1346:        return(-1);
                   1347: 
                   1348:     if ((from == NULL) || (from->intSubset == NULL))
                   1349:        return(0);
                   1350: 
                   1351:     target = doc->intSubset;
                   1352:     if (target == NULL) {
                   1353:        cur = xmlDocGetRootElement(doc);
                   1354:        if (cur == NULL)
                   1355:            return(-1);
                   1356:         target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
                   1357:        if (target == NULL)
                   1358:            return(-1);
                   1359:     }
                   1360: 
                   1361:     source = from->intSubset;
                   1362:     if ((source != NULL) && (source->entities != NULL)) {
                   1363:        xmlXIncludeMergeData data;
                   1364: 
                   1365:        data.ctxt = ctxt;
                   1366:        data.doc = doc;
                   1367: 
                   1368:        xmlHashScan((xmlHashTablePtr) source->entities,
                   1369:                    (xmlHashScanner) xmlXIncludeMergeEntity, &data);
                   1370:     }
                   1371:     source = from->extSubset;
                   1372:     if ((source != NULL) && (source->entities != NULL)) {
                   1373:        xmlXIncludeMergeData data;
                   1374: 
                   1375:        data.ctxt = ctxt;
                   1376:        data.doc = doc;
                   1377: 
                   1378:        /*
                   1379:         * don't duplicate existing stuff when external subsets are the same
                   1380:         */
                   1381:        if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
                   1382:            (!xmlStrEqual(target->SystemID, source->SystemID))) {
                   1383:            xmlHashScan((xmlHashTablePtr) source->entities,
                   1384:                        (xmlHashScanner) xmlXIncludeMergeEntity, &data);
                   1385:        }
                   1386:     }
                   1387:     return(0);
                   1388: }
                   1389: 
                   1390: /**
                   1391:  * xmlXIncludeLoadDoc:
                   1392:  * @ctxt:  the XInclude context
                   1393:  * @url:  the associated URL
                   1394:  * @nr:  the xinclude node number
1.1.1.3 ! misho    1395:  *
1.1       misho    1396:  * Load the document, and store the result in the XInclude context
                   1397:  *
                   1398:  * Returns 0 in case of success, -1 in case of failure
                   1399:  */
                   1400: static int
                   1401: xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
                   1402:     xmlDocPtr doc;
                   1403:     xmlURIPtr uri;
                   1404:     xmlChar *URL;
                   1405:     xmlChar *fragment = NULL;
                   1406:     int i = 0;
                   1407: #ifdef LIBXML_XPTR_ENABLED
                   1408:     int saveFlags;
                   1409: #endif
                   1410: 
                   1411: #ifdef DEBUG_XINCLUDE
                   1412:     xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
                   1413: #endif
                   1414:     /*
                   1415:      * Check the URL and remove any fragment identifier
                   1416:      */
                   1417:     uri = xmlParseURI((const char *)url);
                   1418:     if (uri == NULL) {
1.1.1.3 ! misho    1419:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1420:                       XML_XINCLUDE_HREF_URI,
                   1421:                       "invalid value URI %s\n", url);
                   1422:        return(-1);
                   1423:     }
                   1424:     if (uri->fragment != NULL) {
                   1425:        fragment = (xmlChar *) uri->fragment;
                   1426:        uri->fragment = NULL;
                   1427:     }
                   1428:     if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
                   1429:         (ctxt->incTab[nr]->fragment != NULL)) {
                   1430:        if (fragment != NULL) xmlFree(fragment);
                   1431:        fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
                   1432:     }
                   1433:     URL = xmlSaveUri(uri);
                   1434:     xmlFreeURI(uri);
                   1435:     if (URL == NULL) {
                   1436:         if (ctxt->incTab != NULL)
1.1.1.3 ! misho    1437:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1438:                           XML_XINCLUDE_HREF_URI,
                   1439:                           "invalid value URI %s\n", url);
                   1440:        else
                   1441:            xmlXIncludeErr(ctxt, NULL,
                   1442:                           XML_XINCLUDE_HREF_URI,
                   1443:                           "invalid value URI %s\n", url);
                   1444:        if (fragment != NULL)
                   1445:            xmlFree(fragment);
                   1446:        return(-1);
                   1447:     }
                   1448: 
                   1449:     /*
                   1450:      * Handling of references to the local document are done
                   1451:      * directly through ctxt->doc.
                   1452:      */
                   1453:     if ((URL[0] == 0) || (URL[0] == '#') ||
                   1454:        ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
                   1455:        doc = NULL;
                   1456:         goto loaded;
                   1457:     }
                   1458: 
                   1459:     /*
                   1460:      * Prevent reloading twice the document.
                   1461:      */
                   1462:     for (i = 0; i < ctxt->incNr; i++) {
                   1463:        if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
                   1464:            (ctxt->incTab[i]->doc != NULL)) {
                   1465:            doc = ctxt->incTab[i]->doc;
                   1466: #ifdef DEBUG_XINCLUDE
                   1467:            printf("Already loaded %s\n", URL);
                   1468: #endif
                   1469:            goto loaded;
                   1470:        }
                   1471:     }
                   1472: 
                   1473:     /*
                   1474:      * Load it.
                   1475:      */
                   1476: #ifdef DEBUG_XINCLUDE
                   1477:     printf("loading %s\n", URL);
                   1478: #endif
                   1479: #ifdef LIBXML_XPTR_ENABLED
                   1480:     /*
                   1481:      * If this is an XPointer evaluation, we want to assure that
                   1482:      * all entities have been resolved prior to processing the
                   1483:      * referenced document
                   1484:      */
                   1485:     saveFlags = ctxt->parseFlags;
                   1486:     if (fragment != NULL) {    /* if this is an XPointer eval */
                   1487:        ctxt->parseFlags |= XML_PARSE_NOENT;
                   1488:     }
                   1489: #endif
                   1490: 
                   1491:     doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
                   1492: #ifdef LIBXML_XPTR_ENABLED
                   1493:     ctxt->parseFlags = saveFlags;
                   1494: #endif
                   1495:     if (doc == NULL) {
                   1496:        xmlFree(URL);
                   1497:        if (fragment != NULL)
                   1498:            xmlFree(fragment);
                   1499:        return(-1);
                   1500:     }
                   1501:     ctxt->incTab[nr]->doc = doc;
                   1502:     /*
                   1503:      * It's possible that the requested URL has been mapped to a
                   1504:      * completely different location (e.g. through a catalog entry).
                   1505:      * To check for this, we compare the URL with that of the doc
                   1506:      * and change it if they disagree (bug 146988).
                   1507:      */
                   1508:    if (!xmlStrEqual(URL, doc->URL)) {
                   1509:        xmlFree(URL);
                   1510:        URL = xmlStrdup(doc->URL);
                   1511:    }
                   1512:     for (i = nr + 1; i < ctxt->incNr; i++) {
                   1513:        if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
                   1514:            ctxt->incTab[nr]->count++;
                   1515: #ifdef DEBUG_XINCLUDE
                   1516:            printf("Increasing %s count since reused\n", URL);
                   1517: #endif
                   1518:             break;
                   1519:        }
                   1520:     }
                   1521: 
                   1522:     /*
                   1523:      * Make sure we have all entities fixed up
                   1524:      */
                   1525:     xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
                   1526: 
                   1527:     /*
                   1528:      * We don't need the DTD anymore, free up space
                   1529:     if (doc->intSubset != NULL) {
                   1530:        xmlUnlinkNode((xmlNodePtr) doc->intSubset);
                   1531:        xmlFreeNode((xmlNodePtr) doc->intSubset);
                   1532:        doc->intSubset = NULL;
                   1533:     }
                   1534:     if (doc->extSubset != NULL) {
                   1535:        xmlUnlinkNode((xmlNodePtr) doc->extSubset);
                   1536:        xmlFreeNode((xmlNodePtr) doc->extSubset);
                   1537:        doc->extSubset = NULL;
                   1538:     }
                   1539:      */
                   1540:     xmlXIncludeRecurseDoc(ctxt, doc, URL);
                   1541: 
                   1542: loaded:
                   1543:     if (fragment == NULL) {
                   1544:        /*
                   1545:         * Add the top children list as the replacement copy.
                   1546:         */
                   1547:        if (doc == NULL)
                   1548:        {
                   1549:            /* Hopefully a DTD declaration won't be copied from
                   1550:             * the same document */
                   1551:            ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
                   1552:        } else {
                   1553:            ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
                   1554:                                                       doc, doc->children);
                   1555:        }
1.1.1.3 ! misho    1556:     }
1.1       misho    1557: #ifdef LIBXML_XPTR_ENABLED
                   1558:     else {
                   1559:        /*
                   1560:         * Computes the XPointer expression and make a copy used
                   1561:         * as the replacement copy.
                   1562:         */
                   1563:        xmlXPathObjectPtr xptr;
                   1564:        xmlXPathContextPtr xptrctxt;
                   1565:        xmlNodeSetPtr set;
                   1566: 
                   1567:        if (doc == NULL) {
                   1568:            xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
                   1569:                                         NULL);
                   1570:        } else {
                   1571:            xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
                   1572:        }
                   1573:        if (xptrctxt == NULL) {
1.1.1.3 ! misho    1574:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1575:                           XML_XINCLUDE_XPTR_FAILED,
                   1576:                           "could not create XPointer context\n", NULL);
                   1577:            xmlFree(URL);
                   1578:            xmlFree(fragment);
                   1579:            return(-1);
                   1580:        }
                   1581:        xptr = xmlXPtrEval(fragment, xptrctxt);
                   1582:        if (xptr == NULL) {
                   1583:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                   1584:                           XML_XINCLUDE_XPTR_FAILED,
                   1585:                           "XPointer evaluation failed: #%s\n",
                   1586:                           fragment);
                   1587:            xmlXPathFreeContext(xptrctxt);
                   1588:            xmlFree(URL);
                   1589:            xmlFree(fragment);
                   1590:            return(-1);
                   1591:        }
                   1592:        switch (xptr->type) {
                   1593:            case XPATH_UNDEFINED:
                   1594:            case XPATH_BOOLEAN:
                   1595:            case XPATH_NUMBER:
                   1596:            case XPATH_STRING:
                   1597:            case XPATH_POINT:
                   1598:            case XPATH_USERS:
                   1599:            case XPATH_XSLT_TREE:
1.1.1.3 ! misho    1600:                xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1601:                               XML_XINCLUDE_XPTR_RESULT,
                   1602:                               "XPointer is not a range: #%s\n",
                   1603:                               fragment);
                   1604:                xmlXPathFreeContext(xptrctxt);
                   1605:                xmlFree(URL);
                   1606:                xmlFree(fragment);
                   1607:                return(-1);
                   1608:            case XPATH_NODESET:
                   1609:                if ((xptr->nodesetval == NULL) ||
                   1610:                    (xptr->nodesetval->nodeNr <= 0)) {
                   1611:                    xmlXPathFreeContext(xptrctxt);
                   1612:                    xmlFree(URL);
                   1613:                    xmlFree(fragment);
                   1614:                    return(-1);
                   1615:                }
                   1616: 
                   1617:            case XPATH_RANGE:
                   1618:            case XPATH_LOCATIONSET:
                   1619:                break;
                   1620:        }
                   1621:        set = xptr->nodesetval;
                   1622:        if (set != NULL) {
                   1623:            for (i = 0;i < set->nodeNr;i++) {
                   1624:                if (set->nodeTab[i] == NULL)
                   1625:                    continue;
                   1626:                switch (set->nodeTab[i]->type) {
                   1627:                    case XML_ELEMENT_NODE:
                   1628:                    case XML_TEXT_NODE:
                   1629:                    case XML_CDATA_SECTION_NODE:
                   1630:                    case XML_ENTITY_REF_NODE:
                   1631:                    case XML_ENTITY_NODE:
                   1632:                    case XML_PI_NODE:
                   1633:                    case XML_COMMENT_NODE:
                   1634:                    case XML_DOCUMENT_NODE:
                   1635:                    case XML_HTML_DOCUMENT_NODE:
                   1636: #ifdef LIBXML_DOCB_ENABLED
                   1637:                    case XML_DOCB_DOCUMENT_NODE:
                   1638: #endif
                   1639:                        continue;
                   1640: 
                   1641:                    case XML_ATTRIBUTE_NODE:
1.1.1.3 ! misho    1642:                        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1643:                                       XML_XINCLUDE_XPTR_RESULT,
                   1644:                                       "XPointer selects an attribute: #%s\n",
                   1645:                                       fragment);
                   1646:                        set->nodeTab[i] = NULL;
                   1647:                        continue;
                   1648:                    case XML_NAMESPACE_DECL:
1.1.1.3 ! misho    1649:                        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1650:                                       XML_XINCLUDE_XPTR_RESULT,
                   1651:                                       "XPointer selects a namespace: #%s\n",
                   1652:                                       fragment);
                   1653:                        set->nodeTab[i] = NULL;
                   1654:                        continue;
                   1655:                    case XML_DOCUMENT_TYPE_NODE:
                   1656:                    case XML_DOCUMENT_FRAG_NODE:
                   1657:                    case XML_NOTATION_NODE:
                   1658:                    case XML_DTD_NODE:
                   1659:                    case XML_ELEMENT_DECL:
                   1660:                    case XML_ATTRIBUTE_DECL:
                   1661:                    case XML_ENTITY_DECL:
                   1662:                    case XML_XINCLUDE_START:
                   1663:                    case XML_XINCLUDE_END:
1.1.1.3 ! misho    1664:                        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1665:                                       XML_XINCLUDE_XPTR_RESULT,
                   1666:                                   "XPointer selects unexpected nodes: #%s\n",
                   1667:                                       fragment);
                   1668:                        set->nodeTab[i] = NULL;
                   1669:                        set->nodeTab[i] = NULL;
                   1670:                        continue; /* for */
                   1671:                }
                   1672:            }
                   1673:        }
                   1674:        if (doc == NULL) {
                   1675:            ctxt->incTab[nr]->xptr = xptr;
                   1676:            ctxt->incTab[nr]->inc = NULL;
                   1677:        } else {
                   1678:            ctxt->incTab[nr]->inc =
                   1679:                xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
                   1680:            xmlXPathFreeObject(xptr);
                   1681:        }
                   1682:        xmlXPathFreeContext(xptrctxt);
                   1683:        xmlFree(fragment);
                   1684:     }
                   1685: #endif
                   1686: 
                   1687:     /*
                   1688:      * Do the xml:base fixup if needed
                   1689:      */
                   1690:     if ((doc != NULL) && (URL != NULL) && (xmlStrchr(URL, (xmlChar) '/')) &&
                   1691:         (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) &&
                   1692:        (!(doc->parseFlags & XML_PARSE_NOBASEFIX))) {
                   1693:        xmlNodePtr node;
                   1694:        xmlChar *base;
                   1695:        xmlChar *curBase;
                   1696: 
                   1697:        /*
                   1698:         * The base is only adjusted if "necessary", i.e. if the xinclude node
                   1699:         * has a base specified, or the URL is relative
                   1700:         */
                   1701:        base = xmlGetNsProp(ctxt->incTab[nr]->ref, BAD_CAST "base",
                   1702:                        XML_XML_NAMESPACE);
                   1703:        if (base == NULL) {
                   1704:            /*
                   1705:             * No xml:base on the xinclude node, so we check whether the
                   1706:             * URI base is different than (relative to) the context base
                   1707:             */
                   1708:            curBase = xmlBuildRelativeURI(URL, ctxt->base);
                   1709:            if (curBase == NULL) {      /* Error return */
1.1.1.3 ! misho    1710:                xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1711:                       XML_XINCLUDE_HREF_URI,
                   1712:                       "trying to build relative URI from %s\n", URL);
                   1713:            } else {
                   1714:                /* If the URI doesn't contain a slash, it's not relative */
                   1715:                if (!xmlStrchr(curBase, (xmlChar) '/'))
                   1716:                    xmlFree(curBase);
                   1717:                else
                   1718:                    base = curBase;
                   1719:            }
                   1720:        }
                   1721:        if (base != NULL) {     /* Adjustment may be needed */
                   1722:            node = ctxt->incTab[nr]->inc;
                   1723:            while (node != NULL) {
                   1724:                /* Only work on element nodes */
                   1725:                if (node->type == XML_ELEMENT_NODE) {
                   1726:                    curBase = xmlNodeGetBase(node->doc, node);
                   1727:                    /* If no current base, set it */
                   1728:                    if (curBase == NULL) {
                   1729:                        xmlNodeSetBase(node, base);
                   1730:                    } else {
                   1731:                        /*
                   1732:                         * If the current base is the same as the
                   1733:                         * URL of the document, then reset it to be
                   1734:                         * the specified xml:base or the relative URI
                   1735:                         */
                   1736:                        if (xmlStrEqual(curBase, node->doc->URL)) {
                   1737:                            xmlNodeSetBase(node, base);
                   1738:                        } else {
                   1739:                            /*
                   1740:                             * If the element already has an xml:base
                   1741:                             * set, then relativise it if necessary
                   1742:                             */
                   1743:                            xmlChar *xmlBase;
                   1744:                            xmlBase = xmlGetNsProp(node,
                   1745:                                            BAD_CAST "base",
                   1746:                                            XML_XML_NAMESPACE);
                   1747:                            if (xmlBase != NULL) {
                   1748:                                xmlChar *relBase;
                   1749:                                relBase = xmlBuildURI(xmlBase, base);
                   1750:                                if (relBase == NULL) { /* error */
1.1.1.3 ! misho    1751:                                    xmlXIncludeErr(ctxt,
1.1       misho    1752:                                                ctxt->incTab[nr]->ref,
                   1753:                                                XML_XINCLUDE_HREF_URI,
                   1754:                                        "trying to rebuild base from %s\n",
                   1755:                                                xmlBase);
                   1756:                                } else {
                   1757:                                    xmlNodeSetBase(node, relBase);
                   1758:                                    xmlFree(relBase);
                   1759:                                }
                   1760:                                xmlFree(xmlBase);
                   1761:                            }
                   1762:                        }
                   1763:                        xmlFree(curBase);
                   1764:                    }
                   1765:                }
                   1766:                node = node->next;
                   1767:            }
                   1768:            xmlFree(base);
                   1769:        }
                   1770:     }
                   1771:     if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
                   1772:        (ctxt->incTab[nr]->count <= 1)) {
                   1773: #ifdef DEBUG_XINCLUDE
                   1774:         printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
                   1775: #endif
                   1776:        xmlFreeDoc(ctxt->incTab[nr]->doc);
                   1777:        ctxt->incTab[nr]->doc = NULL;
                   1778:     }
                   1779:     xmlFree(URL);
                   1780:     return(0);
                   1781: }
                   1782: 
                   1783: /**
                   1784:  * xmlXIncludeLoadTxt:
                   1785:  * @ctxt:  the XInclude context
                   1786:  * @url:  the associated URL
                   1787:  * @nr:  the xinclude node number
1.1.1.3 ! misho    1788:  *
1.1       misho    1789:  * Load the content, and store the result in the XInclude context
                   1790:  *
                   1791:  * Returns 0 in case of success, -1 in case of failure
                   1792:  */
                   1793: static int
                   1794: xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
                   1795:     xmlParserInputBufferPtr buf;
                   1796:     xmlNodePtr node;
                   1797:     xmlURIPtr uri;
                   1798:     xmlChar *URL;
                   1799:     int i;
                   1800:     xmlChar *encoding = NULL;
                   1801:     xmlCharEncoding enc = (xmlCharEncoding) 0;
1.1.1.2   misho    1802:     xmlParserCtxtPtr pctxt;
                   1803:     xmlParserInputPtr inputStream;
1.1.1.3 ! misho    1804:     int xinclude_multibyte_fallback_used = 0;
1.1       misho    1805: 
                   1806:     /*
                   1807:      * Check the URL and remove any fragment identifier
                   1808:      */
                   1809:     uri = xmlParseURI((const char *)url);
                   1810:     if (uri == NULL) {
                   1811:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
                   1812:                       "invalid value URI %s\n", url);
                   1813:        return(-1);
                   1814:     }
                   1815:     if (uri->fragment != NULL) {
                   1816:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
                   1817:                       "fragment identifier forbidden for text: %s\n",
                   1818:                       (const xmlChar *) uri->fragment);
                   1819:        xmlFreeURI(uri);
                   1820:        return(-1);
                   1821:     }
                   1822:     URL = xmlSaveUri(uri);
                   1823:     xmlFreeURI(uri);
                   1824:     if (URL == NULL) {
                   1825:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
                   1826:                       "invalid value URI %s\n", url);
                   1827:        return(-1);
                   1828:     }
                   1829: 
                   1830:     /*
                   1831:      * Handling of references to the local document are done
                   1832:      * directly through ctxt->doc.
                   1833:      */
                   1834:     if (URL[0] == 0) {
1.1.1.3 ! misho    1835:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    1836:                       XML_XINCLUDE_TEXT_DOCUMENT,
                   1837:                       "text serialization of document not available\n", NULL);
                   1838:        xmlFree(URL);
                   1839:        return(-1);
                   1840:     }
                   1841: 
                   1842:     /*
                   1843:      * Prevent reloading twice the document.
                   1844:      */
                   1845:     for (i = 0; i < ctxt->txtNr; i++) {
                   1846:        if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
                   1847:            node = xmlCopyNode(ctxt->txtTab[i], 1);
                   1848:            goto loaded;
                   1849:        }
                   1850:     }
                   1851:     /*
                   1852:      * Try to get the encoding if available
                   1853:      */
                   1854:     if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
                   1855:        encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
                   1856:     }
                   1857:     if (encoding != NULL) {
                   1858:        /*
                   1859:         * TODO: we should not have to remap to the xmlCharEncoding
                   1860:         *       predefined set, a better interface than
                   1861:         *       xmlParserInputBufferCreateFilename should allow any
                   1862:         *       encoding supported by iconv
                   1863:         */
                   1864:         enc = xmlParseCharEncoding((const char *) encoding);
                   1865:        if (enc == XML_CHAR_ENCODING_ERROR) {
                   1866:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                   1867:                           XML_XINCLUDE_UNKNOWN_ENCODING,
                   1868:                           "encoding %s not supported\n", encoding);
                   1869:            xmlFree(encoding);
                   1870:            xmlFree(URL);
                   1871:            return(-1);
                   1872:        }
                   1873:        xmlFree(encoding);
                   1874:     }
                   1875: 
                   1876:     /*
                   1877:      * Load it.
                   1878:      */
1.1.1.2   misho    1879:     pctxt = xmlNewParserCtxt();
                   1880:     inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt);
                   1881:     if(inputStream == NULL) {
                   1882:        xmlFreeParserCtxt(pctxt);
                   1883:        xmlFree(URL);
                   1884:        return(-1);
                   1885:     }
                   1886:     buf = inputStream->buf;
1.1       misho    1887:     if (buf == NULL) {
1.1.1.2   misho    1888:        xmlFreeInputStream (inputStream);
                   1889:        xmlFreeParserCtxt(pctxt);
1.1       misho    1890:        xmlFree(URL);
                   1891:        return(-1);
                   1892:     }
1.1.1.2   misho    1893:     if (buf->encoder)
                   1894:        xmlCharEncCloseFunc(buf->encoder);
                   1895:     buf->encoder = xmlGetCharEncodingHandler(enc);
1.1       misho    1896:     node = xmlNewText(NULL);
                   1897: 
                   1898:     /*
                   1899:      * Scan all chars from the resource and add the to the node
                   1900:      */
1.1.1.3 ! misho    1901: xinclude_multibyte_fallback:
1.1       misho    1902:     while (xmlParserInputBufferRead(buf, 128) > 0) {
                   1903:        int len;
                   1904:        const xmlChar *content;
                   1905: 
1.1.1.3 ! misho    1906:        content = xmlBufContent(buf->buffer);
        !          1907:        len = xmlBufLength(buf->buffer);
1.1       misho    1908:        for (i = 0;i < len;) {
                   1909:            int cur;
                   1910:            int l;
                   1911: 
                   1912:            cur = xmlStringCurrentChar(NULL, &content[i], &l);
                   1913:            if (!IS_CHAR(cur)) {
1.1.1.3 ! misho    1914:                /* Handle splitted multibyte char at buffer boundary */
        !          1915:                if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) {
        !          1916:                    xinclude_multibyte_fallback_used = 1;
        !          1917:                    xmlBufShrink(buf->buffer, i);
        !          1918:                    goto xinclude_multibyte_fallback;
        !          1919:                } else {
        !          1920:                    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
        !          1921:                                   XML_XINCLUDE_INVALID_CHAR,
        !          1922:                                   "%s contains invalid char\n", URL);
        !          1923:                    xmlFreeParserInputBuffer(buf);
        !          1924:                    xmlFree(URL);
        !          1925:                    return(-1);
        !          1926:                }
1.1       misho    1927:            } else {
1.1.1.3 ! misho    1928:                xinclude_multibyte_fallback_used = 0;
1.1       misho    1929:                xmlNodeAddContentLen(node, &content[i], l);
                   1930:            }
                   1931:            i += l;
                   1932:        }
1.1.1.3 ! misho    1933:        xmlBufShrink(buf->buffer, len);
1.1       misho    1934:     }
1.1.1.2   misho    1935:     xmlFreeParserCtxt(pctxt);
1.1       misho    1936:     xmlXIncludeAddTxt(ctxt, node, URL);
1.1.1.2   misho    1937:     xmlFreeInputStream(inputStream);
1.1       misho    1938: 
                   1939: loaded:
                   1940:     /*
                   1941:      * Add the element as the replacement copy.
                   1942:      */
                   1943:     ctxt->incTab[nr]->inc = node;
                   1944:     xmlFree(URL);
                   1945:     return(0);
                   1946: }
                   1947: 
                   1948: /**
                   1949:  * xmlXIncludeLoadFallback:
                   1950:  * @ctxt:  the XInclude context
                   1951:  * @fallback:  the fallback node
                   1952:  * @nr:  the xinclude node number
1.1.1.3 ! misho    1953:  *
1.1       misho    1954:  * Load the content of the fallback node, and store the result
                   1955:  * in the XInclude context
                   1956:  *
                   1957:  * Returns 0 in case of success, -1 in case of failure
                   1958:  */
                   1959: static int
                   1960: xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
                   1961:     xmlXIncludeCtxtPtr newctxt;
                   1962:     int ret = 0;
1.1.1.3 ! misho    1963: 
        !          1964:     if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
        !          1965:         (ctxt == NULL))
1.1       misho    1966:        return(-1);
                   1967:     if (fallback->children != NULL) {
                   1968:        /*
                   1969:         * It's possible that the fallback also has 'includes'
                   1970:         * (Bug 129969), so we re-process the fallback just in case
                   1971:         */
                   1972:        newctxt = xmlXIncludeNewContext(ctxt->doc);
                   1973:        if (newctxt == NULL)
                   1974:            return (-1);
                   1975:        newctxt->_private = ctxt->_private;
                   1976:        newctxt->base = xmlStrdup(ctxt->base);  /* Inherit the base from the existing context */
                   1977:        xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
                   1978:        ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
                   1979:        if (ctxt->nbErrors > 0)
                   1980:            ret = -1;
                   1981:        else if (ret > 0)
                   1982:            ret = 0;    /* xmlXIncludeDoProcess can return +ve number */
                   1983:        xmlXIncludeFreeContext(newctxt);
                   1984: 
                   1985:        ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
                   1986:                                                   fallback->children);
                   1987:     } else {
                   1988:         ctxt->incTab[nr]->inc = NULL;
                   1989:        ctxt->incTab[nr]->emptyFb = 1;  /* flag empty callback */
                   1990:     }
                   1991:     return(ret);
                   1992: }
                   1993: 
                   1994: /************************************************************************
                   1995:  *                                                                     *
                   1996:  *                     XInclude Processing                             *
                   1997:  *                                                                     *
                   1998:  ************************************************************************/
                   1999: 
                   2000: /**
                   2001:  * xmlXIncludePreProcessNode:
                   2002:  * @ctxt: an XInclude context
                   2003:  * @node: an XInclude node
                   2004:  *
                   2005:  * Implement the XInclude preprocessing, currently just adding the element
                   2006:  * for further processing.
                   2007:  *
                   2008:  * Returns the result list or NULL in case of error
                   2009:  */
                   2010: static xmlNodePtr
                   2011: xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
                   2012:     xmlXIncludeAddNode(ctxt, node);
                   2013:     return(NULL);
                   2014: }
                   2015: 
                   2016: /**
                   2017:  * xmlXIncludeLoadNode:
                   2018:  * @ctxt: an XInclude context
                   2019:  * @nr: the node number
                   2020:  *
                   2021:  * Find and load the infoset replacement for the given node.
                   2022:  *
                   2023:  * Returns 0 if substitution succeeded, -1 if some processing failed
                   2024:  */
                   2025: static int
                   2026: xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
                   2027:     xmlNodePtr cur;
                   2028:     xmlChar *href;
                   2029:     xmlChar *parse;
                   2030:     xmlChar *base;
                   2031:     xmlChar *oldBase;
                   2032:     xmlChar *URI;
                   2033:     int xml = 1; /* default Issue 64 */
                   2034:     int ret;
                   2035: 
                   2036:     if (ctxt == NULL)
                   2037:        return(-1);
                   2038:     if ((nr < 0) || (nr >= ctxt->incNr))
                   2039:        return(-1);
                   2040:     cur = ctxt->incTab[nr]->ref;
                   2041:     if (cur == NULL)
                   2042:        return(-1);
                   2043: 
                   2044:     /*
                   2045:      * read the attributes
                   2046:      */
                   2047:     href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
                   2048:     if (href == NULL) {
                   2049:        href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
1.1.1.3 ! misho    2050:        if (href == NULL)
1.1       misho    2051:            return(-1);
                   2052:     }
                   2053:     parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
                   2054:     if (parse != NULL) {
                   2055:        if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
                   2056:            xml = 1;
                   2057:        else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
                   2058:            xml = 0;
                   2059:        else {
                   2060:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                   2061:                           XML_XINCLUDE_PARSE_VALUE,
                   2062:                           "invalid value %s for 'parse'\n", parse);
                   2063:            if (href != NULL)
                   2064:                xmlFree(href);
                   2065:            if (parse != NULL)
                   2066:                xmlFree(parse);
                   2067:            return(-1);
                   2068:        }
                   2069:     }
                   2070: 
                   2071:     /*
                   2072:      * compute the URI
                   2073:      */
                   2074:     base = xmlNodeGetBase(ctxt->doc, cur);
                   2075:     if (base == NULL) {
                   2076:        URI = xmlBuildURI(href, ctxt->doc->URL);
                   2077:     } else {
                   2078:        URI = xmlBuildURI(href, base);
                   2079:     }
                   2080:     if (URI == NULL) {
                   2081:        xmlChar *escbase;
                   2082:        xmlChar *eschref;
                   2083:        /*
                   2084:         * Some escaping may be needed
                   2085:         */
                   2086:        escbase = xmlURIEscape(base);
                   2087:        eschref = xmlURIEscape(href);
                   2088:        URI = xmlBuildURI(eschref, escbase);
                   2089:        if (escbase != NULL)
                   2090:            xmlFree(escbase);
                   2091:        if (eschref != NULL)
                   2092:            xmlFree(eschref);
                   2093:     }
                   2094:     if (URI == NULL) {
1.1.1.3 ! misho    2095:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    2096:                       XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
                   2097:        if (parse != NULL)
                   2098:            xmlFree(parse);
                   2099:        if (href != NULL)
                   2100:            xmlFree(href);
                   2101:        if (base != NULL)
                   2102:            xmlFree(base);
                   2103:        return(-1);
                   2104:     }
                   2105: #ifdef DEBUG_XINCLUDE
                   2106:     xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
                   2107:            xml ? "xml": "text");
                   2108:     xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
                   2109: #endif
                   2110: 
                   2111:     /*
                   2112:      * Save the base for this include (saving the current one)
                   2113:      */
                   2114:     oldBase = ctxt->base;
                   2115:     ctxt->base = base;
                   2116: 
                   2117:     if (xml) {
                   2118:        ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
                   2119:        /* xmlXIncludeGetFragment(ctxt, cur, URI); */
                   2120:     } else {
                   2121:        ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
                   2122:     }
                   2123: 
                   2124:     /*
                   2125:      * Restore the original base before checking for fallback
                   2126:      */
                   2127:     ctxt->base = oldBase;
1.1.1.3 ! misho    2128: 
1.1       misho    2129:     if (ret < 0) {
                   2130:        xmlNodePtr children;
                   2131: 
                   2132:        /*
                   2133:         * Time to try a fallback if availble
                   2134:         */
                   2135: #ifdef DEBUG_XINCLUDE
                   2136:        xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
                   2137: #endif
                   2138:        children = cur->children;
                   2139:        while (children != NULL) {
                   2140:            if ((children->type == XML_ELEMENT_NODE) &&
                   2141:                (children->ns != NULL) &&
                   2142:                (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
                   2143:                ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
                   2144:                 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
                   2145:                ret = xmlXIncludeLoadFallback(ctxt, children, nr);
1.1.1.3 ! misho    2146:                if (ret == 0)
1.1       misho    2147:                    break;
                   2148:            }
                   2149:            children = children->next;
                   2150:        }
                   2151:     }
                   2152:     if (ret < 0) {
1.1.1.3 ! misho    2153:        xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    2154:                       XML_XINCLUDE_NO_FALLBACK,
                   2155:                       "could not load %s, and no fallback was found\n",
                   2156:                       URI);
                   2157:     }
                   2158: 
                   2159:     /*
                   2160:      * Cleanup
                   2161:      */
                   2162:     if (URI != NULL)
                   2163:        xmlFree(URI);
                   2164:     if (parse != NULL)
                   2165:        xmlFree(parse);
                   2166:     if (href != NULL)
                   2167:        xmlFree(href);
                   2168:     if (base != NULL)
                   2169:        xmlFree(base);
                   2170:     return(0);
                   2171: }
                   2172: 
                   2173: /**
                   2174:  * xmlXIncludeIncludeNode:
                   2175:  * @ctxt: an XInclude context
                   2176:  * @nr: the node number
                   2177:  *
                   2178:  * Inplement the infoset replacement for the given node
                   2179:  *
                   2180:  * Returns 0 if substitution succeeded, -1 if some processing failed
                   2181:  */
                   2182: static int
                   2183: xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
                   2184:     xmlNodePtr cur, end, list, tmp;
                   2185: 
                   2186:     if (ctxt == NULL)
                   2187:        return(-1);
                   2188:     if ((nr < 0) || (nr >= ctxt->incNr))
                   2189:        return(-1);
                   2190:     cur = ctxt->incTab[nr]->ref;
1.1.1.3 ! misho    2191:     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
1.1       misho    2192:        return(-1);
                   2193: 
                   2194:     /*
                   2195:      * If we stored an XPointer a late computation may be needed
                   2196:      */
                   2197:     if ((ctxt->incTab[nr]->inc == NULL) &&
                   2198:        (ctxt->incTab[nr]->xptr != NULL)) {
                   2199:        ctxt->incTab[nr]->inc =
                   2200:            xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
                   2201:                                    ctxt->incTab[nr]->xptr);
                   2202:        xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
                   2203:        ctxt->incTab[nr]->xptr = NULL;
                   2204:     }
                   2205:     list = ctxt->incTab[nr]->inc;
                   2206:     ctxt->incTab[nr]->inc = NULL;
                   2207: 
                   2208:     /*
                   2209:      * Check against the risk of generating a multi-rooted document
                   2210:      */
                   2211:     if ((cur->parent != NULL) &&
                   2212:        (cur->parent->type != XML_ELEMENT_NODE)) {
                   2213:        int nb_elem = 0;
                   2214: 
                   2215:        tmp = list;
                   2216:        while (tmp != NULL) {
                   2217:            if (tmp->type == XML_ELEMENT_NODE)
                   2218:                nb_elem++;
                   2219:            tmp = tmp->next;
                   2220:        }
                   2221:        if (nb_elem > 1) {
1.1.1.3 ! misho    2222:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1.1       misho    2223:                           XML_XINCLUDE_MULTIPLE_ROOT,
                   2224:                       "XInclude error: would result in multiple root nodes\n",
                   2225:                           NULL);
                   2226:            return(-1);
                   2227:        }
                   2228:     }
                   2229: 
                   2230:     if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
                   2231:        /*
                   2232:         * Add the list of nodes
                   2233:         */
                   2234:        while (list != NULL) {
                   2235:            end = list;
                   2236:            list = list->next;
                   2237: 
                   2238:            xmlAddPrevSibling(cur, end);
                   2239:        }
                   2240:        xmlUnlinkNode(cur);
                   2241:        xmlFreeNode(cur);
                   2242:     } else {
                   2243:        /*
                   2244:         * Change the current node as an XInclude start one, and add an
                   2245:         * XInclude end one
                   2246:         */
                   2247:        cur->type = XML_XINCLUDE_START;
                   2248:        end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
                   2249:        if (end == NULL) {
                   2250:            xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
                   2251:                           XML_XINCLUDE_BUILD_FAILED,
                   2252:                           "failed to build node\n", NULL);
                   2253:            return(-1);
                   2254:        }
                   2255:        end->type = XML_XINCLUDE_END;
                   2256:        xmlAddNextSibling(cur, end);
                   2257: 
                   2258:        /*
                   2259:         * Add the list of nodes
                   2260:         */
                   2261:        while (list != NULL) {
                   2262:            cur = list;
                   2263:            list = list->next;
                   2264: 
                   2265:            xmlAddPrevSibling(end, cur);
                   2266:        }
                   2267:     }
                   2268: 
1.1.1.3 ! misho    2269: 
1.1       misho    2270:     return(0);
                   2271: }
                   2272: 
                   2273: /**
                   2274:  * xmlXIncludeTestNode:
                   2275:  * @ctxt: the XInclude processing context
                   2276:  * @node: an XInclude node
                   2277:  *
                   2278:  * test if the node is an XInclude node
                   2279:  *
                   2280:  * Returns 1 true, 0 otherwise
                   2281:  */
                   2282: static int
                   2283: xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
                   2284:     if (node == NULL)
                   2285:        return(0);
                   2286:     if (node->type != XML_ELEMENT_NODE)
                   2287:        return(0);
                   2288:     if (node->ns == NULL)
                   2289:        return(0);
                   2290:     if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
                   2291:         (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
                   2292:        if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
                   2293:            if (ctxt->legacy == 0) {
                   2294: #if 0 /* wait for the XML Core Working Group to get something stable ! */
                   2295:                xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
                   2296:                       "Deprecated XInclude namespace found, use %s",
                   2297:                                XINCLUDE_NS);
                   2298: #endif
                   2299:                ctxt->legacy = 1;
                   2300:            }
                   2301:        }
                   2302:        if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
                   2303:            xmlNodePtr child = node->children;
                   2304:            int nb_fallback = 0;
                   2305: 
                   2306:            while (child != NULL) {
                   2307:                if ((child->type == XML_ELEMENT_NODE) &&
                   2308:                    (child->ns != NULL) &&
                   2309:                    ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
                   2310:                     (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
                   2311:                    if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
                   2312:                        xmlXIncludeErr(ctxt, node,
                   2313:                                       XML_XINCLUDE_INCLUDE_IN_INCLUDE,
                   2314:                                       "%s has an 'include' child\n",
                   2315:                                       XINCLUDE_NODE);
                   2316:                        return(0);
                   2317:                    }
                   2318:                    if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
                   2319:                        nb_fallback++;
                   2320:                    }
                   2321:                }
                   2322:                child = child->next;
                   2323:            }
                   2324:            if (nb_fallback > 1) {
                   2325:                xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
                   2326:                               "%s has multiple fallback children\n",
                   2327:                               XINCLUDE_NODE);
                   2328:                return(0);
                   2329:            }
                   2330:            return(1);
                   2331:        }
                   2332:        if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
                   2333:            if ((node->parent == NULL) ||
                   2334:                (node->parent->type != XML_ELEMENT_NODE) ||
                   2335:                (node->parent->ns == NULL) ||
                   2336:                ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
                   2337:                 (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
                   2338:                (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
                   2339:                xmlXIncludeErr(ctxt, node,
                   2340:                               XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE,
                   2341:                               "%s is not the child of an 'include'\n",
                   2342:                               XINCLUDE_FALLBACK);
                   2343:            }
                   2344:        }
                   2345:     }
                   2346:     return(0);
                   2347: }
                   2348: 
                   2349: /**
                   2350:  * xmlXIncludeDoProcess:
                   2351:  * @ctxt: the XInclude processing context
                   2352:  * @doc: an XML document
                   2353:  * @tree: the top of the tree to process
                   2354:  *
                   2355:  * Implement the XInclude substitution on the XML document @doc
                   2356:  *
                   2357:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2358:  *    or the number of substitutions done.
                   2359:  */
                   2360: static int
                   2361: xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
                   2362:     xmlNodePtr cur;
                   2363:     int ret = 0;
                   2364:     int i, start;
                   2365: 
1.1.1.3 ! misho    2366:     if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
1.1       misho    2367:        return(-1);
                   2368:     if (ctxt == NULL)
                   2369:        return(-1);
                   2370: 
                   2371:     if (doc->URL != NULL) {
                   2372:        ret = xmlXIncludeURLPush(ctxt, doc->URL);
                   2373:        if (ret < 0)
                   2374:            return(-1);
                   2375:     }
                   2376:     start = ctxt->incNr;
                   2377: 
                   2378:     /*
                   2379:      * First phase: lookup the elements in the document
                   2380:      */
                   2381:     cur = tree;
                   2382:     if (xmlXIncludeTestNode(ctxt, cur) == 1)
                   2383:        xmlXIncludePreProcessNode(ctxt, cur);
                   2384:     while ((cur != NULL) && (cur != tree->parent)) {
                   2385:        /* TODO: need to work on entities -> stack */
                   2386:        if ((cur->children != NULL) &&
                   2387:            (cur->children->type != XML_ENTITY_DECL) &&
                   2388:            (cur->children->type != XML_XINCLUDE_START) &&
                   2389:            (cur->children->type != XML_XINCLUDE_END)) {
                   2390:            cur = cur->children;
                   2391:            if (xmlXIncludeTestNode(ctxt, cur))
                   2392:                xmlXIncludePreProcessNode(ctxt, cur);
                   2393:        } else if (cur->next != NULL) {
                   2394:            cur = cur->next;
                   2395:            if (xmlXIncludeTestNode(ctxt, cur))
                   2396:                xmlXIncludePreProcessNode(ctxt, cur);
                   2397:        } else {
                   2398:            if (cur == tree)
                   2399:                break;
                   2400:            do {
                   2401:                cur = cur->parent;
                   2402:                if ((cur == NULL) || (cur == tree->parent))
                   2403:                    break; /* do */
                   2404:                if (cur->next != NULL) {
                   2405:                    cur = cur->next;
                   2406:                    if (xmlXIncludeTestNode(ctxt, cur))
                   2407:                        xmlXIncludePreProcessNode(ctxt, cur);
                   2408:                    break; /* do */
                   2409:                }
                   2410:            } while (cur != NULL);
                   2411:        }
                   2412:     }
                   2413: 
                   2414:     /*
                   2415:      * Second Phase : collect the infosets fragments
                   2416:      */
                   2417:     for (i = start;i < ctxt->incNr; i++) {
                   2418:         xmlXIncludeLoadNode(ctxt, i);
                   2419:        ret++;
                   2420:     }
                   2421: 
                   2422:     /*
                   2423:      * Third phase: extend the original document infoset.
                   2424:      *
                   2425:      * Originally we bypassed the inclusion if there were any errors
                   2426:      * encountered on any of the XIncludes.  A bug was raised (bug
                   2427:      * 132588) requesting that we output the XIncludes without error,
                   2428:      * so the check for inc!=NULL || xptr!=NULL was put in.  This may
                   2429:      * give some other problems in the future, but for now it seems to
                   2430:      * work ok.
                   2431:      *
                   2432:      */
                   2433:     for (i = ctxt->incBase;i < ctxt->incNr; i++) {
                   2434:        if ((ctxt->incTab[i]->inc != NULL) ||
                   2435:                (ctxt->incTab[i]->xptr != NULL) ||
                   2436:                (ctxt->incTab[i]->emptyFb != 0))        /* (empty fallback) */
                   2437:            xmlXIncludeIncludeNode(ctxt, i);
                   2438:     }
                   2439: 
                   2440:     if (doc->URL != NULL)
                   2441:        xmlXIncludeURLPop(ctxt);
                   2442:     return(ret);
                   2443: }
                   2444: 
                   2445: /**
                   2446:  * xmlXIncludeSetFlags:
                   2447:  * @ctxt:  an XInclude processing context
                   2448:  * @flags: a set of xmlParserOption used for parsing XML includes
                   2449:  *
                   2450:  * Set the flags used for further processing of XML resources.
                   2451:  *
                   2452:  * Returns 0 in case of success and -1 in case of error.
                   2453:  */
                   2454: int
                   2455: xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
                   2456:     if (ctxt == NULL)
                   2457:         return(-1);
                   2458:     ctxt->parseFlags = flags;
                   2459:     return(0);
                   2460: }
                   2461: 
                   2462: /**
                   2463:  * xmlXIncludeProcessTreeFlagsData:
                   2464:  * @tree: an XML node
                   2465:  * @flags: a set of xmlParserOption used for parsing XML includes
                   2466:  * @data: application data that will be passed to the parser context
                   2467:  *        in the _private field of the parser context(s)
                   2468:  *
                   2469:  * Implement the XInclude substitution on the XML node @tree
                   2470:  *
                   2471:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2472:  *    or the number of substitutions done.
                   2473:  */
                   2474: 
                   2475: int
                   2476: xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
                   2477:     xmlXIncludeCtxtPtr ctxt;
                   2478:     int ret = 0;
                   2479: 
1.1.1.3 ! misho    2480:     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
        !          2481:         (tree->doc == NULL))
1.1       misho    2482:         return(-1);
                   2483: 
                   2484:     ctxt = xmlXIncludeNewContext(tree->doc);
                   2485:     if (ctxt == NULL)
                   2486:         return(-1);
                   2487:     ctxt->_private = data;
                   2488:     ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
                   2489:     xmlXIncludeSetFlags(ctxt, flags);
                   2490:     ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
                   2491:     if ((ret >= 0) && (ctxt->nbErrors > 0))
                   2492:         ret = -1;
                   2493: 
                   2494:     xmlXIncludeFreeContext(ctxt);
                   2495:     return(ret);
                   2496: }
                   2497: 
                   2498: /**
                   2499:  * xmlXIncludeProcessFlagsData:
                   2500:  * @doc: an XML document
                   2501:  * @flags: a set of xmlParserOption used for parsing XML includes
                   2502:  * @data: application data that will be passed to the parser context
                   2503:  *        in the _private field of the parser context(s)
                   2504:  *
                   2505:  * Implement the XInclude substitution on the XML document @doc
                   2506:  *
                   2507:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2508:  *    or the number of substitutions done.
                   2509:  */
                   2510: int
                   2511: xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) {
                   2512:     xmlNodePtr tree;
                   2513: 
                   2514:     if (doc == NULL)
                   2515:        return(-1);
                   2516:     tree = xmlDocGetRootElement(doc);
                   2517:     if (tree == NULL)
                   2518:        return(-1);
                   2519:     return(xmlXIncludeProcessTreeFlagsData(tree, flags, data));
                   2520: }
                   2521: 
                   2522: /**
                   2523:  * xmlXIncludeProcessFlags:
                   2524:  * @doc: an XML document
                   2525:  * @flags: a set of xmlParserOption used for parsing XML includes
                   2526:  *
                   2527:  * Implement the XInclude substitution on the XML document @doc
                   2528:  *
                   2529:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2530:  *    or the number of substitutions done.
                   2531:  */
                   2532: int
                   2533: xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
                   2534:     return xmlXIncludeProcessFlagsData(doc, flags, NULL);
                   2535: }
                   2536: 
                   2537: /**
                   2538:  * xmlXIncludeProcess:
                   2539:  * @doc: an XML document
                   2540:  *
                   2541:  * Implement the XInclude substitution on the XML document @doc
                   2542:  *
                   2543:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2544:  *    or the number of substitutions done.
                   2545:  */
                   2546: int
                   2547: xmlXIncludeProcess(xmlDocPtr doc) {
                   2548:     return(xmlXIncludeProcessFlags(doc, 0));
                   2549: }
                   2550: 
                   2551: /**
                   2552:  * xmlXIncludeProcessTreeFlags:
                   2553:  * @tree: a node in an XML document
                   2554:  * @flags: a set of xmlParserOption used for parsing XML includes
                   2555:  *
                   2556:  * Implement the XInclude substitution for the given subtree
                   2557:  *
                   2558:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2559:  *    or the number of substitutions done.
                   2560:  */
                   2561: int
                   2562: xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
                   2563:     xmlXIncludeCtxtPtr ctxt;
                   2564:     int ret = 0;
                   2565: 
1.1.1.3 ! misho    2566:     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
        !          2567:         (tree->doc == NULL))
1.1       misho    2568:        return(-1);
                   2569:     ctxt = xmlXIncludeNewContext(tree->doc);
                   2570:     if (ctxt == NULL)
                   2571:        return(-1);
                   2572:     ctxt->base = xmlNodeGetBase(tree->doc, tree);
                   2573:     xmlXIncludeSetFlags(ctxt, flags);
                   2574:     ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
                   2575:     if ((ret >= 0) && (ctxt->nbErrors > 0))
                   2576:        ret = -1;
                   2577: 
                   2578:     xmlXIncludeFreeContext(ctxt);
                   2579:     return(ret);
                   2580: }
                   2581: 
                   2582: /**
                   2583:  * xmlXIncludeProcessTree:
                   2584:  * @tree: a node in an XML document
                   2585:  *
                   2586:  * Implement the XInclude substitution for the given subtree
                   2587:  *
                   2588:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2589:  *    or the number of substitutions done.
                   2590:  */
                   2591: int
                   2592: xmlXIncludeProcessTree(xmlNodePtr tree) {
                   2593:     return(xmlXIncludeProcessTreeFlags(tree, 0));
                   2594: }
                   2595: 
                   2596: /**
                   2597:  * xmlXIncludeProcessNode:
                   2598:  * @ctxt: an existing XInclude context
                   2599:  * @node: a node in an XML document
                   2600:  *
                   2601:  * Implement the XInclude substitution for the given subtree reusing
                   2602:  * the informations and data coming from the given context.
                   2603:  *
                   2604:  * Returns 0 if no substitution were done, -1 if some processing failed
                   2605:  *    or the number of substitutions done.
                   2606:  */
                   2607: int
                   2608: xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
                   2609:     int ret = 0;
                   2610: 
1.1.1.3 ! misho    2611:     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
        !          2612:         (node->doc == NULL) || (ctxt == NULL))
1.1       misho    2613:        return(-1);
                   2614:     ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
                   2615:     if ((ret >= 0) && (ctxt->nbErrors > 0))
                   2616:        ret = -1;
                   2617:     return(ret);
                   2618: }
                   2619: 
                   2620: #else /* !LIBXML_XINCLUDE_ENABLED */
                   2621: #endif
                   2622: #define bottom_xinclude
                   2623: #include "elfgcchack.h"

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>