Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenextensions.c
Go to the documentation of this file.
00001 /* 00002 * extensions.c: Implemetation of the extensions support 00003 * 00004 * Reference: 00005 * http://www.w3.org/TR/1999/REC-xslt-19991116 00006 * 00007 * See Copyright for the status of this software. 00008 * 00009 * daniel@veillard.com 00010 */ 00011 00012 #define IN_LIBXSLT 00013 #include "libxslt.h" 00014 00015 #include <string.h> 00016 #include <limits.h> 00017 00018 #include <libxml/xmlmemory.h> 00019 #include <libxml/tree.h> 00020 #include <libxml/hash.h> 00021 #include <libxml/xmlerror.h> 00022 #include <libxml/parserInternals.h> 00023 #include <libxml/xpathInternals.h> 00024 #ifdef WITH_MODULES 00025 #include <libxml/xmlmodule.h> 00026 #endif 00027 #include <libxml/list.h> 00028 #include <libxml/xmlIO.h> 00029 #include "xslt.h" 00030 #include "xsltInternals.h" 00031 #include "xsltutils.h" 00032 #include "imports.h" 00033 #include "extensions.h" 00034 00035 #ifdef _WIN32 00036 #include <stdlib.h> /* for _MAX_PATH */ 00037 #ifndef PATH_MAX 00038 #define PATH_MAX _MAX_PATH 00039 #endif 00040 #endif 00041 00042 #ifdef WITH_XSLT_DEBUG 00043 #define WITH_XSLT_DEBUG_EXTENSIONS 00044 #endif 00045 00046 /************************************************************************ 00047 * * 00048 * Private Types and Globals * 00049 * * 00050 ************************************************************************/ 00051 00052 typedef struct _xsltExtDef xsltExtDef; 00053 typedef xsltExtDef *xsltExtDefPtr; 00054 struct _xsltExtDef { 00055 struct _xsltExtDef *next; 00056 xmlChar *prefix; 00057 xmlChar *URI; 00058 void *data; 00059 }; 00060 00061 typedef struct _xsltExtModule xsltExtModule; 00062 typedef xsltExtModule *xsltExtModulePtr; 00063 struct _xsltExtModule { 00064 xsltExtInitFunction initFunc; 00065 xsltExtShutdownFunction shutdownFunc; 00066 xsltStyleExtInitFunction styleInitFunc; 00067 xsltStyleExtShutdownFunction styleShutdownFunc; 00068 }; 00069 00070 typedef struct _xsltExtData xsltExtData; 00071 typedef xsltExtData *xsltExtDataPtr; 00072 struct _xsltExtData { 00073 xsltExtModulePtr extModule; 00074 void *extData; 00075 }; 00076 00077 typedef struct _xsltExtElement xsltExtElement; 00078 typedef xsltExtElement *xsltExtElementPtr; 00079 struct _xsltExtElement { 00080 xsltPreComputeFunction precomp; 00081 xsltTransformFunction transform; 00082 }; 00083 00084 static xmlHashTablePtr xsltExtensionsHash = NULL; 00085 static xmlHashTablePtr xsltFunctionsHash = NULL; 00086 static xmlHashTablePtr xsltElementsHash = NULL; 00087 static xmlHashTablePtr xsltTopLevelsHash = NULL; 00088 static xmlHashTablePtr xsltModuleHash = NULL; 00089 static xmlMutexPtr xsltExtMutex = NULL; 00090 00091 /************************************************************************ 00092 * * 00093 * Type functions * 00094 * * 00095 ************************************************************************/ 00096 00106 static xsltExtDefPtr 00107 xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI) 00108 { 00109 xsltExtDefPtr cur; 00110 00111 cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef)); 00112 if (cur == NULL) { 00113 xsltTransformError(NULL, NULL, NULL, 00114 "xsltNewExtDef : malloc failed\n"); 00115 return (NULL); 00116 } 00117 memset(cur, 0, sizeof(xsltExtDef)); 00118 if (prefix != NULL) 00119 cur->prefix = xmlStrdup(prefix); 00120 if (URI != NULL) 00121 cur->URI = xmlStrdup(URI); 00122 return (cur); 00123 } 00124 00131 static void 00132 xsltFreeExtDef(xsltExtDefPtr extensiond) 00133 { 00134 if (extensiond == NULL) 00135 return; 00136 if (extensiond->prefix != NULL) 00137 xmlFree(extensiond->prefix); 00138 if (extensiond->URI != NULL) 00139 xmlFree(extensiond->URI); 00140 xmlFree(extensiond); 00141 } 00142 00149 static void 00150 xsltFreeExtDefList(xsltExtDefPtr extensiond) 00151 { 00152 xsltExtDefPtr cur; 00153 00154 while (extensiond != NULL) { 00155 cur = extensiond; 00156 extensiond = extensiond->next; 00157 xsltFreeExtDef(cur); 00158 } 00159 } 00160 00172 static xsltExtModulePtr 00173 xsltNewExtModule(xsltExtInitFunction initFunc, 00174 xsltExtShutdownFunction shutdownFunc, 00175 xsltStyleExtInitFunction styleInitFunc, 00176 xsltStyleExtShutdownFunction styleShutdownFunc) 00177 { 00178 xsltExtModulePtr cur; 00179 00180 cur = (xsltExtModulePtr) xmlMalloc(sizeof(xsltExtModule)); 00181 if (cur == NULL) { 00182 xsltTransformError(NULL, NULL, NULL, 00183 "xsltNewExtModule : malloc failed\n"); 00184 return (NULL); 00185 } 00186 cur->initFunc = initFunc; 00187 cur->shutdownFunc = shutdownFunc; 00188 cur->styleInitFunc = styleInitFunc; 00189 cur->styleShutdownFunc = styleShutdownFunc; 00190 return (cur); 00191 } 00192 00199 static void 00200 xsltFreeExtModule(xsltExtModulePtr ext) 00201 { 00202 if (ext == NULL) 00203 return; 00204 xmlFree(ext); 00205 } 00206 00216 static xsltExtDataPtr 00217 xsltNewExtData(xsltExtModulePtr extModule, void *extData) 00218 { 00219 xsltExtDataPtr cur; 00220 00221 if (extModule == NULL) 00222 return (NULL); 00223 cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData)); 00224 if (cur == NULL) { 00225 xsltTransformError(NULL, NULL, NULL, 00226 "xsltNewExtData : malloc failed\n"); 00227 return (NULL); 00228 } 00229 cur->extModule = extModule; 00230 cur->extData = extData; 00231 return (cur); 00232 } 00233 00240 static void 00241 xsltFreeExtData(xsltExtDataPtr ext) 00242 { 00243 if (ext == NULL) 00244 return; 00245 xmlFree(ext); 00246 } 00247 00258 static xsltExtElementPtr 00259 xsltNewExtElement(xsltPreComputeFunction precomp, 00260 xsltTransformFunction transform) 00261 { 00262 xsltExtElementPtr cur; 00263 00264 if (transform == NULL) 00265 return (NULL); 00266 00267 cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement)); 00268 if (cur == NULL) { 00269 xsltTransformError(NULL, NULL, NULL, 00270 "xsltNewExtElement : malloc failed\n"); 00271 return (NULL); 00272 } 00273 cur->precomp = precomp; 00274 cur->transform = transform; 00275 return (cur); 00276 } 00277 00284 static void 00285 xsltFreeExtElement(xsltExtElementPtr ext) 00286 { 00287 if (ext == NULL) 00288 return; 00289 xmlFree(ext); 00290 } 00291 00292 00293 #ifdef WITH_MODULES 00294 typedef void (*exsltRegisterFunction) (void); 00295 00296 #ifndef PATH_MAX 00297 #define PATH_MAX 4096 00298 #endif 00299 00319 static int 00320 xsltExtModuleRegisterDynamic(const xmlChar * URI) 00321 { 00322 00323 xmlModulePtr m; 00324 exsltRegisterFunction regfunc; 00325 xmlChar *ext_name; 00326 char module_filename[PATH_MAX]; 00327 const xmlChar *ext_directory = NULL; 00328 const xmlChar *protocol = NULL; 00329 xmlChar *i, *regfunc_name; 00330 void *vregfunc; 00331 int rc; 00332 00333 /* check for bad inputs */ 00334 if (URI == NULL) 00335 return (-1); 00336 00337 if (NULL == xsltModuleHash) { 00338 xsltModuleHash = xmlHashCreate(5); 00339 if (xsltModuleHash == NULL) 00340 return (-1); 00341 } 00342 00343 xmlMutexLock(xsltExtMutex); 00344 00345 /* have we attempted to register this module already? */ 00346 if (xmlHashLookup(xsltModuleHash, URI) != NULL) { 00347 xmlMutexUnlock(xsltExtMutex); 00348 return (-1); 00349 } 00350 xmlMutexUnlock(xsltExtMutex); 00351 00352 /* transform extension namespace into a module name */ 00353 protocol = xmlStrstr(URI, BAD_CAST "://"); 00354 if (protocol == NULL) { 00355 ext_name = xmlStrdup(URI); 00356 } else { 00357 ext_name = xmlStrdup(protocol + 3); 00358 } 00359 if (ext_name == NULL) { 00360 return (-1); 00361 } 00362 00363 i = ext_name; 00364 while ('\0' != *i) { 00365 if (('/' == *i) || ('\\' == *i) || ('.' == *i) || ('-' == *i)) 00366 *i = '_'; 00367 i++; 00368 } 00369 00370 if (*(i - 1) == '_') 00371 *i = '\0'; 00372 00373 /* determine module directory */ 00374 ext_directory = (xmlChar *) getenv("LIBXSLT_PLUGINS_PATH"); 00375 00376 if (NULL == ext_directory) { 00377 ext_directory = BAD_CAST LIBXSLT_DEFAULT_PLUGINS_PATH(); 00378 if (NULL == ext_directory) 00379 return (-1); 00380 } 00381 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00382 else 00383 xsltGenericDebug(xsltGenericDebugContext, 00384 "LIBXSLT_PLUGINS_PATH is %s\n", ext_directory); 00385 #endif 00386 00387 /* build the module filename, and confirm the module exists */ 00388 xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename), 00389 BAD_CAST "%s/%s%s", 00390 ext_directory, ext_name, LIBXML_MODULE_EXTENSION); 00391 00392 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00393 xsltGenericDebug(xsltGenericDebugContext, 00394 "Attempting to load plugin: %s for URI: %s\n", 00395 module_filename, URI); 00396 #endif 00397 00398 if (1 != xmlCheckFilename(module_filename)) { 00399 00400 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00401 xsltGenericDebug(xsltGenericDebugContext, 00402 "xmlCheckFilename failed for plugin: %s\n", module_filename); 00403 #endif 00404 00405 xmlFree(ext_name); 00406 return (-1); 00407 } 00408 00409 /* attempt to open the module */ 00410 m = xmlModuleOpen(module_filename, 0); 00411 if (NULL == m) { 00412 00413 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00414 xsltGenericDebug(xsltGenericDebugContext, 00415 "xmlModuleOpen failed for plugin: %s\n", module_filename); 00416 #endif 00417 00418 xmlFree(ext_name); 00419 return (-1); 00420 } 00421 00422 /* construct initialization func name */ 00423 regfunc_name = xmlStrdup(ext_name); 00424 regfunc_name = xmlStrcat(regfunc_name, BAD_CAST "_init"); 00425 00426 vregfunc = NULL; 00427 rc = xmlModuleSymbol(m, (const char *) regfunc_name, &vregfunc); 00428 regfunc = vregfunc; 00429 if (0 == rc) { 00430 /* 00431 * Call the module's init function. Note that this function 00432 * calls xsltRegisterExtModuleFull which will add the module 00433 * to xsltExtensionsHash (together with it's entry points). 00434 */ 00435 (*regfunc) (); 00436 00437 /* register this module in our hash */ 00438 xmlMutexLock(xsltExtMutex); 00439 xmlHashAddEntry(xsltModuleHash, URI, (void *) m); 00440 xmlMutexUnlock(xsltExtMutex); 00441 } else { 00442 00443 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00444 xsltGenericDebug(xsltGenericDebugContext, 00445 "xmlModuleSymbol failed for plugin: %s, regfunc: %s\n", 00446 module_filename, regfunc_name); 00447 #endif 00448 00449 /* if regfunc not found unload the module immediately */ 00450 xmlModuleClose(m); 00451 } 00452 00453 xmlFree(ext_name); 00454 xmlFree(regfunc_name); 00455 return (NULL == regfunc) ? -1 : 0; 00456 } 00457 #else 00458 static int 00459 xsltExtModuleRegisterDynamic(const xmlChar * URI ATTRIBUTE_UNUSED) 00460 { 00461 return -1; 00462 } 00463 #endif 00464 00465 /************************************************************************ 00466 * * 00467 * The stylesheet extension prefixes handling * 00468 * * 00469 ************************************************************************/ 00470 00471 00478 void 00479 xsltFreeExts(xsltStylesheetPtr style) 00480 { 00481 if (style->nsDefs != NULL) 00482 xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs); 00483 } 00484 00502 int 00503 xsltRegisterExtPrefix(xsltStylesheetPtr style, 00504 const xmlChar * prefix, const xmlChar * URI) 00505 { 00506 xsltExtDefPtr def, ret; 00507 00508 if ((style == NULL) || (URI == NULL)) 00509 return (-1); 00510 00511 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00512 xsltGenericDebug(xsltGenericDebugContext, 00513 "Registering extension namespace '%s'.\n", URI); 00514 #endif 00515 def = (xsltExtDefPtr) style->nsDefs; 00516 #ifdef XSLT_REFACTORED 00517 /* 00518 * The extension is associated with a namespace name. 00519 */ 00520 while (def != NULL) { 00521 if (xmlStrEqual(URI, def->URI)) 00522 return (1); 00523 def = def->next; 00524 } 00525 #else 00526 while (def != NULL) { 00527 if (xmlStrEqual(prefix, def->prefix)) 00528 return (-1); 00529 def = def->next; 00530 } 00531 #endif 00532 ret = xsltNewExtDef(prefix, URI); 00533 if (ret == NULL) 00534 return (-1); 00535 ret->next = (xsltExtDefPtr) style->nsDefs; 00536 style->nsDefs = ret; 00537 00538 /* 00539 * check whether there is an extension module with a stylesheet 00540 * initialization function. 00541 */ 00542 #ifdef XSLT_REFACTORED 00543 /* 00544 * Don't initialize modules based on specified namespaces via 00545 * the attribute "[xsl:]extension-element-prefixes". 00546 */ 00547 #else 00548 if (xsltExtensionsHash != NULL) { 00549 xsltExtModulePtr module; 00550 00551 xmlMutexLock(xsltExtMutex); 00552 module = xmlHashLookup(xsltExtensionsHash, URI); 00553 xmlMutexUnlock(xsltExtMutex); 00554 if (NULL == module) { 00555 if (!xsltExtModuleRegisterDynamic(URI)) { 00556 xmlMutexLock(xsltExtMutex); 00557 module = xmlHashLookup(xsltExtensionsHash, URI); 00558 xmlMutexUnlock(xsltExtMutex); 00559 } 00560 } 00561 if (module != NULL) { 00562 xsltStyleGetExtData(style, URI); 00563 } 00564 } 00565 #endif 00566 return (0); 00567 } 00568 00569 /************************************************************************ 00570 * * 00571 * The extensions modules interfaces * 00572 * * 00573 ************************************************************************/ 00574 00586 int 00587 xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar * name, 00588 const xmlChar * URI, xmlXPathFunction function) 00589 { 00590 int ret; 00591 00592 if ((ctxt == NULL) || (name == NULL) || 00593 (URI == NULL) || (function == NULL)) 00594 return (-1); 00595 if (ctxt->xpathCtxt != NULL) { 00596 xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function); 00597 } 00598 if (ctxt->extFunctions == NULL) 00599 ctxt->extFunctions = xmlHashCreate(10); 00600 if (ctxt->extFunctions == NULL) 00601 return (-1); 00602 00603 ret = xmlHashAddEntry2(ctxt->extFunctions, name, URI, 00604 XML_CAST_FPTR(function)); 00605 00606 return(ret); 00607 } 00608 00620 int 00621 xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar * name, 00622 const xmlChar * URI, xsltTransformFunction function) 00623 { 00624 if ((ctxt == NULL) || (name == NULL) || 00625 (URI == NULL) || (function == NULL)) 00626 return (-1); 00627 if (ctxt->extElements == NULL) 00628 ctxt->extElements = xmlHashCreate(10); 00629 if (ctxt->extElements == NULL) 00630 return (-1); 00631 return (xmlHashAddEntry2 00632 (ctxt->extElements, name, URI, XML_CAST_FPTR(function))); 00633 } 00634 00641 void 00642 xsltFreeCtxtExts(xsltTransformContextPtr ctxt) 00643 { 00644 if (ctxt->extElements != NULL) 00645 xmlHashFree(ctxt->extElements, NULL); 00646 if (ctxt->extFunctions != NULL) 00647 xmlHashFree(ctxt->extFunctions, NULL); 00648 } 00649 00662 static xsltExtDataPtr 00663 xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style, 00664 const xmlChar * URI) 00665 { 00666 xsltExtDataPtr dataContainer; 00667 void *userData = NULL; 00668 xsltExtModulePtr module; 00669 00670 if ((style == NULL) || (URI == NULL)) 00671 return(NULL); 00672 00673 if (xsltExtensionsHash == NULL) { 00674 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00675 xsltGenericDebug(xsltGenericDebugContext, 00676 "Not registered extension module: %s\n", URI); 00677 #endif 00678 return(NULL); 00679 } 00680 00681 xmlMutexLock(xsltExtMutex); 00682 00683 module = xmlHashLookup(xsltExtensionsHash, URI); 00684 00685 xmlMutexUnlock(xsltExtMutex); 00686 00687 if (module == NULL) { 00688 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00689 xsltGenericDebug(xsltGenericDebugContext, 00690 "Not registered extension module: %s\n", URI); 00691 #endif 00692 return (NULL); 00693 } 00694 /* 00695 * The specified module was registered so initialize it. 00696 */ 00697 if (style->extInfos == NULL) { 00698 style->extInfos = xmlHashCreate(10); 00699 if (style->extInfos == NULL) 00700 return (NULL); 00701 } 00702 /* 00703 * Fire the initialization callback if available. 00704 */ 00705 if (module->styleInitFunc == NULL) { 00706 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00707 xsltGenericDebug(xsltGenericDebugContext, 00708 "Initializing module with *no* callback: %s\n", URI); 00709 #endif 00710 } else { 00711 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00712 xsltGenericDebug(xsltGenericDebugContext, 00713 "Initializing module with callback: %s\n", URI); 00714 #endif 00715 /* 00716 * Fire the initialization callback. 00717 */ 00718 userData = module->styleInitFunc(style, URI); 00719 } 00720 /* 00721 * Store the user-data in the context of the given stylesheet. 00722 */ 00723 dataContainer = xsltNewExtData(module, userData); 00724 if (dataContainer == NULL) 00725 return (NULL); 00726 00727 if (xmlHashAddEntry(style->extInfos, URI, 00728 (void *) dataContainer) < 0) 00729 { 00730 xsltTransformError(NULL, style, NULL, 00731 "Failed to register module '%s'.\n", URI); 00732 style->errors++; 00733 if (module->styleShutdownFunc) 00734 module->styleShutdownFunc(style, URI, userData); 00735 xsltFreeExtData(dataContainer); 00736 return (NULL); 00737 } 00738 00739 return(dataContainer); 00740 } 00741 00755 void * 00756 xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) 00757 { 00758 xsltExtDataPtr dataContainer = NULL; 00759 xsltStylesheetPtr tmpStyle; 00760 00761 if ((style == NULL) || (URI == NULL) || 00762 (xsltExtensionsHash == NULL)) 00763 return (NULL); 00764 00765 00766 #ifdef XSLT_REFACTORED 00767 /* 00768 * This is intended for global storage, so only the main 00769 * stylesheet will hold the data. 00770 */ 00771 tmpStyle = style; 00772 while (tmpStyle->parent != NULL) 00773 tmpStyle = tmpStyle->parent; 00774 if (tmpStyle->extInfos != NULL) { 00775 dataContainer = 00776 (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI); 00777 if (dataContainer != NULL) { 00778 /* 00779 * The module was already initialized in the context 00780 * of this stylesheet; just return the user-data that 00781 * comes with it. 00782 */ 00783 return(dataContainer->extData); 00784 } 00785 } 00786 #else 00787 /* 00788 * Old behaviour. 00789 */ 00790 tmpStyle = style; 00791 while (tmpStyle != NULL) { 00792 if (tmpStyle->extInfos != NULL) { 00793 dataContainer = 00794 (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI); 00795 if (dataContainer != NULL) { 00796 return(dataContainer->extData); 00797 } 00798 } 00799 tmpStyle = xsltNextImport(tmpStyle); 00800 } 00801 tmpStyle = style; 00802 #endif 00803 00804 dataContainer = 00805 xsltStyleInitializeStylesheetModule(tmpStyle, URI); 00806 if (dataContainer != NULL) 00807 return (dataContainer->extData); 00808 return(NULL); 00809 } 00810 00811 #ifdef XSLT_REFACTORED 00812 00822 void * 00823 xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style, 00824 const xmlChar * URI) 00825 { 00826 xsltExtDataPtr dataContainer = NULL; 00827 00828 if ((style == NULL) || (URI == NULL) || 00829 (xsltExtensionsHash == NULL)) 00830 return (NULL); 00831 00832 if (style->extInfos != NULL) { 00833 dataContainer = (xsltExtDataPtr) xmlHashLookup(style->extInfos, URI); 00834 /* 00835 * The module was already initialized in the context 00836 * of this stylesheet; just return the user-data that 00837 * comes with it. 00838 */ 00839 if (dataContainer) 00840 return(dataContainer->extData); 00841 } 00842 00843 dataContainer = 00844 xsltStyleInitializeStylesheetModule(style, URI); 00845 if (dataContainer != NULL) 00846 return (dataContainer->extData); 00847 return(NULL); 00848 } 00849 #endif 00850 00861 void * 00862 xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI) 00863 { 00864 xsltExtDataPtr data; 00865 00866 if ((ctxt == NULL) || (URI == NULL)) 00867 return (NULL); 00868 if (ctxt->extInfos == NULL) { 00869 ctxt->extInfos = xmlHashCreate(10); 00870 if (ctxt->extInfos == NULL) 00871 return (NULL); 00872 data = NULL; 00873 } else { 00874 data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI); 00875 } 00876 if (data == NULL) { 00877 void *extData; 00878 xsltExtModulePtr module; 00879 00880 xmlMutexLock(xsltExtMutex); 00881 00882 module = xmlHashLookup(xsltExtensionsHash, URI); 00883 00884 xmlMutexUnlock(xsltExtMutex); 00885 00886 if (module == NULL) { 00887 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00888 xsltGenericDebug(xsltGenericDebugContext, 00889 "Not registered extension module: %s\n", URI); 00890 #endif 00891 return (NULL); 00892 } else { 00893 if (module->initFunc == NULL) 00894 return (NULL); 00895 00896 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00897 xsltGenericDebug(xsltGenericDebugContext, 00898 "Initializing module: %s\n", URI); 00899 #endif 00900 00901 extData = module->initFunc(ctxt, URI); 00902 if (extData == NULL) 00903 return (NULL); 00904 00905 data = xsltNewExtData(module, extData); 00906 if (data == NULL) 00907 return (NULL); 00908 if (xmlHashAddEntry(ctxt->extInfos, URI, (void *) data) < 0) { 00909 xsltTransformError(ctxt, NULL, NULL, 00910 "Failed to register module data: %s\n", 00911 URI); 00912 if (module->shutdownFunc) 00913 module->shutdownFunc(ctxt, URI, extData); 00914 xsltFreeExtData(data); 00915 return (NULL); 00916 } 00917 } 00918 } 00919 return (data->extData); 00920 } 00921 00922 typedef struct _xsltInitExtCtxt xsltInitExtCtxt; 00923 struct _xsltInitExtCtxt { 00924 xsltTransformContextPtr ctxt; 00925 int ret; 00926 }; 00927 00936 static void 00937 xsltInitCtxtExt(xsltExtDataPtr styleData, xsltInitExtCtxt * ctxt, 00938 const xmlChar * URI) 00939 { 00940 xsltExtModulePtr module; 00941 xsltExtDataPtr ctxtData; 00942 void *extData; 00943 00944 if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) || 00945 (ctxt->ret == -1)) { 00946 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00947 xsltGenericDebug(xsltGenericDebugContext, 00948 "xsltInitCtxtExt: NULL param or error\n"); 00949 #endif 00950 return; 00951 } 00952 module = styleData->extModule; 00953 if ((module == NULL) || (module->initFunc == NULL)) { 00954 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00955 xsltGenericDebug(xsltGenericDebugContext, 00956 "xsltInitCtxtExt: no module or no initFunc\n"); 00957 #endif 00958 return; 00959 } 00960 00961 ctxtData = (xsltExtDataPtr) xmlHashLookup(ctxt->ctxt->extInfos, URI); 00962 if (ctxtData != NULL) { 00963 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00964 xsltGenericDebug(xsltGenericDebugContext, 00965 "xsltInitCtxtExt: already initialized\n"); 00966 #endif 00967 return; 00968 } 00969 00970 extData = module->initFunc(ctxt->ctxt, URI); 00971 if (extData == NULL) { 00972 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 00973 xsltGenericDebug(xsltGenericDebugContext, 00974 "xsltInitCtxtExt: no extData\n"); 00975 #endif 00976 } 00977 ctxtData = xsltNewExtData(module, extData); 00978 if (ctxtData == NULL) { 00979 ctxt->ret = -1; 00980 return; 00981 } 00982 00983 if (ctxt->ctxt->extInfos == NULL) 00984 ctxt->ctxt->extInfos = xmlHashCreate(10); 00985 if (ctxt->ctxt->extInfos == NULL) { 00986 ctxt->ret = -1; 00987 return; 00988 } 00989 00990 if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) { 00991 xsltGenericError(xsltGenericErrorContext, 00992 "Failed to register module data: %s\n", URI); 00993 if (module->shutdownFunc) 00994 module->shutdownFunc(ctxt->ctxt, URI, extData); 00995 xsltFreeExtData(ctxtData); 00996 ctxt->ret = -1; 00997 return; 00998 } 00999 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 01000 xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n", 01001 URI); 01002 #endif 01003 ctxt->ret++; 01004 } 01005 01014 int 01015 xsltInitCtxtExts(xsltTransformContextPtr ctxt) 01016 { 01017 xsltStylesheetPtr style; 01018 xsltInitExtCtxt ctx; 01019 01020 if (ctxt == NULL) 01021 return (-1); 01022 01023 style = ctxt->style; 01024 if (style == NULL) 01025 return (-1); 01026 01027 ctx.ctxt = ctxt; 01028 ctx.ret = 0; 01029 01030 while (style != NULL) { 01031 if (style->extInfos != NULL) { 01032 xmlHashScan(style->extInfos, 01033 (xmlHashScanner) xsltInitCtxtExt, &ctx); 01034 if (ctx.ret == -1) 01035 return (-1); 01036 } 01037 style = xsltNextImport(style); 01038 } 01039 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 01040 xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n", 01041 ctx.ret); 01042 #endif 01043 return (ctx.ret); 01044 } 01045 01054 static void 01055 xsltShutdownCtxtExt(xsltExtDataPtr data, xsltTransformContextPtr ctxt, 01056 const xmlChar * URI) 01057 { 01058 xsltExtModulePtr module; 01059 01060 if ((data == NULL) || (ctxt == NULL) || (URI == NULL)) 01061 return; 01062 module = data->extModule; 01063 if ((module == NULL) || (module->shutdownFunc == NULL)) 01064 return; 01065 01066 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 01067 xsltGenericDebug(xsltGenericDebugContext, 01068 "Shutting down module : %s\n", URI); 01069 #endif 01070 module->shutdownFunc(ctxt, URI, data->extData); 01071 } 01072 01079 void 01080 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt) 01081 { 01082 if (ctxt == NULL) 01083 return; 01084 if (ctxt->extInfos == NULL) 01085 return; 01086 xmlHashScan(ctxt->extInfos, (xmlHashScanner) xsltShutdownCtxtExt, 01087 ctxt); 01088 xmlHashFree(ctxt->extInfos, (xmlHashDeallocator) xsltFreeExtData); 01089 ctxt->extInfos = NULL; 01090 } 01091 01100 static void 01101 xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style, 01102 const xmlChar * URI) 01103 { 01104 xsltExtModulePtr module; 01105 01106 if ((data == NULL) || (style == NULL) || (URI == NULL)) 01107 return; 01108 module = data->extModule; 01109 if ((module == NULL) || (module->styleShutdownFunc == NULL)) 01110 return; 01111 01112 #ifdef WITH_XSLT_DEBUG_EXTENSIONS 01113 xsltGenericDebug(xsltGenericDebugContext, 01114 "Shutting down module : %s\n", URI); 01115 #endif 01116 module->styleShutdownFunc(style, URI, data->extData); 01117 /* 01118 * Don't remove the entry from the hash table here, since 01119 * this will produce segfaults - this fixes bug #340624. 01120 * 01121 * xmlHashRemoveEntry(style->extInfos, URI, 01122 * (xmlHashDeallocator) xsltFreeExtData); 01123 */ 01124 } 01125 01132 void 01133 xsltShutdownExts(xsltStylesheetPtr style) 01134 { 01135 if (style == NULL) 01136 return; 01137 if (style->extInfos == NULL) 01138 return; 01139 xmlHashScan(style->extInfos, (xmlHashScanner) xsltShutdownExt, style); 01140 xmlHashFree(style->extInfos, (xmlHashDeallocator) xsltFreeExtData); 01141 style->extInfos = NULL; 01142 } 01143 01157 int 01158 xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * URI) 01159 { 01160 #ifdef XSLT_REFACTORED 01161 if ((style == NULL) || (style->compCtxt == NULL) || 01162 (XSLT_CCTXT(style)->inode == NULL) || 01163 (XSLT_CCTXT(style)->inode->extElemNs == NULL)) 01164 return (0); 01165 /* 01166 * Lookup the extension namespaces registered 01167 * at the current node in the stylesheet's tree. 01168 */ 01169 if (XSLT_CCTXT(style)->inode->extElemNs != NULL) { 01170 int i; 01171 xsltPointerListPtr list = XSLT_CCTXT(style)->inode->extElemNs; 01172 01173 for (i = 0; i < list->number; i++) { 01174 if (xmlStrEqual((const xmlChar *) list->items[i], 01175 URI)) 01176 { 01177 return(1); 01178 } 01179 } 01180 } 01181 #else 01182 xsltExtDefPtr cur; 01183 01184 if ((style == NULL) || (style->nsDefs == NULL)) 01185 return (0); 01186 if (URI == NULL) 01187 URI = BAD_CAST "#default"; 01188 cur = (xsltExtDefPtr) style->nsDefs; 01189 while (cur != NULL) { 01190 /* 01191 * NOTE: This was change to work on namespace names rather 01192 * than namespace prefixes. This fixes bug #339583. 01193 * TODO: Consider renaming the field "prefix" of xsltExtDef 01194 * to "href". 01195 */ 01196 if (xmlStrEqual(URI, cur->prefix)) 01197 return (1); 01198 cur = cur->next; 01199 } 01200 #endif 01201 return (0); 01202 } 01203 01217 int 01218 xsltCheckExtURI(xsltStylesheetPtr style, const xmlChar * URI) 01219 { 01220 xsltExtDefPtr cur; 01221 01222 if ((style == NULL) || (style->nsDefs == NULL)) 01223 return (0); 01224 if (URI == NULL) 01225 return (0); 01226 cur = (xsltExtDefPtr) style->nsDefs; 01227 while (cur != NULL) { 01228 if (xmlStrEqual(URI, cur->URI)) 01229 return (1); 01230 cur = cur->next; 01231 } 01232 return (0); 01233 } 01234 01247 int 01248 xsltRegisterExtModuleFull(const xmlChar * URI, 01249 xsltExtInitFunction initFunc, 01250 xsltExtShutdownFunction shutdownFunc, 01251 xsltStyleExtInitFunction styleInitFunc, 01252 xsltStyleExtShutdownFunction styleShutdownFunc) 01253 { 01254 int ret; 01255 xsltExtModulePtr module; 01256 01257 if ((URI == NULL) || (initFunc == NULL)) 01258 return (-1); 01259 if (xsltExtensionsHash == NULL) 01260 xsltExtensionsHash = xmlHashCreate(10); 01261 01262 if (xsltExtensionsHash == NULL) 01263 return (-1); 01264 01265 xmlMutexLock(xsltExtMutex); 01266 01267 module = xmlHashLookup(xsltExtensionsHash, URI); 01268 if (module != NULL) { 01269 if ((module->initFunc == initFunc) && 01270 (module->shutdownFunc == shutdownFunc)) 01271 ret = 0; 01272 else 01273 ret = -1; 01274 goto done; 01275 } 01276 module = xsltNewExtModule(initFunc, shutdownFunc, 01277 styleInitFunc, styleShutdownFunc); 01278 if (module == NULL) { 01279 ret = -1; 01280 goto done; 01281 } 01282 ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module); 01283 01284 done: 01285 xmlMutexUnlock(xsltExtMutex); 01286 return (ret); 01287 } 01288 01299 int 01300 xsltRegisterExtModule(const xmlChar * URI, 01301 xsltExtInitFunction initFunc, 01302 xsltExtShutdownFunction shutdownFunc) 01303 { 01304 return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc, 01305 NULL, NULL); 01306 } 01307 01316 int 01317 xsltUnregisterExtModule(const xmlChar * URI) 01318 { 01319 int ret; 01320 01321 if (URI == NULL) 01322 return (-1); 01323 if (xsltExtensionsHash == NULL) 01324 return (-1); 01325 01326 xmlMutexLock(xsltExtMutex); 01327 01328 ret = xmlHashRemoveEntry(xsltExtensionsHash, URI, 01329 (xmlHashDeallocator) xsltFreeExtModule); 01330 01331 xmlMutexUnlock(xsltExtMutex); 01332 01333 return (ret); 01334 } 01335 01341 static void 01342 xsltUnregisterAllExtModules(void) 01343 { 01344 if (xsltExtensionsHash == NULL) 01345 return; 01346 01347 xmlMutexLock(xsltExtMutex); 01348 01349 xmlHashFree(xsltExtensionsHash, 01350 (xmlHashDeallocator) xsltFreeExtModule); 01351 xsltExtensionsHash = NULL; 01352 01353 xmlMutexUnlock(xsltExtMutex); 01354 } 01355 01368 xsltTransformContextPtr 01369 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt) 01370 { 01371 if ((ctxt == NULL) || (ctxt->context == NULL)) 01372 return (NULL); 01373 return (ctxt->context->extra); 01374 } 01375 01386 int 01387 xsltRegisterExtModuleFunction(const xmlChar * name, const xmlChar * URI, 01388 xmlXPathFunction function) 01389 { 01390 if ((name == NULL) || (URI == NULL) || (function == NULL)) 01391 return (-1); 01392 01393 if (xsltFunctionsHash == NULL) 01394 xsltFunctionsHash = xmlHashCreate(10); 01395 if (xsltFunctionsHash == NULL) 01396 return (-1); 01397 01398 xmlMutexLock(xsltExtMutex); 01399 01400 xmlHashUpdateEntry2(xsltFunctionsHash, name, URI, 01401 XML_CAST_FPTR(function), NULL); 01402 01403 xmlMutexUnlock(xsltExtMutex); 01404 01405 return (0); 01406 } 01407 01417 xmlXPathFunction 01418 xsltExtModuleFunctionLookup(const xmlChar * name, const xmlChar * URI) 01419 { 01420 xmlXPathFunction ret; 01421 01422 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL)) 01423 return (NULL); 01424 01425 xmlMutexLock(xsltExtMutex); 01426 01427 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI); 01428 01429 xmlMutexUnlock(xsltExtMutex); 01430 01431 /* if lookup fails, attempt a dynamic load on supported platforms */ 01432 if (NULL == ret) { 01433 if (!xsltExtModuleRegisterDynamic(URI)) { 01434 xmlMutexLock(xsltExtMutex); 01435 01436 XML_CAST_FPTR(ret) = 01437 xmlHashLookup2(xsltFunctionsHash, name, URI); 01438 01439 xmlMutexUnlock(xsltExtMutex); 01440 } 01441 } 01442 01443 return ret; 01444 } 01445 01455 int 01456 xsltUnregisterExtModuleFunction(const xmlChar * name, const xmlChar * URI) 01457 { 01458 int ret; 01459 01460 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL)) 01461 return (-1); 01462 01463 xmlMutexLock(xsltExtMutex); 01464 01465 ret = xmlHashRemoveEntry2(xsltFunctionsHash, name, URI, NULL); 01466 01467 xmlMutexUnlock(xsltExtMutex); 01468 01469 return(ret); 01470 } 01471 01477 static void 01478 xsltUnregisterAllExtModuleFunction(void) 01479 { 01480 xmlMutexLock(xsltExtMutex); 01481 01482 xmlHashFree(xsltFunctionsHash, NULL); 01483 xsltFunctionsHash = NULL; 01484 01485 xmlMutexUnlock(xsltExtMutex); 01486 } 01487 01488 01499 xsltElemPreCompPtr 01500 xsltNewElemPreComp(xsltStylesheetPtr style, xmlNodePtr inst, 01501 xsltTransformFunction function) 01502 { 01503 xsltElemPreCompPtr cur; 01504 01505 cur = (xsltElemPreCompPtr) xmlMalloc(sizeof(xsltElemPreComp)); 01506 if (cur == NULL) { 01507 xsltTransformError(NULL, style, NULL, 01508 "xsltNewExtElement : malloc failed\n"); 01509 return (NULL); 01510 } 01511 memset(cur, 0, sizeof(xsltElemPreComp)); 01512 01513 xsltInitElemPreComp(cur, style, inst, function, 01514 (xsltElemPreCompDeallocator) xmlFree); 01515 01516 return (cur); 01517 } 01518 01532 void 01533 xsltInitElemPreComp(xsltElemPreCompPtr comp, xsltStylesheetPtr style, 01534 xmlNodePtr inst, xsltTransformFunction function, 01535 xsltElemPreCompDeallocator freeFunc) 01536 { 01537 comp->type = XSLT_FUNC_EXTENSION; 01538 comp->func = function; 01539 comp->inst = inst; 01540 comp->free = freeFunc; 01541 01542 comp->next = style->preComps; 01543 style->preComps = comp; 01544 } 01545 01555 xsltElemPreCompPtr 01556 xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst) 01557 { 01558 xsltExtElementPtr ext; 01559 xsltElemPreCompPtr comp = NULL; 01560 01561 if ((style == NULL) || (inst == NULL) || 01562 (inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL)) 01563 return (NULL); 01564 01565 xmlMutexLock(xsltExtMutex); 01566 01567 ext = (xsltExtElementPtr) 01568 xmlHashLookup2(xsltElementsHash, inst->name, inst->ns->href); 01569 01570 xmlMutexUnlock(xsltExtMutex); 01571 01572 /* 01573 * EXT TODO: Now what? 01574 */ 01575 if (ext == NULL) 01576 return (NULL); 01577 01578 if (ext->precomp != NULL) { 01579 /* 01580 * REVISIT TODO: Check if the text below is correct. 01581 * This will return a xsltElemPreComp structure or NULL. 01582 * 1) If the the author of the extension needs a 01583 * custom structure to hold the specific values of 01584 * this extension, he will derive a structure based on 01585 * xsltElemPreComp; thus we obviously *cannot* refactor 01586 * the xsltElemPreComp structure, since all already derived 01587 * user-defined strucures will break. 01588 * Example: For the extension xsl:document, 01589 * in xsltDocumentComp() (preproc.c), the structure 01590 * xsltStyleItemDocument is allocated, filled with 01591 * specific values and returned. 01592 * 2) If the author needs no values to be stored in 01593 * this structure, then he'll return NULL; 01594 */ 01595 comp = ext->precomp(style, inst, ext->transform); 01596 } 01597 if (comp == NULL) { 01598 /* 01599 * Default creation of a xsltElemPreComp structure, if 01600 * the author of this extension did not create a custom 01601 * structure. 01602 */ 01603 comp = xsltNewElemPreComp(style, inst, ext->transform); 01604 } 01605 01606 return (comp); 01607 } 01608 01620 int 01621 xsltRegisterExtModuleElement(const xmlChar * name, const xmlChar * URI, 01622 xsltPreComputeFunction precomp, 01623 xsltTransformFunction transform) 01624 { 01625 int ret; 01626 01627 xsltExtElementPtr ext; 01628 01629 if ((name == NULL) || (URI == NULL) || (transform == NULL)) 01630 return (-1); 01631 01632 if (xsltElementsHash == NULL) 01633 xsltElementsHash = xmlHashCreate(10); 01634 if (xsltElementsHash == NULL) 01635 return (-1); 01636 01637 xmlMutexLock(xsltExtMutex); 01638 01639 ext = xsltNewExtElement(precomp, transform); 01640 if (ext == NULL) { 01641 ret = -1; 01642 goto done; 01643 } 01644 01645 xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext, 01646 (xmlHashDeallocator) xsltFreeExtElement); 01647 01648 done: 01649 xmlMutexUnlock(xsltExtMutex); 01650 01651 return (0); 01652 } 01653 01665 xsltTransformFunction 01666 xsltExtElementLookup(xsltTransformContextPtr ctxt, 01667 const xmlChar * name, const xmlChar * URI) 01668 { 01669 xsltTransformFunction ret; 01670 01671 if ((name == NULL) || (URI == NULL)) 01672 return (NULL); 01673 01674 if ((ctxt != NULL) && (ctxt->extElements != NULL)) { 01675 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->extElements, name, URI); 01676 if (ret != NULL) { 01677 return(ret); 01678 } 01679 } 01680 01681 ret = xsltExtModuleElementLookup(name, URI); 01682 01683 return (ret); 01684 } 01685 01695 xsltTransformFunction 01696 xsltExtModuleElementLookup(const xmlChar * name, const xmlChar * URI) 01697 { 01698 xsltExtElementPtr ext; 01699 01700 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) 01701 return (NULL); 01702 01703 xmlMutexLock(xsltExtMutex); 01704 01705 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); 01706 01707 xmlMutexUnlock(xsltExtMutex); 01708 01709 /* 01710 * if function lookup fails, attempt a dynamic load on 01711 * supported platforms 01712 */ 01713 if (NULL == ext) { 01714 if (!xsltExtModuleRegisterDynamic(URI)) { 01715 xmlMutexLock(xsltExtMutex); 01716 01717 ext = (xsltExtElementPtr) 01718 xmlHashLookup2(xsltElementsHash, name, URI); 01719 01720 xmlMutexUnlock(xsltExtMutex); 01721 } 01722 } 01723 01724 if (ext == NULL) 01725 return (NULL); 01726 return (ext->transform); 01727 } 01728 01738 xsltPreComputeFunction 01739 xsltExtModuleElementPreComputeLookup(const xmlChar * name, 01740 const xmlChar * URI) 01741 { 01742 xsltExtElementPtr ext; 01743 01744 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) 01745 return (NULL); 01746 01747 xmlMutexLock(xsltExtMutex); 01748 01749 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); 01750 01751 xmlMutexUnlock(xsltExtMutex); 01752 01753 if (ext == NULL) { 01754 if (!xsltExtModuleRegisterDynamic(URI)) { 01755 xmlMutexLock(xsltExtMutex); 01756 01757 ext = (xsltExtElementPtr) 01758 xmlHashLookup2(xsltElementsHash, name, URI); 01759 01760 xmlMutexUnlock(xsltExtMutex); 01761 } 01762 } 01763 01764 if (ext == NULL) 01765 return (NULL); 01766 return (ext->precomp); 01767 } 01768 01778 int 01779 xsltUnregisterExtModuleElement(const xmlChar * name, const xmlChar * URI) 01780 { 01781 int ret; 01782 01783 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) 01784 return (-1); 01785 01786 xmlMutexLock(xsltExtMutex); 01787 01788 ret = xmlHashRemoveEntry2(xsltElementsHash, name, URI, 01789 (xmlHashDeallocator) xsltFreeExtElement); 01790 01791 xmlMutexUnlock(xsltExtMutex); 01792 01793 return(ret); 01794 } 01795 01801 static void 01802 xsltUnregisterAllExtModuleElement(void) 01803 { 01804 xmlMutexLock(xsltExtMutex); 01805 01806 xmlHashFree(xsltElementsHash, (xmlHashDeallocator) xsltFreeExtElement); 01807 xsltElementsHash = NULL; 01808 01809 xmlMutexUnlock(xsltExtMutex); 01810 } 01811 01822 int 01823 xsltRegisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI, 01824 xsltTopLevelFunction function) 01825 { 01826 if ((name == NULL) || (URI == NULL) || (function == NULL)) 01827 return (-1); 01828 01829 if (xsltTopLevelsHash == NULL) 01830 xsltTopLevelsHash = xmlHashCreate(10); 01831 if (xsltTopLevelsHash == NULL) 01832 return (-1); 01833 01834 xmlMutexLock(xsltExtMutex); 01835 01836 xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI, 01837 XML_CAST_FPTR(function), NULL); 01838 01839 xmlMutexUnlock(xsltExtMutex); 01840 01841 return (0); 01842 } 01843 01853 xsltTopLevelFunction 01854 xsltExtModuleTopLevelLookup(const xmlChar * name, const xmlChar * URI) 01855 { 01856 xsltTopLevelFunction ret; 01857 01858 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL)) 01859 return (NULL); 01860 01861 xmlMutexLock(xsltExtMutex); 01862 01863 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI); 01864 01865 xmlMutexUnlock(xsltExtMutex); 01866 01867 /* if lookup fails, attempt a dynamic load on supported platforms */ 01868 if (NULL == ret) { 01869 if (!xsltExtModuleRegisterDynamic(URI)) { 01870 xmlMutexLock(xsltExtMutex); 01871 01872 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI); 01873 01874 xmlMutexUnlock(xsltExtMutex); 01875 } 01876 } 01877 01878 return (ret); 01879 } 01880 01890 int 01891 xsltUnregisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI) 01892 { 01893 int ret; 01894 01895 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL)) 01896 return (-1); 01897 01898 xmlMutexLock(xsltExtMutex); 01899 01900 ret = xmlHashRemoveEntry2(xsltTopLevelsHash, name, URI, NULL); 01901 01902 xmlMutexUnlock(xsltExtMutex); 01903 01904 return(ret); 01905 } 01906 01912 static void 01913 xsltUnregisterAllExtModuleTopLevel(void) 01914 { 01915 xmlMutexLock(xsltExtMutex); 01916 01917 xmlHashFree(xsltTopLevelsHash, NULL); 01918 xsltTopLevelsHash = NULL; 01919 01920 xmlMutexUnlock(xsltExtMutex); 01921 } 01922 01932 xmlHashTablePtr 01933 xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI) 01934 { 01935 xsltExtDataPtr data; 01936 01937 /* 01938 * TODO: Why do we have a return type of xmlHashTablePtr? 01939 * Is the user-allocated data for extension modules expected 01940 * to be a xmlHashTablePtr only? Or is this intended for 01941 * the EXSLT module only? 01942 */ 01943 01944 if (style != NULL && style->extInfos != NULL) { 01945 data = xmlHashLookup(style->extInfos, URI); 01946 if (data != NULL && data->extData != NULL) 01947 return data->extData; 01948 } 01949 return NULL; 01950 } 01951 01952 /************************************************************************ 01953 * * 01954 * Test module http://xmlsoft.org/XSLT/ * 01955 * * 01956 ************************************************************************/ 01957 01958 /************************************************************************ 01959 * * 01960 * Test of the extension module API * 01961 * * 01962 ************************************************************************/ 01963 01964 static xmlChar *testData = NULL; 01965 static xmlChar *testStyleData = NULL; 01966 01974 static void 01975 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, 01976 int nargs ATTRIBUTE_UNUSED) 01977 { 01978 xsltTransformContextPtr tctxt; 01979 void *data = NULL; 01980 01981 tctxt = xsltXPathGetTransformContext(ctxt); 01982 01983 if (testData == NULL) { 01984 xsltGenericDebug(xsltGenericDebugContext, 01985 "xsltExtFunctionTest: not initialized," 01986 " calling xsltGetExtData\n"); 01987 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL); 01988 if (data == NULL) { 01989 xsltTransformError(tctxt, NULL, NULL, 01990 "xsltExtElementTest: not initialized\n"); 01991 return; 01992 } 01993 } 01994 if (tctxt == NULL) { 01995 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 01996 "xsltExtFunctionTest: failed to get the transformation context\n"); 01997 return; 01998 } 01999 if (data == NULL) 02000 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL); 02001 if (data == NULL) { 02002 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 02003 "xsltExtFunctionTest: failed to get module data\n"); 02004 return; 02005 } 02006 if (data != testData) { 02007 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 02008 "xsltExtFunctionTest: got wrong module data\n"); 02009 return; 02010 } 02011 #ifdef WITH_XSLT_DEBUG_FUNCTION 02012 xsltGenericDebug(xsltGenericDebugContext, 02013 "libxslt:test() called with %d args\n", nargs); 02014 #endif 02015 } 02016 02024 static xsltElemPreCompPtr 02025 xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst, 02026 xsltTransformFunction function) 02027 { 02028 xsltElemPreCompPtr ret; 02029 02030 if (style == NULL) { 02031 xsltTransformError(NULL, NULL, inst, 02032 "xsltExtElementTest: no transformation context\n"); 02033 return (NULL); 02034 } 02035 if (testStyleData == NULL) { 02036 xsltGenericDebug(xsltGenericDebugContext, 02037 "xsltExtElementPreCompTest: not initialized," 02038 " calling xsltStyleGetExtData\n"); 02039 xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL); 02040 if (testStyleData == NULL) { 02041 xsltTransformError(NULL, style, inst, 02042 "xsltExtElementPreCompTest: not initialized\n"); 02043 if (style != NULL) 02044 style->errors++; 02045 return (NULL); 02046 } 02047 } 02048 if (inst == NULL) { 02049 xsltTransformError(NULL, style, inst, 02050 "xsltExtElementPreCompTest: no instruction\n"); 02051 if (style != NULL) 02052 style->errors++; 02053 return (NULL); 02054 } 02055 ret = xsltNewElemPreComp(style, inst, function); 02056 return (ret); 02057 } 02058 02068 static void 02069 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, 02070 xmlNodePtr inst, 02071 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) 02072 { 02073 xmlNodePtr commentNode; 02074 02075 if (testData == NULL) { 02076 xsltGenericDebug(xsltGenericDebugContext, 02077 "xsltExtElementTest: not initialized," 02078 " calling xsltGetExtData\n"); 02079 xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL); 02080 if (testData == NULL) { 02081 xsltTransformError(ctxt, NULL, inst, 02082 "xsltExtElementTest: not initialized\n"); 02083 return; 02084 } 02085 } 02086 if (ctxt == NULL) { 02087 xsltTransformError(ctxt, NULL, inst, 02088 "xsltExtElementTest: no transformation context\n"); 02089 return; 02090 } 02091 if (node == NULL) { 02092 xsltTransformError(ctxt, NULL, inst, 02093 "xsltExtElementTest: no current node\n"); 02094 return; 02095 } 02096 if (inst == NULL) { 02097 xsltTransformError(ctxt, NULL, inst, 02098 "xsltExtElementTest: no instruction\n"); 02099 return; 02100 } 02101 if (ctxt->insert == NULL) { 02102 xsltTransformError(ctxt, NULL, inst, 02103 "xsltExtElementTest: no insertion point\n"); 02104 return; 02105 } 02106 commentNode = xmlNewComment((const xmlChar *) 02107 "libxslt:test element test worked"); 02108 xmlAddChild(ctxt->insert, commentNode); 02109 } 02110 02120 static void * 02121 xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) 02122 { 02123 if (testStyleData == NULL) { 02124 xsltGenericDebug(xsltGenericErrorContext, 02125 "xsltExtInitTest: not initialized," 02126 " calling xsltStyleGetExtData\n"); 02127 testStyleData = xsltStyleGetExtData(ctxt->style, URI); 02128 if (testStyleData == NULL) { 02129 xsltTransformError(ctxt, NULL, NULL, 02130 "xsltExtInitTest: not initialized\n"); 02131 return (NULL); 02132 } 02133 } 02134 if (testData != NULL) { 02135 xsltTransformError(ctxt, NULL, NULL, 02136 "xsltExtInitTest: already initialized\n"); 02137 return (NULL); 02138 } 02139 testData = (void *) "test data"; 02140 xsltGenericDebug(xsltGenericDebugContext, 02141 "Registered test module : %s\n", URI); 02142 return (testData); 02143 } 02144 02145 02154 static void 02155 xsltExtShutdownTest(xsltTransformContextPtr ctxt, 02156 const xmlChar * URI, void *data) 02157 { 02158 if (testData == NULL) { 02159 xsltTransformError(ctxt, NULL, NULL, 02160 "xsltExtShutdownTest: not initialized\n"); 02161 return; 02162 } 02163 if (data != testData) { 02164 xsltTransformError(ctxt, NULL, NULL, 02165 "xsltExtShutdownTest: wrong data\n"); 02166 } 02167 testData = NULL; 02168 xsltGenericDebug(xsltGenericDebugContext, 02169 "Unregistered test module : %s\n", URI); 02170 } 02171 02181 static void * 02182 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, 02183 const xmlChar * URI) 02184 { 02185 if (testStyleData != NULL) { 02186 xsltTransformError(NULL, NULL, NULL, 02187 "xsltExtInitTest: already initialized\n"); 02188 return (NULL); 02189 } 02190 testStyleData = (void *) "test data"; 02191 xsltGenericDebug(xsltGenericDebugContext, 02192 "Registered test module : %s\n", URI); 02193 return (testStyleData); 02194 } 02195 02196 02205 static void 02206 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, 02207 const xmlChar * URI, void *data) 02208 { 02209 if (testStyleData == NULL) { 02210 xsltGenericError(xsltGenericErrorContext, 02211 "xsltExtShutdownTest: not initialized\n"); 02212 return; 02213 } 02214 if (data != testStyleData) { 02215 xsltTransformError(NULL, NULL, NULL, 02216 "xsltExtShutdownTest: wrong data\n"); 02217 } 02218 testStyleData = NULL; 02219 xsltGenericDebug(xsltGenericDebugContext, 02220 "Unregistered test module : %s\n", URI); 02221 } 02222 02228 void 02229 xsltRegisterTestModule(void) 02230 { 02231 xsltInitGlobals(); 02232 xsltRegisterExtModuleFull((const xmlChar *) XSLT_DEFAULT_URL, 02233 xsltExtInitTest, xsltExtShutdownTest, 02234 xsltExtStyleInitTest, 02235 xsltExtStyleShutdownTest); 02236 xsltRegisterExtModuleFunction((const xmlChar *) "test", 02237 (const xmlChar *) XSLT_DEFAULT_URL, 02238 xsltExtFunctionTest); 02239 xsltRegisterExtModuleElement((const xmlChar *) "test", 02240 (const xmlChar *) XSLT_DEFAULT_URL, 02241 xsltExtElementPreCompTest, 02242 xsltExtElementTest); 02243 } 02244 02245 static void 02246 xsltHashScannerModuleFree(void *payload ATTRIBUTE_UNUSED, 02247 void *data ATTRIBUTE_UNUSED, 02248 xmlChar * name ATTRIBUTE_UNUSED) 02249 { 02250 #ifdef WITH_MODULES 02251 xmlModuleClose(payload); 02252 #endif 02253 } 02254 02260 void 02261 xsltInitGlobals(void) 02262 { 02263 if (xsltExtMutex == NULL) { 02264 xsltExtMutex = xmlNewMutex(); 02265 } 02266 } 02267 02273 void 02274 xsltCleanupGlobals(void) 02275 { 02276 xsltUnregisterAllExtModules(); 02277 xsltUnregisterAllExtModuleFunction(); 02278 xsltUnregisterAllExtModuleElement(); 02279 xsltUnregisterAllExtModuleTopLevel(); 02280 02281 xmlMutexLock(xsltExtMutex); 02282 /* cleanup dynamic module hash */ 02283 if (NULL != xsltModuleHash) { 02284 xmlHashScan(xsltModuleHash, xsltHashScannerModuleFree, 0); 02285 xmlHashFree(xsltModuleHash, NULL); 02286 xsltModuleHash = NULL; 02287 } 02288 xmlMutexUnlock(xsltExtMutex); 02289 02290 xmlFreeMutex(xsltExtMutex); 02291 xsltExtMutex = NULL; 02292 xsltUninit(); 02293 } 02294 02295 static void 02296 xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED, 02297 FILE * output, const xmlChar * name, 02298 const xmlChar * URI, 02299 const xmlChar * not_used ATTRIBUTE_UNUSED) 02300 { 02301 if (!name || !URI) 02302 return; 02303 fprintf(output, "{%s}%s\n", URI, name); 02304 } 02305 02306 static void 02307 xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED, 02308 FILE * output, const xmlChar * URI, 02309 const xmlChar * not_used ATTRIBUTE_UNUSED, 02310 const xmlChar * not_used2 ATTRIBUTE_UNUSED) 02311 { 02312 if (!URI) 02313 return; 02314 fprintf(output, "%s\n", URI); 02315 } 02316 02323 void 02324 xsltDebugDumpExtensions(FILE * output) 02325 { 02326 if (output == NULL) 02327 output = stdout; 02328 fprintf(output, 02329 "Registered XSLT Extensions\n--------------------------\n"); 02330 if (!xsltFunctionsHash) 02331 fprintf(output, "No registered extension functions\n"); 02332 else { 02333 fprintf(output, "Registered Extension Functions:\n"); 02334 xmlMutexLock(xsltExtMutex); 02335 xmlHashScanFull(xsltFunctionsHash, 02336 (xmlHashScannerFull) 02337 xsltDebugDumpExtensionsCallback, output); 02338 xmlMutexUnlock(xsltExtMutex); 02339 } 02340 if (!xsltElementsHash) 02341 fprintf(output, "\nNo registered extension elements\n"); 02342 else { 02343 fprintf(output, "\nRegistered Extension Elements:\n"); 02344 xmlMutexLock(xsltExtMutex); 02345 xmlHashScanFull(xsltElementsHash, 02346 (xmlHashScannerFull) 02347 xsltDebugDumpExtensionsCallback, output); 02348 xmlMutexUnlock(xsltExtMutex); 02349 } 02350 if (!xsltExtensionsHash) 02351 fprintf(output, "\nNo registered extension modules\n"); 02352 else { 02353 fprintf(output, "\nRegistered Extension Modules:\n"); 02354 xmlMutexLock(xsltExtMutex); 02355 xmlHashScanFull(xsltExtensionsHash, 02356 (xmlHashScannerFull) 02357 xsltDebugDumpExtModulesCallback, output); 02358 xmlMutexUnlock(xsltExtMutex); 02359 } 02360 02361 } Generated on Sat May 26 2012 04:18:25 for ReactOS by
1.7.6.1
|