Changeset 13db9ee in github
- Timestamp:
- Mar 29, 2012 7:14:47 AM (14 months ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.8
- Children:
- 48e9c14
- Parents:
- cc46fb2
- Files:
-
- 3 edited
-
CHANGELOG (modified) (1 diff)
-
config/main.inc.php.dist (modified) (1 diff)
-
program/include/rcube_ldap.php (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r0223094 r13db9ee 2 2 =========================== 3 3 4 - Support LDAP RFC2256's country object class read/write (#1488123) 4 5 - Upgraded to jQuery 1.7.2 5 6 - Image resize with GD extension (#1488383) -
config/main.inc.php.dist
r377bc60 r13db9ee 581 581 'required_fields' => array('cn', 'sn', 'mail'), 582 582 '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(), 583 585 // mapping of contact fields to directory attributes 584 586 'fieldmap' => array( -
program/include/rcube_ldap.php
r38dc510 r13db9ee 45 45 protected $prop = array(); 46 46 protected $fieldmap = array(); 47 47 protected $sub_filter; 48 48 protected $filter = ''; 49 49 protected $result = null; … … 137 137 foreach ($this->prop['required_fields'] as $key => $val) 138 138 $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 } 139 153 140 154 $this->sort_col = is_array($p['sort']) ? $p['sort'][0] : $p['sort']; … … 895 909 function get_record($dn, $assoc=false) 896 910 { 897 $res = null; 911 $res = $this->result = null; 912 898 913 if ($this->conn && $dn) 899 914 { … … 902 917 $this->_debug("C: Read [dn: $dn] [(objectclass=*)]"); 903 918 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 { 907 929 $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)) { 915 943 // Add in the dn for the entry. 916 944 $rec['dn'] = $dn; 917 945 $res = $this->_ldap2result($rec); 918 $this->result = new rcube_result_set( 1);946 $this->result = new rcube_result_set(); 919 947 $this->result->add($res); 920 948 } … … 1007 1035 $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn; 1008 1036 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)) { 1014 1049 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1015 1050 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 } 1019 1062 1020 1063 $dn = self::dn_encode($dn); … … 1039 1082 { 1040 1083 $record = $this->get_record($id, true); 1041 $result = $this->get_result(); 1042 $record = $result->first(); 1043 1044 $newdata = array(); 1084 1085 $newdata = array(); 1045 1086 $replacedata = array(); 1046 $deletedata = array(); 1087 $deletedata = array(); 1088 $subdata = array(); 1089 $subdeldata = array(); 1090 $subnewdata = array(); 1047 1091 1048 1092 $ldap_data = $this->_map_data($save_cols); 1049 $old_data = $record['_raw_attrib'];1093 $old_data = $record['_raw_attrib']; 1050 1094 1051 1095 foreach ($this->fieldmap as $col => $fld) { 1052 $val = $ldap_data[$fld];1053 1096 if ($fld) { 1097 $val = $ldap_data[$fld]; 1098 $old = $old_data[$fld]; 1054 1099 // remove empty array values 1055 1100 if (is_array($val)) 1056 1101 $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 } 1057 1122 // The field does exist compare it to the ldap record. 1058 if ($old _data[$fld]!= $val) {1123 if ($old != $val) { 1059 1124 // Changed, but find out how. 1060 if ( !isset($old_data[$fld])) {1125 if ($old === null) { 1061 1126 // Field was not set prior, need to add it. 1062 1127 $newdata[$fld] = $val; … … 1068 1133 $deletedata[$fld] = $old_data[$fld]; 1069 1134 } 1070 } // end elseif1135 } 1071 1136 else { 1072 1137 // The data was modified, save it out. … … 1076 1141 } // end if 1077 1142 } // 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 */ 1079 1155 $dn = self::dn_decode($id); 1080 1156 … … 1082 1158 if (!empty($deletedata)) { 1083 1159 // 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)) { 1087 1161 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1088 1162 return false; 1089 1163 } 1090 $this->_debug("S: OK");1091 1164 } // end if 1092 1165 … … 1105 1178 // Replace the fields. 1106 1179 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'); 1110 1182 return false; 1111 1183 } 1112 $this->_debug("S: OK"); 1113 } // end if 1184 } 1114 1185 } // 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 } 1115 1202 1116 1203 if (!empty($newdata)) { 1117 1204 // 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)) { 1121 1206 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1122 1207 return false; 1123 1208 } 1124 $this->_debug("S: OK");1125 1209 } // end if 1126 1210 1127 1211 // Handle RDN change 1128 1212 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'); 1132 1215 return false; 1133 1216 } 1134 $this->_debug("S: OK");1135 1217 1136 1218 $dn = self::dn_encode($dn); … … 1138 1220 1139 1221 // change the group membership of the contact 1140 if ($this->groups) 1141 { 1222 if ($this->groups) { 1142 1223 $group_ids = $this->get_record_groups($dn); 1143 1224 foreach ($group_ids as $group_id) … … 1148 1229 } 1149 1230 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; 1154 1247 } 1155 1248 … … 1172 1265 foreach ($ids as $id) { 1173 1266 $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 1175 1280 // 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)) { 1179 1282 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1180 1283 return false; 1181 } // end if 1182 $this->_debug("S: OK"); 1284 } 1183 1285 1184 1286 // remove contact from all groups where he was member … … 1272 1374 break; 1273 1375 } 1274 1376 1275 1377 return $function; 1276 1378 } … … 1375 1477 } 1376 1478 } 1377 1479 1378 1480 return $ldap_data; 1379 1481 } … … 1624 1726 ); 1625 1727 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)) { 1632 1729 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1633 1730 return false; 1634 1731 } 1635 1732 1636 $this->_debug("S: OK");1637 1733 $this->cache->remove('groups'); 1638 1734 … … 1655 1751 $del_dn = "cn=$group_name,$base_dn"; 1656 1752 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)) { 1663 1754 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1664 1755 return false; 1665 1756 } 1666 1757 1667 $this->_debug("S: OK");1668 1758 $this->cache->remove('groups'); 1669 1759 … … 1690 1780 $new_gid = self::dn_encode($new_name); 1691 1781 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)) { 1698 1783 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1699 1784 return false; 1700 1785 } 1701 1786 1702 $this->_debug("S: OK");1703 1787 $this->cache->remove('groups'); 1704 1788 … … 1730 1814 $new_attrs[$member_attr][] = self::dn_decode($id); 1731 1815 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)) { 1738 1817 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1739 1818 return 0; 1740 1819 } 1741 1820 1742 $this->_debug("S: OK");1743 1821 $this->cache->remove('groups'); 1744 1822 … … 1767 1845 $del_attrs[$member_attr][] = self::dn_decode($id); 1768 1846 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)) { 1775 1848 $this->set_error(self::ERROR_SAVING, 'errorsaving'); 1776 1849 return 0; 1777 1850 } 1778 1851 1779 $this->_debug("S: OK");1780 1852 $this->cache->remove('groups'); 1781 1853 … … 1982 2054 return base64_decode($str); 1983 2055 } 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 1984 2183 }
Note: See TracChangeset
for help on using the changeset viewer.
