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