Changeset 4467 in subversion


Ignore:
Timestamp:
Jan 29, 2011 6:31:23 AM (2 years ago)
Author:
thomasb
Message:

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

Location:
trunk/roundcubemail
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/config/main.inc.php.dist

    r4466 r4467  
    502502  'filter'        => '',      // used for basic listing (if not empty) and will be &'d with search queries. example: status=act 
    503503  'fuzzy_search'  => true,    // server allows wildcard search 
    504   'sizelimit'     => '0',     // Enables you to limit the count of entries fetched. Setting this to 0 means no limit.  
    505   'timelimit'     => '0',     // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit.  
     504  'sizelimit'     => '0',     // Enables you to limit the count of entries fetched. Setting this to 0 means no limit. 
     505  'timelimit'     => '0',     // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit. 
     506  // definition for groups, set to false if no groups are supported 
     507  'groups'        => array( 
     508    'base_dn'     => 'ou=groups,ou=rcabook,dc=localhost', 
     509    'filter'      => '(objectClass=groupOfNames)', 
     510  ), 
    506511); 
    507512*/ 
  • trunk/roundcubemail/program/include/rcmail.php

    r4466 r4467  
    395395          'id' => $id, 
    396396          'name' => $prop['name'], 
    397           'groups' => false, 
     397          'groups' => is_array($prop['groups']), 
    398398          'readonly' => !$prop['writable'], 
    399399          'autocomplete' => in_array('sql', $autocomplete) 
  • trunk/roundcubemail/program/include/rcube_ldap.php

    r4424 r4467  
    55 |                                                                       | 
    66 | This file is part of the Roundcube Webmail client                     | 
    7  | Copyright (C) 2006-2010, The Roundcube Dev Team                       | 
     7 | Copyright (C) 2006-2011, The Roundcube Dev Team                       | 
    88 | Licensed under the GNU GPL                                            | 
    99 |                                                                       | 
     
    1313 +-----------------------------------------------------------------------+ 
    1414 | Author: Thomas Bruederli <roundcube@gmail.com>                        | 
     15 |         Andreas Dick <andudi (at) gmx (dot) ch>                       | 
    1516 +-----------------------------------------------------------------------+ 
    1617 
     
    4142  public $primary_key = 'ID'; 
    4243  public $readonly = true; 
     44  public $groups = false; 
    4345  public $list_page = 1; 
    4446  public $page_size = 10; 
     47  public $group_id = 0; 
    4548  public $ready = false; 
    4649  public $coltypes = array(); 
     50 
     51  private $group_cache = array(); 
     52  private $group_members = array(); 
    4753 
    4854 
     
    5965    $this->prop = $p; 
    6066 
     67    // check if groups are configured 
     68    if (is_array($p['groups'])) 
     69      $this->groups = true; 
     70     
    6171    // fieldmap property is given 
    6272    if (is_array($p['fieldmap'])) { 
     
    346356      for ($i = $start_row; $i < min($entries['count'], $last_row); $i++) 
    347357        $this->result->add($this->_ldap2result($entries[$i])); 
     358    } 
     359 
     360    // temp hack for filtering group members 
     361    if ($this->group_id) 
     362    { 
     363        $result = new rcube_result_set(); 
     364        while ($record = $this->result->iterate()) 
     365        { 
     366            if ($this->group_members[$record['ID']]) 
     367            { 
     368                $result->add($record); 
     369                $result->count++; 
     370            } 
     371        } 
     372        $this->result = $result; 
    348373    } 
    349374 
     
    800825  } 
    801826 
     827 
     828    /** 
     829     * Setter for the current group 
     830     * (empty, has to be re-implemented by extending class) 
     831     */ 
     832    function set_group($group_id) 
     833    { 
     834        if ($group_id) 
     835        { 
     836            if (! $this->group_cache) $this->list_groups(); 
     837            $cache = $this->group_cache[$group_id]['members']; 
     838 
     839            $members = array(); 
     840            for ($i=1; $i<$cache["count"]; $i++) 
     841            { 
     842                $member_dn = base64_encode($cache[$i]); 
     843                $members[$member_dn] = 1; 
     844            } 
     845            $this->group_members = $members; 
     846            $this->group_id = $group_id; 
     847        } 
     848        else $this->group_id = 0; 
     849    } 
     850 
     851    /** 
     852     * List all active contact groups of this source 
     853     * 
     854     * @param string  Optional search string to match group name 
     855     * @return array  Indexed list of contact groups, each a hash array 
     856     */ 
     857    function list_groups($search = null) 
     858    { 
     859        if (!$this->prop['groups']) 
     860          return array(); 
     861 
     862        $base_dn = $this->prop['groups']['base_dn']; 
     863        $filter = $this->prop['groups']['filter']; 
     864 
     865        $res = ldap_search($this->conn, $base_dn, $filter, array('cn','member')); 
     866        if ($res === false) 
     867        { 
     868            $this->_debug("S: ".ldap_error($this->conn)); 
     869            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     870            return array(); 
     871        } 
     872        $ldap_data = ldap_get_entries($this->conn, $res); 
     873 
     874        $groups = array(); 
     875        $group_sortnames = array(); 
     876        for ($i=0; $i<$ldap_data["count"]; $i++) 
     877        { 
     878            $group_name = $ldap_data[$i]['cn'][0]; 
     879            $group_id = base64_encode($group_name); 
     880            $groups[$group_id]['ID'] = $group_id; 
     881            $groups[$group_id]['name'] = $group_name; 
     882            $groups[$group_id]['members'] = $ldap_data[$i]['member']; 
     883            $group_sortnames[] = strtolower($group_name); 
     884        } 
     885        array_multisort($group_sortnames, SORT_ASC, SORT_STRING, $groups); 
     886 
     887        $this->group_cache = $groups; 
     888        return $groups; 
     889    } 
     890 
     891    /** 
     892     * Create a contact group with the given name 
     893     * 
     894     * @param string The group name 
     895     * @return mixed False on error, array with record props in success 
     896     */ 
     897    function create_group($group_name) 
     898    { 
     899        if (!$this->group_cache) 
     900            $this->list_groups(); 
     901 
     902        $base_dn = $this->prop['groups']['base_dn']; 
     903        $new_dn = "cn=$group_name,$base_dn"; 
     904        $new_gid = base64_encode($group_name); 
     905 
     906        $new_entry = array( 
     907            'objectClass' => array('top', 'groupOfNames'), 
     908            'cn' => $group_name, 
     909            'member' => '', 
     910        ); 
     911 
     912        $res = ldap_add($this->conn, $new_dn, $new_entry); 
     913        if ($res === false) 
     914        { 
     915            $this->_debug("S: ".ldap_error($this->conn)); 
     916            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     917            return false; 
     918        } 
     919        return array('id' => $new_gid, 'name' => $group_name); 
     920    } 
     921 
     922    /** 
     923     * Delete the given group and all linked group members 
     924     * 
     925     * @param string Group identifier 
     926     * @return boolean True on success, false if no data was changed 
     927     */ 
     928    function delete_group($group_id) 
     929    { 
     930        if (!$this->group_cache) 
     931            $this->list_groups(); 
     932 
     933        $base_dn = $this->prop['groups']['base_dn']; 
     934        $group_name = $this->group_cache[$group_id]['name']; 
     935 
     936        $del_dn = "cn=$group_name,$base_dn"; 
     937        $res = ldap_delete($this->conn, $del_dn); 
     938        if ($res === false) 
     939        { 
     940            $this->_debug("S: ".ldap_error($this->conn)); 
     941            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     942            return false; 
     943        } 
     944        return true; 
     945    } 
     946 
     947    /** 
     948     * Rename a specific contact group 
     949     * 
     950     * @param string Group identifier 
     951     * @param string New name to set for this group 
     952     * @return boolean New name on success, false if no data was changed 
     953     */ 
     954    function rename_group($group_id, $new_name) 
     955    { 
     956        if (!$this->group_cache) 
     957            $this->list_groups(); 
     958 
     959        $base_dn = $this->prop['groups']['base_dn']; 
     960        $group_name = $this->group_cache[$group_id]['name']; 
     961        $old_dn = "cn=$group_name,$base_dn"; 
     962        $new_rdn = "cn=$new_name"; 
     963 
     964        $res = ldap_rename($this->conn, $old_dn, $new_rdn, NULL, TRUE); 
     965        if ($res === false) 
     966        { 
     967            $this->_debug("S: ".ldap_error($this->conn)); 
     968            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     969            return false; 
     970        } 
     971        return $new_name; 
     972    } 
     973 
     974    /** 
     975     * Add the given contact records the a certain group 
     976     * 
     977     * @param string  Group identifier 
     978     * @param array   List of contact identifiers to be added 
     979     * @return int    Number of contacts added 
     980     */ 
     981    function add_to_group($group_id, $contact_ids) 
     982    { 
     983        if (!$this->group_cache) 
     984            $this->list_groups(); 
     985 
     986        $base_dn = $this->prop['groups']['base_dn']; 
     987        $group_name = $this->group_cache[$group_id]['name']; 
     988        $group_dn = "cn=$group_name,$base_dn"; 
     989 
     990        $new_attrs = array(); 
     991        foreach (explode(",", $contact_ids) as $id) 
     992            $new_attrs['member'][] = base64_decode($id); 
     993 
     994        $res = ldap_mod_add($this->conn, $group_dn, $new_attrs); 
     995        if ($res === false) 
     996        { 
     997            $this->_debug("S: ".ldap_error($this->conn)); 
     998            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     999            return 0; 
     1000        } 
     1001        return count($new_attrs['member']); 
     1002    } 
     1003 
     1004    /** 
     1005     * Remove the given contact records from a certain group 
     1006     * 
     1007     * @param string  Group identifier 
     1008     * @param array   List of contact identifiers to be removed 
     1009     * @return int    Number of deleted group members 
     1010     */ 
     1011    function remove_from_group($group_id, $contact_ids) 
     1012    { 
     1013        if (!$this->group_cache) 
     1014            $this->list_groups(); 
     1015 
     1016        $base_dn = $this->prop['groups']['base_dn']; 
     1017        $group_name = $this->group_cache[$group_id]['name']; 
     1018        $group_dn = "cn=$group_name,$base_dn"; 
     1019 
     1020        $del_attrs = array(); 
     1021        foreach (explode(",", $contact_ids) as $id) 
     1022            $del_attrs['member'][] = base64_decode($id); 
     1023 
     1024        $res = ldap_mod_del($this->conn, $group_dn, $del_attrs); 
     1025        if ($res === false) 
     1026        { 
     1027            $this->_debug("S: ".ldap_error($this->conn)); 
     1028            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     1029            return 0; 
     1030        } 
     1031        return count($del_attrs['member']); 
     1032    } 
     1033 
     1034    /** 
     1035     * Get group assignments of a specific contact record 
     1036     * 
     1037     * @param mixed Record identifier 
     1038     * 
     1039     * @return array List of assigned groups as ID=>Name pairs 
     1040     * @since 0.5-beta 
     1041     */ 
     1042    function get_record_groups($contact_id) 
     1043    { 
     1044        if (!$this->prop['groups']) 
     1045            return array(); 
     1046 
     1047        $base_dn = $this->prop['groups']['base_dn']; 
     1048        $contact_dn = base64_decode($contact_id); 
     1049        $filter = "(member=$contact_dn)"; 
     1050 
     1051        $res = ldap_search($this->conn, $base_dn, $filter, array('cn')); 
     1052        if ($res === false) 
     1053        { 
     1054            $this->_debug("S: ".ldap_error($this->conn)); 
     1055            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     1056            return array(); 
     1057        } 
     1058        $ldap_data = ldap_get_entries($this->conn, $res); 
     1059 
     1060        $groups = array(); 
     1061        for ($i=0; $i<$ldap_data["count"]; $i++) 
     1062        { 
     1063            $group_name = $ldap_data[$i]['cn'][0]; 
     1064            $group_id = base64_encode($group_name); 
     1065            $groups[$group_id] = $group_id; 
     1066        } 
     1067        return $groups; 
     1068    } 
    8021069} 
    8031070 
  • trunk/roundcubemail/program/steps/addressbook/save.inc

    r4454 r4467  
    243243  if ($insert_id) { 
    244244    // add new contact to the specified group 
    245     if ($CONTACTS->group_id) { 
     245    if ($CONTACTS->groups && $CONTACTS->group_id) { 
    246246      $plugin = $RCMAIL->plugins->exec_hook('group_addmembers', array('group_id' => $CONTACTS->group_id, 'ids' => $insert_id, 'source' => $source)); 
    247247 
Note: See TracChangeset for help on using the changeset viewer.