ReactOS  0.4.15-dev-439-g292f67a
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  xmlXPathObjectPtr xptr; /* the xpointer if needed */
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  xmlNodePtr *txtTab; /* array of unparsed text nodes */
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 
91 static int
92 xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
93 
94 
95 /************************************************************************
96  * *
97  * XInclude error handler *
98  * *
99  ************************************************************************/
100 
107 static void
108 xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node,
109  const char *extra)
110 {
111  if (ctxt != NULL)
112  ctxt->nbErrors++;
113  __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
115  extra, NULL, NULL, 0, 0,
116  "Memory allocation failed : %s\n", extra);
117 }
118 
128 static void LIBXML_ATTR_FORMAT(4,0)
129 xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
130  const char *msg, const xmlChar *extra)
131 {
132  if (ctxt != NULL)
133  ctxt->nbErrors++;
134  __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
135  error, XML_ERR_ERROR, NULL, 0,
136  (const char *) extra, NULL, NULL, 0, 0,
137  msg, (const char *) extra);
138 }
139 
140 #if 0
141 
150 static void LIBXML_ATTR_FORMAT(4,0)
151 xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
152  const char *msg, const xmlChar *extra)
153 {
154  __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE,
156  (const char *) extra, NULL, NULL, 0, 0,
157  msg, (const char *) extra);
158 }
159 #endif
160 
171 static xmlChar *
172 xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur,
173  const xmlChar *name) {
174  xmlChar *ret;
175 
176  ret = xmlGetNsProp(cur, XINCLUDE_NS, name);
177  if (ret != NULL)
178  return(ret);
179  if (ctxt->legacy != 0) {
180  ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name);
181  if (ret != NULL)
182  return(ret);
183  }
184  ret = xmlGetProp(cur, name);
185  return(ret);
186 }
193 static void
194 xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
195  if (ref == NULL)
196  return;
197 #ifdef DEBUG_XINCLUDE
198  xmlGenericError(xmlGenericErrorContext, "Freeing ref\n");
199 #endif
200  if (ref->doc != NULL) {
201 #ifdef DEBUG_XINCLUDE
202  xmlGenericError(xmlGenericErrorContext, "Freeing doc %s\n", ref->URI);
203 #endif
204  xmlFreeDoc(ref->doc);
205  }
206  if (ref->URI != NULL)
207  xmlFree(ref->URI);
208  if (ref->fragment != NULL)
209  xmlFree(ref->fragment);
210  if (ref->xptr != NULL)
211  xmlXPathFreeObject(ref->xptr);
212  xmlFree(ref);
213 }
214 
224 static xmlXIncludeRefPtr
225 xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI,
226  xmlNodePtr ref) {
227  xmlXIncludeRefPtr ret;
228 
229 #ifdef DEBUG_XINCLUDE
230  xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI);
231 #endif
232  ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
233  if (ret == NULL) {
234  xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
235  return(NULL);
236  }
237  memset(ret, 0, sizeof(xmlXIncludeRef));
238  if (URI == NULL)
239  ret->URI = NULL;
240  else
241  ret->URI = xmlStrdup(URI);
242  ret->fragment = NULL;
243  ret->ref = ref;
244  ret->doc = NULL;
245  ret->count = 0;
246  ret->xml = 0;
247  ret->inc = NULL;
248  if (ctxt->incMax == 0) {
249  ctxt->incMax = 4;
250  ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax *
251  sizeof(ctxt->incTab[0]));
252  if (ctxt->incTab == NULL) {
253  xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
254  xmlXIncludeFreeRef(ret);
255  return(NULL);
256  }
257  }
258  if (ctxt->incNr >= ctxt->incMax) {
259  ctxt->incMax *= 2;
260  ctxt->incTab = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
261  ctxt->incMax * sizeof(ctxt->incTab[0]));
262  if (ctxt->incTab == NULL) {
263  xmlXIncludeErrMemory(ctxt, ref, "growing XInclude context");
264  xmlXIncludeFreeRef(ret);
265  return(NULL);
266  }
267  }
268  ctxt->incTab[ctxt->incNr++] = ret;
269  return(ret);
270 }
271 
280 xmlXIncludeCtxtPtr
281 xmlXIncludeNewContext(xmlDocPtr doc) {
282  xmlXIncludeCtxtPtr ret;
283 
284 #ifdef DEBUG_XINCLUDE
285  xmlGenericError(xmlGenericErrorContext, "New context\n");
286 #endif
287  if (doc == NULL)
288  return(NULL);
289  ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt));
290  if (ret == NULL) {
291  xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc,
292  "creating XInclude context");
293  return(NULL);
294  }
295  memset(ret, 0, sizeof(xmlXIncludeCtxt));
296  ret->doc = doc;
297  ret->incNr = 0;
298  ret->incBase = 0;
299  ret->incMax = 0;
300  ret->incTab = NULL;
301  ret->nbErrors = 0;
302  return(ret);
303 }
304 
314 static int
315 xmlXIncludeURLPush(xmlXIncludeCtxtPtr ctxt,
316  const xmlChar *value)
317 {
318  if (ctxt->urlNr > XINCLUDE_MAX_DEPTH) {
319  xmlXIncludeErr(ctxt, NULL, XML_XINCLUDE_RECURSION,
320  "detected a recursion in %s\n", value);
321  return(-1);
322  }
323  if (ctxt->urlTab == NULL) {
324  ctxt->urlMax = 4;
325  ctxt->urlNr = 0;
326  ctxt->urlTab = (xmlChar * *) xmlMalloc(
327  ctxt->urlMax * sizeof(ctxt->urlTab[0]));
328  if (ctxt->urlTab == NULL) {
329  xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
330  return (-1);
331  }
332  }
333  if (ctxt->urlNr >= ctxt->urlMax) {
334  ctxt->urlMax *= 2;
335  ctxt->urlTab =
336  (xmlChar * *) xmlRealloc(ctxt->urlTab,
337  ctxt->urlMax *
338  sizeof(ctxt->urlTab[0]));
339  if (ctxt->urlTab == NULL) {
340  xmlXIncludeErrMemory(ctxt, NULL, "adding URL");
341  return (-1);
342  }
343  }
344  ctxt->url = ctxt->urlTab[ctxt->urlNr] = xmlStrdup(value);
345  return (ctxt->urlNr++);
346 }
347 
354 static void
355 xmlXIncludeURLPop(xmlXIncludeCtxtPtr ctxt)
356 {
357  xmlChar * ret;
358 
359  if (ctxt->urlNr <= 0)
360  return;
361  ctxt->urlNr--;
362  if (ctxt->urlNr > 0)
363  ctxt->url = ctxt->urlTab[ctxt->urlNr - 1];
364  else
365  ctxt->url = NULL;
366  ret = ctxt->urlTab[ctxt->urlNr];
367  ctxt->urlTab[ctxt->urlNr] = NULL;
368  if (ret != NULL)
369  xmlFree(ret);
370 }
371 
378 void
379 xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
380  int i;
381 
382 #ifdef DEBUG_XINCLUDE
383  xmlGenericError(xmlGenericErrorContext, "Freeing context\n");
384 #endif
385  if (ctxt == NULL)
386  return;
387  while (ctxt->urlNr > 0)
388  xmlXIncludeURLPop(ctxt);
389  if (ctxt->urlTab != NULL)
390  xmlFree(ctxt->urlTab);
391  for (i = 0;i < ctxt->incNr;i++) {
392  if (ctxt->incTab[i] != NULL)
393  xmlXIncludeFreeRef(ctxt->incTab[i]);
394  }
395  if (ctxt->txturlTab != NULL) {
396  for (i = 0;i < ctxt->txtNr;i++) {
397  if (ctxt->txturlTab[i] != NULL)
398  xmlFree(ctxt->txturlTab[i]);
399  }
400  }
401  if (ctxt->incTab != NULL)
402  xmlFree(ctxt->incTab);
403  if (ctxt->txtTab != NULL)
404  xmlFree(ctxt->txtTab);
405  if (ctxt->txturlTab != NULL)
406  xmlFree(ctxt->txturlTab);
407  if (ctxt->base != NULL) {
408  xmlFree(ctxt->base);
409  }
410  xmlFree(ctxt);
411 }
412 
420 static xmlDocPtr
421 xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
422  xmlDocPtr ret;
423  xmlParserCtxtPtr pctxt;
424  xmlParserInputPtr inputStream;
425 
426  xmlInitParser();
427 
428  pctxt = xmlNewParserCtxt();
429  if (pctxt == NULL) {
430  xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context");
431  return(NULL);
432  }
433 
434  /*
435  * pass in the application data to the parser context.
436  */
437  pctxt->_private = ctxt->_private;
438 
439  /*
440  * try to ensure that new documents included are actually
441  * built with the same dictionary as the including document.
442  */
443  if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL)) {
444  if (pctxt->dict != NULL)
445  xmlDictFree(pctxt->dict);
446  pctxt->dict = ctxt->doc->dict;
447  xmlDictReference(pctxt->dict);
448  }
449 
450  xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
451 
452  /* Don't read from stdin. */
453  if ((URL != NULL) && (strcmp(URL, "-") == 0))
454  URL = "./-";
455 
456  inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
457  if (inputStream == NULL) {
458  xmlFreeParserCtxt(pctxt);
459  return(NULL);
460  }
461 
462  inputPush(pctxt, inputStream);
463 
464  if (pctxt->directory == NULL)
465  pctxt->directory = xmlParserGetDirectory(URL);
466 
467  pctxt->loadsubset |= XML_DETECT_IDS;
468 
469  xmlParseDocument(pctxt);
470 
471  if (pctxt->wellFormed) {
472  ret = pctxt->myDoc;
473  }
474  else {
475  ret = NULL;
476  if (pctxt->myDoc != NULL)
477  xmlFreeDoc(pctxt->myDoc);
478  pctxt->myDoc = NULL;
479  }
480  xmlFreeParserCtxt(pctxt);
481 
482  return(ret);
483 }
484 
492 static int
493 xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
494  xmlXIncludeRefPtr ref;
495  xmlURIPtr uri;
496  xmlChar *URL;
497  xmlChar *fragment = NULL;
498  xmlChar *href;
499  xmlChar *parse;
500  xmlChar *base;
501  xmlChar *URI;
502  int xml = 1, i; /* default Issue 64 */
503  int local = 0;
504 
505 
506  if (ctxt == NULL)
507  return(-1);
508  if (cur == NULL)
509  return(-1);
510 
511 #ifdef DEBUG_XINCLUDE
513 #endif
514  /*
515  * read the attributes
516  */
517  href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
518  if (href == NULL) {
519  href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
520  if (href == NULL)
521  return(-1);
522  }
523  if ((href[0] == '#') || (href[0] == 0))
524  local = 1;
525  parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
526  if (parse != NULL) {
527  if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
528  xml = 1;
529  else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
530  xml = 0;
531  else {
532  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
533  "invalid value %s for 'parse'\n", parse);
534  if (href != NULL)
535  xmlFree(href);
536  if (parse != NULL)
537  xmlFree(parse);
538  return(-1);
539  }
540  }
541 
542  /*
543  * compute the URI
544  */
545  base = xmlNodeGetBase(ctxt->doc, cur);
546  if (base == NULL) {
547  URI = xmlBuildURI(href, ctxt->doc->URL);
548  } else {
549  URI = xmlBuildURI(href, base);
550  }
551  if (URI == NULL) {
552  xmlChar *escbase;
553  xmlChar *eschref;
554  /*
555  * Some escaping may be needed
556  */
557  escbase = xmlURIEscape(base);
558  eschref = xmlURIEscape(href);
559  URI = xmlBuildURI(eschref, escbase);
560  if (escbase != NULL)
561  xmlFree(escbase);
562  if (eschref != NULL)
563  xmlFree(eschref);
564  }
565  if (parse != NULL)
566  xmlFree(parse);
567  if (href != NULL)
568  xmlFree(href);
569  if (base != NULL)
570  xmlFree(base);
571  if (URI == NULL) {
572  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
573  "failed build URL\n", NULL);
574  return(-1);
575  }
576  fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
577 
578  /*
579  * Check the URL and remove any fragment identifier
580  */
581  uri = xmlParseURI((const char *)URI);
582  if (uri == NULL) {
583  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
584  "invalid value URI %s\n", URI);
585  if (fragment != NULL)
586  xmlFree(fragment);
587  xmlFree(URI);
588  return(-1);
589  }
590 
591  if (uri->fragment != NULL) {
592  if (ctxt->legacy != 0) {
593  if (fragment == NULL) {
594  fragment = (xmlChar *) uri->fragment;
595  } else {
596  xmlFree(uri->fragment);
597  }
598  } else {
599  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
600  "Invalid fragment identifier in URI %s use the xpointer attribute\n",
601  URI);
602  if (fragment != NULL)
603  xmlFree(fragment);
604  xmlFreeURI(uri);
605  xmlFree(URI);
606  return(-1);
607  }
608  uri->fragment = NULL;
609  }
610  URL = xmlSaveUri(uri);
611  xmlFreeURI(uri);
612  xmlFree(URI);
613  if (URL == NULL) {
614  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
615  "invalid value URI %s\n", URI);
616  if (fragment != NULL)
617  xmlFree(fragment);
618  return(-1);
619  }
620 
621  /*
622  * If local and xml then we need a fragment
623  */
624  if ((local == 1) && (xml == 1) &&
625  ((fragment == NULL) || (fragment[0] == 0))) {
626  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
627  "detected a local recursion with no xpointer in %s\n",
628  URL);
629  if (fragment != NULL)
630  xmlFree(fragment);
631  return(-1);
632  }
633 
634  /*
635  * Check the URL against the stack for recursions
636  */
637  if ((!local) && (xml == 1)) {
638  for (i = 0;i < ctxt->urlNr;i++) {
639  if (xmlStrEqual(URL, ctxt->urlTab[i])) {
640  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
641  "detected a recursion in %s\n", URL);
642  return(-1);
643  }
644  }
645  }
646 
647  ref = xmlXIncludeNewRef(ctxt, URL, cur);
648  if (ref == NULL) {
649  return(-1);
650  }
651  ref->fragment = fragment;
652  ref->doc = NULL;
653  ref->xml = xml;
654  ref->count = 1;
655  xmlFree(URL);
656  return(0);
657 }
658 
667 static void
668 xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
669  const xmlURL url ATTRIBUTE_UNUSED) {
670  xmlXIncludeCtxtPtr newctxt;
671  int i;
672 
673  /*
674  * Avoid recursion in already substituted resources
675  for (i = 0;i < ctxt->urlNr;i++) {
676  if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
677  return;
678  }
679  */
680 
681 #ifdef DEBUG_XINCLUDE
682  xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
683 #endif
684  /*
685  * Handle recursion here.
686  */
687 
688  newctxt = xmlXIncludeNewContext(doc);
689  if (newctxt != NULL) {
690  /*
691  * Copy the private user data
692  */
693  newctxt->_private = ctxt->_private;
694  /*
695  * Copy the existing document set
696  */
697  newctxt->incMax = ctxt->incMax;
698  newctxt->incNr = ctxt->incNr;
699  newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
700  sizeof(newctxt->incTab[0]));
701  if (newctxt->incTab == NULL) {
702  xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
703  xmlFree(newctxt);
704  return;
705  }
706  /*
707  * copy the urlTab
708  */
709  newctxt->urlMax = ctxt->urlMax;
710  newctxt->urlNr = ctxt->urlNr;
711  newctxt->urlTab = ctxt->urlTab;
712 
713  /*
714  * Inherit the existing base
715  */
716  newctxt->base = xmlStrdup(ctxt->base);
717 
718  /*
719  * Inherit the documents already in use by other includes
720  */
721  newctxt->incBase = ctxt->incNr;
722  for (i = 0;i < ctxt->incNr;i++) {
723  newctxt->incTab[i] = ctxt->incTab[i];
724  newctxt->incTab[i]->count++; /* prevent the recursion from
725  freeing it */
726  }
727  /*
728  * The new context should also inherit the Parse Flags
729  * (bug 132597)
730  */
731  newctxt->parseFlags = ctxt->parseFlags;
732  xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
733  for (i = 0;i < ctxt->incNr;i++) {
734  newctxt->incTab[i]->count--;
735  newctxt->incTab[i] = NULL;
736  }
737 
738  /* urlTab may have been reallocated */
739  ctxt->urlTab = newctxt->urlTab;
740  ctxt->urlMax = newctxt->urlMax;
741 
742  newctxt->urlMax = 0;
743  newctxt->urlNr = 0;
744  newctxt->urlTab = NULL;
745 
746  xmlXIncludeFreeContext(newctxt);
747  }
748 #ifdef DEBUG_XINCLUDE
749  xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
750 #endif
751 }
752 
761 static void
762 xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
763 #ifdef DEBUG_XINCLUDE
764  xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
765 #endif
766  if (ctxt->txtMax == 0) {
767  ctxt->txtMax = 4;
768  ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
769  sizeof(ctxt->txtTab[0]));
770  if (ctxt->txtTab == NULL) {
771  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
772  return;
773  }
774  ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
775  sizeof(ctxt->txturlTab[0]));
776  if (ctxt->txturlTab == NULL) {
777  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
778  return;
779  }
780  }
781  if (ctxt->txtNr >= ctxt->txtMax) {
782  ctxt->txtMax *= 2;
783  ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
784  ctxt->txtMax * sizeof(ctxt->txtTab[0]));
785  if (ctxt->txtTab == NULL) {
786  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
787  return;
788  }
789  ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
790  ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
791  if (ctxt->txturlTab == NULL) {
792  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
793  return;
794  }
795  }
796  ctxt->txtTab[ctxt->txtNr] = txt;
797  ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
798  ctxt->txtNr++;
799 }
800 
801 /************************************************************************
802  * *
803  * Node copy with specific semantic *
804  * *
805  ************************************************************************/
806 
807 static xmlNodePtr
808 xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
810 
821 static xmlNodePtr
822 xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
825 
826  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
827  (elem == NULL))
828  return(NULL);
829  if (elem->type == XML_DTD_NODE)
830  return(NULL);
831  if (elem->type == XML_DOCUMENT_NODE)
832  result = xmlXIncludeCopyNodeList(ctxt, target, source, elem->children);
833  else
835  return(result);
836 }
837 
848 static xmlNodePtr
849 xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
851  xmlNodePtr cur, res, result = NULL, last = NULL;
852 
853  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
854  (elem == NULL))
855  return(NULL);
856  cur = elem;
857  while (cur != NULL) {
858  res = xmlXIncludeCopyNode(ctxt, target, source, cur);
859  if (res != NULL) {
860  if (result == NULL) {
861  result = last = res;
862  } else {
863  last->next = res;
864  res->prev = last;
865  last = res;
866  }
867  }
868  cur = cur->next;
869  }
870  return(result);
871 }
872 
880 static xmlNodePtr
881 xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
882  int i;
883  if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
884  return(NULL);
885  cur = cur->children;
886  for (i = 0;i <= no;cur = cur->next) {
887  if (cur == NULL)
888  return(cur);
889  if ((cur->type == XML_ELEMENT_NODE) ||
890  (cur->type == XML_DOCUMENT_NODE) ||
891  (cur->type == XML_HTML_DOCUMENT_NODE)) {
892  i++;
893  if (i == no)
894  break;
895  }
896  }
897  return(cur);
898 }
899 
900 xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
913 static xmlNodePtr
914 xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
915  xmlDocPtr source, xmlXPathObjectPtr range) {
916  /* pointers to generated nodes */
917  xmlNodePtr list = NULL, last = NULL, listParent = NULL;
918  xmlNodePtr tmp, tmp2;
919  /* pointers to traversal nodes */
920  xmlNodePtr start, cur, end;
921  int index1, index2;
922  int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
923 
924  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
925  (range == NULL))
926  return(NULL);
927  if (range->type != XPATH_RANGE)
928  return(NULL);
929  start = (xmlNodePtr) range->user;
930 
931  if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
932  return(NULL);
933  end = range->user2;
934  if (end == NULL)
935  return(xmlDocCopyNode(start, target, 1));
936  if (end->type == XML_NAMESPACE_DECL)
937  return(NULL);
938 
939  cur = start;
940  index1 = range->index;
941  index2 = range->index2;
942  /*
943  * level is depth of the current node under consideration
944  * list is the pointer to the root of the output tree
945  * listParent is a pointer to the parent of output tree (within
946  the included file) in case we need to add another level
947  * last is a pointer to the last node added to the output tree
948  * lastLevel is the depth of last (relative to the root)
949  */
950  while (cur != NULL) {
951  /*
952  * Check if our output tree needs a parent
953  */
954  if (level < 0) {
955  while (level < 0) {
956  /* copy must include namespaces and properties */
957  tmp2 = xmlDocCopyNode(listParent, target, 2);
958  xmlAddChild(tmp2, list);
959  list = tmp2;
960  listParent = listParent->parent;
961  level++;
962  }
963  last = list;
964  lastLevel = 0;
965  }
966  /*
967  * Check whether we need to change our insertion point
968  */
969  while (level < lastLevel) {
970  last = last->parent;
971  lastLevel --;
972  }
973  if (cur == end) { /* Are we at the end of the range? */
974  if (cur->type == XML_TEXT_NODE) {
975  const xmlChar *content = cur->content;
976  int len;
977 
978  if (content == NULL) {
979  tmp = xmlNewTextLen(NULL, 0);
980  } else {
981  len = index2;
982  if ((cur == start) && (index1 > 1)) {
983  content += (index1 - 1);
984  len -= (index1 - 1);
985  } else {
986  len = index2;
987  }
988  tmp = xmlNewTextLen(content, len);
989  }
990  /* single sub text node selection */
991  if (list == NULL)
992  return(tmp);
993  /* prune and return full set */
994  if (level == lastLevel)
995  xmlAddNextSibling(last, tmp);
996  else
997  xmlAddChild(last, tmp);
998  return(list);
999  } else { /* ending node not a text node */
1000  endLevel = level; /* remember the level of the end node */
1001  endFlag = 1;
1002  /* last node - need to take care of properties + namespaces */
1003  tmp = xmlDocCopyNode(cur, target, 2);
1004  if (list == NULL) {
1005  list = tmp;
1006  listParent = cur->parent;
1007  } else {
1008  if (level == lastLevel)
1009  xmlAddNextSibling(last, tmp);
1010  else {
1011  xmlAddChild(last, tmp);
1012  lastLevel = level;
1013  }
1014  }
1015  last = tmp;
1016 
1017  if (index2 > 1) {
1018  end = xmlXIncludeGetNthChild(cur, index2 - 1);
1019  index2 = 0;
1020  }
1021  if ((cur == start) && (index1 > 1)) {
1022  cur = xmlXIncludeGetNthChild(cur, index1 - 1);
1023  index1 = 0;
1024  } else {
1025  cur = cur->children;
1026  }
1027  level++; /* increment level to show change */
1028  /*
1029  * Now gather the remaining nodes from cur to end
1030  */
1031  continue; /* while */
1032  }
1033  } else if (cur == start) { /* Not at the end, are we at start? */
1034  if ((cur->type == XML_TEXT_NODE) ||
1035  (cur->type == XML_CDATA_SECTION_NODE)) {
1036  const xmlChar *content = cur->content;
1037 
1038  if (content == NULL) {
1039  tmp = xmlNewTextLen(NULL, 0);
1040  } else {
1041  if (index1 > 1) {
1042  content += (index1 - 1);
1043  index1 = 0;
1044  }
1045  tmp = xmlNewText(content);
1046  }
1047  last = list = tmp;
1048  listParent = cur->parent;
1049  } else { /* Not text node */
1050  /*
1051  * start of the range - need to take care of
1052  * properties and namespaces
1053  */
1054  tmp = xmlDocCopyNode(cur, target, 2);
1055  list = last = tmp;
1056  listParent = cur->parent;
1057  if (index1 > 1) { /* Do we need to position? */
1058  cur = xmlXIncludeGetNthChild(cur, index1 - 1);
1059  level = lastLevel = 1;
1060  index1 = 0;
1061  /*
1062  * Now gather the remaining nodes from cur to end
1063  */
1064  continue; /* while */
1065  }
1066  }
1067  } else {
1068  tmp = NULL;
1069  switch (cur->type) {
1070  case XML_DTD_NODE:
1071  case XML_ELEMENT_DECL:
1072  case XML_ATTRIBUTE_DECL:
1073  case XML_ENTITY_NODE:
1074  /* Do not copy DTD informations */
1075  break;
1076  case XML_ENTITY_DECL:
1077  /* handle crossing entities -> stack needed */
1078  break;
1079  case XML_XINCLUDE_START:
1080  case XML_XINCLUDE_END:
1081  /* don't consider it part of the tree content */
1082  break;
1083  case XML_ATTRIBUTE_NODE:
1084  /* Humm, should not happen ! */
1085  break;
1086  default:
1087  /*
1088  * Middle of the range - need to take care of
1089  * properties and namespaces
1090  */
1091  tmp = xmlDocCopyNode(cur, target, 2);
1092  break;
1093  }
1094  if (tmp != NULL) {
1095  if (level == lastLevel)
1096  xmlAddNextSibling(last, tmp);
1097  else {
1098  xmlAddChild(last, tmp);
1099  lastLevel = level;
1100  }
1101  last = tmp;
1102  }
1103  }
1104  /*
1105  * Skip to next node in document order
1106  */
1107  cur = xmlXPtrAdvanceNode(cur, &level);
1108  if (endFlag && (level >= endLevel))
1109  break;
1110  }
1111  return(list);
1112 }
1113 
1127 static xmlNodePtr
1128 xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
1129  xmlDocPtr source, xmlXPathObjectPtr obj) {
1130  xmlNodePtr list = NULL, last = NULL;
1131  int i;
1132 
1133  if (source == NULL)
1134  source = ctxt->doc;
1135  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
1136  (obj == NULL))
1137  return(NULL);
1138  switch (obj->type) {
1139  case XPATH_NODESET: {
1140  xmlNodeSetPtr set = obj->nodesetval;
1141  if (set == NULL)
1142  return(NULL);
1143  for (i = 0;i < set->nodeNr;i++) {
1144  if (set->nodeTab[i] == NULL)
1145  continue;
1146  switch (set->nodeTab[i]->type) {
1147  case XML_TEXT_NODE:
1149  case XML_ELEMENT_NODE:
1150  case XML_ENTITY_REF_NODE:
1151  case XML_ENTITY_NODE:
1152  case XML_PI_NODE:
1153  case XML_COMMENT_NODE:
1154  case XML_DOCUMENT_NODE:
1156 #ifdef LIBXML_DOCB_ENABLED
1157  case XML_DOCB_DOCUMENT_NODE:
1158 #endif
1159  case XML_XINCLUDE_END:
1160  break;
1161  case XML_XINCLUDE_START: {
1162  xmlNodePtr tmp, cur = set->nodeTab[i];
1163 
1164  cur = cur->next;
1165  while (cur != NULL) {
1166  switch(cur->type) {
1167  case XML_TEXT_NODE:
1169  case XML_ELEMENT_NODE:
1170  case XML_ENTITY_REF_NODE:
1171  case XML_ENTITY_NODE:
1172  case XML_PI_NODE:
1173  case XML_COMMENT_NODE:
1174  tmp = xmlXIncludeCopyNode(ctxt, target,
1175  source, cur);
1176  if (last == NULL) {
1177  list = last = tmp;
1178  } else {
1179  xmlAddNextSibling(last, tmp);
1180  last = tmp;
1181  }
1182  cur = cur->next;
1183  continue;
1184  default:
1185  break;
1186  }
1187  break;
1188  }
1189  continue;
1190  }
1191  case XML_ATTRIBUTE_NODE:
1192  case XML_NAMESPACE_DECL:
1195  case XML_NOTATION_NODE:
1196  case XML_DTD_NODE:
1197  case XML_ELEMENT_DECL:
1198  case XML_ATTRIBUTE_DECL:
1199  case XML_ENTITY_DECL:
1200  continue; /* for */
1201  }
1202  if (last == NULL)
1203  list = last = xmlXIncludeCopyNode(ctxt, target, source,
1204  set->nodeTab[i]);
1205  else {
1207  xmlXIncludeCopyNode(ctxt, target, source,
1208  set->nodeTab[i]));
1209  if (last->next != NULL)
1210  last = last->next;
1211  }
1212  }
1213  break;
1214  }
1215 #ifdef LIBXML_XPTR_ENABLED
1216  case XPATH_LOCATIONSET: {
1217  xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1218  if (set == NULL)
1219  return(NULL);
1220  for (i = 0;i < set->locNr;i++) {
1221  if (last == NULL)
1222  list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
1223  set->locTab[i]);
1224  else
1226  xmlXIncludeCopyXPointer(ctxt, target, source,
1227  set->locTab[i]));
1228  if (last != NULL) {
1229  while (last->next != NULL)
1230  last = last->next;
1231  }
1232  }
1233  break;
1234  }
1235  case XPATH_RANGE:
1236  return(xmlXIncludeCopyRange(ctxt, target, source, obj));
1237 #endif
1238  case XPATH_POINT:
1239  /* points are ignored in XInclude */
1240  break;
1241  default:
1242  break;
1243  }
1244  return(list);
1245 }
1246 /************************************************************************
1247  * *
1248  * XInclude I/O handling *
1249  * *
1250  ************************************************************************/
1251 
1252 typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
1253 typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
1254 struct _xmlXIncludeMergeData {
1255  xmlDocPtr doc;
1256  xmlXIncludeCtxtPtr ctxt;
1257 };
1258 
1267 static void
1268 xmlXIncludeMergeEntity(void *payload, void *vdata,
1269  const xmlChar *name ATTRIBUTE_UNUSED) {
1270  xmlEntityPtr ent = (xmlEntityPtr) payload;
1271  xmlXIncludeMergeDataPtr data = (xmlXIncludeMergeDataPtr) vdata;
1272  xmlEntityPtr ret, prev;
1273  xmlDocPtr doc;
1274  xmlXIncludeCtxtPtr ctxt;
1275 
1276  if ((ent == NULL) || (data == NULL))
1277  return;
1278  ctxt = data->ctxt;
1279  doc = data->doc;
1280  if ((ctxt == NULL) || (doc == NULL))
1281  return;
1282  switch (ent->etype) {
1286  return;
1290  break;
1291  }
1292  ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
1293  ent->SystemID, ent->content);
1294  if (ret != NULL) {
1295  if (ent->URI != NULL)
1296  ret->URI = xmlStrdup(ent->URI);
1297  } else {
1298  prev = xmlGetDocEntity(doc, ent->name);
1299  if (prev != NULL) {
1300  if (ent->etype != prev->etype)
1301  goto error;
1302 
1303  if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
1304  if (!xmlStrEqual(ent->SystemID, prev->SystemID))
1305  goto error;
1306  } else if ((ent->ExternalID != NULL) &&
1307  (prev->ExternalID != NULL)) {
1308  if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
1309  goto error;
1310  } else if ((ent->content != NULL) && (prev->content != NULL)) {
1311  if (!xmlStrEqual(ent->content, prev->content))
1312  goto error;
1313  } else {
1314  goto error;
1315  }
1316 
1317  }
1318  }
1319  return;
1320 error:
1321  switch (ent->etype) {
1327  return;
1329  break;
1330  }
1331  xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
1332  "mismatch in redefinition of entity %s\n",
1333  ent->name);
1334 }
1335 
1346 static int
1347 xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
1348  xmlDocPtr from) {
1349  xmlNodePtr cur;
1351 
1352  if (ctxt == NULL)
1353  return(-1);
1354 
1355  if ((from == NULL) || (from->intSubset == NULL))
1356  return(0);
1357 
1358  target = doc->intSubset;
1359  if (target == NULL) {
1360  cur = xmlDocGetRootElement(doc);
1361  if (cur == NULL)
1362  return(-1);
1363  target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
1364  if (target == NULL)
1365  return(-1);
1366  }
1367 
1368  source = from->intSubset;
1369  if ((source != NULL) && (source->entities != NULL)) {
1370  xmlXIncludeMergeData data;
1371 
1372  data.ctxt = ctxt;
1373  data.doc = doc;
1374 
1375  xmlHashScan((xmlHashTablePtr) source->entities,
1376  xmlXIncludeMergeEntity, &data);
1377  }
1378  source = from->extSubset;
1379  if ((source != NULL) && (source->entities != NULL)) {
1380  xmlXIncludeMergeData data;
1381 
1382  data.ctxt = ctxt;
1383  data.doc = doc;
1384 
1385  /*
1386  * don't duplicate existing stuff when external subsets are the same
1387  */
1388  if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
1389  (!xmlStrEqual(target->SystemID, source->SystemID))) {
1390  xmlHashScan((xmlHashTablePtr) source->entities,
1391  xmlXIncludeMergeEntity, &data);
1392  }
1393  }
1394  return(0);
1395 }
1396 
1407 static int
1408 xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1409  xmlDocPtr doc;
1410  xmlURIPtr uri;
1411  xmlChar *URL;
1412  xmlChar *fragment = NULL;
1413  int i = 0;
1414 #ifdef LIBXML_XPTR_ENABLED
1415  int saveFlags;
1416 #endif
1417 
1418 #ifdef DEBUG_XINCLUDE
1419  xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
1420 #endif
1421  /*
1422  * Check the URL and remove any fragment identifier
1423  */
1424  uri = xmlParseURI((const char *)url);
1425  if (uri == NULL) {
1426  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1428  "invalid value URI %s\n", url);
1429  return(-1);
1430  }
1431  if (uri->fragment != NULL) {
1432  fragment = (xmlChar *) uri->fragment;
1433  uri->fragment = NULL;
1434  }
1435  if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
1436  (ctxt->incTab[nr]->fragment != NULL)) {
1437  if (fragment != NULL) xmlFree(fragment);
1438  fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
1439  }
1440  URL = xmlSaveUri(uri);
1441  xmlFreeURI(uri);
1442  if (URL == NULL) {
1443  if (ctxt->incTab != NULL)
1444  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1446  "invalid value URI %s\n", url);
1447  else
1448  xmlXIncludeErr(ctxt, NULL,
1450  "invalid value URI %s\n", url);
1451  if (fragment != NULL)
1452  xmlFree(fragment);
1453  return(-1);
1454  }
1455 
1456  /*
1457  * Handling of references to the local document are done
1458  * directly through ctxt->doc.
1459  */
1460  if ((URL[0] == 0) || (URL[0] == '#') ||
1461  ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
1462  doc = NULL;
1463  goto loaded;
1464  }
1465 
1466  /*
1467  * Prevent reloading twice the document.
1468  */
1469  for (i = 0; i < ctxt->incNr; i++) {
1470  if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
1471  (ctxt->incTab[i]->doc != NULL)) {
1472  doc = ctxt->incTab[i]->doc;
1473 #ifdef DEBUG_XINCLUDE
1474  printf("Already loaded %s\n", URL);
1475 #endif
1476  goto loaded;
1477  }
1478  }
1479 
1480  /*
1481  * Load it.
1482  */
1483 #ifdef DEBUG_XINCLUDE
1484  printf("loading %s\n", URL);
1485 #endif
1486 #ifdef LIBXML_XPTR_ENABLED
1487  /*
1488  * If this is an XPointer evaluation, we want to assure that
1489  * all entities have been resolved prior to processing the
1490  * referenced document
1491  */
1492  saveFlags = ctxt->parseFlags;
1493  if (fragment != NULL) { /* if this is an XPointer eval */
1494  ctxt->parseFlags |= XML_PARSE_NOENT;
1495  }
1496 #endif
1497 
1498  doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
1499 #ifdef LIBXML_XPTR_ENABLED
1500  ctxt->parseFlags = saveFlags;
1501 #endif
1502  if (doc == NULL) {
1503  xmlFree(URL);
1504  if (fragment != NULL)
1505  xmlFree(fragment);
1506  return(-1);
1507  }
1508  ctxt->incTab[nr]->doc = doc;
1509  /*
1510  * It's possible that the requested URL has been mapped to a
1511  * completely different location (e.g. through a catalog entry).
1512  * To check for this, we compare the URL with that of the doc
1513  * and change it if they disagree (bug 146988).
1514  */
1515  if (!xmlStrEqual(URL, doc->URL)) {
1516  xmlFree(URL);
1517  URL = xmlStrdup(doc->URL);
1518  }
1519  for (i = nr + 1; i < ctxt->incNr; i++) {
1520  if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
1521  ctxt->incTab[nr]->count++;
1522 #ifdef DEBUG_XINCLUDE
1523  printf("Increasing %s count since reused\n", URL);
1524 #endif
1525  break;
1526  }
1527  }
1528 
1529  /*
1530  * Make sure we have all entities fixed up
1531  */
1532  xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
1533 
1534  /*
1535  * We don't need the DTD anymore, free up space
1536  if (doc->intSubset != NULL) {
1537  xmlUnlinkNode((xmlNodePtr) doc->intSubset);
1538  xmlFreeNode((xmlNodePtr) doc->intSubset);
1539  doc->intSubset = NULL;
1540  }
1541  if (doc->extSubset != NULL) {
1542  xmlUnlinkNode((xmlNodePtr) doc->extSubset);
1543  xmlFreeNode((xmlNodePtr) doc->extSubset);
1544  doc->extSubset = NULL;
1545  }
1546  */
1547  xmlXIncludeRecurseDoc(ctxt, doc, URL);
1548 
1549 loaded:
1550  if (fragment == NULL) {
1551  /*
1552  * Add the top children list as the replacement copy.
1553  */
1554  if (doc == NULL)
1555  {
1556  /* Hopefully a DTD declaration won't be copied from
1557  * the same document */
1558  ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
1559  } else {
1560  ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
1561  doc, doc->children);
1562  }
1563  }
1564 #ifdef LIBXML_XPTR_ENABLED
1565  else {
1566  /*
1567  * Computes the XPointer expression and make a copy used
1568  * as the replacement copy.
1569  */
1570  xmlXPathObjectPtr xptr;
1571  xmlXPathContextPtr xptrctxt;
1572  xmlNodeSetPtr set;
1573 
1574  if (doc == NULL) {
1575  xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
1576  NULL);
1577  } else {
1578  xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1579  }
1580  if (xptrctxt == NULL) {
1581  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1583  "could not create XPointer context\n", NULL);
1584  xmlFree(URL);
1585  xmlFree(fragment);
1586  return(-1);
1587  }
1588  xptr = xmlXPtrEval(fragment, xptrctxt);
1589  if (xptr == NULL) {
1590  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1592  "XPointer evaluation failed: #%s\n",
1593  fragment);
1594  xmlXPathFreeContext(xptrctxt);
1595  xmlFree(URL);
1596  xmlFree(fragment);
1597  return(-1);
1598  }
1599  switch (xptr->type) {
1600  case XPATH_UNDEFINED:
1601  case XPATH_BOOLEAN:
1602  case XPATH_NUMBER:
1603  case XPATH_STRING:
1604  case XPATH_POINT:
1605  case XPATH_USERS:
1606  case XPATH_XSLT_TREE:
1607  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1609  "XPointer is not a range: #%s\n",
1610  fragment);
1611  xmlXPathFreeContext(xptrctxt);
1612  xmlFree(URL);
1613  xmlFree(fragment);
1614  return(-1);
1615  case XPATH_NODESET:
1616  if ((xptr->nodesetval == NULL) ||
1617  (xptr->nodesetval->nodeNr <= 0)) {
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  if (doc == NULL) {
1682  ctxt->incTab[nr]->xptr = xptr;
1683  ctxt->incTab[nr]->inc = NULL;
1684  } else {
1685  ctxt->incTab[nr]->inc =
1686  xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
1687  xmlXPathFreeObject(xptr);
1688  }
1689  xmlXPathFreeContext(xptrctxt);
1690  xmlFree(fragment);
1691  }
1692 #endif
1693 
1694  /*
1695  * Do the xml:base fixup if needed
1696  */
1697  if ((doc != NULL) && (URL != NULL) &&
1698  (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) &&
1699  (!(doc->parseFlags & XML_PARSE_NOBASEFIX))) {
1700  xmlNodePtr node;
1701  xmlChar *base;
1702  xmlChar *curBase;
1703 
1704  /*
1705  * The base is only adjusted if "necessary", i.e. if the xinclude node
1706  * has a base specified, or the URL is relative
1707  */
1708  base = xmlGetNsProp(ctxt->incTab[nr]->ref, BAD_CAST "base",
1710  if (base == NULL) {
1711  /*
1712  * No xml:base on the xinclude node, so we check whether the
1713  * URI base is different than (relative to) the context base
1714  */
1715  curBase = xmlBuildRelativeURI(URL, ctxt->base);
1716  if (curBase == NULL) { /* Error return */
1717  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1719  "trying to build relative URI from %s\n", URL);
1720  } else {
1721  /* If the URI doesn't contain a slash, it's not relative */
1722  if (!xmlStrchr(curBase, (xmlChar) '/'))
1723  xmlFree(curBase);
1724  else
1725  base = curBase;
1726  }
1727  }
1728  if (base != NULL) { /* Adjustment may be needed */
1729  node = ctxt->incTab[nr]->inc;
1730  while (node != NULL) {
1731  /* Only work on element nodes */
1732  if (node->type == XML_ELEMENT_NODE) {
1733  curBase = xmlNodeGetBase(node->doc, node);
1734  /* If no current base, set it */
1735  if (curBase == NULL) {
1736  xmlNodeSetBase(node, base);
1737  } else {
1738  /*
1739  * If the current base is the same as the
1740  * URL of the document, then reset it to be
1741  * the specified xml:base or the relative URI
1742  */
1743  if (xmlStrEqual(curBase, node->doc->URL)) {
1744  xmlNodeSetBase(node, base);
1745  } else {
1746  /*
1747  * If the element already has an xml:base
1748  * set, then relativise it if necessary
1749  */
1750  xmlChar *xmlBase;
1751  xmlBase = xmlGetNsProp(node,
1752  BAD_CAST "base",
1754  if (xmlBase != NULL) {
1755  xmlChar *relBase;
1756  relBase = xmlBuildURI(xmlBase, base);
1757  if (relBase == NULL) { /* error */
1758  xmlXIncludeErr(ctxt,
1759  ctxt->incTab[nr]->ref,
1761  "trying to rebuild base from %s\n",
1762  xmlBase);
1763  } else {
1764  xmlNodeSetBase(node, relBase);
1765  xmlFree(relBase);
1766  }
1767  xmlFree(xmlBase);
1768  }
1769  }
1770  xmlFree(curBase);
1771  }
1772  }
1773  node = node->next;
1774  }
1775  xmlFree(base);
1776  }
1777  }
1778  if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
1779  (ctxt->incTab[nr]->count <= 1)) {
1780 #ifdef DEBUG_XINCLUDE
1781  printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
1782 #endif
1783  xmlFreeDoc(ctxt->incTab[nr]->doc);
1784  ctxt->incTab[nr]->doc = NULL;
1785  }
1786  xmlFree(URL);
1787  return(0);
1788 }
1789 
1800 static int
1801 xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1803  xmlNodePtr node;
1804  xmlURIPtr uri;
1805  xmlChar *URL;
1806  int i;
1807  xmlChar *encoding = NULL;
1808  xmlCharEncoding enc = (xmlCharEncoding) 0;
1809  xmlParserCtxtPtr pctxt;
1810  xmlParserInputPtr inputStream;
1811  int xinclude_multibyte_fallback_used = 0;
1812 
1813  /* Don't read from stdin. */
1814  if (xmlStrcmp(url, BAD_CAST "-") == 0)
1815  url = BAD_CAST "./-";
1816 
1817  /*
1818  * Check the URL and remove any fragment identifier
1819  */
1820  uri = xmlParseURI((const char *)url);
1821  if (uri == NULL) {
1822  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1823  "invalid value URI %s\n", url);
1824  return(-1);
1825  }
1826  if (uri->fragment != NULL) {
1827  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
1828  "fragment identifier forbidden for text: %s\n",
1829  (const xmlChar *) uri->fragment);
1830  xmlFreeURI(uri);
1831  return(-1);
1832  }
1833  URL = xmlSaveUri(uri);
1834  xmlFreeURI(uri);
1835  if (URL == NULL) {
1836  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1837  "invalid value URI %s\n", url);
1838  return(-1);
1839  }
1840 
1841  /*
1842  * Handling of references to the local document are done
1843  * directly through ctxt->doc.
1844  */
1845  if (URL[0] == 0) {
1846  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1848  "text serialization of document not available\n", NULL);
1849  xmlFree(URL);
1850  return(-1);
1851  }
1852 
1853  /*
1854  * Prevent reloading twice the document.
1855  */
1856  for (i = 0; i < ctxt->txtNr; i++) {
1857  if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
1858  node = xmlCopyNode(ctxt->txtTab[i], 1);
1859  goto loaded;
1860  }
1861  }
1862  /*
1863  * Try to get the encoding if available
1864  */
1865  if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
1866  encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
1867  }
1868  if (encoding != NULL) {
1869  /*
1870  * TODO: we should not have to remap to the xmlCharEncoding
1871  * predefined set, a better interface than
1872  * xmlParserInputBufferCreateFilename should allow any
1873  * encoding supported by iconv
1874  */
1875  enc = xmlParseCharEncoding((const char *) encoding);
1876  if (enc == XML_CHAR_ENCODING_ERROR) {
1877  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1879  "encoding %s not supported\n", encoding);
1880  xmlFree(encoding);
1881  xmlFree(URL);
1882  return(-1);
1883  }
1884  xmlFree(encoding);
1885  }
1886 
1887  /*
1888  * Load it.
1889  */
1890  pctxt = xmlNewParserCtxt();
1891  inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt);
1892  if(inputStream == NULL) {
1893  xmlFreeParserCtxt(pctxt);
1894  xmlFree(URL);
1895  return(-1);
1896  }
1897  buf = inputStream->buf;
1898  if (buf == NULL) {
1899  xmlFreeInputStream (inputStream);
1900  xmlFreeParserCtxt(pctxt);
1901  xmlFree(URL);
1902  return(-1);
1903  }
1904  if (buf->encoder)
1905  xmlCharEncCloseFunc(buf->encoder);
1906  buf->encoder = xmlGetCharEncodingHandler(enc);
1907  node = xmlNewText(NULL);
1908 
1909  /*
1910  * Scan all chars from the resource and add the to the node
1911  */
1912 xinclude_multibyte_fallback:
1913  while (xmlParserInputBufferRead(buf, 128) > 0) {
1914  int len;
1915  const xmlChar *content;
1916 
1917  content = xmlBufContent(buf->buffer);
1918  len = xmlBufLength(buf->buffer);
1919  for (i = 0;i < len;) {
1920  int cur;
1921  int l;
1922 
1923  cur = xmlStringCurrentChar(NULL, &content[i], &l);
1924  if (!IS_CHAR(cur)) {
1925  /* Handle split multibyte char at buffer boundary */
1926  if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) {
1927  xinclude_multibyte_fallback_used = 1;
1928  xmlBufShrink(buf->buffer, i);
1929  goto xinclude_multibyte_fallback;
1930  } else {
1931  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1933  "%s contains invalid char\n", URL);
1934  xmlFreeParserCtxt(pctxt);
1936  xmlFree(URL);
1937  return(-1);
1938  }
1939  } else {
1940  xinclude_multibyte_fallback_used = 0;
1942  }
1943  i += l;
1944  }
1945  xmlBufShrink(buf->buffer, len);
1946  }
1947  xmlFreeParserCtxt(pctxt);
1948  xmlXIncludeAddTxt(ctxt, node, URL);
1949  xmlFreeInputStream(inputStream);
1950 
1951 loaded:
1952  /*
1953  * Add the element as the replacement copy.
1954  */
1955  ctxt->incTab[nr]->inc = node;
1956  xmlFree(URL);
1957  return(0);
1958 }
1959 
1971 static int
1972 xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
1973  xmlXIncludeCtxtPtr newctxt;
1974  int ret = 0;
1975  int oldNbErrors = ctxt->nbErrors;
1976 
1977  if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
1978  (ctxt == NULL))
1979  return(-1);
1980  if (fallback->children != NULL) {
1981  /*
1982  * It's possible that the fallback also has 'includes'
1983  * (Bug 129969), so we re-process the fallback just in case
1984  */
1985  newctxt = xmlXIncludeNewContext(ctxt->doc);
1986  if (newctxt == NULL)
1987  return (-1);
1988  newctxt->_private = ctxt->_private;
1989  newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
1990  xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
1991  ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
1992  if (ctxt->nbErrors > oldNbErrors)
1993  ret = -1;
1994  else if (ret > 0)
1995  ret = 0; /* xmlXIncludeDoProcess can return +ve number */
1996  xmlXIncludeFreeContext(newctxt);
1997 
1998  ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
1999  fallback->children);
2000  } else {
2001  ctxt->incTab[nr]->inc = NULL;
2002  ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
2003  }
2004  return(ret);
2005 }
2006 
2007 /************************************************************************
2008  * *
2009  * XInclude Processing *
2010  * *
2011  ************************************************************************/
2012 
2023 static xmlNodePtr
2024 xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2025  xmlXIncludeAddNode(ctxt, node);
2026  return(NULL);
2027 }
2028 
2038 static int
2039 xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
2040  xmlNodePtr cur;
2041  xmlChar *href;
2042  xmlChar *parse;
2043  xmlChar *base;
2044  xmlChar *oldBase;
2045  xmlChar *URI;
2046  int xml = 1; /* default Issue 64 */
2047  int ret;
2048 
2049  if (ctxt == NULL)
2050  return(-1);
2051  if ((nr < 0) || (nr >= ctxt->incNr))
2052  return(-1);
2053  cur = ctxt->incTab[nr]->ref;
2054  if (cur == NULL)
2055  return(-1);
2056 
2057  /*
2058  * read the attributes
2059  */
2060  href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
2061  if (href == NULL) {
2062  href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
2063  if (href == NULL)
2064  return(-1);
2065  }
2066  parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
2067  if (parse != NULL) {
2068  if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
2069  xml = 1;
2070  else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
2071  xml = 0;
2072  else {
2073  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2075  "invalid value %s for 'parse'\n", parse);
2076  if (href != NULL)
2077  xmlFree(href);
2078  if (parse != NULL)
2079  xmlFree(parse);
2080  return(-1);
2081  }
2082  }
2083 
2084  /*
2085  * compute the URI
2086  */
2087  base = xmlNodeGetBase(ctxt->doc, cur);
2088  if (base == NULL) {
2089  URI = xmlBuildURI(href, ctxt->doc->URL);
2090  } else {
2091  URI = xmlBuildURI(href, base);
2092  }
2093  if (URI == NULL) {
2094  xmlChar *escbase;
2095  xmlChar *eschref;
2096  /*
2097  * Some escaping may be needed
2098  */
2099  escbase = xmlURIEscape(base);
2100  eschref = xmlURIEscape(href);
2101  URI = xmlBuildURI(eschref, escbase);
2102  if (escbase != NULL)
2103  xmlFree(escbase);
2104  if (eschref != NULL)
2105  xmlFree(eschref);
2106  }
2107  if (URI == NULL) {
2108  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2109  XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
2110  if (parse != NULL)
2111  xmlFree(parse);
2112  if (href != NULL)
2113  xmlFree(href);
2114  if (base != NULL)
2115  xmlFree(base);
2116  return(-1);
2117  }
2118 #ifdef DEBUG_XINCLUDE
2119  xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
2120  xml ? "xml": "text");
2121  xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
2122 #endif
2123 
2124  /*
2125  * Save the base for this include (saving the current one)
2126  */
2127  oldBase = ctxt->base;
2128  ctxt->base = base;
2129 
2130  if (xml) {
2131  ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
2132  /* xmlXIncludeGetFragment(ctxt, cur, URI); */
2133  } else {
2134  ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
2135  }
2136 
2137  /*
2138  * Restore the original base before checking for fallback
2139  */
2140  ctxt->base = oldBase;
2141 
2142  if (ret < 0) {
2143  xmlNodePtr children;
2144 
2145  /*
2146  * Time to try a fallback if available
2147  */
2148 #ifdef DEBUG_XINCLUDE
2149  xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
2150 #endif
2151  children = cur->children;
2152  while (children != NULL) {
2153  if ((children->type == XML_ELEMENT_NODE) &&
2154  (children->ns != NULL) &&
2155  (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
2156  ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
2157  (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
2158  ret = xmlXIncludeLoadFallback(ctxt, children, nr);
2159  if (ret == 0)
2160  break;
2161  }
2162  children = children->next;
2163  }
2164  }
2165  if (ret < 0) {
2166  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2168  "could not load %s, and no fallback was found\n",
2169  URI);
2170  }
2171 
2172  /*
2173  * Cleanup
2174  */
2175  if (URI != NULL)
2176  xmlFree(URI);
2177  if (parse != NULL)
2178  xmlFree(parse);
2179  if (href != NULL)
2180  xmlFree(href);
2181  if (base != NULL)
2182  xmlFree(base);
2183  return(0);
2184 }
2185 
2195 static int
2196 xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
2197  xmlNodePtr cur, end, list, tmp;
2198 
2199  if (ctxt == NULL)
2200  return(-1);
2201  if ((nr < 0) || (nr >= ctxt->incNr))
2202  return(-1);
2203  cur = ctxt->incTab[nr]->ref;
2204  if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2205  return(-1);
2206 
2207  /*
2208  * If we stored an XPointer a late computation may be needed
2209  */
2210  if ((ctxt->incTab[nr]->inc == NULL) &&
2211  (ctxt->incTab[nr]->xptr != NULL)) {
2212  ctxt->incTab[nr]->inc =
2213  xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
2214  ctxt->incTab[nr]->xptr);
2215  xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
2216  ctxt->incTab[nr]->xptr = NULL;
2217  }
2218  list = ctxt->incTab[nr]->inc;
2219  ctxt->incTab[nr]->inc = NULL;
2220 
2221  /*
2222  * Check against the risk of generating a multi-rooted document
2223  */
2224  if ((cur->parent != NULL) &&
2225  (cur->parent->type != XML_ELEMENT_NODE)) {
2226  int nb_elem = 0;
2227 
2228  tmp = list;
2229  while (tmp != NULL) {
2230  if (tmp->type == XML_ELEMENT_NODE)
2231  nb_elem++;
2232  tmp = tmp->next;
2233  }
2234  if (nb_elem > 1) {
2235  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2237  "XInclude error: would result in multiple root nodes\n",
2238  NULL);
2239  return(-1);
2240  }
2241  }
2242 
2243  if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
2244  /*
2245  * Add the list of nodes
2246  */
2247  while (list != NULL) {
2248  end = list;
2249  list = list->next;
2250 
2251  xmlAddPrevSibling(cur, end);
2252  }
2253  xmlUnlinkNode(cur);
2254  xmlFreeNode(cur);
2255  } else {
2256  /*
2257  * Change the current node as an XInclude start one, and add an
2258  * XInclude end one
2259  */
2260  cur->type = XML_XINCLUDE_START;
2261  end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
2262  if (end == NULL) {
2263  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2265  "failed to build node\n", NULL);
2266  return(-1);
2267  }
2268  end->type = XML_XINCLUDE_END;
2269  xmlAddNextSibling(cur, 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 
2373 static int
2374 xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
2375  xmlNodePtr cur;
2376  int ret = 0;
2377  int i, start;
2378 
2379  if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2380  return(-1);
2381  if (ctxt == NULL)
2382  return(-1);
2383 
2384  if (doc->URL != NULL) {
2385  ret = xmlXIncludeURLPush(ctxt, doc->URL);
2386  if (ret < 0)
2387  return(-1);
2388  }
2389  start = ctxt->incNr;
2390 
2391  /*
2392  * First phase: lookup the elements in the document
2393  */
2394  cur = tree;
2395  if (xmlXIncludeTestNode(ctxt, cur) == 1)
2396  xmlXIncludePreProcessNode(ctxt, cur);
2397  while ((cur != NULL) && (cur != tree->parent)) {
2398  /* TODO: need to work on entities -> stack */
2399  if ((cur->children != NULL) &&
2400  (cur->children->type != XML_ENTITY_DECL) &&
2401  (cur->children->type != XML_XINCLUDE_START) &&
2402  (cur->children->type != XML_XINCLUDE_END)) {
2403  cur = cur->children;
2404  if (xmlXIncludeTestNode(ctxt, cur))
2405  xmlXIncludePreProcessNode(ctxt, cur);
2406  } else if (cur->next != NULL) {
2407  cur = cur->next;
2408  if (xmlXIncludeTestNode(ctxt, cur))
2409  xmlXIncludePreProcessNode(ctxt, cur);
2410  } else {
2411  if (cur == tree)
2412  break;
2413  do {
2414  cur = cur->parent;
2415  if ((cur == NULL) || (cur == tree->parent))
2416  break; /* do */
2417  if (cur->next != NULL) {
2418  cur = cur->next;
2419  if (xmlXIncludeTestNode(ctxt, cur))
2420  xmlXIncludePreProcessNode(ctxt, cur);
2421  break; /* do */
2422  }
2423  } while (cur != NULL);
2424  }
2425  }
2426 
2427  /*
2428  * Second Phase : collect the infosets fragments
2429  */
2430  for (i = start;i < ctxt->incNr; i++) {
2431  xmlXIncludeLoadNode(ctxt, i);
2432  ret++;
2433  }
2434 
2435  /*
2436  * Third phase: extend the original document infoset.
2437  *
2438  * Originally we bypassed the inclusion if there were any errors
2439  * encountered on any of the XIncludes. A bug was raised (bug
2440  * 132588) requesting that we output the XIncludes without error,
2441  * so the check for inc!=NULL || xptr!=NULL was put in. This may
2442  * give some other problems in the future, but for now it seems to
2443  * work ok.
2444  *
2445  */
2446  for (i = ctxt->incBase;i < ctxt->incNr; i++) {
2447  if ((ctxt->incTab[i]->inc != NULL) ||
2448  (ctxt->incTab[i]->xptr != NULL) ||
2449  (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
2450  xmlXIncludeIncludeNode(ctxt, i);
2451  }
2452 
2453  if (doc->URL != NULL)
2454  xmlXIncludeURLPop(ctxt);
2455  return(ret);
2456 }
2457 
2467 int
2468 xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
2469  if (ctxt == NULL)
2470  return(-1);
2471  ctxt->parseFlags = flags;
2472  return(0);
2473 }
2474 
2488 int
2489 xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
2490  xmlXIncludeCtxtPtr ctxt;
2491  int ret = 0;
2492 
2493  if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2494  (tree->doc == NULL))
2495  return(-1);
2496 
2497  ctxt = xmlXIncludeNewContext(tree->doc);
2498  if (ctxt == NULL)
2499  return(-1);
2500  ctxt->_private = data;
2501  ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
2502  xmlXIncludeSetFlags(ctxt, flags);
2503  ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2504  if ((ret >= 0) && (ctxt->nbErrors > 0))
2505  ret = -1;
2506 
2507  xmlXIncludeFreeContext(ctxt);
2508  return(ret);
2509 }
2510 
2523 int
2524 xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) {
2525  xmlNodePtr tree;
2526 
2527  if (doc == NULL)
2528  return(-1);
2529  tree = xmlDocGetRootElement(doc);
2530  if (tree == NULL)
2531  return(-1);
2532  return(xmlXIncludeProcessTreeFlagsData(tree, flags, data));
2533 }
2534 
2545 int
2546 xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
2547  return xmlXIncludeProcessFlagsData(doc, flags, NULL);
2548 }
2549 
2559 int
2560 xmlXIncludeProcess(xmlDocPtr doc) {
2561  return(xmlXIncludeProcessFlags(doc, 0));
2562 }
2563 
2574 int
2575 xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
2576  xmlXIncludeCtxtPtr ctxt;
2577  int ret = 0;
2578 
2579  if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2580  (tree->doc == NULL))
2581  return(-1);
2582  ctxt = xmlXIncludeNewContext(tree->doc);
2583  if (ctxt == NULL)
2584  return(-1);
2585  ctxt->base = xmlNodeGetBase(tree->doc, tree);
2586  xmlXIncludeSetFlags(ctxt, flags);
2587  ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2588  if ((ret >= 0) && (ctxt->nbErrors > 0))
2589  ret = -1;
2590 
2591  xmlXIncludeFreeContext(ctxt);
2592  return(ret);
2593 }
2594 
2604 int
2605 xmlXIncludeProcessTree(xmlNodePtr tree) {
2606  return(xmlXIncludeProcessTreeFlags(tree, 0));
2607 }
2608 
2620 int
2621 xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2622  int ret = 0;
2623 
2624  if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
2625  (node->doc == NULL) || (ctxt == NULL))
2626  return(-1);
2627  ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
2628  if ((ret >= 0) && (ctxt->nbErrors > 0))
2629  ret = -1;
2630  return(ret);
2631 }
2632 
2633 #else /* !LIBXML_XINCLUDE_ENABLED */
2634 #endif
2635 #define bottom_xinclude
2636 #include "elfgcchack.h"
xmlEntityType etype
Definition: entities.h:52
XMLPUBFUN xmlChar *XMLCALL xmlBuildRelativeURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:2165
GLint level
Definition: gl.h:1546
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:645
XMLPUBFUN xmlCharEncoding XMLCALL xmlParseCharEncoding(const char *name)
Definition: encoding.c:1150
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
const xmlChar * name
Definition: tree.h:492
XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlGetCharEncodingHandler(xmlCharEncoding enc)
Definition: encoding.c:1507
ULONG nr
Definition: thread.c:7
struct _xmlDtd * intSubset
Definition: tree.h:570
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
POINT last
Definition: font.c:46
const char * uri
Definition: sec_mgr.c:1588
XMLPUBFUN void XMLCALL xmlInitParser(void)
Definition: parser.c:14740
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct _tree tree
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:1718
XMLPUBFUN void XMLCALL xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
size_t xmlBufLength(const xmlBufPtr buf)
Definition: buf.c:668
xmlCharEncoding
Definition: encoding.h:58
GLuint GLuint end
Definition: gl.h:1545
XMLPUBFUN xmlURIPtr XMLCALL xmlParseURI(const char *str)
Definition: uri.c:934
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur)
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:321
const xmlChar * URI
Definition: entities.h:57
Definition: send.c:48
static HWND child
Definition: cursoricon.c:298
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode(xmlNodePtr node, int recursive)
struct _xmlDoc * doc
Definition: tree.h:498
Definition: tree.h:406
struct _xmlDoc * doc
Definition: tree.h:560
XMLPUBFUN xmlNodePtr XMLCALL xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem)
struct node node
struct _xmlDictEntry * dict
Definition: dict.c:119
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
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:1884
smooth NULL
Definition: ftsmooth.c:416
#define XML_XML_NAMESPACE
Definition: tree.h:140
void * _private
Definition: parser.h:256
struct _tree * parent
Definition: btrfs_drv.h:447
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:1095
XMLPUBFUN void XMLCALL xmlFreeInputStream(xmlParserInputPtr input)
#define BAD_CAST
Definition: xmlstring.h:35
xmlDictPtr dict
Definition: parser.h:263
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
XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNodeList(xmlNodePtr node)
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
int wellFormed
Definition: parser.h:188
Definition: id3.c:95
if(!(yy_init))
Definition: macro.lex.yy.c:714
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:15186
struct list * next
Definition: list.h:38
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBFUN int XMLCALL xmlCharEncCloseFunc(xmlCharEncodingHandler *handler)
Definition: encoding.c:2720
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
xmlChar * content
Definition: tree.h:502
XMLPUBFUN int XMLCALL xmlParseDocument(xmlParserCtxtPtr ctxt)
Definition: parser.c:10615
GLbitfield flags
Definition: glext.h:7161
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:187
#define ATTRIBUTE_UNUSED
Definition: win32config.h:132
XMLPUBFUN xmlChar *XMLCALL xmlURIEscape(const xmlChar *str)
Definition: uri.c:1745
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:258
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
xmlParserInputBufferPtr buf
Definition: parser.h:56
#define local
Definition: zutil.h:30
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
Definition: uri.h:33
int parseFlags
Definition: tree.h:582
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
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content)
XMLPUBFUN void XMLCALL xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1381
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
char * directory
Definition: parser.h:226
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:157
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
GLuint64EXT * result
Definition: glext.h:11304
#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:1060
#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