ReactOS 0.4.16-dev-2232-gc2aaa52
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>
23#include <libxml/xmlerror.h>
24#include <libxml/encoding.h>
25
26#ifdef LIBXML_XINCLUDE_ENABLED
27#include <libxml/xinclude.h>
28
29#include "private/buf.h"
30#include "private/error.h"
31#include "private/tree.h"
32#include "private/xinclude.h"
33
34#define XINCLUDE_MAX_DEPTH 40
35
36/************************************************************************
37 * *
38 * XInclude context handling *
39 * *
40 ************************************************************************/
41
42/*
43 * An XInclude context
44 */
45typedef xmlChar *xmlURL;
46
47typedef struct _xmlXIncludeRef xmlXIncludeRef;
48typedef xmlXIncludeRef *xmlXIncludeRefPtr;
49struct _xmlXIncludeRef {
50 xmlChar *URI; /* the fully resolved resource URL */
51 xmlChar *fragment; /* the fragment in the URI */
52 xmlNodePtr elem; /* the xi:include element */
53 xmlNodePtr inc; /* the included copy */
54 int xml; /* xml or txt */
55 int fallback; /* fallback was loaded */
56 int emptyFb; /* flag to show fallback empty */
57 int expanding; /* flag to detect inclusion loops */
58 int replace; /* should the node be replaced? */
59};
60
61typedef struct _xmlXIncludeDoc xmlXIncludeDoc;
62typedef xmlXIncludeDoc *xmlXIncludeDocPtr;
63struct _xmlXIncludeDoc {
64 xmlDocPtr doc; /* the parsed document */
65 xmlChar *url; /* the URL */
66 int expanding; /* flag to detect inclusion loops */
67};
68
69typedef struct _xmlXIncludeTxt xmlXIncludeTxt;
70typedef xmlXIncludeTxt *xmlXIncludeTxtPtr;
71struct _xmlXIncludeTxt {
72 xmlChar *text; /* text string */
73 xmlChar *url; /* the URL */
74};
75
76struct _xmlXIncludeCtxt {
77 xmlDocPtr doc; /* the source document */
78 int incNr; /* number of includes */
79 int incMax; /* size of includes tab */
80 xmlXIncludeRefPtr *incTab; /* array of included references */
81
82 int txtNr; /* number of unparsed documents */
83 int txtMax; /* size of unparsed documents tab */
84 xmlXIncludeTxt *txtTab; /* array of unparsed documents */
85
86 int urlNr; /* number of documents stacked */
87 int urlMax; /* size of document stack */
88 xmlXIncludeDoc *urlTab; /* document stack */
89
90 int nbErrors; /* the number of errors detected */
91 int fatalErr; /* abort processing */
92 int legacy; /* using XINCLUDE_OLD_NS */
93 int parseFlags; /* the flags used for parsing XML documents */
94 xmlChar * base; /* the current xml:base */
95
96 void *_private; /* application data */
97
98#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
99 unsigned long incTotal; /* total number of processed inclusions */
100#endif
101 int depth; /* recursion depth */
102 int isStream; /* streaming mode */
103};
104
105static xmlXIncludeRefPtr
106xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node);
107
108static int
109xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref);
110
111static int
112xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree);
113
114
115/************************************************************************
116 * *
117 * XInclude error handler *
118 * *
119 ************************************************************************/
120
127static void
128xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node,
129 const char *extra)
130{
131 if (ctxt != NULL)
132 ctxt->nbErrors++;
135 extra, NULL, NULL, 0, 0,
136 "Memory allocation failed : %s\n", extra);
137}
138
148static void LIBXML_ATTR_FORMAT(4,0)
149xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
150 const char *msg, const xmlChar *extra)
151{
152 if (ctxt != NULL)
153 ctxt->nbErrors++;
156 (const char *) extra, NULL, NULL, 0, 0,
157 msg, (const char *) extra);
158}
159
160#if 0
170static void LIBXML_ATTR_FORMAT(4,0)
171xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error,
172 const char *msg, const xmlChar *extra)
173{
176 (const char *) extra, NULL, NULL, 0, 0,
177 msg, (const char *) extra);
178}
179#endif
180
191static xmlChar *
192xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur,
193 const xmlChar *name) {
194 xmlChar *ret;
195
196 ret = xmlGetNsProp(cur, XINCLUDE_NS, name);
197 if (ret != NULL)
198 return(ret);
199 if (ctxt->legacy != 0) {
200 ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name);
201 if (ret != NULL)
202 return(ret);
203 }
204 ret = xmlGetProp(cur, name);
205 return(ret);
206}
213static void
214xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
215 if (ref == NULL)
216 return;
217 if (ref->URI != NULL)
218 xmlFree(ref->URI);
219 if (ref->fragment != NULL)
220 xmlFree(ref->fragment);
221 xmlFree(ref);
222}
223
234static xmlXIncludeRefPtr
235xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI,
236 xmlNodePtr elem) {
237 xmlXIncludeRefPtr ret;
238
239 ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef));
240 if (ret == NULL) {
241 xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context");
242 return(NULL);
243 }
244 memset(ret, 0, sizeof(xmlXIncludeRef));
245 if (URI == NULL)
246 ret->URI = NULL;
247 else
248 ret->URI = xmlStrdup(URI);
249 ret->fragment = NULL;
250 ret->elem = elem;
251 ret->xml = 0;
252 ret->inc = NULL;
253 if (ctxt->incNr >= ctxt->incMax) {
254 xmlXIncludeRefPtr *tmp;
255#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
256 size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 1;
257#else
258 size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 4;
259#endif
260
261 tmp = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab,
262 newSize * sizeof(ctxt->incTab[0]));
263 if (tmp == NULL) {
264 xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context");
265 xmlXIncludeFreeRef(ret);
266 return(NULL);
267 }
268 ctxt->incTab = tmp;
269 ctxt->incMax = newSize;
270 }
271 ctxt->incTab[ctxt->incNr++] = ret;
272 return(ret);
273}
274
283xmlXIncludeCtxtPtr
284xmlXIncludeNewContext(xmlDocPtr doc) {
285 xmlXIncludeCtxtPtr ret;
286
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->incMax = 0;
299 ret->incTab = NULL;
300 ret->nbErrors = 0;
301 return(ret);
302}
303
310void
311xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
312 int i;
313
314 if (ctxt == NULL)
315 return;
316 if (ctxt->urlTab != NULL) {
317 for (i = 0; i < ctxt->urlNr; i++) {
318 xmlFreeDoc(ctxt->urlTab[i].doc);
319 xmlFree(ctxt->urlTab[i].url);
320 }
321 xmlFree(ctxt->urlTab);
322 }
323 for (i = 0;i < ctxt->incNr;i++) {
324 if (ctxt->incTab[i] != NULL)
325 xmlXIncludeFreeRef(ctxt->incTab[i]);
326 }
327 if (ctxt->incTab != NULL)
328 xmlFree(ctxt->incTab);
329 if (ctxt->txtTab != NULL) {
330 for (i = 0;i < ctxt->txtNr;i++) {
331 xmlFree(ctxt->txtTab[i].text);
332 xmlFree(ctxt->txtTab[i].url);
333 }
334 xmlFree(ctxt->txtTab);
335 }
336 if (ctxt->base != NULL) {
337 xmlFree(ctxt->base);
338 }
339 xmlFree(ctxt);
340}
341
349static xmlDocPtr
350xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) {
351 xmlDocPtr ret;
352 xmlParserCtxtPtr pctxt;
353 xmlParserInputPtr inputStream;
354
356
357 pctxt = xmlNewParserCtxt();
358 if (pctxt == NULL) {
359 xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context");
360 return(NULL);
361 }
362
363 /*
364 * pass in the application data to the parser context.
365 */
366 pctxt->_private = ctxt->_private;
367
368 /*
369 * try to ensure that new documents included are actually
370 * built with the same dictionary as the including document.
371 */
372 if ((ctxt->doc != NULL) && (ctxt->doc->dict != NULL)) {
373 if (pctxt->dict != NULL)
374 xmlDictFree(pctxt->dict);
375 pctxt->dict = ctxt->doc->dict;
376 xmlDictReference(pctxt->dict);
377 }
378
379 xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD);
380
381 /* Don't read from stdin. */
382 if ((URL != NULL) && (strcmp(URL, "-") == 0))
383 URL = "./-";
384
385 inputStream = xmlLoadExternalEntity(URL, NULL, pctxt);
386 if (inputStream == NULL) {
387 xmlFreeParserCtxt(pctxt);
388 return(NULL);
389 }
390
391 inputPush(pctxt, inputStream);
392
393 if (pctxt->directory == NULL)
394 pctxt->directory = xmlParserGetDirectory(URL);
395
396 pctxt->loadsubset |= XML_DETECT_IDS;
397
398 xmlParseDocument(pctxt);
399
400 if (pctxt->wellFormed) {
401 ret = pctxt->myDoc;
402 }
403 else {
404 ret = NULL;
405 if (pctxt->myDoc != NULL)
406 xmlFreeDoc(pctxt->myDoc);
407 pctxt->myDoc = NULL;
408 }
409 xmlFreeParserCtxt(pctxt);
410
411 return(ret);
412}
413
421static xmlXIncludeRefPtr
422xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
423 xmlXIncludeRefPtr ref;
425 xmlChar *URL;
426 xmlChar *fragment = NULL;
427 xmlChar *href;
428 xmlChar *parse;
429 xmlChar *base;
430 xmlChar *URI;
431 int xml = 1;
432 int local = 0;
433
434
435 if (ctxt == NULL)
436 return(NULL);
437 if (cur == NULL)
438 return(NULL);
439
440 /*
441 * read the attributes
442 */
443 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
444 if (href == NULL) {
445 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
446 if (href == NULL)
447 return(NULL);
448 }
449 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
450 if (parse != NULL) {
451 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
452 xml = 1;
453 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
454 xml = 0;
455 else {
456 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
457 "invalid value %s for 'parse'\n", parse);
458 if (href != NULL)
459 xmlFree(href);
460 if (parse != NULL)
461 xmlFree(parse);
462 return(NULL);
463 }
464 }
465
466 /*
467 * compute the URI
468 */
469 base = xmlNodeGetBase(ctxt->doc, cur);
470 if (base == NULL) {
471 URI = xmlBuildURI(href, ctxt->doc->URL);
472 } else {
473 URI = xmlBuildURI(href, base);
474 }
475 if (URI == NULL) {
476 xmlChar *escbase;
477 xmlChar *eschref;
478 /*
479 * Some escaping may be needed
480 */
481 escbase = xmlURIEscape(base);
482 eschref = xmlURIEscape(href);
483 URI = xmlBuildURI(eschref, escbase);
484 if (escbase != NULL)
485 xmlFree(escbase);
486 if (eschref != NULL)
487 xmlFree(eschref);
488 }
489 if (parse != NULL)
490 xmlFree(parse);
491 if (href != NULL)
492 xmlFree(href);
493 if (base != NULL)
494 xmlFree(base);
495 if (URI == NULL) {
496 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
497 "failed build URL\n", NULL);
498 return(NULL);
499 }
500 fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER);
501
502 /*
503 * Check the URL and remove any fragment identifier
504 */
505 uri = xmlParseURI((const char *)URI);
506 if (uri == NULL) {
507 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
508 "invalid value URI %s\n", URI);
509 if (fragment != NULL)
510 xmlFree(fragment);
511 xmlFree(URI);
512 return(NULL);
513 }
514
515 if (uri->fragment != NULL) {
516 if (ctxt->legacy != 0) {
517 if (fragment == NULL) {
518 fragment = (xmlChar *) uri->fragment;
519 } else {
520 xmlFree(uri->fragment);
521 }
522 } else {
523 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID,
524 "Invalid fragment identifier in URI %s use the xpointer attribute\n",
525 URI);
526 if (fragment != NULL)
527 xmlFree(fragment);
529 xmlFree(URI);
530 return(NULL);
531 }
532 uri->fragment = NULL;
533 }
534 URL = xmlSaveUri(uri);
536 if (URL == NULL) {
537 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
538 "invalid value URI %s\n", URI);
539 if (fragment != NULL)
540 xmlFree(fragment);
541 xmlFree(URI);
542 return(NULL);
543 }
544 xmlFree(URI);
545
546 if (xmlStrEqual(URL, ctxt->doc->URL))
547 local = 1;
548
549 /*
550 * If local and xml then we need a fragment
551 */
552 if ((local == 1) && (xml == 1) &&
553 ((fragment == NULL) || (fragment[0] == 0))) {
554 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
555 "detected a local recursion with no xpointer in %s\n",
556 URL);
557 xmlFree(URL);
558 xmlFree(fragment);
559 return(NULL);
560 }
561
562 ref = xmlXIncludeNewRef(ctxt, URL, cur);
563 xmlFree(URL);
564 if (ref == NULL) {
565 xmlFree(fragment);
566 return(NULL);
567 }
568 ref->fragment = fragment;
569 ref->xml = xml;
570 return(ref);
571}
572
581static void
582xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
583 const xmlURL url ATTRIBUTE_UNUSED) {
584 xmlDocPtr oldDoc;
585 xmlXIncludeRefPtr *oldIncTab;
586 int oldIncMax, oldIncNr, oldIsStream;
587 int i;
588
589 oldDoc = ctxt->doc;
590 oldIncMax = ctxt->incMax;
591 oldIncNr = ctxt->incNr;
592 oldIncTab = ctxt->incTab;
593 oldIsStream = ctxt->isStream;
594 ctxt->doc = doc;
595 ctxt->incMax = 0;
596 ctxt->incNr = 0;
597 ctxt->incTab = NULL;
598 ctxt->isStream = 0;
599
600 xmlXIncludeDoProcess(ctxt, xmlDocGetRootElement(doc));
601
602 if (ctxt->incTab != NULL) {
603 for (i = 0; i < ctxt->incNr; i++)
604 xmlXIncludeFreeRef(ctxt->incTab[i]);
605 xmlFree(ctxt->incTab);
606 }
607
608 ctxt->doc = oldDoc;
609 ctxt->incMax = oldIncMax;
610 ctxt->incNr = oldIncNr;
611 ctxt->incTab = oldIncTab;
612 ctxt->isStream = oldIsStream;
613}
614
615/************************************************************************
616 * *
617 * Node copy with specific semantic *
618 * *
619 ************************************************************************/
620
631static xmlNodePtr
632xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem,
633 int copyChildren) {
634 xmlNodePtr result = NULL;
635 xmlNodePtr insertParent = NULL;
636 xmlNodePtr insertLast = NULL;
637 xmlNodePtr cur;
638
639 if (copyChildren) {
640 cur = elem->children;
641 if (cur == NULL)
642 return(NULL);
643 } else {
644 cur = elem;
645 }
646
647 while (1) {
648 xmlNodePtr copy = NULL;
649 int recurse = 0;
650
651 if ((cur->type == XML_DOCUMENT_NODE) ||
652 (cur->type == XML_DTD_NODE)) {
653 ;
654 } else if ((cur->type == XML_ELEMENT_NODE) &&
655 (cur->ns != NULL) &&
656 (xmlStrEqual(cur->name, XINCLUDE_NODE)) &&
657 ((xmlStrEqual(cur->ns->href, XINCLUDE_NS)) ||
658 (xmlStrEqual(cur->ns->href, XINCLUDE_OLD_NS)))) {
659 xmlXIncludeRefPtr ref = xmlXIncludeExpandNode(ctxt, cur);
660
661 if (ref == NULL)
662 goto error;
663 /*
664 * TODO: Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes
665 */
666 if (ref->inc != NULL) {
667 copy = xmlStaticCopyNodeList(ref->inc, ctxt->doc,
668 insertParent);
669 if (copy == NULL)
670 goto error;
671 }
672 } else {
673 copy = xmlStaticCopyNode(cur, ctxt->doc, insertParent, 2);
674 if (copy == NULL)
675 goto error;
676
677 recurse = (cur->type != XML_ENTITY_REF_NODE) &&
678 (cur->children != NULL);
679 }
680
681 if (copy != NULL) {
682 if (result == NULL)
683 result = copy;
684 if (insertLast != NULL) {
685 insertLast->next = copy;
686 copy->prev = insertLast;
687 } else if (insertParent != NULL) {
688 insertParent->children = copy;
689 }
690 insertLast = copy;
691 while (insertLast->next != NULL) {
692 insertLast = insertLast->next;
693 }
694 }
695
696 if (recurse) {
697 cur = cur->children;
698 insertParent = insertLast;
699 insertLast = NULL;
700 continue;
701 }
702
703 if (cur == elem)
704 return(result);
705
706 while (cur->next == NULL) {
707 if (insertParent != NULL)
708 insertParent->last = insertLast;
709 cur = cur->parent;
710 if (cur == elem)
711 return(result);
712 insertLast = insertParent;
713 insertParent = insertParent->parent;
714 }
715
716 cur = cur->next;
717 }
718
719error:
720 xmlFreeNodeList(result);
721 return(NULL);
722}
723
724#ifdef LIBXML_XPTR_LOCS_ENABLED
732static xmlNodePtr
733xmlXIncludeGetNthChild(xmlNodePtr cur, int no) {
734 int i;
735 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
736 return(NULL);
737 cur = cur->children;
738 for (i = 0;i <= no;cur = cur->next) {
739 if (cur == NULL)
740 return(cur);
741 if ((cur->type == XML_ELEMENT_NODE) ||
742 (cur->type == XML_DOCUMENT_NODE) ||
743 (cur->type == XML_HTML_DOCUMENT_NODE)) {
744 i++;
745 if (i == no)
746 break;
747 }
748 }
749 return(cur);
750}
751
752xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level); /* in xpointer.c */
763static xmlNodePtr
764xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr range) {
765 /* pointers to generated nodes */
766 xmlNodePtr list = NULL, last = NULL, listParent = NULL;
767 xmlNodePtr tmp, tmp2;
768 /* pointers to traversal nodes */
769 xmlNodePtr start, cur, end;
770 int index1, index2;
771 int level = 0, lastLevel = 0, endLevel = 0, endFlag = 0;
772
773 if ((ctxt == NULL) || (range == NULL))
774 return(NULL);
775 if (range->type != XPATH_RANGE)
776 return(NULL);
777 start = (xmlNodePtr) range->user;
778
779 if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
780 return(NULL);
781 end = range->user2;
782 if (end == NULL)
783 return(xmlDocCopyNode(start, ctxt->doc, 1));
784 if (end->type == XML_NAMESPACE_DECL)
785 return(NULL);
786
787 cur = start;
788 index1 = range->index;
789 index2 = range->index2;
790 /*
791 * level is depth of the current node under consideration
792 * list is the pointer to the root of the output tree
793 * listParent is a pointer to the parent of output tree (within
794 the included file) in case we need to add another level
795 * last is a pointer to the last node added to the output tree
796 * lastLevel is the depth of last (relative to the root)
797 */
798 while (cur != NULL) {
799 /*
800 * Check if our output tree needs a parent
801 */
802 if (level < 0) {
803 while (level < 0) {
804 /* copy must include namespaces and properties */
805 tmp2 = xmlDocCopyNode(listParent, ctxt->doc, 2);
806 xmlAddChild(tmp2, list);
807 list = tmp2;
808 listParent = listParent->parent;
809 level++;
810 }
811 last = list;
812 lastLevel = 0;
813 }
814 /*
815 * Check whether we need to change our insertion point
816 */
817 while (level < lastLevel) {
818 last = last->parent;
819 lastLevel --;
820 }
821 if (cur == end) { /* Are we at the end of the range? */
822 if (cur->type == XML_TEXT_NODE) {
823 const xmlChar *content = cur->content;
824 int len;
825
826 if (content == NULL) {
827 tmp = xmlNewDocTextLen(ctxt->doc, NULL, 0);
828 } else {
829 len = index2;
830 if ((cur == start) && (index1 > 1)) {
831 content += (index1 - 1);
832 len -= (index1 - 1);
833 } else {
834 len = index2;
835 }
836 tmp = xmlNewDocTextLen(ctxt->doc, content, len);
837 }
838 /* single sub text node selection */
839 if (list == NULL)
840 return(tmp);
841 /* prune and return full set */
842 if (level == lastLevel)
843 xmlAddNextSibling(last, tmp);
844 else
845 xmlAddChild(last, tmp);
846 return(list);
847 } else { /* ending node not a text node */
848 endLevel = level; /* remember the level of the end node */
849 endFlag = 1;
850 /* last node - need to take care of properties + namespaces */
851 tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
852 if (list == NULL) {
853 list = tmp;
854 listParent = cur->parent;
855 last = tmp;
856 } else {
857 if (level == lastLevel)
858 last = xmlAddNextSibling(last, tmp);
859 else {
860 last = xmlAddChild(last, tmp);
861 lastLevel = level;
862 }
863 }
864
865 if (index2 > 1) {
866 end = xmlXIncludeGetNthChild(cur, index2 - 1);
867 index2 = 0;
868 }
869 if ((cur == start) && (index1 > 1)) {
870 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
871 index1 = 0;
872 } else {
873 cur = cur->children;
874 }
875 level++; /* increment level to show change */
876 /*
877 * Now gather the remaining nodes from cur to end
878 */
879 continue; /* while */
880 }
881 } else if (cur == start) { /* Not at the end, are we at start? */
882 if ((cur->type == XML_TEXT_NODE) ||
883 (cur->type == XML_CDATA_SECTION_NODE)) {
884 const xmlChar *content = cur->content;
885
886 if (content == NULL) {
887 tmp = xmlNewDocTextLen(ctxt->doc, NULL, 0);
888 } else {
889 if (index1 > 1) {
890 content += (index1 - 1);
891 index1 = 0;
892 }
893 tmp = xmlNewDocText(ctxt->doc, content);
894 }
895 last = list = tmp;
896 listParent = cur->parent;
897 } else { /* Not text node */
898 /*
899 * start of the range - need to take care of
900 * properties and namespaces
901 */
902 tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
903 list = last = tmp;
904 listParent = cur->parent;
905 if (index1 > 1) { /* Do we need to position? */
906 cur = xmlXIncludeGetNthChild(cur, index1 - 1);
907 level = lastLevel = 1;
908 index1 = 0;
909 /*
910 * Now gather the remaining nodes from cur to end
911 */
912 continue; /* while */
913 }
914 }
915 } else {
916 tmp = NULL;
917 switch (cur->type) {
918 case XML_DTD_NODE:
919 case XML_ELEMENT_DECL:
920 case XML_ATTRIBUTE_DECL:
921 case XML_ENTITY_NODE:
922 /* Do not copy DTD information */
923 break;
924 case XML_ENTITY_DECL:
925 /* handle crossing entities -> stack needed */
926 break;
927 case XML_XINCLUDE_START:
928 case XML_XINCLUDE_END:
929 /* don't consider it part of the tree content */
930 break;
931 case XML_ATTRIBUTE_NODE:
932 /* Humm, should not happen ! */
933 break;
934 default:
935 /*
936 * Middle of the range - need to take care of
937 * properties and namespaces
938 */
939 tmp = xmlDocCopyNode(cur, ctxt->doc, 2);
940 break;
941 }
942 if (tmp != NULL) {
943 if (level == lastLevel)
944 last = xmlAddNextSibling(last, tmp);
945 else {
946 last = xmlAddChild(last, tmp);
947 lastLevel = level;
948 }
949 }
950 }
951 /*
952 * Skip to next node in document order
953 */
954 cur = xmlXPtrAdvanceNode(cur, &level);
955 if (endFlag && (level >= endLevel))
956 break;
957 }
958 return(list);
959}
960#endif /* LIBXML_XPTR_LOCS_ENABLED */
961
973static xmlNodePtr
974xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) {
975 xmlNodePtr list = NULL, last = NULL, copy;
976 int i;
977
978 if ((ctxt == NULL) || (obj == NULL))
979 return(NULL);
980 switch (obj->type) {
981 case XPATH_NODESET: {
982 xmlNodeSetPtr set = obj->nodesetval;
983 if (set == NULL)
984 return(NULL);
985 for (i = 0;i < set->nodeNr;i++) {
986 xmlNodePtr node;
987
988 if (set->nodeTab[i] == NULL)
989 continue;
990 switch (set->nodeTab[i]->type) {
991 case XML_DOCUMENT_NODE:
992 case XML_HTML_DOCUMENT_NODE:
993 node = xmlDocGetRootElement(
994 (xmlDocPtr) set->nodeTab[i]);
995 if (node == NULL) {
996 xmlXIncludeErr(ctxt, set->nodeTab[i],
998 "document without root\n", NULL);
999 continue;
1000 }
1001 break;
1002 case XML_TEXT_NODE:
1003 case XML_CDATA_SECTION_NODE:
1004 case XML_ELEMENT_NODE:
1005 case XML_PI_NODE:
1006 case XML_COMMENT_NODE:
1007 node = set->nodeTab[i];
1008 break;
1009 default:
1010 xmlXIncludeErr(ctxt, set->nodeTab[i],
1012 "invalid node type in XPtr result\n",
1013 NULL);
1014 continue; /* for */
1015 }
1016 /*
1017 * OPTIMIZE TODO: External documents should already be
1018 * expanded, so xmlDocCopyNode should work as well.
1019 * xmlXIncludeCopyNode is only required for the initial
1020 * document.
1021 */
1022 copy = xmlXIncludeCopyNode(ctxt, node, 0);
1023 if (copy == NULL) {
1024 xmlFreeNodeList(list);
1025 return(NULL);
1026 }
1027 if (last == NULL) {
1028 list = copy;
1029 } else {
1030 while (last->next != NULL)
1031 last = last->next;
1032 copy->prev = last;
1033 last->next = copy;
1034 }
1035 last = copy;
1036 }
1037 break;
1038 }
1039#ifdef LIBXML_XPTR_LOCS_ENABLED
1040 case XPATH_LOCATIONSET: {
1041 xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1042 if (set == NULL)
1043 return(NULL);
1044 for (i = 0;i < set->locNr;i++) {
1045 if (last == NULL)
1046 list = last = xmlXIncludeCopyXPointer(ctxt,
1047 set->locTab[i]);
1048 else
1049 xmlAddNextSibling(last,
1050 xmlXIncludeCopyXPointer(ctxt, set->locTab[i]));
1051 if (last != NULL) {
1052 while (last->next != NULL)
1053 last = last->next;
1054 }
1055 }
1056 break;
1057 }
1058 case XPATH_RANGE:
1059 return(xmlXIncludeCopyRange(ctxt, obj));
1060 case XPATH_POINT:
1061 /* points are ignored in XInclude */
1062 break;
1063#endif
1064 default:
1065 break;
1066 }
1067 return(list);
1068}
1069/************************************************************************
1070 * *
1071 * XInclude I/O handling *
1072 * *
1073 ************************************************************************/
1074
1075typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData;
1076typedef xmlXIncludeMergeData *xmlXIncludeMergeDataPtr;
1077struct _xmlXIncludeMergeData {
1078 xmlDocPtr doc;
1079 xmlXIncludeCtxtPtr ctxt;
1080};
1081
1090static void
1091xmlXIncludeMergeEntity(void *payload, void *vdata,
1092 const xmlChar *name ATTRIBUTE_UNUSED) {
1093 xmlEntityPtr ent = (xmlEntityPtr) payload;
1094 xmlXIncludeMergeDataPtr data = (xmlXIncludeMergeDataPtr) vdata;
1095 xmlEntityPtr ret, prev;
1096 xmlDocPtr doc;
1097 xmlXIncludeCtxtPtr ctxt;
1098
1099 if ((ent == NULL) || (data == NULL))
1100 return;
1101 ctxt = data->ctxt;
1102 doc = data->doc;
1103 if ((ctxt == NULL) || (doc == NULL))
1104 return;
1105 switch (ent->etype) {
1109 return;
1113 break;
1114 }
1115 ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID,
1116 ent->SystemID, ent->content);
1117 if (ret != NULL) {
1118 if (ent->URI != NULL)
1119 ret->URI = xmlStrdup(ent->URI);
1120 } else {
1121 prev = xmlGetDocEntity(doc, ent->name);
1122 if (prev != NULL) {
1123 if (ent->etype != prev->etype)
1124 goto error;
1125
1126 if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) {
1127 if (!xmlStrEqual(ent->SystemID, prev->SystemID))
1128 goto error;
1129 } else if ((ent->ExternalID != NULL) &&
1130 (prev->ExternalID != NULL)) {
1131 if (!xmlStrEqual(ent->ExternalID, prev->ExternalID))
1132 goto error;
1133 } else if ((ent->content != NULL) && (prev->content != NULL)) {
1134 if (!xmlStrEqual(ent->content, prev->content))
1135 goto error;
1136 } else {
1137 goto error;
1138 }
1139
1140 }
1141 }
1142 return;
1143error:
1144 switch (ent->etype) {
1150 return;
1152 break;
1153 }
1154 xmlXIncludeErr(ctxt, (xmlNodePtr) ent, XML_XINCLUDE_ENTITY_DEF_MISMATCH,
1155 "mismatch in redefinition of entity %s\n",
1156 ent->name);
1157}
1158
1169static int
1170xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
1171 xmlDocPtr from) {
1172 xmlNodePtr cur;
1173 xmlDtdPtr target, source;
1174
1175 if (ctxt == NULL)
1176 return(-1);
1177
1178 if ((from == NULL) || (from->intSubset == NULL))
1179 return(0);
1180
1181 target = doc->intSubset;
1182 if (target == NULL) {
1183 cur = xmlDocGetRootElement(doc);
1184 if (cur == NULL)
1185 return(-1);
1186 target = xmlCreateIntSubset(doc, cur->name, NULL, NULL);
1187 if (target == NULL)
1188 return(-1);
1189 }
1190
1191 source = from->intSubset;
1192 if ((source != NULL) && (source->entities != NULL)) {
1193 xmlXIncludeMergeData data;
1194
1195 data.ctxt = ctxt;
1196 data.doc = doc;
1197
1199 xmlXIncludeMergeEntity, &data);
1200 }
1201 source = from->extSubset;
1202 if ((source != NULL) && (source->entities != NULL)) {
1203 xmlXIncludeMergeData data;
1204
1205 data.ctxt = ctxt;
1206 data.doc = doc;
1207
1208 /*
1209 * don't duplicate existing stuff when external subsets are the same
1210 */
1211 if ((!xmlStrEqual(target->ExternalID, source->ExternalID)) &&
1212 (!xmlStrEqual(target->SystemID, source->SystemID))) {
1214 xmlXIncludeMergeEntity, &data);
1215 }
1216 }
1217 return(0);
1218}
1219
1230static int
1231xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
1232 xmlXIncludeRefPtr ref) {
1233 xmlXIncludeDocPtr cache;
1234 xmlDocPtr doc;
1235 xmlURIPtr uri;
1236 xmlChar *URL = NULL;
1237 xmlChar *fragment = NULL;
1238 int i = 0;
1239 int ret = -1;
1240 int cacheNr;
1241#ifdef LIBXML_XPTR_ENABLED
1242 int saveFlags;
1243#endif
1244
1245 /*
1246 * Check the URL and remove any fragment identifier
1247 */
1248 uri = xmlParseURI((const char *)url);
1249 if (uri == NULL) {
1250 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI,
1251 "invalid value URI %s\n", url);
1252 goto error;
1253 }
1254 if (uri->fragment != NULL) {
1255 fragment = (xmlChar *) uri->fragment;
1256 uri->fragment = NULL;
1257 }
1258 if (ref->fragment != NULL) {
1259 if (fragment != NULL) xmlFree(fragment);
1260 fragment = xmlStrdup(ref->fragment);
1261 }
1262 URL = xmlSaveUri(uri);
1263 xmlFreeURI(uri);
1264 if (URL == NULL) {
1265 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI,
1266 "invalid value URI %s\n", url);
1267 goto error;
1268 }
1269
1270 /*
1271 * Handling of references to the local document are done
1272 * directly through ctxt->doc.
1273 */
1274 if ((URL[0] == 0) || (URL[0] == '#') ||
1275 ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
1276 doc = ctxt->doc;
1277 goto loaded;
1278 }
1279
1280 /*
1281 * Prevent reloading the document twice.
1282 */
1283 for (i = 0; i < ctxt->urlNr; i++) {
1284 if (xmlStrEqual(URL, ctxt->urlTab[i].url)) {
1285 if (ctxt->urlTab[i].expanding) {
1286 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_RECURSION,
1287 "inclusion loop detected\n", NULL);
1288 goto error;
1289 }
1290 doc = ctxt->urlTab[i].doc;
1291 if (doc == NULL)
1292 goto error;
1293 goto loaded;
1294 }
1295 }
1296
1297 /*
1298 * Load it.
1299 */
1300#ifdef LIBXML_XPTR_ENABLED
1301 /*
1302 * If this is an XPointer evaluation, we want to assure that
1303 * all entities have been resolved prior to processing the
1304 * referenced document
1305 */
1306 saveFlags = ctxt->parseFlags;
1307 if (fragment != NULL) { /* if this is an XPointer eval */
1308 ctxt->parseFlags |= XML_PARSE_NOENT;
1309 }
1310#endif
1311
1312 doc = xmlXIncludeParseFile(ctxt, (const char *)URL);
1313#ifdef LIBXML_XPTR_ENABLED
1314 ctxt->parseFlags = saveFlags;
1315#endif
1316
1317 /* Also cache NULL docs */
1318 if (ctxt->urlNr >= ctxt->urlMax) {
1319 xmlXIncludeDoc *tmp;
1320#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1321 size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 1;
1322#else
1323 size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 8;
1324#endif
1325
1326 tmp = xmlRealloc(ctxt->urlTab, sizeof(xmlXIncludeDoc) * newSize);
1327 if (tmp == NULL) {
1328 xmlXIncludeErrMemory(ctxt, ref->elem,
1329 "growing XInclude URL table");
1330 xmlFreeDoc(doc);
1331 goto error;
1332 }
1333 ctxt->urlMax = newSize;
1334 ctxt->urlTab = tmp;
1335 }
1336 cacheNr = ctxt->urlNr++;
1337 cache = &ctxt->urlTab[cacheNr];
1338 cache->doc = doc;
1339 cache->url = xmlStrdup(URL);
1340 cache->expanding = 0;
1341
1342 if (doc == NULL)
1343 goto error;
1344 /*
1345 * It's possible that the requested URL has been mapped to a
1346 * completely different location (e.g. through a catalog entry).
1347 * To check for this, we compare the URL with that of the doc
1348 * and change it if they disagree (bug 146988).
1349 */
1350 if (!xmlStrEqual(URL, doc->URL)) {
1351 xmlFree(URL);
1352 URL = xmlStrdup(doc->URL);
1353 }
1354
1355 /*
1356 * Make sure we have all entities fixed up
1357 */
1358 xmlXIncludeMergeEntities(ctxt, ctxt->doc, doc);
1359
1360 /*
1361 * We don't need the DTD anymore, free up space
1362 if (doc->intSubset != NULL) {
1363 xmlUnlinkNode((xmlNodePtr) doc->intSubset);
1364 xmlFreeNode((xmlNodePtr) doc->intSubset);
1365 doc->intSubset = NULL;
1366 }
1367 if (doc->extSubset != NULL) {
1368 xmlUnlinkNode((xmlNodePtr) doc->extSubset);
1369 xmlFreeNode((xmlNodePtr) doc->extSubset);
1370 doc->extSubset = NULL;
1371 }
1372 */
1373 cache->expanding = 1;
1374 xmlXIncludeRecurseDoc(ctxt, doc, URL);
1375 /* urlTab might be reallocated. */
1376 cache = &ctxt->urlTab[cacheNr];
1377 cache->expanding = 0;
1378
1379loaded:
1380 if (fragment == NULL) {
1381 /*
1382 * Add the top children list as the replacement copy.
1383 */
1384 ref->inc = xmlDocCopyNode(xmlDocGetRootElement(doc), ctxt->doc, 1);
1385 }
1386#ifdef LIBXML_XPTR_ENABLED
1387 else {
1388 /*
1389 * Computes the XPointer expression and make a copy used
1390 * as the replacement copy.
1391 */
1392 xmlXPathObjectPtr xptr;
1393 xmlXPathContextPtr xptrctxt;
1394 xmlNodeSetPtr set;
1395
1396 if (ctxt->isStream && doc == ctxt->doc) {
1397 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED,
1398 "XPointer expressions not allowed in streaming"
1399 " mode\n", NULL);
1400 goto error;
1401 }
1402
1403 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
1404 if (xptrctxt == NULL) {
1405 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED,
1406 "could not create XPointer context\n", NULL);
1407 goto error;
1408 }
1409 xptr = xmlXPtrEval(fragment, xptrctxt);
1410 if (xptr == NULL) {
1411 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED,
1412 "XPointer evaluation failed: #%s\n",
1413 fragment);
1414 xmlXPathFreeContext(xptrctxt);
1415 goto error;
1416 }
1417 switch (xptr->type) {
1418 case XPATH_UNDEFINED:
1419 case XPATH_BOOLEAN:
1420 case XPATH_NUMBER:
1421 case XPATH_STRING:
1422#ifdef LIBXML_XPTR_LOCS_ENABLED
1423 case XPATH_POINT:
1424#endif
1425 case XPATH_USERS:
1426 case XPATH_XSLT_TREE:
1427 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_RESULT,
1428 "XPointer is not a range: #%s\n",
1429 fragment);
1430 xmlXPathFreeObject(xptr);
1431 xmlXPathFreeContext(xptrctxt);
1432 goto error;
1433 case XPATH_NODESET:
1434 if ((xptr->nodesetval == NULL) ||
1435 (xptr->nodesetval->nodeNr <= 0)) {
1436 xmlXPathFreeObject(xptr);
1437 xmlXPathFreeContext(xptrctxt);
1438 goto error;
1439 }
1440
1441#ifdef LIBXML_XPTR_LOCS_ENABLED
1442 case XPATH_RANGE:
1443 case XPATH_LOCATIONSET:
1444 break;
1445#endif
1446 }
1447 set = xptr->nodesetval;
1448 if (set != NULL) {
1449 for (i = 0;i < set->nodeNr;i++) {
1450 if (set->nodeTab[i] == NULL)
1451 continue;
1452 switch (set->nodeTab[i]->type) {
1453 case XML_ELEMENT_NODE:
1454 case XML_TEXT_NODE:
1455 case XML_CDATA_SECTION_NODE:
1456 case XML_ENTITY_REF_NODE:
1457 case XML_ENTITY_NODE:
1458 case XML_PI_NODE:
1459 case XML_COMMENT_NODE:
1460 case XML_DOCUMENT_NODE:
1461 case XML_HTML_DOCUMENT_NODE:
1462 continue;
1463
1464 case XML_ATTRIBUTE_NODE:
1465 xmlXIncludeErr(ctxt, ref->elem,
1467 "XPointer selects an attribute: #%s\n",
1468 fragment);
1469 set->nodeTab[i] = NULL;
1470 continue;
1471 case XML_NAMESPACE_DECL:
1472 xmlXIncludeErr(ctxt, ref->elem,
1474 "XPointer selects a namespace: #%s\n",
1475 fragment);
1476 set->nodeTab[i] = NULL;
1477 continue;
1478 case XML_DOCUMENT_TYPE_NODE:
1479 case XML_DOCUMENT_FRAG_NODE:
1480 case XML_NOTATION_NODE:
1481 case XML_DTD_NODE:
1482 case XML_ELEMENT_DECL:
1483 case XML_ATTRIBUTE_DECL:
1484 case XML_ENTITY_DECL:
1485 case XML_XINCLUDE_START:
1486 case XML_XINCLUDE_END:
1487 xmlXIncludeErr(ctxt, ref->elem,
1489 "XPointer selects unexpected nodes: #%s\n",
1490 fragment);
1491 set->nodeTab[i] = NULL;
1492 set->nodeTab[i] = NULL;
1493 continue; /* for */
1494 }
1495 }
1496 }
1497 ref->inc = xmlXIncludeCopyXPointer(ctxt, xptr);
1498 xmlXPathFreeObject(xptr);
1499 xmlXPathFreeContext(xptrctxt);
1500 }
1501#endif
1502
1503 /*
1504 * Do the xml:base fixup if needed
1505 */
1506 if ((doc != NULL) && (URL != NULL) &&
1507 (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) &&
1508 (!(doc->parseFlags & XML_PARSE_NOBASEFIX))) {
1509 xmlNodePtr node;
1510 xmlChar *base;
1511 xmlChar *curBase;
1512
1513 /*
1514 * The base is only adjusted if "necessary", i.e. if the xinclude node
1515 * has a base specified, or the URL is relative
1516 */
1517 base = xmlGetNsProp(ref->elem, BAD_CAST "base", XML_XML_NAMESPACE);
1518 if (base == NULL) {
1519 /*
1520 * No xml:base on the xinclude node, so we check whether the
1521 * URI base is different than (relative to) the context base
1522 */
1523 curBase = xmlBuildRelativeURI(URL, ctxt->base);
1524 if (curBase == NULL) { /* Error return */
1525 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI,
1526 "trying to build relative URI from %s\n", URL);
1527 } else {
1528 /* If the URI doesn't contain a slash, it's not relative */
1529 if (!xmlStrchr(curBase, '/'))
1530 xmlFree(curBase);
1531 else
1532 base = curBase;
1533 }
1534 }
1535 if (base != NULL) { /* Adjustment may be needed */
1536 node = ref->inc;
1537 while (node != NULL) {
1538 /* Only work on element nodes */
1539 if (node->type == XML_ELEMENT_NODE) {
1540 curBase = xmlNodeGetBase(node->doc, node);
1541 /* If no current base, set it */
1542 if (curBase == NULL) {
1543 xmlNodeSetBase(node, base);
1544 } else {
1545 /*
1546 * If the current base is the same as the
1547 * URL of the document, then reset it to be
1548 * the specified xml:base or the relative URI
1549 */
1550 if (xmlStrEqual(curBase, node->doc->URL)) {
1551 xmlNodeSetBase(node, base);
1552 } else {
1553 /*
1554 * If the element already has an xml:base
1555 * set, then relativise it if necessary
1556 */
1557 xmlChar *xmlBase;
1558 xmlBase = xmlGetNsProp(node,
1559 BAD_CAST "base",
1560 XML_XML_NAMESPACE);
1561 if (xmlBase != NULL) {
1562 xmlChar *relBase;
1563 relBase = xmlBuildURI(xmlBase, base);
1564 if (relBase == NULL) { /* error */
1565 xmlXIncludeErr(ctxt,
1566 ref->elem,
1568 "trying to rebuild base from %s\n",
1569 xmlBase);
1570 } else {
1571 xmlNodeSetBase(node, relBase);
1572 xmlFree(relBase);
1573 }
1574 xmlFree(xmlBase);
1575 }
1576 }
1577 xmlFree(curBase);
1578 }
1579 }
1580 node = node->next;
1581 }
1582 xmlFree(base);
1583 }
1584 }
1585 ret = 0;
1586
1587error:
1588 xmlFree(URL);
1589 xmlFree(fragment);
1590 return(ret);
1591}
1592
1603static int
1604xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
1605 xmlXIncludeRefPtr ref) {
1606 xmlParserInputBufferPtr buf;
1607 xmlNodePtr node = NULL;
1608 xmlURIPtr uri = NULL;
1609 xmlChar *URL = NULL;
1610 int i;
1611 int ret = -1;
1612 xmlChar *encoding = NULL;
1614 xmlParserCtxtPtr pctxt = NULL;
1615 xmlParserInputPtr inputStream = NULL;
1616 int len;
1617 const xmlChar *content;
1618
1619
1620 /* Don't read from stdin. */
1621 if (xmlStrcmp(url, BAD_CAST "-") == 0)
1622 url = BAD_CAST "./-";
1623
1624 /*
1625 * Check the URL and remove any fragment identifier
1626 */
1627 uri = xmlParseURI((const char *)url);
1628 if (uri == NULL) {
1629 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI,
1630 "invalid value URI %s\n", url);
1631 goto error;
1632 }
1633 if (uri->fragment != NULL) {
1634 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_TEXT_FRAGMENT,
1635 "fragment identifier forbidden for text: %s\n",
1636 (const xmlChar *) uri->fragment);
1637 goto error;
1638 }
1639 URL = xmlSaveUri(uri);
1640 if (URL == NULL) {
1641 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI,
1642 "invalid value URI %s\n", url);
1643 goto error;
1644 }
1645
1646 /*
1647 * Handling of references to the local document are done
1648 * directly through ctxt->doc.
1649 */
1650 if (URL[0] == 0) {
1651 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_TEXT_DOCUMENT,
1652 "text serialization of document not available\n", NULL);
1653 goto error;
1654 }
1655
1656 /*
1657 * Prevent reloading the document twice.
1658 */
1659 for (i = 0; i < ctxt->txtNr; i++) {
1660 if (xmlStrEqual(URL, ctxt->txtTab[i].url)) {
1661 node = xmlNewDocText(ctxt->doc, ctxt->txtTab[i].text);
1662 goto loaded;
1663 }
1664 }
1665
1666 /*
1667 * Try to get the encoding if available
1668 */
1669 if (ref->elem != NULL) {
1670 encoding = xmlGetProp(ref->elem, XINCLUDE_PARSE_ENCODING);
1671 }
1672 if (encoding != NULL) {
1673 /*
1674 * TODO: we should not have to remap to the xmlCharEncoding
1675 * predefined set, a better interface than
1676 * xmlParserInputBufferCreateFilename should allow any
1677 * encoding supported by iconv
1678 */
1679 enc = xmlParseCharEncoding((const char *) encoding);
1680 if (enc == XML_CHAR_ENCODING_ERROR) {
1681 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_UNKNOWN_ENCODING,
1682 "encoding %s not supported\n", encoding);
1683 goto error;
1684 }
1685 }
1686
1687 /*
1688 * Load it.
1689 */
1690 pctxt = xmlNewParserCtxt();
1691 inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt);
1692 if(inputStream == NULL)
1693 goto error;
1694 buf = inputStream->buf;
1695 if (buf == NULL)
1696 goto error;
1697 if (buf->encoder)
1698 xmlCharEncCloseFunc(buf->encoder);
1699 buf->encoder = xmlGetCharEncodingHandler(enc);
1700 node = xmlNewDocText(ctxt->doc, NULL);
1701 if (node == NULL) {
1702 xmlXIncludeErrMemory(ctxt, ref->elem, NULL);
1703 goto error;
1704 }
1705
1706 /*
1707 * Scan all chars from the resource and add the to the node
1708 */
1709 while (xmlParserInputBufferRead(buf, 4096) > 0)
1710 ;
1711
1712 content = xmlBufContent(buf->buffer);
1713 len = xmlBufLength(buf->buffer);
1714 for (i = 0; i < len;) {
1715 int cur;
1716 int l;
1717
1718 l = len - i;
1719 cur = xmlGetUTF8Char(&content[i], &l);
1720 if ((cur < 0) || (!IS_CHAR(cur))) {
1721 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_INVALID_CHAR,
1722 "%s contains invalid char\n", URL);
1723 goto error;
1724 }
1725
1726 i += l;
1727 }
1728
1729 xmlNodeAddContentLen(node, content, len);
1730
1731 if (ctxt->txtNr >= ctxt->txtMax) {
1732 xmlXIncludeTxt *tmp;
1733#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1734 size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 1;
1735#else
1736 size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 8;
1737#endif
1738
1739 tmp = xmlRealloc(ctxt->txtTab, sizeof(xmlXIncludeTxt) * newSize);
1740 if (tmp == NULL) {
1741 xmlXIncludeErrMemory(ctxt, ref->elem,
1742 "growing XInclude text table");
1743 goto error;
1744 }
1745 ctxt->txtMax = newSize;
1746 ctxt->txtTab = tmp;
1747 }
1748 ctxt->txtTab[ctxt->txtNr].text = xmlStrdup(node->content);
1749 ctxt->txtTab[ctxt->txtNr].url = xmlStrdup(URL);
1750 ctxt->txtNr++;
1751
1752loaded:
1753 /*
1754 * Add the element as the replacement copy.
1755 */
1756 ref->inc = node;
1757 node = NULL;
1758 ret = 0;
1759
1760error:
1761 xmlFreeNode(node);
1762 xmlFreeInputStream(inputStream);
1763 xmlFreeParserCtxt(pctxt);
1764 xmlFree(encoding);
1765 xmlFreeURI(uri);
1766 xmlFree(URL);
1767 return(ret);
1768}
1769
1781static int
1782xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback,
1783 xmlXIncludeRefPtr ref) {
1784 int ret = 0;
1785 int oldNbErrors;
1786
1787 if ((fallback == NULL) || (fallback->type == XML_NAMESPACE_DECL) ||
1788 (ctxt == NULL))
1789 return(-1);
1790 if (fallback->children != NULL) {
1791 /*
1792 * It's possible that the fallback also has 'includes'
1793 * (Bug 129969), so we re-process the fallback just in case
1794 */
1795 oldNbErrors = ctxt->nbErrors;
1796 ref->inc = xmlXIncludeCopyNode(ctxt, fallback, 1);
1797 if (ctxt->nbErrors > oldNbErrors)
1798 ret = -1;
1799 else if (ref->inc == NULL)
1800 ref->emptyFb = 1;
1801 } else {
1802 ref->inc = NULL;
1803 ref->emptyFb = 1; /* flag empty callback */
1804 }
1805 ref->fallback = 1;
1806 return(ret);
1807}
1808
1809/************************************************************************
1810 * *
1811 * XInclude Processing *
1812 * *
1813 ************************************************************************/
1814
1825static xmlXIncludeRefPtr
1826xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
1827 xmlXIncludeRefPtr ref;
1828 int i;
1829
1830 if (ctxt->fatalErr)
1831 return(NULL);
1832 if (ctxt->depth >= XINCLUDE_MAX_DEPTH) {
1833 xmlXIncludeErr(ctxt, node, XML_XINCLUDE_RECURSION,
1834 "maximum recursion depth exceeded\n", NULL);
1835 ctxt->fatalErr = 1;
1836 return(NULL);
1837 }
1838
1839#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1840 /*
1841 * The XInclude engine offers no protection against exponential
1842 * expansion attacks similar to "billion laughs". Avoid timeouts by
1843 * limiting the total number of replacements when fuzzing.
1844 *
1845 * Unfortuately, a single XInclude can already result in quadratic
1846 * behavior:
1847 *
1848 * <doc xmlns:xi="http://www.w3.org/2001/XInclude">
1849 * <xi:include xpointer="xpointer(//e)"/>
1850 * <e>
1851 * <e>
1852 * <e>
1853 * <!-- more nested elements -->
1854 * </e>
1855 * </e>
1856 * </e>
1857 * </doc>
1858 */
1859 if (ctxt->incTotal >= 20)
1860 return(NULL);
1861 ctxt->incTotal++;
1862#endif
1863
1864 for (i = 0; i < ctxt->incNr; i++) {
1865 if (ctxt->incTab[i]->elem == node) {
1866 if (ctxt->incTab[i]->expanding) {
1867 xmlXIncludeErr(ctxt, node, XML_XINCLUDE_RECURSION,
1868 "inclusion loop detected\n", NULL);
1869 return(NULL);
1870 }
1871 return(ctxt->incTab[i]);
1872 }
1873 }
1874
1875 ref = xmlXIncludeAddNode(ctxt, node);
1876 if (ref == NULL)
1877 return(NULL);
1878 ref->expanding = 1;
1879 ctxt->depth++;
1880 xmlXIncludeLoadNode(ctxt, ref);
1881 ctxt->depth--;
1882 ref->expanding = 0;
1883
1884 return(ref);
1885}
1886
1896static int
1897xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
1898 xmlNodePtr cur;
1899 xmlChar *href;
1900 xmlChar *parse;
1901 xmlChar *base;
1902 xmlChar *oldBase;
1903 xmlChar *URI;
1904 int xml = 1; /* default Issue 64 */
1905 int ret;
1906
1907 if ((ctxt == NULL) || (ref == NULL))
1908 return(-1);
1909 cur = ref->elem;
1910 if (cur == NULL)
1911 return(-1);
1912
1913 /*
1914 * read the attributes
1915 */
1916 href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF);
1917 if (href == NULL) {
1918 href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */
1919 if (href == NULL)
1920 return(-1);
1921 }
1922 parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE);
1923 if (parse != NULL) {
1924 if (xmlStrEqual(parse, XINCLUDE_PARSE_XML))
1925 xml = 1;
1926 else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
1927 xml = 0;
1928 else {
1929 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE,
1930 "invalid value %s for 'parse'\n", parse);
1931 if (href != NULL)
1932 xmlFree(href);
1933 if (parse != NULL)
1934 xmlFree(parse);
1935 return(-1);
1936 }
1937 }
1938
1939 /*
1940 * compute the URI
1941 */
1942 base = xmlNodeGetBase(ctxt->doc, cur);
1943 if (base == NULL) {
1944 URI = xmlBuildURI(href, ctxt->doc->URL);
1945 } else {
1946 URI = xmlBuildURI(href, base);
1947 }
1948 if (URI == NULL) {
1949 xmlChar *escbase;
1950 xmlChar *eschref;
1951 /*
1952 * Some escaping may be needed
1953 */
1954 escbase = xmlURIEscape(base);
1955 eschref = xmlURIEscape(href);
1956 URI = xmlBuildURI(eschref, escbase);
1957 if (escbase != NULL)
1958 xmlFree(escbase);
1959 if (eschref != NULL)
1960 xmlFree(eschref);
1961 }
1962 if (URI == NULL) {
1963 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI,
1964 "failed build URL\n", NULL);
1965 if (parse != NULL)
1966 xmlFree(parse);
1967 if (href != NULL)
1968 xmlFree(href);
1969 if (base != NULL)
1970 xmlFree(base);
1971 return(-1);
1972 }
1973
1974 /*
1975 * Save the base for this include (saving the current one)
1976 */
1977 oldBase = ctxt->base;
1978 ctxt->base = base;
1979
1980 if (xml) {
1981 ret = xmlXIncludeLoadDoc(ctxt, URI, ref);
1982 /* xmlXIncludeGetFragment(ctxt, cur, URI); */
1983 } else {
1984 ret = xmlXIncludeLoadTxt(ctxt, URI, ref);
1985 }
1986
1987 /*
1988 * Restore the original base before checking for fallback
1989 */
1990 ctxt->base = oldBase;
1991
1992 if (ret < 0) {
1993 xmlNodePtr children;
1994
1995 /*
1996 * Time to try a fallback if available
1997 */
1998 children = cur->children;
1999 while (children != NULL) {
2000 if ((children->type == XML_ELEMENT_NODE) &&
2001 (children->ns != NULL) &&
2002 (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) &&
2003 ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
2004 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
2005 ret = xmlXIncludeLoadFallback(ctxt, children, ref);
2006 break;
2007 }
2008 children = children->next;
2009 }
2010 }
2011 if (ret < 0) {
2012 xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_NO_FALLBACK,
2013 "could not load %s, and no fallback was found\n",
2014 URI);
2015 }
2016
2017 /*
2018 * Cleanup
2019 */
2020 if (URI != NULL)
2021 xmlFree(URI);
2022 if (parse != NULL)
2023 xmlFree(parse);
2024 if (href != NULL)
2025 xmlFree(href);
2026 if (base != NULL)
2027 xmlFree(base);
2028 return(0);
2029}
2030
2040static int
2041xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
2042 xmlNodePtr cur, end, list, tmp;
2043
2044 if ((ctxt == NULL) || (ref == NULL))
2045 return(-1);
2046 cur = ref->elem;
2047 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2048 return(-1);
2049
2050 list = ref->inc;
2051 ref->inc = NULL;
2052 ref->emptyFb = 0;
2053
2054 /*
2055 * Check against the risk of generating a multi-rooted document
2056 */
2057 if ((cur->parent != NULL) &&
2058 (cur->parent->type != XML_ELEMENT_NODE)) {
2059 int nb_elem = 0;
2060
2061 tmp = list;
2062 while (tmp != NULL) {
2063 if (tmp->type == XML_ELEMENT_NODE)
2064 nb_elem++;
2065 tmp = tmp->next;
2066 }
2067 if (nb_elem > 1) {
2068 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_MULTIPLE_ROOT,
2069 "XInclude error: would result in multiple root nodes\n",
2070 NULL);
2071 xmlFreeNodeList(list);
2072 return(-1);
2073 }
2074 }
2075
2076 if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) {
2077 /*
2078 * Add the list of nodes
2079 */
2080 while (list != NULL) {
2081 end = list;
2082 list = list->next;
2083
2084 xmlAddPrevSibling(cur, end);
2085 }
2086 /*
2087 * FIXME: xmlUnlinkNode doesn't coalesce text nodes.
2088 */
2089 xmlUnlinkNode(cur);
2090 xmlFreeNode(cur);
2091 } else {
2092 xmlNodePtr child, next;
2093
2094 /*
2095 * Change the current node as an XInclude start one, and add an
2096 * XInclude end one
2097 */
2098 if (ref->fallback)
2099 xmlUnsetProp(cur, BAD_CAST "href");
2100 cur->type = XML_XINCLUDE_START;
2101 /* Remove fallback children */
2102 for (child = cur->children; child != NULL; child = next) {
2103 next = child->next;
2104 xmlUnlinkNode(child);
2105 xmlFreeNode(child);
2106 }
2107 end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
2108 if (end == NULL) {
2109 xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_BUILD_FAILED,
2110 "failed to build node\n", NULL);
2111 xmlFreeNodeList(list);
2112 return(-1);
2113 }
2114 end->type = XML_XINCLUDE_END;
2115 xmlAddNextSibling(cur, end);
2116
2117 /*
2118 * Add the list of nodes
2119 */
2120 while (list != NULL) {
2121 cur = list;
2122 list = list->next;
2123
2124 xmlAddPrevSibling(end, cur);
2125 }
2126 }
2127
2128
2129 return(0);
2130}
2131
2141static int
2142xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2143 if (node == NULL)
2144 return(0);
2145 if (node->type != XML_ELEMENT_NODE)
2146 return(0);
2147 if (node->ns == NULL)
2148 return(0);
2149 if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) ||
2150 (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) {
2151 if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) {
2152 if (ctxt->legacy == 0) {
2153#if 0 /* wait for the XML Core Working Group to get something stable ! */
2154 xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS,
2155 "Deprecated XInclude namespace found, use %s",
2156 XINCLUDE_NS);
2157#endif
2158 ctxt->legacy = 1;
2159 }
2160 }
2161 if (xmlStrEqual(node->name, XINCLUDE_NODE)) {
2162 xmlNodePtr child = node->children;
2163 int nb_fallback = 0;
2164
2165 while (child != NULL) {
2166 if ((child->type == XML_ELEMENT_NODE) &&
2167 (child->ns != NULL) &&
2168 ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) ||
2169 (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) {
2170 if (xmlStrEqual(child->name, XINCLUDE_NODE)) {
2171 xmlXIncludeErr(ctxt, node,
2173 "%s has an 'include' child\n",
2174 XINCLUDE_NODE);
2175 return(0);
2176 }
2177 if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) {
2178 nb_fallback++;
2179 }
2180 }
2181 child = child->next;
2182 }
2183 if (nb_fallback > 1) {
2184 xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE,
2185 "%s has multiple fallback children\n",
2186 XINCLUDE_NODE);
2187 return(0);
2188 }
2189 return(1);
2190 }
2191 if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) {
2192 if ((node->parent == NULL) ||
2193 (node->parent->type != XML_ELEMENT_NODE) ||
2194 (node->parent->ns == NULL) ||
2195 ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) &&
2196 (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) ||
2197 (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) {
2198 xmlXIncludeErr(ctxt, node,
2200 "%s is not the child of an 'include'\n",
2201 XINCLUDE_FALLBACK);
2202 }
2203 }
2204 }
2205 return(0);
2206}
2207
2218static int
2219xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) {
2220 xmlXIncludeRefPtr ref;
2221 xmlNodePtr cur;
2222 int ret = 0;
2223 int i, start;
2224
2225 if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2226 return(-1);
2227 if (ctxt == NULL)
2228 return(-1);
2229
2230 /*
2231 * First phase: lookup the elements in the document
2232 */
2233 start = ctxt->incNr;
2234 cur = tree;
2235 do {
2236 /* TODO: need to work on entities -> stack */
2237 if (xmlXIncludeTestNode(ctxt, cur) == 1) {
2238 ref = xmlXIncludeExpandNode(ctxt, cur);
2239 /*
2240 * Mark direct includes.
2241 */
2242 if (ref != NULL)
2243 ref->replace = 1;
2244 } else if ((cur->children != NULL) &&
2245 ((cur->type == XML_DOCUMENT_NODE) ||
2246 (cur->type == XML_ELEMENT_NODE))) {
2247 cur = cur->children;
2248 continue;
2249 }
2250 do {
2251 if (cur == tree)
2252 break;
2253 if (cur->next != NULL) {
2254 cur = cur->next;
2255 break;
2256 }
2257 cur = cur->parent;
2258 } while (cur != NULL);
2259 } while ((cur != NULL) && (cur != tree));
2260
2261 /*
2262 * Second phase: extend the original document infoset.
2263 */
2264 for (i = start; i < ctxt->incNr; i++) {
2265 if (ctxt->incTab[i]->replace != 0) {
2266 if ((ctxt->incTab[i]->inc != NULL) ||
2267 (ctxt->incTab[i]->emptyFb != 0)) { /* (empty fallback) */
2268 xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]);
2269 }
2270 ctxt->incTab[i]->replace = 0;
2271 } else {
2272 /*
2273 * Ignore includes which were added indirectly, for example
2274 * inside xi:fallback elements.
2275 */
2276 if (ctxt->incTab[i]->inc != NULL) {
2277 xmlFreeNodeList(ctxt->incTab[i]->inc);
2278 ctxt->incTab[i]->inc = NULL;
2279 }
2280 }
2281 ret++;
2282 }
2283
2284 if (ctxt->isStream) {
2285 /*
2286 * incTab references nodes which will eventually be deleted in
2287 * streaming mode. The table is only required for XPointer
2288 * expressions which aren't allowed in streaming mode.
2289 */
2290 for (i = 0;i < ctxt->incNr;i++) {
2291 xmlXIncludeFreeRef(ctxt->incTab[i]);
2292 }
2293 ctxt->incNr = 0;
2294 }
2295
2296 return(ret);
2297}
2298
2308int
2309xmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) {
2310 if (ctxt == NULL)
2311 return(-1);
2312 ctxt->parseFlags = flags;
2313 return(0);
2314}
2315
2325int
2326xmlXIncludeSetStreamingMode(xmlXIncludeCtxtPtr ctxt, int mode) {
2327 if (ctxt == NULL)
2328 return(-1);
2329 ctxt->isStream = !!mode;
2330 return(0);
2331}
2332
2346int
2347xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
2348 xmlXIncludeCtxtPtr ctxt;
2349 int ret = 0;
2350
2351 if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2352 (tree->doc == NULL))
2353 return(-1);
2354
2355 ctxt = xmlXIncludeNewContext(tree->doc);
2356 if (ctxt == NULL)
2357 return(-1);
2358 ctxt->_private = data;
2359 ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
2360 xmlXIncludeSetFlags(ctxt, flags);
2361 ret = xmlXIncludeDoProcess(ctxt, tree);
2362 if ((ret >= 0) && (ctxt->nbErrors > 0))
2363 ret = -1;
2364
2365 xmlXIncludeFreeContext(ctxt);
2366 return(ret);
2367}
2368
2381int
2382xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) {
2383 xmlNodePtr tree;
2384
2385 if (doc == NULL)
2386 return(-1);
2387 tree = xmlDocGetRootElement(doc);
2388 if (tree == NULL)
2389 return(-1);
2390 return(xmlXIncludeProcessTreeFlagsData(tree, flags, data));
2391}
2392
2403int
2404xmlXIncludeProcessFlags(xmlDocPtr doc, int flags) {
2405 return xmlXIncludeProcessFlagsData(doc, flags, NULL);
2406}
2407
2417int
2418xmlXIncludeProcess(xmlDocPtr doc) {
2419 return(xmlXIncludeProcessFlags(doc, 0));
2420}
2421
2432int
2433xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
2434 xmlXIncludeCtxtPtr ctxt;
2435 int ret = 0;
2436
2437 if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL) ||
2438 (tree->doc == NULL))
2439 return(-1);
2440 ctxt = xmlXIncludeNewContext(tree->doc);
2441 if (ctxt == NULL)
2442 return(-1);
2443 ctxt->base = xmlNodeGetBase(tree->doc, tree);
2444 xmlXIncludeSetFlags(ctxt, flags);
2445 ret = xmlXIncludeDoProcess(ctxt, tree);
2446 if ((ret >= 0) && (ctxt->nbErrors > 0))
2447 ret = -1;
2448
2449 xmlXIncludeFreeContext(ctxt);
2450 return(ret);
2451}
2452
2462int
2463xmlXIncludeProcessTree(xmlNodePtr tree) {
2464 return(xmlXIncludeProcessTreeFlags(tree, 0));
2465}
2466
2478int
2479xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
2480 int ret = 0;
2481
2482 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
2483 (node->doc == NULL) || (ctxt == NULL))
2484 return(-1);
2485 ret = xmlXIncludeDoProcess(ctxt, node);
2486 if ((ret >= 0) && (ctxt->nbErrors > 0))
2487 ret = -1;
2488 return(ret);
2489}
2490
2491#else /* !LIBXML_XINCLUDE_ENABLED */
2492#endif
#define msg(x)
Definition: auth_time.c:54
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
struct _tree tree
size_t xmlBufLength(const xmlBufPtr buf)
Definition: buf.c:551
xmlChar * xmlBufContent(const xmlBuf *buf)
Definition: buf.c:490
r l[0]
Definition: byte_order.h:168
Definition: list.h:37
struct list * next
Definition: list.h:38
Definition: _set.h:50
#define NULL
Definition: types.h:112
content
Definition: atl_ax.c:994
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
const WCHAR * text
Definition: package.c:1794
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
xmlCharEncodingHandlerPtr xmlGetCharEncodingHandler(xmlCharEncoding enc)
Definition: encoding.c:1547
xmlCharEncoding xmlParseCharEncoding(const char *name)
Definition: encoding.c:1148
xmlCharEncoding
Definition: encoding.h:65
@ XML_CHAR_ENCODING_ERROR
Definition: encoding.h:66
XMLPUBFUN int xmlCharEncCloseFunc(xmlCharEncodingHandler *handler)
#define local
Definition: zutil.h:30
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint level
Definition: gl.h:1546
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum GLint * range
Definition: glext.h:7539
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLsizei len
Definition: glext.h:6722
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
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
XMLPUBFUN xmlEntityPtr xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content)
XMLPUBFUN xmlEntityPtr xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
@ XML_EXTERNAL_GENERAL_PARSED_ENTITY
Definition: entities.h:28
@ XML_INTERNAL_PREDEFINED_ENTITY
Definition: entities.h:32
@ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
Definition: entities.h:29
@ XML_INTERNAL_GENERAL_ENTITY
Definition: entities.h:27
@ XML_INTERNAL_PARAMETER_ENTITY
Definition: entities.h:30
@ XML_EXTERNAL_PARAMETER_ENTITY
Definition: entities.h:31
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
BOOL legacy
Definition: mkisofs.c:131
static const WCHAR url[]
Definition: encode.c:1384
static UINT UINT last
Definition: font.c:45
static size_t elem
Definition: string.c:71
BOOL loaded
Definition: xmlview.c:54
const char * uri
Definition: sec_mgr.c:1588
static HWND child
Definition: cursoricon.c:298
BOOLEAN isStream(PUNICODE_STRING name)
#define IS_CHAR(c)
XMLPUBFUN void xmlFreeInputStream(xmlParserInputPtr input)
XMLPUBFUN int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
Definition: parser.c:1897
XML_HIDDEN int xmlXIncludeSetStreamingMode(xmlXIncludeCtxtPtr ctxt, int mode)
static unsigned __int64 next
Definition: rand_nt.c:6
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:38
#define list
Definition: rosglue.h:35
void xmlDictFree(xmlDictPtr dict)
Definition: dict.c:333
int xmlDictReference(xmlDictPtr dict)
Definition: dict.c:317
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data)
Definition: hash.c:898
XMLPUBFUN int xmlParseDocument(xmlParserCtxtPtr ctxt)
Definition: parser.c:11009
XMLPUBFUN int xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
Definition: parser.c:14698
XMLPUBFUN xmlParserInputPtr xmlLoadExternalEntity(const char *URL, const char *ID, xmlParserCtxtPtr ctxt)
XML_GLOBALS_PARSER XMLPUBFUN void xmlInitParser(void)
Definition: threads.c:569
#define XML_DETECT_IDS
Definition: parser.h:143
XMLPUBFUN void xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
@ XML_PARSE_NOBASEFIX
Definition: parser.h:1250
@ XML_PARSE_DTDLOAD
Definition: parser.h:1232
@ XML_PARSE_NOXINCNODE
Definition: parser.h:1245
@ XML_PARSE_NOENT
Definition: parser.h:1231
XMLPUBFUN xmlParserCtxtPtr xmlNewParserCtxt(void)
XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *nod, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg,...) LIBXML_ATTR_FORMAT(16
XML_HIDDEN xmlNodePtr xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent)
XML_HIDDEN xmlNodePtr xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, int extended)
#define memset(x, y, z)
Definition: compat.h:39
CardRegion * from
Definition: spigame.cpp:19
Definition: uri.h:34
Definition: cache.c:49
struct define * next
Definition: compiler.c:65
Definition: name.c:39
Definition: send.c:48
Definition: tools.h:99
Definition: dlist.c:348
void * next
Definition: dlist.c:360
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN xmlChar * xmlURIEscape(const xmlChar *str)
Definition: uri.c:1762
XMLPUBFUN void xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1396
XMLPUBFUN xmlChar * xmlBuildRelativeURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:2186
XMLPUBFUN xmlURIPtr xmlParseURI(const char *str)
Definition: uri.c:947
XMLPUBFUN xmlChar * xmlSaveUri(xmlURIPtr uri)
Definition: uri.c:1074
XMLPUBFUN char * xmlParserGetDirectory(const char *filename)
XMLPUBFUN int xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len)
@ XML_ERR_WARNING
Definition: xmlerror.h:26
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_FROM_XINCLUDE
Definition: xmlerror.h:48
@ XML_XINCLUDE_ENTITY_DEF_MISMATCH
Definition: xmlerror.h:478
@ XML_XINCLUDE_INCLUDE_IN_INCLUDE
Definition: xmlerror.h:490
@ XML_XINCLUDE_TEXT_FRAGMENT
Definition: xmlerror.h:482
@ XML_XINCLUDE_UNKNOWN_ENCODING
Definition: xmlerror.h:486
@ XML_XINCLUDE_XPTR_FAILED
Definition: xmlerror.h:488
@ XML_XINCLUDE_INVALID_CHAR
Definition: xmlerror.h:484
@ XML_XINCLUDE_XPTR_RESULT
Definition: xmlerror.h:489
@ XML_XINCLUDE_DEPRECATED_NS
Definition: xmlerror.h:493
@ XML_XINCLUDE_PARSE_VALUE
Definition: xmlerror.h:477
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_XINCLUDE_TEXT_DOCUMENT
Definition: xmlerror.h:483
@ XML_XINCLUDE_FALLBACKS_IN_INCLUDE
Definition: xmlerror.h:491
@ XML_XINCLUDE_MULTIPLE_ROOT
Definition: xmlerror.h:487
@ XML_XINCLUDE_NO_FALLBACK
Definition: xmlerror.h:480
@ XML_XINCLUDE_HREF_URI
Definition: xmlerror.h:481
@ XML_XINCLUDE_FRAGMENT_ID
Definition: xmlerror.h:494
@ XML_XINCLUDE_RECURSION
Definition: xmlerror.h:476
@ XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE
Definition: xmlerror.h:492
@ XML_XINCLUDE_BUILD_FAILED
Definition: xmlerror.h:485
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
XMLPUBFUN int XMLPUBFUN int XMLPUBFUN int xmlGetUTF8Char(const unsigned char *utf, int *len)
Definition: xmlstring.c:708
XMLPUBFUN int xmlStrcmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:135
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
XMLPUBFUN const xmlChar * xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:327
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:472
#define const
Definition: zconf.h:233