[xslt] plugin patch v3 plus exslt:regexp implementation



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**)&regfunc);
+  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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]