Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add groups support for LDAP address books, contributed by Andreas Dick

  • Loading branch information...
commit 6039aae3878aa5880415290cbc41af4bac4fdcb5 1 parent cf2da2f
@thomascube thomascube authored
View
9 config/main.inc.php.dist
@@ -501,8 +501,13 @@ $rcmail_config['ldap_public']['Verisign'] = array(
'scope' => 'sub', // search mode: sub|base|list
'filter' => '', // used for basic listing (if not empty) and will be &'d with search queries. example: status=act
'fuzzy_search' => true, // server allows wildcard search
- 'sizelimit' => '0', // Enables you to limit the count of entries fetched. Setting this to 0 means no limit.
- 'timelimit' => '0', // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit.
+ 'sizelimit' => '0', // Enables you to limit the count of entries fetched. Setting this to 0 means no limit.
+ 'timelimit' => '0', // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit.
+ // definition for groups, set to false if no groups are supported
+ 'groups' => array(
+ 'base_dn' => 'ou=groups,ou=rcabook,dc=localhost',
+ 'filter' => '(objectClass=groupOfNames)',
+ ),
);
*/
View
2  program/include/rcmail.php
@@ -394,7 +394,7 @@ public function get_address_sources($writeable = false)
$list[$id] = array(
'id' => $id,
'name' => $prop['name'],
- 'groups' => false,
+ 'groups' => is_array($prop['groups']),
'readonly' => !$prop['writable'],
'autocomplete' => in_array('sql', $autocomplete)
);
View
269 program/include/rcube_ldap.php
@@ -4,7 +4,7 @@
| program/include/rcube_ldap.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2006-2010, The Roundcube Dev Team |
+ | Copyright (C) 2006-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -12,6 +12,7 @@
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Andreas Dick <andudi (at) gmx (dot) ch> |
+-----------------------------------------------------------------------+
$Id$
@@ -40,11 +41,16 @@ class rcube_ldap extends rcube_addressbook
/** public properties */
public $primary_key = 'ID';
public $readonly = true;
+ public $groups = false;
public $list_page = 1;
public $page_size = 10;
+ public $group_id = 0;
public $ready = false;
public $coltypes = array();
+ private $group_cache = array();
+ private $group_members = array();
+
/**
* Object constructor
@@ -58,6 +64,10 @@ function __construct($p, $debug=false, $mail_domain=NULL)
{
$this->prop = $p;
+ // check if groups are configured
+ if (is_array($p['groups']))
+ $this->groups = true;
+
// fieldmap property is given
if (is_array($p['fieldmap'])) {
foreach ($p['fieldmap'] as $rf => $lf)
@@ -347,6 +357,21 @@ function list_records($cols=null, $subset=0)
$this->result->add($this->_ldap2result($entries[$i]));
}
+ // temp hack for filtering group members
+ if ($this->group_id)
+ {
+ $result = new rcube_result_set();
+ while ($record = $this->result->iterate())
+ {
+ if ($this->group_members[$record['ID']])
+ {
+ $result->add($record);
+ $result->count++;
+ }
+ }
+ $this->result = $result;
+ }
+
return $this->result;
}
@@ -799,5 +824,247 @@ function quote_string($str, $dn=false)
return strtr($str, $replace);
}
+
+ /**
+ * Setter for the current group
+ * (empty, has to be re-implemented by extending class)
+ */
+ function set_group($group_id)
+ {
+ if ($group_id)
+ {
+ if (! $this->group_cache) $this->list_groups();
+ $cache = $this->group_cache[$group_id]['members'];
+
+ $members = array();
+ for ($i=1; $i<$cache["count"]; $i++)
+ {
+ $member_dn = base64_encode($cache[$i]);
+ $members[$member_dn] = 1;
+ }
+ $this->group_members = $members;
+ $this->group_id = $group_id;
+ }
+ else $this->group_id = 0;
+ }
+
+ /**
+ * List all active contact groups of this source
+ *
+ * @param string Optional search string to match group name
+ * @return array Indexed list of contact groups, each a hash array
+ */
+ function list_groups($search = null)
+ {
+ if (!$this->prop['groups'])
+ return array();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $filter = $this->prop['groups']['filter'];
+
+ $res = ldap_search($this->conn, $base_dn, $filter, array('cn','member'));
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return array();
+ }
+ $ldap_data = ldap_get_entries($this->conn, $res);
+
+ $groups = array();
+ $group_sortnames = array();
+ for ($i=0; $i<$ldap_data["count"]; $i++)
+ {
+ $group_name = $ldap_data[$i]['cn'][0];
+ $group_id = base64_encode($group_name);
+ $groups[$group_id]['ID'] = $group_id;
+ $groups[$group_id]['name'] = $group_name;
+ $groups[$group_id]['members'] = $ldap_data[$i]['member'];
+ $group_sortnames[] = strtolower($group_name);
+ }
+ array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups);
+
+ $this->group_cache = $groups;
+ return $groups;
+ }
+
+ /**
+ * Create a contact group with the given name
+ *
+ * @param string The group name
+ * @return mixed False on error, array with record props in success
+ */
+ function create_group($group_name)
+ {
+ if (!$this->group_cache)
+ $this->list_groups();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $new_dn = "cn=$group_name,$base_dn";
+ $new_gid = base64_encode($group_name);
+
+ $new_entry = array(
+ 'objectClass' => array('top', 'groupOfNames'),
+ 'cn' => $group_name,
+ 'member' => '',
+ );
+
+ $res = ldap_add($this->conn, $new_dn, $new_entry);
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return false;
+ }
+ return array('id' => $new_gid, 'name' => $group_name);
+ }
+
+ /**
+ * Delete the given group and all linked group members
+ *
+ * @param string Group identifier
+ * @return boolean True on success, false if no data was changed
+ */
+ function delete_group($group_id)
+ {
+ if (!$this->group_cache)
+ $this->list_groups();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $group_name = $this->group_cache[$group_id]['name'];
+
+ $del_dn = "cn=$group_name,$base_dn";
+ $res = ldap_delete($this->conn, $del_dn);
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Rename a specific contact group
+ *
+ * @param string Group identifier
+ * @param string New name to set for this group
+ * @return boolean New name on success, false if no data was changed
+ */
+ function rename_group($group_id, $new_name)
+ {
+ if (!$this->group_cache)
+ $this->list_groups();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $group_name = $this->group_cache[$group_id]['name'];
+ $old_dn = "cn=$group_name,$base_dn";
+ $new_rdn = "cn=$new_name";
+
+ $res = ldap_rename($this->conn, $old_dn, $new_rdn, NULL, TRUE);
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return false;
+ }
+ return $new_name;
+ }
+
+ /**
+ * Add the given contact records the a certain group
+ *
+ * @param string Group identifier
+ * @param array List of contact identifiers to be added
+ * @return int Number of contacts added
+ */
+ function add_to_group($group_id, $contact_ids)
+ {
+ if (!$this->group_cache)
+ $this->list_groups();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $group_name = $this->group_cache[$group_id]['name'];
+ $group_dn = "cn=$group_name,$base_dn";
+
+ $new_attrs = array();
+ foreach (explode(",", $contact_ids) as $id)
+ $new_attrs['member'][] = base64_decode($id);
+
+ $res = ldap_mod_add($this->conn, $group_dn, $new_attrs);
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return 0;
+ }
+ return count($new_attrs['member']);
+ }
+
+ /**
+ * Remove the given contact records from a certain group
+ *
+ * @param string Group identifier
+ * @param array List of contact identifiers to be removed
+ * @return int Number of deleted group members
+ */
+ function remove_from_group($group_id, $contact_ids)
+ {
+ if (!$this->group_cache)
+ $this->list_groups();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $group_name = $this->group_cache[$group_id]['name'];
+ $group_dn = "cn=$group_name,$base_dn";
+
+ $del_attrs = array();
+ foreach (explode(",", $contact_ids) as $id)
+ $del_attrs['member'][] = base64_decode($id);
+
+ $res = ldap_mod_del($this->conn, $group_dn, $del_attrs);
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return 0;
+ }
+ return count($del_attrs['member']);
+ }
+
+ /**
+ * Get group assignments of a specific contact record
+ *
+ * @param mixed Record identifier
+ *
+ * @return array List of assigned groups as ID=>Name pairs
+ * @since 0.5-beta
+ */
+ function get_record_groups($contact_id)
+ {
+ if (!$this->prop['groups'])
+ return array();
+
+ $base_dn = $this->prop['groups']['base_dn'];
+ $contact_dn = base64_decode($contact_id);
+ $filter = "(member=$contact_dn)";
+
+ $res = ldap_search($this->conn, $base_dn, $filter, array('cn'));
+ if ($res === false)
+ {
+ $this->_debug("S: ".ldap_error($this->conn));
+ $this->set_error(self::ERROR_SAVING, 'errorsaving');
+ return array();
+ }
+ $ldap_data = ldap_get_entries($this->conn, $res);
+
+ $groups = array();
+ for ($i=0; $i<$ldap_data["count"]; $i++)
+ {
+ $group_name = $ldap_data[$i]['cn'][0];
+ $group_id = base64_encode($group_name);
+ $groups[$group_id] = $group_id;
+ }
+ return $groups;
+ }
}
View
2  program/steps/addressbook/save.inc
@@ -242,7 +242,7 @@ else {
if ($insert_id) {
// add new contact to the specified group
- if ($CONTACTS->group_id) {
+ if ($CONTACTS->groups && $CONTACTS->group_id) {
$plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array('group_id' => $CONTACTS->group_id, 'ids' => $insert_id, 'source' => $source));
if (!$plugin['abort']) {
Please sign in to comment.
Something went wrong with that request. Please try again.