new module with runtime security checks, it will also check and do
[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
48
49
50 /************************************************************************
51  *                                                                      *
52  *                      Module interfaces                               *
53  *                                                                      *
54  ************************************************************************/
55
56 /**
57  * xsltParseStylesheetImport:
58  * @style:  the XSLT stylesheet
59  * @template:  the "strip-space" element
60  *
61  * parse an XSLT stylesheet strip-space element and record
62  * elements needing stripping. Returns zero on success and something else
63  * on 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         xsltPrintErrorContext(NULL, style, cur);
82         xsltGenericError(xsltGenericErrorContext,
83             "xsl:import : missing href attribute\n");
84         goto error;
85     }
86
87     base = xmlNodeGetBase(style->doc, cur);
88     URI = xmlBuildURI(uriRef, base);
89     if (URI == NULL) {
90         xsltPrintErrorContext(NULL, style, cur);
91         xsltGenericError(xsltGenericErrorContext,
92             "xsl:import : invalid URI reference %s\n", uriRef);
93         goto error;
94     }
95
96     /*
97      * Security framework check
98      */
99     sec = xsltGetDefaultSecurityPrefs();
100     if (sec != NULL) {
101         int res;
102
103         res = xsltCheckRead(sec, NULL, URI);
104         if (res == 0) {
105             xsltPrintErrorContext(NULL, NULL, NULL);
106             xsltGenericError(xsltGenericErrorContext,
107                  "xsl:import: read rights for %s denied\n",
108                              URI);
109             goto error;
110         }
111     }
112
113     import = xmlParseFile((const char *)URI);
114     if (import == NULL) {
115         xsltPrintErrorContext(NULL, style, cur);
116         xsltGenericError(xsltGenericErrorContext,
117             "xsl:import : unable to load %s\n", URI);
118         goto error;
119     }
120
121     res = xsltParseStylesheetDoc(import);
122     if (res != NULL) {
123         res->parent = style;
124         res->next = style->imports;
125         style->imports = res;
126         style->extrasNr += res->extrasNr;
127         ret = 0;
128     } else {
129         xmlFreeDoc(import);
130         }
131
132 error:
133     if (uriRef != NULL)
134         xmlFree(uriRef);
135     if (base != NULL)
136         xmlFree(base);
137     if (URI != NULL)
138         xmlFree(URI);
139
140     return (ret);
141 }
142
143 /**
144  * xsltParseStylesheetInclude:
145  * @style:  the XSLT stylesheet
146  * @template:  the "strip-space" element
147  *
148  * parse an XSLT stylesheet strip-space element and record
149  * elements needing stripping. Returns zero on success, something else
150  * on failure.
151  */
152
153 int
154 xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
155     int ret = -1;
156     xmlDocPtr oldDoc;
157     xmlChar *base = NULL;
158     xmlChar *uriRef = NULL;
159     xmlChar *URI = NULL;
160     xsltDocumentPtr include;
161
162     if ((cur == NULL) || (style == NULL))
163         return (ret);
164
165     uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
166     if (uriRef == NULL) {
167         xsltPrintErrorContext(NULL, style, cur);
168         xsltGenericError(xsltGenericErrorContext,
169             "xsl:include : missing href attribute\n");
170         goto error;
171     }
172
173     base = xmlNodeGetBase(style->doc, cur);
174     URI = xmlBuildURI(uriRef, base);
175     if (URI == NULL) {
176         xsltPrintErrorContext(NULL, style, cur);
177         xsltGenericError(xsltGenericErrorContext,
178             "xsl:include : invalid URI reference %s\n", uriRef);
179         goto error;
180     }
181
182     include = xsltLoadStyleDocument(style, URI);
183     if (include == NULL) {
184         xsltPrintErrorContext(NULL, style, cur);
185         xsltGenericError(xsltGenericErrorContext,
186             "xsl:include : unable to load %s\n", URI);
187         goto error;
188     }
189
190     oldDoc = style->doc;
191     style->doc = include->doc;
192     ret = (int)xsltParseStylesheetProcess(style, include->doc);
193     style->doc = oldDoc;
194     if (ret == 0) {
195                 ret = -1;
196                 goto error;
197         }
198     ret = 0;
199
200 error:
201     if (uriRef != NULL)
202         xmlFree(uriRef);
203     if (base != NULL)
204         xmlFree(base);
205     if (URI != NULL)
206         xmlFree(URI);
207
208     return (ret);
209 }
210
211 /**
212  * xsltNextImport:
213  * @cur:  the current XSLT stylesheet
214  *
215  * Find the next stylesheet in import precedence.
216  *
217  * Returns the next stylesheet or NULL if it was the last one
218  */
219
220 xsltStylesheetPtr
221 xsltNextImport(xsltStylesheetPtr cur) {
222     if (cur == NULL)
223         return(NULL);
224     if (cur->imports != NULL)
225         return(cur->imports);
226     if (cur->next != NULL)
227         return(cur->next) ;
228     do {
229         cur = cur->parent;
230         if (cur == NULL) return(NULL);
231         if (cur->next != NULL) return(cur->next);
232     } while (cur != NULL);
233     return(cur);
234 }
235
236 /**
237  * xsltNeedElemSpaceHandling:
238  * @ctxt:  an XSLT transformation context
239  *
240  * Returns whether that stylesheet requires white-space stripping
241  *
242  * Returns 1 if space should be stripped, 0 if not
243  */
244
245 int
246 xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
247     xsltStylesheetPtr style;
248
249     if (ctxt == NULL)
250         return(0);
251     style = ctxt->style;
252     while (style != NULL) {
253         if (style->stripSpaces != NULL)
254             return(1);
255         style = xsltNextImport(style);
256     }
257     return(0);
258 }
259
260 /**
261  * xsltFindElemSpaceHandling:
262  * @ctxt:  an XSLT transformation context
263  * @node:  an XML node
264  *
265  * Find strip-space or preserve-space informations for an element
266  * respect the import precedence or the wildcards
267  *
268  * Returns 1 if space should be stripped, 0 if not, and 2 if everything
269  *         should be CDTATA wrapped.
270  */
271
272 int
273 xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
274     xsltStylesheetPtr style;
275     const xmlChar *val;
276
277     if ((ctxt == NULL) || (node == NULL))
278         return(0);
279     style = ctxt->style;
280     while (style != NULL) {
281         if (node->ns != NULL) {
282             val = (const xmlChar *)
283               xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
284         } else {
285             val = (const xmlChar *)
286                   xmlHashLookup2(style->stripSpaces, node->name, NULL);
287         }
288         if (val != NULL) {
289             if (xmlStrEqual(val, (xmlChar *) "strip"))
290                 return(1);
291             if (xmlStrEqual(val, (xmlChar *) "preserve"))
292                 return(0);
293         } 
294         if (ctxt->style->stripAll == 1)
295             return(1);
296         if (ctxt->style->stripAll == -1)
297             return(0);
298
299         style = xsltNextImport(style);
300     }
301     return(0);
302 }
303
304 /**
305  * xsltFindTemplate:
306  * @ctxt:  an XSLT transformation context
307  * @name: the template name
308  * @nameURI: the template name URI
309  *
310  * Finds the named template, apply import precedence rule.
311  *
312  * Returns the xsltTemplatePtr or NULL if not found
313  */
314 xsltTemplatePtr
315 xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
316                  const xmlChar *nameURI) {
317     xsltTemplatePtr cur;
318     xsltStylesheetPtr style;
319
320     if ((ctxt == NULL) || (name == NULL))
321         return(NULL);
322     style = ctxt->style;
323     while (style != NULL) {
324         cur = style->templates;
325         while (cur != NULL) {
326             if (xmlStrEqual(name, cur->name)) {
327                 if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
328                     ((nameURI != NULL) && (cur->nameURI != NULL) &&
329                      (xmlStrEqual(nameURI, cur->nameURI)))) {
330                     return(cur);
331                 }
332             }
333             cur = cur->next;
334         }
335
336         style = xsltNextImport(style);
337     }
338     return(NULL);
339 }
340