[DINPUT]
[reactos.git] / reactos / dll / 3rdparty / libxslt / documents.c
1 /*
2 * documents.c: Implementation of the documents handling
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9 #include "precomp.h"
10
11 #ifdef LIBXML_XINCLUDE_ENABLED
12 #include <libxml/xinclude.h>
13 #endif
14
15 #define WITH_XSLT_DEBUG_DOCUMENTS
16
17 #ifdef WITH_XSLT_DEBUG
18 #define WITH_XSLT_DEBUG_DOCUMENTS
19 #endif
20
21 /************************************************************************
22 * *
23 * Hooks for the document loader *
24 * *
25 ************************************************************************/
26
27 /**
28 * xsltDocDefaultLoaderFunc:
29 * @URI: the URI of the document to load
30 * @dict: the dictionary to use when parsing that document
31 * @options: parsing options, a set of xmlParserOption
32 * @ctxt: the context, either a stylesheet or a transformation context
33 * @type: the xsltLoadType indicating the kind of loading required
34 *
35 * Default function to load document not provided by the compilation or
36 * transformation API themselve, for example when an xsl:import,
37 * xsl:include is found at compilation time or when a document()
38 * call is made at runtime.
39 *
40 * Returns the pointer to the document (which will be modified and
41 * freed by the engine later), or NULL in case of error.
42 */
43 static xmlDocPtr
44 xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
45 void *ctxt ATTRIBUTE_UNUSED,
46 xsltLoadType type ATTRIBUTE_UNUSED)
47 {
48 xmlParserCtxtPtr pctxt;
49 xmlParserInputPtr inputStream;
50 xmlDocPtr doc;
51
52 pctxt = xmlNewParserCtxt();
53 if (pctxt == NULL)
54 return(NULL);
55 if ((dict != NULL) && (pctxt->dict != NULL)) {
56 xmlDictFree(pctxt->dict);
57 pctxt->dict = NULL;
58 }
59 if (dict != NULL) {
60 pctxt->dict = dict;
61 xmlDictReference(pctxt->dict);
62 #ifdef WITH_XSLT_DEBUG
63 xsltGenericDebug(xsltGenericDebugContext,
64 "Reusing dictionary for document\n");
65 #endif
66 }
67 xmlCtxtUseOptions(pctxt, options);
68 inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
69 if (inputStream == NULL) {
70 xmlFreeParserCtxt(pctxt);
71 return(NULL);
72 }
73 inputPush(pctxt, inputStream);
74 if (pctxt->directory == NULL)
75 pctxt->directory = xmlParserGetDirectory((const char *) URI);
76
77 xmlParseDocument(pctxt);
78
79 if (pctxt->wellFormed) {
80 doc = pctxt->myDoc;
81 }
82 else {
83 doc = NULL;
84 xmlFreeDoc(pctxt->myDoc);
85 pctxt->myDoc = NULL;
86 }
87 xmlFreeParserCtxt(pctxt);
88
89 return(doc);
90 }
91
92
93 xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
94
95 /**
96 * xsltSetLoaderFunc:
97 * @f: the new function to handle document loading.
98 *
99 * Set the new function to load document, if NULL it resets it to the
100 * default function.
101 */
102
103 void
104 xsltSetLoaderFunc(xsltDocLoaderFunc f) {
105 if (f == NULL)
106 xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
107 else
108 xsltDocDefaultLoader = f;
109 }
110
111 /************************************************************************
112 * *
113 * Module interfaces *
114 * *
115 ************************************************************************/
116
117 /**
118 * xsltNewDocument:
119 * @ctxt: an XSLT transformation context (or NULL)
120 * @doc: a parsed XML document
121 *
122 * Register a new document, apply key computations
123 *
124 * Returns a handler to the document
125 */
126 xsltDocumentPtr
127 xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
128 xsltDocumentPtr cur;
129
130 cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
131 if (cur == NULL) {
132 xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
133 "xsltNewDocument : malloc failed\n");
134 return(NULL);
135 }
136 memset(cur, 0, sizeof(xsltDocument));
137 cur->doc = doc;
138 if (ctxt != NULL) {
139 if (! XSLT_IS_RES_TREE_FRAG(doc)) {
140 cur->next = ctxt->docList;
141 ctxt->docList = cur;
142 }
143 /*
144 * A key with a specific name for a specific document
145 * will only be computed if there's a call to the key()
146 * function using that specific name for that specific
147 * document. I.e. computation of keys will be done in
148 * xsltGetKey() (keys.c) on an on-demand basis.
149 *
150 * xsltInitCtxtKeys(ctxt, cur); not called here anymore
151 */
152 }
153 return(cur);
154 }
155
156 /**
157 * xsltNewStyleDocument:
158 * @style: an XSLT style sheet
159 * @doc: a parsed XML document
160 *
161 * Register a new document, apply key computations
162 *
163 * Returns a handler to the document
164 */
165 xsltDocumentPtr
166 xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
167 xsltDocumentPtr cur;
168
169 cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
170 if (cur == NULL) {
171 xsltTransformError(NULL, style, (xmlNodePtr) doc,
172 "xsltNewStyleDocument : malloc failed\n");
173 return(NULL);
174 }
175 memset(cur, 0, sizeof(xsltDocument));
176 cur->doc = doc;
177 if (style != NULL) {
178 cur->next = style->docList;
179 style->docList = cur;
180 }
181 return(cur);
182 }
183
184 /**
185 * xsltFreeStyleDocuments:
186 * @style: an XSLT stylesheet (representing a stylesheet-level)
187 *
188 * Frees the node-trees (and xsltDocument structures) of all
189 * stylesheet-modules of the stylesheet-level represented by
190 * the given @style.
191 */
192 void
193 xsltFreeStyleDocuments(xsltStylesheetPtr style) {
194 xsltDocumentPtr doc, cur;
195 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
196 xsltNsMapPtr nsMap;
197 #endif
198
199 if (style == NULL)
200 return;
201
202 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
203 if (XSLT_HAS_INTERNAL_NSMAP(style))
204 nsMap = XSLT_GET_INTERNAL_NSMAP(style);
205 else
206 nsMap = NULL;
207 #endif
208
209 cur = style->docList;
210 while (cur != NULL) {
211 doc = cur;
212 cur = cur->next;
213 #ifdef XSLT_REFACTORED_XSLT_NSCOMP
214 /*
215 * Restore all changed namespace URIs of ns-decls.
216 */
217 if (nsMap)
218 xsltRestoreDocumentNamespaces(nsMap, doc->doc);
219 #endif
220 xsltFreeDocumentKeys(doc);
221 if (!doc->main)
222 xmlFreeDoc(doc->doc);
223 xmlFree(doc);
224 }
225 }
226
227 /**
228 * xsltFreeDocuments:
229 * @ctxt: an XSLT transformation context
230 *
231 * Free up all the space used by the loaded documents
232 */
233 void
234 xsltFreeDocuments(xsltTransformContextPtr ctxt) {
235 xsltDocumentPtr doc, cur;
236
237 cur = ctxt->docList;
238 while (cur != NULL) {
239 doc = cur;
240 cur = cur->next;
241 xsltFreeDocumentKeys(doc);
242 if (!doc->main)
243 xmlFreeDoc(doc->doc);
244 xmlFree(doc);
245 }
246 cur = ctxt->styleList;
247 while (cur != NULL) {
248 doc = cur;
249 cur = cur->next;
250 xsltFreeDocumentKeys(doc);
251 if (!doc->main)
252 xmlFreeDoc(doc->doc);
253 xmlFree(doc);
254 }
255 }
256
257 /**
258 * xsltLoadDocument:
259 * @ctxt: an XSLT transformation context
260 * @URI: the computed URI of the document
261 *
262 * Try to load a document (not a stylesheet)
263 * within the XSLT transformation context
264 *
265 * Returns the new xsltDocumentPtr or NULL in case of error
266 */
267 xsltDocumentPtr
268 xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
269 xsltDocumentPtr ret;
270 xmlDocPtr doc;
271
272 if ((ctxt == NULL) || (URI == NULL))
273 return(NULL);
274
275 /*
276 * Security framework check
277 */
278 if (ctxt->sec != NULL) {
279 int res;
280
281 res = xsltCheckRead(ctxt->sec, ctxt, URI);
282 if (res == 0) {
283 xsltTransformError(ctxt, NULL, NULL,
284 "xsltLoadDocument: read rights for %s denied\n",
285 URI);
286 return(NULL);
287 }
288 }
289
290 /*
291 * Walk the context list to find the document if preparsed
292 */
293 ret = ctxt->docList;
294 while (ret != NULL) {
295 if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
296 (xmlStrEqual(ret->doc->URL, URI)))
297 return(ret);
298 ret = ret->next;
299 }
300
301 doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
302 (void *) ctxt, XSLT_LOAD_DOCUMENT);
303
304 if (doc == NULL)
305 return(NULL);
306
307 if (ctxt->xinclude != 0) {
308 #ifdef LIBXML_XINCLUDE_ENABLED
309 #if LIBXML_VERSION >= 20603
310 xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
311 #else
312 xmlXIncludeProcess(doc);
313 #endif
314 #else
315 xsltTransformError(ctxt, NULL, NULL,
316 "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
317 URI);
318 #endif
319 }
320 /*
321 * Apply white-space stripping if asked for
322 */
323 if (xsltNeedElemSpaceHandling(ctxt))
324 xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
325 if (ctxt->debugStatus == XSLT_DEBUG_NONE)
326 xmlXPathOrderDocElems(doc);
327
328 ret = xsltNewDocument(ctxt, doc);
329 return(ret);
330 }
331
332 /**
333 * xsltLoadStyleDocument:
334 * @style: an XSLT style sheet
335 * @URI: the computed URI of the document
336 *
337 * Try to load a stylesheet document within the XSLT transformation context
338 *
339 * Returns the new xsltDocumentPtr or NULL in case of error
340 */
341 xsltDocumentPtr
342 xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
343 xsltDocumentPtr ret;
344 xmlDocPtr doc;
345 xsltSecurityPrefsPtr sec;
346
347 if ((style == NULL) || (URI == NULL))
348 return(NULL);
349
350 /*
351 * Security framework check
352 */
353 sec = xsltGetDefaultSecurityPrefs();
354 if (sec != NULL) {
355 int res;
356
357 res = xsltCheckRead(sec, NULL, URI);
358 if (res == 0) {
359 xsltTransformError(NULL, NULL, NULL,
360 "xsltLoadStyleDocument: read rights for %s denied\n",
361 URI);
362 return(NULL);
363 }
364 }
365
366 /*
367 * Walk the context list to find the document if preparsed
368 */
369 ret = style->docList;
370 while (ret != NULL) {
371 if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
372 (xmlStrEqual(ret->doc->URL, URI)))
373 return(ret);
374 ret = ret->next;
375 }
376
377 doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
378 (void *) style, XSLT_LOAD_STYLESHEET);
379 if (doc == NULL)
380 return(NULL);
381
382 ret = xsltNewStyleDocument(style, doc);
383 return(ret);
384 }
385
386 /**
387 * xsltFindDocument:
388 * @ctxt: an XSLT transformation context
389 * @doc: a parsed XML document
390 *
391 * Try to find a document within the XSLT transformation context.
392 * This will not find document infos for temporary
393 * Result Tree Fragments.
394 *
395 * Returns the desired xsltDocumentPtr or NULL in case of error
396 */
397 xsltDocumentPtr
398 xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
399 xsltDocumentPtr ret;
400
401 if ((ctxt == NULL) || (doc == NULL))
402 return(NULL);
403
404 /*
405 * Walk the context list to find the document
406 */
407 ret = ctxt->docList;
408 while (ret != NULL) {
409 if (ret->doc == doc)
410 return(ret);
411 ret = ret->next;
412 }
413 if (doc == ctxt->style->doc)
414 return(ctxt->document);
415 return(NULL);
416 }
417