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