ReactOS  0.4.14-dev-376-gaedba84
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  inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
453  if (inputStream == NULL) {
454  xmlFreeParserCtxt(pctxt);
455  return(NULL);
456  }
457 
458  inputPush(pctxt, inputStream);
459 
460  if (pctxt->directory == NULL)
461  pctxt->directory = xmlParserGetDirectory(URL);
462 
463  pctxt->loadsubset |= XML_DETECT_IDS;
464 
465  xmlParseDocument(pctxt);
466 
467  if (pctxt->wellFormed) {
468  ret = pctxt->myDoc;
469  }
470  else {
471  ret = NULL;
472  if (pctxt->myDoc != NULL)
473  xmlFreeDoc(pctxt->myDoc);
474  pctxt->myDoc = NULL;
475  }
476  xmlFreeParserCtxt(pctxt);
477 
478  return(ret);
479 }
480 
488 static int
489 xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
490  xmlXIncludeRefPtr ref;
491  xmlURIPtr uri;
492  xmlChar *URL;
493  xmlChar *fragment = NULL;
494  xmlChar *href;
495  xmlChar *parse;
496  xmlChar *base;
497  xmlChar *URI;
498  int xml = 1, i; /* default Issue 64 */
499  int local = 0;
500 
501 
502  if (ctxt == NULL)
503  return(-1);
504  if (cur == NULL)
505  return(-1);
506 
507 #ifdef DEBUG_XINCLUDE
509 #endif
510  /*
511  * read the attributes
512  */
513  href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
514  if (href == NULL) {
515  href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
516  if (href == NULL)
517  return(-1);
518  }
519  if ((href[0] == '#') || (href[0] == 0))
520  local = 1;
521  parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
522  if (parse != NULL) {
523  if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
524  xml = 1;
525  else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
526  xml = 0;
527  else {
528  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
529  "invalid value %s for 'parse'\n", parse);
530  if (href != NULL)
531  xmlFree(href);
532  if (parse != NULL)
533  xmlFree(parse);
534  return(-1);
535  }
536  }
537 
538  /*
539  * compute the URI
540  */
541  base = xmlNodeGetBase(ctxt->doc, cur);
542  if (base == NULL) {
543  URI = xmlBuildURI(href, ctxt->doc->URL);
544  } else {
545  URI = xmlBuildURI(href, base);
546  }
547  if (URI == NULL) {
548  xmlChar *escbase;
549  xmlChar *eschref;
550  /*
551  * Some escaping may be needed
552  */
553  escbase = xmlURIEscape(base);
554  eschref = xmlURIEscape(href);
555  URI = xmlBuildURI(eschref, escbase);
556  if (escbase != NULL)
557  xmlFree(escbase);
558  if (eschref != NULL)
559  xmlFree(eschref);
560  }
561  if (parse != NULL)
562  xmlFree(parse);
563  if (href != NULL)
564  xmlFree(href);
565  if (base != NULL)
566  xmlFree(base);
567  if (URI == NULL) {
568  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
569  "failed build URL\n", NULL);
570  return(-1);
571  }
572  fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
573 
574  /*
575  * Check the URL and remove any fragment identifier
576  */
577  uri = xmlParseURI((const char *)URI);
578  if (uri == NULL) {
579  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
580  "invalid value URI %s\n", URI);
581  if (fragment != NULL)
582  xmlFree(fragment);
583  xmlFree(URI);
584  return(-1);
585  }
586 
587  if (uri->fragment != NULL) {
588  if (ctxt->legacy != 0) {
589  if (fragment == NULL) {
590  fragment = (xmlChar *) uri->fragment;
591  } else {
592  xmlFree(uri->fragment);
593  }
594  } else {
595  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
596  "Invalid fragment identifier in URI %s use the xpointer attribute\n",
597  URI);
598  if (fragment != NULL)
599  xmlFree(fragment);
600  xmlFreeURI(uri);
601  xmlFree(URI);
602  return(-1);
603  }
604  uri->fragment = NULL;
605  }
606  URL = xmlSaveUri(uri);
607  xmlFreeURI(uri);
608  xmlFree(URI);
609  if (URL == NULL) {
610  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
611  "invalid value URI %s\n", URI);
612  if (fragment != NULL)
613  xmlFree(fragment);
614  return(-1);
615  }
616 
617  /*
618  * If local and xml then we need a fragment
619  */
620  if ((local == 1) && (xml == 1) &&
621  ((fragment == NULL) || (fragment[0] == 0))) {
622  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
623  "detected a local recursion with no xpointer in %s\n",
624  URL);
625  if (fragment != NULL)
626  xmlFree(fragment);
627  return(-1);
628  }
629 
630  /*
631  * Check the URL against the stack for recursions
632  */
633  if ((!local) && (xml == 1)) {
634  for (i = 0;i < ctxt->urlNr;i++) {
635  if (xmlStrEqual(URL, ctxt->urlTab[i])) {
636  xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
637  "detected a recursion in %s\n", URL);
638  return(-1);
639  }
640  }
641  }
642 
643  ref = xmlXIncludeNewRef(ctxt, URL, cur);
644  if (ref == NULL) {
645  return(-1);
646  }
647  ref->fragment = fragment;
648  ref->doc = NULL;
649  ref->xml = xml;
650  ref->count = 1;
651  xmlFree(URL);
652  return(0);
653 }
654 
663 static void
664 xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
665  const xmlURL url ATTRIBUTE_UNUSED) {
666  xmlXIncludeCtxtPtr newctxt;
667  int i;
668 
669  /*
670  * Avoid recursion in already substitued resources
671  for (i = 0;i < ctxt->urlNr;i++) {
672  if (xmlStrEqual(doc->URL, ctxt->urlTab[i]))
673  return;
674  }
675  */
676 
677 #ifdef DEBUG_XINCLUDE
678  xmlGenericError(xmlGenericErrorContext, "Recursing in doc %s\n", doc->URL);
679 #endif
680  /*
681  * Handle recursion here.
682  */
683 
684  newctxt = xmlXIncludeNewContext(doc);
685  if (newctxt != NULL) {
686  /*
687  * Copy the private user data
688  */
689  newctxt->_private = ctxt->_private;
690  /*
691  * Copy the existing document set
692  */
693  newctxt->incMax = ctxt->incMax;
694  newctxt->incNr = ctxt->incNr;
695  newctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(newctxt->incMax *
696  sizeof(newctxt->incTab[0]));
697  if (newctxt->incTab == NULL) {
698  xmlXIncludeErrMemory(ctxt, (xmlNodePtr) doc, "processing doc");
699  xmlFree(newctxt);
700  return;
701  }
702  /*
703  * copy the urlTab
704  */
705  newctxt->urlMax = ctxt->urlMax;
706  newctxt->urlNr = ctxt->urlNr;
707  newctxt->urlTab = ctxt->urlTab;
708 
709  /*
710  * Inherit the existing base
711  */
712  newctxt->base = xmlStrdup(ctxt->base);
713 
714  /*
715  * Inherit the documents already in use by other includes
716  */
717  newctxt->incBase = ctxt->incNr;
718  for (i = 0;i < ctxt->incNr;i++) {
719  newctxt->incTab[i] = ctxt->incTab[i];
720  newctxt->incTab[i]->count++; /* prevent the recursion from
721  freeing it */
722  }
723  /*
724  * The new context should also inherit the Parse Flags
725  * (bug 132597)
726  */
727  newctxt->parseFlags = ctxt->parseFlags;
728  xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
729  for (i = 0;i < ctxt->incNr;i++) {
730  newctxt->incTab[i]->count--;
731  newctxt->incTab[i] = NULL;
732  }
733 
734  /* urlTab may have been reallocated */
735  ctxt->urlTab = newctxt->urlTab;
736  ctxt->urlMax = newctxt->urlMax;
737 
738  newctxt->urlMax = 0;
739  newctxt->urlNr = 0;
740  newctxt->urlTab = NULL;
741 
742  xmlXIncludeFreeContext(newctxt);
743  }
744 #ifdef DEBUG_XINCLUDE
745  xmlGenericError(xmlGenericErrorContext, "Done recursing in doc %s\n", url);
746 #endif
747 }
748 
757 static void
758 xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
759 #ifdef DEBUG_XINCLUDE
760  xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
761 #endif
762  if (ctxt->txtMax == 0) {
763  ctxt->txtMax = 4;
764  ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
765  sizeof(ctxt->txtTab[0]));
766  if (ctxt->txtTab == NULL) {
767  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
768  return;
769  }
770  ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
771  sizeof(ctxt->txturlTab[0]));
772  if (ctxt->txturlTab == NULL) {
773  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
774  return;
775  }
776  }
777  if (ctxt->txtNr >= ctxt->txtMax) {
778  ctxt->txtMax *= 2;
779  ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
780  ctxt->txtMax * sizeof(ctxt->txtTab[0]));
781  if (ctxt->txtTab == NULL) {
782  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
783  return;
784  }
785  ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
786  ctxt->txtMax * sizeof(ctxt->txturlTab[0]));
787  if (ctxt->txturlTab == NULL) {
788  xmlXIncludeErrMemory(ctxt, NULL, "processing text");
789  return;
790  }
791  }
792  ctxt->txtTab[ctxt->txtNr] = txt;
793  ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
794  ctxt->txtNr++;
795 }
796 
797 /************************************************************************
798  * *
799  * Node copy with specific semantic *
800  * *
801  ************************************************************************/
802 
803 static xmlNodePtr
804 xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
806 
817 static xmlNodePtr
818 xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
821 
822  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
823  (elem == NULL))
824  return(NULL);
825  if (elem->type == XML_DTD_NODE)
826  return(NULL);
827  if (elem->type == XML_DOCUMENT_NODE)
828  result = xmlXIncludeCopyNodeList(ctxt, target, source, elem->children);
829  else
831  return(result);
832 }
833 
844 static xmlNodePtr
845 xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
847  xmlNodePtr cur, res, result = NULL, last = NULL;
848 
849  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
850  (elem == NULL))
851  return(NULL);
852  cur = elem;
853  while (cur != NULL) {
854  res = xmlXIncludeCopyNode(ctxt, target, source, cur);
855  if (res != NULL) {
856  if (result == NULL) {
857  result = last = res;
858  } else {
859  last->next = res;
860  res->prev = last;
861  last = res;
862  }
863  }
864  cur = cur->next;
865  }
866  return(result);
867 }
868 
876 static xmlNodePtr
877 xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
878  int i;
879  if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
880  return(NULL);
881  cur = cur->children;
882  for (i = 0;i <= no;cur = cur->next) {
883  if (cur == NULL)
884  return(cur);
885  if ((cur->type == XML_ELEMENT_NODE) ||
886  (cur->type == XML_DOCUMENT_NODE) ||
887  (cur->type == XML_HTML_DOCUMENT_NODE)) {
888  i++;
889  if (i == no)
890  break;
891  }
892  }
893  return(cur);
894 }
895 
896 xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
909 static xmlNodePtr
910 xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
911  xmlDocPtr source, xmlXPathObjectPtr range) {
912  /* pointers to generated nodes */
913  xmlNodePtr list = NULL, last = NULL, listParent = NULL;
914  xmlNodePtr tmp, tmp2;
915  /* pointers to traversal nodes */
916  xmlNodePtr start, cur, end;
917  int index1, index2;
918  int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
919 
920  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
921  (range == NULL))
922  return(NULL);
923  if (range->type != XPATH_RANGE)
924  return(NULL);
925  start = (xmlNodePtr) range->user;
926 
927  if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
928  return(NULL);
929  end = range->user2;
930  if (end == NULL)
931  return(xmlDocCopyNode(start, target, 1));
932  if (end->type == XML_NAMESPACE_DECL)
933  return(NULL);
934 
935  cur = start;
936  index1 = range->index;
937  index2 = range->index2;
938  /*
939  * level is depth of the current node under consideration
940  * list is the pointer to the root of the output tree
941  * listParent is a pointer to the parent of output tree (within
942  the included file) in case we need to add another level
943  * last is a pointer to the last node added to the output tree
944  * lastLevel is the depth of last (relative to the root)
945  */
946  while (cur != NULL) {
947  /*
948  * Check if our output tree needs a parent
949  */
950  if (level < 0) {
951  while (level < 0) {
952  /* copy must include namespaces and properties */
953  tmp2 = xmlDocCopyNode(listParent, target, 2);
954  xmlAddChild(tmp2, list);
955  list = tmp2;
956  listParent = listParent->parent;
957  level++;
958  }
959  last = list;
960  lastLevel = 0;
961  }
962  /*
963  * Check whether we need to change our insertion point
964  */
965  while (level < lastLevel) {
966  last = last->parent;
967  lastLevel --;
968  }
969  if (cur == end) { /* Are we at the end of the range? */
970  if (cur->type == XML_TEXT_NODE) {
971  const xmlChar *content = cur->content;
972  int len;
973 
974  if (content == NULL) {
975  tmp = xmlNewTextLen(NULL, 0);
976  } else {
977  len = index2;
978  if ((cur == start) && (index1 > 1)) {
979  content += (index1 - 1);
980  len -= (index1 - 1);
981  } else {
982  len = index2;
983  }
984  tmp = xmlNewTextLen(content, len);
985  }
986  /* single sub text node selection */
987  if (list == NULL)
988  return(tmp);
989  /* prune and return full set */
990  if (level == lastLevel)
991  xmlAddNextSibling(last, tmp);
992  else
993  xmlAddChild(last, tmp);
994  return(list);
995  } else { /* ending node not a text node */
996  endLevel = level; /* remember the level of the end node */
997  endFlag = 1;
998  /* last node - need to take care of properties + namespaces */
999  tmp = xmlDocCopyNode(cur, target, 2);
1000  if (list == NULL) {
1001  list = tmp;
1002  listParent = cur->parent;
1003  } else {
1004  if (level == lastLevel)
1005  xmlAddNextSibling(last, tmp);
1006  else {
1007  xmlAddChild(last, tmp);
1008  lastLevel = level;
1009  }
1010  }
1011  last = tmp;
1012 
1013  if (index2 > 1) {
1014  end = xmlXIncludeGetNthChild(cur, index2 - 1);
1015  index2 = 0;
1016  }
1017  if ((cur == start) && (index1 > 1)) {
1018  cur = xmlXIncludeGetNthChild(cur, index1 - 1);
1019  index1 = 0;
1020  } else {
1021  cur = cur->children;
1022  }
1023  level++; /* increment level to show change */
1024  /*
1025  * Now gather the remaining nodes from cur to end
1026  */
1027  continue; /* while */
1028  }
1029  } else if (cur == start) { /* Not at the end, are we at start? */
1030  if ((cur->type == XML_TEXT_NODE) ||
1031  (cur->type == XML_CDATA_SECTION_NODE)) {
1032  const xmlChar *content = cur->content;
1033 
1034  if (content == NULL) {
1035  tmp = xmlNewTextLen(NULL, 0);
1036  } else {
1037  if (index1 > 1) {
1038  content += (index1 - 1);
1039  index1 = 0;
1040  }
1041  tmp = xmlNewText(content);
1042  }
1043  last = list = tmp;
1044  listParent = cur->parent;
1045  } else { /* Not text node */
1046  /*
1047  * start of the range - need to take care of
1048  * properties and namespaces
1049  */
1050  tmp = xmlDocCopyNode(cur, target, 2);
1051  list = last = tmp;
1052  listParent = cur->parent;
1053  if (index1 > 1) { /* Do we need to position? */
1054  cur = xmlXIncludeGetNthChild(cur, index1 - 1);
1055  level = lastLevel = 1;
1056  index1 = 0;
1057  /*
1058  * Now gather the remaining nodes from cur to end
1059  */
1060  continue; /* while */
1061  }
1062  }
1063  } else {
1064  tmp = NULL;
1065  switch (cur->type) {
1066  case XML_DTD_NODE:
1067  case XML_ELEMENT_DECL:
1068  case XML_ATTRIBUTE_DECL:
1069  case XML_ENTITY_NODE:
1070  /* Do not copy DTD informations */
1071  break;
1072  case XML_ENTITY_DECL:
1073  /* handle crossing entities -> stack needed */
1074  break;
1075  case XML_XINCLUDE_START:
1076  case XML_XINCLUDE_END:
1077  /* don't consider it part of the tree content */
1078  break;
1079  case XML_ATTRIBUTE_NODE:
1080  /* Humm, should not happen ! */
1081  break;
1082  default:
1083  /*
1084  * Middle of the range - need to take care of
1085  * properties and namespaces
1086  */
1087  tmp = xmlDocCopyNode(cur, target, 2);
1088  break;
1089  }
1090  if (tmp != NULL) {
1091  if (level == lastLevel)
1092  xmlAddNextSibling(last, tmp);
1093  else {
1094  xmlAddChild(last, tmp);
1095  lastLevel = level;
1096  }
1097  last = tmp;
1098  }
1099  }
1100  /*
1101  * Skip to next node in document order
1102  */
1103  cur = xmlXPtrAdvanceNode(cur, &level);
1104  if (endFlag && (level >= endLevel))
1105  break;
1106  }
1107  return(list);
1108 }
1109 
1123 static xmlNodePtr
1124 xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
1125  xmlDocPtr source, xmlXPathObjectPtr obj) {
1126  xmlNodePtr list = NULL, last = NULL;
1127  int i;
1128 
1129  if (source == NULL)
1130  source = ctxt->doc;
1131  if ((ctxt == NULL) || (target == NULL) || (source == NULL) ||
1132  (obj == NULL))
1133  return(NULL);
1134  switch (obj->type) {
1135  case XPATH_NODESET: {
1136  xmlNodeSetPtr set = obj->nodesetval;
1137  if (set == NULL)
1138  return(NULL);
1139  for (i = 0;i < set->nodeNr;i++) {
1140  if (set->nodeTab[i] == NULL)
1141  continue;
1142  switch (set->nodeTab[i]->type) {
1143  case XML_TEXT_NODE:
1145  case XML_ELEMENT_NODE:
1146  case XML_ENTITY_REF_NODE:
1147  case XML_ENTITY_NODE:
1148  case XML_PI_NODE:
1149  case XML_COMMENT_NODE:
1150  case XML_DOCUMENT_NODE:
1152 #ifdef LIBXML_DOCB_ENABLED
1153  case XML_DOCB_DOCUMENT_NODE:
1154 #endif
1155  case XML_XINCLUDE_END:
1156  break;
1157  case XML_XINCLUDE_START: {
1158  xmlNodePtr tmp, cur = set->nodeTab[i];
1159 
1160  cur = cur->next;
1161  while (cur != NULL) {
1162  switch(cur->type) {
1163  case XML_TEXT_NODE:
1165  case XML_ELEMENT_NODE:
1166  case XML_ENTITY_REF_NODE:
1167  case XML_ENTITY_NODE:
1168  case XML_PI_NODE:
1169  case XML_COMMENT_NODE:
1170  tmp = xmlXIncludeCopyNode(ctxt, target,
1171  source, cur);
1172  if (last == NULL) {
1173  list = last = tmp;
1174  } else {
1175  xmlAddNextSibling(last, tmp);
1176  last = tmp;
1177  }
1178  cur = cur->next;
1179  continue;
1180  default:
1181  break;
1182  }
1183  break;
1184  }
1185  continue;
1186  }
1187  case XML_ATTRIBUTE_NODE:
1188  case XML_NAMESPACE_DECL:
1191  case XML_NOTATION_NODE:
1192  case XML_DTD_NODE:
1193  case XML_ELEMENT_DECL:
1194  case XML_ATTRIBUTE_DECL:
1195  case XML_ENTITY_DECL:
1196  continue; /* for */
1197  }
1198  if (last == NULL)
1199  list = last = xmlXIncludeCopyNode(ctxt, target, source,
1200  set->nodeTab[i]);
1201  else {
1203  xmlXIncludeCopyNode(ctxt, target, source,
1204  set->nodeTab[i]));
1205  if (last->next != NULL)
1206  last = last->next;
1207  }
1208  }
1209  break;
1210  }
1211 #ifdef LIBXML_XPTR_ENABLED
1212  case XPATH_LOCATIONSET: {
1213  xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1214  if (set == NULL)
1215  return(NULL);
1216  for (i = 0;i < set->locNr;i++) {
1217  if (last == NULL)
1218  list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
1219  set->locTab[i]);
1220  else
1222  xmlXIncludeCopyXPointer(ctxt, target, source,
1223  set->locTab[i]));
1224  if (last != NULL) {
1225  while (last->next != NULL)
1226  last = last->next;
1227  }
1228  }
1229  break;
1230  }
1231  case XPATH_RANGE:
1232  return(xmlXIncludeCopyRange(ctxt, target, source, obj));
1233 #endif
1234  case XPATH_POINT:
1235  /* points are ignored in XInclude */
1236  break;
1237  default:
1238  break;
1239  }
1240  return(list);
1241 }
1242 /************************************************************************
1243  * *
1244  * XInclude I/O handling *
1245  * *
1246  ************************************************************************/
1247 
1248 typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
1249 typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
1250 struct _xmlXIncludeMergeData {
1251  xmlDocPtr doc;
1252  xmlXIncludeCtxtPtr ctxt;
1253 };
1254 
1263 static void
1264 xmlXIncludeMergeEntity(void *payload, void *vdata,
1265  const xmlChar *name ATTRIBUTE_UNUSED) {
1266  xmlEntityPtr ent = (xmlEntityPtr) payload;
1267  xmlXIncludeMergeDataPtr data = (xmlXIncludeMergeDataPtr) vdata;
1268  xmlEntityPtr ret, prev;
1269  xmlDocPtr doc;
1270  xmlXIncludeCtxtPtr ctxt;
1271 
1272  if ((ent == NULL) || (data == NULL))
1273  return;
1274  ctxt = data->ctxt;
1275  doc = data->doc;
1276  if ((ctxt == NULL) || (doc == NULL))
1277  return;
1278  switch (ent->etype) {
1282  return;
1286  break;
1287  }
1288  ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
1289  ent->SystemID, ent->content);
1290  if (ret != NULL) {
1291  if (ent->URI != NULL)
1292  ret->URI = xmlStrdup(ent->URI);
1293  } else {
1294  prev = xmlGetDocEntity(doc, ent->name);
1295  if (prev != NULL) {
1296  if (ent->etype != prev->etype)
1297  goto error;
1298 
1299  if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
1300  if (!xmlStrEqual(ent->SystemID, prev->SystemID))
1301  goto error;
1302  } else if ((ent->ExternalID != NULL) &&
1303  (prev->ExternalID != NULL)) {
1304  if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
1305  goto error;
1306  } else if ((ent->content != NULL) && (prev->content != NULL)) {
1307  if (!xmlStrEqual(ent->content, prev->content))
1308  goto error;
1309  } else {
1310  goto error;
1311  }
1312 
1313  }
1314  }
1315  return;
1316 error:
1317  switch (ent->etype) {
1323  return;
1325  break;
1326  }
1327  xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
1328  "mismatch in redefinition of entity %s\n",
1329  ent->name);
1330 }
1331 
1342 static int
1343 xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
1344  xmlDocPtr from) {
1345  xmlNodePtr cur;
1347 
1348  if (ctxt == NULL)
1349  return(-1);
1350 
1351  if ((from == NULL) || (from->intSubset == NULL))
1352  return(0);
1353 
1354  target = doc->intSubset;
1355  if (target == NULL) {
1356  cur = xmlDocGetRootElement(doc);
1357  if (cur == NULL)
1358  return(-1);
1359  target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
1360  if (target == NULL)
1361  return(-1);
1362  }
1363 
1364  source = from->intSubset;
1365  if ((source != NULL) && (source->entities != NULL)) {
1366  xmlXIncludeMergeData data;
1367 
1368  data.ctxt = ctxt;
1369  data.doc = doc;
1370 
1371  xmlHashScan((xmlHashTablePtr) source->entities,
1372  xmlXIncludeMergeEntity, &data);
1373  }
1374  source = from->extSubset;
1375  if ((source != NULL) && (source->entities != NULL)) {
1376  xmlXIncludeMergeData data;
1377 
1378  data.ctxt = ctxt;
1379  data.doc = doc;
1380 
1381  /*
1382  * don't duplicate existing stuff when external subsets are the same
1383  */
1384  if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
1385  (!xmlStrEqual(target->SystemID, source->SystemID))) {
1386  xmlHashScan((xmlHashTablePtr) source->entities,
1387  xmlXIncludeMergeEntity, &data);
1388  }
1389  }
1390  return(0);
1391 }
1392 
1403 static int
1404 xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1405  xmlDocPtr doc;
1406  xmlURIPtr uri;
1407  xmlChar *URL;
1408  xmlChar *fragment = NULL;
1409  int i = 0;
1410 #ifdef LIBXML_XPTR_ENABLED
1411  int saveFlags;
1412 #endif
1413 
1414 #ifdef DEBUG_XINCLUDE
1415  xmlGenericError(xmlGenericErrorContext, "Loading doc %s:%d\n", url, nr);
1416 #endif
1417  /*
1418  * Check the URL and remove any fragment identifier
1419  */
1420  uri = xmlParseURI((const char *)url);
1421  if (uri == NULL) {
1422  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1424  "invalid value URI %s\n", url);
1425  return(-1);
1426  }
1427  if (uri->fragment != NULL) {
1428  fragment = (xmlChar *) uri->fragment;
1429  uri->fragment = NULL;
1430  }
1431  if ((ctxt->incTab != NULL) && (ctxt->incTab[nr] != NULL) &&
1432  (ctxt->incTab[nr]->fragment != NULL)) {
1433  if (fragment != NULL) xmlFree(fragment);
1434  fragment = xmlStrdup(ctxt->incTab[nr]->fragment);
1435  }
1436  URL = xmlSaveUri(uri);
1437  xmlFreeURI(uri);
1438  if (URL == NULL) {
1439  if (ctxt->incTab != NULL)
1440  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1442  "invalid value URI %s\n", url);
1443  else
1444  xmlXIncludeErr(ctxt, NULL,
1446  "invalid value URI %s\n", url);
1447  if (fragment != NULL)
1448  xmlFree(fragment);
1449  return(-1);
1450  }
1451 
1452  /*
1453  * Handling of references to the local document are done
1454  * directly through ctxt->doc.
1455  */
1456  if ((URL[0] == 0) || (URL[0] == '#') ||
1457  ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
1458  doc = NULL;
1459  goto loaded;
1460  }
1461 
1462  /*
1463  * Prevent reloading twice the document.
1464  */
1465  for (i = 0; i < ctxt->incNr; i++) {
1466  if ((xmlStrEqual(URL, ctxt->incTab[i]->URI)) &&
1467  (ctxt->incTab[i]->doc != NULL)) {
1468  doc = ctxt->incTab[i]->doc;
1469 #ifdef DEBUG_XINCLUDE
1470  printf("Already loaded %s\n", URL);
1471 #endif
1472  goto loaded;
1473  }
1474  }
1475 
1476  /*
1477  * Load it.
1478  */
1479 #ifdef DEBUG_XINCLUDE
1480  printf("loading %s\n", URL);
1481 #endif
1482 #ifdef LIBXML_XPTR_ENABLED
1483  /*
1484  * If this is an XPointer evaluation, we want to assure that
1485  * all entities have been resolved prior to processing the
1486  * referenced document
1487  */
1488  saveFlags = ctxt->parseFlags;
1489  if (fragment != NULL) { /* if this is an XPointer eval */
1490  ctxt->parseFlags |= XML_PARSE_NOENT;
1491  }
1492 #endif
1493 
1494  doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
1495 #ifdef LIBXML_XPTR_ENABLED
1496  ctxt->parseFlags = saveFlags;
1497 #endif
1498  if (doc == NULL) {
1499  xmlFree(URL);
1500  if (fragment != NULL)
1501  xmlFree(fragment);
1502  return(-1);
1503  }
1504  ctxt->incTab[nr]->doc = doc;
1505  /*
1506  * It's possible that the requested URL has been mapped to a
1507  * completely different location (e.g. through a catalog entry).
1508  * To check for this, we compare the URL with that of the doc
1509  * and change it if they disagree (bug 146988).
1510  */
1511  if (!xmlStrEqual(URL, doc->URL)) {
1512  xmlFree(URL);
1513  URL = xmlStrdup(doc->URL);
1514  }
1515  for (i = nr + 1; i < ctxt->incNr; i++) {
1516  if (xmlStrEqual(URL, ctxt->incTab[i]->URI)) {
1517  ctxt->incTab[nr]->count++;
1518 #ifdef DEBUG_XINCLUDE
1519  printf("Increasing %s count since reused\n", URL);
1520 #endif
1521  break;
1522  }
1523  }
1524 
1525  /*
1526  * Make sure we have all entities fixed up
1527  */
1528  xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
1529 
1530  /*
1531  * We don't need the DTD anymore, free up space
1532  if (doc->intSubset != NULL) {
1533  xmlUnlinkNode((xmlNodePtr) doc->intSubset);
1534  xmlFreeNode((xmlNodePtr) doc->intSubset);
1535  doc->intSubset = NULL;
1536  }
1537  if (doc->extSubset != NULL) {
1538  xmlUnlinkNode((xmlNodePtr) doc->extSubset);
1539  xmlFreeNode((xmlNodePtr) doc->extSubset);
1540  doc->extSubset = NULL;
1541  }
1542  */
1543  xmlXIncludeRecurseDoc(ctxt, doc, URL);
1544 
1545 loaded:
1546  if (fragment == NULL) {
1547  /*
1548  * Add the top children list as the replacement copy.
1549  */
1550  if (doc == NULL)
1551  {
1552  /* Hopefully a DTD declaration won't be copied from
1553  * the same document */
1554  ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
1555  } else {
1556  ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
1557  doc, doc->children);
1558  }
1559  }
1560 #ifdef LIBXML_XPTR_ENABLED
1561  else {
1562  /*
1563  * Computes the XPointer expression and make a copy used
1564  * as the replacement copy.
1565  */
1566  xmlXPathObjectPtr xptr;
1567  xmlXPathContextPtr xptrctxt;
1568  xmlNodeSetPtr set;
1569 
1570  if (doc == NULL) {
1571  xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
1572  NULL);
1573  } else {
1574  xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1575  }
1576  if (xptrctxt == NULL) {
1577  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1579  "could not create XPointer context\n", NULL);
1580  xmlFree(URL);
1581  xmlFree(fragment);
1582  return(-1);
1583  }
1584  xptr = xmlXPtrEval(fragment, xptrctxt);
1585  if (xptr == NULL) {
1586  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1588  "XPointer evaluation failed: #%s\n",
1589  fragment);
1590  xmlXPathFreeContext(xptrctxt);
1591  xmlFree(URL);
1592  xmlFree(fragment);
1593  return(-1);
1594  }
1595  switch (xptr->type) {
1596  case XPATH_UNDEFINED:
1597  case XPATH_BOOLEAN:
1598  case XPATH_NUMBER:
1599  case XPATH_STRING:
1600  case XPATH_POINT:
1601  case XPATH_USERS:
1602  case XPATH_XSLT_TREE:
1603  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1605  "XPointer is not a range: #%s\n",
1606  fragment);
1607  xmlXPathFreeContext(xptrctxt);
1608  xmlFree(URL);
1609  xmlFree(fragment);
1610  return(-1);
1611  case XPATH_NODESET:
1612  if ((xptr->nodesetval == NULL) ||
1613  (xptr->nodesetval->nodeNr <= 0)) {
1614  xmlXPathFreeContext(xptrctxt);
1615  xmlFree(URL);
1616  xmlFree(fragment);
1617  return(-1);
1618  }
1619 
1620  case XPATH_RANGE:
1621  case XPATH_LOCATIONSET:
1622  break;
1623  }
1624  set = xptr->nodesetval;
1625  if (set != NULL) {
1626  for (i = 0;i < set->nodeNr;i++) {
1627  if (set->nodeTab[i] == NULL)
1628  continue;
1629  switch (set->nodeTab[i]->type) {
1630  case XML_ELEMENT_NODE:
1631  case XML_TEXT_NODE:
1633  case XML_ENTITY_REF_NODE:
1634  case XML_ENTITY_NODE:
1635  case XML_PI_NODE:
1636  case XML_COMMENT_NODE:
1637  case XML_DOCUMENT_NODE:
1639 #ifdef LIBXML_DOCB_ENABLED
1640  case XML_DOCB_DOCUMENT_NODE:
1641 #endif
1642  continue;
1643 
1644  case XML_ATTRIBUTE_NODE:
1645  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1647  "XPointer selects an attribute: #%s\n",
1648  fragment);
1649  set->nodeTab[i] = NULL;
1650  continue;
1651  case XML_NAMESPACE_DECL:
1652  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1654  "XPointer selects a namespace: #%s\n",
1655  fragment);
1656  set->nodeTab[i] = NULL;
1657  continue;
1660  case XML_NOTATION_NODE:
1661  case XML_DTD_NODE:
1662  case XML_ELEMENT_DECL:
1663  case XML_ATTRIBUTE_DECL:
1664  case XML_ENTITY_DECL:
1665  case XML_XINCLUDE_START:
1666  case XML_XINCLUDE_END:
1667  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1669  "XPointer selects unexpected nodes: #%s\n",
1670  fragment);
1671  set->nodeTab[i] = NULL;
1672  set->nodeTab[i] = NULL;
1673  continue; /* for */
1674  }
1675  }
1676  }
1677  if (doc == NULL) {
1678  ctxt->incTab[nr]->xptr = xptr;
1679  ctxt->incTab[nr]->inc = NULL;
1680  } else {
1681  ctxt->incTab[nr]->inc =
1682  xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
1683  xmlXPathFreeObject(xptr);
1684  }
1685  xmlXPathFreeContext(xptrctxt);
1686  xmlFree(fragment);
1687  }
1688 #endif
1689 
1690  /*
1691  * Do the xml:base fixup if needed
1692  */
1693  if ((doc != NULL) && (URL != NULL) &&
1694  (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) &&
1695  (!(doc->parseFlags & XML_PARSE_NOBASEFIX))) {
1696  xmlNodePtr node;
1697  xmlChar *base;
1698  xmlChar *curBase;
1699 
1700  /*
1701  * The base is only adjusted if "necessary", i.e. if the xinclude node
1702  * has a base specified, or the URL is relative
1703  */
1704  base = xmlGetNsProp(ctxt->incTab[nr]->ref, BAD_CAST "base",
1706  if (base == NULL) {
1707  /*
1708  * No xml:base on the xinclude node, so we check whether the
1709  * URI base is different than (relative to) the context base
1710  */
1711  curBase = xmlBuildRelativeURI(URL, ctxt->base);
1712  if (curBase == NULL) { /* Error return */
1713  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1715  "trying to build relative URI from %s\n", URL);
1716  } else {
1717  /* If the URI doesn't contain a slash, it's not relative */
1718  if (!xmlStrchr(curBase, (xmlChar) '/'))
1719  xmlFree(curBase);
1720  else
1721  base = curBase;
1722  }
1723  }
1724  if (base != NULL) { /* Adjustment may be needed */
1725  node = ctxt->incTab[nr]->inc;
1726  while (node != NULL) {
1727  /* Only work on element nodes */
1728  if (node->type == XML_ELEMENT_NODE) {
1729  curBase = xmlNodeGetBase(node->doc, node);
1730  /* If no current base, set it */
1731  if (curBase == NULL) {
1732  xmlNodeSetBase(node, base);
1733  } else {
1734  /*
1735  * If the current base is the same as the
1736  * URL of the document, then reset it to be
1737  * the specified xml:base or the relative URI
1738  */
1739  if (xmlStrEqual(curBase, node->doc->URL)) {
1740  xmlNodeSetBase(node, base);
1741  } else {
1742  /*
1743  * If the element already has an xml:base
1744  * set, then relativise it if necessary
1745  */
1746  xmlChar *xmlBase;
1747  xmlBase = xmlGetNsProp(node,
1748  BAD_CAST "base",
1750  if (xmlBase != NULL) {
1751  xmlChar *relBase;
1752  relBase = xmlBuildURI(xmlBase, base);
1753  if (relBase == NULL) { /* error */
1754  xmlXIncludeErr(ctxt,
1755  ctxt->incTab[nr]->ref,
1757  "trying to rebuild base from %s\n",
1758  xmlBase);
1759  } else {
1760  xmlNodeSetBase(node, relBase);
1761  xmlFree(relBase);
1762  }
1763  xmlFree(xmlBase);
1764  }
1765  }
1766  xmlFree(curBase);
1767  }
1768  }
1769  node = node->next;
1770  }
1771  xmlFree(base);
1772  }
1773  }
1774  if ((nr < ctxt->incNr) && (ctxt->incTab[nr]->doc != NULL) &&
1775  (ctxt->incTab[nr]->count <= 1)) {
1776 #ifdef DEBUG_XINCLUDE
1777  printf("freeing %s\n", ctxt->incTab[nr]->doc->URL);
1778 #endif
1779  xmlFreeDoc(ctxt->incTab[nr]->doc);
1780  ctxt->incTab[nr]->doc = NULL;
1781  }
1782  xmlFree(URL);
1783  return(0);
1784 }
1785 
1796 static int
1797 xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
1799  xmlNodePtr node;
1800  xmlURIPtr uri;
1801  xmlChar *URL;
1802  int i;
1803  xmlChar *encoding = NULL;
1804  xmlCharEncoding enc = (xmlCharEncoding) 0;
1805  xmlParserCtxtPtr pctxt;
1806  xmlParserInputPtr inputStream;
1807  int xinclude_multibyte_fallback_used = 0;
1808 
1809  /*
1810  * Check the URL and remove any fragment identifier
1811  */
1812  uri = xmlParseURI((const char *)url);
1813  if (uri == NULL) {
1814  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1815  "invalid value URI %s\n", url);
1816  return(-1);
1817  }
1818  if (uri->fragment != NULL) {
1819  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_TEXT_FRAGMENT,
1820  "fragment identifier forbidden for text: %s\n",
1821  (const xmlChar *) uri->fragment);
1822  xmlFreeURI(uri);
1823  return(-1);
1824  }
1825  URL = xmlSaveUri(uri);
1826  xmlFreeURI(uri);
1827  if (URL == NULL) {
1828  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI,
1829  "invalid value URI %s\n", url);
1830  return(-1);
1831  }
1832 
1833  /*
1834  * Handling of references to the local document are done
1835  * directly through ctxt->doc.
1836  */
1837  if (URL[0] == 0) {
1838  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1840  "text serialization of document not available\n", NULL);
1841  xmlFree(URL);
1842  return(-1);
1843  }
1844 
1845  /*
1846  * Prevent reloading twice the document.
1847  */
1848  for (i = 0; i < ctxt->txtNr; i++) {
1849  if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
1850  node = xmlCopyNode(ctxt->txtTab[i], 1);
1851  goto loaded;
1852  }
1853  }
1854  /*
1855  * Try to get the encoding if available
1856  */
1857  if ((ctxt->incTab[nr] != NULL) && (ctxt->incTab[nr]->ref != NULL)) {
1858  encoding = xmlGetProp(ctxt->incTab[nr]->ref, XINCLUDE_PARSE_ENCODING);
1859  }
1860  if (encoding != NULL) {
1861  /*
1862  * TODO: we should not have to remap to the xmlCharEncoding
1863  * predefined set, a better interface than
1864  * xmlParserInputBufferCreateFilename should allow any
1865  * encoding supported by iconv
1866  */
1867  enc = xmlParseCharEncoding((const char *) encoding);
1868  if (enc == XML_CHAR_ENCODING_ERROR) {
1869  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1871  "encoding %s not supported\n", encoding);
1872  xmlFree(encoding);
1873  xmlFree(URL);
1874  return(-1);
1875  }
1876  xmlFree(encoding);
1877  }
1878 
1879  /*
1880  * Load it.
1881  */
1882  pctxt = xmlNewParserCtxt();
1883  inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt);
1884  if(inputStream == NULL) {
1885  xmlFreeParserCtxt(pctxt);
1886  xmlFree(URL);
1887  return(-1);
1888  }
1889  buf = inputStream->buf;
1890  if (buf == NULL) {
1891  xmlFreeInputStream (inputStream);
1892  xmlFreeParserCtxt(pctxt);
1893  xmlFree(URL);
1894  return(-1);
1895  }
1896  if (buf->encoder)
1897  xmlCharEncCloseFunc(buf->encoder);
1898  buf->encoder = xmlGetCharEncodingHandler(enc);
1899  node = xmlNewText(NULL);
1900 
1901  /*
1902  * Scan all chars from the resource and add the to the node
1903  */
1904 xinclude_multibyte_fallback:
1905  while (xmlParserInputBufferRead(buf, 128) > 0) {
1906  int len;
1907  const xmlChar *content;
1908 
1909  content = xmlBufContent(buf->buffer);
1910  len = xmlBufLength(buf->buffer);
1911  for (i = 0;i < len;) {
1912  int cur;
1913  int l;
1914 
1915  cur = xmlStringCurrentChar(NULL, &content[i], &l);
1916  if (!IS_CHAR(cur)) {
1917  /* Handle splitted multibyte char at buffer boundary */
1918  if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) {
1919  xinclude_multibyte_fallback_used = 1;
1920  xmlBufShrink(buf->buffer, i);
1921  goto xinclude_multibyte_fallback;
1922  } else {
1923  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
1925  "%s contains invalid char\n", URL);
1927  xmlFree(URL);
1928  return(-1);
1929  }
1930  } else {
1931  xinclude_multibyte_fallback_used = 0;
1933  }
1934  i += l;
1935  }
1936  xmlBufShrink(buf->buffer, len);
1937  }
1938  xmlFreeParserCtxt(pctxt);
1939  xmlXIncludeAddTxt(ctxt, node, URL);
1940  xmlFreeInputStream(inputStream);
1941 
1942 loaded:
1943  /*
1944  * Add the element as the replacement copy.
1945  */
1946  ctxt->incTab[nr]->inc = node;
1947  xmlFree(URL);
1948  return(0);
1949 }
1950 
1962 static int
1963 xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
1964  xmlXIncludeCtxtPtr newctxt;
1965  int ret = 0;
1966 
1967  if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
1968  (ctxt == NULL))
1969  return(-1);
1970  if (fallback->children != NULL) {
1971  /*
1972  * It's possible that the fallback also has 'includes'
1973  * (Bug 129969), so we re-process the fallback just in case
1974  */
1975  newctxt = xmlXIncludeNewContext(ctxt->doc);
1976  if (newctxt == NULL)
1977  return (-1);
1978  newctxt->_private = ctxt->_private;
1979  newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
1980  xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
1981  ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
1982  if (ctxt->nbErrors > 0)
1983  ret = -1;
1984  else if (ret > 0)
1985  ret = 0; /* xmlXIncludeDoProcess can return +ve number */
1986  xmlXIncludeFreeContext(newctxt);
1987 
1988  ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
1989  fallback->children);
1990  } else {
1991  ctxt->incTab[nr]->inc = NULL;
1992  ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
1993  }
1994  return(ret);
1995 }
1996 
1997 /************************************************************************
1998  * *
1999  * XInclude Processing *
2000  * *
2001  ************************************************************************/
2002 
2013 static xmlNodePtr
2014 xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2015  xmlXIncludeAddNode(ctxt, node);
2016  return(NULL);
2017 }
2018 
2028 static int
2029 xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
2030  xmlNodePtr cur;
2031  xmlChar *href;
2032  xmlChar *parse;
2033  xmlChar *base;
2034  xmlChar *oldBase;
2035  xmlChar *URI;
2036  int xml = 1; /* default Issue 64 */
2037  int ret;
2038 
2039  if (ctxt == NULL)
2040  return(-1);
2041  if ((nr < 0) || (nr >= ctxt->incNr))
2042  return(-1);
2043  cur = ctxt->incTab[nr]->ref;
2044  if (cur == NULL)
2045  return(-1);
2046 
2047  /*
2048  * read the attributes
2049  */
2050  href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
2051  if (href == NULL) {
2052  href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
2053  if (href == NULL)
2054  return(-1);
2055  }
2056  parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
2057  if (parse != NULL) {
2058  if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
2059  xml = 1;
2060  else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
2061  xml = 0;
2062  else {
2063  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2065  "invalid value %s for 'parse'\n", parse);
2066  if (href != NULL)
2067  xmlFree(href);
2068  if (parse != NULL)
2069  xmlFree(parse);
2070  return(-1);
2071  }
2072  }
2073 
2074  /*
2075  * compute the URI
2076  */
2077  base = xmlNodeGetBase(ctxt->doc, cur);
2078  if (base == NULL) {
2079  URI = xmlBuildURI(href, ctxt->doc->URL);
2080  } else {
2081  URI = xmlBuildURI(href, base);
2082  }
2083  if (URI == NULL) {
2084  xmlChar *escbase;
2085  xmlChar *eschref;
2086  /*
2087  * Some escaping may be needed
2088  */
2089  escbase = xmlURIEscape(base);
2090  eschref = xmlURIEscape(href);
2091  URI = xmlBuildURI(eschref, escbase);
2092  if (escbase != NULL)
2093  xmlFree(escbase);
2094  if (eschref != NULL)
2095  xmlFree(eschref);
2096  }
2097  if (URI == NULL) {
2098  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2099  XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL);
2100  if (parse != NULL)
2101  xmlFree(parse);
2102  if (href != NULL)
2103  xmlFree(href);
2104  if (base != NULL)
2105  xmlFree(base);
2106  return(-1);
2107  }
2108 #ifdef DEBUG_XINCLUDE
2109  xmlGenericError(xmlGenericErrorContext, "parse: %s\n",
2110  xml ? "xml": "text");
2111  xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);
2112 #endif
2113 
2114  /*
2115  * Save the base for this include (saving the current one)
2116  */
2117  oldBase = ctxt->base;
2118  ctxt->base = base;
2119 
2120  if (xml) {
2121  ret = xmlXIncludeLoadDoc(ctxt, URI, nr);
2122  /* xmlXIncludeGetFragment(ctxt, cur, URI); */
2123  } else {
2124  ret = xmlXIncludeLoadTxt(ctxt, URI, nr);
2125  }
2126 
2127  /*
2128  * Restore the original base before checking for fallback
2129  */
2130  ctxt->base = oldBase;
2131 
2132  if (ret < 0) {
2133  xmlNodePtr children;
2134 
2135  /*
2136  * Time to try a fallback if availble
2137  */
2138 #ifdef DEBUG_XINCLUDE
2139  xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");
2140 #endif
2141  children = cur->children;
2142  while (children != NULL) {
2143  if ((children->type == XML_ELEMENT_NODE) &&
2144  (children->ns != NULL) &&
2145  (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
2146  ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
2147  (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
2148  ret = xmlXIncludeLoadFallback(ctxt, children, nr);
2149  if (ret == 0)
2150  break;
2151  }
2152  children = children->next;
2153  }
2154  }
2155  if (ret < 0) {
2156  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2158  "could not load %s, and no fallback was found\n",
2159  URI);
2160  }
2161 
2162  /*
2163  * Cleanup
2164  */
2165  if (URI != NULL)
2166  xmlFree(URI);
2167  if (parse != NULL)
2168  xmlFree(parse);
2169  if (href != NULL)
2170  xmlFree(href);
2171  if (base != NULL)
2172  xmlFree(base);
2173  return(0);
2174 }
2175 
2185 static int
2186 xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
2187  xmlNodePtr cur, end, list, tmp;
2188 
2189  if (ctxt == NULL)
2190  return(-1);
2191  if ((nr < 0) || (nr >= ctxt->incNr))
2192  return(-1);
2193  cur = ctxt->incTab[nr]->ref;
2194  if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2195  return(-1);
2196 
2197  /*
2198  * If we stored an XPointer a late computation may be needed
2199  */
2200  if ((ctxt->incTab[nr]->inc == NULL) &&
2201  (ctxt->incTab[nr]->xptr != NULL)) {
2202  ctxt->incTab[nr]->inc =
2203  xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
2204  ctxt->incTab[nr]->xptr);
2205  xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
2206  ctxt->incTab[nr]->xptr = NULL;
2207  }
2208  list = ctxt->incTab[nr]->inc;
2209  ctxt->incTab[nr]->inc = NULL;
2210 
2211  /*
2212  * Check against the risk of generating a multi-rooted document
2213  */
2214  if ((cur->parent != NULL) &&
2215  (cur->parent->type != XML_ELEMENT_NODE)) {
2216  int nb_elem = 0;
2217 
2218  tmp = list;
2219  while (tmp != NULL) {
2220  if (tmp->type == XML_ELEMENT_NODE)
2221  nb_elem++;
2222  tmp = tmp->next;
2223  }
2224  if (nb_elem > 1) {
2225  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2227  "XInclude error: would result in multiple root nodes\n",
2228  NULL);
2229  return(-1);
2230  }
2231  }
2232 
2233  if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
2234  /*
2235  * Add the list of nodes
2236  */
2237  while (list != NULL) {
2238  end = list;
2239  list = list->next;
2240 
2241  xmlAddPrevSibling(cur, end);
2242  }
2243  xmlUnlinkNode(cur);
2244  xmlFreeNode(cur);
2245  } else {
2246  /*
2247  * Change the current node as an XInclude start one, and add an
2248  * XInclude end one
2249  */
2250  cur->type = XML_XINCLUDE_START;
2251  end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
2252  if (end == NULL) {
2253  xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
2255  "failed to build node\n", NULL);
2256  return(-1);
2257  }
2258  end->type = XML_XINCLUDE_END;
2259  xmlAddNextSibling(cur, end);
2260 
2261  /*
2262  * Add the list of nodes
2263  */
2264  while (list != NULL) {
2265  cur = list;
2266  list = list->next;
2267 
2268  xmlAddPrevSibling(end, cur);
2269  }
2270  }
2271 
2272 
2273  return(0);
2274 }
2275 
2285 static int
2286 xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2287  if (node == NULL)
2288  return(0);
2289  if (node->type != XML_ELEMENT_NODE)
2290  return(0);
2291  if (node->ns == NULL)
2292  return(0);
2293  if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
2294  (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
2295  if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
2296  if (ctxt->legacy == 0) {
2297 #if 0 /* wait for the XML Core Working Group to get something stable ! */
2298  xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
2299  "Deprecated XInclude namespace found, use %s",
2300  XINCLUDE_NS);
2301 #endif
2302  ctxt->legacy = 1;
2303  }
2304  }
2305  if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
2306  xmlNodePtr child = node->children;
2307  int nb_fallback = 0;
2308 
2309  while (child != NULL) {
2310  if ((child->type == XML_ELEMENT_NODE) &&
2311  (child->ns != NULL) &&
2312  ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
2313  (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
2314  if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
2315  xmlXIncludeErr(ctxt, node,
2317  "%s has an 'include' child\n",
2318  XINCLUDE_NODE);
2319  return(0);
2320  }
2321  if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
2322  nb_fallback++;
2323  }
2324  }
2325  child = child->next;
2326  }
2327  if (nb_fallback > 1) {
2328  xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
2329  "%s has multiple fallback children\n",
2330  XINCLUDE_NODE);
2331  return(0);
2332  }
2333  return(1);
2334  }
2335  if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
2336  if ((node->parent == NULL) ||
2337  (node->parent->type != XML_ELEMENT_NODE) ||
2338  (node->parent->ns == NULL) ||
2339  ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
2340  (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
2341  (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
2342  xmlXIncludeErr(ctxt, node,
2344  "%s is not the child of an 'include'\n",
2345  XINCLUDE_FALLBACK);
2346  }
2347  }
2348  }
2349  return(0);
2350 }
2351 
2363 static int
2364 xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
2365  xmlNodePtr cur;
2366  int ret = 0;
2367  int i, start;
2368 
2369  if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2370  return(-1);
2371  if (ctxt == NULL)
2372  return(-1);
2373 
2374  if (doc->URL != NULL) {
2375  ret = xmlXIncludeURLPush(ctxt, doc->URL);
2376  if (ret < 0)
2377  return(-1);
2378  }
2379  start = ctxt->incNr;
2380 
2381  /*
2382  * First phase: lookup the elements in the document
2383  */
2384  cur = tree;
2385  if (xmlXIncludeTestNode(ctxt, cur) == 1)
2386  xmlXIncludePreProcessNode(ctxt, cur);
2387  while ((cur != NULL) && (cur != tree->parent)) {
2388  /* TODO: need to work on entities -> stack */
2389  if ((cur->children != NULL) &&
2390  (cur->children->type != XML_ENTITY_DECL) &&
2391  (cur->children->type != XML_XINCLUDE_START) &&
2392  (cur->children->type != XML_XINCLUDE_END)) {
2393  cur = cur->children;
2394  if (xmlXIncludeTestNode(ctxt, cur))
2395  xmlXIncludePreProcessNode(ctxt, cur);
2396  } else if (cur->next != NULL) {
2397  cur = cur->next;
2398  if (xmlXIncludeTestNode(ctxt, cur))
2399  xmlXIncludePreProcessNode(ctxt, cur);
2400  } else {
2401  if (cur == tree)
2402  break;
2403  do {
2404  cur = cur->parent;
2405  if ((cur == NULL) || (cur == tree->parent))
2406  break; /* do */
2407  if (cur->next != NULL) {
2408  cur = cur->next;
2409  if (xmlXIncludeTestNode(ctxt, cur))
2410  xmlXIncludePreProcessNode(ctxt, cur);
2411  break; /* do */
2412  }
2413  } while (cur != NULL);
2414  }
2415  }
2416 
2417  /*
2418  * Second Phase : collect the infosets fragments
2419  */
2420  for (i = start;i < ctxt->incNr; i++) {
2421  xmlXIncludeLoadNode(ctxt, i);
2422  ret++;
2423  }
2424 
2425  /*
2426  * Third phase: extend the original document infoset.
2427  *
2428  * Originally we bypassed the inclusion if there were any errors
2429  * encountered on any of the XIncludes. A bug was raised (bug
2430  * 132588) requesting that we output the XIncludes without error,
2431  * so the check for inc!=NULL || xptr!=NULL was put in. This may
2432  * give some other problems in the future, but for now it seems to
2433  * work ok.
2434  *
2435  */
2436  for (i = ctxt->incBase;i < ctxt->incNr; i++) {
2437  if ((ctxt->incTab[i]->inc != NULL) ||
2438  (ctxt->incTab[i]->xptr != NULL) ||
2439  (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
2440  xmlXIncludeIncludeNode(ctxt, i);
2441  }
2442 
2443  if (doc->URL != NULL)
2444  xmlXIncludeURLPop(ctxt);
2445  return(ret);
2446 }
2447 
2457 int
2458 xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
2459  if (ctxt == NULL)
2460  return(-1);
2461  ctxt->parseFlags = flags;
2462  return(0);
2463 }
2464 
2478 int
2479 xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
2480  xmlXIncludeCtxtPtr ctxt;
2481  int ret = 0;
2482 
2483  if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2484  (tree->doc == NULL))
2485  return(-1);
2486 
2487  ctxt = xmlXIncludeNewContext(tree->doc);
2488  if (ctxt == NULL)
2489  return(-1);
2490  ctxt->_private = data;
2491  ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
2492  xmlXIncludeSetFlags(ctxt, flags);
2493  ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2494  if ((ret >= 0) && (ctxt->nbErrors > 0))
2495  ret = -1;
2496 
2497  xmlXIncludeFreeContext(ctxt);
2498  return(ret);
2499 }
2500 
2513 int
2514 xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) {
2515  xmlNodePtr tree;
2516 
2517  if (doc == NULL)
2518  return(-1);
2519  tree = xmlDocGetRootElement(doc);
2520  if (tree == NULL)
2521  return(-1);
2522  return(xmlXIncludeProcessTreeFlagsData(tree, flags, data));
2523 }
2524 
2535 int
2536 xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
2537  return xmlXIncludeProcessFlagsData(doc, flags, NULL);
2538 }
2539 
2549 int
2550 xmlXIncludeProcess(xmlDocPtr doc) {
2551  return(xmlXIncludeProcessFlags(doc, 0));
2552 }
2553 
2564 int
2565 xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
2566  xmlXIncludeCtxtPtr ctxt;
2567  int ret = 0;
2568 
2569  if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2570  (tree->doc == NULL))
2571  return(-1);
2572  ctxt = xmlXIncludeNewContext(tree->doc);
2573  if (ctxt == NULL)
2574  return(-1);
2575  ctxt->base = xmlNodeGetBase(tree->doc, tree);
2576  xmlXIncludeSetFlags(ctxt, flags);
2577  ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
2578  if ((ret >= 0) && (ctxt->nbErrors > 0))
2579  ret = -1;
2580 
2581  xmlXIncludeFreeContext(ctxt);
2582  return(ret);
2583 }
2584 
2594 int
2595 xmlXIncludeProcessTree(xmlNodePtr tree) {
2596  return(xmlXIncludeProcessTreeFlags(tree, 0));
2597 }
2598 
2610 int
2611 xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2612  int ret = 0;
2613 
2614  if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
2615  (node->doc == NULL) || (ctxt == NULL))
2616  return(-1);
2617  ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
2618  if ((ret >= 0) && (ctxt->nbErrors > 0))
2619  ret = -1;
2620  return(ret);
2621 }
2622 
2623 #else /* !LIBXML_XINCLUDE_ENABLED */
2624 #endif
2625 #define bottom_xinclude
2626 #include "elfgcchack.h"
xmlEntityType etype
Definition: entities.h:52
XMLPUBFUN xmlChar *XMLCALL xmlBuildRelativeURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:2163
GLint level
Definition: gl.h:1546
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:638
XMLPUBFUN xmlCharEncoding XMLCALL xmlParseCharEncoding(const char *name)
Definition: encoding.c:1150
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:857
#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:1594
XMLPUBFUN void XMLCALL xmlInitParser(void)
Definition: parser.c:14706
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:1709
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:932
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:47
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
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:1882
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:432
xmlNode * xmlNodePtr
Definition: tree.h:488
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:478
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:18
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:15162
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
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:10579
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:1743
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN void XMLCALL xmlDictFree(xmlDictPtr dict)
Definition: dict.c:793
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:2839
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:1379
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:36
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
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:1058
#define printf
Definition: config.h:203
Definition: dlist.c:348
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:362