Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: third_party/libxslt/libxslt/extensions.c

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

Powered by Google App Engine
This is Rietveld 408576698