@helm2/poc_jenki_rce 0.0.1

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

Potentially problematic release.


This version of @helm2/poc_jenki_rce 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 +118 -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"