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