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

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

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