Index: ldap.tcl
===================================================================
RCS file: /local/cvs/ldaposiris/tcl/ldap.tcl,v
retrieving revision 1.9
diff -u -r1.9 ldap.tcl
--- ldap.tcl	17 Aug 2006 15:44:40 -0000	1.9
+++ ldap.tcl	18 Aug 2006 14:05:56 -0000
@@ -55,6 +55,7 @@
 		      searchNext	     \
 		      searchEnd		     \
                       modify                 \
+                      modifyMulti            \
                       add                    \
 		      addMulti		     \
                       delete                 \
@@ -728,12 +729,49 @@
 
     upvar $handle conn
 
+    set lrep {}
+    foreach {attr value} $attrValToReplace {
+	lappend lrep $attr [list $value]
+    }
+
+    set ldel {}
+    foreach {attr value} $attrToDelete {
+	if {[string equal $value ""]} then {
+	    lappend ldel $attr {}
+	} else {
+	    lappend ldel $attr [list $value]
+	}
+    }
+
+    set ladd {}
+    foreach {attr value} $attrValToAdd {
+	lappend ladd $attr [list $value]
+    }
+
+    modifyMulti $handle $dn $lrep $ldel $ladd
+}
+
+
+#-----------------------------------------------------------------------------
+#    modify  -  provides attribute modifications on one single object (DN):
+#                 o replace attributes with new values
+#                 o delete attributes (having certain values)
+#                 o add attributes with new values
+#
+#-----------------------------------------------------------------------------
+proc ldap::modifyMulti {handle dn
+                    attrValToReplace {attrValToDelete {}} {attrValToAdd {}}} {
+
+    upvar $handle conn
+
     checkNotSearch $handle
 
     set operationAdd     0
     set operationDelete  1
     set operationReplace 2
 
+    set modifications ""
+
     #------------------------------------------------------------------
     #   marshal attribute modify operations
     #    - always mode 'replace' ! see rfc2251:
@@ -745,34 +783,15 @@
     #        attribute does not exist.
     #
     #------------------------------------------------------------------
-    set modifications {}
-    foreach { attrName attrValue } $attrValToReplace {
-        append modifications [asnSequence                            \
-                                 [asnEnumeration $operationReplace ] \
-                                 [asnSequence                        \
-                                    [asnOctetString $attrName  ]     \
-                                    [asnSet                          \
-                                        [asnOctetString $attrValue ] \
-                                    ]                                \
-                                 ]                                   \
-                             ]
-    }
+    append modifications [ldap::packOpAttrVal $operationReplace \
+				$attrValToReplace]
 
     #------------------------------------------------------------------
     #   marshal attribute add operations
     #
     #------------------------------------------------------------------
-    foreach { attrName attrValue } $attrValToAdd {
-        append modifications [asnSequence                            \
-                                 [asnEnumeration $operationAdd ]     \
-                                 [asnSequence                        \
-                                    [asnOctetString $attrName  ]     \
-                                    [asnSet                          \
-                                        [asnOctetString $attrValue ] \
-                                    ]                                \
-                                 ]                                   \
-                             ]
-    }
+    append modifications [ldap::packOpAttrVal $operationAdd \
+				$attrValToAdd]
 
     #------------------------------------------------------------------
     #   marshal attribute delete operations
@@ -784,20 +803,8 @@
     #       in all cases
     #
     #------------------------------------------------------------------
-    foreach { attrName attrValue } $attrToDelete {
-        if {$attrValue == ""} {
-            set val [asnSet ""]
-        } else {
-            set val [asnSet [asnOctetString $attrValue]]
-        }
-        append modifications [asnSequence                            \
-                                 [asnEnumeration $operationDelete ]  \
-                                 [asnSequence                        \
-                                    [asnOctetString $attrName  ]     \
-                                    $val                             \
-                                 ]                                   \
-                             ]
-    }
+    append modifications [ldap::packOpAttrVal $operationDelete \
+				$attrValToDelete]
 
     #----------------------------------------------------------
     #   marshal 'modify' request packet and send it
@@ -838,6 +845,24 @@
     }
 }
 
+proc ldap::packOpAttrVal {op attrValueTuples} {
+    set p ""
+    foreach {attrName attrValues} $attrValueTuples {
+	set l {}
+	foreach v $attrValues {
+	    lappend l [asnOctetString $v]
+	}
+        append p [asnSequence                        \
+		    [asnEnumeration $op ]            \
+		    [asnSequence                     \
+			[asnOctetString $attrName  ] \
+			[asnSetFromList $l]          \
+		    ]                                \
+		]
+    }
+    return $p
+}
+
 
 #-----------------------------------------------------------------------------
 #    add  -  will create a new object using given DN and sets the given
Index: ldap.man
===================================================================
RCS file: /local/cvs/ldaposiris/tcl/ldap.man,v
retrieving revision 1.7
diff -u -r1.7 ldap.man
--- ldap.man	17 Aug 2006 09:35:10 -0000	1.7
+++ ldap.man	18 Aug 2006 14:05:56 -0000
@@ -218,6 +218,49 @@
 is the empty string.
 
 
+[call [cmd ::ldap::modifyMulti] [arg handle] [arg dn] \
+	[arg attrValToReplace] \
+	[opt [arg attrValToDelete]] \
+	[opt [arg attrValToAdd]]]
+
+This command modifies the object [arg dn] on the ldap server we are
+connected to via [arg handle]. It replaces attributes with new values,
+deletes attributes, and adds new attributes with new values.
+
+All arguments are lists with the format:
+[nl]
+[example {
+    attr1 {val11 val12 ...}} {attr2 {val21...} ...} ...
+}]
+[nl]
+where each value list may be empty for deleting all attributes.
+The optional arguments default to empty lists of attributes to
+delete and to add.
+
+[list_begin arg]
+[arg_def list attrValToReplace in]
+
+No attributes will be changed if this argument is empty. The
+dictionary contains the new attributes and their values. They
+[emph {replace all}] attributes known to the object.
+
+[arg_def list attrValToDelete in]
+
+No attributes will be deleted if this argument is empty. If no
+value is specified, the whole set of values for an attribute
+will be deleted.
+
+[arg_def list attrValToAdd in]
+
+No attributes will be added if this argument is empty.
+
+[list_end]
+[nl]
+
+The command blocks until all modifications have completed. Its result
+is the empty string.
+
+
 [call [cmd ::ldap::add] [arg handle] [arg dn] [arg attrValueTuples]]
 
 This command creates a new object using the specified [arg dn]. The
