Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xslt/libxslt/documents.c
4393 views
1
/*
2
* documents.c: Implementation of the documents handling
3
*
4
* See Copyright for the status of this software.
5
*
6
* [email protected]
7
*/
8
9
#define IN_LIBXSLT
10
#include "libxslt.h"
11
12
#include <string.h>
13
14
#include <libxml/xmlmemory.h>
15
#include <libxml/tree.h>
16
#include <libxml/hash.h>
17
#include <libxml/parser.h>
18
#include <libxml/parserInternals.h>
19
#include "xslt.h"
20
#include "xsltInternals.h"
21
#include "xsltutils.h"
22
#include "documents.h"
23
#include "transform.h"
24
#include "imports.h"
25
#include "keys.h"
26
#include "security.h"
27
28
#ifdef LIBXML_XINCLUDE_ENABLED
29
#include <libxml/xinclude.h>
30
#endif
31
32
#define WITH_XSLT_DEBUG_DOCUMENTS
33
34
#ifdef WITH_XSLT_DEBUG
35
#define WITH_XSLT_DEBUG_DOCUMENTS
36
#endif
37
38
/************************************************************************
39
* *
40
* Hooks for the document loader *
41
* *
42
************************************************************************/
43
44
/**
45
* xsltDocDefaultLoaderFunc:
46
* @URI: the URI of the document to load
47
* @dict: the dictionary to use when parsing that document
48
* @options: parsing options, a set of xmlParserOption
49
* @ctxt: the context, either a stylesheet or a transformation context
50
* @type: the xsltLoadType indicating the kind of loading required
51
*
52
* Default function to load document not provided by the compilation or
53
* transformation API themselve, for example when an xsl:import,
54
* xsl:include is found at compilation time or when a document()
55
* call is made at runtime.
56
*
57
* Returns the pointer to the document (which will be modified and
58
* freed by the engine later), or NULL in case of error.
59
*/
60
static xmlDocPtr
61
xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
62
void *ctxt ATTRIBUTE_UNUSED,
63
xsltLoadType type ATTRIBUTE_UNUSED)
64
{
65
xmlParserCtxtPtr pctxt;
66
xmlParserInputPtr inputStream;
67
xmlDocPtr doc;
68
69
pctxt = xmlNewParserCtxt();
70
if (pctxt == NULL)
71
return(NULL);
72
if ((dict != NULL) && (pctxt->dict != NULL)) {
73
xmlDictFree(pctxt->dict);
74
pctxt->dict = NULL;
75
}
76
if (dict != NULL) {
77
pctxt->dict = dict;
78
xmlDictReference(pctxt->dict);
79
#ifdef WITH_XSLT_DEBUG
80
xsltGenericDebug(xsltGenericDebugContext,
81
"Reusing dictionary for document\n");
82
#endif
83
}
84
xmlCtxtUseOptions(pctxt, options);
85
inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
86
if (inputStream == NULL) {
87
xmlFreeParserCtxt(pctxt);
88
return(NULL);
89
}
90
91
#if LIBXML_VERSION >= 21300
92
doc = xmlCtxtParseDocument(pctxt, inputStream);
93
#else
94
inputPush(pctxt, inputStream);
95
96
xmlParseDocument(pctxt);
97
98
if (pctxt->wellFormed) {
99
doc = pctxt->myDoc;
100
}
101
else {
102
doc = NULL;
103
xmlFreeDoc(pctxt->myDoc);
104
pctxt->myDoc = NULL;
105
}
106
#endif
107
108
xmlFreeParserCtxt(pctxt);
109
110
return(doc);
111
}
112
113
114
xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
115
116
/**
117
* xsltSetLoaderFunc:
118
* @f: the new function to handle document loading.
119
*
120
* Set the new function to load document, if NULL it resets it to the
121
* default function.
122
*/
123
124
void
125
xsltSetLoaderFunc(xsltDocLoaderFunc f) {
126
if (f == NULL)
127
xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
128
else
129
xsltDocDefaultLoader = f;
130
}
131
132
/************************************************************************
133
* *
134
* Module interfaces *
135
* *
136
************************************************************************/
137
138
/**
139
* xsltNewDocument:
140
* @ctxt: an XSLT transformation context (or NULL)
141
* @doc: a parsed XML document
142
*
143
* Register a new document, apply key computations
144
*
145
* Returns a handler to the document
146
*/
147
xsltDocumentPtr
148
xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
149
xsltDocumentPtr cur;
150
151
cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
152
if (cur == NULL) {
153
xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
154
"xsltNewDocument : malloc failed\n");
155
return(NULL);
156
}
157
memset(cur, 0, sizeof(xsltDocument));
158
cur->doc = doc;
159
if (ctxt != NULL) {
160
if (! XSLT_IS_RES_TREE_FRAG(doc)) {
161
cur->next = ctxt->docList;
162
ctxt->docList = cur;
163
}
164
/*
165
* A key with a specific name for a specific document
166
* will only be computed if there's a call to the key()
167
* function using that specific name for that specific
168
* document. I.e. computation of keys will be done in
169
* xsltGetKey() (keys.c) on an on-demand basis.
170
*
171
* xsltInitCtxtKeys(ctxt, cur); not called here anymore
172
*/
173
}
174
return(cur);
175
}
176
177
/**
178
* xsltNewStyleDocument:
179
* @style: an XSLT style sheet
180
* @doc: a parsed XML document
181
*
182
* Register a new document, apply key computations
183
*
184
* Returns a handler to the document
185
*/
186
xsltDocumentPtr
187
xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
188
xsltDocumentPtr cur;
189
190
cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
191
if (cur == NULL) {
192
xsltTransformError(NULL, style, (xmlNodePtr) doc,
193
"xsltNewStyleDocument : malloc failed\n");
194
return(NULL);
195
}
196
memset(cur, 0, sizeof(xsltDocument));
197
cur->doc = doc;
198
if (style != NULL) {
199
cur->next = style->docList;
200
style->docList = cur;
201
}
202
return(cur);
203
}
204
205
/**
206
* xsltFreeStyleDocuments:
207
* @style: an XSLT stylesheet (representing a stylesheet-level)
208
*
209
* Frees the node-trees (and xsltDocument structures) of all
210
* stylesheet-modules of the stylesheet-level represented by
211
* the given @style.
212
*/
213
void
214
xsltFreeStyleDocuments(xsltStylesheetPtr style) {
215
xsltDocumentPtr doc, cur;
216
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
217
xsltNsMapPtr nsMap;
218
#endif
219
220
if (style == NULL)
221
return;
222
223
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
224
if (XSLT_HAS_INTERNAL_NSMAP(style))
225
nsMap = XSLT_GET_INTERNAL_NSMAP(style);
226
else
227
nsMap = NULL;
228
#endif
229
230
cur = style->docList;
231
while (cur != NULL) {
232
doc = cur;
233
cur = cur->next;
234
#ifdef XSLT_REFACTORED_XSLT_NSCOMP
235
/*
236
* Restore all changed namespace URIs of ns-decls.
237
*/
238
if (nsMap)
239
xsltRestoreDocumentNamespaces(nsMap, doc->doc);
240
#endif
241
xsltFreeDocumentKeys(doc);
242
if (!doc->main)
243
xmlFreeDoc(doc->doc);
244
xmlFree(doc);
245
}
246
}
247
248
/**
249
* xsltFreeDocuments:
250
* @ctxt: an XSLT transformation context
251
*
252
* Free up all the space used by the loaded documents
253
*/
254
void
255
xsltFreeDocuments(xsltTransformContextPtr ctxt) {
256
xsltDocumentPtr doc, cur;
257
258
cur = ctxt->docList;
259
while (cur != NULL) {
260
doc = cur;
261
cur = cur->next;
262
xsltFreeDocumentKeys(doc);
263
if (!doc->main)
264
xmlFreeDoc(doc->doc);
265
xmlFree(doc);
266
}
267
cur = ctxt->styleList;
268
while (cur != NULL) {
269
doc = cur;
270
cur = cur->next;
271
xsltFreeDocumentKeys(doc);
272
if (!doc->main)
273
xmlFreeDoc(doc->doc);
274
xmlFree(doc);
275
}
276
}
277
278
/**
279
* xsltLoadDocument:
280
* @ctxt: an XSLT transformation context
281
* @URI: the computed URI of the document
282
*
283
* Try to load a document (not a stylesheet)
284
* within the XSLT transformation context
285
*
286
* Returns the new xsltDocumentPtr or NULL in case of error
287
*/
288
xsltDocumentPtr
289
xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
290
xsltDocumentPtr ret;
291
xmlDocPtr doc;
292
293
if ((ctxt == NULL) || (URI == NULL))
294
return(NULL);
295
296
/*
297
* Security framework check
298
*/
299
if (ctxt->sec != NULL) {
300
int res;
301
302
res = xsltCheckRead(ctxt->sec, ctxt, URI);
303
if (res <= 0) {
304
if (res == 0)
305
xsltTransformError(ctxt, NULL, NULL,
306
"xsltLoadDocument: read rights for %s denied\n",
307
URI);
308
return(NULL);
309
}
310
}
311
312
/*
313
* Walk the context list to find the document if preparsed
314
*/
315
ret = ctxt->docList;
316
while (ret != NULL) {
317
if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
318
(xmlStrEqual(ret->doc->URL, URI)))
319
return(ret);
320
ret = ret->next;
321
}
322
323
doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
324
(void *) ctxt, XSLT_LOAD_DOCUMENT);
325
326
if (doc == NULL)
327
return(NULL);
328
329
if (ctxt->xinclude != 0) {
330
#ifdef LIBXML_XINCLUDE_ENABLED
331
#if LIBXML_VERSION >= 20603
332
xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
333
#else
334
xmlXIncludeProcess(doc);
335
#endif
336
#else
337
xsltTransformError(ctxt, NULL, NULL,
338
"xsltLoadDocument(%s) : XInclude processing not compiled in\n",
339
URI);
340
#endif
341
}
342
/*
343
* Apply white-space stripping if asked for
344
*/
345
if (xsltNeedElemSpaceHandling(ctxt))
346
xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
347
if (ctxt->debugStatus == XSLT_DEBUG_NONE)
348
xmlXPathOrderDocElems(doc);
349
350
ret = xsltNewDocument(ctxt, doc);
351
return(ret);
352
}
353
354
/**
355
* xsltLoadStyleDocument:
356
* @style: an XSLT style sheet
357
* @URI: the computed URI of the document
358
*
359
* Try to load a stylesheet document within the XSLT transformation context
360
*
361
* Returns the new xsltDocumentPtr or NULL in case of error
362
*/
363
xsltDocumentPtr
364
xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
365
xsltDocumentPtr ret;
366
xmlDocPtr doc;
367
xsltSecurityPrefsPtr sec;
368
369
if ((style == NULL) || (URI == NULL))
370
return(NULL);
371
372
/*
373
* Security framework check
374
*/
375
sec = xsltGetDefaultSecurityPrefs();
376
if (sec != NULL) {
377
int res;
378
379
res = xsltCheckRead(sec, NULL, URI);
380
if (res <= 0) {
381
if (res == 0)
382
xsltTransformError(NULL, NULL, NULL,
383
"xsltLoadStyleDocument: read rights for %s denied\n",
384
URI);
385
return(NULL);
386
}
387
}
388
389
/*
390
* Walk the context list to find the document if preparsed
391
*/
392
ret = style->docList;
393
while (ret != NULL) {
394
if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
395
(xmlStrEqual(ret->doc->URL, URI)))
396
return(ret);
397
ret = ret->next;
398
}
399
400
doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
401
(void *) style, XSLT_LOAD_STYLESHEET);
402
if (doc == NULL)
403
return(NULL);
404
405
ret = xsltNewStyleDocument(style, doc);
406
if (ret == NULL)
407
xmlFreeDoc(doc);
408
return(ret);
409
}
410
411
/**
412
* xsltFindDocument:
413
* @ctxt: an XSLT transformation context
414
* @doc: a parsed XML document
415
*
416
* Try to find a document within the XSLT transformation context.
417
* This will not find document infos for temporary
418
* Result Tree Fragments.
419
*
420
* Returns the desired xsltDocumentPtr or NULL in case of error
421
*/
422
xsltDocumentPtr
423
xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
424
xsltDocumentPtr ret;
425
426
if ((ctxt == NULL) || (doc == NULL))
427
return(NULL);
428
429
/*
430
* Walk the context list to find the document
431
*/
432
ret = ctxt->docList;
433
while (ret != NULL) {
434
if (ret->doc == doc)
435
return(ret);
436
ret = ret->next;
437
}
438
if (doc == ctxt->style->doc)
439
return(ctxt->document);
440
return(NULL);
441
}
442
443