Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xslt/libxslt/extensions.c
4392 views
1
/*
2
* extensions.c: Implemetation of the extensions support
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 <stdlib.h>
16
#include <string.h>
17
#include <limits.h>
18
19
#ifdef WITH_MODULES
20
#ifdef _WIN32
21
#define WIN32_LEAN_AND_MEAN
22
#include <windows.h>
23
#else
24
#include <dlfcn.h>
25
#endif
26
#endif
27
28
#include <libxml/xmlmemory.h>
29
#include <libxml/tree.h>
30
#include <libxml/hash.h>
31
#include <libxml/xmlerror.h>
32
#include <libxml/parserInternals.h>
33
#include <libxml/xpathInternals.h>
34
#include <libxml/list.h>
35
#include <libxml/xmlIO.h>
36
#include <libxml/threads.h>
37
#include "xslt.h"
38
#include "xsltInternals.h"
39
#include "xsltlocale.h"
40
#include "xsltutils.h"
41
#include "imports.h"
42
#include "extensions.h"
43
44
#include <stdlib.h> /* for _MAX_PATH & getenv */
45
#ifdef _WIN32
46
#ifndef PATH_MAX
47
#define PATH_MAX _MAX_PATH
48
#endif
49
#endif
50
51
#ifdef WITH_XSLT_DEBUG
52
#define WITH_XSLT_DEBUG_EXTENSIONS
53
#endif
54
55
/************************************************************************
56
* *
57
* Private Types and Globals *
58
* *
59
************************************************************************/
60
61
typedef struct _xsltExtDef xsltExtDef;
62
typedef xsltExtDef *xsltExtDefPtr;
63
struct _xsltExtDef {
64
struct _xsltExtDef *next;
65
xmlChar *prefix;
66
xmlChar *URI;
67
void *data;
68
};
69
70
typedef struct _xsltExtModule xsltExtModule;
71
typedef xsltExtModule *xsltExtModulePtr;
72
struct _xsltExtModule {
73
xsltExtInitFunction initFunc;
74
xsltExtShutdownFunction shutdownFunc;
75
xsltStyleExtInitFunction styleInitFunc;
76
xsltStyleExtShutdownFunction styleShutdownFunc;
77
};
78
79
typedef struct _xsltExtData xsltExtData;
80
typedef xsltExtData *xsltExtDataPtr;
81
struct _xsltExtData {
82
xsltExtModulePtr extModule;
83
void *extData;
84
};
85
86
typedef struct _xsltExtElement xsltExtElement;
87
typedef xsltExtElement *xsltExtElementPtr;
88
struct _xsltExtElement {
89
xsltPreComputeFunction precomp;
90
xsltTransformFunction transform;
91
};
92
93
static xmlHashTablePtr xsltExtensionsHash = NULL;
94
static xmlHashTablePtr xsltFunctionsHash = NULL;
95
static xmlHashTablePtr xsltElementsHash = NULL;
96
static xmlHashTablePtr xsltTopLevelsHash = NULL;
97
static xmlHashTablePtr xsltModuleHash = NULL;
98
static xmlMutexPtr xsltExtMutex = NULL;
99
100
/************************************************************************
101
* *
102
* Type functions *
103
* *
104
************************************************************************/
105
106
/**
107
* xsltNewExtDef:
108
* @prefix: the extension prefix
109
* @URI: the namespace URI
110
*
111
* Create a new XSLT ExtDef
112
*
113
* Returns the newly allocated xsltExtDefPtr or NULL in case of error
114
*/
115
static xsltExtDefPtr
116
xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI)
117
{
118
xsltExtDefPtr cur;
119
120
cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef));
121
if (cur == NULL) {
122
xsltTransformError(NULL, NULL, NULL,
123
"xsltNewExtDef : malloc failed\n");
124
return (NULL);
125
}
126
memset(cur, 0, sizeof(xsltExtDef));
127
if (prefix != NULL)
128
cur->prefix = xmlStrdup(prefix);
129
if (URI != NULL)
130
cur->URI = xmlStrdup(URI);
131
return (cur);
132
}
133
134
/**
135
* xsltFreeExtDef:
136
* @extensiond: an XSLT extension definition
137
*
138
* Free up the memory allocated by @extensiond
139
*/
140
static void
141
xsltFreeExtDef(xsltExtDefPtr extensiond)
142
{
143
if (extensiond == NULL)
144
return;
145
if (extensiond->prefix != NULL)
146
xmlFree(extensiond->prefix);
147
if (extensiond->URI != NULL)
148
xmlFree(extensiond->URI);
149
xmlFree(extensiond);
150
}
151
152
/**
153
* xsltFreeExtDefList:
154
* @extensiond: an XSLT extension definition list
155
*
156
* Free up the memory allocated by all the elements of @extensiond
157
*/
158
static void
159
xsltFreeExtDefList(xsltExtDefPtr extensiond)
160
{
161
xsltExtDefPtr cur;
162
163
while (extensiond != NULL) {
164
cur = extensiond;
165
extensiond = extensiond->next;
166
xsltFreeExtDef(cur);
167
}
168
}
169
170
/**
171
* xsltNewExtModule:
172
* @initFunc: the module initialization function
173
* @shutdownFunc: the module shutdown function
174
* @styleInitFunc: the stylesheet module data allocator function
175
* @styleShutdownFunc: the stylesheet module data free function
176
*
177
* Create a new XSLT extension module
178
*
179
* Returns the newly allocated xsltExtModulePtr or NULL in case of error
180
*/
181
static xsltExtModulePtr
182
xsltNewExtModule(xsltExtInitFunction initFunc,
183
xsltExtShutdownFunction shutdownFunc,
184
xsltStyleExtInitFunction styleInitFunc,
185
xsltStyleExtShutdownFunction styleShutdownFunc)
186
{
187
xsltExtModulePtr cur;
188
189
cur = (xsltExtModulePtr) xmlMalloc(sizeof(xsltExtModule));
190
if (cur == NULL) {
191
xsltTransformError(NULL, NULL, NULL,
192
"xsltNewExtModule : malloc failed\n");
193
return (NULL);
194
}
195
cur->initFunc = initFunc;
196
cur->shutdownFunc = shutdownFunc;
197
cur->styleInitFunc = styleInitFunc;
198
cur->styleShutdownFunc = styleShutdownFunc;
199
return (cur);
200
}
201
202
/**
203
* xsltFreeExtModule:
204
* @ext: an XSLT extension module
205
*
206
* Free up the memory allocated by @ext
207
*/
208
static void
209
xsltFreeExtModule(xsltExtModulePtr ext)
210
{
211
if (ext == NULL)
212
return;
213
xmlFree(ext);
214
}
215
216
static void
217
xsltFreeExtModuleEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
218
xsltFreeExtModule((xsltExtModulePtr) payload);
219
}
220
221
/**
222
* xsltNewExtData:
223
* @extModule: the module
224
* @extData: the associated data
225
*
226
* Create a new XSLT extension module data wrapper
227
*
228
* Returns the newly allocated xsltExtDataPtr or NULL in case of error
229
*/
230
static xsltExtDataPtr
231
xsltNewExtData(xsltExtModulePtr extModule, void *extData)
232
{
233
xsltExtDataPtr cur;
234
235
if (extModule == NULL)
236
return (NULL);
237
cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData));
238
if (cur == NULL) {
239
xsltTransformError(NULL, NULL, NULL,
240
"xsltNewExtData : malloc failed\n");
241
return (NULL);
242
}
243
cur->extModule = extModule;
244
cur->extData = extData;
245
return (cur);
246
}
247
248
/**
249
* xsltFreeExtData:
250
* @ext: an XSLT extension module data wrapper
251
*
252
* Free up the memory allocated by @ext
253
*/
254
static void
255
xsltFreeExtData(xsltExtDataPtr ext)
256
{
257
if (ext == NULL)
258
return;
259
xmlFree(ext);
260
}
261
262
static void
263
xsltFreeExtDataEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
264
xsltFreeExtData((xsltExtDataPtr) payload);
265
}
266
267
/**
268
* xsltNewExtElement:
269
* @precomp: the pre-computation function
270
* @transform: the transformation function
271
*
272
* Create a new XSLT extension element
273
*
274
* Returns the newly allocated xsltExtElementPtr or NULL in case of
275
* error
276
*/
277
static xsltExtElementPtr
278
xsltNewExtElement(xsltPreComputeFunction precomp,
279
xsltTransformFunction transform)
280
{
281
xsltExtElementPtr cur;
282
283
if (transform == NULL)
284
return (NULL);
285
286
cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement));
287
if (cur == NULL) {
288
xsltTransformError(NULL, NULL, NULL,
289
"xsltNewExtElement : malloc failed\n");
290
return (NULL);
291
}
292
cur->precomp = precomp;
293
cur->transform = transform;
294
return (cur);
295
}
296
297
/**
298
* xsltFreeExtElement:
299
* @ext: an XSLT extension element
300
*
301
* Frees up the memory allocated by @ext
302
*/
303
static void
304
xsltFreeExtElement(xsltExtElementPtr ext)
305
{
306
if (ext == NULL)
307
return;
308
xmlFree(ext);
309
}
310
311
static void
312
xsltFreeExtElementEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
313
xsltFreeExtElement((xsltExtElementPtr) payload);
314
}
315
316
317
#ifdef WITH_MODULES
318
typedef void (*exsltRegisterFunction) (void);
319
320
#ifndef PATH_MAX
321
#define PATH_MAX 4096
322
#endif
323
324
/**
325
* xsltExtModuleRegisterDynamic:
326
* @URI: the function or element namespace URI
327
*
328
* Dynamically loads an extension plugin when available.
329
*
330
* The plugin name is derived from the URI by removing the
331
* initial protocol designation, e.g. "http://", then converting
332
* the characters ".", "-", "/", and "\" into "_", the removing
333
* any trailing "/", then concatenating LIBXML_MODULE_EXTENSION.
334
*
335
* Plugins are loaded from the directory specified by the
336
* environment variable LIBXSLT_PLUGINS_PATH, or if NULL,
337
* by LIBXSLT_DEFAULT_PLUGINS_PATH() which is determined at
338
* compile time.
339
*
340
* Returns 0 if successful, -1 in case of error.
341
*/
342
343
static int
344
xsltExtModuleRegisterDynamic(const xmlChar * URI)
345
{
346
void *m;
347
exsltRegisterFunction regfunc;
348
xmlChar *ext_name;
349
char module_filename[PATH_MAX];
350
const xmlChar *ext_directory = NULL;
351
const xmlChar *protocol = NULL;
352
xmlChar *i, *regfunc_name;
353
354
/* check for bad inputs */
355
if (URI == NULL)
356
return (-1);
357
358
if (NULL == xsltModuleHash) {
359
xsltModuleHash = xmlHashCreate(5);
360
if (xsltModuleHash == NULL)
361
return (-1);
362
}
363
364
xmlMutexLock(xsltExtMutex);
365
366
/* have we attempted to register this module already? */
367
if (xmlHashLookup(xsltModuleHash, URI) != NULL) {
368
xmlMutexUnlock(xsltExtMutex);
369
return (-1);
370
}
371
xmlMutexUnlock(xsltExtMutex);
372
373
/* transform extension namespace into a module name */
374
protocol = xmlStrstr(URI, BAD_CAST "://");
375
if (protocol == NULL) {
376
ext_name = xmlStrdup(URI);
377
} else {
378
ext_name = xmlStrdup(protocol + 3);
379
}
380
if (ext_name == NULL) {
381
return (-1);
382
}
383
384
i = ext_name;
385
while ('\0' != *i) {
386
if (('/' == *i) || ('\\' == *i) || ('.' == *i) || ('-' == *i))
387
*i = '_';
388
i++;
389
}
390
391
/* Strip underscores from end of string. */
392
while (i > ext_name && *(i - 1) == '_') {
393
i--;
394
*i = '\0';
395
}
396
397
/* determine module directory */
398
ext_directory = (xmlChar *) getenv("LIBXSLT_PLUGINS_PATH");
399
400
if (NULL == ext_directory) {
401
ext_directory = BAD_CAST LIBXSLT_DEFAULT_PLUGINS_PATH();
402
if (NULL == ext_directory)
403
return (-1);
404
}
405
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
406
else
407
xsltGenericDebug(xsltGenericDebugContext,
408
"LIBXSLT_PLUGINS_PATH is %s\n", ext_directory);
409
#endif
410
411
/* build the module filename, and confirm the module exists */
412
xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename),
413
"%s/%s%s", ext_directory, ext_name, MODULE_EXTENSION);
414
415
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
416
xsltGenericDebug(xsltGenericDebugContext,
417
"Attempting to load plugin: %s for URI: %s\n",
418
module_filename, URI);
419
#endif
420
421
#if LIBXML_VERSION < 21300
422
if (1 != xmlCheckFilename(module_filename)) {
423
424
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
425
xsltGenericDebug(xsltGenericDebugContext,
426
"xmlCheckFilename failed for plugin: %s\n", module_filename);
427
#endif
428
429
xmlFree(ext_name);
430
return (-1);
431
}
432
#endif
433
434
/* attempt to open the module */
435
#ifdef _WIN32
436
m = LoadLibraryA(module_filename);
437
#else
438
m = dlopen(module_filename, RTLD_LOCAL | RTLD_NOW);
439
#endif
440
if (NULL == m) {
441
442
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
443
xsltGenericDebug(xsltGenericDebugContext,
444
"dlopen failed for plugin: %s\n", module_filename);
445
#endif
446
447
xmlFree(ext_name);
448
return (-1);
449
}
450
451
/* construct initialization func name */
452
regfunc_name = xmlStrdup(ext_name);
453
regfunc_name = xmlStrcat(regfunc_name, BAD_CAST "_init");
454
455
#ifdef _WIN32
456
regfunc = (void *) GetProcAddress(m, (const char *) regfunc_name);
457
#else
458
regfunc = dlsym(m, (const char *) regfunc_name);
459
#endif
460
if (regfunc != NULL) {
461
/*
462
* Call the module's init function. Note that this function
463
* calls xsltRegisterExtModuleFull which will add the module
464
* to xsltExtensionsHash (together with it's entry points).
465
*/
466
(*regfunc) ();
467
468
/* register this module in our hash */
469
xmlMutexLock(xsltExtMutex);
470
xmlHashAddEntry(xsltModuleHash, URI, (void *) m);
471
xmlMutexUnlock(xsltExtMutex);
472
} else {
473
474
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
475
xsltGenericDebug(xsltGenericDebugContext,
476
"dlsym failed for plugin: %s, regfunc: %s\n",
477
module_filename, regfunc_name);
478
#endif
479
480
/* if regfunc not found unload the module immediately */
481
#ifdef _WIN32
482
FreeLibrary(m);
483
#else
484
dlclose(m);
485
#endif
486
}
487
488
xmlFree(ext_name);
489
xmlFree(regfunc_name);
490
return (NULL == regfunc) ? -1 : 0;
491
}
492
#else
493
static int
494
xsltExtModuleRegisterDynamic(const xmlChar * URI ATTRIBUTE_UNUSED)
495
{
496
return -1;
497
}
498
#endif
499
500
/************************************************************************
501
* *
502
* The stylesheet extension prefixes handling *
503
* *
504
************************************************************************/
505
506
507
/**
508
* xsltFreeExts:
509
* @style: an XSLT stylesheet
510
*
511
* Free up the memory used by XSLT extensions in a stylesheet
512
*/
513
void
514
xsltFreeExts(xsltStylesheetPtr style)
515
{
516
if (style->nsDefs != NULL)
517
xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs);
518
}
519
520
/**
521
* xsltRegisterExtPrefix:
522
* @style: an XSLT stylesheet
523
* @prefix: the prefix used (optional)
524
* @URI: the URI associated to the extension
525
*
526
* Registers an extension namespace
527
* This is called from xslt.c during compile-time.
528
* The given prefix is not needed.
529
* Called by:
530
* xsltParseExtElemPrefixes() (new function)
531
* xsltRegisterExtPrefix() (old function)
532
*
533
* Returns 0 in case of success, 1 if the @URI was already
534
* registered as an extension namespace and
535
* -1 in case of failure
536
*/
537
int
538
xsltRegisterExtPrefix(xsltStylesheetPtr style,
539
const xmlChar * prefix, const xmlChar * URI)
540
{
541
xsltExtDefPtr def, ret;
542
543
if ((style == NULL) || (URI == NULL))
544
return (-1);
545
546
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
547
xsltGenericDebug(xsltGenericDebugContext,
548
"Registering extension namespace '%s'.\n", URI);
549
#endif
550
def = (xsltExtDefPtr) style->nsDefs;
551
#ifdef XSLT_REFACTORED
552
/*
553
* The extension is associated with a namespace name.
554
*/
555
while (def != NULL) {
556
if (xmlStrEqual(URI, def->URI))
557
return (1);
558
def = def->next;
559
}
560
#else
561
while (def != NULL) {
562
if (xmlStrEqual(prefix, def->prefix))
563
return (-1);
564
def = def->next;
565
}
566
#endif
567
ret = xsltNewExtDef(prefix, URI);
568
if (ret == NULL)
569
return (-1);
570
ret->next = (xsltExtDefPtr) style->nsDefs;
571
style->nsDefs = ret;
572
573
/*
574
* check whether there is an extension module with a stylesheet
575
* initialization function.
576
*/
577
#ifdef XSLT_REFACTORED
578
/*
579
* Don't initialize modules based on specified namespaces via
580
* the attribute "[xsl:]extension-element-prefixes".
581
*/
582
#else
583
if (xsltExtensionsHash != NULL) {
584
xsltExtModulePtr module;
585
586
xmlMutexLock(xsltExtMutex);
587
module = xmlHashLookup(xsltExtensionsHash, URI);
588
xmlMutexUnlock(xsltExtMutex);
589
if (NULL == module) {
590
if (!xsltExtModuleRegisterDynamic(URI)) {
591
xmlMutexLock(xsltExtMutex);
592
module = xmlHashLookup(xsltExtensionsHash, URI);
593
xmlMutexUnlock(xsltExtMutex);
594
}
595
}
596
if (module != NULL) {
597
xsltStyleGetExtData(style, URI);
598
}
599
}
600
#endif
601
return (0);
602
}
603
604
/************************************************************************
605
* *
606
* The extensions modules interfaces *
607
* *
608
************************************************************************/
609
610
/**
611
* xsltRegisterExtFunction:
612
* @ctxt: an XSLT transformation context
613
* @name: the name of the element
614
* @URI: the URI associated to the element
615
* @function: the actual implementation which should be called
616
*
617
* Registers an extension function
618
*
619
* Returns 0 in case of success, -1 in case of failure
620
*/
621
int
622
xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar * name,
623
const xmlChar * URI, xmlXPathFunction function)
624
{
625
int ret;
626
627
if ((ctxt == NULL) || (name == NULL) ||
628
(URI == NULL) || (function == NULL))
629
return (-1);
630
if (ctxt->xpathCtxt != NULL) {
631
xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function);
632
}
633
if (ctxt->extFunctions == NULL)
634
ctxt->extFunctions = xmlHashCreate(10);
635
if (ctxt->extFunctions == NULL)
636
return (-1);
637
638
ret = xmlHashAddEntry2(ctxt->extFunctions, name, URI,
639
XML_CAST_FPTR(function));
640
641
return(ret);
642
}
643
644
/**
645
* xsltRegisterExtElement:
646
* @ctxt: an XSLT transformation context
647
* @name: the name of the element
648
* @URI: the URI associated to the element
649
* @function: the actual implementation which should be called
650
*
651
* Registers an extension element
652
*
653
* Returns 0 in case of success, -1 in case of failure
654
*/
655
int
656
xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar * name,
657
const xmlChar * URI, xsltTransformFunction function)
658
{
659
if ((ctxt == NULL) || (name == NULL) ||
660
(URI == NULL) || (function == NULL))
661
return (-1);
662
if (ctxt->extElements == NULL)
663
ctxt->extElements = xmlHashCreate(10);
664
if (ctxt->extElements == NULL)
665
return (-1);
666
return (xmlHashAddEntry2
667
(ctxt->extElements, name, URI, XML_CAST_FPTR(function)));
668
}
669
670
/**
671
* xsltFreeCtxtExts:
672
* @ctxt: an XSLT transformation context
673
*
674
* Free the XSLT extension data
675
*/
676
void
677
xsltFreeCtxtExts(xsltTransformContextPtr ctxt)
678
{
679
if (ctxt->extElements != NULL)
680
xmlHashFree(ctxt->extElements, NULL);
681
if (ctxt->extFunctions != NULL)
682
xmlHashFree(ctxt->extFunctions, NULL);
683
}
684
685
/**
686
* xsltStyleGetStylesheetExtData:
687
* @style: an XSLT stylesheet
688
* @URI: the URI associated to the exension module
689
*
690
* Fires the compile-time initialization callback
691
* of an extension module and returns a container
692
* holding the user-data (retrieved via the callback).
693
*
694
* Returns the create module-data container
695
* or NULL if such a module was not registered.
696
*/
697
static xsltExtDataPtr
698
xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style,
699
const xmlChar * URI)
700
{
701
xsltExtDataPtr dataContainer;
702
void *userData = NULL;
703
xsltExtModulePtr module;
704
705
if ((style == NULL) || (URI == NULL))
706
return(NULL);
707
708
if (xsltExtensionsHash == NULL) {
709
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
710
xsltGenericDebug(xsltGenericDebugContext,
711
"Not registered extension module: %s\n", URI);
712
#endif
713
return(NULL);
714
}
715
716
xmlMutexLock(xsltExtMutex);
717
718
module = xmlHashLookup(xsltExtensionsHash, URI);
719
720
xmlMutexUnlock(xsltExtMutex);
721
722
if (module == NULL) {
723
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
724
xsltGenericDebug(xsltGenericDebugContext,
725
"Not registered extension module: %s\n", URI);
726
#endif
727
return (NULL);
728
}
729
/*
730
* The specified module was registered so initialize it.
731
*/
732
if (style->extInfos == NULL) {
733
style->extInfos = xmlHashCreate(10);
734
if (style->extInfos == NULL)
735
return (NULL);
736
}
737
/*
738
* Fire the initialization callback if available.
739
*/
740
if (module->styleInitFunc == NULL) {
741
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
742
xsltGenericDebug(xsltGenericDebugContext,
743
"Initializing module with *no* callback: %s\n", URI);
744
#endif
745
} else {
746
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
747
xsltGenericDebug(xsltGenericDebugContext,
748
"Initializing module with callback: %s\n", URI);
749
#endif
750
/*
751
* Fire the initialization callback.
752
*/
753
userData = module->styleInitFunc(style, URI);
754
}
755
/*
756
* Store the user-data in the context of the given stylesheet.
757
*/
758
dataContainer = xsltNewExtData(module, userData);
759
if (dataContainer == NULL) {
760
if (module->styleShutdownFunc)
761
module->styleShutdownFunc(style, URI, userData);
762
return (NULL);
763
}
764
765
if (xmlHashAddEntry(style->extInfos, URI,
766
(void *) dataContainer) < 0)
767
{
768
xsltTransformError(NULL, style, NULL,
769
"Failed to register module '%s'.\n", URI);
770
style->errors++;
771
if (module->styleShutdownFunc)
772
module->styleShutdownFunc(style, URI, userData);
773
xsltFreeExtData(dataContainer);
774
return (NULL);
775
}
776
777
return(dataContainer);
778
}
779
780
/**
781
* xsltStyleGetExtData:
782
* @style: an XSLT stylesheet
783
* @URI: the URI associated to the exension module
784
*
785
* Retrieve the data associated to the extension module
786
* in this given stylesheet.
787
* Called by:
788
* xsltRegisterExtPrefix(),
789
* ( xsltExtElementPreCompTest(), xsltExtInitTest )
790
*
791
* Returns the pointer or NULL if not present
792
*/
793
void *
794
xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI)
795
{
796
xsltExtDataPtr dataContainer = NULL;
797
xsltStylesheetPtr tmpStyle;
798
799
if ((style == NULL) || (URI == NULL) ||
800
(xsltExtensionsHash == NULL))
801
return (NULL);
802
803
804
#ifdef XSLT_REFACTORED
805
/*
806
* This is intended for global storage, so only the main
807
* stylesheet will hold the data.
808
*/
809
tmpStyle = style;
810
while (tmpStyle->parent != NULL)
811
tmpStyle = tmpStyle->parent;
812
if (tmpStyle->extInfos != NULL) {
813
dataContainer =
814
(xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
815
if (dataContainer != NULL) {
816
/*
817
* The module was already initialized in the context
818
* of this stylesheet; just return the user-data that
819
* comes with it.
820
*/
821
return(dataContainer->extData);
822
}
823
}
824
#else
825
/*
826
* Old behaviour.
827
*/
828
tmpStyle = style;
829
if (tmpStyle->extInfos != NULL) {
830
dataContainer =
831
(xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
832
if (dataContainer != NULL) {
833
return(dataContainer->extData);
834
}
835
}
836
#endif
837
838
dataContainer =
839
xsltStyleInitializeStylesheetModule(tmpStyle, URI);
840
if (dataContainer != NULL)
841
return (dataContainer->extData);
842
return(NULL);
843
}
844
845
#ifdef XSLT_REFACTORED
846
/**
847
* xsltStyleStylesheetLevelGetExtData:
848
* @style: an XSLT stylesheet
849
* @URI: the URI associated to the exension module
850
*
851
* Retrieve the data associated to the extension module in this given
852
* stylesheet.
853
*
854
* Returns the pointer or NULL if not present
855
*/
856
void *
857
xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style,
858
const xmlChar * URI)
859
{
860
xsltExtDataPtr dataContainer = NULL;
861
862
if ((style == NULL) || (URI == NULL) ||
863
(xsltExtensionsHash == NULL))
864
return (NULL);
865
866
if (style->extInfos != NULL) {
867
dataContainer = (xsltExtDataPtr) xmlHashLookup(style->extInfos, URI);
868
/*
869
* The module was already initialized in the context
870
* of this stylesheet; just return the user-data that
871
* comes with it.
872
*/
873
if (dataContainer)
874
return(dataContainer->extData);
875
}
876
877
dataContainer =
878
xsltStyleInitializeStylesheetModule(style, URI);
879
if (dataContainer != NULL)
880
return (dataContainer->extData);
881
return(NULL);
882
}
883
#endif
884
885
/**
886
* xsltGetExtData:
887
* @ctxt: an XSLT transformation context
888
* @URI: the URI associated to the exension module
889
*
890
* Retrieve the data associated to the extension module in this given
891
* transformation.
892
*
893
* Returns the pointer or NULL if not present
894
*/
895
void *
896
xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI)
897
{
898
xsltExtDataPtr data;
899
900
if ((ctxt == NULL) || (URI == NULL))
901
return (NULL);
902
if (ctxt->extInfos == NULL) {
903
ctxt->extInfos = xmlHashCreate(10);
904
if (ctxt->extInfos == NULL)
905
return (NULL);
906
data = NULL;
907
} else {
908
data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI);
909
}
910
if (data == NULL) {
911
void *extData;
912
xsltExtModulePtr module;
913
914
xmlMutexLock(xsltExtMutex);
915
916
module = xmlHashLookup(xsltExtensionsHash, URI);
917
918
xmlMutexUnlock(xsltExtMutex);
919
920
if (module == NULL) {
921
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
922
xsltGenericDebug(xsltGenericDebugContext,
923
"Not registered extension module: %s\n", URI);
924
#endif
925
return (NULL);
926
} else {
927
if (module->initFunc == NULL)
928
return (NULL);
929
930
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
931
xsltGenericDebug(xsltGenericDebugContext,
932
"Initializing module: %s\n", URI);
933
#endif
934
935
extData = module->initFunc(ctxt, URI);
936
if (extData == NULL)
937
return (NULL);
938
939
data = xsltNewExtData(module, extData);
940
if ((data == NULL) ||
941
(xmlHashAddEntry(ctxt->extInfos, URI, (void *) data) < 0)) {
942
xsltTransformError(ctxt, NULL, NULL,
943
"Failed to register module data: %s\n",
944
URI);
945
if (module->shutdownFunc)
946
module->shutdownFunc(ctxt, URI, extData);
947
xsltFreeExtData(data);
948
return (NULL);
949
}
950
}
951
}
952
return (data->extData);
953
}
954
955
typedef struct _xsltInitExtCtxt xsltInitExtCtxt;
956
struct _xsltInitExtCtxt {
957
xsltTransformContextPtr ctxt;
958
int ret;
959
};
960
961
/**
962
* xsltInitCtxtExt:
963
* @styleData: the registered stylesheet data for the module
964
* @ctxt: the XSLT transformation context + the return value
965
* @URI: the extension URI
966
*
967
* Initializes an extension module
968
*/
969
static void
970
xsltInitCtxtExt(void *payload, void *data, const xmlChar * URI)
971
{
972
xsltExtDataPtr styleData = (xsltExtDataPtr) payload;
973
xsltInitExtCtxt *ctxt = (xsltInitExtCtxt *) data;
974
xsltExtModulePtr module;
975
xsltExtDataPtr ctxtData;
976
void *extData;
977
978
if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) ||
979
(ctxt->ret == -1)) {
980
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
981
xsltGenericDebug(xsltGenericDebugContext,
982
"xsltInitCtxtExt: NULL param or error\n");
983
#endif
984
return;
985
}
986
module = styleData->extModule;
987
if ((module == NULL) || (module->initFunc == NULL)) {
988
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
989
xsltGenericDebug(xsltGenericDebugContext,
990
"xsltInitCtxtExt: no module or no initFunc\n");
991
#endif
992
return;
993
}
994
995
ctxtData = (xsltExtDataPtr) xmlHashLookup(ctxt->ctxt->extInfos, URI);
996
if (ctxtData != NULL) {
997
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
998
xsltGenericDebug(xsltGenericDebugContext,
999
"xsltInitCtxtExt: already initialized\n");
1000
#endif
1001
return;
1002
}
1003
1004
extData = module->initFunc(ctxt->ctxt, URI);
1005
if (extData == NULL) {
1006
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
1007
xsltGenericDebug(xsltGenericDebugContext,
1008
"xsltInitCtxtExt: no extData\n");
1009
#endif
1010
}
1011
ctxtData = xsltNewExtData(module, extData);
1012
if (ctxtData == NULL) {
1013
if (module->shutdownFunc)
1014
module->shutdownFunc(ctxt->ctxt, URI, extData);
1015
ctxt->ret = -1;
1016
return;
1017
}
1018
1019
if (ctxt->ctxt->extInfos == NULL)
1020
ctxt->ctxt->extInfos = xmlHashCreate(10);
1021
if (ctxt->ctxt->extInfos == NULL) {
1022
if (module->shutdownFunc)
1023
module->shutdownFunc(ctxt->ctxt, URI, extData);
1024
xsltFreeExtData(ctxtData);
1025
ctxt->ret = -1;
1026
return;
1027
}
1028
1029
if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) {
1030
xsltGenericError(xsltGenericErrorContext,
1031
"Failed to register module data: %s\n", URI);
1032
if (module->shutdownFunc)
1033
module->shutdownFunc(ctxt->ctxt, URI, extData);
1034
xsltFreeExtData(ctxtData);
1035
ctxt->ret = -1;
1036
return;
1037
}
1038
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
1039
xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n",
1040
URI);
1041
#endif
1042
ctxt->ret++;
1043
}
1044
1045
/**
1046
* xsltInitCtxtExts:
1047
* @ctxt: an XSLT transformation context
1048
*
1049
* Initialize the set of modules with registered stylesheet data
1050
*
1051
* Returns the number of modules initialized or -1 in case of error
1052
*/
1053
int
1054
xsltInitCtxtExts(xsltTransformContextPtr ctxt)
1055
{
1056
xsltStylesheetPtr style;
1057
xsltInitExtCtxt ctx;
1058
1059
if (ctxt == NULL)
1060
return (-1);
1061
1062
style = ctxt->style;
1063
if (style == NULL)
1064
return (-1);
1065
1066
ctx.ctxt = ctxt;
1067
ctx.ret = 0;
1068
1069
while (style != NULL) {
1070
if (style->extInfos != NULL) {
1071
xmlHashScan(style->extInfos, xsltInitCtxtExt, &ctx);
1072
if (ctx.ret == -1)
1073
return (-1);
1074
}
1075
style = xsltNextImport(style);
1076
}
1077
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
1078
xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n",
1079
ctx.ret);
1080
#endif
1081
return (ctx.ret);
1082
}
1083
1084
/**
1085
* xsltShutdownCtxtExt:
1086
* @data: the registered data for the module
1087
* @ctxt: the XSLT transformation context
1088
* @URI: the extension URI
1089
*
1090
* Shutdown an extension module loaded
1091
*/
1092
static void
1093
xsltShutdownCtxtExt(void *payload, void *vctxt, const xmlChar * URI)
1094
{
1095
xsltExtDataPtr data = (xsltExtDataPtr) payload;
1096
xsltTransformContextPtr ctxt = (xsltTransformContextPtr) vctxt;
1097
xsltExtModulePtr module;
1098
1099
if ((data == NULL) || (ctxt == NULL) || (URI == NULL))
1100
return;
1101
module = data->extModule;
1102
if ((module == NULL) || (module->shutdownFunc == NULL))
1103
return;
1104
1105
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
1106
xsltGenericDebug(xsltGenericDebugContext,
1107
"Shutting down module : %s\n", URI);
1108
#endif
1109
module->shutdownFunc(ctxt, URI, data->extData);
1110
}
1111
1112
/**
1113
* xsltShutdownCtxtExts:
1114
* @ctxt: an XSLT transformation context
1115
*
1116
* Shutdown the set of modules loaded
1117
*/
1118
void
1119
xsltShutdownCtxtExts(xsltTransformContextPtr ctxt)
1120
{
1121
if (ctxt == NULL)
1122
return;
1123
if (ctxt->extInfos == NULL)
1124
return;
1125
xmlHashScan(ctxt->extInfos, xsltShutdownCtxtExt, ctxt);
1126
xmlHashFree(ctxt->extInfos, xsltFreeExtDataEntry);
1127
ctxt->extInfos = NULL;
1128
}
1129
1130
/**
1131
* xsltShutdownExt:
1132
* @data: the registered data for the module
1133
* @ctxt: the XSLT stylesheet
1134
* @URI: the extension URI
1135
*
1136
* Shutdown an extension module loaded
1137
*/
1138
static void
1139
xsltShutdownExt(void *payload, void *vctxt, const xmlChar * URI)
1140
{
1141
xsltExtDataPtr data = (xsltExtDataPtr) payload;
1142
xsltStylesheetPtr style = (xsltStylesheetPtr) vctxt;
1143
xsltExtModulePtr module;
1144
1145
if ((data == NULL) || (style == NULL) || (URI == NULL))
1146
return;
1147
module = data->extModule;
1148
if ((module == NULL) || (module->styleShutdownFunc == NULL))
1149
return;
1150
1151
#ifdef WITH_XSLT_DEBUG_EXTENSIONS
1152
xsltGenericDebug(xsltGenericDebugContext,
1153
"Shutting down module : %s\n", URI);
1154
#endif
1155
module->styleShutdownFunc(style, URI, data->extData);
1156
/*
1157
* Don't remove the entry from the hash table here, since
1158
* this will produce segfaults - this fixes bug #340624.
1159
*
1160
* xmlHashRemoveEntry(style->extInfos, URI, xsltFreeExtDataEntry);
1161
*/
1162
}
1163
1164
/**
1165
* xsltShutdownExts:
1166
* @style: an XSLT stylesheet
1167
*
1168
* Shutdown the set of modules loaded
1169
*/
1170
void
1171
xsltShutdownExts(xsltStylesheetPtr style)
1172
{
1173
if (style == NULL)
1174
return;
1175
if (style->extInfos == NULL)
1176
return;
1177
xmlHashScan(style->extInfos, xsltShutdownExt, style);
1178
xmlHashFree(style->extInfos, xsltFreeExtDataEntry);
1179
style->extInfos = NULL;
1180
}
1181
1182
/**
1183
* xsltCheckExtPrefix:
1184
* @style: the stylesheet
1185
* @URI: the namespace prefix (possibly NULL)
1186
*
1187
* Check if the given prefix is one of the declared extensions.
1188
* This is intended to be called only at compile-time.
1189
* Called by:
1190
* xsltGetInheritedNsList() (xslt.c)
1191
* xsltParseTemplateContent (xslt.c)
1192
*
1193
* Returns 1 if this is an extension, 0 otherwise
1194
*/
1195
int
1196
xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * URI)
1197
{
1198
#ifdef XSLT_REFACTORED
1199
if ((style == NULL) || (style->compCtxt == NULL) ||
1200
(XSLT_CCTXT(style)->inode == NULL) ||
1201
(XSLT_CCTXT(style)->inode->extElemNs == NULL))
1202
return (0);
1203
/*
1204
* Lookup the extension namespaces registered
1205
* at the current node in the stylesheet's tree.
1206
*/
1207
if (XSLT_CCTXT(style)->inode->extElemNs != NULL) {
1208
int i;
1209
xsltPointerListPtr list = XSLT_CCTXT(style)->inode->extElemNs;
1210
1211
for (i = 0; i < list->number; i++) {
1212
if (xmlStrEqual((const xmlChar *) list->items[i],
1213
URI))
1214
{
1215
return(1);
1216
}
1217
}
1218
}
1219
#else
1220
xsltExtDefPtr cur;
1221
1222
if ((style == NULL) || (style->nsDefs == NULL))
1223
return (0);
1224
if (URI == NULL)
1225
URI = BAD_CAST "#default";
1226
cur = (xsltExtDefPtr) style->nsDefs;
1227
while (cur != NULL) {
1228
/*
1229
* NOTE: This was change to work on namespace names rather
1230
* than namespace prefixes. This fixes bug #339583.
1231
* TODO: Consider renaming the field "prefix" of xsltExtDef
1232
* to "href".
1233
*/
1234
if (xmlStrEqual(URI, cur->prefix))
1235
return (1);
1236
cur = cur->next;
1237
}
1238
#endif
1239
return (0);
1240
}
1241
1242
/**
1243
* xsltCheckExtURI:
1244
* @style: the stylesheet
1245
* @URI: the namespace URI (possibly NULL)
1246
*
1247
* Check if the given prefix is one of the declared extensions.
1248
* This is intended to be called only at compile-time.
1249
* Called by:
1250
* xsltPrecomputeStylesheet() (xslt.c)
1251
* xsltParseTemplateContent (xslt.c)
1252
*
1253
* Returns 1 if this is an extension, 0 otherwise
1254
*/
1255
int
1256
xsltCheckExtURI(xsltStylesheetPtr style, const xmlChar * URI)
1257
{
1258
xsltExtDefPtr cur;
1259
1260
if ((style == NULL) || (style->nsDefs == NULL))
1261
return (0);
1262
if (URI == NULL)
1263
return (0);
1264
cur = (xsltExtDefPtr) style->nsDefs;
1265
while (cur != NULL) {
1266
if (xmlStrEqual(URI, cur->URI))
1267
return (1);
1268
cur = cur->next;
1269
}
1270
return (0);
1271
}
1272
1273
/**
1274
* xsltRegisterExtModuleFull:
1275
* @URI: URI associated to this module
1276
* @initFunc: the module initialization function
1277
* @shutdownFunc: the module shutdown function
1278
* @styleInitFunc: the module initialization function
1279
* @styleShutdownFunc: the module shutdown function
1280
*
1281
* Register an XSLT extension module to the library.
1282
*
1283
* Returns 0 if sucessful, -1 in case of error
1284
*/
1285
int
1286
xsltRegisterExtModuleFull(const xmlChar * URI,
1287
xsltExtInitFunction initFunc,
1288
xsltExtShutdownFunction shutdownFunc,
1289
xsltStyleExtInitFunction styleInitFunc,
1290
xsltStyleExtShutdownFunction styleShutdownFunc)
1291
{
1292
int ret;
1293
xsltExtModulePtr module;
1294
1295
if ((URI == NULL) || (initFunc == NULL))
1296
return (-1);
1297
if (xsltExtensionsHash == NULL)
1298
xsltExtensionsHash = xmlHashCreate(10);
1299
1300
if (xsltExtensionsHash == NULL)
1301
return (-1);
1302
1303
xmlMutexLock(xsltExtMutex);
1304
1305
module = xmlHashLookup(xsltExtensionsHash, URI);
1306
if (module != NULL) {
1307
if ((module->initFunc == initFunc) &&
1308
(module->shutdownFunc == shutdownFunc))
1309
ret = 0;
1310
else
1311
ret = -1;
1312
goto done;
1313
}
1314
module = xsltNewExtModule(initFunc, shutdownFunc,
1315
styleInitFunc, styleShutdownFunc);
1316
if (module == NULL) {
1317
ret = -1;
1318
goto done;
1319
}
1320
ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module);
1321
1322
done:
1323
xmlMutexUnlock(xsltExtMutex);
1324
return (ret);
1325
}
1326
1327
/**
1328
* xsltRegisterExtModule:
1329
* @URI: URI associated to this module
1330
* @initFunc: the module initialization function
1331
* @shutdownFunc: the module shutdown function
1332
*
1333
* Register an XSLT extension module to the library.
1334
*
1335
* Returns 0 if sucessful, -1 in case of error
1336
*/
1337
int
1338
xsltRegisterExtModule(const xmlChar * URI,
1339
xsltExtInitFunction initFunc,
1340
xsltExtShutdownFunction shutdownFunc)
1341
{
1342
return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc,
1343
NULL, NULL);
1344
}
1345
1346
/**
1347
* xsltUnregisterExtModule:
1348
* @URI: URI associated to this module
1349
*
1350
* Unregister an XSLT extension module from the library.
1351
*
1352
* Returns 0 if sucessful, -1 in case of error
1353
*/
1354
int
1355
xsltUnregisterExtModule(const xmlChar * URI)
1356
{
1357
int ret;
1358
1359
if (URI == NULL)
1360
return (-1);
1361
if (xsltExtensionsHash == NULL)
1362
return (-1);
1363
1364
xmlMutexLock(xsltExtMutex);
1365
1366
ret = xmlHashRemoveEntry(xsltExtensionsHash, URI, xsltFreeExtModuleEntry);
1367
1368
xmlMutexUnlock(xsltExtMutex);
1369
1370
return (ret);
1371
}
1372
1373
/**
1374
* xsltUnregisterAllExtModules:
1375
*
1376
* Unregister all the XSLT extension module from the library.
1377
*/
1378
static void
1379
xsltUnregisterAllExtModules(void)
1380
{
1381
if (xsltExtensionsHash == NULL)
1382
return;
1383
1384
xmlMutexLock(xsltExtMutex);
1385
1386
xmlHashFree(xsltExtensionsHash, xsltFreeExtModuleEntry);
1387
xsltExtensionsHash = NULL;
1388
1389
xmlMutexUnlock(xsltExtMutex);
1390
}
1391
1392
/**
1393
* xsltXPathGetTransformContext:
1394
* @ctxt: an XPath transformation context
1395
*
1396
* Provides the XSLT transformation context from the XPath transformation
1397
* context. This is useful when an XPath function in the extension module
1398
* is called by the XPath interpreter and that the XSLT context is needed
1399
* for example to retrieve the associated data pertaining to this XSLT
1400
* transformation.
1401
*
1402
* Returns the XSLT transformation context or NULL in case of error.
1403
*/
1404
xsltTransformContextPtr
1405
xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
1406
{
1407
if ((ctxt == NULL) || (ctxt->context == NULL))
1408
return (NULL);
1409
return (ctxt->context->extra);
1410
}
1411
1412
/**
1413
* xsltRegisterExtModuleFunction:
1414
* @name: the function name
1415
* @URI: the function namespace URI
1416
* @function: the function callback
1417
*
1418
* Registers an extension module function.
1419
*
1420
* Returns 0 if successful, -1 in case of error.
1421
*/
1422
int
1423
xsltRegisterExtModuleFunction(const xmlChar * name, const xmlChar * URI,
1424
xmlXPathFunction function)
1425
{
1426
if ((name == NULL) || (URI == NULL) || (function == NULL))
1427
return (-1);
1428
1429
if (xsltFunctionsHash == NULL)
1430
xsltFunctionsHash = xmlHashCreate(10);
1431
if (xsltFunctionsHash == NULL)
1432
return (-1);
1433
1434
xmlMutexLock(xsltExtMutex);
1435
1436
xmlHashUpdateEntry2(xsltFunctionsHash, name, URI,
1437
XML_CAST_FPTR(function), NULL);
1438
1439
xmlMutexUnlock(xsltExtMutex);
1440
1441
return (0);
1442
}
1443
1444
/**
1445
* xsltExtModuleFunctionLookup:
1446
* @name: the function name
1447
* @URI: the function namespace URI
1448
*
1449
* Looks up an extension module function
1450
*
1451
* Returns the function if found, NULL otherwise.
1452
*/
1453
xmlXPathFunction
1454
xsltExtModuleFunctionLookup(const xmlChar * name, const xmlChar * URI)
1455
{
1456
xmlXPathFunction ret;
1457
1458
if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
1459
return (NULL);
1460
1461
xmlMutexLock(xsltExtMutex);
1462
1463
XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI);
1464
1465
xmlMutexUnlock(xsltExtMutex);
1466
1467
/* if lookup fails, attempt a dynamic load on supported platforms */
1468
if (NULL == ret) {
1469
if (!xsltExtModuleRegisterDynamic(URI)) {
1470
xmlMutexLock(xsltExtMutex);
1471
1472
XML_CAST_FPTR(ret) =
1473
xmlHashLookup2(xsltFunctionsHash, name, URI);
1474
1475
xmlMutexUnlock(xsltExtMutex);
1476
}
1477
}
1478
1479
return ret;
1480
}
1481
1482
/**
1483
* xsltUnregisterExtModuleFunction:
1484
* @name: the function name
1485
* @URI: the function namespace URI
1486
*
1487
* Unregisters an extension module function
1488
*
1489
* Returns 0 if successful, -1 in case of error.
1490
*/
1491
int
1492
xsltUnregisterExtModuleFunction(const xmlChar * name, const xmlChar * URI)
1493
{
1494
int ret;
1495
1496
if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
1497
return (-1);
1498
1499
xmlMutexLock(xsltExtMutex);
1500
1501
ret = xmlHashRemoveEntry2(xsltFunctionsHash, name, URI, NULL);
1502
1503
xmlMutexUnlock(xsltExtMutex);
1504
1505
return(ret);
1506
}
1507
1508
/**
1509
* xsltUnregisterAllExtModuleFunction:
1510
*
1511
* Unregisters all extension module function
1512
*/
1513
static void
1514
xsltUnregisterAllExtModuleFunction(void)
1515
{
1516
xmlMutexLock(xsltExtMutex);
1517
1518
xmlHashFree(xsltFunctionsHash, NULL);
1519
xsltFunctionsHash = NULL;
1520
1521
xmlMutexUnlock(xsltExtMutex);
1522
}
1523
1524
1525
static void
1526
xsltFreeElemPreComp(xsltElemPreCompPtr comp) {
1527
xmlFree(comp);
1528
}
1529
1530
/**
1531
* xsltNewElemPreComp:
1532
* @style: the XSLT stylesheet
1533
* @inst: the element node
1534
* @function: the transform function
1535
*
1536
* Creates and initializes an #xsltElemPreComp
1537
*
1538
* Returns the new and initialized #xsltElemPreComp
1539
*/
1540
xsltElemPreCompPtr
1541
xsltNewElemPreComp(xsltStylesheetPtr style, xmlNodePtr inst,
1542
xsltTransformFunction function)
1543
{
1544
xsltElemPreCompPtr cur;
1545
1546
cur = (xsltElemPreCompPtr) xmlMalloc(sizeof(xsltElemPreComp));
1547
if (cur == NULL) {
1548
xsltTransformError(NULL, style, NULL,
1549
"xsltNewExtElement : malloc failed\n");
1550
return (NULL);
1551
}
1552
memset(cur, 0, sizeof(xsltElemPreComp));
1553
1554
xsltInitElemPreComp(cur, style, inst, function, xsltFreeElemPreComp);
1555
1556
return (cur);
1557
}
1558
1559
/**
1560
* xsltInitElemPreComp:
1561
* @comp: an #xsltElemPreComp (or generally a derived structure)
1562
* @style: the XSLT stylesheet
1563
* @inst: the element node
1564
* @function: the transform function
1565
* @freeFunc: the @comp deallocator
1566
*
1567
* Initializes an existing #xsltElemPreComp structure. This is usefull
1568
* when extending an #xsltElemPreComp to store precomputed data.
1569
* This function MUST be called on any extension element precomputed
1570
* data struct.
1571
*/
1572
void
1573
xsltInitElemPreComp(xsltElemPreCompPtr comp, xsltStylesheetPtr style,
1574
xmlNodePtr inst, xsltTransformFunction function,
1575
xsltElemPreCompDeallocator freeFunc)
1576
{
1577
comp->type = XSLT_FUNC_EXTENSION;
1578
comp->func = function;
1579
comp->inst = inst;
1580
comp->free = freeFunc;
1581
1582
comp->next = style->preComps;
1583
style->preComps = comp;
1584
}
1585
1586
/**
1587
* xsltPreComputeExtModuleElement:
1588
* @style: the stylesheet
1589
* @inst: the element node
1590
*
1591
* Precomputes an extension module element
1592
*
1593
* Returns the precomputed data
1594
*/
1595
xsltElemPreCompPtr
1596
xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst)
1597
{
1598
xsltExtElementPtr ext;
1599
xsltElemPreCompPtr comp = NULL;
1600
1601
if ((style == NULL) || (inst == NULL) ||
1602
(inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL))
1603
return (NULL);
1604
1605
xmlMutexLock(xsltExtMutex);
1606
1607
ext = (xsltExtElementPtr)
1608
xmlHashLookup2(xsltElementsHash, inst->name, inst->ns->href);
1609
1610
xmlMutexUnlock(xsltExtMutex);
1611
1612
/*
1613
* EXT TODO: Now what?
1614
*/
1615
if (ext == NULL)
1616
return (NULL);
1617
1618
if (ext->precomp != NULL) {
1619
/*
1620
* REVISIT TODO: Check if the text below is correct.
1621
* This will return a xsltElemPreComp structure or NULL.
1622
* 1) If the the author of the extension needs a
1623
* custom structure to hold the specific values of
1624
* this extension, he will derive a structure based on
1625
* xsltElemPreComp; thus we obviously *cannot* refactor
1626
* the xsltElemPreComp structure, since all already derived
1627
* user-defined strucures will break.
1628
* Example: For the extension xsl:document,
1629
* in xsltDocumentComp() (preproc.c), the structure
1630
* xsltStyleItemDocument is allocated, filled with
1631
* specific values and returned.
1632
* 2) If the author needs no values to be stored in
1633
* this structure, then he'll return NULL;
1634
*/
1635
comp = ext->precomp(style, inst, ext->transform);
1636
}
1637
if (comp == NULL) {
1638
/*
1639
* Default creation of a xsltElemPreComp structure, if
1640
* the author of this extension did not create a custom
1641
* structure.
1642
*/
1643
comp = xsltNewElemPreComp(style, inst, ext->transform);
1644
}
1645
1646
return (comp);
1647
}
1648
1649
/**
1650
* xsltRegisterExtModuleElement:
1651
* @name: the element name
1652
* @URI: the element namespace URI
1653
* @precomp: the pre-computation callback
1654
* @transform: the transformation callback
1655
*
1656
* Registers an extension module element.
1657
*
1658
* Returns 0 if successful, -1 in case of error.
1659
*/
1660
int
1661
xsltRegisterExtModuleElement(const xmlChar * name, const xmlChar * URI,
1662
xsltPreComputeFunction precomp,
1663
xsltTransformFunction transform)
1664
{
1665
int ret = 0;
1666
1667
xsltExtElementPtr ext;
1668
1669
if ((name == NULL) || (URI == NULL) || (transform == NULL))
1670
return (-1);
1671
1672
if (xsltElementsHash == NULL)
1673
xsltElementsHash = xmlHashCreate(10);
1674
if (xsltElementsHash == NULL)
1675
return (-1);
1676
1677
xmlMutexLock(xsltExtMutex);
1678
1679
ext = xsltNewExtElement(precomp, transform);
1680
if (ext == NULL) {
1681
ret = -1;
1682
goto done;
1683
}
1684
1685
xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext,
1686
xsltFreeExtElementEntry);
1687
1688
done:
1689
xmlMutexUnlock(xsltExtMutex);
1690
1691
return (ret);
1692
}
1693
1694
/**
1695
* xsltExtElementLookup:
1696
* @ctxt: an XSLT process context
1697
* @name: the element name
1698
* @URI: the element namespace URI
1699
*
1700
* Looks up an extension element. @ctxt can be NULL to search only in
1701
* module elements.
1702
*
1703
* Returns the element callback or NULL if not found
1704
*/
1705
xsltTransformFunction
1706
xsltExtElementLookup(xsltTransformContextPtr ctxt,
1707
const xmlChar * name, const xmlChar * URI)
1708
{
1709
xsltTransformFunction ret;
1710
1711
if ((name == NULL) || (URI == NULL))
1712
return (NULL);
1713
1714
if ((ctxt != NULL) && (ctxt->extElements != NULL)) {
1715
XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->extElements, name, URI);
1716
if (ret != NULL) {
1717
return(ret);
1718
}
1719
}
1720
1721
ret = xsltExtModuleElementLookup(name, URI);
1722
1723
return (ret);
1724
}
1725
1726
/**
1727
* xsltExtModuleElementLookup:
1728
* @name: the element name
1729
* @URI: the element namespace URI
1730
*
1731
* Looks up an extension module element
1732
*
1733
* Returns the callback function if found, NULL otherwise.
1734
*/
1735
xsltTransformFunction
1736
xsltExtModuleElementLookup(const xmlChar * name, const xmlChar * URI)
1737
{
1738
xsltExtElementPtr ext;
1739
1740
if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1741
return (NULL);
1742
1743
xmlMutexLock(xsltExtMutex);
1744
1745
ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1746
1747
xmlMutexUnlock(xsltExtMutex);
1748
1749
/*
1750
* if function lookup fails, attempt a dynamic load on
1751
* supported platforms
1752
*/
1753
if (NULL == ext) {
1754
if (!xsltExtModuleRegisterDynamic(URI)) {
1755
xmlMutexLock(xsltExtMutex);
1756
1757
ext = (xsltExtElementPtr)
1758
xmlHashLookup2(xsltElementsHash, name, URI);
1759
1760
xmlMutexUnlock(xsltExtMutex);
1761
}
1762
}
1763
1764
if (ext == NULL)
1765
return (NULL);
1766
return (ext->transform);
1767
}
1768
1769
/**
1770
* xsltExtModuleElementPreComputeLookup:
1771
* @name: the element name
1772
* @URI: the element namespace URI
1773
*
1774
* Looks up an extension module element pre-computation function
1775
*
1776
* Returns the callback function if found, NULL otherwise.
1777
*/
1778
xsltPreComputeFunction
1779
xsltExtModuleElementPreComputeLookup(const xmlChar * name,
1780
const xmlChar * URI)
1781
{
1782
xsltExtElementPtr ext;
1783
1784
if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1785
return (NULL);
1786
1787
xmlMutexLock(xsltExtMutex);
1788
1789
ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1790
1791
xmlMutexUnlock(xsltExtMutex);
1792
1793
if (ext == NULL) {
1794
if (!xsltExtModuleRegisterDynamic(URI)) {
1795
xmlMutexLock(xsltExtMutex);
1796
1797
ext = (xsltExtElementPtr)
1798
xmlHashLookup2(xsltElementsHash, name, URI);
1799
1800
xmlMutexUnlock(xsltExtMutex);
1801
}
1802
}
1803
1804
if (ext == NULL)
1805
return (NULL);
1806
return (ext->precomp);
1807
}
1808
1809
/**
1810
* xsltUnregisterExtModuleElement:
1811
* @name: the element name
1812
* @URI: the element namespace URI
1813
*
1814
* Unregisters an extension module element
1815
*
1816
* Returns 0 if successful, -1 in case of error.
1817
*/
1818
int
1819
xsltUnregisterExtModuleElement(const xmlChar * name, const xmlChar * URI)
1820
{
1821
int ret;
1822
1823
if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1824
return (-1);
1825
1826
xmlMutexLock(xsltExtMutex);
1827
1828
ret = xmlHashRemoveEntry2(xsltElementsHash, name, URI,
1829
xsltFreeExtElementEntry);
1830
1831
xmlMutexUnlock(xsltExtMutex);
1832
1833
return(ret);
1834
}
1835
1836
/**
1837
* xsltUnregisterAllExtModuleElement:
1838
*
1839
* Unregisters all extension module element
1840
*/
1841
static void
1842
xsltUnregisterAllExtModuleElement(void)
1843
{
1844
xmlMutexLock(xsltExtMutex);
1845
1846
xmlHashFree(xsltElementsHash, xsltFreeExtElementEntry);
1847
xsltElementsHash = NULL;
1848
1849
xmlMutexUnlock(xsltExtMutex);
1850
}
1851
1852
/**
1853
* xsltRegisterExtModuleTopLevel:
1854
* @name: the top-level element name
1855
* @URI: the top-level element namespace URI
1856
* @function: the top-level element callback
1857
*
1858
* Registers an extension module top-level element.
1859
*
1860
* Returns 0 if successful, -1 in case of error.
1861
*/
1862
int
1863
xsltRegisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI,
1864
xsltTopLevelFunction function)
1865
{
1866
if ((name == NULL) || (URI == NULL) || (function == NULL))
1867
return (-1);
1868
1869
if (xsltTopLevelsHash == NULL)
1870
xsltTopLevelsHash = xmlHashCreate(10);
1871
if (xsltTopLevelsHash == NULL)
1872
return (-1);
1873
1874
xmlMutexLock(xsltExtMutex);
1875
1876
xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI,
1877
XML_CAST_FPTR(function), NULL);
1878
1879
xmlMutexUnlock(xsltExtMutex);
1880
1881
return (0);
1882
}
1883
1884
/**
1885
* xsltExtModuleTopLevelLookup:
1886
* @name: the top-level element name
1887
* @URI: the top-level element namespace URI
1888
*
1889
* Looks up an extension module top-level element
1890
*
1891
* Returns the callback function if found, NULL otherwise.
1892
*/
1893
xsltTopLevelFunction
1894
xsltExtModuleTopLevelLookup(const xmlChar * name, const xmlChar * URI)
1895
{
1896
xsltTopLevelFunction ret;
1897
1898
if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1899
return (NULL);
1900
1901
xmlMutexLock(xsltExtMutex);
1902
1903
XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
1904
1905
xmlMutexUnlock(xsltExtMutex);
1906
1907
/* if lookup fails, attempt a dynamic load on supported platforms */
1908
if (NULL == ret) {
1909
if (!xsltExtModuleRegisterDynamic(URI)) {
1910
xmlMutexLock(xsltExtMutex);
1911
1912
XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
1913
1914
xmlMutexUnlock(xsltExtMutex);
1915
}
1916
}
1917
1918
return (ret);
1919
}
1920
1921
/**
1922
* xsltUnregisterExtModuleTopLevel:
1923
* @name: the top-level element name
1924
* @URI: the top-level element namespace URI
1925
*
1926
* Unregisters an extension module top-level element
1927
*
1928
* Returns 0 if successful, -1 in case of error.
1929
*/
1930
int
1931
xsltUnregisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI)
1932
{
1933
int ret;
1934
1935
if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1936
return (-1);
1937
1938
xmlMutexLock(xsltExtMutex);
1939
1940
ret = xmlHashRemoveEntry2(xsltTopLevelsHash, name, URI, NULL);
1941
1942
xmlMutexUnlock(xsltExtMutex);
1943
1944
return(ret);
1945
}
1946
1947
/**
1948
* xsltUnregisterAllExtModuleTopLevel:
1949
*
1950
* Unregisters all extension module function
1951
*/
1952
static void
1953
xsltUnregisterAllExtModuleTopLevel(void)
1954
{
1955
xmlMutexLock(xsltExtMutex);
1956
1957
xmlHashFree(xsltTopLevelsHash, NULL);
1958
xsltTopLevelsHash = NULL;
1959
1960
xmlMutexUnlock(xsltExtMutex);
1961
}
1962
1963
/**
1964
* xsltGetExtInfo:
1965
* @style: pointer to a stylesheet
1966
* @URI: the namespace URI desired
1967
*
1968
* looks up URI in extInfos of the stylesheet
1969
*
1970
* returns a pointer to the hash table if found, else NULL
1971
*/
1972
xmlHashTablePtr
1973
xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI)
1974
{
1975
xsltExtDataPtr data;
1976
1977
/*
1978
* TODO: Why do we have a return type of xmlHashTablePtr?
1979
* Is the user-allocated data for extension modules expected
1980
* to be a xmlHashTablePtr only? Or is this intended for
1981
* the EXSLT module only?
1982
*/
1983
1984
if (style != NULL && style->extInfos != NULL) {
1985
data = xmlHashLookup(style->extInfos, URI);
1986
if (data != NULL && data->extData != NULL)
1987
return data->extData;
1988
}
1989
return NULL;
1990
}
1991
1992
/************************************************************************
1993
* *
1994
* Test of the extension module API *
1995
* *
1996
************************************************************************/
1997
1998
static xmlChar *testData = NULL;
1999
static xmlChar *testStyleData = NULL;
2000
2001
/**
2002
* xsltExtFunctionTest:
2003
* @ctxt: the XPath Parser context
2004
* @nargs: the number of arguments
2005
*
2006
* function libxslt:test() for testing the extensions support.
2007
*/
2008
static void
2009
xsltExtFunctionTest(xmlXPathParserContextPtr ctxt,
2010
int nargs ATTRIBUTE_UNUSED)
2011
{
2012
xsltTransformContextPtr tctxt;
2013
void *data = NULL;
2014
2015
tctxt = xsltXPathGetTransformContext(ctxt);
2016
2017
if (testData == NULL) {
2018
xsltGenericDebug(xsltGenericDebugContext,
2019
"xsltExtFunctionTest: not initialized,"
2020
" calling xsltGetExtData\n");
2021
data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
2022
if (data == NULL) {
2023
xsltTransformError(tctxt, NULL, NULL,
2024
"xsltExtElementTest: not initialized\n");
2025
return;
2026
}
2027
}
2028
if (tctxt == NULL) {
2029
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2030
"xsltExtFunctionTest: failed to get the transformation context\n");
2031
return;
2032
}
2033
if (data == NULL)
2034
data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
2035
if (data == NULL) {
2036
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2037
"xsltExtFunctionTest: failed to get module data\n");
2038
return;
2039
}
2040
if (data != testData) {
2041
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
2042
"xsltExtFunctionTest: got wrong module data\n");
2043
return;
2044
}
2045
#ifdef WITH_XSLT_DEBUG_FUNCTION
2046
xsltGenericDebug(xsltGenericDebugContext,
2047
"libxslt:test() called with %d args\n", nargs);
2048
#endif
2049
}
2050
2051
/**
2052
* xsltExtElementPreCompTest:
2053
* @style: the stylesheet
2054
* @inst: the instruction in the stylesheet
2055
*
2056
* Process a libxslt:test node
2057
*/
2058
static xsltElemPreCompPtr
2059
xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst,
2060
xsltTransformFunction function)
2061
{
2062
xsltElemPreCompPtr ret;
2063
2064
if (style == NULL) {
2065
xsltTransformError(NULL, NULL, inst,
2066
"xsltExtElementTest: no transformation context\n");
2067
return (NULL);
2068
}
2069
if (testStyleData == NULL) {
2070
xsltGenericDebug(xsltGenericDebugContext,
2071
"xsltExtElementPreCompTest: not initialized,"
2072
" calling xsltStyleGetExtData\n");
2073
xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL);
2074
if (testStyleData == NULL) {
2075
xsltTransformError(NULL, style, inst,
2076
"xsltExtElementPreCompTest: not initialized\n");
2077
if (style != NULL)
2078
style->errors++;
2079
return (NULL);
2080
}
2081
}
2082
if (inst == NULL) {
2083
xsltTransformError(NULL, style, inst,
2084
"xsltExtElementPreCompTest: no instruction\n");
2085
if (style != NULL)
2086
style->errors++;
2087
return (NULL);
2088
}
2089
ret = xsltNewElemPreComp(style, inst, function);
2090
return (ret);
2091
}
2092
2093
/**
2094
* xsltExtElementTest:
2095
* @ctxt: an XSLT processing context
2096
* @node: The current node
2097
* @inst: the instruction in the stylesheet
2098
* @comp: precomputed information
2099
*
2100
* Process a libxslt:test node
2101
*/
2102
static void
2103
xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
2104
xmlNodePtr inst,
2105
xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
2106
{
2107
xmlNodePtr commentNode;
2108
2109
if (testData == NULL) {
2110
xsltGenericDebug(xsltGenericDebugContext,
2111
"xsltExtElementTest: not initialized,"
2112
" calling xsltGetExtData\n");
2113
xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL);
2114
if (testData == NULL) {
2115
xsltTransformError(ctxt, NULL, inst,
2116
"xsltExtElementTest: not initialized\n");
2117
return;
2118
}
2119
}
2120
if (ctxt == NULL) {
2121
xsltTransformError(ctxt, NULL, inst,
2122
"xsltExtElementTest: no transformation context\n");
2123
return;
2124
}
2125
if (node == NULL) {
2126
xsltTransformError(ctxt, NULL, inst,
2127
"xsltExtElementTest: no current node\n");
2128
return;
2129
}
2130
if (inst == NULL) {
2131
xsltTransformError(ctxt, NULL, inst,
2132
"xsltExtElementTest: no instruction\n");
2133
return;
2134
}
2135
if (ctxt->insert == NULL) {
2136
xsltTransformError(ctxt, NULL, inst,
2137
"xsltExtElementTest: no insertion point\n");
2138
return;
2139
}
2140
commentNode = xmlNewComment((const xmlChar *)
2141
"libxslt:test element test worked");
2142
xmlAddChild(ctxt->insert, commentNode);
2143
}
2144
2145
/**
2146
* xsltExtInitTest:
2147
* @ctxt: an XSLT transformation context
2148
* @URI: the namespace URI for the extension
2149
*
2150
* A function called at initialization time of an XSLT extension module
2151
*
2152
* Returns a pointer to the module specific data for this transformation
2153
*/
2154
static void *
2155
xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI)
2156
{
2157
if (testStyleData == NULL) {
2158
xsltGenericDebug(xsltGenericErrorContext,
2159
"xsltExtInitTest: not initialized,"
2160
" calling xsltStyleGetExtData\n");
2161
testStyleData = xsltStyleGetExtData(ctxt->style, URI);
2162
if (testStyleData == NULL) {
2163
xsltTransformError(ctxt, NULL, NULL,
2164
"xsltExtInitTest: not initialized\n");
2165
return (NULL);
2166
}
2167
}
2168
if (testData != NULL) {
2169
xsltTransformError(ctxt, NULL, NULL,
2170
"xsltExtInitTest: already initialized\n");
2171
return (NULL);
2172
}
2173
testData = (void *) "test data";
2174
xsltGenericDebug(xsltGenericDebugContext,
2175
"Registered test module : %s\n", URI);
2176
return (testData);
2177
}
2178
2179
2180
/**
2181
* xsltExtShutdownTest:
2182
* @ctxt: an XSLT transformation context
2183
* @URI: the namespace URI for the extension
2184
* @data: the data associated to this module
2185
*
2186
* A function called at shutdown time of an XSLT extension module
2187
*/
2188
static void
2189
xsltExtShutdownTest(xsltTransformContextPtr ctxt,
2190
const xmlChar * URI, void *data)
2191
{
2192
if (testData == NULL) {
2193
xsltTransformError(ctxt, NULL, NULL,
2194
"xsltExtShutdownTest: not initialized\n");
2195
return;
2196
}
2197
if (data != testData) {
2198
xsltTransformError(ctxt, NULL, NULL,
2199
"xsltExtShutdownTest: wrong data\n");
2200
}
2201
testData = NULL;
2202
xsltGenericDebug(xsltGenericDebugContext,
2203
"Unregistered test module : %s\n", URI);
2204
}
2205
2206
/**
2207
* xsltExtStyleInitTest:
2208
* @style: an XSLT stylesheet
2209
* @URI: the namespace URI for the extension
2210
*
2211
* A function called at initialization time of an XSLT extension module
2212
*
2213
* Returns a pointer to the module specific data for this transformation
2214
*/
2215
static void *
2216
xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
2217
const xmlChar * URI)
2218
{
2219
if (testStyleData != NULL) {
2220
xsltTransformError(NULL, NULL, NULL,
2221
"xsltExtInitTest: already initialized\n");
2222
return (NULL);
2223
}
2224
testStyleData = (void *) "test data";
2225
xsltGenericDebug(xsltGenericDebugContext,
2226
"Registered test module : %s\n", URI);
2227
return (testStyleData);
2228
}
2229
2230
2231
/**
2232
* xsltExtStyleShutdownTest:
2233
* @style: an XSLT stylesheet
2234
* @URI: the namespace URI for the extension
2235
* @data: the data associated to this module
2236
*
2237
* A function called at shutdown time of an XSLT extension module
2238
*/
2239
static void
2240
xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
2241
const xmlChar * URI, void *data)
2242
{
2243
if (testStyleData == NULL) {
2244
xsltGenericError(xsltGenericErrorContext,
2245
"xsltExtShutdownTest: not initialized\n");
2246
return;
2247
}
2248
if (data != testStyleData) {
2249
xsltTransformError(NULL, NULL, NULL,
2250
"xsltExtShutdownTest: wrong data\n");
2251
}
2252
testStyleData = NULL;
2253
xsltGenericDebug(xsltGenericDebugContext,
2254
"Unregistered test module : %s\n", URI);
2255
}
2256
2257
/**
2258
* xsltRegisterTestModule:
2259
*
2260
* Registers the test module
2261
*/
2262
void
2263
xsltRegisterTestModule(void)
2264
{
2265
xsltInitGlobals();
2266
xsltRegisterExtModuleFull((const xmlChar *) XSLT_DEFAULT_URL,
2267
xsltExtInitTest, xsltExtShutdownTest,
2268
xsltExtStyleInitTest,
2269
xsltExtStyleShutdownTest);
2270
xsltRegisterExtModuleFunction((const xmlChar *) "test",
2271
(const xmlChar *) XSLT_DEFAULT_URL,
2272
xsltExtFunctionTest);
2273
xsltRegisterExtModuleElement((const xmlChar *) "test",
2274
(const xmlChar *) XSLT_DEFAULT_URL,
2275
xsltExtElementPreCompTest,
2276
xsltExtElementTest);
2277
}
2278
2279
static void
2280
xsltHashScannerModuleFree(void *payload,
2281
void *data ATTRIBUTE_UNUSED,
2282
const xmlChar *name ATTRIBUTE_UNUSED)
2283
{
2284
#ifdef WITH_MODULES
2285
#ifdef _WIN32
2286
FreeLibrary(payload);
2287
#else
2288
dlclose(payload);
2289
#endif
2290
#else
2291
(void) payload;
2292
#endif
2293
}
2294
2295
/**
2296
* xsltInitGlobals:
2297
*
2298
* Initialize the global variables for extensions
2299
*/
2300
void
2301
xsltInitGlobals(void)
2302
{
2303
if (xsltExtMutex == NULL) {
2304
xsltExtMutex = xmlNewMutex();
2305
}
2306
}
2307
2308
/**
2309
* xsltCleanupGlobals:
2310
*
2311
* Unregister all global variables set up by the XSLT library
2312
*/
2313
void
2314
xsltCleanupGlobals(void)
2315
{
2316
xsltUnregisterAllExtModules();
2317
xsltUnregisterAllExtModuleFunction();
2318
xsltUnregisterAllExtModuleElement();
2319
xsltUnregisterAllExtModuleTopLevel();
2320
2321
xmlMutexLock(xsltExtMutex);
2322
/* cleanup dynamic module hash */
2323
if (NULL != xsltModuleHash) {
2324
xmlHashScan(xsltModuleHash, xsltHashScannerModuleFree, 0);
2325
xmlHashFree(xsltModuleHash, NULL);
2326
xsltModuleHash = NULL;
2327
}
2328
xmlMutexUnlock(xsltExtMutex);
2329
2330
xmlFreeMutex(xsltExtMutex);
2331
xsltExtMutex = NULL;
2332
xsltFreeLocales();
2333
xsltUninit();
2334
}
2335
2336
static void
2337
xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED,
2338
void *data, const xmlChar * name,
2339
const xmlChar * URI,
2340
const xmlChar * not_used ATTRIBUTE_UNUSED)
2341
{
2342
FILE *output = (FILE *) data;
2343
if (!name || !URI)
2344
return;
2345
fprintf(output, "{%s}%s\n", URI, name);
2346
}
2347
2348
static void
2349
xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED,
2350
void *data, const xmlChar * URI,
2351
const xmlChar * not_used ATTRIBUTE_UNUSED,
2352
const xmlChar * not_used2 ATTRIBUTE_UNUSED)
2353
{
2354
FILE *output = (FILE *) data;
2355
if (!URI)
2356
return;
2357
fprintf(output, "%s\n", URI);
2358
}
2359
2360
/**
2361
* xsltDebugDumpExtensions:
2362
* @output: the FILE * for the output, if NULL stdout is used
2363
*
2364
* Dumps a list of the registered XSLT extension functions and elements
2365
*/
2366
void
2367
xsltDebugDumpExtensions(FILE * output)
2368
{
2369
if (output == NULL)
2370
output = stdout;
2371
fprintf(output,
2372
"Registered XSLT Extensions\n--------------------------\n");
2373
xmlMutexLock(xsltExtMutex);
2374
if (!xsltFunctionsHash) {
2375
fprintf(output, "No registered extension functions\n");
2376
} else {
2377
fprintf(output, "Registered extension functions:\n");
2378
xmlHashScanFull(xsltFunctionsHash, xsltDebugDumpExtensionsCallback,
2379
output);
2380
}
2381
if (!xsltTopLevelsHash) {
2382
fprintf(output, "\nNo registered top-level extension elements\n");
2383
} else {
2384
fprintf(output, "\nRegistered top-level extension elements:\n");
2385
xmlHashScanFull(xsltTopLevelsHash, xsltDebugDumpExtensionsCallback,
2386
output);
2387
}
2388
if (!xsltElementsHash) {
2389
fprintf(output, "\nNo registered instruction extension elements\n");
2390
} else {
2391
fprintf(output, "\nRegistered instruction extension elements:\n");
2392
xmlHashScanFull(xsltElementsHash, xsltDebugDumpExtensionsCallback,
2393
output);
2394
}
2395
if (!xsltExtensionsHash) {
2396
fprintf(output, "\nNo registered extension modules\n");
2397
} else {
2398
fprintf(output, "\nRegistered extension modules:\n");
2399
xmlHashScanFull(xsltExtensionsHash, xsltDebugDumpExtModulesCallback,
2400
output);
2401
}
2402
xmlMutexUnlock(xsltExtMutex);
2403
}
2404
2405