Changeset 13db9ee in github


Ignore:
Timestamp:
Mar 29, 2012 7:14:47 AM (14 months ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.8
Children:
48e9c14
Parents:
cc46fb2
Message:
  • Support LDAP RFC2256's country object class read/write (#1488123)
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    r0223094 r13db9ee  
    22=========================== 
    33 
     4- Support LDAP RFC2256's country object class read/write (#1488123) 
    45- Upgraded to jQuery 1.7.2 
    56- Image resize with GD extension (#1488383) 
  • config/main.inc.php.dist

    r377bc60 r13db9ee  
    581581  'required_fields' => array('cn', 'sn', 'mail'), 
    582582  'search_fields'   => array('mail', 'cn'),  // fields to search in 
     583  // Map of contact sub-objects (attribute name => objectClass(es)), e.g. 'c' => 'country' 
     584  'sub_fields' => array(), 
    583585  // mapping of contact fields to directory attributes 
    584586  'fieldmap' => array( 
  • program/include/rcube_ldap.php

    r38dc510 r13db9ee  
    4545    protected $prop = array(); 
    4646    protected $fieldmap = array(); 
    47  
     47    protected $sub_filter; 
    4848    protected $filter = ''; 
    4949    protected $result = null; 
     
    137137        foreach ($this->prop['required_fields'] as $key => $val) 
    138138            $this->prop['required_fields'][$key] = $this->_attr_name(strtolower($val)); 
     139 
     140        // Build sub_fields filter 
     141        if (!empty($this->prop['sub_fields']) && is_array($this->prop['sub_fields'])) { 
     142            $this->sub_filter = ''; 
     143            foreach ($this->prop['sub_fields'] as $attr => $class) { 
     144                if (!empty($class)) { 
     145                    $class = is_array($class) ? array_pop($class) : $class; 
     146                    $this->sub_filter .= '(objectClass=' . $class . ')'; 
     147                } 
     148            } 
     149            if (count($this->prop['sub_fields']) > 1) { 
     150                $this->sub_filter = '(|' . $this->sub_filter . ')'; 
     151            } 
     152        } 
    139153 
    140154        $this->sort_col    = is_array($p['sort']) ? $p['sort'][0] : $p['sort']; 
     
    895909    function get_record($dn, $assoc=false) 
    896910    { 
    897         $res = null; 
     911        $res = $this->result = null; 
     912 
    898913        if ($this->conn && $dn) 
    899914        { 
     
    902917            $this->_debug("C: Read [dn: $dn] [(objectclass=*)]"); 
    903918 
    904             if ($this->ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', array_values($this->fieldmap))) 
    905                 $entry = ldap_first_entry($this->conn, $this->ldap_result); 
    906             else 
     919            if ($ldap_result = @ldap_read($this->conn, $dn, '(objectclass=*)', array_values($this->fieldmap))) { 
     920                $this->_debug("S: OK"); 
     921 
     922                $entry = ldap_first_entry($this->conn, $ldap_result); 
     923 
     924                if ($entry && ($rec = ldap_get_attributes($this->conn, $entry))) { 
     925                    $rec = array_change_key_case($rec, CASE_LOWER); 
     926                } 
     927            } 
     928            else { 
    907929                $this->_debug("S: ".ldap_error($this->conn)); 
    908  
    909             if ($entry && ($rec = ldap_get_attributes($this->conn, $entry))) 
    910             { 
    911                 $this->_debug("S: OK"/* . print_r($rec, true)*/); 
    912  
    913                 $rec = array_change_key_case($rec, CASE_LOWER); 
    914  
     930            } 
     931 
     932            // Use ldap_list to get subentries like country (c) attribute (#1488123) 
     933            if (!empty($rec) && $this->sub_filter) { 
     934                if ($entries = $this->ldap_list($dn, $this->sub_filter, array_keys($this->prop['sub_fields']))) { 
     935                    foreach ($entries as $entry) { 
     936                        $lrec = array_change_key_case($entry, CASE_LOWER); 
     937                        $rec  = array_merge($lrec, $rec); 
     938                    } 
     939                } 
     940            } 
     941 
     942            if (!empty($rec)) { 
    915943                // Add in the dn for the entry. 
    916944                $rec['dn'] = $dn; 
    917945                $res = $this->_ldap2result($rec); 
    918                 $this->result = new rcube_result_set(1); 
     946                $this->result = new rcube_result_set(); 
    919947                $this->result->add($res); 
    920948            } 
     
    10071035        $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn; 
    10081036 
    1009         $this->_debug("C: Add [dn: $dn]: ".print_r($newentry, true)); 
    1010  
    1011         $res = ldap_add($this->conn, $dn, $newentry); 
    1012         if ($res === FALSE) { 
    1013             $this->_debug("S: ".ldap_error($this->conn)); 
     1037        // Remove attributes that need to be added separately (child objects) 
     1038        $xfields = array(); 
     1039        if (!empty($this->prop['sub_fields']) && is_array($this->prop['sub_fields'])) { 
     1040            foreach ($this->prop['sub_fields'] as $xf => $xclass) { 
     1041                if (!empty($newentry[$xf])) { 
     1042                    $xfields[$xf] = $newentry[$xf]; 
     1043                    unset($newentry[$xf]); 
     1044                } 
     1045            } 
     1046        } 
     1047 
     1048        if (!$this->ldap_add($dn, $newentry)) { 
    10141049            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    10151050            return false; 
    1016         } // end if 
    1017  
    1018         $this->_debug("S: OK"); 
     1051        } 
     1052 
     1053        foreach ($xfields as $xidx => $xf) { 
     1054            $xdn = $xidx.'='.$this->_quote_string($xf).','.$dn; 
     1055            $xf = array( 
     1056                $xidx => $xf, 
     1057                'objectClass' => (array) $this->prop['sub_fields'][$xidx], 
     1058            ); 
     1059 
     1060            $this->ldap_add($xdn, $xf); 
     1061        } 
    10191062 
    10201063        $dn = self::dn_encode($dn); 
     
    10391082    { 
    10401083        $record = $this->get_record($id, true); 
    1041         $result = $this->get_result(); 
    1042         $record = $result->first(); 
    1043  
    1044         $newdata = array(); 
     1084 
     1085        $newdata     = array(); 
    10451086        $replacedata = array(); 
    1046         $deletedata = array(); 
     1087        $deletedata  = array(); 
     1088        $subdata     = array(); 
     1089        $subdeldata  = array(); 
     1090        $subnewdata  = array(); 
    10471091 
    10481092        $ldap_data = $this->_map_data($save_cols); 
    1049         $old_data = $record['_raw_attrib']; 
     1093        $old_data  = $record['_raw_attrib']; 
    10501094 
    10511095        foreach ($this->fieldmap as $col => $fld) { 
    1052             $val = $ldap_data[$fld]; 
    10531096            if ($fld) { 
     1097                $val = $ldap_data[$fld]; 
     1098                $old = $old_data[$fld]; 
    10541099                // remove empty array values 
    10551100                if (is_array($val)) 
    10561101                    $val = array_filter($val); 
     1102                // $this->_map_data() result and _raw_attrib use different format 
     1103                // make sure comparing array with one element with a string works as expected 
     1104                if (is_array($old) && count($old) == 1 && !is_array($val)) { 
     1105                    $old = array_pop($old); 
     1106                } 
     1107                // Subentries must be handled separately 
     1108                if (!empty($this->prop['sub_fields']) && isset($this->prop['sub_fields'][$fld])) { 
     1109                    if ($old != $val) { 
     1110                        if ($old !== null) { 
     1111                            $subdeldata[$fld] = $old; 
     1112                        } 
     1113                        if ($val) { 
     1114                            $subnewdata[$fld] = $val; 
     1115                        } 
     1116                    } 
     1117                    else if ($old !== null) { 
     1118                        $subdata[$fld] = $old; 
     1119                    } 
     1120                    continue; 
     1121                } 
    10571122                // The field does exist compare it to the ldap record. 
    1058                 if ($old_data[$fld] != $val) { 
     1123                if ($old != $val) { 
    10591124                    // Changed, but find out how. 
    1060                     if (!isset($old_data[$fld])) { 
     1125                    if ($old === null) { 
    10611126                        // Field was not set prior, need to add it. 
    10621127                        $newdata[$fld] = $val; 
     
    10681133                            $deletedata[$fld] = $old_data[$fld]; 
    10691134                        } 
    1070                     } // end elseif 
     1135                    } 
    10711136                    else { 
    10721137                        // The data was modified, save it out. 
     
    10761141            } // end if 
    10771142        } // end foreach 
    1078  
     1143/* 
     1144        console($old_data); 
     1145        console($ldap_data); 
     1146        console('----'); 
     1147        console($newdata); 
     1148        console($replacedata); 
     1149        console($deletedata); 
     1150        console('----'); 
     1151        console($subdata); 
     1152        console($subnewdata); 
     1153        console($subdeldata); 
     1154*/ 
    10791155        $dn = self::dn_decode($id); 
    10801156 
     
    10821158        if (!empty($deletedata)) { 
    10831159            // Delete the fields. 
    1084             $this->_debug("C: Delete [dn: $dn]: ".print_r($deletedata, true)); 
    1085             if (!ldap_mod_del($this->conn, $dn, $deletedata)) { 
    1086                 $this->_debug("S: ".ldap_error($this->conn)); 
     1160            if (!$this->ldap_mod_del($dn, $deletedata)) { 
    10871161                $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    10881162                return false; 
    10891163            } 
    1090             $this->_debug("S: OK"); 
    10911164        } // end if 
    10921165 
     
    11051178            // Replace the fields. 
    11061179            if (!empty($replacedata)) { 
    1107                 $this->_debug("C: Replace [dn: $dn]: ".print_r($replacedata, true)); 
    1108                 if (!ldap_mod_replace($this->conn, $dn, $replacedata)) { 
    1109                     $this->_debug("S: ".ldap_error($this->conn)); 
     1180                if (!$this->ldap_mod_replace($dn, $replacedata)) { 
     1181                    $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    11101182                    return false; 
    11111183                } 
    1112                 $this->_debug("S: OK"); 
    1113             } // end if 
     1184            } 
    11141185        } // end if 
     1186 
     1187        // RDN change, we need to remove all sub-entries 
     1188        if (!empty($newrdn)) { 
     1189            $subdeldata = array_merge($subdeldata, $subdata); 
     1190            $subnewdata = array_merge($subnewdata, $subdata); 
     1191        } 
     1192 
     1193        // remove sub-entries 
     1194        if (!empty($subdeldata)) { 
     1195            foreach ($subdeldata as $fld => $val) { 
     1196                $subdn = $fld.'='.$this->_quote_string($val).','.$dn; 
     1197                if (!$this->ldap_delete($subdn)) { 
     1198                    return false; 
     1199                } 
     1200            } 
     1201        } 
    11151202 
    11161203        if (!empty($newdata)) { 
    11171204            // Add the fields. 
    1118             $this->_debug("C: Add [dn: $dn]: ".print_r($newdata, true)); 
    1119             if (!ldap_mod_add($this->conn, $dn, $newdata)) { 
    1120                 $this->_debug("S: ".ldap_error($this->conn)); 
     1205            if (!$this->ldap_mod_add($dn, $newdata)) { 
    11211206                $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    11221207                return false; 
    11231208            } 
    1124             $this->_debug("S: OK"); 
    11251209        } // end if 
    11261210 
    11271211        // Handle RDN change 
    11281212        if (!empty($newrdn)) { 
    1129             $this->_debug("C: Rename [dn: $dn] [dn: $newrdn]"); 
    1130             if (!ldap_rename($this->conn, $dn, $newrdn, NULL, TRUE)) { 
    1131                 $this->_debug("S: ".ldap_error($this->conn)); 
     1213            if (!$this->ldap_rename($dn, $newrdn, null, true)) { 
     1214                $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    11321215                return false; 
    11331216            } 
    1134             $this->_debug("S: OK"); 
    11351217 
    11361218            $dn    = self::dn_encode($dn); 
     
    11381220 
    11391221            // change the group membership of the contact 
    1140             if ($this->groups) 
    1141             { 
     1222            if ($this->groups) { 
    11421223                $group_ids = $this->get_record_groups($dn); 
    11431224                foreach ($group_ids as $group_id) 
     
    11481229            } 
    11491230 
    1150             return $newdn; 
    1151         } 
    1152  
    1153         return true; 
     1231            $dn = self::dn_decode($newdn); 
     1232        } 
     1233 
     1234        // add sub-entries 
     1235        if (!empty($subnewdata)) { 
     1236            foreach ($subnewdata as $fld => $val) { 
     1237                $subdn = $fld.'='.$this->_quote_string($val).','.$dn; 
     1238                $xf = array( 
     1239                    $fld => $val, 
     1240                    'objectClass' => (array) $this->prop['sub_fields'][$fld], 
     1241                ); 
     1242                $this->ldap_add($subdn, $xf); 
     1243            } 
     1244        } 
     1245 
     1246        return $newdn ? $newdn : true; 
    11541247    } 
    11551248 
     
    11721265        foreach ($ids as $id) { 
    11731266            $dn = self::dn_decode($id); 
    1174             $this->_debug("C: Delete [dn: $dn]"); 
     1267 
     1268            // Need to delete all sub-entries first 
     1269            if ($this->sub_filter) { 
     1270                if ($entries = $this->ldap_list($dn, $this->sub_filter, array_keys($this->props['sub_fields']))) { 
     1271                    foreach ($entries as $entry) { 
     1272                        if (!$this->ldap_delete($entry['dn'])) { 
     1273                            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
     1274                            return false; 
     1275                        } 
     1276                    } 
     1277                } 
     1278            } 
     1279 
    11751280            // Delete the record. 
    1176             $res = ldap_delete($this->conn, $dn); 
    1177             if ($res === FALSE) { 
    1178                 $this->_debug("S: ".ldap_error($this->conn)); 
     1281            if (!$this->ldap_delete($dn)) { 
    11791282                $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    11801283                return false; 
    1181             } // end if 
    1182             $this->_debug("S: OK"); 
     1284            } 
    11831285 
    11841286            // remove contact from all groups where he was member 
     
    12721374            break; 
    12731375        } 
    1274          
     1376 
    12751377        return $function; 
    12761378    } 
     
    13751477            } 
    13761478        } 
    1377          
     1479 
    13781480        return $ldap_data; 
    13791481    } 
     
    16241726        ); 
    16251727 
    1626         $this->_debug("C: Add [dn: $new_dn]: ".print_r($new_entry, true)); 
    1627  
    1628         $res = ldap_add($this->conn, $new_dn, $new_entry); 
    1629         if ($res === false) 
    1630         { 
    1631             $this->_debug("S: ".ldap_error($this->conn)); 
     1728        if (!$this->ldap_add($new_dn, $new_entry)) { 
    16321729            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    16331730            return false; 
    16341731        } 
    16351732 
    1636         $this->_debug("S: OK"); 
    16371733        $this->cache->remove('groups'); 
    16381734 
     
    16551751        $del_dn = "cn=$group_name,$base_dn"; 
    16561752 
    1657         $this->_debug("C: Delete [dn: $del_dn]"); 
    1658  
    1659         $res = ldap_delete($this->conn, $del_dn); 
    1660         if ($res === false) 
    1661         { 
    1662             $this->_debug("S: ".ldap_error($this->conn)); 
     1753        if (!$this->ldap_delete($del_dn)) { 
    16631754            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    16641755            return false; 
    16651756        } 
    16661757 
    1667         $this->_debug("S: OK"); 
    16681758        $this->cache->remove('groups'); 
    16691759 
     
    16901780        $new_gid = self::dn_encode($new_name); 
    16911781 
    1692         $this->_debug("C: Rename [dn: $old_dn] [dn: $new_rdn]"); 
    1693  
    1694         $res = ldap_rename($this->conn, $old_dn, $new_rdn, NULL, TRUE); 
    1695         if ($res === false) 
    1696         { 
    1697             $this->_debug("S: ".ldap_error($this->conn)); 
     1782        if (!$this->ldap_rename($old_dn, $new_rdn, null, true)) { 
    16981783            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    16991784            return false; 
    17001785        } 
    17011786 
    1702         $this->_debug("S: OK"); 
    17031787        $this->cache->remove('groups'); 
    17041788 
     
    17301814            $new_attrs[$member_attr][] = self::dn_decode($id); 
    17311815 
    1732         $this->_debug("C: Add [dn: $group_dn]: ".print_r($new_attrs, true)); 
    1733  
    1734         $res = ldap_mod_add($this->conn, $group_dn, $new_attrs); 
    1735         if ($res === false) 
    1736         { 
    1737             $this->_debug("S: ".ldap_error($this->conn)); 
     1816        if (!$this->ldap_mod_add($group_dn, $new_attrs)) { 
    17381817            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    17391818            return 0; 
    17401819        } 
    17411820 
    1742         $this->_debug("S: OK"); 
    17431821        $this->cache->remove('groups'); 
    17441822 
     
    17671845            $del_attrs[$member_attr][] = self::dn_decode($id); 
    17681846 
    1769         $this->_debug("C: Delete [dn: $group_dn]: ".print_r($del_attrs, true)); 
    1770  
    1771         $res = ldap_mod_del($this->conn, $group_dn, $del_attrs); 
    1772         if ($res === false) 
    1773         { 
    1774             $this->_debug("S: ".ldap_error($this->conn)); 
     1847        if (!$this->ldap_mod_del($group_dn, $del_attrs)) { 
    17751848            $this->set_error(self::ERROR_SAVING, 'errorsaving'); 
    17761849            return 0; 
    17771850        } 
    17781851 
    1779         $this->_debug("S: OK"); 
    17801852        $this->cache->remove('groups'); 
    17811853 
     
    19822054        return base64_decode($str); 
    19832055    } 
     2056 
     2057    /** 
     2058     * Wrapper for ldap_add() 
     2059     */ 
     2060    protected function ldap_add($dn, $entry) 
     2061    { 
     2062        $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true)); 
     2063 
     2064        $res = ldap_add($this->conn, $dn, $entry); 
     2065        if ($res === false) { 
     2066            $this->_debug("S: ".ldap_error($this->conn)); 
     2067            return false; 
     2068        } 
     2069 
     2070        $this->_debug("S: OK"); 
     2071        return true; 
     2072    } 
     2073 
     2074    /** 
     2075     * Wrapper for ldap_delete() 
     2076     */ 
     2077    protected function ldap_delete($dn) 
     2078    { 
     2079        $this->_debug("C: Delete [dn: $dn]"); 
     2080 
     2081        $res = ldap_delete($this->conn, $dn); 
     2082        if ($res === false) { 
     2083            $this->_debug("S: ".ldap_error($this->conn)); 
     2084            return false; 
     2085        } 
     2086 
     2087        $this->_debug("S: OK"); 
     2088        return true; 
     2089    } 
     2090 
     2091    /** 
     2092     * Wrapper for ldap_mod_replace() 
     2093     */ 
     2094    protected function ldap_mod_replace($dn, $entry) 
     2095    { 
     2096        $this->_debug("C: Replace [dn: $dn]: ".print_r($entry, true)); 
     2097 
     2098        if (!ldap_mod_replace($this->conn, $dn, $entry)) { 
     2099            $this->_debug("S: ".ldap_error($this->conn)); 
     2100            return false; 
     2101        } 
     2102 
     2103        $this->_debug("S: OK"); 
     2104        return true; 
     2105    } 
     2106 
     2107    /** 
     2108     * Wrapper for ldap_mod_add() 
     2109     */ 
     2110    protected function ldap_mod_add($dn, $entry) 
     2111    { 
     2112        $this->_debug("C: Add [dn: $dn]: ".print_r($entry, true)); 
     2113 
     2114        if (!ldap_mod_add($this->conn, $dn, $entry)) { 
     2115            $this->_debug("S: ".ldap_error($this->conn)); 
     2116            return false; 
     2117        } 
     2118 
     2119        $this->_debug("S: OK"); 
     2120        return true; 
     2121    } 
     2122 
     2123    /** 
     2124     * Wrapper for ldap_mod_del() 
     2125     */ 
     2126    protected function ldap_mod_del($dn, $entry) 
     2127    { 
     2128        $this->_debug("C: Delete [dn: $dn]: ".print_r($entry, true)); 
     2129 
     2130        if (!ldap_mod_del($this->conn, $dn, $entry)) { 
     2131            $this->_debug("S: ".ldap_error($this->conn)); 
     2132            return false; 
     2133        } 
     2134 
     2135        $this->_debug("S: OK"); 
     2136        return true; 
     2137    } 
     2138 
     2139    /** 
     2140     * Wrapper for ldap_rename() 
     2141     */ 
     2142    protected function ldap_rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true) 
     2143    { 
     2144        $this->_debug("C: Rename [dn: $dn] [dn: $newrdn]"); 
     2145 
     2146        if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) { 
     2147            $this->_debug("S: ".ldap_error($this->conn)); 
     2148            return false; 
     2149        } 
     2150 
     2151        $this->_debug("S: OK"); 
     2152        return true; 
     2153    } 
     2154 
     2155    /** 
     2156     * Wrapper for ldap_list() 
     2157     */ 
     2158    protected function ldap_list($dn, $filter, $attrs) 
     2159    { 
     2160        $list = array(); 
     2161        $this->_debug("C: List [dn: $dn] [{$filter}]"); 
     2162 
     2163        if ($result = ldap_list($this->conn, $dn, $filter, $attrs)) { 
     2164            $list = ldap_get_entries($this->conn, $result); 
     2165 
     2166            if ($list === false) { 
     2167                $this->_debug("S: ".ldap_error($this->conn)); 
     2168                return array(); 
     2169            } 
     2170 
     2171            $count = $list['count']; 
     2172            unset($list['count']); 
     2173 
     2174            $this->_debug("S: $count record(s)"); 
     2175        } 
     2176        else { 
     2177            $this->_debug("S: ".ldap_error($this->conn)); 
     2178        } 
     2179 
     2180        return $list; 
     2181    } 
     2182 
    19842183} 
Note: See TracChangeset for help on using the changeset viewer.