pocjenkixx 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 pocjenkixx might be problematic. Click here for more details.
- package/LICENSE +19 -0
- package/Makefile +18 -0
- package/README.md +52 -0
- package/binding.gyp +81 -0
- package/index.d.ts +273 -0
- package/index.js +45 -0
- package/lib/bindings.js +1 -0
- package/lib/document.js +122 -0
- package/lib/element.js +82 -0
- package/lib/sax_parser.js +38 -0
- package/package.json +70 -0
- package/src/html_document.cc +7 -0
- package/src/html_document.h +18 -0
- package/src/libxmljs.cc +252 -0
- package/src/libxmljs.h +53 -0
- package/src/xml_attribute.cc +173 -0
- package/src/xml_attribute.h +40 -0
- package/src/xml_comment.cc +117 -0
- package/src/xml_comment.h +30 -0
- package/src/xml_document.cc +810 -0
- package/src/xml_document.h +67 -0
- package/src/xml_element.cc +565 -0
- package/src/xml_element.h +61 -0
- package/src/xml_namespace.cc +158 -0
- package/src/xml_namespace.h +39 -0
- package/src/xml_node.cc +761 -0
- package/src/xml_node.h +73 -0
- package/src/xml_pi.cc +161 -0
- package/src/xml_pi.h +34 -0
- package/src/xml_sax_parser.cc +424 -0
- package/src/xml_sax_parser.h +73 -0
- package/src/xml_syntax_error.cc +66 -0
- package/src/xml_syntax_error.h +25 -0
- package/src/xml_text.cc +320 -0
- package/src/xml_text.h +48 -0
- package/src/xml_textwriter.cc +315 -0
- package/src/xml_textwriter.h +62 -0
- package/src/xml_xpath_context.cc +70 -0
- package/src/xml_xpath_context.h +23 -0
- package/vendor/libxml/Copyright +23 -0
- package/vendor/libxml/DOCBparser.c +305 -0
- package/vendor/libxml/HTMLparser.c +7287 -0
- package/vendor/libxml/HTMLtree.c +1200 -0
- package/vendor/libxml/Makefile +2983 -0
- package/vendor/libxml/SAX.c +180 -0
- package/vendor/libxml/SAX2.c +3036 -0
- package/vendor/libxml/buf.c +1351 -0
- package/vendor/libxml/buf.h +72 -0
- package/vendor/libxml/c14n.c +2234 -0
- package/vendor/libxml/catalog.c +3828 -0
- package/vendor/libxml/chvalid.c +336 -0
- package/vendor/libxml/config.h +294 -0
- package/vendor/libxml/config.h.gch +0 -0
- package/vendor/libxml/debugXML.c +3423 -0
- package/vendor/libxml/dict.c +1298 -0
- package/vendor/libxml/elfgcchack.h +17818 -0
- package/vendor/libxml/enc.h +32 -0
- package/vendor/libxml/encoding.c +3975 -0
- package/vendor/libxml/entities.c +1163 -0
- package/vendor/libxml/error.c +998 -0
- package/vendor/libxml/globals.c +1126 -0
- package/vendor/libxml/hash.c +1146 -0
- package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
- package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
- package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
- package/vendor/libxml/include/libxml/Makefile +725 -0
- package/vendor/libxml/include/libxml/Makefile.am +54 -0
- package/vendor/libxml/include/libxml/Makefile.in +725 -0
- package/vendor/libxml/include/libxml/SAX.h +173 -0
- package/vendor/libxml/include/libxml/SAX2.h +178 -0
- package/vendor/libxml/include/libxml/c14n.h +128 -0
- package/vendor/libxml/include/libxml/catalog.h +182 -0
- package/vendor/libxml/include/libxml/chvalid.h +230 -0
- package/vendor/libxml/include/libxml/debugXML.h +217 -0
- package/vendor/libxml/include/libxml/dict.h +79 -0
- package/vendor/libxml/include/libxml/encoding.h +245 -0
- package/vendor/libxml/include/libxml/entities.h +151 -0
- package/vendor/libxml/include/libxml/globals.h +508 -0
- package/vendor/libxml/include/libxml/hash.h +236 -0
- package/vendor/libxml/include/libxml/list.h +137 -0
- package/vendor/libxml/include/libxml/nanoftp.h +163 -0
- package/vendor/libxml/include/libxml/nanohttp.h +81 -0
- package/vendor/libxml/include/libxml/parser.h +1243 -0
- package/vendor/libxml/include/libxml/parserInternals.h +644 -0
- package/vendor/libxml/include/libxml/pattern.h +100 -0
- package/vendor/libxml/include/libxml/relaxng.h +217 -0
- package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
- package/vendor/libxml/include/libxml/schematron.h +142 -0
- package/vendor/libxml/include/libxml/threads.h +89 -0
- package/vendor/libxml/include/libxml/tree.h +1311 -0
- package/vendor/libxml/include/libxml/uri.h +94 -0
- package/vendor/libxml/include/libxml/valid.h +458 -0
- package/vendor/libxml/include/libxml/xinclude.h +129 -0
- package/vendor/libxml/include/libxml/xlink.h +189 -0
- package/vendor/libxml/include/libxml/xmlIO.h +368 -0
- package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
- package/vendor/libxml/include/libxml/xmlerror.h +945 -0
- package/vendor/libxml/include/libxml/xmlexports.h +77 -0
- package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
- package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
- package/vendor/libxml/include/libxml/xmlreader.h +428 -0
- package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
- package/vendor/libxml/include/libxml/xmlsave.h +88 -0
- package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
- package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
- package/vendor/libxml/include/libxml/xmlstring.h +140 -0
- package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
- package/vendor/libxml/include/libxml/xmlversion.h +484 -0
- package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
- package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
- package/vendor/libxml/include/libxml/xpath.h +564 -0
- package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
- package/vendor/libxml/include/libxml/xpointer.h +114 -0
- package/vendor/libxml/include/win32config.h +122 -0
- package/vendor/libxml/include/wsockcompat.h +54 -0
- package/vendor/libxml/legacy.c +1343 -0
- package/vendor/libxml/libxml.h +134 -0
- package/vendor/libxml/list.c +779 -0
- package/vendor/libxml/nanoftp.c +2118 -0
- package/vendor/libxml/nanohttp.c +1899 -0
- package/vendor/libxml/parser.c +15553 -0
- package/vendor/libxml/parserInternals.c +2164 -0
- package/vendor/libxml/pattern.c +2621 -0
- package/vendor/libxml/relaxng.c +11101 -0
- package/vendor/libxml/rngparser.c +1595 -0
- package/vendor/libxml/runsuite.c +1157 -0
- package/vendor/libxml/save.h +36 -0
- package/vendor/libxml/schematron.c +1787 -0
- package/vendor/libxml/threads.c +1049 -0
- package/vendor/libxml/timsort.h +601 -0
- package/vendor/libxml/tree.c +10183 -0
- package/vendor/libxml/trio.c +6895 -0
- package/vendor/libxml/trio.h +230 -0
- package/vendor/libxml/triodef.h +228 -0
- package/vendor/libxml/trionan.c +914 -0
- package/vendor/libxml/trionan.h +84 -0
- package/vendor/libxml/triop.h +150 -0
- package/vendor/libxml/triostr.c +2112 -0
- package/vendor/libxml/triostr.h +144 -0
- package/vendor/libxml/uri.c +2561 -0
- package/vendor/libxml/valid.c +7138 -0
- package/vendor/libxml/xinclude.c +2657 -0
- package/vendor/libxml/xlink.c +183 -0
- package/vendor/libxml/xmlIO.c +4135 -0
- package/vendor/libxml/xmlcatalog.c +624 -0
- package/vendor/libxml/xmllint.c +3796 -0
- package/vendor/libxml/xmlmemory.c +1163 -0
- package/vendor/libxml/xmlmodule.c +468 -0
- package/vendor/libxml/xmlreader.c +6033 -0
- package/vendor/libxml/xmlregexp.c +8271 -0
- package/vendor/libxml/xmlsave.c +2735 -0
- package/vendor/libxml/xmlschemas.c +29173 -0
- package/vendor/libxml/xmlschemastypes.c +6276 -0
- package/vendor/libxml/xmlstring.c +1050 -0
- package/vendor/libxml/xmlunicode.c +3179 -0
- package/vendor/libxml/xmlwriter.c +4738 -0
- package/vendor/libxml/xpath.c +14734 -0
- package/vendor/libxml/xpointer.c +2969 -0
- package/vendor/libxml/xzlib.c +815 -0
- 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"
|