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