[turba] Turba Patch - allowing LDAP addresses to be added to SQL addressbooks

jonathan soong jon.soong at imvs.sa.gov.au
Fri Aug 15 00:43:46 PDT 2003


Chuck told me that it would be better to patch against CVS HEAD, 
unfortunately my boss asked me to write it
against 1.2 STABLE. So this patch is for 1.2 STABLE.

I did write my initial version of it on CVS HEAD, so if anyone wants it 
written for CVS HEAD, it probably won't
take me long to write it. However, i am not even sure that the logic i 
have used here is acceptable. If it is acceptable
let me know, and i will write it for CVS HEAD.

Basically:
    I have changed the turba_member field in turba_objects.
    Rather than just having a serialized array of object_id's, i.e.:
         
a:3:{i:0;s:32:"876d1826fdb03265df3243272a5f4420";i:1;s:32:"16469607fe47e22d129464135ee79160";}
       This is really just: array(XXX,YYY)  

     I now have serialized array of arrays, with each inner array 
containing the source where the entry is from, i.e:
        
a:2:{i:0;a:2:{i:0;s:8:"imvsldap";i:1;s:47:"uid=iisjsoo,ou=Users,dc=imvs,dc=sa,dc=gov,dc=au";}
                           
i:1;a:2:{i:0;s:8:"localsql";i:1;s:32:"4cf194f308531d497fc909be896e6f05";}}
       This is: array( array(localsql, XXX), array(localldap,YYY)

       I had to change
             browse.php
             lib/AbstractObject.php
             lib/api.php
             lib/Group.php
             templates/browse/actions.inc
             templates/browse/contactrow.inc
         
Below are some notes, and things that NEED to be changed to make it work.
--------------------------------------------------------------------------------------------------------------
NOTE:
In config/sources.php, you will need to add the following line to the 
bottom of the file, where 'localsql' is the name  of your
sql source.. (i.e. $cfgSources['localsql'] )

  define('PERSONAL_ADDRESS_BOOK_SOURCE', 'localsql');

Also, make sure that  $cfgSources['localsql'] array has something that 
looks like:
 
         'map' => array(
            '__key' => 'object_id',
            '__owner' => 'owner_id',
            '__type' => 'object_type',
            '__members' => 'object_members',

Also,
    In lib/api.php, i don't check for 'turba_lists' as was in 1.2 
STABLE, i couldn't work out why this was needed, so i just   
    assume it is a turba_list.
---------------------------------------------------------------------------------------------------------------------
  end.
-------------- next part --------------
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/browse.php ./browse.php
--- /home/iisjsoo/turba-1.2/browse.php	Wed Mar  5 02:33:34 2003
+++ ./browse.php	Fri Aug 15 16:11:54 2003
@@ -69,13 +69,20 @@
         /* Remove a contact from a list. */
         $keys = Horde::getFormData('objectkeys');
         if (is_array($keys)) {
-
             $key = Horde::getFormData('key', false);
             if ($key && $key != "**search") {
                 /* We are removing a contact from a list. */
                 $list = $driver->getObject($key);
                 foreach ($keys as $objectKey) {
-                    if (!$list->removeMember($driver->getObject($objectKey))) {
+/* iisjsoo
+ *
+ *  This was changed so that it takes into account the source of the
+ *  entry
+ *
+ */
+        	    list($objectKeySource, $objectKey)  = splitSourceAndKey($objectKey);
+                    $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+                    if (!$list->removeMemberSource($driver->getObject($objectKey))) {
                         Horde::raiseMessage(_("There was an error removing this object."), HORDE_ERROR);
                     } else {
                         Horde::raiseMessage(_("Contact removed from list."), HORDE_SUCCESS);
@@ -84,6 +91,13 @@
             } else {
                 /* We are deleting an object. */
                 foreach ($keys as $objectKey) {
+/* iisjsoo
+ *
+ *  This was changed so that it takes into account the source of the
+ *  entry
+ *
+ */
+        	    list($objectKeySource, $objectKey)  = splitSourceAndKey($objectKey);
                     if (!$driver->removeObject($objectKey)) {
                         Horde::raiseMessage(_("There was an error deleting this object."), HORDE_ERROR);
                     }
@@ -110,15 +124,32 @@
             break;
         }
 
+/* iisjsoo
+ *
+ * I need to first get a driver for the PERSONAL_ADDRESS_BOOK_SOURCE and then get 
+ * the object
+ *
+ */
+        list($targetKeySource, $newTargetKey)  = splitSourceAndKey($targetKey);
         if (!Horde::getFormData('targetNew')) {
-            $target = $driver->getObject($targetKey);
+          $driver = &Turba_Source::singleton(PERSONAL_ADDRESS_BOOK_SOURCE, $cfgSources[PERSONAL_ADDRESS_BOOK_SOURCE]);
+          $target = $driver->getObject($newTargetKey);
         }
 
+	
         if (!empty($target) && is_object($target) && $target->isGroup()) {
             /* Adding contact to an existing list */
             if (is_array($keys)) {
                 foreach ($keys as $objectKey) {
-                    $target->addMember($driver->getObject($objectKey));
+/* iisjsoo
+ *
+ *  This was changed so that it takes into account the source of the
+ *  entry
+ *
+ */
+		    list($objectKeySource, $objectKey)  = splitSourceAndKey($objectKey);
+                    $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+                    $target->addMemberSource($driver->getObject($objectKey),$objectKeySource);
                 }
                 $target->store();
             }
@@ -135,7 +166,15 @@
             if (!empty($target) && is_object($target) && $target->isGroup()) {
                 if (is_array($keys)) {
                     foreach ($keys as $objectKey) {
-                        $target->addMember($driver->getObject($objectKey));
+/* iisjsoo
+ *
+ *  This was changed so that it takes into account the source of the
+ *  entry
+ *
+ */
+		      list($objectKeySource, $objectKey)  = splitSourceAndKey($objectKey);
+                      $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+                      $target->addMemberSource($driver->getObject($objectKey),$objectKeySource);
                     }
                     $target->store();
                 }
@@ -165,13 +204,20 @@
                    !isset($columns[$prefs->getValue('sortby') - 1])) ?
         'lastname' : $columns[$prefs->getValue('sortby') - 1];
 
-    /* Create list of lists for Add to. */
+/* Create list of lists for Add to. */
+/* iisjsoo: 
+ *         this next block is new - it is used so that addresses can be added
+ *         to any address books. (e.g. ldap addresses can be added to sql books)
+*/
     $addToList = array();
-    if (!empty($cfgSources[$source]['map']['__type'])) {
-        $listList = $driver->search(array('__type' => 'Group'), null, null, 0);
+   foreach ($sources as $src=>$val) {
+     if (!empty($cfgSources[$src]['map']['__type'])) {
+       $tmp_driver = &Turba_Source::singleton($source, $cfgSources[$src]);
+       $listList = $tmp_driver->search(array('__type' => 'Group'), null, null, 0);
         $listList->reset();
         while ($listObject = $listList->next()) {
-            $addToList[] = array('name' => $listObject->getValue('name'), 'key' => $listObject->getValue('__key'));
+         $addToList[] = array('name' => $listObject->getValue('name'), 'key' => $src."|".$listObject->getValue('__key'));
+        }
         }
     }
 
@@ -198,29 +244,44 @@
 
     } else if (Horde::getFormData('key')) {
         /* We are displaying the contents of a list */
+            $templates[] = '/browse/header.inc';
+
+        /*  iisjsoo:
+         *      First we will grab an array using the listMembersArray() function to
+         *      give us all users in this list as well as the source they come from.
+         *
+         *      Then we will go thru the list and extract the users from their sources
+         *      into a Turba_List which will be passed on.
+         *
+         *      Note: there could be a performance enhancement here - make only one driver
+         *            for each source
+         */
+            require_once TURBA_BASE . '/lib/List.php';
+            $results = &new Turba_List();
+            $listType = 'list';
+	     
+            $driver = &Turba_Source::singleton(PERSONAL_ADDRESS_BOOK_SOURCE, $cfgSources[PERSONAL_ADDRESS_BOOK_SOURCE]);
         $list = $driver->getObject(Horde::getFormData('key'));
-        if (isset($list) && is_object($list) && $list->isGroup()) {
-            $title = sprintf(_("Addresses in list: %s"), $list->getValue('name'));
-            include TURBA_TEMPLATES . '/browse/header.inc';
-            /* Show List Members */
-            if (!is_object($results = $list->listMembers($sortcolumn, $prefs->getValue('sortdir')))) {
-                Horde::raiseMessage(_("Failed to browse list"), HORDE_ERROR);
-                include TURBA_BASE . '/status.php';
-            } else {
-                $listType = "list";
+            $results_array = $list->listMembersArray();
+            if (count($results_array) != 0) {
+                foreach ($results_array as $tmp=>$listMember) {
+        /*  iisjsoo:
+         *     The $results_array contains entries of the form: 
+         *                 'localsql'|'38183e5d7ace6910e33eb925f29181c6'
+         *                'localldap'|'uid=asddf,dn=adsf,dn=com'
+         */
+      
+                  $driver = &Turba_Source::singleton($listMember[0], $cfgSources[$listMember[0]]);
+                  $tmp2= $driver->getObject($listMember[1]);
+                  $results->insert($tmp2);
+                }
+            }
                 include TURBA_TEMPLATES . '/browse/actions.inc';
                 include TURBA_TEMPLATES . '/browse/column_headers.inc';
-
                 require_once TURBA_BASE . '/lib/ListView.php';
                 $display = &new Turba_ListView($results, TURBA_TEMPLATES . '/browse/contactrow.inc');
                 $numDisplayed = $display->display();
-
                 include TURBA_TEMPLATES . '/browse/column_footers.inc';
-            }
-        } else {
-            Horde::raiseMessage(_("There was an error displaying the select List"), HORDE_ERROR);
-            include TURBA_BASE . '/status.php';
-        }
     } else {
         /* We are displaying the contents of the address book */
         $title = sprintf(_("Contents of %s"), $cfgSources[$source]['title']);
@@ -256,3 +317,32 @@
 require TURBA_TEMPLATES . '/browse/footer.inc';
 $registry->shutdown();
 require TURBA_TEMPLATES . '/common-footer.inc';
+
+
+/* iisjsoo
+ * 
+ *      Function written to take an $objectKey of form: 
+ *
+ *                'localsql'|'38183e5d7ace6910e33eb925f29181c6'
+ *                'localldap'|'uid=asddf,dn=adsf,dn=com'
+ *
+ *      and it returns an array of the two parts:
+ *
+ *            Array([0]=>'localsql', [1]=>'38183e5d7ace6910e33eb925f29181c6')
+ *            Array([0]=>'localldap', [1]=>'uid=asddf,dn=adsf,dn=com')
+ * 
+ *      You should probably call it like:
+ *          list($objectKeySource, $objectKey)  = splitSourceAndKey($objectKey);
+ */       
+
+function splitSourceAndKey($objectKey) {
+ if (preg_match("/\|/", $objectKey)) {
+   $objectKeyArr = preg_split('/\|/', $objectKey);
+   $objectKeySource = $objectKeyArr[0];
+   $objectKeyKey = $objectKeyArr[1];
+   return array($objectKeySource, $objectKeyKey);
+ } else {
+   return -1;
+ }
+}
+
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/AbstractObject.php ./lib/AbstractObject.php
--- /home/iisjsoo/turba-1.2/lib/AbstractObject.php	Sat Nov  2 03:42:00 2002
+++ ./lib/AbstractObject.php	Thu Aug 14 16:35:05 2003
@@ -52,6 +52,14 @@
         return $this->source->name;
     }
 
+    /* iisjsoo 
+     * return the type of source this is (e.g. ldap, sql)
+     */
+    function getSourceType()
+    {
+        return $this->source->driver->type;
+    }
+
     /**
      * Returns the value of the specified attribute.
      *
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/Group.php ./lib/Group.php
--- /home/iisjsoo/turba-1.2/lib/Group.php	Sat Sep 14 07:13:05 2002
+++ ./lib/Group.php	Fri Aug 15 16:17:39 2003
@@ -60,6 +60,36 @@
         }
     }
 
+
+    /**
+     * iisjsoo: 
+     *         new function (wouldn't some OO overloading be good here?)
+     *         Adds a new contact entry to this group, also takes in the name of the group
+     *         to add it to.
+     *
+     * @param Turba_AbstractObject $object   The object to add to the Group
+     *
+     * @since Turba 1.2
+     */
+    function addMemberSource($object, $source)
+    {
+        if ($source == "") {
+          return addMemberSource($object);
+        }
+         // Can't add itself.
+         if ($object->getValue('__key') != $this->attributes['__key']) {
+            $members = @unserialize($this->attributes['__members']);
+            if (!is_array($members)) {
+                $members = array();
+            }
+            $member_entry[] = $object->getSource();
+            $member_entry[] = $object->getValue('__key');
+            $members[] = $member_entry;
+            $this->attributes['__members'] = serialize($members);
+         }
+    }
+
+
     /**
      * Deletes a contact entry from this group.
      *
@@ -81,6 +111,65 @@
         return true;
     }
 
+
+    /**
+     * iisjsoo: Deletes a contact entry from this group
+     *          Passed the $key and $source
+     *          e.g.for ldap:
+     *                $key: 'uid=iisjsoo,dn=XX,dn=YY'
+     *             $source: 'myldap'
+     *
+     *          e.g.for sql:
+     *                $key: '765ef989dc9a9d9c5' 
+     *             $source: 'localsql'
+     *               
+     * @param Turba_AbstractObject $object   The object to remove from the Group
+     *
+     * @since Turba 1.2
+     */
+    function removeMemberSource($object)
+    {
+        $members = unserialize($this->attributes['__members']);
+        $key = $object->getValue('__key');
+	$source = $object->getSource();
+	$memberToRemove = array($source,$key);
+	
+        if(($i = array_search($memberToRemove, $members)) !== false) {
+//		 print "found and deleting<br>";
+            unset($members[$i]);
+        } else {
+	  print "could not find the member<br>";
+	}
+	
+
+        $this->attributes['__members'] = serialize($members);
+        $this->store();
+        return true;
+    }
+
+
+
+   /** iisjsoo
+     *  Function to return a Turba_List of arrays containing the Source of
+     *  an entry and the entry's Key (object_id for sql, dn for ldap)
+     *   e.g.
+     *   list => (array('localsql', '73ebb2f4623ec959e5c6b12608750f57'),
+     *            array('localldap', 'uid=itpdfdr,ou=Users,dc=xxx,dc=xxx,dc=com,dc=au'))
+     */
+    function listMembersArray()
+    {
+        $children = unserialize($this->attributes['__members']);
+        if (!is_array($children)) {
+            $children = array();
+        }
+        reset($children);
+	$list = array();
+        foreach ($children as $member) {
+          $list[] =  $member;
+        }
+        return $list; //we can't sort this yet, lets work it out later
+      }
+
     /**
      * Retrieve the Objects in this group
      *
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/api.php ./lib/api.php
--- /home/iisjsoo/turba-1.2/lib/api.php	Mon Feb 10 12:06:55 2003
+++ ./lib/api.php	Fri Aug 15 16:31:46 2003
@@ -115,34 +115,27 @@
                             /* Is a Distribution List */
                             $listatt = $ob->getAttributes();
                             $seeninlist = array();
-                            $members = $ob->listMembers();
-                            if (get_class($members) == 'turba_list') {
-                                if ($members->count() == 1) {
-                                    $ob = $members->next();
-                                    $att = $ob->getAttributes();
-                                    $email = '';
-                                    foreach ($att as $key => $value) {
-                                        if (!empty($value) && isset($attributes[$key]) &&
-                                            $attributes[$key]['type'] == 'email') {
-                                            $email = $value;
-                                        }
-                                    }
-                                    $results[$name][] = array('name' => $listatt['name'] . ' - ' . $att['name'], 'email' => $email);
-                                } else {
+                            $members = $ob->listMembersArray();
+
+/*  iisjsoo 
+ *
+ *      i'm not sure how to get around this..
+ *      members is no longer a 'turba_list', but an array of arrays... 
+ *      maybe this should just check the return value of $ob->listMembersArray()
+ */
+                            if (get_class($members) == 'turba_list' || 1==1) {
                                     $email = '';
-                                    while ($ob = $members->next()) {
-                                        $att = $ob->getAttributes();
-                                        foreach ($att as $key => $value) {
-                                            if (!empty($value) && isset($attributes[$key]) &&
-                                                $attributes[$key]['type'] == 'email' &&
-                                                empty($seeninlist[trim(strtolower($att['name'])) . trim(strtolower($value))])) {
-
-                                                $email .= ($email == '') ? '' : ', ';
-                                                $email .= '"' . $att['name'] . '" <' . $value . '>';
-                                                $seeninlist[trim(strtolower($att['name'])) . trim(strtolower($value))] = true;
-                                            }
-                                        }
+                                    $members = $ob->listMembersArray();
+
+                                    foreach($members as $key=>$val){
+                                            $driver = &Turba_Source::singleton($val[0], $cfgSources[$val[0]]);
+                                            $listMember= $driver->getObject($val[1]); 
+                                            $emailAddress = '"'.$listMember->getValue('name').
+                                                    '" <'.$listMember->getValue('email').'>';
+                                            $email .= $emailAddress .= ',';
                                     }
+                                    // get rid of trailing ','
+                                    $email = preg_replace("/,$/","",$email);
                                     $results[$name][] = array('name' => $listatt['name'], 'email' => $email);
                                 }
                             }
@@ -151,7 +144,6 @@
                 }
             }
         }
-    }
     return $results;
 }
 
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/templates/browse/actions.inc ./templates/browse/actions.inc
--- /home/iisjsoo/turba-1.2/templates/browse/actions.inc	Wed Mar  5 02:33:37 2003
+++ ./templates/browse/actions.inc	Thu Aug 14 17:09:54 2003
@@ -12,7 +12,11 @@
   </td>
 
   <td align="right" nowrap="nowrap">
-<?php if (!empty($cfgSources[$source]['map']['__type'])): ?>
+<?php 
+
+	$source = PERSONAL_ADDRESS_BOOK_SOURCE;
+
+if (!empty($cfgSources[$source]['map']['__type'])): ?>
     <form name='targetList' action="javascript:void(0)" onsubmit="return false">
     <input type="button" class="button" onclick="ListUpdate(); Submit(<?php echo TURBA_ADD ?>); return false;" value="<?php echo _("Add to") ?>" />
     <select name="listList">
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/templates/browse/contactrow.inc ./templates/browse/contactrow.inc
--- /home/iisjsoo/turba-1.2/templates/browse/contactrow.inc	Mon Feb 10 12:35:57 2003
+++ ./templates/browse/contactrow.inc	Fri Aug 15 16:12:37 2003
@@ -66,7 +66,10 @@
 ?>
 <tr class="<?php echo $class ?>" onmouseover="javascript:style.backgroundColor='<?php echo $hi ?>';" onmouseout="javascript:style.backgroundColor='<?php echo $lo ?>';">
   <td>
-    <input type="checkbox" name="objectkeys[]" value="<?php echo htmlspecialchars($ob->getValue('__key')) ?>" />
+<!-- iisjsoo
+            Changed the next line to include the source of where the entry comes from
+-->
+    <input type="checkbox" name="objectkeys[]" value="<?php echo htmlspecialchars($ob->getSource()) . "|" .htmlspecialchars($ob->getValue('__key')) ?>" />
     <?php echo $ob->isGroup() ? Horde::img('group.gif', 'alt="' . _("Group") . '"') : '' ?>
   </td>
   <td><?php echo $cell ?></td>


More information about the turba mailing list