ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

extensions.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.