source: trunk/third/libxslt/libxslt/imports.c @ 20733

Revision 20733, 8.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20732, which included commits to RCS files with non-trunk default branches.
Line 
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 * xsltFixImportedCompSteps:
57 * @master: the "master" stylesheet
58 * @style: the stylesheet being imported by the master
59 *
60 * normalize the comp steps for the stylesheet being imported
61 * by the master, together with any imports within that.
62 *
63 */
64static void xsltFixImportedCompSteps(xsltStylesheetPtr master,
65                        xsltStylesheetPtr style) {
66    xsltStylesheetPtr res;
67    xmlHashScan(style->templatesHash,
68                    (xmlHashScanner) xsltNormalizeCompSteps, master);
69    master->extrasNr += style->extrasNr;
70    for (res = style->imports; res != NULL; res = res->next) {
71        xsltFixImportedCompSteps(master, res);
72    }
73}
74
75/**
76 * xsltParseStylesheetImport:
77 * @style:  the XSLT stylesheet
78 * @cur:  the import element
79 *
80 * parse an XSLT stylesheet import element
81 *
82 * Returns 0 in case of success -1 in case of failure.
83 */
84
85int
86xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
87    int ret = -1;
88    xmlDocPtr import = NULL;
89    xmlChar *base = NULL;
90    xmlChar *uriRef = NULL;
91    xmlChar *URI = NULL;
92    xsltStylesheetPtr res;
93    xsltSecurityPrefsPtr sec;
94
95    if ((cur == NULL) || (style == NULL))
96        return (ret);
97
98    uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
99    if (uriRef == NULL) {
100        xsltTransformError(NULL, style, cur,
101            "xsl:import : missing href attribute\n");
102        goto error;
103    }
104
105    base = xmlNodeGetBase(style->doc, cur);
106    URI = xmlBuildURI(uriRef, base);
107    if (URI == NULL) {
108        xsltTransformError(NULL, style, cur,
109            "xsl:import : invalid URI reference %s\n", uriRef);
110        goto error;
111    }
112
113    res = style;
114    while (res != NULL) {
115        if (res->doc == NULL)
116            break;
117        if (xmlStrEqual(res->doc->URL, URI)) {
118            xsltTransformError(NULL, style, cur,
119               "xsl:import : recursion detected on imported URL %s\n", URI);
120            goto error;
121        }
122        res = res->parent;
123    }
124
125    /*
126     * Security framework check
127     */
128    sec = xsltGetDefaultSecurityPrefs();
129    if (sec != NULL) {
130        int secres;
131
132        secres = xsltCheckRead(sec, NULL, URI);
133        if (secres == 0) {
134            xsltTransformError(NULL, NULL, NULL,
135                 "xsl:import: read rights for %s denied\n",
136                             URI);
137            goto error;
138        }
139    }
140
141    import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
142                                  (void *) style, XSLT_LOAD_STYLESHEET);
143    if (import == NULL) {
144        xsltTransformError(NULL, style, cur,
145            "xsl:import : unable to load %s\n", URI);
146        goto error;
147    }
148
149    res = xsltParseStylesheetImportedDoc(import, style);
150    if (res != NULL) {
151        res->next = style->imports;
152        style->imports = res;
153        if (style->parent == NULL) {
154            xsltFixImportedCompSteps(style, res);
155        }
156        ret = 0;
157    } else {
158        xmlFreeDoc(import);
159        }
160
161error:
162    if (uriRef != NULL)
163        xmlFree(uriRef);
164    if (base != NULL)
165        xmlFree(base);
166    if (URI != NULL)
167        xmlFree(URI);
168
169    return (ret);
170}
171
172/**
173 * xsltParseStylesheetInclude:
174 * @style:  the XSLT stylesheet
175 * @cur:  the include node
176 *
177 * parse an XSLT stylesheet include element
178 *
179 * Returns 0 in case of success -1 in case of failure
180 */
181
182int
183xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
184    int ret = -1;
185    xmlDocPtr oldDoc;
186    xmlChar *base = NULL;
187    xmlChar *uriRef = NULL;
188    xmlChar *URI = NULL;
189    xsltStylesheetPtr result;
190    xsltDocumentPtr include;
191    xsltDocumentPtr docptr;
192
193    if ((cur == NULL) || (style == NULL))
194        return (ret);
195
196    uriRef = xsltGetNsProp(cur, (const xmlChar *)"href", XSLT_NAMESPACE);
197    if (uriRef == NULL) {
198        xsltTransformError(NULL, style, cur,
199            "xsl:include : missing href attribute\n");
200        goto error;
201    }
202
203    base = xmlNodeGetBase(style->doc, cur);
204    URI = xmlBuildURI(uriRef, base);
205    if (URI == NULL) {
206        xsltTransformError(NULL, style, cur,
207            "xsl:include : invalid URI reference %s\n", uriRef);
208        goto error;
209    }
210
211    /*
212     * in order to detect recursion, we check all previously included
213     * stylesheets.
214     */
215    docptr = style->includes;
216    while (docptr != NULL) {
217        if (xmlStrEqual(docptr->doc->URL, URI)) {
218            xsltTransformError(NULL, style, cur,
219                "xsl:include : recursion detected on included URL %s\n", URI);
220            goto error;
221        }
222        docptr = docptr->includes;
223    }
224
225    include = xsltLoadStyleDocument(style, URI);
226    if (include == NULL) {
227        xsltTransformError(NULL, style, cur,
228            "xsl:include : unable to load %s\n", URI);
229        goto error;
230    }
231
232    oldDoc = style->doc;
233    style->doc = include->doc;
234    /* chain to stylesheet for recursion checking */
235    include->includes = style->includes;
236    style->includes = include;
237    result = xsltParseStylesheetProcess(style, include->doc);
238    style->includes = include->includes;
239    style->doc = oldDoc;
240    if (result == NULL) {
241        ret = -1;
242        goto error;
243    }
244    ret = 0;
245
246error:
247    if (uriRef != NULL)
248        xmlFree(uriRef);
249    if (base != NULL)
250        xmlFree(base);
251    if (URI != NULL)
252        xmlFree(URI);
253
254    return (ret);
255}
256
257/**
258 * xsltNextImport:
259 * @cur:  the current XSLT stylesheet
260 *
261 * Find the next stylesheet in import precedence.
262 *
263 * Returns the next stylesheet or NULL if it was the last one
264 */
265
266xsltStylesheetPtr
267xsltNextImport(xsltStylesheetPtr cur) {
268    if (cur == NULL)
269        return(NULL);
270    if (cur->imports != NULL)
271        return(cur->imports);
272    if (cur->next != NULL)
273        return(cur->next) ;
274    do {
275        cur = cur->parent;
276        if (cur == NULL) return(NULL);
277        if (cur->next != NULL) return(cur->next);
278    } while (cur != NULL);
279    return(cur);
280}
281
282/**
283 * xsltNeedElemSpaceHandling:
284 * @ctxt:  an XSLT transformation context
285 *
286 * Checks whether that stylesheet requires white-space stripping
287 *
288 * Returns 1 if space should be stripped, 0 if not
289 */
290
291int
292xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt) {
293    xsltStylesheetPtr style;
294
295    if (ctxt == NULL)
296        return(0);
297    style = ctxt->style;
298    while (style != NULL) {
299        if (style->stripSpaces != NULL)
300            return(1);
301        style = xsltNextImport(style);
302    }
303    return(0);
304}
305
306/**
307 * xsltFindElemSpaceHandling:
308 * @ctxt:  an XSLT transformation context
309 * @node:  an XML node
310 *
311 * Find strip-space or preserve-space informations for an element
312 * respect the import precedence or the wildcards
313 *
314 * Returns 1 if space should be stripped, 0 if not, and 2 if everything
315 *         should be CDTATA wrapped.
316 */
317
318int
319xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
320    xsltStylesheetPtr style;
321    const xmlChar *val;
322
323    if ((ctxt == NULL) || (node == NULL))
324        return(0);
325    style = ctxt->style;
326    while (style != NULL) {
327        if (node->ns != NULL) {
328            val = (const xmlChar *)
329              xmlHashLookup2(style->stripSpaces, node->name, node->ns->href);
330        } else {
331            val = (const xmlChar *)
332                  xmlHashLookup2(style->stripSpaces, node->name, NULL);
333        }
334        if (val != NULL) {
335            if (xmlStrEqual(val, (xmlChar *) "strip"))
336                return(1);
337            if (xmlStrEqual(val, (xmlChar *) "preserve"))
338                return(0);
339        }
340        if (style->stripAll == 1)
341            return(1);
342        if (style->stripAll == -1)
343            return(0);
344
345        style = xsltNextImport(style);
346    }
347    return(0);
348}
349
350/**
351 * xsltFindTemplate:
352 * @ctxt:  an XSLT transformation context
353 * @name: the template name
354 * @nameURI: the template name URI
355 *
356 * Finds the named template, apply import precedence rule.
357 *
358 * Returns the xsltTemplatePtr or NULL if not found
359 */
360xsltTemplatePtr
361xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name,
362                 const xmlChar *nameURI) {
363    xsltTemplatePtr cur;
364    xsltStylesheetPtr style;
365
366    if ((ctxt == NULL) || (name == NULL))
367        return(NULL);
368    style = ctxt->style;
369    while (style != NULL) {
370        cur = style->templates;
371        while (cur != NULL) {
372            if (xmlStrEqual(name, cur->name)) {
373                if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
374                    ((nameURI != NULL) && (cur->nameURI != NULL) &&
375                     (xmlStrEqual(nameURI, cur->nameURI)))) {
376                    return(cur);
377                }
378            }
379            cur = cur->next;
380        }
381
382        style = xsltNextImport(style);
383    }
384    return(NULL);
385}
386
Note: See TracBrowser for help on using the repository browser.