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