Annotation of embedaddon/libxml2/xinclude.c, revision 1.1
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;
! 1799:
! 1800: /*
! 1801: * Check the URL and remove any fragment identifier
! 1802: */
! 1803: uri = xmlParseURI((const char *)url);
! 1804: if (uri == NULL) {
! 1805: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
! 1806: "invalid value URI %s\n", url);
! 1807: return(-1);
! 1808: }
! 1809: if (uri->fragment != NULL) {
! 1810: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
! 1811: "fragment identifier forbidden for text: %s\n",
! 1812: (const xmlChar *) uri->fragment);
! 1813: xmlFreeURI(uri);
! 1814: return(-1);
! 1815: }
! 1816: URL = xmlSaveUri(uri);
! 1817: xmlFreeURI(uri);
! 1818: if (URL == NULL) {
! 1819: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
! 1820: "invalid value URI %s\n", url);
! 1821: return(-1);
! 1822: }
! 1823:
! 1824: /*
! 1825: * Handling of references to the local document are done
! 1826: * directly through ctxt->doc.
! 1827: */
! 1828: if (URL[0] == 0) {
! 1829: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 1830: XML_XINCLUDE_TEXT_DOCUMENT,
! 1831: "text serialization of document not available\n", NULL);
! 1832: xmlFree(URL);
! 1833: return(-1);
! 1834: }
! 1835:
! 1836: /*
! 1837: * Prevent reloading twice the document.
! 1838: */
! 1839: for (i = 0; i < ctxt->txtNr; i++) {
! 1840: if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
! 1841: node = xmlCopyNode(ctxt->txtTab[i], 1);
! 1842: goto loaded;
! 1843: }
! 1844: }
! 1845: /*
! 1846: * Try to get the encoding if available
! 1847: */
! 1848: if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
! 1849: encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
! 1850: }
! 1851: if (encoding != NULL) {
! 1852: /*
! 1853: * TODO: we should not have to remap to the xmlCharEncoding
! 1854: * predefined set, a better interface than
! 1855: * xmlParserInputBufferCreateFilename should allow any
! 1856: * encoding supported by iconv
! 1857: */
! 1858: enc = xmlParseCharEncoding((const char *) encoding);
! 1859: if (enc == XML_CHAR_ENCODING_ERROR) {
! 1860: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 1861: XML_XINCLUDE_UNKNOWN_ENCODING,
! 1862: "encoding %s not supported\n", encoding);
! 1863: xmlFree(encoding);
! 1864: xmlFree(URL);
! 1865: return(-1);
! 1866: }
! 1867: xmlFree(encoding);
! 1868: }
! 1869:
! 1870: /*
! 1871: * Load it.
! 1872: */
! 1873: buf = xmlParserInputBufferCreateFilename((const char *)URL, enc);
! 1874: if (buf == NULL) {
! 1875: xmlFree(URL);
! 1876: return(-1);
! 1877: }
! 1878: node = xmlNewText(NULL);
! 1879:
! 1880: /*
! 1881: * Scan all chars from the resource and add the to the node
! 1882: */
! 1883: while (xmlParserInputBufferRead(buf, 128) > 0) {
! 1884: int len;
! 1885: const xmlChar *content;
! 1886:
! 1887: content = xmlBufferContent(buf->buffer);
! 1888: len = xmlBufferLength(buf->buffer);
! 1889: for (i = 0;i < len;) {
! 1890: int cur;
! 1891: int l;
! 1892:
! 1893: cur = xmlStringCurrentChar(NULL, &content[i], &l);
! 1894: if (!IS_CHAR(cur)) {
! 1895: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 1896: XML_XINCLUDE_INVALID_CHAR,
! 1897: "%s contains invalid char\n", URL);
! 1898: xmlFreeParserInputBuffer(buf);
! 1899: xmlFree(URL);
! 1900: return(-1);
! 1901: } else {
! 1902: xmlNodeAddContentLen(node, &content[i], l);
! 1903: }
! 1904: i += l;
! 1905: }
! 1906: xmlBufferShrink(buf->buffer, len);
! 1907: }
! 1908: xmlFreeParserInputBuffer(buf);
! 1909: xmlXIncludeAddTxt(ctxt, node, URL);
! 1910:
! 1911: loaded:
! 1912: /*
! 1913: * Add the element as the replacement copy.
! 1914: */
! 1915: ctxt->incTab[nr]->inc = node;
! 1916: xmlFree(URL);
! 1917: return(0);
! 1918: }
! 1919:
! 1920: /**
! 1921: * xmlXIncludeLoadFallback:
! 1922: * @ctxt: the XInclude context
! 1923: * @fallback: the fallback node
! 1924: * @nr: the xinclude node number
! 1925: *
! 1926: * Load the content of the fallback node, and store the result
! 1927: * in the XInclude context
! 1928: *
! 1929: * Returns 0 in case of success, -1 in case of failure
! 1930: */
! 1931: static int
! 1932: xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
! 1933: xmlXIncludeCtxtPtr newctxt;
! 1934: int ret = 0;
! 1935:
! 1936: if ((fallback == NULL) || (ctxt == NULL))
! 1937: return(-1);
! 1938: if (fallback->children != NULL) {
! 1939: /*
! 1940: * It's possible that the fallback also has 'includes'
! 1941: * (Bug 129969), so we re-process the fallback just in case
! 1942: */
! 1943: newctxt = xmlXIncludeNewContext(ctxt->doc);
! 1944: if (newctxt == NULL)
! 1945: return (-1);
! 1946: newctxt->_private = ctxt->_private;
! 1947: newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
! 1948: xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
! 1949: ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
! 1950: if (ctxt->nbErrors > 0)
! 1951: ret = -1;
! 1952: else if (ret > 0)
! 1953: ret = 0; /* xmlXIncludeDoProcess can return +ve number */
! 1954: xmlXIncludeFreeContext(newctxt);
! 1955:
! 1956: ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
! 1957: fallback->children);
! 1958: } else {
! 1959: ctxt->incTab[nr]->inc = NULL;
! 1960: ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
! 1961: }
! 1962: return(ret);
! 1963: }
! 1964:
! 1965: /************************************************************************
! 1966: * *
! 1967: * XInclude Processing *
! 1968: * *
! 1969: ************************************************************************/
! 1970:
! 1971: /**
! 1972: * xmlXIncludePreProcessNode:
! 1973: * @ctxt: an XInclude context
! 1974: * @node: an XInclude node
! 1975: *
! 1976: * Implement the XInclude preprocessing, currently just adding the element
! 1977: * for further processing.
! 1978: *
! 1979: * Returns the result list or NULL in case of error
! 1980: */
! 1981: static xmlNodePtr
! 1982: xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
! 1983: xmlXIncludeAddNode(ctxt, node);
! 1984: return(NULL);
! 1985: }
! 1986:
! 1987: /**
! 1988: * xmlXIncludeLoadNode:
! 1989: * @ctxt: an XInclude context
! 1990: * @nr: the node number
! 1991: *
! 1992: * Find and load the infoset replacement for the given node.
! 1993: *
! 1994: * Returns 0 if substitution succeeded, -1 if some processing failed
! 1995: */
! 1996: static int
! 1997: xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
! 1998: xmlNodePtr cur;
! 1999: xmlChar *href;
! 2000: xmlChar *parse;
! 2001: xmlChar *base;
! 2002: xmlChar *oldBase;
! 2003: xmlChar *URI;
! 2004: int xml = 1; /* default Issue 64 */
! 2005: int ret;
! 2006:
! 2007: if (ctxt == NULL)
! 2008: return(-1);
! 2009: if ((nr < 0) || (nr >= ctxt->incNr))
! 2010: return(-1);
! 2011: cur = ctxt->incTab[nr]->ref;
! 2012: if (cur == NULL)
! 2013: return(-1);
! 2014:
! 2015: /*
! 2016: * read the attributes
! 2017: */
! 2018: href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
! 2019: if (href == NULL) {
! 2020: href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
! 2021: if (href == NULL)
! 2022: return(-1);
! 2023: }
! 2024: parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
! 2025: if (parse != NULL) {
! 2026: if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
! 2027: xml = 1;
! 2028: else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
! 2029: xml = 0;
! 2030: else {
! 2031: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 2032: XML_XINCLUDE_PARSE_VALUE,
! 2033: "invalid value %s for 'parse'\n", parse);
! 2034: if (href != NULL)
! 2035: xmlFree(href);
! 2036: if (parse != NULL)
! 2037: xmlFree(parse);
! 2038: return(-1);
! 2039: }
! 2040: }
! 2041:
! 2042: /*
! 2043: * compute the URI
! 2044: */
! 2045: base = xmlNodeGetBase(ctxt->doc, cur);
! 2046: if (base == NULL) {
! 2047: URI = xmlBuildURI(href, ctxt->doc->URL);
! 2048: } else {
! 2049: URI = xmlBuildURI(href, base);
! 2050: }
! 2051: if (URI == NULL) {
! 2052: xmlChar *escbase;
! 2053: xmlChar *eschref;
! 2054: /*
! 2055: * Some escaping may be needed
! 2056: */
! 2057: escbase = xmlURIEscape(base);
! 2058: eschref = xmlURIEscape(href);
! 2059: URI = xmlBuildURI(eschref, escbase);
! 2060: if (escbase != NULL)
! 2061: xmlFree(escbase);
! 2062: if (eschref != NULL)
! 2063: xmlFree(eschref);
! 2064: }
! 2065: if (URI == NULL) {
! 2066: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 2067: XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
! 2068: if (parse != NULL)
! 2069: xmlFree(parse);
! 2070: if (href != NULL)
! 2071: xmlFree(href);
! 2072: if (base != NULL)
! 2073: xmlFree(base);
! 2074: return(-1);
! 2075: }
! 2076: #ifdef DEBUG_XINCLUDE
! 2077: xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
! 2078: xml ? "xml": "text");
! 2079: xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
! 2080: #endif
! 2081:
! 2082: /*
! 2083: * Save the base for this include (saving the current one)
! 2084: */
! 2085: oldBase = ctxt->base;
! 2086: ctxt->base = base;
! 2087:
! 2088: if (xml) {
! 2089: ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
! 2090: /* xmlXIncludeGetFragment(ctxt, cur, URI); */
! 2091: } else {
! 2092: ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
! 2093: }
! 2094:
! 2095: /*
! 2096: * Restore the original base before checking for fallback
! 2097: */
! 2098: ctxt->base = oldBase;
! 2099:
! 2100: if (ret < 0) {
! 2101: xmlNodePtr children;
! 2102:
! 2103: /*
! 2104: * Time to try a fallback if availble
! 2105: */
! 2106: #ifdef DEBUG_XINCLUDE
! 2107: xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
! 2108: #endif
! 2109: children = cur->children;
! 2110: while (children != NULL) {
! 2111: if ((children->type == XML_ELEMENT_NODE) &&
! 2112: (children->ns != NULL) &&
! 2113: (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
! 2114: ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
! 2115: (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
! 2116: ret = xmlXIncludeLoadFallback(ctxt, children, nr);
! 2117: if (ret == 0)
! 2118: break;
! 2119: }
! 2120: children = children->next;
! 2121: }
! 2122: }
! 2123: if (ret < 0) {
! 2124: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 2125: XML_XINCLUDE_NO_FALLBACK,
! 2126: "could not load %s, and no fallback was found\n",
! 2127: URI);
! 2128: }
! 2129:
! 2130: /*
! 2131: * Cleanup
! 2132: */
! 2133: if (URI != NULL)
! 2134: xmlFree(URI);
! 2135: if (parse != NULL)
! 2136: xmlFree(parse);
! 2137: if (href != NULL)
! 2138: xmlFree(href);
! 2139: if (base != NULL)
! 2140: xmlFree(base);
! 2141: return(0);
! 2142: }
! 2143:
! 2144: /**
! 2145: * xmlXIncludeIncludeNode:
! 2146: * @ctxt: an XInclude context
! 2147: * @nr: the node number
! 2148: *
! 2149: * Inplement the infoset replacement for the given node
! 2150: *
! 2151: * Returns 0 if substitution succeeded, -1 if some processing failed
! 2152: */
! 2153: static int
! 2154: xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
! 2155: xmlNodePtr cur, end, list, tmp;
! 2156:
! 2157: if (ctxt == NULL)
! 2158: return(-1);
! 2159: if ((nr < 0) || (nr >= ctxt->incNr))
! 2160: return(-1);
! 2161: cur = ctxt->incTab[nr]->ref;
! 2162: if (cur == NULL)
! 2163: return(-1);
! 2164:
! 2165: /*
! 2166: * If we stored an XPointer a late computation may be needed
! 2167: */
! 2168: if ((ctxt->incTab[nr]->inc == NULL) &&
! 2169: (ctxt->incTab[nr]->xptr != NULL)) {
! 2170: ctxt->incTab[nr]->inc =
! 2171: xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
! 2172: ctxt->incTab[nr]->xptr);
! 2173: xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
! 2174: ctxt->incTab[nr]->xptr = NULL;
! 2175: }
! 2176: list = ctxt->incTab[nr]->inc;
! 2177: ctxt->incTab[nr]->inc = NULL;
! 2178:
! 2179: /*
! 2180: * Check against the risk of generating a multi-rooted document
! 2181: */
! 2182: if ((cur->parent != NULL) &&
! 2183: (cur->parent->type != XML_ELEMENT_NODE)) {
! 2184: int nb_elem = 0;
! 2185:
! 2186: tmp = list;
! 2187: while (tmp != NULL) {
! 2188: if (tmp->type == XML_ELEMENT_NODE)
! 2189: nb_elem++;
! 2190: tmp = tmp->next;
! 2191: }
! 2192: if (nb_elem > 1) {
! 2193: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 2194: XML_XINCLUDE_MULTIPLE_ROOT,
! 2195: "XInclude error: would result in multiple root nodes\n",
! 2196: NULL);
! 2197: return(-1);
! 2198: }
! 2199: }
! 2200:
! 2201: if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
! 2202: /*
! 2203: * Add the list of nodes
! 2204: */
! 2205: while (list != NULL) {
! 2206: end = list;
! 2207: list = list->next;
! 2208:
! 2209: xmlAddPrevSibling(cur, end);
! 2210: }
! 2211: xmlUnlinkNode(cur);
! 2212: xmlFreeNode(cur);
! 2213: } else {
! 2214: /*
! 2215: * Change the current node as an XInclude start one, and add an
! 2216: * XInclude end one
! 2217: */
! 2218: cur->type = XML_XINCLUDE_START;
! 2219: end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
! 2220: if (end == NULL) {
! 2221: xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
! 2222: XML_XINCLUDE_BUILD_FAILED,
! 2223: "failed to build node\n", NULL);
! 2224: return(-1);
! 2225: }
! 2226: end->type = XML_XINCLUDE_END;
! 2227: xmlAddNextSibling(cur, end);
! 2228:
! 2229: /*
! 2230: * Add the list of nodes
! 2231: */
! 2232: while (list != NULL) {
! 2233: cur = list;
! 2234: list = list->next;
! 2235:
! 2236: xmlAddPrevSibling(end, cur);
! 2237: }
! 2238: }
! 2239:
! 2240:
! 2241: return(0);
! 2242: }
! 2243:
! 2244: /**
! 2245: * xmlXIncludeTestNode:
! 2246: * @ctxt: the XInclude processing context
! 2247: * @node: an XInclude node
! 2248: *
! 2249: * test if the node is an XInclude node
! 2250: *
! 2251: * Returns 1 true, 0 otherwise
! 2252: */
! 2253: static int
! 2254: xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
! 2255: if (node == NULL)
! 2256: return(0);
! 2257: if (node->type != XML_ELEMENT_NODE)
! 2258: return(0);
! 2259: if (node->ns == NULL)
! 2260: return(0);
! 2261: if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
! 2262: (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
! 2263: if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
! 2264: if (ctxt->legacy == 0) {
! 2265: #if 0 /* wait for the XML Core Working Group to get something stable ! */
! 2266: xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
! 2267: "Deprecated XInclude namespace found, use %s",
! 2268: XINCLUDE_NS);
! 2269: #endif
! 2270: ctxt->legacy = 1;
! 2271: }
! 2272: }
! 2273: if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
! 2274: xmlNodePtr child = node->children;
! 2275: int nb_fallback = 0;
! 2276:
! 2277: while (child != NULL) {
! 2278: if ((child->type == XML_ELEMENT_NODE) &&
! 2279: (child->ns != NULL) &&
! 2280: ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
! 2281: (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
! 2282: if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
! 2283: xmlXIncludeErr(ctxt, node,
! 2284: XML_XINCLUDE_INCLUDE_IN_INCLUDE,
! 2285: "%s has an 'include' child\n",
! 2286: XINCLUDE_NODE);
! 2287: return(0);
! 2288: }
! 2289: if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
! 2290: nb_fallback++;
! 2291: }
! 2292: }
! 2293: child = child->next;
! 2294: }
! 2295: if (nb_fallback > 1) {
! 2296: xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
! 2297: "%s has multiple fallback children\n",
! 2298: XINCLUDE_NODE);
! 2299: return(0);
! 2300: }
! 2301: return(1);
! 2302: }
! 2303: if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
! 2304: if ((node->parent == NULL) ||
! 2305: (node->parent->type != XML_ELEMENT_NODE) ||
! 2306: (node->parent->ns == NULL) ||
! 2307: ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
! 2308: (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
! 2309: (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
! 2310: xmlXIncludeErr(ctxt, node,
! 2311: XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE,
! 2312: "%s is not the child of an 'include'\n",
! 2313: XINCLUDE_FALLBACK);
! 2314: }
! 2315: }
! 2316: }
! 2317: return(0);
! 2318: }
! 2319:
! 2320: /**
! 2321: * xmlXIncludeDoProcess:
! 2322: * @ctxt: the XInclude processing context
! 2323: * @doc: an XML document
! 2324: * @tree: the top of the tree to process
! 2325: *
! 2326: * Implement the XInclude substitution on the XML document @doc
! 2327: *
! 2328: * Returns 0 if no substitution were done, -1 if some processing failed
! 2329: * or the number of substitutions done.
! 2330: */
! 2331: static int
! 2332: xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
! 2333: xmlNodePtr cur;
! 2334: int ret = 0;
! 2335: int i, start;
! 2336:
! 2337: if ((doc == NULL) || (tree == NULL))
! 2338: return(-1);
! 2339: if (ctxt == NULL)
! 2340: return(-1);
! 2341:
! 2342: if (doc->URL != NULL) {
! 2343: ret = xmlXIncludeURLPush(ctxt, doc->URL);
! 2344: if (ret < 0)
! 2345: return(-1);
! 2346: }
! 2347: start = ctxt->incNr;
! 2348:
! 2349: /*
! 2350: * First phase: lookup the elements in the document
! 2351: */
! 2352: cur = tree;
! 2353: if (xmlXIncludeTestNode(ctxt, cur) == 1)
! 2354: xmlXIncludePreProcessNode(ctxt, cur);
! 2355: while ((cur != NULL) && (cur != tree->parent)) {
! 2356: /* TODO: need to work on entities -> stack */
! 2357: if ((cur->children != NULL) &&
! 2358: (cur->children->type != XML_ENTITY_DECL) &&
! 2359: (cur->children->type != XML_XINCLUDE_START) &&
! 2360: (cur->children->type != XML_XINCLUDE_END)) {
! 2361: cur = cur->children;
! 2362: if (xmlXIncludeTestNode(ctxt, cur))
! 2363: xmlXIncludePreProcessNode(ctxt, cur);
! 2364: } else if (cur->next != NULL) {
! 2365: cur = cur->next;
! 2366: if (xmlXIncludeTestNode(ctxt, cur))
! 2367: xmlXIncludePreProcessNode(ctxt, cur);
! 2368: } else {
! 2369: if (cur == tree)
! 2370: break;
! 2371: do {
! 2372: cur = cur->parent;
! 2373: if ((cur == NULL) || (cur == tree->parent))
! 2374: break; /* do */
! 2375: if (cur->next != NULL) {
! 2376: cur = cur->next;
! 2377: if (xmlXIncludeTestNode(ctxt, cur))
! 2378: xmlXIncludePreProcessNode(ctxt, cur);
! 2379: break; /* do */
! 2380: }
! 2381: } while (cur != NULL);
! 2382: }
! 2383: }
! 2384:
! 2385: /*
! 2386: * Second Phase : collect the infosets fragments
! 2387: */
! 2388: for (i = start;i < ctxt->incNr; i++) {
! 2389: xmlXIncludeLoadNode(ctxt, i);
! 2390: ret++;
! 2391: }
! 2392:
! 2393: /*
! 2394: * Third phase: extend the original document infoset.
! 2395: *
! 2396: * Originally we bypassed the inclusion if there were any errors
! 2397: * encountered on any of the XIncludes. A bug was raised (bug
! 2398: * 132588) requesting that we output the XIncludes without error,
! 2399: * so the check for inc!=NULL || xptr!=NULL was put in. This may
! 2400: * give some other problems in the future, but for now it seems to
! 2401: * work ok.
! 2402: *
! 2403: */
! 2404: for (i = ctxt->incBase;i < ctxt->incNr; i++) {
! 2405: if ((ctxt->incTab[i]->inc != NULL) ||
! 2406: (ctxt->incTab[i]->xptr != NULL) ||
! 2407: (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
! 2408: xmlXIncludeIncludeNode(ctxt, i);
! 2409: }
! 2410:
! 2411: if (doc->URL != NULL)
! 2412: xmlXIncludeURLPop(ctxt);
! 2413: return(ret);
! 2414: }
! 2415:
! 2416: /**
! 2417: * xmlXIncludeSetFlags:
! 2418: * @ctxt: an XInclude processing context
! 2419: * @flags: a set of xmlParserOption used for parsing XML includes
! 2420: *
! 2421: * Set the flags used for further processing of XML resources.
! 2422: *
! 2423: * Returns 0 in case of success and -1 in case of error.
! 2424: */
! 2425: int
! 2426: xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
! 2427: if (ctxt == NULL)
! 2428: return(-1);
! 2429: ctxt->parseFlags = flags;
! 2430: return(0);
! 2431: }
! 2432:
! 2433: /**
! 2434: * xmlXIncludeProcessTreeFlagsData:
! 2435: * @tree: an XML node
! 2436: * @flags: a set of xmlParserOption used for parsing XML includes
! 2437: * @data: application data that will be passed to the parser context
! 2438: * in the _private field of the parser context(s)
! 2439: *
! 2440: * Implement the XInclude substitution on the XML node @tree
! 2441: *
! 2442: * Returns 0 if no substitution were done, -1 if some processing failed
! 2443: * or the number of substitutions done.
! 2444: */
! 2445:
! 2446: int
! 2447: xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
! 2448: xmlXIncludeCtxtPtr ctxt;
! 2449: int ret = 0;
! 2450:
! 2451: if ((tree == NULL) || (tree->doc == NULL))
! 2452: return(-1);
! 2453:
! 2454: ctxt = xmlXIncludeNewContext(tree->doc);
! 2455: if (ctxt == NULL)
! 2456: return(-1);
! 2457: ctxt->_private = data;
! 2458: ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
! 2459: xmlXIncludeSetFlags(ctxt, flags);
! 2460: ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
! 2461: if ((ret >= 0) && (ctxt->nbErrors > 0))
! 2462: ret = -1;
! 2463:
! 2464: xmlXIncludeFreeContext(ctxt);
! 2465: return(ret);
! 2466: }
! 2467:
! 2468: /**
! 2469: * xmlXIncludeProcessFlagsData:
! 2470: * @doc: an XML document
! 2471: * @flags: a set of xmlParserOption used for parsing XML includes
! 2472: * @data: application data that will be passed to the parser context
! 2473: * in the _private field of the parser context(s)
! 2474: *
! 2475: * Implement the XInclude substitution on the XML document @doc
! 2476: *
! 2477: * Returns 0 if no substitution were done, -1 if some processing failed
! 2478: * or the number of substitutions done.
! 2479: */
! 2480: int
! 2481: xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) {
! 2482: xmlNodePtr tree;
! 2483:
! 2484: if (doc == NULL)
! 2485: return(-1);
! 2486: tree = xmlDocGetRootElement(doc);
! 2487: if (tree == NULL)
! 2488: return(-1);
! 2489: return(xmlXIncludeProcessTreeFlagsData(tree, flags, data));
! 2490: }
! 2491:
! 2492: /**
! 2493: * xmlXIncludeProcessFlags:
! 2494: * @doc: an XML document
! 2495: * @flags: a set of xmlParserOption used for parsing XML includes
! 2496: *
! 2497: * Implement the XInclude substitution on the XML document @doc
! 2498: *
! 2499: * Returns 0 if no substitution were done, -1 if some processing failed
! 2500: * or the number of substitutions done.
! 2501: */
! 2502: int
! 2503: xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
! 2504: return xmlXIncludeProcessFlagsData(doc, flags, NULL);
! 2505: }
! 2506:
! 2507: /**
! 2508: * xmlXIncludeProcess:
! 2509: * @doc: an XML document
! 2510: *
! 2511: * Implement the XInclude substitution on the XML document @doc
! 2512: *
! 2513: * Returns 0 if no substitution were done, -1 if some processing failed
! 2514: * or the number of substitutions done.
! 2515: */
! 2516: int
! 2517: xmlXIncludeProcess(xmlDocPtr doc) {
! 2518: return(xmlXIncludeProcessFlags(doc, 0));
! 2519: }
! 2520:
! 2521: /**
! 2522: * xmlXIncludeProcessTreeFlags:
! 2523: * @tree: a node in an XML document
! 2524: * @flags: a set of xmlParserOption used for parsing XML includes
! 2525: *
! 2526: * Implement the XInclude substitution for the given subtree
! 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: xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
! 2533: xmlXIncludeCtxtPtr ctxt;
! 2534: int ret = 0;
! 2535:
! 2536: if ((tree == NULL) || (tree->doc == NULL))
! 2537: return(-1);
! 2538: ctxt = xmlXIncludeNewContext(tree->doc);
! 2539: if (ctxt == NULL)
! 2540: return(-1);
! 2541: ctxt->base = xmlNodeGetBase(tree->doc, tree);
! 2542: xmlXIncludeSetFlags(ctxt, flags);
! 2543: ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
! 2544: if ((ret >= 0) && (ctxt->nbErrors > 0))
! 2545: ret = -1;
! 2546:
! 2547: xmlXIncludeFreeContext(ctxt);
! 2548: return(ret);
! 2549: }
! 2550:
! 2551: /**
! 2552: * xmlXIncludeProcessTree:
! 2553: * @tree: a node in an XML document
! 2554: *
! 2555: * Implement the XInclude substitution for the given subtree
! 2556: *
! 2557: * Returns 0 if no substitution were done, -1 if some processing failed
! 2558: * or the number of substitutions done.
! 2559: */
! 2560: int
! 2561: xmlXIncludeProcessTree(xmlNodePtr tree) {
! 2562: return(xmlXIncludeProcessTreeFlags(tree, 0));
! 2563: }
! 2564:
! 2565: /**
! 2566: * xmlXIncludeProcessNode:
! 2567: * @ctxt: an existing XInclude context
! 2568: * @node: a node in an XML document
! 2569: *
! 2570: * Implement the XInclude substitution for the given subtree reusing
! 2571: * the informations and data coming from the given context.
! 2572: *
! 2573: * Returns 0 if no substitution were done, -1 if some processing failed
! 2574: * or the number of substitutions done.
! 2575: */
! 2576: int
! 2577: xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
! 2578: int ret = 0;
! 2579:
! 2580: if ((node == NULL) || (node->doc == NULL) || (ctxt == NULL))
! 2581: return(-1);
! 2582: ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
! 2583: if ((ret >= 0) && (ctxt->nbErrors > 0))
! 2584: ret = -1;
! 2585: return(ret);
! 2586: }
! 2587:
! 2588: #else /* !LIBXML_XINCLUDE_ENABLED */
! 2589: #endif
! 2590: #define bottom_xinclude
! 2591: #include "elfgcchack.h"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>