Thanks a lot! I'll take a look at your changes this weekend!

Aleksey

Tomas Sieger wrote:
Aleksey Sanin wrote:

Write me if you need more help following this complex hack (e.g. to send sources).


I am interested :) It would be really great if you can share your
changes. It seems that this solves the problem and does not require
the latest libxml2. In the ideal case I would love to have both:
your patch for old libxml2 and xmlParseInNodeContext() for newer
libxml2.


Ok, I'm sending a diff to xmltree.c. I've tried to follow the XMLSec coding rules, but I guess a review is a must ;-).
Note newly created functions in xmltree.c are static - please publish them if you think it is a good idea.


best regards,
 Tomas


------------------------------------------------------------------------

Index: xmltree.c
===================================================================
RCS file: /cvs/gnome/xmlsec/src/xmltree.c,v
retrieving revision 1.38
diff -c -r1.38 xmltree.c
*** xmltree.c 17 Jun 2004 18:17:06 -0000 1.38
--- xmltree.c 17 Sep 2004 09:40:16 -0000
***************
*** 16,21 ****
--- 16,22 ----
#include <libxml/tree.h>
#include <libxml/valid.h>
+ #include <libxml/xmlstring.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
***************
*** 474,479 ****
--- 475,674 ----
/**
+ * xmlSecGatherNamespaceDeclarations
+ * @node: node affected by namespace declarations
+ *
+ * Gathers namespace declarations from the "ancestor-or-self" axis of @node,
+ * i.e. those applying to @node. Only namespaces having a prefix are gathered
+ * (default namespaces are not gathered).
+ *
+ * Returns NULL if no namespace declarations found or an allocated string
+ * containing namespace declarations in format
+ * 'xmlns:PREFIX_1="URI_1" xmlns:PREFIX_2="URI_2"... '. Note there is
+ * a trailing space in the string. The string must be freed by the caller.
+ */
+ static xmlChar *
+ xmlSecGatherNamespaceDeclarations(xmlNodePtr node) {
+ static const char *nsDeclPart1 = "xmlns:";
+ static const char *nsDeclPart3 = "=\"";
+ static const char *nsDeclPart5 = "\" ";
+ int nsDeclSkeletLen;
+ xmlChar *namespaceDecls;
+ xmlNsPtr *ns;
+ + xmlSecAssert2(node != NULL, NULL);
+ + nsDeclSkeletLen = strlen(nsDeclPart1) +
+ strlen(nsDeclPart3) +
+ strlen(nsDeclPart5);
+ + /* get applying namespaces */
+ ns = xmlGetNsList(node->doc, node);
+ if(ns != NULL) {
+ /* convert the namespaces into text (namespace declarations) */
+ + xmlNsPtr *p;
+ xmlChar *s;
+ int size;
+ + /* determine namespace declarations length */
+ size = 0;
+ for(p = ns; *p != NULL; p++) {
+ if((*p)->prefix != NULL) {
+ size += nsDeclSkeletLen +
+ xmlStrlen((*p)->prefix) +
+ ((*p)->href ? xmlStrlen((*p)->href) : 0 );
+ }
+ }
+ size++; /* trailing zero */
+ + /* allocate buffer for namespace declarations */
+ namespaceDecls = (xmlChar *) xmlMalloc(size);
+ if(namespaceDecls == NULL) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ "xmlMalloc",
+ XMLSEC_ERRORS_R_MALLOC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(ns);
+ return(NULL);
+ }
+ + /* write namespace declarations */
+ s = namespaceDecls;
+ for(p = ns; *p != NULL; p++) {
+ if((*p)->prefix != NULL) {
+ int wroteLen;
+ wroteLen = xmlStrPrintf(s, size, BAD_CAST "%s%s%s%s%s",
+ nsDeclPart1,
+ (const char *)(*p)->prefix,
+ nsDeclPart3,
+ (*p)->href != NULL ? (const char *)(*p)->href : "",
+ nsDeclPart5);
+ xmlSecAssert2(wroteLen != -1, NULL);
+ s += wroteLen;
+ size -= wroteLen;
+ }
+ }
+ xmlFree(ns);
+ }
+ else namespaceDecls = NULL;
+ return(namespaceDecls);
+ }
+ + /**
+ * xmlSecIsNsInNsList
+ * @ns: namespace to be find in @nsList
+ * @nsList: namespace list
+ *
+ * Finds @ns in @nsList.
+ *
+ * Returns 1 if @ns found in @nsList, 0 if @ns not found in @nsList or
+ * a negative value if an error occurs.
+ */
+ static int
+ xmlSecIsNsInNsList(xmlNsPtr ns, xmlNsPtr *nsList) {
+ xmlNsPtr *ptr;
+ + xmlSecAssert2(ns != NULL, -1);
+ xmlSecAssert2(nsList != NULL, -1);
+ + for(ptr = nsList; *ptr != NULL; ptr++) {
+ if(ns == *ptr) return 1;
+ }
+ return 0;
+ }
+ + /**
+ * xmlSecGetNsFromNsList
+ * @prefix: namespace prefix
+ * @nsList: namespace list
+ *
+ * Returns namespace having prefix @prefix or NULL if no namespace having
+ * prefix @prefix found or an error occurs.
+ */
+ static xmlNsPtr
+ xmlSecGetNsFromNsList(const xmlChar *prefix, xmlNsPtr *nsList) {
+ xmlNsPtr *ptr;
+ + xmlSecAssert2(prefix != NULL, NULL);
+ xmlSecAssert2(nsList != NULL, NULL);
+ + for(ptr = nsList; *ptr != NULL; ptr++) {
+ if(xmlStrEqual(prefix, (*ptr)->prefix)) return(*ptr);
+ }
+ return(NULL);
+ }
+ + /**
+ * xmlSecReplaceNodeNamespaces
+ * @node: node where to replace the namespaces
+ * @curNsList: current namespace list
+ * @newNsList: new namespace list
+ *
+ * Replaces namespaces appearing at @node, its attributes and, recursively,
+ * at its descendants and their attributes, in this manner: every use of
+ * a namespace from @curNsList gets repointed to namespace declaration from
+ * @newNsList.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+ static int
+ xmlSecReplaceNodeNamespaces(xmlNodePtr node, xmlNsPtr *curNsList, xmlNsPtr *newNsList) {
+ xmlAttrPtr attr;
+ xmlNodePtr n;
+ int rc;
+ + xmlSecAssert2(node != NULL, -1);
+ xmlSecAssert2(curNsList != NULL, -1);
+ xmlSecAssert2(newNsList != NULL, -1);
+ + /* fix attributes */
+ for(attr = node->properties; attr != NULL; attr = attr->next) {
+ if(attr->ns != NULL) {
+ rc = xmlSecIsNsInNsList(attr->ns, curNsList);
+ if(rc < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(rc == 1) {
+ /* TODO: namespace lookup may be faster than this silly sequential lookup */
+ attr->ns = xmlSecGetNsFromNsList(attr->ns->prefix, newNsList);
+ }
+ }
+ }
+ + /* fix the node itself */
+ rc = xmlSecIsNsInNsList(node->ns, curNsList);
+ if(node->ns != NULL) {
+ if(rc < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return(-1);
+ }
+ if(rc == 1) {
+ /* TODO: namespace lookup may be faster than this silly sequential lookup */
+ node->ns = xmlSecGetNsFromNsList(node->ns->prefix, newNsList);
+ }
+ }
+ + /* fix descendants */
+ for(n = xmlSecGetNextElementNode(node->children);
+ n != NULL;
+ n = xmlSecGetNextElementNode(n->next)) {
+ xmlSecReplaceNodeNamespaces(n, curNsList, newNsList);
+ }
+ return(0);
+ }
+ + /**
* xmlSecReplaceNodeBuffer:
* @node: the current node.
* @buffer: the XML data.
***************
*** 486,499 ****
int
xmlSecReplaceNodeBuffer(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size) {
! static const char dummyPrefix[] = "<dummy>";
static const char dummyPostfix[] = "</dummy>";
xmlDocPtr doc;
xmlNodePtr ptr1, ptr2;
xmlSecAssert2(node != NULL, -1);
! ! doc = xmlSecParseMemoryExt((xmlSecByte*)dummyPrefix, strlen(dummyPrefix),
buffer, size,
(xmlSecByte*)dummyPostfix, strlen(dummyPostfix));
if(doc == NULL){
--- 681,729 ----
int
xmlSecReplaceNodeBuffer(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize size) {
! static const char dummyPrefixPart1[] = "<dummy ";
! const char *dummyPrefixPart2;
! static const char dummyPrefixPart3[] = ">";
! xmlChar *dummyPrefix;
! int dummyPrefixSize;
static const char dummyPostfix[] = "</dummy>";
+ xmlChar *namespaceDecls;
xmlDocPtr doc;
xmlNodePtr ptr1, ptr2;
+ xmlNsPtr *curNsList;
+ xmlNsPtr *newNsList;
xmlSecAssert2(node != NULL, -1);
! ! /* get namespace declarations applying to 'node' ... */
! namespaceDecls = xmlSecGatherNamespaceDeclarations(node);
! if(namespaceDecls != NULL) {
! dummyPrefixPart2 = (const char *)namespaceDecls;
! }
! else {
! dummyPrefixPart2 = "";
! }
! ! /* ... and put it in the parser context (the <dummy> opening tag) */
! dummyPrefixSize =
! strlen(dummyPrefixPart1) +
! strlen(dummyPrefixPart2) +
! strlen(dummyPrefixPart3) + 1;
! dummyPrefix = xmlMalloc(dummyPrefixSize);
! if(dummyPrefix == NULL) {
! xmlSecError(XMLSEC_ERRORS_HERE,
! NULL,
! "xmlMalloc",
! XMLSEC_ERRORS_R_MALLOC_FAILED,
! XMLSEC_ERRORS_NO_MESSAGE);
! xmlFree(namespaceDecls);
! return(-1);
! }
! xmlStrPrintf(dummyPrefix, dummyPrefixSize, BAD_CAST "%s%s%s",
! dummyPrefixPart1, dummyPrefixPart2, dummyPrefixPart3);
! xmlFree(namespaceDecls);
! ! doc = xmlSecParseMemoryExt((xmlSecByte*)dummyPrefix, dummyPrefixSize-1,
buffer, size,
(xmlSecByte*)dummyPostfix, strlen(dummyPostfix));
if(doc == NULL){
***************
*** 502,507 ****
--- 732,738 ----
"xmlSecParseMemoryExt",
XMLSEC_ERRORS_R_XMLSEC_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(dummyPrefix);
return(-1);
}
***************
*** 513,531 ****
XMLSEC_ERRORS_R_XML_FAILED,
"root is null");
xmlFreeDoc(doc);
return(-1);
}
! ptr1 = ptr1->children;
while(ptr1 != NULL) {
ptr2 = ptr1->next;
xmlUnlinkNode(ptr1);
xmlAddPrevSibling(node, ptr1);
ptr1 = ptr2;
}
xmlUnlinkNode(node);
xmlFreeNode(node); xmlFreeDoc(doc);
return(0);
}
--- 744,796 ----
XMLSEC_ERRORS_R_XML_FAILED,
"root is null");
xmlFreeDoc(doc);
+ xmlFree(dummyPrefix);
return(-1);
}
! ! /* get namespace list applying to the parsed node
! * (the namespaces are declared at the <dummy> element)
! */
! curNsList = xmlGetNsList(ptr1->doc, ptr1);
! /* get namespace list applying to node->parent (if any) */
! if(node->parent != NULL) {
! newNsList = xmlGetNsList(node->parent->doc, node->parent);
! }
! else newNsList = NULL;
! ptr1 = ptr1->children;
while(ptr1 != NULL) {
ptr2 = ptr1->next;
xmlUnlinkNode(ptr1);
xmlAddPrevSibling(node, ptr1);
+ if((curNsList != NULL) && (newNsList != NULL)) {
+ /* repoint namespaces in the parsed document from those
+ * declared at the <dummy> alement to those appearing in
+ * the original tree
+ */
+ if(xmlSecReplaceNodeNamespaces(ptr1, curNsList, newNsList) < 0) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ NULL,
+ NULL,
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ xmlFree(curNsList);
+ xmlFree(newNsList);
+ xmlUnlinkNode(node);
+ xmlFreeNode(node);
+ xmlFree(dummyPrefix);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ }
ptr1 = ptr2;
}
+ xmlFree(curNsList);
+ xmlFree(newNsList);
xmlUnlinkNode(node);
xmlFreeNode(node); + xmlFree(dummyPrefix);
xmlFreeDoc(doc);
return(0);
}



------------------------------------------------------------------------

_______________________________________________
xmlsec mailing list
[EMAIL PROTECTED]
http://www.aleksey.com/mailman/listinfo/xmlsec
_______________________________________________
xmlsec mailing list
[EMAIL PROTECTED]
http://www.aleksey.com/mailman/listinfo/xmlsec

Reply via email to