[LOCALSPL_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / 3rdparty / libxslt / imports.c
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 */
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
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 xsltTransformError(NULL, NULL, NULL,
98 "xsl:import: read rights for %s denied\n",
99 URI);
100 goto error;
101 }
102 }
103
104 import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
105 (void *) style, XSLT_LOAD_STYLESHEET);
106 if (import == NULL) {
107 xsltTransformError(NULL, style, cur,
108 "xsl:import : unable to load %s\n", URI);
109 goto error;
110 }
111
112 res = xsltParseStylesheetImportedDoc(import, style);
113 if (res != NULL) {
114 res->next = style->imports;
115 style->imports = res;
116 if (style->parent == NULL) {
117 xsltFixImportedCompSteps(style, res);
118 }
119 ret = 0;
120 } else {
121 xmlFreeDoc(import);
122 }
123
124 error:
125 if (uriRef != NULL)
126 xmlFree(uriRef);
127 if (base != NULL)
128 xmlFree(base);
129 if (URI != NULL)
130 xmlFree(URI);
131
132 return (ret);
133 }
134
135 /**
136 * xsltParseStylesheetInclude:
137 * @style: the XSLT stylesheet
138 * @cur: the include node
139 *
140 * parse an XSLT stylesheet include element
141 *
142 * Returns 0 in case of success -1 in case of failure
143 */
144
145 int
146 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
147 int ret = -1;
148 xmlDocPtr oldDoc;
149 xmlChar *base = NULL;
150 xmlChar *uriRef = NULL;
151 xmlChar *URI = NULL;
152 xsltStylesheetPtr result;
153 xsltDocumentPtr include;
154 xsltDocumentPtr docptr;
155 int oldNopreproc;
156
157 if ((cur == NULL) || (style == NULL))
158 return (ret);
159
160 uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
161 if (uriRef == NULL) {
162 xsltTransformError(NULL, style, cur,
163 "xsl:include : missing href attribute\n");
164 goto error;
165 }
166
167 base = xmlNodeGetBase(style->doc, cur);
168 URI = xmlBuildURI(uriRef, base);
169 if (URI == NULL) {
170 xsltTransformError(NULL, style, cur,
171 "xsl:include : invalid URI reference %s\n", uriRef);
172 goto error;
173 }
174
175 /*
176 * in order to detect recursion, we check all previously included
177 * stylesheets.
178 */
179 docptr = style->includes;
180 while (docptr != NULL) {
181 if (xmlStrEqual(docptr->doc->URL, URI)) {
182 xsltTransformError(NULL, style, cur,
183 "xsl:include : recursion detected on included URL %s\n", URI);
184 goto error;
185 }
186 docptr = docptr->includes;
187 }
188
189 include = xsltLoadStyleDocument(style, URI);
190 if (include == NULL) {
191 xsltTransformError(NULL, style, cur,
192 "xsl:include : unable to load %s\n", URI);
193 goto error;
194 }
195 #ifdef XSLT_REFACTORED
196 if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
197 ((xsltStyleItemIncludePtr) cur->psvi)->include = include;
198 } else {
199 xsltTransformError(NULL, style, cur,
200 "Internal error: (xsltParseStylesheetInclude) "
201 "The xsl:include element was not compiled.\n", URI);
202 style->errors++;
203 }
204 #endif
205 oldDoc = style->doc;
206 style->doc = include->doc;
207 /* chain to stylesheet for recursion checking */
208 include->includes = style->includes;
209 style->includes = include;
210 oldNopreproc = style->nopreproc;
211 style->nopreproc = include->preproc;
212 /*
213 * TODO: This will change some values of the
214 * including stylesheet with every included module
215 * (e.g. excluded-result-prefixes)
216 * We need to strictly seperate such stylesheet-owned values.
217 */
218 result = xsltParseStylesheetProcess(style, include->doc);
219 style->nopreproc = oldNopreproc;
220 include->preproc = 1;
221 style->includes = include->includes;
222 style->doc = oldDoc;
223 if (result == NULL) {
224 ret = -1;
225 goto error;
226 }
227 ret = 0;
228
229 error:
230 if (uriRef != NULL)
231 xmlFree(uriRef);
232 if (base != NULL)
233 xmlFree(base);
234 if (URI != NULL)
235 xmlFree(URI);
236
237 return (ret);
238 }
239
240 /**
241 * xsltNextImport:
242 * @cur: the current XSLT stylesheet
243 *
244 * Find the next stylesheet in import precedence.
245 *
246 * Returns the next stylesheet or NULL if it was the last one
247 */
248
249 xsltStylesheetPtr
250 xsltNextImport(xsltStylesheetPtr cur) {
251 if (cur == NULL)
252 return(NULL);
253 if (cur->imports != NULL)
254 return(cur->imports);
255 if (cur->next != NULL)
256 return(cur->next) ;
257 do {
258 cur = cur->parent;
259 if (cur == NULL) break;
260 if (cur->next != NULL) return(cur->next);
261 } while (cur != NULL);
262 return(cur);
263 }
264
265 /**
266 * xsltNeedElemSpaceHandling:
267 * @ctxt: an XSLT transformation context
268 *
269 * Checks whether that stylesheet requires white-space stripping
270 *
271 * Returns 1 if space should be stripped, 0 if not
272 */
273
274 int
275 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
276 xsltStylesheetPtr style;
277
278 if (ctxt == NULL)
279 return(0);
280 style = ctxt->style;
281 while (style != NULL) {
282 if (style->stripSpaces != NULL)
283 return(1);
284 style = xsltNextImport(style);
285 }
286 return(0);
287 }
288
289 /**
290 * xsltFindElemSpaceHandling:
291 * @ctxt: an XSLT transformation context
292 * @node: an XML node
293 *
294 * Find strip-space or preserve-space information for an element
295 * respect the import precedence or the wildcards
296 *
297 * Returns 1 if space should be stripped, 0 if not, and 2 if everything
298 * should be CDTATA wrapped.
299 */
300
301 int
302 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
303 xsltStylesheetPtr style;
304 const xmlChar *val;
305
306 if ((ctxt == NULL) || (node == NULL))
307 return(0);
308 style = ctxt->style;
309 while (style != NULL) {
310 if (node->ns != NULL) {
311 val = (const xmlChar *)
312 xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
313 if (val == NULL) {
314 val = (const xmlChar *)
315 xmlHashLookup2(style->stripSpaces, BAD_CAST "*",
316 node->ns->href);
317 }
318 } else {
319 val = (const xmlChar *)
320 xmlHashLookup2(style->stripSpaces, node->name, NULL);
321 }
322 if (val != NULL) {
323 if (xmlStrEqual(val, (xmlChar *) "strip"))
324 return(1);
325 if (xmlStrEqual(val, (xmlChar *) "preserve"))
326 return(0);
327 }
328 if (style->stripAll == 1)
329 return(1);
330 if (style->stripAll == -1)
331 return(0);
332
333 style = xsltNextImport(style);
334 }
335 return(0);
336 }
337
338 /**
339 * xsltFindTemplate:
340 * @ctxt: an XSLT transformation context
341 * @name: the template name
342 * @nameURI: the template name URI
343 *
344 * Finds the named template, apply import precedence rule.
345 * REVISIT TODO: We'll change the nameURI fields of
346 * templates to be in the string dict, so if the
347 * specified @nameURI is in the same dict, then use pointer
348 * comparison. Check if this can be done in a sane way.
349 * Maybe this function is not needed internally at
350 * transformation-time if we hard-wire the called templates
351 * to the caller.
352 *
353 * Returns the xsltTemplatePtr or NULL if not found
354 */
355 xsltTemplatePtr
356 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
357 const xmlChar *nameURI) {
358 xsltTemplatePtr cur;
359 xsltStylesheetPtr style;
360
361 if ((ctxt == NULL) || (name == NULL))
362 return(NULL);
363 style = ctxt->style;
364 while (style != NULL) {
365 if (style->namedTemplates != NULL) {
366 cur = (xsltTemplatePtr)
367 xmlHashLookup2(style->namedTemplates, name, nameURI);
368 if (cur != NULL)
369 return(cur);
370 }
371
372 style = xsltNextImport(style);
373 }
374 return(NULL);
375 }
376