From 5c0faa58cf4776550097dbcc1d2f5867c929d5a6 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sun, 4 Feb 2018 15:52:31 +0100 Subject: [PATCH] [LIBXSLT] Update to version 1.1.32. CORE-14291 --- dll/3rdparty/libxslt/Makefile.am | 2 +- dll/3rdparty/libxslt/attributes.c | 752 ++++++++++-------- dll/3rdparty/libxslt/extensions.c | 3 +- dll/3rdparty/libxslt/extra.c | 138 +--- dll/3rdparty/libxslt/extra.h | 8 - dll/3rdparty/libxslt/functions.c | 29 +- dll/3rdparty/libxslt/keys.c | 3 + dll/3rdparty/libxslt/numbers.c | 123 ++- dll/3rdparty/libxslt/pattern.c | 32 +- dll/3rdparty/libxslt/preproc.c | 5 +- dll/3rdparty/libxslt/security.c | 4 +- dll/3rdparty/libxslt/templates.c | 17 +- dll/3rdparty/libxslt/transform.c | 257 +++--- dll/3rdparty/libxslt/variables.c | 176 ++-- dll/3rdparty/libxslt/xslt.c | 127 ++- dll/3rdparty/libxslt/xsltconfig.h.in | 13 - dll/3rdparty/libxslt/xsltlocale.c | 25 +- dll/3rdparty/libxslt/xsltutils.c | 25 +- dll/3rdparty/libxslt/xsltwin32config.h | 10 +- sdk/include/reactos/libs/libxslt/libxslt.h | 2 +- sdk/include/reactos/libs/libxslt/variables.h | 35 + .../reactos/libs/libxslt/xsltInternals.h | 18 +- sdk/include/reactos/libs/libxslt/xsltconfig.h | 19 +- sdk/include/reactos/libs/libxslt/xsltlocale.h | 33 +- 24 files changed, 945 insertions(+), 911 deletions(-) diff --git a/dll/3rdparty/libxslt/Makefile.am b/dll/3rdparty/libxslt/Makefile.am index d9fed686846..ef2de24e2ef 100644 --- a/dll/3rdparty/libxslt/Makefile.am +++ b/dll/3rdparty/libxslt/Makefile.am @@ -62,7 +62,7 @@ else LIBXSLT_VERSION_SCRIPT = endif -libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS) +libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS) $(M_LIBS) libxslt_la_LDFLAGS = \ $(WIN32_EXTRA_LDFLAGS) \ $(LIBXSLT_VERSION_SCRIPT) \ diff --git a/dll/3rdparty/libxslt/attributes.c b/dll/3rdparty/libxslt/attributes.c index c038a3cb67f..8191f44948e 100644 --- a/dll/3rdparty/libxslt/attributes.c +++ b/dll/3rdparty/libxslt/attributes.c @@ -16,14 +16,6 @@ #define WITH_XSLT_DEBUG_ATTRIBUTES #endif -/* - * TODO: merge attribute sets from different import precedence. - * all this should be precomputed just before the transformation - * starts or at first hit with a cache in the context. - * The simple way for now would be to not allow redefinition of - * attributes once generated in the output tree, possibly costlier. - */ - /* * Useful macros */ @@ -37,6 +29,10 @@ #define IS_BLANK_NODE(n) \ (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content))) +#define ATTRSET_UNRESOLVED 0 +#define ATTRSET_RESOLVING 1 +#define ATTRSET_RESOLVED 2 + /* * The in-memory structure corresponding to an XSLT Attribute in @@ -49,10 +45,36 @@ typedef xsltAttrElem *xsltAttrElemPtr; struct _xsltAttrElem { struct _xsltAttrElem *next;/* chained list */ xmlNodePtr attr; /* the xsl:attribute definition */ - const xmlChar *set; /* or the attribute set */ - const xmlChar *ns; /* and its namespace */ }; +typedef struct _xsltUseAttrSet xsltUseAttrSet; +typedef xsltUseAttrSet *xsltUseAttrSetPtr; +struct _xsltUseAttrSet { + struct _xsltUseAttrSet *next; /* chained list */ + const xmlChar *ncname; + const xmlChar *ns; +}; + +typedef struct _xsltAttrSet xsltAttrSet; +typedef xsltAttrSet *xsltAttrSetPtr; +struct _xsltAttrSet { + int state; + xsltAttrElemPtr attrs; /* list head */ + xsltUseAttrSetPtr useAttrSets; /* list head */ +}; + +typedef struct _xsltAttrSetContext xsltAttrSetContext; +typedef xsltAttrSetContext *xsltAttrSetContextPtr; +struct _xsltAttrSetContext { + xsltStylesheetPtr topStyle; + xsltStylesheetPtr style; +}; + +static void +xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, + xsltStylesheetPtr style, const xmlChar *name, + const xmlChar *ns, int depth); + /************************************************************************ * * * XSLT Attribute handling * @@ -110,11 +132,6 @@ xsltFreeAttrElemList(xsltAttrElemPtr list) { } } -#ifdef XSLT_REFACTORED - /* - * This was moved to xsltParseStylesheetAttributeSet(). - */ -#else /** * xsltAddAttrElemList: * @list: an XSLT AttrElem list @@ -135,9 +152,7 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) { cur = list; while (cur != NULL) { next = cur->next; - if (cur->attr == attr) - return(cur); - if (cur->next == NULL) { + if (next == NULL) { cur->next = xsltNewAttrElem(attr); return(list); } @@ -145,92 +160,174 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) { } return(list); } -#endif /* XSLT_REFACTORED */ /** - * xsltMergeAttrElemList: - * @list: an XSLT AttrElem list - * @old: another XSLT AttrElem list + * xsltNewUseAttrSet: + * @ncname: local name + * @ns: namespace URI * - * Add all the attributes from list @old to list @list, - * but drop redefinition of existing values. + * Create a new XSLT UseAttrSet * - * Returns the new list pointer + * Returns the newly allocated xsltUseAttrSetPtr or NULL in case of error. */ -static xsltAttrElemPtr -xsltMergeAttrElemList(xsltStylesheetPtr style, - xsltAttrElemPtr list, xsltAttrElemPtr old) { +static xsltUseAttrSetPtr +xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) { + xsltUseAttrSetPtr cur; + + cur = (xsltUseAttrSetPtr) xmlMalloc(sizeof(xsltUseAttrSet)); + if (cur == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewUseAttrSet : malloc failed\n"); + return(NULL); + } + memset(cur, 0, sizeof(xsltUseAttrSet)); + cur->ncname = ncname; + cur->ns = ns; + return(cur); +} + +/** + * xsltFreeUseAttrSet: + * @use: an XSLT UseAttrSet + * + * Free up the memory allocated by @use + */ +static void +xsltFreeUseAttrSet(xsltUseAttrSetPtr use) { + xmlFree(use); +} + +/** + * xsltFreeUseAttrSetList: + * @list: an XSLT UseAttrSet list + * + * Free up the memory allocated by @list + */ +static void +xsltFreeUseAttrSetList(xsltUseAttrSetPtr list) { + xsltUseAttrSetPtr next; + + while (list != NULL) { + next = list->next; + xsltFreeUseAttrSet(list); + list = next; + } +} + +/** + * xsltAddUseAttrSetList: + * @list: a xsltUseAttrSet list + * @ncname: local name + * @ns: namespace URI + * + * Add the use-attribute-set name to the list. + * + * Returns the new list pointer. + */ +static xsltUseAttrSetPtr +xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname, + const xmlChar *ns) { + xsltUseAttrSetPtr next, cur; + + if (ncname == NULL) + return(list); + if (list == NULL) + return(xsltNewUseAttrSet(ncname, ns)); + cur = list; + while (cur != NULL) { + if ((cur->ncname == ncname) && (cur->ns == ns)) + return(list); + next = cur->next; + if (next == NULL) { + cur->next = xsltNewUseAttrSet(ncname, ns); + return(list); + } + cur = next; + } + return(list); +} + +/** + * xsltNewAttrSet: + * + * Create a new attribute set. + * + * Returns the newly allocated xsltAttrSetPtr or NULL in case of error. + */ +static xsltAttrSetPtr +xsltNewAttrSet() { + xsltAttrSetPtr cur; + + cur = (xsltAttrSetPtr) xmlMalloc(sizeof(xsltAttrSet)); + if (cur == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewAttrSet : malloc failed\n"); + return(NULL); + } + memset(cur, 0, sizeof(xsltAttrSet)); + return(cur); +} + +/** + * xsltFreeAttrSet: + * @set: an attribute set + * + * Free memory allocated by @set + */ +static void +xsltFreeAttrSet(xsltAttrSetPtr set) { + if (set == NULL) + return; + + xsltFreeAttrElemList(set->attrs); + xsltFreeUseAttrSetList(set->useAttrSets); + xmlFree(set); +} + +/** + * xsltMergeAttrSets: + * @set: an attribute set + * @other: another attribute set + * + * Add all the attributes from @other to @set, + * but drop redefinition of existing values. + */ +static void +xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other) { xsltAttrElemPtr cur; + xsltAttrElemPtr old = other->attrs; int add; while (old != NULL) { - if ((old->attr == NULL) && (old->set == NULL)) { - old = old->next; - continue; - } /* * Check that the attribute is not yet in the list */ - cur = list; + cur = set->attrs; add = 1; while (cur != NULL) { - if ((cur->attr == NULL) && (cur->set == NULL)) { - if (cur->next == NULL) - break; - cur = cur->next; - continue; - } - if ((cur->set != NULL) && (cur->set == old->set)) { - add = 0; - break; - } - if (cur->set != NULL) { - if (cur->next == NULL) - break; - cur = cur->next; - continue; - } - if (old->set != NULL) { - if (cur->next == NULL) - break; - cur = cur->next; - continue; - } - if (cur->attr == old->attr) { - xsltGenericError(xsltGenericErrorContext, - "xsl:attribute-set : use-attribute-sets recursion detected\n"); - return(list); - } + xsltStylePreCompPtr curComp = cur->attr->psvi; + xsltStylePreCompPtr oldComp = old->attr->psvi; + + if ((curComp->name == oldComp->name) && + (curComp->ns == oldComp->ns)) { + add = 0; + break; + } if (cur->next == NULL) break; cur = cur->next; } if (add == 1) { - /* - * Changed to use the string-dict, rather than duplicating - * @set and @ns; this fixes bug #340400. - */ if (cur == NULL) { - list = xsltNewAttrElem(old->attr); - if (old->set != NULL) { - list->set = xmlDictLookup(style->dict, old->set, -1); - if (old->ns != NULL) - list->ns = xmlDictLookup(style->dict, old->ns, -1); - } + set->attrs = xsltNewAttrElem(old->attr); } else if (add) { cur->next = xsltNewAttrElem(old->attr); - if (old->set != NULL) { - cur->next->set = xmlDictLookup(style->dict, old->set, -1); - if (old->ns != NULL) - cur->next->ns = xmlDictLookup(style->dict, old->ns, -1); - } } } old = old->next; } - return(list); } /************************************************************************ @@ -251,9 +348,10 @@ void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { const xmlChar *ncname; const xmlChar *prefix; + const xmlChar *nsUri = NULL; xmlChar *value; xmlNodePtr child; - xsltAttrElemPtr attrItems; + xsltAttrSetPtr set; if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE)) return; @@ -267,9 +365,29 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { return; } + if (xmlValidateQName(value, 0)) { + xsltTransformError(NULL, style, cur, + "xsl:attribute-set : The name '%s' is not a valid QName.\n", + value); + style->errors++; + xmlFree(value); + return; + } + ncname = xsltSplitQName(style->dict, value, &prefix); xmlFree(value); value = NULL; + if (prefix != NULL) { + xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix); + if (ns == NULL) { + xsltTransformError(NULL, style, cur, + "xsl:attribute-set : No namespace found for QName '%s:%s'\n", + prefix, ncname); + style->errors++; + return; + } + nsUri = ns->href; + } if (style->attributeSets == NULL) { #ifdef WITH_XSLT_DEBUG_ATTRIBUTES @@ -281,7 +399,13 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { if (style->attributeSets == NULL) return; - attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix); + set = xmlHashLookup2(style->attributeSets, ncname, nsUri); + if (set == NULL) { + set = xsltNewAttrSet(); + if (set == NULL) + return; + xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set); + } /* * Parse the content. Only xsl:attribute elements are allowed. @@ -307,71 +431,36 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) { "xsl:attribute-set : unexpected child xsl:%s\n", child->name); } else { +#ifdef WITH_XSLT_DEBUG_ATTRIBUTES + xsltGenericDebug(xsltGenericDebugContext, + "add attribute to list %s\n", ncname); +#endif + xsltStylePreCompute(style, child); + if (child->children != NULL) { #ifdef XSLT_REFACTORED - xsltAttrElemPtr nextAttr, curAttr; - - /* - * Process xsl:attribute - * --------------------- - */ - -#ifdef WITH_XSLT_DEBUG_ATTRIBUTES - xsltGenericDebug(xsltGenericDebugContext, - "add attribute to list %s\n", ncname); -#endif - /* - * The following was taken over from - * xsltAddAttrElemList(). - */ - if (attrItems == NULL) { - attrItems = xsltNewAttrElem(child); - } else { - curAttr = attrItems; - while (curAttr != NULL) { - nextAttr = curAttr->next; - if (curAttr->attr == child) { - /* - * URGENT TODO: Can somebody explain - * why attrItems is set to curAttr - * here? Is this somehow related to - * avoidance of recursions? - */ - attrItems = curAttr; - goto next_child; - } - if (curAttr->next == NULL) - curAttr->next = xsltNewAttrElem(child); - curAttr = nextAttr; - } - } - /* - * Parse the xsl:attribute and its content. - */ - xsltParseAnyXSLTElem(XSLT_CCTXT(style), child); + xsltParseSequenceConstructor(XSLT_CCTXT(style), + child->children); #else -#ifdef WITH_XSLT_DEBUG_ATTRIBUTES - xsltGenericDebug(xsltGenericDebugContext, - "add attribute to list %s\n", ncname); -#endif - /* - * OLD behaviour: - */ - attrItems = xsltAddAttrElemList(attrItems, child); + xsltParseTemplateContent(style, child); #endif + } + if (child->psvi == NULL) { + xsltTransformError(NULL, style, child, + "xsl:attribute-set : internal error, attribute %s not " + "compiled\n", child->name); + } + else { + set->attrs = xsltAddAttrElemList(set->attrs, child); + } } -#ifdef XSLT_REFACTORED -next_child: -#endif child = child->next; } /* - * Process attribue "use-attribute-sets". + * Process attribute "use-attribute-sets". */ - /* TODO check recursion */ - value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets", - NULL); + value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL); if (value != NULL) { const xmlChar *curval, *endval; curval = value; @@ -385,21 +474,38 @@ next_child: if (curval) { const xmlChar *ncname2 = NULL; const xmlChar *prefix2 = NULL; - xsltAttrElemPtr refAttrItems; + const xmlChar *nsUri2 = NULL; #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "xsl:attribute-set : %s adds use %s\n", ncname, curval); #endif + + if (xmlValidateQName(curval, 0)) { + xsltTransformError(NULL, style, cur, + "xsl:attribute-set : The name '%s' in " + "use-attribute-sets is not a valid QName.\n", curval); + style->errors++; + xmlFree(value); + return; + } + ncname2 = xsltSplitQName(style->dict, curval, &prefix2); - refAttrItems = xsltNewAttrElem(NULL); - if (refAttrItems != NULL) { - refAttrItems->set = ncname2; - refAttrItems->ns = prefix2; - attrItems = xsltMergeAttrElemList(style, - attrItems, refAttrItems); - xsltFreeAttrElem(refAttrItems); - } + if (prefix2 != NULL) { + xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2); + if (ns2 == NULL) { + xsltTransformError(NULL, style, cur, + "xsl:attribute-set : No namespace found for QName " + "'%s:%s' in use-attribute-sets\n", + prefix2, ncname2); + style->errors++; + xmlFree(value); + return; + } + nsUri2 = ns2->href; + } + set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets, + ncname2, nsUri2); } curval = endval; } @@ -407,15 +513,6 @@ next_child: value = NULL; } - /* - * Update the value - */ - /* - * TODO: Why is this dummy entry needed.? - */ - if (attrItems == NULL) - attrItems = xsltNewAttrElem(NULL); - xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL); #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "updated attribute list %s\n", ncname); @@ -423,143 +520,141 @@ next_child: } /** - * xsltGetSAS: - * @style: the XSLT stylesheet - * @name: the attribute list name - * @ns: the attribute list namespace + * xsltResolveUseAttrSets: + * @set: the attribute set + * @asctx: the context for attribute set resolution + * @depth: recursion depth * - * lookup an attribute set based on the style cascade - * - * Returns the attribute set or NULL + * Process "use-attribute-sets". */ -static xsltAttrElemPtr -xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) { - xsltAttrElemPtr values; +static void +xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, + int depth) { + xsltStylesheetPtr cur; + xsltAttrSetPtr other; + xsltUseAttrSetPtr use = set->useAttrSets; + xsltUseAttrSetPtr next; - while (style != NULL) { - values = xmlHashLookup2(style->attributeSets, name, ns); - if (values != NULL) - return(values); - style = xsltNextImport(style); + while (use != NULL) { + /* + * Iterate top stylesheet and all imports. + */ + cur = topStyle; + while (cur != NULL) { + if (cur->attributeSets) { + other = xmlHashLookup2(cur->attributeSets, use->ncname, + use->ns); + if (other != NULL) { + xsltResolveAttrSet(other, topStyle, cur, use->ncname, + use->ns, depth + 1); + xsltMergeAttrSets(set, other); + break; + } + } + cur = xsltNextImport(cur); + } + + next = use->next; + /* Free useAttrSets early. */ + xsltFreeUseAttrSet(use); + use = next; } - return(NULL); + + set->useAttrSets = NULL; } /** - * xsltResolveSASCallbackInt: - * @style: the XSLT stylesheet + * xsltResolveAttrSet: + * @set: the attribute set + * @asctx: the context for attribute set resolution + * @name: the local name of the attirbute set + * @ns: the namespace of the attribute set + * @depth: recursion depth * * resolve the references in an attribute set. */ static void -xsltResolveSASCallbackInt(xsltAttrElemPtr values, xsltStylesheetPtr style, - const xmlChar *name, const xmlChar *ns, - int depth) { - xsltAttrElemPtr tmp; - xsltAttrElemPtr refs; +xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, + xsltStylesheetPtr style, const xmlChar *name, + const xmlChar *ns, int depth) { + xsltStylesheetPtr cur; + xsltAttrSetPtr other; - tmp = values; - if ((name == NULL) || (name[0] == 0)) + if (set->state == ATTRSET_RESOLVED) return; + if (set->state == ATTRSET_RESOLVING) { + xsltTransformError(NULL, topStyle, NULL, + "xsl:attribute-set : use-attribute-sets recursion detected" + " on %s\n", name); + topStyle->errors++; + set->state = ATTRSET_RESOLVED; + return; + } if (depth > 100) { - xsltGenericError(xsltGenericErrorContext, - "xsl:attribute-set : use-attribute-sets recursion detected on %s\n", - name); + xsltTransformError(NULL, topStyle, NULL, + "xsl:attribute-set : use-attribute-sets maximum recursion " + "depth exceeded on %s\n", name); + topStyle->errors++; return; } - while (tmp != NULL) { - if (tmp->set != NULL) { - /* - * Check against cycles ! - */ - if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) { - xsltGenericError(xsltGenericErrorContext, - "xsl:attribute-set : use-attribute-sets recursion detected on %s\n", - name); - } else { -#ifdef WITH_XSLT_DEBUG_ATTRIBUTES - xsltGenericDebug(xsltGenericDebugContext, - "Importing attribute list %s\n", tmp->set); -#endif - refs = xsltGetSAS(style, tmp->set, tmp->ns); - if (refs == NULL) { - xsltGenericError(xsltGenericErrorContext, - "xsl:attribute-set : use-attribute-sets %s reference missing %s\n", - name, tmp->set); - } else { - /* - * recurse first for cleanup - */ - xsltResolveSASCallbackInt(refs, style, name, ns, depth + 1); - /* - * Then merge - */ - xsltMergeAttrElemList(style, values, refs); - /* - * Then suppress the reference - */ - tmp->set = NULL; - tmp->ns = NULL; - } - } - } - tmp = tmp->next; + set->state = ATTRSET_RESOLVING; + + xsltResolveUseAttrSets(set, topStyle, depth); + + /* Merge imported sets. */ + cur = xsltNextImport(style); + while (cur != NULL) { + if (cur->attributeSets != NULL) { + other = xmlHashLookup2(cur->attributeSets, name, ns); + + if (other != NULL) { +#ifdef WITH_XSLT_DEBUG_ATTRIBUTES + xsltGenericDebug(xsltGenericDebugContext, + "xsl:attribute-set : merging import for %s\n", name); +#endif + xsltResolveUseAttrSets(other, topStyle, depth); + xsltMergeAttrSets(set, other); + xmlHashRemoveEntry2(cur->attributeSets, name, ns, NULL); + xsltFreeAttrSet(other); + } + } + + cur = xsltNextImport(cur); } + + set->state = ATTRSET_RESOLVED; } /** - * xsltResolveSASCallback,: - * @style: the XSLT stylesheet + * xsltResolveSASCallback: + * @set: the attribute set + * @asctx: the context for attribute set resolution + * @name: the local name of the attirbute set + * @ns: the namespace of the attribute set * * resolve the references in an attribute set. */ static void -xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style, +xsltResolveSASCallback(xsltAttrSetPtr set, xsltAttrSetContextPtr asctx, const xmlChar *name, const xmlChar *ns, ATTRIBUTE_UNUSED const xmlChar *ignored) { - xsltResolveSASCallbackInt(values, style, name, ns, 1); -} + xsltStylesheetPtr topStyle = asctx->topStyle; + xsltStylesheetPtr style = asctx->style; -/** - * xsltMergeSASCallback,: - * @style: the XSLT stylesheet - * - * Merge an attribute set from an imported stylesheet. - */ -static void -xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style, - const xmlChar *name, const xmlChar *ns, - ATTRIBUTE_UNUSED const xmlChar *ignored) { - int ret; - xsltAttrElemPtr topSet; + xsltResolveAttrSet(set, topStyle, style, name, ns, 1); - ret = xmlHashAddEntry2(style->attributeSets, name, ns, values); - if (ret < 0) { - /* - * Add failed, this attribute set can be removed. - */ -#ifdef WITH_XSLT_DEBUG_ATTRIBUTES - xsltGenericDebug(xsltGenericDebugContext, - "attribute set %s present already in top stylesheet" - " - merging\n", name); -#endif - topSet = xmlHashLookup2(style->attributeSets, name, ns); - if (topSet==NULL) { + /* Move attribute sets to top stylesheet. */ + if (style != topStyle) { + /* + * This imported stylesheet won't be visited anymore. Don't bother + * removing the hash entry. + */ + if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) { xsltGenericError(xsltGenericErrorContext, - "xsl:attribute-set : logic error merging from imports for" - " attribute-set %s\n", name); - } else { - topSet = xsltMergeAttrElemList(style, topSet, values); - xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL); - } - xsltFreeAttrElemList(values); -#ifdef WITH_XSLT_DEBUG_ATTRIBUTES - } else { - xsltGenericDebug(xsltGenericDebugContext, - "attribute set %s moved to top stylesheet\n", - name); -#endif + "xsl:attribute-set : internal error, can't move imported " + " attribute set %s\n", name); + } } } @@ -572,15 +667,14 @@ xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style, void xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) { xsltStylesheetPtr cur; + xsltAttrSetContext asctx; #ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, "Resolving attribute sets references\n"); #endif - /* - * First aggregate all the attribute sets definitions from the imports - */ - cur = xsltNextImport(style); + asctx.topStyle = style; + cur = style; while (cur != NULL) { if (cur->attributeSets != NULL) { if (style->attributeSets == NULL) { @@ -590,43 +684,37 @@ xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) { #endif style->attributeSets = xmlHashCreate(10); } + asctx.style = cur; xmlHashScanFull(cur->attributeSets, - (xmlHashScannerFull) xsltMergeSASCallback, style); - /* - * the attribute lists have either been migrated to style - * or freed directly in xsltMergeSASCallback() - */ - xmlHashFree(cur->attributeSets, NULL); - cur->attributeSets = NULL; + (xmlHashScannerFull) xsltResolveSASCallback, &asctx); + + if (cur != style) { + /* + * the attribute lists have either been migrated to style + * or freed directly in xsltResolveSASCallback() + */ + xmlHashFree(cur->attributeSets, NULL); + cur->attributeSets = NULL; + } } cur = xsltNextImport(cur); } - - /* - * Then resolve all the references and computes the resulting sets - */ - if (style->attributeSets != NULL) { - xmlHashScanFull(style->attributeSets, - (xmlHashScannerFull) xsltResolveSASCallback, style); - } } /** - * xsltAttributeInternal: + * xsltAttribute: * @ctxt: a XSLT process context - * @node: the current node in the source tree + * @contextNode: the current node in the source tree * @inst: the xsl:attribute element - * @comp: precomputed information - * @fromAttributeSet: the attribute comes from an attribute-set + * @castedComp: precomputed information * * Process the xslt attribute node on the source node */ -static void -xsltAttributeInternal(xsltTransformContextPtr ctxt, - xmlNodePtr contextNode, - xmlNodePtr inst, - xsltStylePreCompPtr castedComp, - int fromAttributeSet) +void +xsltAttribute(xsltTransformContextPtr ctxt, + xmlNodePtr contextNode, + xmlNodePtr inst, + xsltStylePreCompPtr castedComp) { #ifdef XSLT_REFACTORED xsltStyleItemAttributePtr comp = @@ -666,7 +754,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, if (comp == NULL) { xsltTransformError(ctxt, NULL, inst, - "Internal error in xsltAttributeInternal(): " + "Internal error in xsltAttribute(): " "The XSLT 'attribute' instruction was not compiled.\n"); return; } @@ -831,19 +919,6 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt, nsName = ns->href; } - if (fromAttributeSet) { - /* - * This tries to ensure that xsl:attribute(s) coming - * from an xsl:attribute-set won't override attribute of - * literal result elements or of explicit xsl:attribute(s). - * URGENT TODO: This might be buggy, since it will miss to - * overwrite two equal attributes both from attribute sets. - */ - attr = xmlHasNsProp(targetElem, name, nsName); - if (attr != NULL) - return; - } - /* * Find/create a matching ns-decl in the result tree. */ @@ -993,21 +1068,6 @@ error: return; } -/** - * xsltAttribute: - * @ctxt: a XSLT process context - * @node: the node in the source tree. - * @inst: the xslt attribute node - * @comp: precomputed information - * - * Process the xslt attribute node on the source node - */ -void -xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node, - xmlNodePtr inst, xsltStylePreCompPtr comp) { - xsltAttributeInternal(ctxt, node, inst, comp, 0); -} - /** * xsltApplyAttributeSet: * @ctxt: the XSLT stylesheet @@ -1028,7 +1088,7 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *ncname = NULL; const xmlChar *prefix = NULL; const xmlChar *curstr, *endstr; - xsltAttrElemPtr attrs; + xsltAttrSetPtr set; xsltStylesheetPtr style; if (attrSets == NULL) { @@ -1065,15 +1125,32 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, endstr++; curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr); if (curstr) { - /* - * TODO: Validate the QName. - */ + xmlNsPtr ns; + const xmlChar *nsUri = NULL; -#ifdef WITH_XSLT_DEBUG_curstrUTES +#ifdef WITH_XSLT_DEBUG_ATTRIBUTES xsltGenericDebug(xsltGenericDebugContext, - "apply curstrute set %s\n", curstr); + "apply attribute set %s\n", curstr); #endif + + if (xmlValidateQName(curstr, 0)) { + xsltTransformError(ctxt, NULL, inst, + "The name '%s' in use-attribute-sets is not a valid " + "QName.\n", curstr); + return; + } + ncname = xsltSplitQName(ctxt->dict, curstr, &prefix); + if (prefix != NULL) { + ns = xmlSearchNs(inst->doc, inst, prefix); + if (ns == NULL) { + xsltTransformError(ctxt, NULL, inst, + "use-attribute-set : No namespace found for QName " + "'%s:%s'\n", prefix, ncname); + return; + } + nsUri = ns->href; + } style = ctxt->style; @@ -1082,27 +1159,28 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, (style->attributeSets != NULL) && (ctxt->debugStatus != XSLT_DEBUG_NONE)) { - attrs = - xmlHashLookup2(style->attributeSets, ncname, prefix); - if ((attrs != NULL) && (attrs->attr != NULL)) - xslHandleDebugger(attrs->attr->parent, node, NULL, + set = xmlHashLookup2(style->attributeSets, ncname, nsUri); + if ((set != NULL) && (set->attrs != NULL) && + (set->attrs->attr != NULL)) + xslHandleDebugger(set->attrs->attr->parent, node, NULL, ctxt); } #endif /* - * Lookup the referenced curstrute-set. + * Lookup the referenced attribute-set. All attribute sets were + * moved to the top stylesheet so there's no need to iterate + * imported stylesheets */ - while (style != NULL) { - attrs = - xmlHashLookup2(style->attributeSets, ncname, prefix); - while (attrs != NULL) { - if (attrs->attr != NULL) { - xsltAttributeInternal(ctxt, node, attrs->attr, - attrs->attr->psvi, 1); + set = xmlHashLookup2(style->attributeSets, ncname, nsUri); + if (set != NULL) { + xsltAttrElemPtr cur = set->attrs; + while (cur != NULL) { + if (cur->attr != NULL) { + xsltAttribute(ctxt, node, cur->attr, + cur->attr->psvi); } - attrs = attrs->next; + cur = cur->next; } - style = xsltNextImport(style); } } curstr = endstr; @@ -1119,6 +1197,6 @@ void xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) { if (style->attributeSets != NULL) xmlHashFree((xmlHashTablePtr) style->attributeSets, - (xmlHashDeallocator) xsltFreeAttrElemList); + (xmlHashDeallocator) xsltFreeAttrSet); style->attributeSets = NULL; } diff --git a/dll/3rdparty/libxslt/extensions.c b/dll/3rdparty/libxslt/extensions.c index 4c0763f4542..58c99138f28 100644 --- a/dll/3rdparty/libxslt/extensions.c +++ b/dll/3rdparty/libxslt/extensions.c @@ -372,8 +372,7 @@ xsltExtModuleRegisterDynamic(const xmlChar * URI) /* build the module filename, and confirm the module exists */ xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename), - BAD_CAST "%s/%s%s", - ext_directory, ext_name, LIBXML_MODULE_EXTENSION); + "%s/%s%s", ext_directory, ext_name, LIBXML_MODULE_EXTENSION); #ifdef WITH_XSLT_DEBUG_EXTENSIONS xsltGenericDebug(xsltGenericDebugContext, diff --git a/dll/3rdparty/libxslt/extra.c b/dll/3rdparty/libxslt/extra.c index bfcd953422a..71fe28a1db7 100644 --- a/dll/3rdparty/libxslt/extra.c +++ b/dll/3rdparty/libxslt/extra.c @@ -76,7 +76,10 @@ xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED, xsltGenericError(xsltGenericErrorContext, "noname !!!!"); #ifdef LIBXML_DEBUG_ENABLED if (cur->value != NULL) { - xmlXPathDebugDumpObject(stdout, cur->value, 1); + if ((xsltGenericDebugContext == stdout) || + (xsltGenericDebugContext == stderr)) + xmlXPathDebugDumpObject((FILE*)xsltGenericDebugContext, + cur->value, 1); } else { xsltGenericError(xsltGenericErrorContext, "NULL !!!!"); } @@ -125,134 +128,6 @@ xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){ } } - -/* - * Okay the following really seems unportable and since it's not - * part of any standard I'm not too ashamed to do this - */ -#if defined(linux) || defined(__sun) -#if defined(HAVE_MKTIME) && defined(HAVE_LOCALTIME) && defined(HAVE_ASCTIME) -#define WITH_LOCALTIME - -/** - * xsltFunctionLocalTime: - * @ctxt: the XPath Parser context - * @nargs: the number of arguments - * - * Implement the localTime XSLT function used by NORM - * string localTime(???) - * - * This function is available in Norm's extension namespace - * Code (and comments) contributed by Norm - */ -static void -xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt, int nargs) { - xmlXPathObjectPtr obj; - char *str; - char digits[5]; - char result[29]; - long int field; - time_t gmt, lmt; - struct tm gmt_tm; - struct tm *local_tm; - - if (nargs != 1) { - xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, - "localTime() : invalid number of args %d\n", nargs); - ctxt->error = XPATH_INVALID_ARITY; - return; - } - - obj = valuePop(ctxt); - - if (obj->type != XPATH_STRING) { - obj = xmlXPathConvertString(obj); - } - if (obj == NULL) { - valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); - return; - } - - str = (char *) obj->stringval; - - /* str = "$Date$" */ - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+7, 4); - field = strtol(digits, NULL, 10); - gmt_tm.tm_year = field - 1900; - - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+12, 2); - field = strtol(digits, NULL, 10); - gmt_tm.tm_mon = field - 1; - - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+15, 2); - field = strtol(digits, NULL, 10); - gmt_tm.tm_mday = field; - - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+18, 2); - field = strtol(digits, NULL, 10); - gmt_tm.tm_hour = field; - - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+21, 2); - field = strtol(digits, NULL, 10); - gmt_tm.tm_min = field; - - memset(digits, 0, sizeof(digits)); - strncpy(digits, str+24, 2); - field = strtol(digits, NULL, 10); - gmt_tm.tm_sec = field; - - /* Now turn gmt_tm into a time. */ - gmt = mktime(&gmt_tm); - - - /* - * FIXME: it's been too long since I did manual memory management. - * (I swore never to do it again.) Does this introduce a memory leak? - */ - local_tm = localtime(&gmt); - - /* - * Calling localtime() has the side-effect of setting timezone. - * After we know the timezone, we can adjust for it - */ -#if !defined(__FreeBSD__) - lmt = gmt - timezone; -#else /* FreeBSD DOESN'T have such side-ffect */ - lmt = gmt - local_tm->tm_gmtoff; -#endif - /* - * FIXME: it's been too long since I did manual memory management. - * (I swore never to do it again.) Does this introduce a memory leak? - */ - local_tm = localtime(&lmt); - - /* - * Now convert local_tm back into a string. This doesn't introduce - * a memory leak, so says asctime(3). - */ - - str = asctime(local_tm); /* "Tue Jun 26 05:02:16 2001" */ - /* 0123456789 123456789 123 */ - - memset(result, 0, sizeof(result)); /* "Thu, 26 Jun 2001" */ - /* 0123456789 12345 */ - - strncpy(result, str, 20); - strcpy(result+20, "???"); /* tzname doesn't work, fake it */ - strncpy(result+23, str+19, 5); - - /* Ok, now result contains the string I want to send back. */ - valuePush(ctxt, xmlXPathNewString((xmlChar *)result)); -} -#endif -#endif /* linux or sun */ - - /** * xsltRegisterExtras: * @ctxt: a XSLT process context @@ -281,11 +156,6 @@ xsltRegisterAllExtras (void) { xsltRegisterExtModuleFunction((const xmlChar *) "node-set", XSLT_XT_NAMESPACE, xsltFunctionNodeSet); -#ifdef WITH_LOCALTIME - xsltRegisterExtModuleFunction((const xmlChar *) "localTime", - XSLT_NORM_SAXON_NAMESPACE, - xsltFunctionLocalTime); -#endif xsltRegisterExtModuleElement((const xmlChar *) "debug", XSLT_LIBXSLT_NAMESPACE, NULL, diff --git a/dll/3rdparty/libxslt/extra.h b/dll/3rdparty/libxslt/extra.h index 6929e3c6408..1b36d56877f 100644 --- a/dll/3rdparty/libxslt/extra.h +++ b/dll/3rdparty/libxslt/extra.h @@ -48,14 +48,6 @@ extern "C" { #define XSLT_XALAN_NAMESPACE ((xmlChar *) \ "org.apache.xalan.xslt.extensions.Redirect") -/** - * XSLT_NORM_SAXON_NAMESPACE: - * - * This is Norm's namespace for SAXON extensions. - */ -#define XSLT_NORM_SAXON_NAMESPACE ((xmlChar *) \ - "http://nwalsh.com/xslt/ext/com.nwalsh.saxon.CVS") - XSLTPUBFUN void XSLTCALL xsltFunctionNodeSet (xmlXPathParserContextPtr ctxt, diff --git a/dll/3rdparty/libxslt/functions.c b/dll/3rdparty/libxslt/functions.c index 41a58d36c30..decb3d98989 100644 --- a/dll/3rdparty/libxslt/functions.c +++ b/dll/3rdparty/libxslt/functions.c @@ -575,12 +575,15 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) xmlXPathObjectPtr formatObj = NULL; xmlXPathObjectPtr decimalObj = NULL; xsltStylesheetPtr sheet; - xsltDecimalFormatPtr formatValues; + xsltDecimalFormatPtr formatValues = NULL; xmlChar *result; + const xmlChar *ncname; + const xmlChar *prefix = NULL; + const xmlChar *nsUri = NULL; xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); - if (tctxt == NULL) + if ((tctxt == NULL) || (tctxt->inst == NULL)) return; sheet = tctxt->style; if (sheet == NULL) @@ -591,7 +594,23 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) case 3: CAST_TO_STRING; decimalObj = valuePop(ctxt); - formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval); + ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix); + if (prefix != NULL) { + xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix); + if (ns == NULL) { + xsltTransformError(tctxt, NULL, NULL, + "format-number : No namespace found for QName '%s:%s'\n", + prefix, ncname); + sheet->errors++; + ncname = NULL; + } + else { + nsUri = ns->href; + } + } + if (ncname != NULL) { + formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname); + } if (formatValues == NULL) { xsltTransformError(tctxt, NULL, NULL, "format-number() : undeclared decimal format '%s'\n", @@ -807,7 +826,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ } obj = valuePop(ctxt); tctxt = xsltXPathGetTransformContext(ctxt); - if (tctxt == NULL) { + if ((tctxt == NULL) || (tctxt->inst == NULL)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "element-available() : internal error tctxt == NULL\n"); xmlXPathFreeObject(obj); @@ -822,7 +841,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){ name = xmlStrdup(obj->stringval); ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL); - if (ns != NULL) nsURI = xmlStrdup(ns->href); + if (ns != NULL) nsURI = ns->href; } else { nsURI = xmlXPathNsLookup(ctxt->context, prefix); if (nsURI == NULL) { diff --git a/dll/3rdparty/libxslt/keys.c b/dll/3rdparty/libxslt/keys.c index e3a929c16d8..91705384bca 100644 --- a/dll/3rdparty/libxslt/keys.c +++ b/dll/3rdparty/libxslt/keys.c @@ -384,10 +384,13 @@ xsltAddKey(xsltStylesheetPtr style, const xmlChar *name, prev->next = key; } key->next = NULL; + key = NULL; error: if (pattern != NULL) xmlFree(pattern); + if (key != NULL) + xsltFreeKeyDef(key); return(0); } diff --git a/dll/3rdparty/libxslt/numbers.c b/dll/3rdparty/libxslt/numbers.c index 790300d7e2e..470ee3253c5 100644 --- a/dll/3rdparty/libxslt/numbers.c +++ b/dll/3rdparty/libxslt/numbers.c @@ -48,39 +48,11 @@ static xsltFormatToken default_token; /* * **** Start temp insert **** * - * The following two routines (xsltUTF8Size and xsltUTF8Charcmp) - * will be replaced with calls to the corresponding libxml routines - * at a later date (when other inter-library dependencies require it) + * The following routine xsltUTF8Charcmp will be replaced with calls to + * the corresponding libxml routine at a later date (when other + * inter-library dependencies require it). */ -/** - * xsltUTF8Size: - * @utf: pointer to the UTF8 character - * - * returns the numbers of bytes in the character, -1 on format error - */ -static int -xsltUTF8Size(xmlChar *utf) { - xmlChar mask; - int len; - - if (utf == NULL) - return -1; - if (*utf < 0x80) - return 1; - /* check valid UTF8 character */ - if (!(*utf & 0x40)) - return -1; - /* determine number of bytes in char */ - len = 2; - for (mask=0x20; mask != 0; mask>>=1) { - if (!(*utf & mask)) - return len; - len++; - } - return -1; -} - /** * xsltUTF8Charcmp * @utf1: pointer to first UTF8 char @@ -91,13 +63,16 @@ xsltUTF8Size(xmlChar *utf) { */ static int xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2) { + int len = xmlUTF8Strsize(utf1, 1); + if (len < 1) + return -1; if (utf1 == NULL ) { if (utf2 == NULL) return 0; return -1; } - return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1)); + return xmlStrncmp(utf1, utf2, len); } /***** Stop temp insert *****/ @@ -205,7 +180,7 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer, } if (i < 0) xsltGenericError(xsltGenericErrorContext, - "xsltNumberFormatDecimal: Internal buffer size exceeded"); + "xsltNumberFormatDecimal: Internal buffer size exceeded\n"); xmlBufferCat(buffer, pointer); } @@ -599,25 +574,7 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, { int amount = 0; int cnt = 0; - xmlNodePtr cur; - - /* select the starting node */ - switch (node->type) { - case XML_ELEMENT_NODE: - cur = node; - break; - case XML_ATTRIBUTE_NODE: - cur = ((xmlAttrPtr) node)->parent; - break; - case XML_TEXT_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - cur = node->parent; - break; - default: - cur = NULL; - break; - } + xmlNodePtr cur = node; while (cur != NULL) { /* process current node */ @@ -636,16 +593,25 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, (cur->type == XML_HTML_DOCUMENT_NODE)) break; /* while */ - while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) || - (cur->prev->type == XML_XINCLUDE_START) || - (cur->prev->type == XML_XINCLUDE_END))) - cur = cur->prev; - if (cur->prev != NULL) { - for (cur = cur->prev; cur->last != NULL; cur = cur->last); - } else { - cur = cur->parent; - } - + if (cur->type == XML_NAMESPACE_DECL) { + /* + * The XPath module stores the parent of a namespace node in + * the ns->next field. + */ + cur = (xmlNodePtr) ((xmlNsPtr) cur)->next; + } else if (cur->type == XML_ATTRIBUTE_NODE) { + cur = cur->parent; + } else { + while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) || + (cur->prev->type == XML_XINCLUDE_START) || + (cur->prev->type == XML_XINCLUDE_END))) + cur = cur->prev; + if (cur->prev != NULL) { + for (cur = cur->prev; cur->last != NULL; cur = cur->last); + } else { + cur = cur->parent; + } + } } array[amount++] = (double) cnt; @@ -891,7 +857,7 @@ xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltForma } } - if ((len=xsltUTF8Size(*format)) < 1) + if ((len=xmlUTF8Strsize(*format, 1)) < 1) return -1; count += len; *format += len; @@ -1073,7 +1039,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, } else break; /* while */ - if ((len=xsltUTF8Size(the_format)) < 1) { + if ((len=xmlUTF8Strsize(the_format, 1)) < 1) { found_error = 1; goto OUTPUT_NUMBER; } @@ -1082,9 +1048,14 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, } /* We have finished the integer part, now work on fraction */ - if (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) { + if ( (*the_format != 0) && + (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) ) { format_info.add_decimal = TRUE; - the_format += xsltUTF8Size(the_format); /* Skip over the decimal */ + if ((len = xmlUTF8Strsize(the_format, 1)) < 1) { + found_error = 1; + goto OUTPUT_NUMBER; + } + the_format += len; /* Skip over the decimal */ } while (*the_format != 0) { @@ -1103,7 +1074,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, goto OUTPUT_NUMBER; } delayed_multiplier = 100; - if ((len = xsltUTF8Size(the_format)) < 1) { + if ((len = xmlUTF8Strsize(the_format, 1)) < 1) { found_error = 1; goto OUTPUT_NUMBER; } @@ -1115,7 +1086,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, goto OUTPUT_NUMBER; } delayed_multiplier = 1000; - if ((len = xsltUTF8Size(the_format)) < 1) { + if ((len = xmlUTF8Strsize(the_format, 1)) < 1) { found_error = 1; goto OUTPUT_NUMBER; } @@ -1124,7 +1095,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) { break; /* while */ } - if ((len = xsltUTF8Size(the_format)) < 1) { + if ((len = xmlUTF8Strsize(the_format, 1)) < 1) { found_error = 1; goto OUTPUT_NUMBER; } @@ -1201,7 +1172,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self, delayed_multiplier = 0; else break; /* while */ - if ((len = xsltUTF8Size(the_format)) < 1) { + if ((len = xmlUTF8Strsize(the_format, 1)) < 1) { found_error = 1; goto OUTPUT_NUMBER; } @@ -1267,12 +1238,12 @@ OUTPUT_NUMBER: /* Ready to output our number. First see if "default sign" is required */ if (default_sign != 0) - xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign)); + xmlBufferAdd(buffer, self->minusSign, xmlUTF8Strsize(self->minusSign, 1)); /* Put the prefix into the buffer */ for (j = 0; j < prefix_length; j++) { if ((pchar = *prefix++) == SYMBOL_QUOTE) { - len = xsltUTF8Size(prefix); + len = xmlUTF8Strsize(prefix, 1); xmlBufferAdd(buffer, prefix, len); prefix += len; j += len - 1; /* length of symbol less length of quote */ @@ -1309,20 +1280,20 @@ OUTPUT_NUMBER: /* Add leading zero, if required */ if ((floor(number) == 0) && (format_info.integer_digits + format_info.frac_digits == 0)) { - xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit)); + xmlBufferAdd(buffer, self->zeroDigit, xmlUTF8Strsize(self->zeroDigit, 1)); } /* Next the fractional part, if required */ if (format_info.frac_digits + format_info.frac_hash == 0) { if (format_info.add_decimal) xmlBufferAdd(buffer, self->decimalPoint, - xsltUTF8Size(self->decimalPoint)); + xmlUTF8Strsize(self->decimalPoint, 1)); } else { number -= floor(number); if ((number != 0) || (format_info.frac_digits != 0)) { xmlBufferAdd(buffer, self->decimalPoint, - xsltUTF8Size(self->decimalPoint)); + xmlUTF8Strsize(self->decimalPoint, 1)); number = floor(scale * number + 0.5); for (j = format_info.frac_hash; j > 0; j--) { if (fmod(number, 10.0) >= 1.0) @@ -1337,7 +1308,7 @@ OUTPUT_NUMBER: /* Put the suffix into the buffer */ for (j = 0; j < suffix_length; j++) { if ((pchar = *suffix++) == SYMBOL_QUOTE) { - len = xsltUTF8Size(suffix); + len = xmlUTF8Strsize(suffix, 1); xmlBufferAdd(buffer, suffix, len); suffix += len; j += len - 1; /* length of symbol less length of escape */ diff --git a/dll/3rdparty/libxslt/pattern.c b/dll/3rdparty/libxslt/pattern.c index 62dfe0a56d4..e27e9402a73 100644 --- a/dll/3rdparty/libxslt/pattern.c +++ b/dll/3rdparty/libxslt/pattern.c @@ -85,6 +85,7 @@ struct _xsltCompMatch { const xmlChar *mode; /* the mode */ const xmlChar *modeURI; /* the mode URI */ xsltTemplatePtr template; /* the associated template */ + xmlNodePtr node; /* the containing element */ int direct; /* TODO fix the statically allocated size steps[] */ @@ -895,7 +896,9 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr matchNode, const xmlChar *mode, const xmlChar *modeURI) { int i; + int found = 0; xmlNodePtr node = matchNode; + xmlNodePtr oldInst; xsltStepOpPtr step, sel = NULL; xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */ @@ -929,6 +932,10 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, return(0); } + /* Some XPath functions rely on inst being set correctly. */ + oldInst = ctxt->inst; + ctxt->inst = comp->node; + i = 0; restart: for (;i < comp->nbStep;i++) { @@ -1121,12 +1128,9 @@ restart: * as possible this costly computation. */ if (comp->direct) { - if (states.states != NULL) { - /* Free the rollback states */ - xmlFree(states.states); - } - return(xsltTestCompMatchDirect(ctxt, comp, matchNode, - comp->nsList, comp->nsNr)); + found = xsltTestCompMatchDirect(ctxt, comp, matchNode, + comp->nsList, comp->nsNr); + goto exit; } if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel)) @@ -1166,18 +1170,19 @@ restart: } } found: + found = 1; +exit: + ctxt->inst = oldInst; if (states.states != NULL) { /* Free the rollback states */ xmlFree(states.states); } - return(1); + return found; rollback: /* got an error try to rollback */ - if (states.states == NULL) - return(0); - if (states.nbstates <= 0) { - xmlFree(states.states); - return(0); + if (states.states == NULL || states.nbstates <= 0) { + found = 0; + goto exit; } states.nbstates--; i = states.states[states.nbstates].step; @@ -1456,6 +1461,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, xsltTransformError(NULL, NULL, NULL, "xsltCompileIdKeyPattern : ) expected\n"); ctxt->error = 1; + xmlFree(lit); return; } } @@ -1618,6 +1624,7 @@ parse_node_test: xsltTransformError(NULL, NULL, NULL, "xsltCompileStepPattern : Name expected\n"); ctxt->error = 1; + xmlFree(URL); goto error; } } else { @@ -1925,6 +1932,7 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc, goto error; ctxt->cur = &(ctxt->base)[current - start]; element->pattern = ctxt->base; + element->node = node; element->nsList = xmlGetNsList(doc, node); j = 0; if (element->nsList != NULL) { diff --git a/dll/3rdparty/libxslt/preproc.c b/dll/3rdparty/libxslt/preproc.c index d47aa29171b..44d4983c15d 100644 --- a/dll/3rdparty/libxslt/preproc.c +++ b/dll/3rdparty/libxslt/preproc.c @@ -1394,9 +1394,6 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) { return; cur->psvi = comp; - if ((style == NULL) || (cur == NULL)) - return; - comp->numdata.doc = cur->doc; comp->numdata.node = cur; comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value", @@ -2319,7 +2316,7 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) { xsltCheckInstructionElement(style, inst); inst->psvi = (void *) xsltDocumentComp(style, inst, (xsltTransformFunction) xsltDocumentElem); - } else { + } else if ((style == NULL) || (style->forwards_compatible == 0)) { xsltTransformError(NULL, style, inst, "xsltStylePreCompute: unknown xsl:%s\n", inst->name); if (style != NULL) style->warnings++; diff --git a/dll/3rdparty/libxslt/security.c b/dll/3rdparty/libxslt/security.c index 51b631cf8c1..6478cc5bba7 100644 --- a/dll/3rdparty/libxslt/security.c +++ b/dll/3rdparty/libxslt/security.c @@ -246,7 +246,7 @@ xsltCheckFilename (const char *path) { #ifdef HAVE_STAT struct stat stat_buffer; -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) DWORD dwAttrs; dwAttrs = GetFileAttributes(path); @@ -351,7 +351,7 @@ xsltCheckWrite(xsltSecurityPrefsPtr sec, if ((uri->scheme == NULL) || (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) { -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) if ((uri->path)&&(uri->path[0]=='/')&& (uri->path[1]!='\0')&&(uri->path[2]==':')) ret = xsltCheckWritePath(sec, ctxt, uri->path+1); diff --git a/dll/3rdparty/libxslt/templates.c b/dll/3rdparty/libxslt/templates.c index a4d7364d3d9..f997cea6e36 100644 --- a/dll/3rdparty/libxslt/templates.c +++ b/dll/3rdparty/libxslt/templates.c @@ -45,6 +45,12 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNodePtr oldInst; int oldProximityPosition, oldContextSize; + if ((ctxt == NULL) || (ctxt->inst == NULL)) { + xsltTransformError(ctxt, NULL, NULL, + "xsltEvalXPathPredicate: No context or instruction\n"); + return(0); + } + oldContextSize = ctxt->xpathCtxt->contextSize; oldProximityPosition = ctxt->xpathCtxt->proximityPosition; oldNsNr = ctxt->xpathCtxt->nsNr; @@ -106,6 +112,12 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, int oldNsNr; xmlNsPtr *oldNamespaces; + if ((ctxt == NULL) || (ctxt->inst == NULL)) { + xsltTransformError(ctxt, NULL, NULL, + "xsltEvalXPathStringNs: No context or instruction\n"); + return(0); + } + oldInst = ctxt->inst; oldNode = ctxt->node; oldPos = ctxt->xpathCtxt->proximityPosition; @@ -278,12 +290,12 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt, xsltTransformError(ctxt, NULL, inst, "xsltAttrTemplateValueProcessNode: unmatched '{'\n"); ret = xmlStrncat(ret, str, cur - str); - return(ret); + goto exit; } str++; expr = xmlStrndup(str, cur - str); if (expr == NULL) - return(ret); + goto exit; else if (*expr == '{') { ret = xmlStrcat(ret, expr); xmlFree(expr); @@ -331,6 +343,7 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt, ret = xmlStrncat(ret, str, cur - str); } +exit: if (nsList != NULL) xmlFree(nsList); diff --git a/dll/3rdparty/libxslt/transform.c b/dll/3rdparty/libxslt/transform.c index 45ceaf16762..5097b76f241 100644 --- a/dll/3rdparty/libxslt/transform.c +++ b/dll/3rdparty/libxslt/transform.c @@ -23,6 +23,7 @@ #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_EXTRA #define WITH_XSLT_DEBUG_PROCESS +#define WITH_XSLT_DEBUG_VARIABLE #endif #define XSLT_GENERATE_HTML_DOCTYPE @@ -55,10 +56,9 @@ static xmlNsPtr xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur); static xmlNodePtr -xsltCopyTreeInternal(xsltTransformContextPtr ctxt, - xmlNodePtr invocNode, - xmlNodePtr node, - xmlNodePtr insert, int isLRE, int topElemVisited); +xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, + xmlNodePtr node, xmlNodePtr insert, int isLRE, + int topElemVisited); static void xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, @@ -434,7 +434,7 @@ xsltGetXIncludeDefault(void) { return(xsltDoXIncludeDefault); } -unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL; +static unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL; /** * xsltDebugSetDefaultTrace: @@ -733,9 +733,6 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) { * * ************************************************************************/ -xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt, - xmlNodePtr node, xmlNodePtr insert, int literal); - /** * xsltAddChild: * @parent: the parent node @@ -751,7 +748,7 @@ static xmlNodePtr xsltAddChild(xmlNodePtr parent, xmlNodePtr cur) { xmlNodePtr ret; - if ((cur == NULL) || (parent == NULL)) + if (cur == NULL) return(NULL); if (parent == NULL) { xmlFreeNode(cur); @@ -783,13 +780,32 @@ xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target, return(target); if (ctxt->lasttext == target->content) { + int minSize; - if (ctxt->lasttuse + len >= ctxt->lasttsize) { + /* Check for integer overflow accounting for NUL terminator. */ + if (len >= INT_MAX - ctxt->lasttuse) { + xsltTransformError(ctxt, NULL, target, + "xsltCopyText: text allocation failed\n"); + return(NULL); + } + minSize = ctxt->lasttuse + len + 1; + + if (ctxt->lasttsize < minSize) { xmlChar *newbuf; int size; + int extra; + + /* Double buffer size but increase by at least 100 bytes. */ + extra = minSize < 100 ? 100 : minSize; + + /* Check for integer overflow. */ + if (extra > INT_MAX - ctxt->lasttsize) { + size = INT_MAX; + } + else { + size = ctxt->lasttsize + extra; + } - size = ctxt->lasttsize + len + 100; - size *= 2; newbuf = (xmlChar *) xmlRealloc(target->content,size); if (newbuf == NULL) { xsltTransformError(ctxt, NULL, target, @@ -1090,7 +1106,7 @@ exit: * * Do a copy of an attribute. * Called by: - * - xsltCopyTreeInternal() + * - xsltCopyTree() * - xsltCopyOf() * - xsltCopy() * @@ -1191,7 +1207,7 @@ xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, * @target element node. * * Called by: - * - xsltCopyTreeInternal() + * - xsltCopyTree() * * Returns 0 on success and -1 on errors and internal errors. */ @@ -1313,7 +1329,7 @@ xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node, * copy over all namespace nodes in scope. * The damn thing about this is, that we would need to * use the xmlGetNsList(), for every single node; this is - * also done in xsltCopyTreeInternal(), but only for the top node. + * also done in xsltCopyTree(), but only for the top node. */ if (node->ns != NULL) { if (isLRE) { @@ -1371,7 +1387,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr copy, ret = NULL; while (list != NULL) { - copy = xsltCopyTreeInternal(ctxt, invocNode, + copy = xsltCopyTree(ctxt, invocNode, list, insert, isLRE, topElemVisited); if (copy != NULL) { if (ret == NULL) { @@ -1391,7 +1407,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, * Do a copy of a namespace list. If @node is non-NULL the * new namespaces are added automatically. * Called by: - * xsltCopyTreeInternal() + * xsltCopyTree() * * QUESTION: What is the exact difference between this function * and xsltCopyNamespaceList() in "namespaces.c"? @@ -1549,7 +1565,7 @@ occupied: } /** - * xsltCopyTreeInternal: + * xsltCopyTree: * @ctxt: the XSLT transformation context * @invocNode: responsible node in the stylesheet; used for error reports * @node: the element node in the source tree @@ -1568,10 +1584,9 @@ occupied: * Returns a pointer to the new tree, or NULL in case of error */ static xmlNodePtr -xsltCopyTreeInternal(xsltTransformContextPtr ctxt, - xmlNodePtr invocNode, - xmlNodePtr node, - xmlNodePtr insert, int isLRE, int topElemVisited) +xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, + xmlNodePtr node, xmlNodePtr insert, int isLRE, + int topElemVisited) { xmlNodePtr copy; @@ -1627,7 +1642,7 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt, copy = xsltAddChild(insert, copy); if (copy == NULL) { xsltTransformError(ctxt, NULL, invocNode, - "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name); + "xsltCopyTree: Copying of '%s' failed.\n", node->name); return (copy); } /* @@ -1758,34 +1773,11 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt, } } else { xsltTransformError(ctxt, NULL, invocNode, - "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name); + "xsltCopyTree: Copying of '%s' failed.\n", node->name); } return(copy); } -/** - * xsltCopyTree: - * @ctxt: the XSLT transformation context - * @node: the element node in the source tree - * @insert: the parent in the result tree - * @literal: indicates if @node is a Literal Result Element - * - * Make a copy of the full tree under the element node @node - * and insert it as last child of @insert - * For literal result element, some of the namespaces may not be copied - * over according to section 7.1. - * TODO: Why is this a public function? - * - * Returns a pointer to the new tree, or NULL in case of error - */ -xmlNodePtr -xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node, - xmlNodePtr insert, int literal) -{ - return(xsltCopyTreeInternal(ctxt, node, node, insert, literal, 0)); - -} - /************************************************************************ * * * Error/fallback processing * @@ -1987,6 +1979,9 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node, /* * Handling of Elements: second pass, actual processing + * + * Note that params are passed to the next template. This matches + * XSLT 2.0 behavior but doesn't conform to XSLT 1.0. */ oldSize = ctxt->xpathCtxt->contextSize; oldPos = ctxt->xpathCtxt->proximityPosition; @@ -2266,30 +2261,28 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base) { xmlDocPtr cur = ctxt->localRVT, tmp; - while ((cur != NULL) && (cur != base)) { - if (cur->psvi == (void *) ((long) 1)) { - cur = (xmlDocPtr) cur->next; - } else { - tmp = cur; - cur = (xmlDocPtr) cur->next; + if (cur == base) + return; + if (cur->prev != NULL) + xsltTransformError(ctxt, NULL, NULL, "localRVT not head of list\n"); - if (tmp == ctxt->localRVT) - ctxt->localRVT = cur; + do { + tmp = cur; + cur = (xmlDocPtr) cur->next; + if (tmp->psvi == XSLT_RVT_LOCAL) { + xsltReleaseRVT(ctxt, tmp); + } else if (tmp->psvi == XSLT_RVT_GLOBAL) { + xsltRegisterPersistRVT(ctxt, tmp); + } else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) { + xmlGenericError(xmlGenericErrorContext, + "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n", + tmp->psvi); + } + } while (cur != base); - /* - * We need ctxt->localRVTBase for extension instructions - * which return values (like EXSLT's function). - */ - if (tmp == ctxt->localRVTBase) - ctxt->localRVTBase = cur; - - if (tmp->prev) - tmp->prev->next = (xmlNodePtr) cur; - if (cur) - cur->prev = tmp->prev; - xsltReleaseRVT(ctxt, tmp); - } - } + if (base != NULL) + base->prev = NULL; + ctxt->localRVT = base; } /** @@ -2315,7 +2308,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode; xmlNodePtr cur, insert, copy = NULL; int level = 0, oldVarsNr; - xmlDocPtr oldLocalFragmentTop, oldLocalFragmentBase; + xmlDocPtr oldLocalFragmentTop; #ifdef XSLT_REFACTORED xsltStylePreCompPtr info; @@ -2343,6 +2336,24 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, return; CHECK_STOPPED; + /* + * Check for infinite recursion: stop if the maximum of nested templates + * is excceeded. Adjust xsltMaxDepth if you need more. + */ + if (ctxt->depth >= ctxt->maxTemplateDepth) { + xsltTransformError(ctxt, NULL, list, + "xsltApplySequenceConstructor: A potential infinite template " + "recursion was detected.\n" + "You can adjust xsltMaxDepth (--maxdepth) in order to " + "raise the maximum number of nested template calls and " + "variables/params (currently set to %d).\n", + ctxt->maxTemplateDepth); + xsltDebug(ctxt, contextNode, list, NULL); + ctxt->state = XSLT_STATE_STOPPED; + return; + } + ctxt->depth++; + oldLocalFragmentTop = ctxt->localRVT; oldInsert = insert = ctxt->insert; oldInst = oldCurInst = ctxt->inst; @@ -2642,17 +2653,22 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, "xsltApplySequenceConstructor: extension construct %s\n", cur->name)); #endif + /* + * Disable the xsltCopyTextString optimization for + * extension elements. Extensions could append text using + * xmlAddChild which will free the buffer pointed to by + * 'lasttext'. This buffer could later be reallocated with + * a different size than recorded in 'lasttsize'. See bug + * #777432. + */ + if (cur->psvi == xsltExtMarker) { + ctxt->lasttext = NULL; + } + ctxt->insert = insert; - /* - * We need the fragment base for extension instructions - * which return values (like EXSLT's function). - */ - oldLocalFragmentBase = ctxt->localRVTBase; - ctxt->localRVTBase = NULL; func(ctxt, contextNode, cur, cur->psvi); - ctxt->localRVTBase = oldLocalFragmentBase; /* * Cleanup temporary tree fragments. */ @@ -2716,12 +2732,9 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, oldCurInst = ctxt->inst; ctxt->inst = cur; ctxt->insert = insert; - oldLocalFragmentBase = ctxt->localRVTBase; - ctxt->localRVTBase = NULL; info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info); - ctxt->localRVTBase = oldLocalFragmentBase; /* * Cleanup temporary tree fragments. */ @@ -2835,13 +2848,19 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, cur->name)); #endif + /* + * Disable the xsltCopyTextString optimization for + * extension elements. Extensions could append text using + * xmlAddChild which will free the buffer pointed to by + * 'lasttext'. This buffer could later be reallocated with + * a different size than recorded in 'lasttsize'. See bug + * #777432. + */ + if (cur->psvi == xsltExtMarker) { + ctxt->lasttext = NULL; + } + ctxt->insert = insert; - /* - * We need the fragment base for extension instructions - * which return values (like EXSLT's function). - */ - oldLocalFragmentBase = ctxt->localRVTBase; - ctxt->localRVTBase = NULL; function(ctxt, contextNode, cur, cur->psvi); /* @@ -2850,7 +2869,6 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, if (oldLocalFragmentTop != ctxt->localRVT) xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop); - ctxt->localRVTBase = oldLocalFragmentBase; ctxt->insert = oldInsert; } @@ -2992,6 +3010,8 @@ error: ctxt->inst = oldInst; ctxt->insert = oldInsert; + ctxt->depth--; + #ifdef WITH_DEBUGGER if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) { xslDropCall(); @@ -3026,7 +3046,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt, long start = 0; xmlNodePtr cur; xsltStackElemPtr tmpParam = NULL; - xmlDocPtr oldUserFragmentTop, oldLocalFragmentTop; + xmlDocPtr oldUserFragmentTop; #ifdef XSLT_REFACTORED xsltStyleItemParamPtr iparam; @@ -3058,23 +3078,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt, return; CHECK_STOPPED; - /* - * Check for infinite recursion: stop if the maximum of nested templates - * is excceeded. Adjust xsltMaxDepth if you need more. - */ - if (ctxt->templNr >= ctxt->maxTemplateDepth) - { - xsltTransformError(ctxt, NULL, list, - "xsltApplyXSLTTemplate: A potential infinite template recursion " - "was detected.\n" - "You can adjust xsltMaxDepth (--maxdepth) in order to " - "raise the maximum number of nested template calls and " - "variables/params (currently set to %d).\n", - ctxt->maxTemplateDepth); - xsltDebug(ctxt, contextNode, list, NULL); - return; - } - if (ctxt->varsNr >= ctxt->maxTemplateVars) { xsltTransformError(ctxt, NULL, list, @@ -3084,12 +3087,12 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt, "raise the maximum number of variables/params (currently set to %d).\n", ctxt->maxTemplateVars); xsltDebug(ctxt, contextNode, list, NULL); + ctxt->state = XSLT_STATE_STOPPED; return; } oldUserFragmentTop = ctxt->tmpRVT; ctxt->tmpRVT = NULL; - oldLocalFragmentTop = ctxt->localRVT; /* * Initiate a distinct scope of local params/variables. @@ -3190,31 +3193,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt, xsltTemplateParamsCleanup(ctxt); ctxt->varsBase = oldVarsBase; - /* - * Clean up remaining local tree fragments. - * This also frees fragments which are the result of - * extension instructions. Should normally not be hit; but - * just for the case xsltExtensionInstructionResultFinalize() - * was not called by the extension author. - */ - if (oldLocalFragmentTop != ctxt->localRVT) { - xmlDocPtr curdoc = ctxt->localRVT, tmp; - - do { - tmp = curdoc; - curdoc = (xmlDocPtr) curdoc->next; - /* Need to housekeep localRVTBase */ - if (tmp == ctxt->localRVTBase) - ctxt->localRVTBase = curdoc; - if (tmp->prev) - tmp->prev->next = (xmlNodePtr) curdoc; - if (curdoc) - curdoc->prev = tmp->prev; - xsltReleaseRVT(ctxt, tmp); - } while (curdoc != oldLocalFragmentTop); - } - ctxt->localRVT = oldLocalFragmentTop; - /* * Release user-created fragments stored in the scope * of xsl:template. Note that this mechanism is deprecated: @@ -3820,7 +3798,6 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltTransformError(ctxt, NULL, inst, "xsltDocumentElem: unable to save to %s\n", filename); - ctxt->state = XSLT_STATE_ERROR; #ifdef WITH_XSLT_DEBUG_EXTRA } else { xsltGenericDebug(xsltGenericDebugContext, @@ -4433,8 +4410,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltShallowCopyAttr(ctxt, inst, ctxt->insert, (xmlAttrPtr) cur); } else { - xsltCopyTreeInternal(ctxt, inst, - cur, ctxt->insert, 0, 0); + xsltCopyTree(ctxt, inst, cur, ctxt->insert, 0, 0); } } } @@ -4685,6 +4661,10 @@ xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, ctxt->currentTemplateRule = oldCurTemplRule; } + else { + /* Use built-in templates. */ + xsltDefaultProcessOneNode(ctxt, contextNode, NULL); + } } /** @@ -5632,6 +5612,7 @@ typedef struct xsltHTMLVersion { } xsltHTMLVersion; static xsltHTMLVersion xsltHTMLVersions[] = { + { "5", NULL, "about:legacy-compat" }, { "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN", "http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"}, { "4.01strict", "-//W3C//DTD HTML 4.01//EN", @@ -5857,7 +5838,8 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, */ root = xmlDocGetRootElement(doc); if (root != NULL) { - if (((long) root->content) >= 0 && (xslDebugStatus == XSLT_DEBUG_NONE)) + if (((ptrdiff_t) root->content >= 0) && + (xslDebugStatus == XSLT_DEBUG_NONE)) xmlXPathOrderDocElems(doc); } @@ -6007,6 +5989,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, xsltEvalGlobalVariables(ctxt); + /* Clean up any unused RVTs. */ + xsltReleaseLocalRVTs(ctxt, NULL); + ctxt->node = (xmlNodePtr) doc; ctxt->output = res; ctxt->insert = (xmlNodePtr) res; @@ -6151,7 +6136,7 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, /* * Be pedantic. */ - if ((ctxt != NULL) && (ctxt->state == XSLT_STATE_ERROR)) { + if ((ctxt != NULL) && (ctxt->state != XSLT_STATE_OK)) { xmlFreeDoc(res); res = NULL; } diff --git a/dll/3rdparty/libxslt/variables.c b/dll/3rdparty/libxslt/variables.c index fcd201db74e..fffb0c97f0b 100644 --- a/dll/3rdparty/libxslt/variables.c +++ b/dll/3rdparty/libxslt/variables.c @@ -19,11 +19,11 @@ const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt"; #endif -const xmlChar *xsltComputingGlobalVarMarker = +static const xmlChar *xsltComputingGlobalVarMarker = (const xmlChar *) " var/param being computed"; -#define XSLT_VAR_GLOBAL 1<<0 -#define XSLT_VAR_IN_SELECT 1<<1 +#define XSLT_VAR_GLOBAL (1<<0) +#define XSLT_VAR_IN_SELECT (1<<1) #define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable) /************************************************************************ @@ -101,6 +101,9 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT) if ((ctxt == NULL) || (RVT == NULL)) return(-1); + RVT->prev = NULL; + RVT->psvi = XSLT_RVT_VARIABLE; + /* * We'll restrict the lifetime of user-created fragments * insinde an xsl:variable and xsl:param to the lifetime of the @@ -138,15 +141,18 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, if ((ctxt == NULL) || (RVT == NULL)) return(-1); + RVT->prev = NULL; + /* * When evaluating "select" expressions of xsl:variable * and xsl:param, we need to bind newly created tree fragments - * to the variable itself; otherwise the tragment will be + * to the variable itself; otherwise the fragment will be * freed before we leave the scope of a var. */ if ((ctxt->contextVariable != NULL) && (XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT)) { + RVT->psvi = XSLT_RVT_VARIABLE; RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment; XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT; return(0); @@ -156,19 +162,11 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, * If not reference by a returning instruction (like EXSLT's function), * then this fragment will be freed, when the instruction exits. */ + RVT->psvi = XSLT_RVT_LOCAL; RVT->next = (xmlNodePtr) ctxt->localRVT; if (ctxt->localRVT != NULL) ctxt->localRVT->prev = (xmlNodePtr) RVT; ctxt->localRVT = RVT; - /* - * We need to keep track of the first registered fragment - * for extension instructions which return fragments - * (e.g. EXSLT'S function), in order to let - * xsltExtensionInstructionResultFinalize() clear the - * preserving flag on the fragments. - */ - if (ctxt->localRVTBase == NULL) - ctxt->localRVTBase = RVT; return(0); } @@ -183,26 +181,16 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, * collector will free them after the function-calling process exits. * * Returns 0 in case of success and -1 in case of API or internal errors. + * + * This function is unsupported in newer releases of libxslt. */ int xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt) { - xmlDocPtr cur; - - if (ctxt == NULL) - return(-1); - if (ctxt->localRVTBase == NULL) - return(0); - /* - * Enable remaining local tree fragments to be freed - * by the fragment garbage collector. - */ - cur = ctxt->localRVTBase; - do { - cur->psvi = NULL; - cur = (xmlDocPtr) cur->next; - } while (cur != NULL); - return(0); + xmlGenericError(xmlGenericErrorContext, + "xsltExtensionInstructionResultFinalize is unsupported " + "in this release of libxslt.\n"); + return(-1); } /** @@ -217,11 +205,35 @@ xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt) * tree fragments (via xsltCreateRVT()) with xsltRegisterLocalRVT(). * * Returns 0 in case of success and -1 in case of error. + * + * It isn't necessary to call this function in newer releases of + * libxslt. */ int xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj) { + return(0); +} + +/** + * xsltFlagRVTs: + * @ctxt: an XSLT transformation context + * @obj: an XPath object to be inspected for result tree fragments + * @val: the flag value + * + * Updates ownership information of RVTs in @obj according to @val. + * + * @val = XSLT_RVT_FUNC_RESULT for the result of an extension function, so its + * RVTs won't be destroyed after leaving the returning scope. + * @val = XSLT_RVT_LOCAL for the result of an extension function to reset + * the state of its RVTs after it was returned to a new scope. + * @val = XSLT_RVT_GLOBAL for parts of global variables. + * + * Returns 0 in case of success and -1 in case of error. + */ +int +xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) { int i; xmlNodePtr cur; xmlDocPtr doc; @@ -254,36 +266,59 @@ xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt, doc = cur->doc; } else { xsltTransformError(ctxt, NULL, ctxt->inst, - "Internal error in " - "xsltExtensionInstructionResultRegister(): " + "Internal error in xsltFlagRVTs(): " "Cannot retrieve the doc of a namespace node.\n"); - goto error; + return(-1); } } else { doc = cur->doc; } if (doc == NULL) { xsltTransformError(ctxt, NULL, ctxt->inst, - "Internal error in " - "xsltExtensionInstructionResultRegister(): " + "Internal error in xsltFlagRVTs(): " "Cannot retrieve the doc of a node.\n"); - goto error; + return(-1); } - if (doc->name && (doc->name[0] == ' ')) { + if (doc->name && (doc->name[0] == ' ') && + doc->psvi != XSLT_RVT_GLOBAL) { /* * This is a result tree fragment. - * We'll use the @psvi field for reference counting. - * TODO: How do we know if this is a value of a - * global variable or a doc acquired via the + * We store ownership information in the @psvi field. + * TODO: How do we know if this is a doc acquired via the * document() function? */ - doc->psvi = (void *) ((long) 1); +#ifdef WITH_XSLT_DEBUG_VARIABLE + XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext, + "Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val)); +#endif + + if (val == XSLT_RVT_LOCAL) { + if (doc->psvi != XSLT_RVT_FUNC_RESULT) { + xmlGenericError(xmlGenericErrorContext, + "xsltFlagRVTs: Invalid transition %p => LOCAL\n", + doc->psvi); + return(-1); + } + + xsltRegisterLocalRVT(ctxt, doc); + } else if (val == XSLT_RVT_GLOBAL) { + if (doc->psvi != XSLT_RVT_LOCAL) { + xmlGenericError(xmlGenericErrorContext, + "xsltFlagRVTs: Invalid transition %p => GLOBAL\n", + doc->psvi); + doc->psvi = XSLT_RVT_GLOBAL; + return(-1); + } + + /* Will be registered as persistant in xsltReleaseLocalRVTs. */ + doc->psvi = XSLT_RVT_GLOBAL; + } else if (val == XSLT_RVT_FUNC_RESULT) { + doc->psvi = val; + } } } return(0); -error: - return(-1); } /** @@ -329,9 +364,9 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT) } /* - * Reset the reference counter. + * Reset the ownership information. */ - RVT->psvi = 0; + RVT->psvi = NULL; RVT->next = (xmlNodePtr) ctxt->cache->RVT; ctxt->cache->RVT = RVT; @@ -370,6 +405,8 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT) { if ((ctxt == NULL) || (RVT == NULL)) return(-1); + RVT->psvi = XSLT_RVT_GLOBAL; + RVT->prev = NULL; RVT->next = (xmlNodePtr) ctxt->persistRVT; if (ctxt->persistRVT != NULL) ctxt->persistRVT->prev = (xmlNodePtr) RVT; @@ -520,35 +557,21 @@ xsltFreeStackElem(xsltStackElemPtr elem) { /* * Release the list of temporary Result Tree Fragments. */ - if (elem->fragment) { + if (elem->context) { xmlDocPtr cur; while (elem->fragment != NULL) { cur = elem->fragment; elem->fragment = (xmlDocPtr) cur->next; - if (elem->context && - (cur->psvi == (void *) ((long) 1))) - { - /* - * This fragment is a result of an extension instruction - * (e.g. XSLT's function) and needs to be preserved until - * the instruction exits. - * Example: The fragment of the variable must not be freed - * since it is returned by the EXSLT function: - * - * - * - * - * - * - * - */ - xsltRegisterLocalRVT(elem->context, cur); - } else { + if (cur->psvi == XSLT_RVT_VARIABLE) { xsltReleaseRVT((xsltTransformContextPtr) elem->context, cur); - } + } else if (cur->psvi != XSLT_RVT_FUNC_RESULT) { + xmlGenericError(xmlGenericErrorContext, + "xsltFreeStackElem: Unexpected RVT flag %p\n", + cur->psvi); + } } } /* @@ -942,6 +965,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable, * the Result Tree Fragment. */ variable->fragment = container; + container->psvi = XSLT_RVT_VARIABLE; oldOutput = ctxt->output; oldInsert = ctxt->insert; @@ -1128,16 +1152,23 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) xsltTransformError(ctxt, NULL, comp->inst, "Evaluating global variable %s failed\n", elem->name); ctxt->state = XSLT_STATE_STOPPED; + goto error; + } + + /* + * Mark all RVTs that are referenced from result as part + * of this variable so they won't be freed too early. + */ + xsltFlagRVTs(ctxt, result, XSLT_RVT_GLOBAL); + #ifdef WITH_XSLT_DEBUG_VARIABLE #ifdef LIBXML_DEBUG_ENABLED - } else { - if ((xsltGenericDebugContext == stdout) || - (xsltGenericDebugContext == stderr)) - xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext, - result, 0); + if ((xsltGenericDebugContext == stdout) || + (xsltGenericDebugContext == stderr)) + xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext, + result, 0); #endif #endif - } } else { if (elem->tree == NULL) { result = xmlXPathNewCString(""); @@ -1751,8 +1782,7 @@ xsltBuildVariable(xsltTransformContextPtr ctxt, elem->tree = tree; elem->value = xsltEvalVariable(ctxt, elem, (xsltStylePreCompPtr) comp); - if (elem->value != NULL) - elem->computed = 1; + elem->computed = 1; return(elem); } diff --git a/dll/3rdparty/libxslt/xslt.c b/dll/3rdparty/libxslt/xslt.c index d076c25614b..411f3444940 100644 --- a/dll/3rdparty/libxslt/xslt.c +++ b/dll/3rdparty/libxslt/xslt.c @@ -247,7 +247,7 @@ xsltIsBlank(xmlChar *str) { * * ************************************************************************/ static xsltDecimalFormatPtr -xsltNewDecimalFormat(xmlChar *name) +xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name) { xsltDecimalFormatPtr self; /* UTF-8 for 0x2030 */ @@ -256,6 +256,7 @@ xsltNewDecimalFormat(xmlChar *name) self = xmlMalloc(sizeof(xsltDecimalFormat)); if (self != NULL) { self->next = NULL; + self->nsUri = nsUri; self->name = name; /* Default values */ @@ -341,7 +342,39 @@ xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name) for (result = style->decimalFormat->next; result != NULL; result = result->next) { - if (xmlStrEqual(name, result->name)) + if ((result->nsUri == NULL) && xmlStrEqual(name, result->name)) + return result; + } + style = xsltNextImport(style); + } + return result; +} + +/** + * xsltDecimalFormatGetByQName: + * @style: the XSLT stylesheet + * @nsUri: the namespace URI of the QName + * @name: the local part of the QName + * + * Find decimal-format by QName + * + * Returns the xsltDecimalFormatPtr + */ +xsltDecimalFormatPtr +xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri, + const xmlChar *name) +{ + xsltDecimalFormatPtr result = NULL; + + if (name == NULL) + return style->decimalFormat; + + while (style != NULL) { + for (result = style->decimalFormat->next; + result != NULL; + result = result->next) { + if (xmlStrEqual(nsUri, result->nsUri) && + xmlStrEqual(name, result->name)) return result; } style = xsltNextImport(style); @@ -719,7 +752,7 @@ xsltNewStylesheet(void) { ret->omitXmlDeclaration = -1; ret->standalone = -1; - ret->decimalFormat = xsltNewDecimalFormat(NULL); + ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL); ret->indent = -1; ret->errors = 0; ret->warnings = 0; @@ -782,9 +815,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt) ctxt->extras = (xsltRuntimeExtraPtr) xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra)); if (ctxt->extras == NULL) { - xmlGenericError(xmlGenericErrorContext, + xsltTransformError(ctxt, NULL, NULL, "xsltAllocateExtraCtxt: out of memory\n"); - ctxt->state = XSLT_STATE_ERROR; return(0); } for (i = 0;i < ctxt->extrasMax;i++) { @@ -800,9 +832,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt) tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras, ctxt->extrasMax * sizeof(xsltRuntimeExtra)); if (tmp == NULL) { - xmlGenericError(xmlGenericErrorContext, + xsltTransformError(ctxt, NULL, NULL, "xsltAllocateExtraCtxt: out of memory\n"); - ctxt->state = XSLT_STATE_ERROR; return(0); } ctxt->extras = tmp; @@ -1181,6 +1212,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur) xsltTransformError(NULL, style, cur, "invalid value for method: %s\n", prop); if (style != NULL) style->warnings++; + xmlFree(prop); } } else { style->method = prop; @@ -1358,18 +1390,37 @@ xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur) prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL); if (prop != NULL) { - format = xsltDecimalFormatGetByName(style, prop); + const xmlChar *nsUri; + + if (xmlValidateQName(prop, 0) != 0) { + xsltTransformError(NULL, style, cur, + "xsl:decimal-format: Invalid QName '%s'.\n", prop); + style->warnings++; + xmlFree(prop); + return; + } + /* + * TODO: Don't use xsltGetQNameURI(). + */ + nsUri = xsltGetQNameURI(cur, &prop); + if (prop == NULL) { + style->warnings++; + return; + } + format = xsltDecimalFormatGetByQName(style, nsUri, prop); if (format != NULL) { xsltTransformError(NULL, style, cur, "xsltParseStylestyleDecimalFormat: %s already exists\n", prop); - if (style != NULL) style->warnings++; + style->warnings++; + xmlFree(prop); return; } - format = xsltNewDecimalFormat(prop); + format = xsltNewDecimalFormat(nsUri, prop); if (format == NULL) { xsltTransformError(NULL, style, cur, "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n"); - if (style != NULL) style->errors++; + style->errors++; + xmlFree(prop); return; } /* Append new decimal-format structure */ @@ -3396,7 +3447,7 @@ internal_err: #ifdef XSLT_REFACTORED #else static void -xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) +xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) { xmlNodePtr deleteNode, styleelem; int internalize = 0; @@ -3427,7 +3478,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) if (deleteNode != NULL) { #ifdef WITH_XSLT_DEBUG_BLANKS xsltGenericDebug(xsltGenericDebugContext, - "xsltPrecomputeStylesheet: removing ignorable blank node\n"); + "xsltPreprocessStylesheet: removing ignorable blank node\n"); #endif xmlUnlinkNode(deleteNode); xmlFreeNode(deleteNode); @@ -3467,7 +3518,6 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) } if (IS_XSLT_ELEM(cur)) { exclPrefixes = 0; - xsltStylePreCompute(style, cur); if (IS_XSLT_NAME(cur, "text")) { for (;exclPrefixes > 0;exclPrefixes--) exclPrefixPop(style); @@ -3518,7 +3568,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) * going back */ if (exclPrefixes > 0) { - xsltPrecomputeStylesheet(style, cur->children); + xsltPreprocessStylesheet(style, cur->children); for (;exclPrefixes > 0;exclPrefixes--) exclPrefixPop(style); goto skip_children; @@ -3589,7 +3639,7 @@ skip_children: if (deleteNode != NULL) { #ifdef WITH_XSLT_DEBUG_PARSING xsltGenericDebug(xsltGenericDebugContext, - "xsltPrecomputeStylesheet: removing ignorable blank node\n"); + "xsltPreprocessStylesheet: removing ignorable blank node\n"); #endif xmlUnlinkNode(deleteNode); xmlFreeNode(deleteNode); @@ -4834,10 +4884,12 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) { delete = NULL; } if (IS_XSLT_ELEM(cur)) { + xsltStylePreCompute(style, cur); + if (IS_XSLT_NAME(cur, "text")) { /* * TODO: Processing of xsl:text should be moved to - * xsltPrecomputeStylesheet(), since otherwise this + * xsltPreprocessStylesheet(), since otherwise this * will be performed for every multiply included * stylesheet; i.e. this here is not skipped with * the use of the style->nopreproc flag. @@ -5367,6 +5419,7 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) { xsltTransformError(NULL, style, template, "xsl:template : error invalid name '%s'\n", prop); if (style != NULL) style->errors++; + xmlFree(prop); goto error; } ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1); @@ -6026,7 +6079,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) { if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) && (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) { xsltTransformError(NULL, style, top, - "xsl:version: only 1.0 features are supported\n"); + "xsl:version: only 1.1 features are supported\n"); if (style != NULL) { style->forwards_compatible = 1; style->warnings++; @@ -6097,31 +6150,31 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) { xsltTransformError(NULL, style, cur, "xsltParseStylesheetTop: ignoring misplaced import element\n"); if (style != NULL) style->errors++; - } else if (IS_XSLT_NAME(cur, "include")) { + } else if (IS_XSLT_NAME(cur, "include")) { if (xsltParseStylesheetInclude(style, cur) != 0) if (style != NULL) style->errors++; - } else if (IS_XSLT_NAME(cur, "strip-space")) { + } else if (IS_XSLT_NAME(cur, "strip-space")) { xsltParseStylesheetStripSpace(style, cur); - } else if (IS_XSLT_NAME(cur, "preserve-space")) { + } else if (IS_XSLT_NAME(cur, "preserve-space")) { xsltParseStylesheetPreserveSpace(style, cur); - } else if (IS_XSLT_NAME(cur, "output")) { + } else if (IS_XSLT_NAME(cur, "output")) { xsltParseStylesheetOutput(style, cur); - } else if (IS_XSLT_NAME(cur, "key")) { + } else if (IS_XSLT_NAME(cur, "key")) { xsltParseStylesheetKey(style, cur); - } else if (IS_XSLT_NAME(cur, "decimal-format")) { + } else if (IS_XSLT_NAME(cur, "decimal-format")) { xsltParseStylesheetDecimalFormat(style, cur); - } else if (IS_XSLT_NAME(cur, "attribute-set")) { + } else if (IS_XSLT_NAME(cur, "attribute-set")) { xsltParseStylesheetAttributeSet(style, cur); - } else if (IS_XSLT_NAME(cur, "variable")) { + } else if (IS_XSLT_NAME(cur, "variable")) { xsltParseGlobalVariable(style, cur); - } else if (IS_XSLT_NAME(cur, "param")) { + } else if (IS_XSLT_NAME(cur, "param")) { xsltParseGlobalParam(style, cur); - } else if (IS_XSLT_NAME(cur, "template")) { + } else if (IS_XSLT_NAME(cur, "template")) { #ifdef WITH_XSLT_DEBUG_PARSING templates++; #endif xsltParseStylesheetTemplate(style, cur); - } else if (IS_XSLT_NAME(cur, "namespace-alias")) { + } else if (IS_XSLT_NAME(cur, "namespace-alias")) { xsltNamespaceAlias(style, cur); } else { if ((style != NULL) && (style->forwards_compatible == 0)) { @@ -6130,13 +6183,6 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) { cur->name); if (style != NULL) style->errors++; } - else { - /* do Forwards-Compatible Processing */ - xsltTransformError(NULL, style, cur, - "xsltParseStylesheetTop: ignoring unknown %s element\n", - cur->name); - if (style != NULL) style->warnings++; - } } cur = cur->next; } @@ -6380,7 +6426,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) { ret->literal_result = 1; } if (!ret->nopreproc) { - xsltPrecomputeStylesheet(ret, cur); + xsltPreprocessStylesheet(ret, cur); } if (ret->literal_result == 0) { xsltParseStylesheetTop(ret, cur); @@ -6403,10 +6449,11 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) { "xsltParseStylesheetProcess : document is stylesheet\n"); #endif - if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) { + if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) && + (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) { xsltTransformError(NULL, ret, cur, - "xsl:version: only 1.0 features are supported\n"); - /* TODO set up compatibility when not XSLT 1.0 */ + "xsl:version: only 1.1 features are supported\n"); + ret->forwards_compatible = 1; ret->warnings++; } xmlFree(prop); diff --git a/dll/3rdparty/libxslt/xsltconfig.h.in b/dll/3rdparty/libxslt/xsltconfig.h.in index 6e4e32850c9..5fa5e589631 100644 --- a/dll/3rdparty/libxslt/xsltconfig.h.in +++ b/dll/3rdparty/libxslt/xsltconfig.h.in @@ -123,19 +123,6 @@ extern "C" { #define LIBXSLT_DEFAULT_PLUGINS_PATH() "@LIBXSLT_DEFAULT_PLUGINS_PATH@" #endif -/** - * Locale support - */ -#if @XSLT_LOCALE_XLOCALE@ -#ifndef XSLT_LOCALE_XLOCALE -#define XSLT_LOCALE_XLOCALE -#endif -#elif @XSLT_LOCALE_WINAPI@ -#ifndef XSLT_LOCALE_WINAPI -#define XSLT_LOCALE_WINAPI -#endif -#endif - /** * ATTRIBUTE_UNUSED: * diff --git a/dll/3rdparty/libxslt/xsltlocale.c b/dll/3rdparty/libxslt/xsltlocale.c index 2b39b0988c5..14b20edc21a 100644 --- a/dll/3rdparty/libxslt/xsltlocale.c +++ b/dll/3rdparty/libxslt/xsltlocale.c @@ -14,13 +14,6 @@ #include "xsltlocale.h" -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2 -#define newlocale __newlocale -#define freelocale __freelocale -#define strxfrm_l __strxfrm_l -#define LC_COLLATE_MASK (1 << LC_COLLATE) -#endif - #define TOUPPER(c) (c & ~0x20) #define TOLOWER(c) (c | 0x20) #define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26) @@ -87,7 +80,7 @@ xsltFreeLocales(void) { */ xsltLocale xsltNewLocale(const xmlChar *languageTag) { -#ifdef XSLT_LOCALE_XLOCALE +#ifdef XSLT_LOCALE_POSIX xsltLocale locale; char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */ const xmlChar *p = languageTag; @@ -189,7 +182,7 @@ xsltNewLocale(const xmlChar *languageTag) { region = xsltDefaultRegion(localeName); if (region == NULL) goto end; - strcpy(localeName + llen + 1, region); + strcpy((char *) localeName + llen + 1, (char *) region); locale = xslt_locale_WINAPI(localeName); end: return(locale); @@ -347,7 +340,7 @@ xsltDefaultRegion(const xmlChar *localeName) { */ void xsltFreeLocale(xsltLocale locale) { -#ifdef XSLT_LOCALE_XLOCALE +#ifdef XSLT_LOCALE_POSIX freelocale(locale); #endif } @@ -371,7 +364,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string) size_t xstrlen, r; xsltLocaleChar *xstr; -#ifdef XSLT_LOCALE_XLOCALE +#ifdef XSLT_LOCALE_POSIX xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1; xstr = (xsltLocaleChar *) xmlMalloc(xstrlen); if (xstr == NULL) { @@ -384,7 +377,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string) #endif #ifdef XSLT_LOCALE_WINAPI - xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0); + xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0); if (xstrlen == 0) { xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n"); return(NULL); @@ -394,7 +387,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string) xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n"); return(NULL); } - r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen); + r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen); if (r == 0) { xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n"); xmlFree(xstr); @@ -481,9 +474,11 @@ xsltIterateSupportedLocales(LPSTR lcid) { k = sscanf(lcid, "%lx", (long*)&p->lcid); if (k < 1) goto end; /*don't count terminating null character*/ - k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang )); + k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME, + (char *) iso639lang, sizeof(iso639lang)); if (--k < 1) goto end; - l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry)); + l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, + (char *) iso3136ctry, sizeof(iso3136ctry)); if (--l < 1) goto end; { /*fill results*/ diff --git a/dll/3rdparty/libxslt/xsltutils.c b/dll/3rdparty/libxslt/xsltutils.c index 53facee6898..1b576489ce3 100644 --- a/dll/3rdparty/libxslt/xsltutils.c +++ b/dll/3rdparty/libxslt/xsltutils.c @@ -18,16 +18,9 @@ #include #endif -/* gettimeofday on Windows ??? */ -#if defined(WIN32) && !defined(__CYGWIN__) -#ifdef _MSC_VER -#include -#pragma comment(lib, "ws2_32.lib") -#define gettimeofday(p1,p2) -#define HAVE_GETTIMEOFDAY +#if defined(_WIN32) && !defined(__CYGWIN__) #define XSLT_WIN32_PERFORMANCE_COUNTER -#endif /* _MS_VER */ -#endif /* WIN32 */ +#endif /************************************************************************ * * @@ -433,9 +426,8 @@ xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) { } else if (xmlStrEqual(prop, (const xmlChar *)"no")) { terminate = 0; } else { - error(errctx, + xsltTransformError(ctxt, NULL, inst, "xsl:message : terminate expecting 'yes' or 'no'\n"); - ctxt->state = XSLT_STATE_ERROR; } xmlFree(prop); } @@ -598,7 +590,8 @@ xsltPrintErrorContext(xsltTransformContextPtr ctxt, void *errctx = xsltGenericErrorContext; if (ctxt != NULL) { - ctxt->state = XSLT_STATE_ERROR; + if (ctxt->state == XSLT_STATE_OK) + ctxt->state = XSLT_STATE_ERROR; if (ctxt->error != NULL) { error = ctxt->error; errctx = ctxt->errctx; @@ -691,7 +684,8 @@ xsltTransformError(xsltTransformContextPtr ctxt, char * str; if (ctxt != NULL) { - ctxt->state = XSLT_STATE_ERROR; + if (ctxt->state == XSLT_STATE_OK) + ctxt->state = XSLT_STATE_ERROR; if (ctxt->error != NULL) { error = ctxt->error; errctx = ctxt->errctx; @@ -1224,6 +1218,8 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, if (res[j] == NULL) { if (res[j+incr] != NULL) tst = 1; + } else if (res[j+incr] == NULL) { + tst = -1; } else { if (numb) { /* We make NaN smaller than number in @@ -1784,6 +1780,8 @@ static long calibration = -1; * * Returns the number of milliseconds used by xsltTimestamp() */ +#if !defined(XSLT_WIN32_PERFORMANCE_COUNTER) && \ + (defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY)) static long xsltCalibrateTimestamps(void) { register int i; @@ -1792,6 +1790,7 @@ xsltCalibrateTimestamps(void) { xsltTimestamp(); return(xsltTimestamp() / 1000); } +#endif /** * xsltCalibrateAdjust: diff --git a/dll/3rdparty/libxslt/xsltwin32config.h b/dll/3rdparty/libxslt/xsltwin32config.h index 70bb756adc8..63d90d08975 100644 --- a/dll/3rdparty/libxslt/xsltwin32config.h +++ b/dll/3rdparty/libxslt/xsltwin32config.h @@ -23,21 +23,21 @@ extern "C" { * * the version string like "1.2.3" */ -#define LIBXSLT_DOTTED_VERSION "1.1.28" +#define LIBXSLT_DOTTED_VERSION "1.1.32" /** * LIBXSLT_VERSION: * * the version number: 1.2.3 value is 1002003 */ -#define LIBXSLT_VERSION 10128 +#define LIBXSLT_VERSION 10132 /** * LIBXSLT_VERSION_STRING: * * the version number string, 1.2.3 value is "1002003" */ -#define LIBXSLT_VERSION_STRING "10128" +#define LIBXSLT_VERSION_STRING "10132" /** * LIBXSLT_VERSION_EXTRA: @@ -53,7 +53,7 @@ extern "C" { * is insignifiant and being able to run xsltpoc -v is useful. On * by default */ -#if 0 +#if 1 #define WITH_XSLT_DEBUG #endif @@ -62,7 +62,7 @@ extern "C" { * * Whether module support is configured into libxslt */ -#if 0 +#if 1 #ifndef WITH_MODULES #define WITH_MODULES #endif diff --git a/sdk/include/reactos/libs/libxslt/libxslt.h b/sdk/include/reactos/libs/libxslt/libxslt.h index 1201807c180..1265c04b719 100644 --- a/sdk/include/reactos/libs/libxslt/libxslt.h +++ b/sdk/include/reactos/libs/libxslt/libxslt.h @@ -10,7 +10,7 @@ #ifndef __XSLT_LIBXSLT_H__ #define __XSLT_LIBXSLT_H__ -#if defined(WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__) +#if defined(_WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__) #include #else #include "config.h" diff --git a/sdk/include/reactos/libs/libxslt/variables.h b/sdk/include/reactos/libs/libxslt/variables.h index 17b4c6f6f1f..24acf8d10e5 100644 --- a/sdk/include/reactos/libs/libxslt/variables.h +++ b/sdk/include/reactos/libs/libxslt/variables.h @@ -34,6 +34,41 @@ extern "C" { xsltRegisterAllElement(ctxt); \ (ctxt)->xpathCtxt->extra = ctxt +/* + * Flags for memory management of RVTs + */ + +/** + * XSLT_RVT_LOCAL: + * + * RVT is destroyed after the current instructions ends. + */ +#define XSLT_RVT_LOCAL ((void *)1) + +/** + * XSLT_RVT_VARIABLE: + * + * RVT is part of a local variable and destroyed after the variable goes out + * of scope. + */ +#define XSLT_RVT_VARIABLE ((void *)2) + +/** + * XSLT_RVT_FUNC_RESULT: + * + * RVT is part of results returned with func:result. The RVT won't be + * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or + * XSLT_RVT_VARIABLE in the template that receives the return value. + */ +#define XSLT_RVT_FUNC_RESULT ((void *)3) + +/** + * XSLT_RVT_GLOBAL: + * + * RVT is part of a global variable. + */ +#define XSLT_RVT_GLOBAL ((void *)4) + /* * Interfaces for the variable module. */ diff --git a/sdk/include/reactos/libs/libxslt/xsltInternals.h b/sdk/include/reactos/libs/libxslt/xsltInternals.h index 7123acec104..47125b36510 100644 --- a/sdk/include/reactos/libs/libxslt/xsltInternals.h +++ b/sdk/include/reactos/libs/libxslt/xsltInternals.h @@ -324,6 +324,7 @@ struct _xsltDecimalFormat { xmlChar *percent; xmlChar *permille; xmlChar *zeroDigit; + const xmlChar *nsUri; }; /** @@ -1754,8 +1755,8 @@ struct _xsltTransformContext { * Speed optimization when coalescing text nodes */ const xmlChar *lasttext; /* last text node content */ - unsigned int lasttsize; /* last text node size */ - unsigned int lasttuse; /* last text node use */ + int lasttsize; /* last text node size */ + int lasttuse; /* last text node use */ /* * Per Context Debugging */ @@ -1783,9 +1784,9 @@ struct _xsltTransformContext { xmlDocPtr localRVT; /* list of local tree fragments; will be freed when the instruction which created the fragment exits */ - xmlDocPtr localRVTBase; + xmlDocPtr localRVTBase; /* Obsolete */ int keyInitLevel; /* Needed to catch recursive keys issues */ - int funcLevel; /* Needed to catch recursive functions issues */ + int depth; /* Needed to catch recursions */ int maxTemplateDepth; int maxTemplateVars; }; @@ -1854,6 +1855,10 @@ XSLTPUBFUN void XSLTCALL XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name); +XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL + xsltDecimalFormatGetByQName(xsltStylesheetPtr style, + const xmlChar *nsUri, + const xmlChar *name); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltParseStylesheetProcess(xsltStylesheetPtr ret, @@ -1906,6 +1911,11 @@ XSLTPUBFUN int XSLTCALL XSLTPUBFUN int XSLTCALL xsltExtensionInstructionResultFinalize( xsltTransformContextPtr ctxt); +XSLTPUBFUN int XSLTCALL + xsltFlagRVTs( + xsltTransformContextPtr ctxt, + xmlXPathObjectPtr obj, + void *val); XSLTPUBFUN void XSLTCALL xsltFreeRVTs (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL diff --git a/sdk/include/reactos/libs/libxslt/xsltconfig.h b/sdk/include/reactos/libs/libxslt/xsltconfig.h index 0b82bf74159..f83bc88c510 100644 --- a/sdk/include/reactos/libs/libxslt/xsltconfig.h +++ b/sdk/include/reactos/libs/libxslt/xsltconfig.h @@ -20,21 +20,21 @@ extern "C" { * * the version string like "1.2.3" */ -#define LIBXSLT_DOTTED_VERSION "1.1.29" +#define LIBXSLT_DOTTED_VERSION "1.1.32" /** * LIBXSLT_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXSLT_VERSION 10129 +#define LIBXSLT_VERSION 10132 /** * LIBXSLT_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXSLT_VERSION_STRING "10129" +#define LIBXSLT_VERSION_STRING "10132" /** * LIBXSLT_VERSION_EXTRA: @@ -123,19 +123,6 @@ extern "C" { #define LIBXSLT_DEFAULT_PLUGINS_PATH() "/usr/lib/libxslt-plugins" #endif -/** - * Locale support - */ -#if 0 -#ifndef XSLT_LOCALE_XLOCALE -#define XSLT_LOCALE_XLOCALE -#endif -#elif 1 -#ifndef XSLT_LOCALE_WINAPI -#define XSLT_LOCALE_WINAPI -#endif -#endif - /** * ATTRIBUTE_UNUSED: * diff --git a/sdk/include/reactos/libs/libxslt/xsltlocale.h b/sdk/include/reactos/libs/libxslt/xsltlocale.h index b7b1b1ff272..657ceebbe0e 100644 --- a/sdk/include/reactos/libs/libxslt/xsltlocale.h +++ b/sdk/include/reactos/libs/libxslt/xsltlocale.h @@ -14,20 +14,31 @@ #include #include "xsltexports.h" -#ifdef XSLT_LOCALE_XLOCALE +#ifdef HAVE_STRXFRM_L +/* + * XSLT_LOCALE_POSIX: + * Macro indicating to use POSIX locale extensions + */ +#define XSLT_LOCALE_POSIX + +#ifdef HAVE_LOCALE_H #include -#include - -#ifdef __GLIBC__ -/*locale_t is defined only if _GNU_SOURCE is defined*/ -typedef __locale_t xsltLocale; -#else -typedef locale_t xsltLocale; #endif +#ifdef HAVE_XLOCALE_H +#include +#endif + +typedef locale_t xsltLocale; typedef xmlChar xsltLocaleChar; -#elif defined(XSLT_LOCALE_WINAPI) +#elif defined(_WIN32) && !defined(__CYGWIN__) + +/* + * XSLT_LOCALE_WINAPI: + * Macro indicating to use WinAPI for extended locale support + */ +#define XSLT_LOCALE_WINAPI #ifdef __REACTOS__ #define WIN32_NO_STATUS @@ -45,11 +56,9 @@ typedef wchar_t xsltLocaleChar; /* * XSLT_LOCALE_NONE: - * Macro indicating that locale are not supported + * Macro indicating that there's no extended locale support */ -#ifndef XSLT_LOCALE_NONE #define XSLT_LOCALE_NONE -#endif typedef void *xsltLocale; typedef xmlChar xsltLocaleChar;