You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

415 lines
11 KiB

Index: libexslt/exslt.c
--- libexslt/exslt.c.orig 2015-05-10 16:11:29.000000000 +0200
+++ libexslt/exslt.c 2019-10-31 07:12:32.698204000 +0100
@@ -36,5 +36,8 @@
exsltDateRegister();
exsltSaxonRegister();
exsltDynRegister();
+#ifdef EXSLT_REGEXP_ENABLED
+ exsltRegexpRegister();
+#endif
}
Index: libexslt/exslt.h
--- libexslt/exslt.h.orig 2012-09-04 16:26:23.000000000 +0200
+++ libexslt/exslt.h 2019-10-31 07:12:32.698331000 +0100
@@ -83,6 +83,7 @@
EXSLTPUBFUN void EXSLTCALL exsltDateRegister (void);
EXSLTPUBFUN void EXSLTCALL exsltSaxonRegister (void);
EXSLTPUBFUN void EXSLTCALL exsltDynRegister(void);
+EXSLTPUBFUN void EXSLTCALL exsltRegexpRegister(void);
EXSLTPUBFUN void EXSLTCALL exsltRegisterAll (void);
Index: libexslt/regexp.c
--- libexslt/regexp.c.orig 2019-10-31 07:12:32.698502000 +0100
+++ libexslt/regexp.c 2019-10-31 07:12:32.698489000 +0100
@@ -0,0 +1,376 @@
+/*
+ * regexp.c: Implementation of the EXSLT Regular Expressions module
+ * References: http://exslt.org/regexp/index.html
+ * Authors: Joel W. Reed <joel.reed@ddiworld.com>
+ */
+
+#if 0 /* we are embedded */
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#define IN_LIBEXSLT
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+#include <libexslt/exsltexports.h>
+#endif
+
+#include <string.h>
+#include "pcre.h"
+
+/**
+ * EXSLT_REGEXP_NAMESPACE:
+ *
+ * Namespace for EXSLT regexp functions
+ */
+#undef EXSLT_REGEXP_NAMESPACE
+#define EXSLT_REGEXP_NAMESPACE ((const xmlChar *)"http://exslt.org/regular-expressions")
+
+static void
+exsltRegexpFlagsFromString(
+ const xmlChar* flagstr,
+ int* global, int* flags)
+{
+ const xmlChar* i = flagstr;
+
+ /* defaults */
+ (*flags) = PCRE_UTF8;
+ (*global) = 0;
+
+ while (*i != '\0') {
+ if (*i == 'i')
+ (*flags) |= PCRE_CASELESS;
+ else if (*i == 'g')
+ (*global)= 1;
+ /* TODO: support other flags? */
+ i++;
+ }
+}
+
+static int
+exsltRegexpExecute(
+ xmlXPathParserContextPtr ctxt,
+ const xmlChar* haystack, const xmlChar *regexp,
+ int flags, int ovector[], int ovector_len)
+{
+ int haystack_len = 0;
+ pcre *compiled_regexp = NULL;
+ int rc = 0, erroffset = 0;
+ const char *error = 0;
+
+ compiled_regexp = pcre_compile(
+ (const char *)regexp, /* the pattern */
+ flags, /* default options */
+ &error, /* for error message */
+ &erroffset, /* for error offset */
+ NULL); /* use default character tables */
+ if (compiled_regexp == NULL) {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:regexp failed to compile %s (char: %d). %s", regexp, erroffset, error);
+ return -1;
+ }
+
+ haystack_len = xmlUTF8Strlen (haystack);
+
+ rc = pcre_exec(
+ compiled_regexp, /* result of pcre_compile() */
+ NULL, /* we didn't study the pattern */
+ (const char *)haystack, /* the subject string */
+ haystack_len, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ (int*)ovector, /* vector of integers for substring information */
+ ovector_len); /* number of elements in the vector (NOT size in bytes) */
+ if (rc < -1) {
+ xsltTransformError(xsltXPathGetTransformContext (ctxt), NULL, NULL,
+ "exslt:regexp failed to execute %s for %s", regexp, haystack);
+ rc = 0;
+ }
+
+ if (compiled_regexp != NULL)
+ pcre_free(compiled_regexp);
+ return rc;
+}
+
+/**
+ * exsltRegexpMatchFunction:
+ * @ns:
+ *
+ * Returns a node set of string matches
+ */
+static void
+exsltRegexpMatchFunction(
+ xmlXPathParserContextPtr ctxt,
+ int nargs)
+{
+ xsltTransformContextPtr tctxt;
+ xmlNodePtr node;
+ xmlDocPtr container;
+ xmlXPathObjectPtr ret = NULL;
+ xmlChar *haystack, *regexp, *flagstr, *working, *match;
+ int rc, flags, global, ovector[3];
+
+ if ((nargs < 1) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ flagstr = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (flagstr == NULL)) {
+ return;
+ }
+
+ regexp = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (regexp == NULL)) {
+ xmlFree(flagstr);
+ return;
+ }
+
+ haystack = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (haystack == NULL)) {
+ xmlFree(regexp);
+ xmlFree(flagstr);
+ return;
+ }
+
+ /* Return a result tree fragment */
+ tctxt = xsltXPathGetTransformContext(ctxt);
+ if (tctxt == NULL) {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:regexp : internal error tctxt == NULL\n");
+ goto fail;
+ }
+
+ container = xsltCreateRVT(tctxt);
+ if (container != NULL) {
+ xsltRegisterTmpRVT(tctxt, container);
+ ret = xmlXPathNewNodeSet(NULL);
+ if (ret != NULL) {
+ ret->boolval = 0;
+
+ exsltRegexpFlagsFromString(flagstr, &global, &flags);
+ working = haystack;
+ rc = exsltRegexpExecute(ctxt, working, regexp, flags,
+ ovector, sizeof(ovector)/sizeof(int));
+
+ while (rc > 0) {
+ match = xmlStrsub(working, ovector[0], ovector[1]-ovector[0]);
+ if (NULL == match) goto fail;
+
+ node = xmlNewDocRawNode(container, NULL, (const xmlChar *)"match", match);
+ xmlFree(match);
+
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+
+ if (!global) break;
+
+ working = working + ovector[1];
+ rc = exsltRegexpExecute(ctxt, working, regexp, flags,
+ ovector, sizeof(ovector)/sizeof(int));
+ }
+ }
+ }
+
+ fail:
+ if (flagstr != NULL)
+ xmlFree(flagstr);
+ if (regexp != NULL)
+ xmlFree(regexp);
+ if (haystack != NULL)
+ xmlFree(haystack);
+
+ if (ret != NULL)
+ valuePush(ctxt, ret);
+ else
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * exsltRegexpReplaceFunction:
+ * @ns:
+ *
+ * Returns a node set of string matches
+ */
+
+static void
+exsltRegexpReplaceFunction(
+ xmlXPathParserContextPtr ctxt,
+ int nargs)
+{
+ xmlChar *haystack, *regexp, *flagstr, *replace, *tmp;
+ xmlChar *result = NULL, *working, *end;
+ int rc, flags, global, ovector[3];
+
+ if ((nargs < 1) || (nargs > 4)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ replace = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (replace == NULL)) {
+ return;
+ }
+
+ flagstr = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (flagstr == NULL)) {
+ xmlFree(replace);
+ return;
+ }
+
+ regexp = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (regexp == NULL)) {
+ xmlFree(flagstr);
+ xmlFree(replace);
+ return;
+ }
+
+ haystack = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (haystack == NULL)) {
+ xmlFree(regexp);
+ xmlFree(flagstr);
+ xmlFree(replace);
+ return;
+ }
+
+ exsltRegexpFlagsFromString(flagstr, &global, &flags);
+
+ working = haystack;
+ rc = exsltRegexpExecute(
+ ctxt, working, regexp, flags,
+ ovector, sizeof(ovector)/sizeof(int));
+
+ while (rc > 0 ) {
+ if (0 == ovector[0]) {
+ if (NULL==result)
+ result = xmlStrdup(replace);
+ else
+ result = xmlStrcat(result, replace);
+ }
+ else {
+ tmp = xmlStrsub(working, 0, ovector[0]);
+ if (NULL == result)
+ result = tmp;
+ else {
+ result = xmlStrcat(result, tmp);
+ xmlFree(tmp);
+ }
+ result = xmlStrcat(result, replace);
+ }
+
+ working = working + ovector[1];
+
+ if (!global)
+ break;
+ rc = exsltRegexpExecute(
+ ctxt, working, regexp, flags,
+ ovector, sizeof(ovector)/sizeof(int));
+ }
+
+ end = haystack + xmlUTF8Strlen(haystack);
+ if (working < end ) {
+ if (NULL == result)
+ result = xmlStrdup(working);
+ else
+ result = xmlStrcat(result, working);
+ }
+
+ if (replace != NULL)
+ xmlFree(replace);
+ if (flagstr != NULL)
+ xmlFree(flagstr);
+ if (regexp != NULL)
+ xmlFree(regexp);
+ if (haystack != NULL)
+ xmlFree(haystack);
+
+ xmlXPathReturnString(ctxt, result);
+}
+
+/**
+ * exsltRegexpTestFunction:
+ * @ns:
+ *
+ * returns true if the string given as the first argument
+ * matches the regular expression given as the second argument
+ *
+ */
+
+static void
+exsltRegexpTestFunction(
+ xmlXPathParserContextPtr ctxt,
+ int nargs)
+{
+ xmlChar *haystack, *regexp_middle, *regexp, *flagstr;
+ int rc = 0, flags, global, ovector[3];
+
+ if ((nargs < 1) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ flagstr = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (flagstr == NULL)) {
+ return;
+ }
+
+ regexp_middle = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (regexp_middle == NULL)) {
+ xmlFree(flagstr);
+ return;
+ }
+
+ haystack = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (haystack == NULL)) {
+ xmlFree(regexp_middle);
+ xmlFree(flagstr);
+ return;
+ }
+
+ /* build the regexp */
+ regexp = xmlStrdup((const xmlChar *)"\\A");
+ regexp = xmlStrcat(regexp, regexp_middle);
+ regexp = xmlStrcat(regexp, (const xmlChar *)"\\Z");
+
+ exsltRegexpFlagsFromString(flagstr, &global, &flags);
+ rc = exsltRegexpExecute(
+ ctxt, haystack, regexp, flags,
+ ovector, sizeof(ovector)/sizeof(int));
+
+ if (flagstr != NULL)
+ xmlFree(flagstr);
+ if (regexp != NULL)
+ xmlFree(regexp);
+ if (regexp_middle != NULL)
+ xmlFree(regexp_middle);
+ if (haystack != NULL)
+ xmlFree(haystack);
+
+ xmlXPathReturnBoolean(ctxt, (rc > 0));
+}
+
+/**
+ * exsltRegexpRegister:
+ *
+ * Registers the EXSLT - Regexp module
+ */
+void
+EXSLTPUBFUN exsltRegexpRegister (void)
+{
+ xsltRegisterExtModuleFunction(
+ (const xmlChar *)"match",
+ EXSLT_REGEXP_NAMESPACE,
+ exsltRegexpMatchFunction);
+ xsltRegisterExtModuleFunction(
+ (const xmlChar *)"replace",
+ EXSLT_REGEXP_NAMESPACE,
+ exsltRegexpReplaceFunction);
+ xsltRegisterExtModuleFunction(
+ (const xmlChar *)"test",
+ EXSLT_REGEXP_NAMESPACE,
+ exsltRegexpTestFunction);
+}
+
Index: libexslt/strings.c
--- libexslt/strings.c.orig 2017-10-30 08:49:55.000000000 +0100
+++ libexslt/strings.c 2019-10-31 07:12:32.698662000 +0100
@@ -889,3 +889,8 @@
}
return -1;
}
+
+#ifdef EXSLT_REGEXP_ENABLED
+#include "regexp.c"
+#endif
+