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