I've attached a new version of the plugin patch, plus an implementation of exslt:regexp. The plugin implements exslt:replace, exslt:match, and exslt:test as documented here: http://www.exslt.org/regexp/index.html The plugin uses pcre 5.0 or later. It was tested against libxml2 CVS and libxslt CVS plus plugin patch. I built some test cases and ran the code thru many permutations all successful, but this is the first time i've coded xpath return sets and used pcre, so code reviews/testing help appreciated. The xslt plugin patch has been updated to the new libxml2 module api, plus it now actually calls xmlModuleClose in xsltCleanupGlobals. I plan to check out and try to add hooks to xslt security module, and eventually test on win32. Please feel free to beat me to win32 if you like :-) jr
Index: configure.in =================================================================== RCS file: /cvs/gnome/libxslt/configure.in,v retrieving revision 1.163 diff -u -w -b -B -r1.163 configure.in --- configure.in 29 Oct 2004 15:07:14 -0000 1.163 +++ configure.in 9 Jan 2005 00:20:27 -0000 @@ -435,6 +435,35 @@ AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) +AC_ARG_WITH(plugins, +[ --with-plugins Add plugin extension support (off)]) +if test "$with_plugins" = "" +then + with_plugins=no +fi + +if test "$with_plugins" = "yes" ; then + AC_MSG_CHECKING([libxml2 module support]) + WITH_MODULES="`$XML_CONFIG --modules`" + if test "${WITH_MODULES}" = "1"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi +else + WITH_MODULES="0" +fi + +AC_SUBST(WITH_MODULES) + +dnl +dnl setup default module path +dnl +module_prefix=$prefix +test "x$module_prefix" = xNONE && module_prefix=$ac_default_prefix +LIBXSLT_DEFAULT_PLUGINS_PATH="\"$module_prefix/lib/libxslt/$LIBXSLT_MAJOR_VERSION.$LIBXSLT_MINOR_VERSION/\"" +AC_SUBST(LIBXSLT_DEFAULT_PLUGINS_PATH) + dnl dnl In build tree I use a static version with memory debug enabled dnl Index: libxslt/extensions.c =================================================================== RCS file: /cvs/gnome/libxslt/libxslt/extensions.c,v retrieving revision 1.35 diff -u -w -b -B -r1.35 extensions.c --- libxslt/extensions.c 1 Dec 2004 14:44:56 -0000 1.35 +++ libxslt/extensions.c 9 Jan 2005 00:20:29 -0000 @@ -13,6 +13,7 @@ #include "libxslt.h" #include <string.h> +#include <limits.h> #include <libxml/xmlmemory.h> #include <libxml/tree.h> @@ -20,12 +21,20 @@ #include <libxml/xmlerror.h> #include <libxml/parserInternals.h> #include <libxml/xpathInternals.h> +#include <libxml/xmlmodule.h> +#include <libxml/list.h> +#include <libxml/xmlIO.h> #include "xslt.h" #include "xsltInternals.h" #include "xsltutils.h" #include "imports.h" #include "extensions.h" +#ifdef _WIN32 +#include <stdlib.h> /* for _MAX_PATH */ +#define PATH_MAX _MAX_PATH +#endif + #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_EXTENSIONS #endif @@ -72,6 +81,7 @@ static xmlHashTablePtr xsltFunctionsHash = NULL; static xmlHashTablePtr xsltElementsHash = NULL; static xmlHashTablePtr xsltTopLevelsHash = NULL; +static xmlHashTablePtr xsltModuleHash = NULL; /************************************************************************ * * @@ -269,6 +279,85 @@ } +/** + * xsltExtModuleRegisterDynamic: + * @URI: the function or element namespace URI + * + * Looks up an extension module to dynamically load + * based on the namespace URI + * + * Returns 0 if successful, -1 in case of error. + */ + +#ifdef WITH_MODULES +typedef void (*exsltRegisterFunction) (void); + +int +static xsltExtModuleRegisterDynamic (const xmlChar *URI) { + + xmlModulePtr m; + exsltRegisterFunction regfunc; + xmlChar module_filename[PATH_MAX]; + const xmlChar *extNameBegin = NULL; + const xmlChar *extDirectory = NULL; + int i, rc, seen_before; + + /* check for bad inputs */ + if (URI == NULL) + return(-1); + + if (NULL == xsltModuleHash) { + xsltModuleHash = xmlHashCreate(5); + if (xsltModuleHash == NULL) + return(-1); + } + + /* have we attempted to register this module already? */ + seen_before = (int)xmlHashLookup(xsltModuleHash, URI); + if (0 != seen_before) { + return(-1); + } + + for (i = xmlStrlen(URI); i != 0 && extNameBegin == NULL; --i) + { + if (URI[i-1] == '/') extNameBegin = URI + i; + } + + if (extNameBegin == NULL || *extNameBegin == '\0') + return(-1); + + /* determine module directory */ + extDirectory = getenv("LIBXSLT_PLUGINS_PATH"); + if (NULL == extDirectory) + extDirectory = LIBXSLT_DEFAULT_PLUGINS_PATH(); + if (NULL == extDirectory) + return(-1); + + /* build the module filename, and confirm the module exists */ + xmlStrPrintf(module_filename, sizeof(module_filename), "%s%s%s", + extDirectory, extNameBegin, + LIBXML_MODULE_EXTENSION); + if (1 != xmlCheckFilename(module_filename)) + return(-1); + + m = xmlModuleOpen(module_filename, 0); + if (NULL == m) + return(-1); + + rc = xmlModuleSymbol(m, "exsltRegisterModule", (void**)®func); + if (0 == rc) { + (*regfunc)(); + } + + /* register this module in our hash */ + xmlHashAddEntry(xsltModuleHash, URI, (void*)m); + + return (NULL == regfunc)? -1 : 0; +} +#else +#define xsltExtModuleRegisterDynamic(b) -1 +#endif + /************************************************************************ * * * The stylesheet extension prefixes handling * @@ -330,6 +419,12 @@ xsltExtModulePtr module; module = xmlHashLookup(xsltExtensionsHash, URI); + if (NULL == module) { + if (!xsltExtModuleRegisterDynamic(URI)) { + module = xmlHashLookup(xsltExtensionsHash, URI); + } + } + if (module != NULL) { xsltStyleGetExtData(style, URI); } @@ -959,6 +1055,14 @@ return(NULL); XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI); + + /* if lookup fails, attempt a dynamic load on supported platforms */ + if (NULL == ret) { + if (!xsltExtModuleRegisterDynamic(URI)) { + XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI); + } + } + return ret; } @@ -1160,6 +1264,14 @@ ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); + /* if function lookup fails, attempt a dynamic load on supported platforms */ + ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); + if (NULL == ext) { + if (!xsltExtModuleRegisterDynamic(URI)) { + ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); + } + } + if (ext == NULL) return(NULL); return(ext->transform); @@ -1184,6 +1296,12 @@ ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); + if (ext == NULL) { + if (!xsltExtModuleRegisterDynamic(URI)) { + ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); + } + } + if (ext == NULL) return(NULL); return(ext->precomp); @@ -1262,6 +1380,14 @@ return(NULL); XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI); + + /* if lookup fails, attempt a dynamic load on supported platforms */ + if (NULL == ret) { + if (!xsltExtModuleRegisterDynamic(URI)) { + XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI); + } + } + return(ret); } @@ -1599,6 +1725,14 @@ xsltExtElementTest); } +static void +xsltHashScannerModuleFree(void * payload, void * data, xmlChar * name) +{ +#ifdef WITH_MODULES + xmlModuleClose(payload); +#endif +} + /** * xsltCleanupGlobals: * @@ -1611,6 +1745,14 @@ xsltUnregisterAllExtModuleFunction(); xsltUnregisterAllExtModuleElement(); xsltUnregisterAllExtModuleTopLevel(); + + /* cleanup dynamic module hash */ + if (NULL != xsltModuleHash) + { + xmlHashScan(xsltModuleHash, xsltHashScannerModuleFree, 0); + xmlHashFree(xsltModuleHash, NULL); + xsltModuleHash = NULL; + } } static void Index: libxslt/xslt.c =================================================================== RCS file: /cvs/gnome/libxslt/libxslt/xslt.c,v retrieving revision 1.113 diff -u -w -b -B -r1.113 xslt.c Index: libxslt/xsltconfig.h.in =================================================================== RCS file: /cvs/gnome/libxslt/libxslt/xsltconfig.h.in,v retrieving revision 1.22 diff -u -w -b -B -r1.22 xsltconfig.h.in --- libxslt/xsltconfig.h.in 18 Aug 2004 21:27:08 -0000 1.22 +++ libxslt/xsltconfig.h.in 9 Jan 2005 00:20:31 -0000 @@ -107,6 +107,19 @@ #endif /** + * WITH_MODULES: + * + * Whether module support is configured into libxslt + * Note: no default module path for win32 platforms + */ +#if @WITH_MODULES@ +#ifndef WITH_MODULES +#define WITH_MODULES +#endif +#define LIBXSLT_DEFAULT_PLUGINS_PATH() @LIBXSLT_DEFAULT_PLUGINS_PATH@ +#endif + +/** * ATTRIBUTE_UNUSED: * * This macro is used to flag unused function parameters to GCC Index: libxslt/xsltwin32config.h =================================================================== RCS file: /cvs/gnome/libxslt/libxslt/xsltwin32config.h,v retrieving revision 1.71 diff -u -w -b -B -r1.71 xsltwin32config.h --- libxslt/xsltwin32config.h 23 Dec 2004 08:08:11 -0000 1.71 +++ libxslt/xsltwin32config.h 9 Jan 2005 00:20:31 -0000 @@ -40,11 +40,11 @@ #define LIBXSLT_VERSION_STRING "10112" /** - * LIBXSLT_VERSION_EXTRA + * LIBXSLT_VERSION_EXTRA: * * extra version information, used to show a CVS compilation */ -#define LIBXML_VERSION_EXTRA "-CVS975" +#define LIBXML_VERSION_EXTRA "-CVS977" /** * WITH_XSLT_DEBUG: @@ -55,6 +55,18 @@ */ #if 1 #define WITH_XSLT_DEBUG +#endif + +/** + * WITH_MODULES: + * + * Whether module support is configured into libxslt + */ +#if 1 +#ifndef WITH_MODULES +#define WITH_MODULES +#endif +#define LIBXSLT_PLUGINS_PATH() getenv("LIBXSLT_PLUGINS_PATH") #endif #if 0 Index: libxslt/xsltwin32config.h.in =================================================================== RCS file: /cvs/gnome/libxslt/libxslt/xsltwin32config.h.in,v retrieving revision 1.7 diff -u -w -b -B -r1.7 xsltwin32config.h.in --- libxslt/xsltwin32config.h.in 18 Aug 2004 21:27:08 -0000 1.7 +++ libxslt/xsltwin32config.h.in 9 Jan 2005 00:20:31 -0000 @@ -40,7 +40,7 @@ #define LIBXSLT_VERSION_STRING "@LIBXSLT_VERSION_NUMBER@" /** - * LIBXSLT_VERSION_EXTRA + * LIBXSLT_VERSION_EXTRA: * * extra version information, used to show a CVS compilation */ @@ -55,6 +55,18 @@ */ #if 1 #define WITH_XSLT_DEBUG +#endif + +/** + * WITH_MODULES: + * + * Whether module support is configured into libxslt + */ +#if @WITH_MODULES@ +#ifndef WITH_MODULES +#define WITH_MODULES +#endif +#define LIBXSLT_PLUGINS_PATH() getenv("LIBXSLT_PLUGINS_PATH") #endif #if 0 Index: win32/configure.js =================================================================== RCS file: /cvs/gnome/libxslt/win32/configure.js,v retrieving revision 1.15 diff -u -w -b -B -r1.15 configure.js --- win32/configure.js 24 Aug 2004 14:43:44 -0000 1.15 +++ win32/configure.js 9 Jan 2005 00:20:37 -0000 @@ -48,6 +48,7 @@ var withIconv = true; var withZlib = false; var withCrypto = true; +var withModules = false; /* Win32 build options. */ var dirSep = "\\"; var compiler = "msvc"; @@ -105,6 +106,7 @@ txt += " iconv: Use iconv library (" + (withIconv? "yes" : "no") + ")\n"; txt += " zlib: Use zlib library (" + (withZlib? "yes" : "no") + ")\n"; txt += " crypto: Enable Crypto support (" + (withCrypto? "yes" : "no") + ")\n"; + txt += " modules: Enable Module support (" + (withModules? "yes" : "no") + ")\n"; txt += "\nWin32 build options, default value given in parentheses:\n\n"; txt += " compiler: Compiler to be used [msvc|mingw] (" + compiler + ")\n"; txt += " cruntime: C-runtime compiler option (only msvc) (" + cruntime + ")\n"; @@ -188,6 +190,7 @@ vf.WriteLine("WITH_ICONV=" + (withIconv? "1" : "0")); vf.WriteLine("WITH_ZLIB=" + (withZlib? "1" : "0")); vf.WriteLine("WITH_CRYPTO=" + (withCrypto? "1" : "0")); + vf.WriteLine("WITH_MODULES=" + (withModules? "1" : "0")); vf.WriteLine("DEBUG=" + (buildDebug? "1" : "0")); vf.WriteLine("STATIC=" + (buildStatic? "1" : "0")); vf.WriteLine("PREFIX=" + buildPrefix); @@ -233,6 +236,10 @@ of.WriteLine(s.replace(/\ WITH_MEM_DEBUG\@/, withMemDebug? "1" : "0")); } else if (s.search(/\ WITH_DEBUGGER\@/) != -1) { of.WriteLine(s.replace(/\ WITH_DEBUGGER\@/, withDebugger? "1" : "0")); + } else if (s.search(/\ WITH_MODULES\@/) != -1) { + of.WriteLine(s.replace(/\ WITH_MODULES\@/, withModules? "1" : "0")); + } else if (s.search(/\ LIBXSLT_DEFAULT_PLUGINS_PATH\@/) != -1) { + of.WriteLine(s.replace(/\ LIBXSLT_DEFAULT_PLUGINS_PATH\@/, "NULL")); } else of.WriteLine(ln); } @@ -262,6 +269,8 @@ of.WriteLine(s.replace(/\ LIBEXSLT_VERSION_EXTRA\@/, verCvs)); } else if (s.search(/\ WITH_CRYPTO\@/) != -1) { of.WriteLine(s.replace(/\ WITH_CRYPTO\@/, withCrypto? "1" : "0")); + } else if (s.search(/\ WITH_MODULES\@/) != -1) { + of.WriteLine(s.replace(/\ WITH_MODULES\@/, withModules? "1" : "0")); } else of.WriteLine(ln); } @@ -332,6 +341,8 @@ withZlib = strToBool(arg.substring(opt.length + 1, arg.length)); else if (opt == "crypto") withCrypto = strToBool(arg.substring(opt.length + 1, arg.length)); + else if (opt == "modules") + withModules = strToBool(arg.substring(opt.length + 1, arg.length)); else if (opt == "compiler") compiler = arg.substring(opt.length + 1, arg.length); else if (opt == "cruntime") @@ -446,6 +457,7 @@ txtOut += " Use iconv: " + boolToStr(withIconv) + "\n"; txtOut += " With zlib: " + boolToStr(withZlib) + "\n"; txtOut += " Crypto: " + boolToStr(withCrypto) + "\n"; +txtOut += " Modules: " + boolToStr(withModules) + "\n"; txtOut += "\n"; txtOut += "Win32 build configuration\n"; txtOut += "-------------------------\n";
Attachment:
xslt-plugin-regexp-0.1.tar.gz
Description: application/tar-gz