Sorry for delay with reviewing the patch! As I wrote before
it completely disappeared from my radar for some reasons.

I've applied and commited your patch but I've had to make
some significant changes:

1) I removed "enum xmlEncCtxNodeReplacementMode" and used
the "flags" variable in the encryption context instead. This
provides better backward compatibility because the structure
size does not change.

2) For the same reason, I replaced "reserved0" pointer with
"replacedNodeList".

3) Again, for backward compatibility, I've kept the old versions
of xmlSecXxxReplace() functions and added new
xmlSecXxxReplaceAndReturn() functions that provide the new
functionality.

4) There was a bug in xmlSecReplaceContent() implementation:
when you copied nodes one by one you forgot to move "cur"
variable (i.e. the tail) after you've added the new node.
As the result, if the original nodes list looks like
1,2,3,4 then the returned result is 1,4,3,2.

5) I've also made some minor cosmetic changes (spaces, brackets,
etc.) to match the xmlsec code style.

Just in case, I am attaching the resulting patch. Please let me know
if you find any problems with my changes!

Thank you again for the patch!

Aleksey
Index: src/xmltree.c
===================================================================
--- src/xmltree.c       (revision 988)
+++ src/xmltree.c       (working copy)
@@ -419,6 +419,21 @@
  */
 int
 xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) {
+    return xmlSecReplaceNodeAndReturn(node, newNode, NULL);
+}
+
+/**                 
+ * xmlSecReplaceNodeAndReturn:
+ * @node:              the current node.
+ * @newNode:           the new node.
+ * @replaced:          the replaced node, or release it if NULL is given
+ * 
+ * Swaps the @node and @newNode in the XML tree.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNodeAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr* 
replaced) {
     xmlNodePtr oldNode;
     int restoreRoot = 0;
     
@@ -448,7 +463,13 @@
        xmlDocSetRootElement(oldNode->doc, newNode);
     }
 
-    xmlFreeNode(oldNode);
+    /* return the old node if requested */
+    if(replaced != NULL) {
+       (*replaced) = oldNode;                  
+    } else {
+       xmlFreeNode(oldNode); 
+    }
+   
     return(0);
 }
 
@@ -463,19 +484,55 @@
  */
 int
 xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) {
+     return xmlSecReplaceContentAndReturn(node, newNode, NULL);
+}
+
+/**
+ * xmlSecReplaceContentAndReturn
+ * @node:              the current node.
+ * @newNode:           the new node.
+ * @replaced:          the replaced nodes, or release them if NULL is given
+ * 
+ * Swaps the content of @node and @newNode.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceContentAndReturn(xmlNodePtr node, xmlNodePtr newNode, xmlNodePtr 
*replaced) {
     xmlSecAssert2(node != NULL, -1);
     xmlSecAssert2(newNode != NULL, -1);  
 
     xmlUnlinkNode(newNode);
     xmlSetTreeDoc(newNode, node->doc);
-    xmlNodeSetContent(node, NULL);
+
+    /* return the old nodes if requested */
+    if(replaced != NULL) {
+        xmlNodePtr cur, next, tail;
+
+        (*replaced) = tail = NULL;
+        for(cur = node->children; (cur != NULL); cur = next) {
+            next = cur->next;
+            if((*replaced) != NULL) {
+               /* n is unlinked in this function */            
+                xmlAddNextSibling(tail, cur); 
+               tail = cur;
+            } else {
+               /* this is the first node, (*replaced) is the head */
+                xmlUnlinkNode(cur);
+               (*replaced) = tail = cur;           
+          }
+        }
+    } else {
+       /* just delete the content */
+        xmlNodeSetContent(node, NULL);
+    }
+
     xmlAddChild(node, newNode);
     xmlSetTreeDoc(newNode, node->doc);
 
     return(0);
 }
 
-
 /**
  * xmlSecReplaceNodeBuffer:
  * @node:              the current node.
@@ -487,8 +544,23 @@
  * Returns 0 on success or a negative value if an error occurs.
  */
 int
-xmlSecReplaceNodeBuffer(xmlNodePtr node, 
-                       const xmlSecByte *buffer, xmlSecSize size) {
+xmlSecReplaceNodeBuffer(xmlNodePtr node, const xmlSecByte *buffer, xmlSecSize 
size) {
+    return xmlSecReplaceNodeBufferAndReturn(node, buffer, size, NULL);
+}
+
+/**
+ * xmlSecReplaceNodeBufferAndReturn:
+ * @node:              the current node.
+ * @buffer:            the XML data.
+ * @size:              the XML data size.
+ * @replaced:          the replaced nodes, or release them if NULL is given
+ * 
+ * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecReplaceNodeBufferAndReturn(xmlNodePtr node, const xmlSecByte *buffer, 
xmlSecSize size, xmlNodePtr *replaced) {
     xmlNodePtr results = NULL;
     xmlNodePtr next = NULL;
 
@@ -514,8 +586,14 @@
 
     /* remove old node */
     xmlUnlinkNode(node);
-    xmlFreeNode(node);  
 
+    /* return the old node if requested */
+    if(replaced != NULL) {
+       (*replaced) = node;             
+    } else {
+       xmlFreeNode(node); 
+    }
+
     return(0);
 }
 
Index: src/xmlenc.c
===================================================================
--- src/xmlenc.c        (revision 988)
+++ src/xmlenc.c        (working copy)
@@ -192,34 +192,45 @@
     encCtx->resultBase64Encoded = 0;
     encCtx->resultReplaced     = 0;
     encCtx->encMethod          = NULL;
+    
+    if (encCtx->replacedNodeList != NULL) { 
+               xmlFreeNodeList(encCtx->replacedNodeList);
+       encCtx->replacedNodeList = NULL;
+    }
+    
     if(encCtx->encKey != NULL) {
-       xmlSecKeyDestroy(encCtx->encKey);
-       encCtx->encKey = NULL;
+           xmlSecKeyDestroy(encCtx->encKey);
+           encCtx->encKey = NULL;
     }
     
     if(encCtx->id != NULL) {
-       xmlFree(encCtx->id);
-       encCtx->id = NULL;
+           xmlFree(encCtx->id);
+           encCtx->id = NULL;
     }  
+
     if(encCtx->type != NULL) {
-       xmlFree(encCtx->type);
-       encCtx->type = NULL;
+           xmlFree(encCtx->type);
+           encCtx->type = NULL;
     }
+
     if(encCtx->mimeType != NULL) {
-       xmlFree(encCtx->mimeType);
-       encCtx->mimeType = NULL;
+           xmlFree(encCtx->mimeType);
+           encCtx->mimeType = NULL;
     }
+
     if(encCtx->encoding != NULL) {
-       xmlFree(encCtx->encoding);
-       encCtx->encoding = NULL;
+           xmlFree(encCtx->encoding);
+           encCtx->encoding = NULL;
     }  
+
     if(encCtx->recipient != NULL) {
-       xmlFree(encCtx->recipient);
-       encCtx->recipient = NULL;
+           xmlFree(encCtx->recipient);
+           encCtx->recipient = NULL;
     }
+
     if(encCtx->carriedKeyName != NULL) {
-       xmlFree(encCtx->carriedKeyName);
-       encCtx->carriedKeyName = NULL;
+           xmlFree(encCtx->carriedKeyName);
+           encCtx->carriedKeyName = NULL;
     }
     
     encCtx->encDataNode = encCtx->encMethodNode = 
@@ -445,43 +456,73 @@
                    "xmlSecEncCtxEncDataNodeWrite",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
-       return(-1);
+       return(-1);
     }
     
     /* now we need to update our original document */
     if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, 
xmlSecTypeEncElement)) {
-       ret = xmlSecReplaceNode(node, tmpl);
-       if(ret < 0) {
-           xmlSecError(XMLSEC_ERRORS_HERE,
-                       NULL,
-                       "xmlSecReplaceNode",
-                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                       "node=%s",
-                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
-           return(-1);
-       }
-       encCtx->resultReplaced = 1;                            
+        /* check if we need to return the replaced node */
+        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+            ret = xmlSecReplaceNodeAndReturn(node, tmpl, 
&(encCtx->replacedNodeList));
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                NULL,
+                "xmlSecReplaceNode",
+                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                "node=%s",
+                xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                return(-1);
+            }
+        } else {
+            ret = xmlSecReplaceNode(node, tmpl);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                           NULL,
+                           "xmlSecReplaceNode",
+                           XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                           "node=%s",
+                           xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                return(-1);
+            }
+        }
+
+           encCtx->resultReplaced = 1;                        
     } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, 
xmlSecTypeEncContent)) {
-       ret = xmlSecReplaceContent(node, tmpl);
-       if(ret < 0) {
+        /* check if we need to return the replaced node */
+        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {        
+            ret = xmlSecReplaceContentAndReturn(node, tmpl, 
&(encCtx->replacedNodeList));
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                       NULL,
+                       "xmlSecReplaceContentAndReturn",
+                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                       "node=%s",
+                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                return(-1);
+            }
+        } else {
+            ret = xmlSecReplaceContent(node, tmpl);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                       NULL,
+                       "xmlSecReplaceContent",
+                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                       "node=%s",
+                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                return(-1);
+            }
+        }
+
+        encCtx->resultReplaced = 1;                           
+    } else {
+           /* we should've catached this error before */
            xmlSecError(XMLSEC_ERRORS_HERE,
-                       NULL,
-                       "xmlSecReplaceContent",
-                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                       "node=%s",
-                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
-           return(-1);
-       }
-       encCtx->resultReplaced = 1;                            
-    } else {
-       /* we should've catached this error before */
-       xmlSecError(XMLSEC_ERRORS_HERE,
-                   NULL,
-                   NULL,
-                   XMLSEC_ERRORS_R_INVALID_TYPE,
-                   "type=%s", 
-                   xmlSecErrorsSafeString(encCtx->type));
-       return(-1);             
+                       NULL,
+                       NULL,
+                       XMLSEC_ERRORS_R_INVALID_TYPE,
+                       "type=%s", 
+                       xmlSecErrorsSafeString(encCtx->type));
+           return(-1);         
     }
     return(0);    
 }
@@ -589,31 +630,62 @@
     
     /* replace original node if requested */
     if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, 
xmlSecTypeEncElement)) {
-       ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer),  
xmlSecBufferGetSize(buffer));
-       if(ret < 0) {
-           xmlSecError(XMLSEC_ERRORS_HERE,
-                       NULL,
-                       "xmlSecReplaceNodeBuffer",
-                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                       "node=%s",
-                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
-           return(-1);         
-       }
-       encCtx->resultReplaced = 1;                            
+        /* check if we need to return the replaced node */
+        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+               ret = xmlSecReplaceNodeBufferAndReturn(node, 
xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer), 
&(encCtx->replacedNodeList));
+               if(ret < 0) {
+                   xmlSecError(XMLSEC_ERRORS_HERE,
+                               NULL,
+                               "xmlSecReplaceNodeBufferAndReturn",
+                               XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                               "node=%s",
+                               
xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                   return(-1);         
+               }
+        } else {
+               ret = xmlSecReplaceNodeBuffer(node, 
xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer));
+               if(ret < 0) {
+                   xmlSecError(XMLSEC_ERRORS_HERE,
+                               NULL,
+                               "xmlSecReplaceNodeBuffer",
+                               XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                               "node=%s",
+                               
xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                   return(-1);         
+               }
+        }
+
+        encCtx->resultReplaced = 1;                           
     } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, 
xmlSecTypeEncContent)) {
-       /* replace the node with the buffer */
-       ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), 
xmlSecBufferGetSize(buffer));
-       if(ret < 0) {
-           xmlSecError(XMLSEC_ERRORS_HERE,
-                       NULL,
-                       "xmlSecReplaceNodeBuffer",
-                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
-                       "node=%s",
-                       xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
-           return(-1);         
-       }       
-       encCtx->resultReplaced = 1;                            
+        /* replace the node with the buffer */
+
+        /* check if we need to return the replaced node */
+        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
+               ret = xmlSecReplaceNodeBufferAndReturn(node, 
xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), 
&(encCtx->replacedNodeList));
+               if(ret < 0) {
+                   xmlSecError(XMLSEC_ERRORS_HERE,
+                               NULL,
+                               "xmlSecReplaceNodeBufferAndReturn",
+                               XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                               "node=%s",
+                               
xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                   return(-1);         
+               }       
+        } else {
+            ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), 
xmlSecBufferGetSize(buffer));
+               if(ret < 0) {
+                   xmlSecError(XMLSEC_ERRORS_HERE,
+                               NULL,
+                               "xmlSecReplaceNodeBuffer",
+                               XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                               "node=%s",
+                               
xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
+                   return(-1);         
+               }         
+        }
+       encCtx->resultReplaced = 1;                            
     }
+
     return(0);
 }
 
Index: include/xmlsec/xmltree.h
===================================================================
--- include/xmlsec/xmltree.h    (revision 988)
+++ include/xmlsec/xmltree.h    (working copy)
@@ -56,11 +56,24 @@
 
 XMLSEC_EXPORT int              xmlSecReplaceNode       (xmlNodePtr node,
                                                         xmlNodePtr newNode);
+XMLSEC_EXPORT int              xmlSecReplaceNodeAndReturn
+                                                       (xmlNodePtr node,
+                                                        xmlNodePtr newNode,
+                                                        xmlNodePtr* replaced);
 XMLSEC_EXPORT int              xmlSecReplaceContent    (xmlNodePtr node,
                                                         xmlNodePtr newNode);
+XMLSEC_EXPORT int              xmlSecReplaceContentAndReturn
+                                                       (xmlNodePtr node,
+                                                        xmlNodePtr newNode,
+                                                        xmlNodePtr* replaced);
 XMLSEC_EXPORT int              xmlSecReplaceNodeBuffer (xmlNodePtr node,
                                                         const xmlSecByte 
*buffer, 
                                                         xmlSecSize size);
+XMLSEC_EXPORT int              xmlSecReplaceNodeBufferAndReturn
+                                                       (xmlNodePtr node,
+                                                        const xmlSecByte 
*buffer, 
+                                                        xmlSecSize size,
+                                                        xmlNodePtr* replaced);
 
 XMLSEC_EXPORT void             xmlSecAddIDs            (xmlDocPtr doc,
                                                         xmlNodePtr cur,
Index: include/xmlsec/xmlenc.h
===================================================================
--- include/xmlsec/xmlenc.h     (revision 988)
+++ include/xmlsec/xmlenc.h     (working copy)
@@ -41,6 +41,14 @@
     xmlEncCtxModeEncryptedKey
 } xmlEncCtxMode;
 
+
+/**
+ * XMLSEC_ENC_RETURN_REPLACED_NODE:
+ *
+ * If this flag is set, then the replaced node will be returned in the 
replacedNodeList
+ */
+#define XMLSEC_ENC_RETURN_REPLACED_NODE                        0x00000001
+
 /** 
  * xmlSecEncCtx:
  * @userData:                  the pointer to user data (xmlsec and 
xmlsec-crypto libraries
@@ -61,6 +69,7 @@
  * @resultReplaced:            the flag: if set then resulted 
<enc:EncryptedData/>
  *                             or <enc:EncryptedKey/> node is added to the 
document.
  * @encMethod:                 the pointer to encryption transform.
+ * @replacedNodeList: the first node of the list of replaced nodes depending 
on the nodeReplacementMode
  * @id:                                the ID attribute of <enc:EncryptedData/>
  *                             or <enc:EncryptedKey/> node.
  * @type:                      the Type attribute of <enc:EncryptedData/>
@@ -76,7 +85,6 @@
  * @encMethodNode:             the pointer to <enc:EncryptionMethod/> node.
  * @keyInfoNode:               the pointer to <enc:KeyInfo/> node.
  * @cipherValueNode:           the pointer to <enc:CipherValue/> node.
- * @reserved0:                 reserved for the future.
  * @reserved1:                 reserved for the future.
  * 
  * XML Encrypiton context.
@@ -99,7 +107,7 @@
     int                                resultBase64Encoded;
     int                                resultReplaced;
     xmlSecTransformPtr         encMethod;
-
+               
     /* attributes from EncryptedData or EncryptedKey */    
     xmlChar*                   id;
     xmlChar*                   type;
@@ -113,10 +121,9 @@
     xmlNodePtr                 encMethodNode;
     xmlNodePtr                 keyInfoNode;
     xmlNodePtr                 cipherValueNode;
-    
-    /* reserved for future */
-    void*                      reserved0;
-    void*                      reserved1;
+        
+    xmlNodePtr                 replacedNodeList; /* the pointer to the 
replaced node */
+    void*                      reserved1;        /* reserved for future */
 };
 
 XMLSEC_EXPORT xmlSecEncCtxPtr  xmlSecEncCtxCreate              
(xmlSecKeysMngrPtr keysMngr);
_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec

Reply via email to