1 /*
2 * imports.c: Implementation of the XSLT imports
3 *
4 * Reference:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 *
7 * See Copyright for the status of this software.
8 *
9 * daniel@veillard.com
10 */
11
12 #include "precomp.h"
13
14 /************************************************************************
15 * *
16 * Module interfaces *
17 * *
18 ************************************************************************/
19 /**
20 * xsltFixImportedCompSteps:
21 * @master: the "master" stylesheet
22 * @style: the stylesheet being imported by the master
23 *
24 * normalize the comp steps for the stylesheet being imported
25 * by the master, together with any imports within that.
26 *
27 */
xsltFixImportedCompSteps(xsltStylesheetPtr master,xsltStylesheetPtr style)28 static void xsltFixImportedCompSteps(xsltStylesheetPtr master,
29 xsltStylesheetPtr style) {
30 xsltStylesheetPtr res;
31 xmlHashScan(style->templatesHash, xsltNormalizeCompSteps, master);
32 master->extrasNr += style->extrasNr;
33 for (res = style->imports; res != NULL; res = res->next) {
34 xsltFixImportedCompSteps(master, res);
35 }
36 }
37
38 /**
39 * xsltParseStylesheetImport:
40 * @style: the XSLT stylesheet
41 * @cur: the import element
42 *
43 * parse an XSLT stylesheet import element
44 *
45 * Returns 0 in case of success -1 in case of failure.
46 */
47
48 int
xsltParseStylesheetImport(xsltStylesheetPtr style,xmlNodePtr cur)49 xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
50 int ret = -1;
51 xmlDocPtr import = NULL;
52 xmlChar *base = NULL;
53 xmlChar *uriRef = NULL;
54 xmlChar *URI = NULL;
55 xsltStylesheetPtr res;
56 xsltSecurityPrefsPtr sec;
57
58 if ((cur == NULL) || (style == NULL))
59 return (ret);
60
61 uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
62 if (uriRef == NULL) {
63 xsltTransformError(NULL, style, cur,
64 "xsl:import : missing href attribute\n");
65 goto error;
66 }
67
68 base = xmlNodeGetBase(style->doc, cur);
69 URI = xmlBuildURI(uriRef, base);
70 if (URI == NULL) {
71 xsltTransformError(NULL, style, cur,
72 "xsl:import : invalid URI reference %s\n", uriRef);
73 goto error;
74 }
75
76 res = style;
77 while (res != NULL) {
78 if (res->doc == NULL)
79 break;
80 if (xmlStrEqual(res->doc->URL, URI)) {
81 xsltTransformError(NULL, style, cur,
82 "xsl:import : recursion detected on imported URL %s\n", URI);
83 goto error;
84 }
85 res = res->parent;
86 }
87
88 /*
89 * Security framework check
90 */
91 sec = xsltGetDefaultSecurityPrefs();
92 if (sec != NULL) {
93 int secres;
94
95 secres = xsltCheckRead(sec, NULL, URI);
96 if (secres <= 0) {
97 if (secres == 0)
98 xsltTransformError(NULL, NULL, NULL,
99 "xsl:import: read rights for %s denied\n",
100 URI);
101 goto error;
102 }
103 }
104
105 import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
106 (void *) style, XSLT_LOAD_STYLESHEET);
107 if (import == NULL) {
108 xsltTransformError(NULL, style, cur,
109 "xsl:import : unable to load %s\n", URI);
110 goto error;
111 }
112
113 res = xsltParseStylesheetImportedDoc(import, style);
114 if (res != NULL) {
115 res->next = style->imports;
116 style->imports = res;
117 if (style->parent == NULL) {
118 xsltFixImportedCompSteps(style, res);
119 }
120 ret = 0;
121 } else {
122 xmlFreeDoc(import);
123 }
124
125 error:
126 if (uriRef != NULL)
127 xmlFree(uriRef);
128 if (base != NULL)
129 xmlFree(base);
130 if (URI != NULL)
131 xmlFree(URI);
132
133 return (ret);
134 }
135
136 /**
137 * xsltParseStylesheetInclude:
138 * @style: the XSLT stylesheet
139 * @cur: the include node
140 *
141 * parse an XSLT stylesheet include element
142 *
143 * Returns 0 in case of success -1 in case of failure
144 */
145
146 int
xsltParseStylesheetInclude(xsltStylesheetPtr style,xmlNodePtr cur)147 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
148 int ret = -1;
149 xmlDocPtr oldDoc;
150 xmlChar *base = NULL;
151 xmlChar *uriRef = NULL;
152 xmlChar *URI = NULL;
153 xsltStylesheetPtr result;
154 xsltDocumentPtr include;
155 xsltDocumentPtr docptr;
156 int oldNopreproc;
157
158 if ((cur == NULL) || (style == NULL))
159 return (ret);
160
161 uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
162 if (uriRef == NULL) {
163 xsltTransformError(NULL, style, cur,
164 "xsl:include : missing href attribute\n");
165 goto error;
166 }
167
168 base = xmlNodeGetBase(style->doc, cur);
169 URI = xmlBuildURI(uriRef, base);
170 if (URI == NULL) {
171 xsltTransformError(NULL, style, cur,
172 "xsl:include : invalid URI reference %s\n", uriRef);
173 goto error;
174 }
175
176 /*
177 * in order to detect recursion, we check all previously included
178 * stylesheets.
179 */
180 docptr = style->includes;
181 while (docptr != NULL) {
182 if (xmlStrEqual(docptr->doc->URL, URI)) {
183 xsltTransformError(NULL, style, cur,
184 "xsl:include : recursion detected on included URL %s\n", URI);
185 goto error;
186 }
187 docptr = docptr->includes;
188 }
189
190 include = xsltLoadStyleDocument(style, URI);
191 if (include == NULL) {
192 xsltTransformError(NULL, style, cur,
193 "xsl:include : unable to load %s\n", URI);
194 goto error;
195 }
196 #ifdef XSLT_REFACTORED
197 if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
198 ((xsltStyleItemIncludePtr) cur->psvi)->include = include;
199 } else {
200 xsltTransformError(NULL, style, cur,
201 "Internal error: (xsltParseStylesheetInclude) "
202 "The xsl:include element was not compiled.\n", URI);
203 style->errors++;
204 }
205 #endif
206 oldDoc = style->doc;
207 style->doc = include->doc;
208 /* chain to stylesheet for recursion checking */
209 include->includes = style->includes;
210 style->includes = include;
211 oldNopreproc = style->nopreproc;
212 style->nopreproc = include->preproc;
213 /*
214 * TODO: This will change some values of the
215 * including stylesheet with every included module
216 * (e.g. excluded-result-prefixes)
217 * We need to strictly seperate such stylesheet-owned values.
218 */
219 result = xsltParseStylesheetProcess(style, include->doc);
220 style->nopreproc = oldNopreproc;
221 include->preproc = 1;
222 style->includes = include->includes;
223 style->doc = oldDoc;
224 if (result == NULL) {
225 ret = -1;
226 goto error;
227 }
228 ret = 0;
229
230 error:
231 if (uriRef != NULL)
232 xmlFree(uriRef);
233 if (base != NULL)
234 xmlFree(base);
235 if (URI != NULL)
236 xmlFree(URI);
237
238 return (ret);
239 }
240
241 /**
242 * xsltNextImport:
243 * @cur: the current XSLT stylesheet
244 *
245 * Find the next stylesheet in import precedence.
246 *
247 * Returns the next stylesheet or NULL if it was the last one
248 */
249
250 xsltStylesheetPtr
xsltNextImport(xsltStylesheetPtr cur)251 xsltNextImport(xsltStylesheetPtr cur) {
252 if (cur == NULL)
253 return(NULL);
254 if (cur->imports != NULL)
255 return(cur->imports);
256 if (cur->next != NULL)
257 return(cur->next) ;
258 do {
259 cur = cur->parent;
260 if (cur == NULL) break;
261 if (cur->next != NULL) return(cur->next);
262 } while (cur != NULL);
263 return(cur);
264 }
265
266 /**
267 * xsltNeedElemSpaceHandling:
268 * @ctxt: an XSLT transformation context
269 *
270 * Checks whether that stylesheet requires white-space stripping
271 *
272 * Returns 1 if space should be stripped, 0 if not
273 */
274
275 int
xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt)276 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
277 xsltStylesheetPtr style;
278
279 if (ctxt == NULL)
280 return(0);
281 style = ctxt->style;
282 while (style != NULL) {
283 if (style->stripSpaces != NULL)
284 return(1);
285 style = xsltNextImport(style);
286 }
287 return(0);
288 }
289
290 /**
291 * xsltFindElemSpaceHandling:
292 * @ctxt: an XSLT transformation context
293 * @node: an XML node
294 *
295 * Find strip-space or preserve-space information for an element
296 * respect the import precedence or the wildcards
297 *
298 * Returns 1 if space should be stripped, 0 if not, and 2 if everything
299 * should be CDTATA wrapped.
300 */
301
302 int
xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt,xmlNodePtr node)303 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
304 xsltStylesheetPtr style;
305 const xmlChar *val;
306
307 if ((ctxt == NULL) || (node == NULL))
308 return(0);
309 style = ctxt->style;
310 while (style != NULL) {
311 if (node->ns != NULL) {
312 val = (const xmlChar *)
313 xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
314 if (val == NULL) {
315 val = (const xmlChar *)
316 xmlHashLookup2(style->stripSpaces, BAD_CAST "*",
317 node->ns->href);
318 }
319 } else {
320 val = (const xmlChar *)
321 xmlHashLookup2(style->stripSpaces, node->name, NULL);
322 }
323 if (val != NULL) {
324 if (xmlStrEqual(val, (xmlChar *) "strip"))
325 return(1);
326 if (xmlStrEqual(val, (xmlChar *) "preserve"))
327 return(0);
328 }
329 if (style->stripAll == 1)
330 return(1);
331 if (style->stripAll == -1)
332 return(0);
333
334 style = xsltNextImport(style);
335 }
336 return(0);
337 }
338
339 /**
340 * xsltFindTemplate:
341 * @ctxt: an XSLT transformation context
342 * @name: the template name
343 * @nameURI: the template name URI
344 *
345 * Finds the named template, apply import precedence rule.
346 * REVISIT TODO: We'll change the nameURI fields of
347 * templates to be in the string dict, so if the
348 * specified @nameURI is in the same dict, then use pointer
349 * comparison. Check if this can be done in a sane way.
350 * Maybe this function is not needed internally at
351 * transformation-time if we hard-wire the called templates
352 * to the caller.
353 *
354 * Returns the xsltTemplatePtr or NULL if not found
355 */
356 xsltTemplatePtr
xsltFindTemplate(xsltTransformContextPtr ctxt,const xmlChar * name,const xmlChar * nameURI)357 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
358 const xmlChar *nameURI) {
359 xsltTemplatePtr cur;
360 xsltStylesheetPtr style;
361
362 if ((ctxt == NULL) || (name == NULL))
363 return(NULL);
364 style = ctxt->style;
365 while (style != NULL) {
366 if (style->namedTemplates != NULL) {
367 cur = (xsltTemplatePtr)
368 xmlHashLookup2(style->namedTemplates, name, nameURI);
369 if (cur != NULL)
370 return(cur);
371 }
372
373 style = xsltNextImport(style);
374 }
375 return(NULL);
376 }
377
378