File indexing completed on 2024-12-22 05:36:48
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Ldap 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * @see Zend_Ldap_Converter 0024 */ 0025 // require_once 'Zend/Ldap/Converter.php'; 0026 0027 /** @see Zend_Crypt_Math */ 0028 // require_once 'Zend/Crypt/Math.php'; 0029 0030 /** 0031 * Zend_Ldap_Attribute is a collection of LDAP attribute related functions. 0032 * 0033 * @category Zend 0034 * @package Zend_Ldap 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Ldap_Attribute 0039 { 0040 const PASSWORD_HASH_MD5 = 'md5'; 0041 const PASSWORD_HASH_SMD5 = 'smd5'; 0042 const PASSWORD_HASH_SHA = 'sha'; 0043 const PASSWORD_HASH_SSHA = 'ssha'; 0044 const PASSWORD_UNICODEPWD = 'unicodePwd'; 0045 0046 /** 0047 * Sets a LDAP attribute. 0048 * 0049 * @param array $data 0050 * @param string $attribName 0051 * @param mixed|array|Traversable $value 0052 * @param boolean $append 0053 * @return void 0054 */ 0055 public static function setAttribute(array &$data, $attribName, $value, $append = false) 0056 { 0057 $attribName = strtolower($attribName); 0058 $valArray = array(); 0059 if (is_array($value) || ($value instanceof Traversable)) 0060 { 0061 foreach ($value as $v) 0062 { 0063 $v = self::_valueToLdap($v); 0064 if ($v !== null) $valArray[] = $v; 0065 } 0066 } 0067 else if ($value !== null) 0068 { 0069 $value = self::_valueToLdap($value); 0070 if ($value !== null) $valArray[] = $value; 0071 } 0072 0073 if ($append === true && isset($data[$attribName])) 0074 { 0075 if (is_string($data[$attribName])) $data[$attribName] = array($data[$attribName]); 0076 $data[$attribName] = array_merge($data[$attribName], $valArray); 0077 } 0078 else 0079 { 0080 $data[$attribName] = $valArray; 0081 } 0082 } 0083 0084 /** 0085 * Gets a LDAP attribute. 0086 * 0087 * @param array $data 0088 * @param string $attribName 0089 * @param integer $index 0090 * @return array|mixed 0091 */ 0092 public static function getAttribute(array $data, $attribName, $index = null) 0093 { 0094 $attribName = strtolower($attribName); 0095 if ($index === null) { 0096 if (!isset($data[$attribName])) return array(); 0097 $retArray = array(); 0098 foreach ($data[$attribName] as $v) 0099 { 0100 $retArray[] = self::_valueFromLdap($v); 0101 } 0102 return $retArray; 0103 } else if (is_int($index)) { 0104 if (!isset($data[$attribName])) { 0105 return null; 0106 } else if ($index >= 0 && $index<count($data[$attribName])) { 0107 return self::_valueFromLdap($data[$attribName][$index]); 0108 } else { 0109 return null; 0110 } 0111 } 0112 return null; 0113 } 0114 0115 /** 0116 * Checks if the given value(s) exist in the attribute 0117 * 0118 * @param array $data 0119 * @param string $attribName 0120 * @param mixed|array $value 0121 * @return boolean 0122 */ 0123 public static function attributeHasValue(array &$data, $attribName, $value) 0124 { 0125 $attribName = strtolower($attribName); 0126 if (!isset($data[$attribName])) return false; 0127 0128 if (is_scalar($value)) { 0129 $value = array($value); 0130 } 0131 0132 foreach ($value as $v) { 0133 $v = self::_valueToLdap($v); 0134 if (!in_array($v, $data[$attribName], true)) { 0135 return false; 0136 } 0137 } 0138 return true; 0139 } 0140 0141 /** 0142 * Removes duplicate values from a LDAP attribute 0143 * 0144 * @param array $data 0145 * @param string $attribName 0146 * @return void 0147 */ 0148 public static function removeDuplicatesFromAttribute(array &$data, $attribName) 0149 { 0150 $attribName = strtolower($attribName); 0151 if (!isset($data[$attribName])) return; 0152 $data[$attribName] = array_values(array_unique($data[$attribName])); 0153 } 0154 0155 /** 0156 * Remove given values from a LDAP attribute 0157 * 0158 * @param array $data 0159 * @param string $attribName 0160 * @param mixed|array $value 0161 * @return void 0162 */ 0163 public static function removeFromAttribute(array &$data, $attribName, $value) 0164 { 0165 $attribName = strtolower($attribName); 0166 if (!isset($data[$attribName])) return; 0167 0168 if (is_scalar($value)) { 0169 $value = array($value); 0170 } 0171 0172 $valArray = array(); 0173 foreach ($value as $v) 0174 { 0175 $v = self::_valueToLdap($v); 0176 if ($v !== null) $valArray[] = $v; 0177 } 0178 0179 $resultArray = $data[$attribName]; 0180 foreach ($valArray as $rv) { 0181 $keys = array_keys($resultArray, $rv); 0182 foreach ($keys as $k) { 0183 unset($resultArray[$k]); 0184 } 0185 } 0186 $resultArray = array_values($resultArray); 0187 $data[$attribName] = $resultArray; 0188 } 0189 0190 /** 0191 * @param mixed $value 0192 * @return string|null 0193 */ 0194 private static function _valueToLdap($value) 0195 { 0196 return Zend_Ldap_Converter::toLdap($value); 0197 } 0198 0199 /** 0200 * @param string $value 0201 * @return mixed 0202 */ 0203 private static function _valueFromLdap($value) 0204 { 0205 try { 0206 $return = Zend_Ldap_Converter::fromLdap($value, Zend_Ldap_Converter::STANDARD, false); 0207 if ($return instanceof DateTime) { 0208 return Zend_Ldap_Converter::toLdapDateTime($return, false); 0209 } else { 0210 return $return; 0211 } 0212 } catch (InvalidArgumentException $e) { 0213 return $value; 0214 } 0215 } 0216 0217 /** 0218 * Converts a PHP data type into its LDAP representation 0219 * 0220 * @deprected use Zend_Ldap_Converter instead 0221 * @param mixed $value 0222 * @return string|null - null if the PHP data type cannot be converted. 0223 */ 0224 public static function convertToLdapValue($value) 0225 { 0226 return self::_valueToLdap($value); 0227 } 0228 0229 /** 0230 * Converts an LDAP value into its PHP data type 0231 * 0232 * @deprected use Zend_Ldap_Converter instead 0233 * @param string $value 0234 * @return mixed 0235 */ 0236 public static function convertFromLdapValue($value) 0237 { 0238 return self::_valueFromLdap($value); 0239 } 0240 0241 /** 0242 * Converts a timestamp into its LDAP date/time representation 0243 * 0244 * @param integer $value 0245 * @param boolean $utc 0246 * @return string|null - null if the value cannot be converted. 0247 */ 0248 public static function convertToLdapDateTimeValue($value, $utc = false) 0249 { 0250 return self::_valueToLdapDateTime($value, $utc); 0251 } 0252 0253 /** 0254 * Converts LDAP date/time representation into a timestamp 0255 * 0256 * @param string $value 0257 * @return integer|null - null if the value cannot be converted. 0258 */ 0259 public static function convertFromLdapDateTimeValue($value) 0260 { 0261 return self::_valueFromLdapDateTime($value); 0262 } 0263 0264 /** 0265 * Sets a LDAP password. 0266 * 0267 * @param array $data 0268 * @param string $password 0269 * @param string $hashType 0270 * @param string|null $attribName 0271 * @return null 0272 */ 0273 public static function setPassword(array &$data, $password, $hashType = self::PASSWORD_HASH_MD5, 0274 $attribName = null) 0275 { 0276 if ($attribName === null) { 0277 if ($hashType === self::PASSWORD_UNICODEPWD) { 0278 $attribName = 'unicodePwd'; 0279 } else { 0280 $attribName = 'userPassword'; 0281 } 0282 } 0283 0284 $hash = self::createPassword($password, $hashType); 0285 self::setAttribute($data, $attribName, $hash, false); 0286 } 0287 0288 /** 0289 * Creates a LDAP password. 0290 * 0291 * @param string $password 0292 * @param string $hashType 0293 * @return string 0294 */ 0295 public static function createPassword($password, $hashType = self::PASSWORD_HASH_MD5) 0296 { 0297 switch ($hashType) { 0298 case self::PASSWORD_UNICODEPWD: 0299 /* see: 0300 * http://msdn.microsoft.com/en-us/library/cc223248(PROT.10).aspx 0301 */ 0302 $password = '"' . $password . '"'; 0303 if (function_exists('mb_convert_encoding')) { 0304 $password = mb_convert_encoding($password, 'UTF-16LE', 'UTF-8'); 0305 } else if (function_exists('iconv')) { 0306 $password = iconv('UTF-8', 'UTF-16LE', $password); 0307 } else { 0308 $len = strlen($password); 0309 $new = ''; 0310 for($i=0; $i < $len; $i++) { 0311 $new .= $password[$i] . "\x00"; 0312 } 0313 $password = $new; 0314 } 0315 return $password; 0316 case self::PASSWORD_HASH_SSHA: 0317 $salt = Zend_Crypt_Math::randBytes(4); 0318 $rawHash = sha1($password . $salt, true) . $salt; 0319 $method = '{SSHA}'; 0320 break; 0321 case self::PASSWORD_HASH_SHA: 0322 $rawHash = sha1($password, true); 0323 $method = '{SHA}'; 0324 break; 0325 case self::PASSWORD_HASH_SMD5: 0326 $salt = Zend_Crypt_Math::randBytes(4); 0327 $rawHash = md5($password . $salt, true) . $salt; 0328 $method = '{SMD5}'; 0329 break; 0330 case self::PASSWORD_HASH_MD5: 0331 default: 0332 $rawHash = md5($password, true); 0333 $method = '{MD5}'; 0334 break; 0335 } 0336 return $method . base64_encode($rawHash); 0337 } 0338 0339 /** 0340 * Sets a LDAP date/time attribute. 0341 * 0342 * @param array $data 0343 * @param string $attribName 0344 * @param integer|array|Traversable $value 0345 * @param boolean $utc 0346 * @param boolean $append 0347 * @return null 0348 */ 0349 public static function setDateTimeAttribute(array &$data, $attribName, $value, $utc = false, 0350 $append = false) 0351 { 0352 $convertedValues = array(); 0353 if (is_array($value) || ($value instanceof Traversable)) 0354 { 0355 foreach ($value as $v) { 0356 $v = self::_valueToLdapDateTime($v, $utc); 0357 if ($v !== null) $convertedValues[] = $v; 0358 } 0359 } 0360 else if ($value !== null) { 0361 $value = self::_valueToLdapDateTime($value, $utc); 0362 if ($value !== null) $convertedValues[] = $value; 0363 } 0364 self::setAttribute($data, $attribName, $convertedValues, $append); 0365 } 0366 0367 /** 0368 * @param integer $value 0369 * @param boolean $utc 0370 * @return string|null 0371 */ 0372 private static function _valueToLdapDateTime($value, $utc) 0373 { 0374 if (is_int($value)) { 0375 return Zend_Ldap_Converter::toLdapDateTime($value, $utc); 0376 } 0377 else return null; 0378 } 0379 0380 /** 0381 * Gets a LDAP date/time attribute. 0382 * 0383 * @param array $data 0384 * @param string $attribName 0385 * @param integer $index 0386 * @return array|integer 0387 */ 0388 public static function getDateTimeAttribute(array $data, $attribName, $index = null) 0389 { 0390 $values = self::getAttribute($data, $attribName, $index); 0391 if (is_array($values)) { 0392 for ($i = 0; $i<count($values); $i++) { 0393 $newVal = self::_valueFromLdapDateTime($values[$i]); 0394 if ($newVal !== null) $values[$i] = $newVal; 0395 } 0396 } 0397 else { 0398 $newVal = self::_valueFromLdapDateTime($values); 0399 if ($newVal !== null) $values = $newVal; 0400 } 0401 return $values; 0402 } 0403 0404 /** 0405 * @param string|DateTime $value 0406 * @return integer|null 0407 */ 0408 private static function _valueFromLdapDateTime($value) 0409 { 0410 if ($value instanceof DateTime) { 0411 return $value->format('U'); 0412 } else if (is_string($value)) { 0413 try { 0414 return Zend_Ldap_Converter::fromLdapDateTime($value, false)->format('U'); 0415 } catch (InvalidArgumentException $e) { 0416 return null; 0417 } 0418 } else return null; 0419 } 0420 }