fixed bug 119946, caused by incorrect creation of "extra" variables when
[platform/upstream/libxslt.git] / 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 #define IN_LIBXSLT
13 #include "libxslt.h"
14
15 #include <string.h>
16
17 #ifdef HAVE_SYS_TYPES_H
18 #include <sys/types.h>
19 #endif
20 #ifdef HAVE_MATH_H
21 #include <math.h>
22 #endif
23 #ifdef HAVE_FLOAT_H
24 #include <float.h>
25 #endif
26 #ifdef HAVE_IEEEFP_H
27 #include <ieeefp.h>
28 #endif
29 #ifdef HAVE_NAN_H
30 #include <nan.h>
31 #endif
32 #ifdef HAVE_CTYPE_H
33 #include <ctype.h>
34 #endif
35
36 #include <libxml/xmlmemory.h>
37 #include <libxml/tree.h>
38 #include <libxml/hash.h>
39 #include <libxml/xmlerror.h>
40 #include <libxml/uri.h>
41 #include "xslt.h"
42 #include "xsltInternals.h"
43 #include "xsltutils.h"
44 #include "imports.h"
45 #include "documents.h"
46 #include "security.h"
47 #include "pattern.h"
48
49
50 /************************************************************************
51  *                                                                      *
52  *                      Module interfaces                               *
53  *                                                                      *
54  ************************************************************************/
55
56 /**
57  * xsltParseStylesheetImport:
58  * @style:  the XSLT stylesheet
59  * @cur:  the import element
60  *
61  * parse an XSLT stylesheet import element
62  *
63  * Returns 0 in case of success -1 in case of failure.
64  */
65
66 int
67 xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
68     int ret = -1;
69     xmlDocPtr import = NULL;
70     xmlChar *base = NULL;
71     xmlChar *uriRef = NULL;
72     xmlChar *URI = NULL;
73     xsltStylesheetPtr res;
74     xsltSecurityPrefsPtr sec;
75
76     if ((cur == NULL) || (style == NULL))
77         return (ret);
78
79     uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
80     if (uriRef == NULL) {
81         xsltTransformError(NULL, style, cur,
82             "xsl:import : missing href attribute\n");
83         goto error;
84     }
85
86     base = xmlNodeGetBase(style->doc, cur);
87     URI = xmlBuildURI(uriRef, base);
88     if (URI == NULL) {
89         xsltTransformError(NULL, style, cur,
90             "xsl:import : invalid URI reference %s\n", uriRef);
91         goto error;
92     }
93
94     /*
95      * Security framework check
96      */
97     sec = xsltGetDefaultSecurityPrefs();
98     if (sec != NULL) {
99         int secres;
100
101         secres = xsltCheckRead(sec, NULL, URI);
102         if (secres == 0) {
103             xsltTransformError(NULL, NULL, NULL,
104                  "xsl:import: read rights for %s denied\n",
105                              URI);
106             goto error;
107         }
108     }
109
110     import = xmlParseFile((const char *)URI);
111     if (import == NULL) {
112         xsltTransformError(NULL, style, cur,
113             "xsl:import : unable to load %s\n", URI);
114         goto error;
115     }
116
117     res = xsltParseStylesheetImportedDoc(import);
118     if (res != NULL) {
119         res->parent = style;
120         res->next = style->imports;
121         style->imports = res;
122         xmlHashScan(res->templatesHash, 
123                     (xmlHashScanner) xsltNormalizeCompSteps, style);
124         style->extrasNr += res->extrasNr;
125         ret = 0;
126     } else {
127         xmlFreeDoc(import);
128         }
129
130 error:
131     if (uriRef != NULL)
132         xmlFree(uriRef);
133     if (base != NULL)
134         xmlFree(base);
135     if (URI != NULL)
136         xmlFree(URI);
137
138     return (ret);
139 }
140
141 /**
142  * xsltParseStylesheetInclude:
143  * @style:  the XSLT stylesheet
144  * @cur:  the include node
145  *
146  * parse an XSLT stylesheet include element
147  *
148  * Returns 0 in case of success -1 in case of failure
149  */
150
151 int
152 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
153     int ret = -1;
154     xmlDocPtr oldDoc;
155     xmlChar *base = NULL;
156     xmlChar *uriRef = NULL;
157     xmlChar *URI = NULL;
158     xsltDocumentPtr include;
159
160     if ((cur == NULL) || (style == NULL))
161         return (ret);
162
163     uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
164     if (uriRef == NULL) {
165         xsltTransformError(NULL, style, cur,
166             "xsl:include : missing href attribute\n");
167         goto error;
168     }
169
170     base = xmlNodeGetBase(style->doc, cur);
171     URI = xmlBuildURI(uriRef, base);
172     if (URI == NULL) {
173         xsltTransformError(NULL, style, cur,
174             "xsl:include : invalid URI reference %s\n", uriRef);
175         goto error;
176     }
177
178     include = xsltLoadStyleDocument(style, URI);
179     if (include == NULL) {
180         xsltTransformError(NULL, style, cur,
181             "xsl:include : unable to load %s\n", URI);
182         goto error;
183     }
184
185     oldDoc = style->doc;
186     style->doc = include->doc;
187     ret = (int)xsltParseStylesheetProcess(style, include->doc);
188     style->doc = oldDoc;
189     if (ret == 0) {
190                 ret = -1;
191                 goto error;
192         }
193     ret = 0;
194
195 error:
196     if (uriRef != NULL)
197         xmlFree(uriRef);
198     if (base != NULL)
199         xmlFree(base);
200     if (URI != NULL)
201         xmlFree(URI);
202
203     return (ret);
204 }
205
206 /**
207  * xsltNextImport:
208  * @cur:  the current XSLT stylesheet
209  *
210  * Find the next stylesheet in import precedence.
211  *
212  * Returns the next stylesheet or NULL if it was the last one
213  */
214
215 xsltStylesheetPtr
216 xsltNextImport(xsltStylesheetPtr cur) {
217     if (cur == NULL)
218         return(NULL);
219     if (cur->imports != NULL)
220         return(cur->imports);
221     if (cur->next != NULL)
222         return(cur->next) ;
223     do {
224         cur = cur->parent;
225         if (cur == NULL) return(NULL);
226         if (cur->next != NULL) return(cur->next);
227     } while (cur != NULL);
228     return(cur);
229 }
230
231 /**
232  * xsltNeedElemSpaceHandling:
233  * @ctxt:  an XSLT transformation context
234  *
235  * Checks whether that stylesheet requires white-space stripping
236  *
237  * Returns 1 if space should be stripped, 0 if not
238  */
239
240 int
241 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
242     xsltStylesheetPtr style;
243
244     if (ctxt == NULL)
245         return(0);
246     style = ctxt->style;
247     while (style != NULL) {
248         if (style->stripSpaces != NULL)
249             return(1);
250         style = xsltNextImport(style);
251     }
252     return(0);
253 }
254
255 /**
256  * xsltFindElemSpaceHandling:
257  * @ctxt:  an XSLT transformation context
258  * @node:  an XML node
259  *
260  * Find strip-space or preserve-space informations for an element
261  * respect the import precedence or the wildcards
262  *
263  * Returns 1 if space should be stripped, 0 if not, and 2 if everything
264  *         should be CDTATA wrapped.
265  */
266
267 int
268 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
269     xsltStylesheetPtr style;
270     const xmlChar *val;
271
272     if ((ctxt == NULL) || (node == NULL))
273         return(0);
274     style = ctxt->style;
275     while (style != NULL) {
276         if (node->ns != NULL) {
277             val = (const xmlChar *)
278               xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
279         } else {
280             val = (const xmlChar *)
281                   xmlHashLookup2(style->stripSpaces, node->name, NULL);
282         }
283         if (val != NULL) {
284             if (xmlStrEqual(val, (xmlChar *) "strip"))
285                 return(1);
286             if (xmlStrEqual(val, (xmlChar *) "preserve"))
287                 return(0);
288         } 
289         if (style->stripAll == 1)
290             return(1);
291         if (style->stripAll == -1)
292             return(0);
293
294         style = xsltNextImport(style);
295     }
296     return(0);
297 }
298
299 /**
300  * xsltFindTemplate:
301  * @ctxt:  an XSLT transformation context
302  * @name: the template name
303  * @nameURI: the template name URI
304  *
305  * Finds the named template, apply import precedence rule.
306  *
307  * Returns the xsltTemplatePtr or NULL if not found
308  */
309 xsltTemplatePtr
310 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
311                  const xmlChar *nameURI) {
312     xsltTemplatePtr cur;
313     xsltStylesheetPtr style;
314
315     if ((ctxt == NULL) || (name == NULL))
316         return(NULL);
317     style = ctxt->style;
318     while (style != NULL) {
319         cur = style->templates;
320         while (cur != NULL) {
321             if (xmlStrEqual(name, cur->name)) {
322                 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
323                     ((nameURI != NULL) && (cur->nameURI != NULL) &&
324                      (xmlStrEqual(nameURI, cur->nameURI)))) {
325                     return(cur);
326                 }
327             }
328             cur = cur->next;
329         }
330
331         style = xsltNextImport(style);
332     }
333     return(NULL);
334 }
335