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
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 |
|
+
|
|
|