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