diff --git a/ChangeLog b/ChangeLog index 8f2f1535..6c2d490c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Mon Jun 3 21:21:26 2002 Aleksey Sanin + + * result/c14n/exc-without-comments/merlin-c14n-two-* + result/c14n/without-comments/merlin-c14n-two-* + test/c14n/exc-without-comments/merlin-c14n-two-* + test/c14n/without-comments/merlin-c14n-two-* + testC14N.c Makefile.am: added merlin-c14n-two.tar.gz tests for + c14n/exc-c14n and slightly modified test script to handle + these test cases + * c14n.c: fixed bugs for complicated nodes set (namespace + without node and others from merlin-c14n-two.tar.gz) + * include/libxml/xpathInternals.h win32/dsp/libxml2.def.src + win32/libxml2.def.src: "opened" xmlXPathNodeSetFreeNs() function + for xmlsec performance patch + * xpath.c: fixed self::node() for namespaces and attributes + Fri May 31 12:16:48 2002 Aleksey Sanin * Makefile.am: updated c14n tests suite diff --git a/Makefile.am b/Makefile.am index 6a2edb59..96433960 100644 --- a/Makefile.am +++ b/Makefile.am @@ -612,29 +612,27 @@ Automatatests: testAutomata$(EXEEXT) fi ; fi ; done) C14Ntests : testC14N$(EXEEXT) + @echo "##" + @echo "## C14N and XPath regression tests" + @echo "##" -@(for m in with-comments without-comments exc-without-comments ; do \ - echo "##"; \ - echo "## C14N regression tests: $$m"; \ - echo "##"; \ for i in $(srcdir)/test/c14n/$$m/*.xml ; do \ if [ ! -d $$i ] ; then \ name=`basename $$i .xml`; \ - echo Testing $$name; \ + echo Testing $$m/$$name; \ + cmdline="$(CHECKER) $(top_builddir)/testC14N --$$m $$i"; \ if [ -e $(srcdir)/test/c14n/$$m/$$name.xpath ] ; then \ - xpathFile=$(srcdir)/test/c14n/$$m/$$name.xpath; \ - else \ - xpathFile=""; \ + cmdline="$$cmdline $(srcdir)/test/c14n/$$m/$$name.xpath"; \ + if [ -e $(srcdir)/test/c14n/$$m/$$name.ns ] ; then \ + cmdline="$$cmdline '`cat $(srcdir)/test/c14n/$$m/$$name.ns`'"; \ + fi; \ fi; \ - if [ -e $(srcdir)/test/c14n/$$m/$$name.ns ] ; then \ - nsList=`cat $(srcdir)/test/c14n/$$m/$$name.ns`; \ - else \ - nsList=""; \ - fi; \ - $(CHECKER) $(top_builddir)/testC14N --$$m $$i $$xpathFile $$nsList > $(srcdir)/test/c14n/test.tmp; \ + $$cmdline > $(srcdir)/test/c14n/test.tmp; \ if [ $$? -eq 0 ]; then \ diff $(srcdir)/result/c14n/$$m/$$name $(srcdir)/test/c14n/test.tmp; \ if [ $$? -ne 0 ]; then \ echo "Test failed"; \ + cat $(srcdir)/test/c14n/test.tmp; \ fi; \ else \ echo "C14N failed"; \ diff --git a/c14n.c b/c14n.c index 3ab4a2f2..9d42fa38 100644 --- a/c14n.c +++ b/c14n.c @@ -38,12 +38,25 @@ typedef enum { XMLC14N_AFTER_DOCUMENT_ELEMENT = 2 } xmlC14NPosition; -typedef struct _xmlC14NNamespaces { - int nsNr; /* number of nodes in the set */ +typedef struct _xmlC14NVisibleNsStack { + int nsCurEnd; /* number of nodes in the set */ + int nsPrevStart; /* the begginning of the stack for previous visible node */ + int nsPrevEnd; /* the end of the stack for previous visible node */ int nsMax; /* size of the array as allocated */ - int nsPos; /* the begginning of the stack for this node */ xmlNsPtr *nsTab; /* array of nodes in no particular order */ -} xmlC14NNamespaces, *xmlC14NNamespacesPtr; +} xmlC14NVisibleNsStack, *xmlC14NVisibleNsStackPtr; +static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void); +static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur); +static void xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur, + xmlNsPtr ns); +static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur, + xmlC14NVisibleNsStackPtr state); +static void xmlC14NVisibleNsStackRestore (xmlC14NVisibleNsStackPtr cur, + xmlC14NVisibleNsStackPtr state); +static void xmlC14NVisibleNsStackShift (xmlC14NVisibleNsStackPtr cur); +static int xmlC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur, + xmlNsPtr ns, + int exclusive); typedef struct _xmlC14NCtx { /* input parameters */ @@ -55,7 +68,7 @@ typedef struct _xmlC14NCtx { /* position in the XML document */ xmlC14NPosition pos; int parent_is_doc; - xmlC14NNamespacesPtr ns_rendered; + xmlC14NVisibleNsStackPtr ns_rendered; /* exclusive canonicalization */ int exclusive; @@ -91,36 +104,45 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input, ************************************************************************/ #define XML_NAMESPACES_DEFAULT 16 -static xmlC14NNamespacesPtr -xmlC14NNamespacesCreate() { - xmlC14NNamespacesPtr ret; +static xmlC14NVisibleNsStackPtr +xmlC14NVisibleNsStackCreate(void) { + xmlC14NVisibleNsStackPtr ret; - ret = (xmlC14NNamespacesPtr) xmlMalloc(sizeof(xmlC14NNamespaces)); + ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack)); if (ret == NULL) { xmlGenericError(xmlGenericErrorContext, - "xmlC14NNamespacesCreate: out of memory\n"); + "xmlC14NVisibleNsStackCreate: out of memory\n"); return(NULL); } - memset(ret, 0 , (size_t) sizeof(xmlC14NNamespaces)); + memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack)); return(ret); } static void -xmlC14NNamespacesDestroy(xmlC14NNamespacesPtr cur) { +xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) { if(cur == NULL) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackAdd: cur is null.\n"); +#endif return; } if(cur->nsTab != NULL) { memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr)); xmlFree(cur->nsTab); } - memset(cur, 0, sizeof(xmlC14NNamespaces)); + memset(cur, 0, sizeof(xmlC14NVisibleNsStack)); xmlFree(cur); } -static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) { - if((cur == NULL) || (ns == NULL)) { +static void +xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns) { + if(cur == NULL) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackAdd: cur is null.\n"); +#endif return; } @@ -128,12 +150,12 @@ static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) { cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); if (cur->nsTab == NULL) { xmlGenericError(xmlGenericErrorContext, - "xmlC14NNamespacesAdd: out of memory\n"); + "xmlC14NVisibleNsStackAdd: out of memory\n"); return; } memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); cur->nsMax = XML_NAMESPACES_DEFAULT; - } else if(cur->nsMax == cur->nsNr) { + } else if(cur->nsMax == cur->nsCurEnd) { xmlNsPtr *tmp; int tmpSize; @@ -141,13 +163,111 @@ static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) { tmp = (xmlNsPtr*) xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr)); if (tmp == NULL) { xmlGenericError(xmlGenericErrorContext, - "xmlC14NNamespacesAdd: out of memory\n"); + "xmlC14NVisibleNsStackAdd: out of memory\n"); return; } cur->nsTab = tmp; cur->nsMax = tmpSize; } - cur->nsTab[cur->nsNr++] = ns; + cur->nsTab[cur->nsCurEnd++] = ns; +} + +static void +xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { + if((cur == NULL) || (state == NULL)) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackSave: cur or state is null.\n"); +#endif + return; + } + + state->nsCurEnd = cur->nsCurEnd; + state->nsPrevStart = cur->nsPrevStart; + state->nsPrevEnd = cur->nsPrevEnd; +} + +static void +xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { + if((cur == NULL) || (state == NULL)) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackRestore: cur or state is null.\n"); +#endif + return; + } + cur->nsCurEnd = state->nsCurEnd; + cur->nsPrevStart = state->nsPrevStart; + cur->nsPrevEnd = state->nsPrevEnd; +} + +static void +xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) { + if(cur == NULL) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackRestore: cur is null.\n"); +#endif + return; + } + cur->nsPrevStart = cur->nsPrevEnd; + cur->nsPrevEnd = cur->nsCurEnd; +} + +static int +xmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) { + if (str1 == str2) return(1); + if (str1 == NULL) return((*str2) == '\0'); + if (str2 == NULL) return((*str1) == '\0'); + do { + if (*str1++ != *str2) return(0); + } while (*str2++); + return(1); +} + +/** + * xmlC14NVisibleNsStackFind: + * @ctx the C14N context + * @ns the namespace to check + * + * Checks whether the given namespace was already rendered or not + * + * Returns 1 if we already wrote this namespace or 0 otherwise + */ +static int +xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, int exclusive) +{ + int i; + const xmlChar *prefix; + const xmlChar *href; + int emptyNs; + + if(cur == NULL) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NVisibleNsStackFind: cur is null.\n"); +#endif + return (0); + } + + /* + * if the default namespace xmlns="" is not defined yet then + * we do not want to print it out + */ + prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix; + href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href; + emptyNs = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL)); + if (cur->nsTab != NULL) { + int start = (exclusive || emptyNs) ? 0 : cur->nsPrevStart; + for (i = cur->nsCurEnd - 1; i >= start; --i) { + xmlNsPtr ns1 = cur->nsTab[i]; + + if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) { + return(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL)); + } + } + } + return(emptyNs); } @@ -179,6 +299,30 @@ xmlC14NIsVisible(xmlC14NCtxPtr ctx, void *node) return (1); } +static int +xmlC14NIsNsVisible(xmlC14NCtxPtr ctx, xmlNsPtr ns, xmlNodePtr cur) +{ + xmlNs ns1; + + if(ns == NULL) { + return(1); + } + memcpy(&ns1, ns, sizeof(ns1)); + ns1.next = (xmlNsPtr)cur; + + /* + * If the input is an XPath node-set, then the node-set must explicitly + * contain every node to be rendered to the canonical form. + */ + if ((ctx->visible_nodes != NULL) && + (!xmlXPathNodeSetContains(ctx->visible_nodes, (xmlNodePtr) &ns1))) + { + return (0); + } + + return (1); +} + /** * xmlC14NIsXmlNs: * @ns: the namespace to check @@ -200,45 +344,9 @@ xmlC14NIsXmlNs(xmlNsPtr ns) "http://www.w3.org/XML/1998/namespace"))); } -/** - * xmlExcC14NIsRendered: - * @ctx the C14N context - * @ns the namespace to check - * - * Checks whether the given namespace was already rendered or not - * - * Returns 1 if we already wrote this namespace or 0 otherwise - */ -static int -xmlExcC14NIsRendered(xmlC14NCtxPtr ctx, xmlNsPtr ns) -{ - int i; - int emptyNs; - - if ((ctx == NULL) || (ctx->ns_rendered == NULL) || (ns == NULL)) { - return (0); - } - - /* - * if the default namespace xmlns="" is not defined yet then - * we do not want to print it out - */ - emptyNs = ((xmlStrlen(ns->prefix) == 0) && (xmlStrlen(ns->href) == 0)); - if (ctx->ns_rendered->nsTab != NULL) { - int pos = (emptyNs) ? 0 : ctx->ns_rendered->nsPos; - for (i = ctx->ns_rendered->nsNr - 1; i >= pos; --i) { - xmlNsPtr ns1 = ctx->ns_rendered->nsTab[i]; - - if (xmlStrEqual(ns1->prefix, ns->prefix)) { - return (xmlStrEqual(ns1->href, ns->href)); - } - } - } - return(emptyNs); -} /** - * xmlC14NNamespacesCompare: + * xmlC14NNsCompare: * @ns1: the pointer to first namespace * @ns2: the pointer to second namespace * @@ -247,7 +355,7 @@ xmlExcC14NIsRendered(xmlC14NCtxPtr ctx, xmlNsPtr ns) * Returns -1 if ns1 < ns2, 0 if ns1 == ns2 or 1 if ns1 > ns2. */ static int -xmlC14NNamespacesCompare(xmlNsPtr ns1, xmlNsPtr ns2) +xmlC14NNsCompare(xmlNsPtr ns1, xmlNsPtr ns2) { if (ns1 == ns2) return (0); @@ -288,7 +396,9 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) } else { xmlOutputBufferWriteString(ctx->buf, " xmlns=\""); } - xmlOutputBufferWriteString(ctx->buf, (const char *) ns->href); + if(ns->href != NULL) { + xmlOutputBufferWriteString(ctx->buf, (const char *) ns->href); + } xmlOutputBufferWriteString(ctx->buf, "\""); return (1); } @@ -333,7 +443,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) * Returns 0 on success or -1 on fail. */ static int -xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) +xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) { xmlNsPtr ns; xmlListPtr list; @@ -350,7 +460,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) * Create a sorted list to store element namespaces */ list = - xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNamespacesCompare); + xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare); if (list == NULL) { #ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, @@ -374,30 +484,56 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) } } } else { + xmlNodePtr node; int i; + int emptyNs = 0; /* * All visible namespace nodes are in the nodes set */ for(i = 0; i < ctx->visible_nodes->nodeNr; i++) { - if(ctx->visible_nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) { - ns = (xmlNsPtr) ctx->visible_nodes->nodeTab[i]; + node = ctx->visible_nodes->nodeTab[i]; + if((node != NULL) && (node->type == XML_NAMESPACE_DECL)) { + ns = (xmlNsPtr)node; - if((ns != NULL) && (ns->next == (xmlNsPtr)cur) && !xmlC14NIsXmlNs(ns)) { - if(!xmlExcC14NIsRendered(ctx, ns)) { + if(((xmlNodePtr)(ns->next) == cur) && !xmlC14NIsXmlNs(ns)) { + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 0)) { xmlListInsert(list, ns); } - xmlC14NNamespacesAdd(ctx->ns_rendered, ns); + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns); + } + if(xmlStrlen(ns->prefix) == 0) { + emptyNs = 1; + } } } } + + /** + * if the first node is not the default namespace node (a node with no + * namespace URI and no local name), then generate a space followed by + * xmlns="" if and only if the following conditions are met: + * - the element E that owns the axis is in the node-set + * - the nearest ancestor element of E in the node-set has a default + * namespace node in the node-set (default namespace nodes always + * have non-empty values in XPath) + */ + if(visible && !emptyNs) { + xmlNs ns1; + + memset(&ns1, 0, sizeof(ns1)); + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns1, 0)) { + xmlC14NPrintNamespaces(&ns1, ctx); + } + } } - + + /* * print out all elements from list */ - xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, - (const void *) ctx); + xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx); /* * Cleanup @@ -438,11 +574,13 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) * Returns 0 on success or -1 on fail. */ static int -xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) +xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) { xmlListPtr list; xmlAttrPtr attr; xmlNsPtr ns; + xmlNs default_ns; + if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { #ifdef DEBUG_C14N @@ -452,7 +590,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) return (-1); } - if ((!ctx->exclusive) || (ctx->ns_rendered == NULL)) { + if(!ctx->exclusive) { #ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, "xmlExcC14NProcessNamespacesAxis: called for non-exclusive canonization or rendered stack is NULL.\n"); @@ -460,12 +598,12 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) return (-1); } + memset(&default_ns, 0, sizeof(default_ns)); /* * Create a sorted list to store element namespaces */ - list = - xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNamespacesCompare); + list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare); if (list == NULL) { #ifdef DEBUG_C14N xmlGenericError(xmlGenericErrorContext, @@ -480,13 +618,19 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) * we also need to check for default "xml:" namespace * todo: shouldn't we check for namespaces "visibility"? */ - ns = (cur->ns != NULL) ? cur->ns : xmlSearchNs(ctx->doc, cur, NULL); - if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) && (xmlListSearch(list, ns) == NULL)) { - if(!xmlExcC14NIsRendered(ctx, ns)) { - xmlListInsert(list, ns); + if(visible) { + ns = (cur->ns != NULL) ? cur->ns : xmlSearchNs(ctx->doc, cur, NULL); + if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) && (xmlListSearch(list, ns) == NULL) && + xmlC14NIsNsVisible(ctx, ns, cur)) { + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 1)) { + xmlListInsert(list, ns); + } + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns); + } } - xmlC14NNamespacesAdd(ctx->ns_rendered, ns); } + attr = cur->properties; while (attr != NULL) { /* @@ -495,11 +639,14 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) * do not apply directly to attributes") */ if ((attr->ns != NULL) && xmlC14NIsVisible(ctx, attr) && + xmlC14NIsNsVisible(ctx, attr->ns, cur) && (!xmlC14NIsXmlNs(attr->ns)) && (xmlListSearch(list, attr->ns) == NULL)) { - if(!xmlExcC14NIsRendered(ctx, attr->ns)) { + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, 1)) { xmlListInsert(list, attr->ns); } - xmlC14NNamespacesAdd(ctx->ns_rendered, attr->ns); + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns); + } } attr = attr->next; } @@ -521,12 +668,21 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) prefix = NULL; } ns = xmlSearchNs(ctx->doc, cur, prefix); - if ((ns != NULL) && (!xmlC14NIsXmlNs(ns))) { - if (xmlListSearch(list, ns) == NULL) { - if(!xmlExcC14NIsRendered(ctx, ns)) { + if((ns != NULL) && (!xmlC14NIsXmlNs(ns))) { + int ns_visible = xmlC14NIsNsVisible(ctx, ns, cur); + + if(!ns_visible && (prefix == NULL)) { + ns = &default_ns; + ns_visible = 1; + } + if (ns_visible) { + if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 1)) { xmlListInsert(list, ns); } - xmlC14NNamespacesAdd(ctx->ns_rendered, ns); + if(visible) { + xmlC14NVisibleNsStackAdd(ctx->ns_rendered, + (ns == &default_ns) ? NULL : ns); + } } } } @@ -535,8 +691,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) /* * print out all elements from list */ - xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, - (const void *) ctx); + xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx); /* * Cleanup @@ -548,7 +703,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) /** * xmlC14NAttrsCompare: - * @attr1: the pointer to first attr + * @attr1: the pointer tls o first attr * @attr2: the pointer to second attr * * Prints the given attribute to the output buffer from C14N context. @@ -748,8 +903,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur) /* * print out all elements from list */ - xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs, - (const void *) ctx); + xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs, (const void *) ctx); /* * Cleanup @@ -836,8 +990,7 @@ static int xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) { int ret; - int ns_rendered_pos = 0; - int ns_rendered_nr = 0; + xmlC14NVisibleNsStack state; int parent_is_doc = 0; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { @@ -863,13 +1016,9 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) /* - * Save ns_rendered stack position for exclusive - * processing + * Save ns_rendered stack position */ - if (ctx->ns_rendered != NULL) { - ns_rendered_pos = ctx->ns_rendered->nsPos; - ns_rendered_nr = ctx->ns_rendered->nsNr; - } + xmlC14NVisibleNsStackSave(ctx->ns_rendered, &state); if (visible) { if (ctx->parent_is_doc) { @@ -886,32 +1035,37 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) xmlOutputBufferWriteString(ctx->buf, ":"); } xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name); + } - if (ctx->exclusive) { - ret = xmlExcC14NProcessNamespacesAxis(ctx, cur); - } else { - ret = xmlC14NProcessNamespacesAxis(ctx, cur); - } - if (ret < 0) { + if (!ctx->exclusive) { + ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible); + } else { + ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible); + } + if (ret < 0) { #ifdef DEBUG_C14N - xmlGenericError(xmlGenericErrorContext, - "xmlC14NProcessElementNode: xmlC14NProcessNamespacesAxis failed.\n"); + xmlGenericError(xmlGenericErrorContext, + "xmlC14NProcessElementNode: xmlC14NProcessNamespacesAxis failed.\n"); #endif - return (-1); - } - if (ctx->ns_rendered != NULL) { - ctx->ns_rendered->nsPos = ns_rendered_nr; + return (-1); + } + /* todo: shouldn't this go to "visible only"? */ + if(visible) { + xmlC14NVisibleNsStackShift(ctx->ns_rendered); + } + + if(visible) { + ret = xmlC14NProcessAttrsAxis(ctx, cur); + if (ret < 0) { +#ifdef DEBUG_C14N + xmlGenericError(xmlGenericErrorContext, + "xmlC14NProcessElementNode: xmlC14NProcessAttrsAxis failed.\n"); +#endif + return (-1); } + } - ret = xmlC14NProcessAttrsAxis(ctx, cur); - if (ret < 0) { -#ifdef DEBUG_C14N - xmlGenericError(xmlGenericErrorContext, - "xmlC14NProcessElementNode: xmlC14NProcessAttrsAxis failed.\n"); -#endif - return (-1); - } - + if (visible) { xmlOutputBufferWriteString(ctx->buf, ">"); } if (cur->children != NULL) { @@ -941,13 +1095,9 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) } /* - * Restore ns_rendered stack position for exclusive - * processing + * Restore ns_rendered stack position */ - if (ctx->ns_rendered != NULL) { - ctx->ns_rendered->nsPos = ns_rendered_pos; - ctx->ns_rendered->nsNr = ns_rendered_nr; - } + xmlC14NVisibleNsStackRestore(ctx->ns_rendered, &state); return (0); } @@ -1210,7 +1360,7 @@ xmlC14NFreeCtx(xmlC14NCtxPtr ctx) } if (ctx->ns_rendered != NULL) { - xmlC14NNamespacesDestroy(ctx->ns_rendered); + xmlC14NVisibleNsStackDestroy(ctx->ns_rendered); } xmlFree(ctx); } @@ -1288,7 +1438,14 @@ xmlC14NNewCtx(xmlDocPtr doc, xmlNodeSetPtr nodes, ctx->buf = buf; ctx->parent_is_doc = 1; ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT; - ctx->ns_rendered = xmlC14NNamespacesCreate(); + ctx->ns_rendered = xmlC14NVisibleNsStackCreate(); + + if(ctx->ns_rendered == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n"); + xmlC14NFreeCtx(ctx); + return (NULL); + } /* * Set "exclusive" flag, create a nodes set for namespaces diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h index 80b6b43e..45f36589 100644 --- a/include/libxml/xpathInternals.h +++ b/include/libxml/xpathInternals.h @@ -571,6 +571,12 @@ void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); + +/** + * Really internal functions + */ +void xmlXPathNodeSetFreeNs(xmlNsPtr ns); + #ifdef __cplusplus } #endif diff --git a/testC14N.c b/testC14N.c index 9bd9e432..14236fa5 100644 --- a/testC14N.c +++ b/testC14N.c @@ -46,8 +46,7 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename); xmlChar **parse_list(xmlChar *str); -void -print_xpath_nodes(xmlXPathObjectPtr ptr); +void print_xpath_nodes(xmlNodeSetPtr nodes); static int test_c14n(const char* xml_filename, int with_comments, int exclusive, @@ -184,11 +183,18 @@ xmlChar **parse_list(xmlChar *str) { xmlChar **buffer; xmlChar **out = NULL; int buffer_size = 0; + int len; if(str == NULL) { return(NULL); } + len = strlen(str); + if((str[0] == '\'') && (str[len - 1] == '\'')) { + str[len - 1] = '\0'; + str++; + len -= 2; + } /* * allocate an translation buffer. */ @@ -298,7 +304,7 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename) { return(NULL); } - /* print_xpath_nodes(xpath); */ + /* print_xpath_nodes(xpath->nodesetval); */ xmlFree(expr); xmlXPathFreeContext(ctx); @@ -307,21 +313,40 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename) { } void -print_xpath_nodes(xmlXPathObjectPtr ptr) { +print_xpath_nodes(xmlNodeSetPtr nodes) { xmlNodePtr cur; int i; - if(ptr == NULL || ptr->nodesetval == NULL ){ + if(nodes == NULL ){ fprintf(stderr, "Error: no nodes set defined\n"); return; } - for(i = 0; i < ptr->nodesetval->nodeNr; ++i) { - cur = ptr->nodesetval->nodeTab[i]; - fprintf(stderr, "node %s. type %d\n", cur->name, cur->type); + fprintf(stderr, "Nodes Set:\n-----\n"); + for(i = 0; i < nodes->nodeNr; ++i) { + if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) { + xmlNsPtr ns; + + ns = (xmlNsPtr)nodes->nodeTab[i]; + cur = (xmlNodePtr)ns->next; + fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n", + ns->prefix, ns->href, + (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name); + } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) { + cur = nodes->nodeTab[i]; + fprintf(stderr, "element node \"%s:%s\"\n", + (cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name); + } else { + cur = nodes->nodeTab[i]; + fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type); + } } } + + + + #else #include int main(int argc, char **argv) { diff --git a/win32/dsp/libxml2.def.src b/win32/dsp/libxml2.def.src index ae09318f..c9e0dbf1 100644 --- a/win32/dsp/libxml2.def.src +++ b/win32/dsp/libxml2.def.src @@ -1335,6 +1335,9 @@ EXPORTS xmlXPathCeilingFunction xmlXPathRoundFunction xmlXPathBooleanFunction + + /* really internal functions */ + xmlXPathNodeSetFreeNs #endif /* LIBXML_XPATH_ENABLED */ diff --git a/win32/libxml2.def.src b/win32/libxml2.def.src index e19e384e..d0263da6 100644 --- a/win32/libxml2.def.src +++ b/win32/libxml2.def.src @@ -1541,6 +1541,9 @@ xmlCleanupPredefinedEntities xmlXPathCeilingFunction xmlXPathRoundFunction xmlXPathBooleanFunction + + /* really internal functions */ + xmlXPathNodeSetFreeNs #endif /* LIBXML_XPATH_ENABLED */ diff --git a/xpath.c b/xpath.c index d56c70f0..c166c820 100644 --- a/xpath.c +++ b/xpath.c @@ -1489,7 +1489,7 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) { * the namespace nodes are duplicated and the next pointer is set to the * parent node in the XPath semantic. Check if such a node need to be freed */ -static void +void xmlXPathNodeSetFreeNs(xmlNsPtr ns) { if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) return; @@ -8736,6 +8736,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, ((cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE) || (cur->type == XML_ELEMENT_NODE) || + (cur->type == XML_NAMESPACE_DECL) || + (cur->type == XML_ATTRIBUTE_NODE) || (cur->type == XML_PI_NODE) || (cur->type == XML_COMMENT_NODE) || (cur->type == XML_CDATA_SECTION_NODE) ||