pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

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