web/lib/Zend/Ldap/Attribute.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Ldap
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: Attribute.php 22996 2010-09-22 17:01:46Z sgehrig $
       
    20  */
       
    21 
       
    22 /**
       
    23  * @see Zend_Ldap_Converter
       
    24  */
       
    25 require_once 'Zend/Ldap/Converter.php';
       
    26 
       
    27 /**
       
    28  * Zend_Ldap_Attribute is a collection of LDAP attribute related functions.
       
    29  *
       
    30  * @category   Zend
       
    31  * @package    Zend_Ldap
       
    32  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    33  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    34  */
       
    35 class Zend_Ldap_Attribute
       
    36 {
       
    37     const PASSWORD_HASH_MD5   = 'md5';
       
    38     const PASSWORD_HASH_SMD5  = 'smd5';
       
    39     const PASSWORD_HASH_SHA   = 'sha';
       
    40     const PASSWORD_HASH_SSHA  = 'ssha';
       
    41     const PASSWORD_UNICODEPWD = 'unicodePwd';
       
    42 
       
    43     /**
       
    44      * Sets a LDAP attribute.
       
    45      *
       
    46      * @param  array                    $data
       
    47      * @param  string                   $attribName
       
    48      * @param  scalar|array|Traversable $value
       
    49      * @param  boolean                  $append
       
    50      * @return void
       
    51      */
       
    52     public static function setAttribute(array &$data, $attribName, $value, $append = false)
       
    53     {
       
    54         $attribName = strtolower($attribName);
       
    55         $valArray = array();
       
    56         if (is_array($value) || ($value instanceof Traversable))
       
    57         {
       
    58             foreach ($value as $v)
       
    59             {
       
    60                 $v = self::_valueToLdap($v);
       
    61                 if ($v !== null) $valArray[] = $v;
       
    62             }
       
    63         }
       
    64         else if ($value !== null)
       
    65         {
       
    66             $value = self::_valueToLdap($value);
       
    67             if ($value !== null) $valArray[] = $value;
       
    68         }
       
    69 
       
    70         if ($append === true && isset($data[$attribName]))
       
    71         {
       
    72             if (is_string($data[$attribName])) $data[$attribName] = array($data[$attribName]);
       
    73             $data[$attribName] = array_merge($data[$attribName], $valArray);
       
    74         }
       
    75         else
       
    76         {
       
    77             $data[$attribName] = $valArray;
       
    78         }
       
    79     }
       
    80 
       
    81     /**
       
    82      * Gets a LDAP attribute.
       
    83      *
       
    84      * @param  array   $data
       
    85      * @param  string  $attribName
       
    86      * @param  integer $index
       
    87      * @return array|mixed
       
    88      */
       
    89     public static function getAttribute(array $data, $attribName, $index = null)
       
    90     {
       
    91         $attribName = strtolower($attribName);
       
    92         if ($index === null) {
       
    93             if (!isset($data[$attribName])) return array();
       
    94             $retArray = array();
       
    95             foreach ($data[$attribName] as $v)
       
    96             {
       
    97                 $retArray[] = self::_valueFromLdap($v);
       
    98             }
       
    99             return $retArray;
       
   100         } else if (is_int($index)) {
       
   101             if (!isset($data[$attribName])) {
       
   102                 return null;
       
   103             } else if ($index >= 0 && $index<count($data[$attribName])) {
       
   104                 return self::_valueFromLdap($data[$attribName][$index]);
       
   105             } else {
       
   106                 return null;
       
   107             }
       
   108         }
       
   109         return null;
       
   110     }
       
   111 
       
   112     /**
       
   113      * Checks if the given value(s) exist in the attribute
       
   114      *
       
   115      * @param array       $data
       
   116      * @param string      $attribName
       
   117      * @param mixed|array $value
       
   118      * @return boolean
       
   119      */
       
   120     public static function attributeHasValue(array &$data, $attribName, $value)
       
   121     {
       
   122         $attribName = strtolower($attribName);
       
   123         if (!isset($data[$attribName])) return false;
       
   124 
       
   125         if (is_scalar($value)) {
       
   126             $value = array($value);
       
   127         }
       
   128 
       
   129         foreach ($value as $v) {
       
   130             $v = self::_valueToLdap($v);
       
   131             if (!in_array($v, $data[$attribName], true)) {
       
   132                 return false;
       
   133             }
       
   134         }
       
   135         return true;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Removes duplicate values from a LDAP attribute
       
   140      *
       
   141      * @param array  $data
       
   142      * @param string $attribName
       
   143      * @return void
       
   144      */
       
   145     public static function removeDuplicatesFromAttribute(array &$data, $attribName)
       
   146     {
       
   147         $attribName = strtolower($attribName);
       
   148         if (!isset($data[$attribName])) return;
       
   149         $data[$attribName] = array_values(array_unique($data[$attribName]));
       
   150     }
       
   151 
       
   152     /**
       
   153      * Remove given values from a LDAP attribute
       
   154      *
       
   155      * @param array       $data
       
   156      * @param string      $attribName
       
   157      * @param mixed|array $value
       
   158      * @return void
       
   159      */
       
   160     public static function removeFromAttribute(array &$data, $attribName, $value)
       
   161     {
       
   162         $attribName = strtolower($attribName);
       
   163         if (!isset($data[$attribName])) return;
       
   164 
       
   165         if (is_scalar($value)) {
       
   166             $value = array($value);
       
   167         }
       
   168 
       
   169         $valArray = array();
       
   170         foreach ($value as $v)
       
   171         {
       
   172             $v = self::_valueToLdap($v);
       
   173             if ($v !== null) $valArray[] = $v;
       
   174         }
       
   175 
       
   176         $resultArray = $data[$attribName];
       
   177         foreach ($valArray as $rv) {
       
   178             $keys = array_keys($resultArray, $rv);
       
   179             foreach ($keys as $k) {
       
   180                 unset($resultArray[$k]);
       
   181             }
       
   182         }
       
   183         $resultArray = array_values($resultArray);
       
   184         $data[$attribName] = $resultArray;
       
   185     }
       
   186 
       
   187     /**
       
   188      * @param  mixed $value
       
   189      * @return string|null
       
   190      */
       
   191     private static function _valueToLdap($value)
       
   192     {
       
   193         return Zend_Ldap_Converter::toLdap($value);
       
   194     }
       
   195 
       
   196     /**
       
   197      * @param  string $value
       
   198      * @return mixed
       
   199      */
       
   200     private static function _valueFromLdap($value)
       
   201     {
       
   202         try {
       
   203             $return = Zend_Ldap_Converter::fromLdap($value, Zend_Ldap_Converter::STANDARD, false);
       
   204             if ($return instanceof DateTime) {
       
   205                 return Zend_Ldap_Converter::toLdapDateTime($return, false);
       
   206             } else {
       
   207                 return $return;
       
   208             }
       
   209         } catch (InvalidArgumentException $e) {
       
   210             return $value;
       
   211         }
       
   212     }
       
   213 
       
   214     /**
       
   215      * Converts a PHP data type into its LDAP representation
       
   216      *
       
   217      * @deprected	use Zend_Ldap_Converter instead
       
   218      * @param  		mixed $value
       
   219      * @return 		string|null - null if the PHP data type cannot be converted.
       
   220      */
       
   221     public static function convertToLdapValue($value)
       
   222     {
       
   223         return self::_valueToLdap($value);
       
   224     }
       
   225 
       
   226     /**
       
   227      * Converts an LDAP value into its PHP data type
       
   228      *
       
   229      * @deprected	use Zend_Ldap_Converter instead
       
   230      * @param  		string $value
       
   231      * @return 		mixed
       
   232      */
       
   233     public static function convertFromLdapValue($value)
       
   234     {
       
   235         return self::_valueFromLdap($value);
       
   236     }
       
   237 
       
   238     /**
       
   239      * Converts a timestamp into its LDAP date/time representation
       
   240      *
       
   241      * @param  integer $value
       
   242      * @param  boolean $utc
       
   243      * @return string|null - null if the value cannot be converted.
       
   244      */
       
   245     public static function convertToLdapDateTimeValue($value, $utc = false)
       
   246     {
       
   247         return self::_valueToLdapDateTime($value, $utc);
       
   248     }
       
   249 
       
   250     /**
       
   251      * Converts LDAP date/time representation into a timestamp
       
   252      *
       
   253      * @param  string $value
       
   254      * @return integer|null - null if the value cannot be converted.
       
   255      */
       
   256     public static function convertFromLdapDateTimeValue($value)
       
   257     {
       
   258         return self::_valueFromLdapDateTime($value);
       
   259     }
       
   260 
       
   261     /**
       
   262      * Sets a LDAP password.
       
   263      *
       
   264      * @param  array       $data
       
   265      * @param  string      $password
       
   266      * @param  string      $hashType
       
   267      * @param  string|null $attribName
       
   268      * @return null
       
   269      */
       
   270     public static function setPassword(array &$data, $password, $hashType = self::PASSWORD_HASH_MD5,
       
   271         $attribName = null)
       
   272     {
       
   273         if ($attribName === null) {
       
   274             if ($hashType === self::PASSWORD_UNICODEPWD) {
       
   275                 $attribName = 'unicodePwd';
       
   276             } else {
       
   277                 $attribName = 'userPassword';
       
   278             }
       
   279         }
       
   280 
       
   281         $hash = self::createPassword($password, $hashType);
       
   282         self::setAttribute($data, $attribName, $hash, false);
       
   283     }
       
   284 
       
   285     /**
       
   286      * Creates a LDAP password.
       
   287      *
       
   288      * @param  string $password
       
   289      * @param  string $hashType
       
   290      * @return string
       
   291      */
       
   292     public static function createPassword($password, $hashType = self::PASSWORD_HASH_MD5)
       
   293     {
       
   294         switch ($hashType) {
       
   295             case self::PASSWORD_UNICODEPWD:
       
   296                 /* see:
       
   297                  * http://msdn.microsoft.com/en-us/library/cc223248(PROT.10).aspx
       
   298                  */
       
   299                 $password = '"' . $password . '"';
       
   300                 if (function_exists('mb_convert_encoding')) {
       
   301                     $password = mb_convert_encoding($password, 'UTF-16LE', 'UTF-8');
       
   302                 } else if (function_exists('iconv')) {
       
   303                     $password = iconv('UTF-8', 'UTF-16LE', $password);
       
   304                 } else {
       
   305                     $len = strlen($password);
       
   306                     $new = '';
       
   307                     for($i=0; $i < $len; $i++) {
       
   308                         $new .= $password[$i] . "\x00";
       
   309                     }
       
   310                     $password = $new;
       
   311                 }
       
   312                 return $password;
       
   313             case self::PASSWORD_HASH_SSHA:
       
   314                 $salt    = substr(sha1(uniqid(mt_rand(), true), true), 0, 4);
       
   315                 $rawHash = sha1($password . $salt, true) . $salt;
       
   316                 $method  = '{SSHA}';
       
   317                 break;
       
   318             case self::PASSWORD_HASH_SHA:
       
   319                 $rawHash = sha1($password, true);
       
   320                 $method  = '{SHA}';
       
   321                 break;
       
   322             case self::PASSWORD_HASH_SMD5:
       
   323                 $salt    = substr(sha1(uniqid(mt_rand(), true), true), 0, 4);
       
   324                 $rawHash = md5($password . $salt, true) . $salt;
       
   325                 $method  = '{SMD5}';
       
   326                 break;
       
   327             case self::PASSWORD_HASH_MD5:
       
   328             default:
       
   329                 $rawHash = md5($password, true);
       
   330                 $method  = '{MD5}';
       
   331                 break;
       
   332         }
       
   333         return $method . base64_encode($rawHash);
       
   334     }
       
   335 
       
   336     /**
       
   337      * Sets a LDAP date/time attribute.
       
   338      *
       
   339      * @param  array                     $data
       
   340      * @param  string                    $attribName
       
   341      * @param  integer|array|Traversable $value
       
   342      * @param  boolean                   $utc
       
   343      * @param  boolean                   $append
       
   344      * @return null
       
   345      */
       
   346     public static function setDateTimeAttribute(array &$data, $attribName, $value, $utc = false,
       
   347         $append = false)
       
   348     {
       
   349         $convertedValues = array();
       
   350         if (is_array($value) || ($value instanceof Traversable))
       
   351         {
       
   352             foreach ($value as $v) {
       
   353                 $v = self::_valueToLdapDateTime($v, $utc);
       
   354                 if ($v !== null) $convertedValues[] = $v;
       
   355             }
       
   356         }
       
   357         else if ($value !== null) {
       
   358             $value = self::_valueToLdapDateTime($value, $utc);
       
   359             if ($value !== null) $convertedValues[] = $value;
       
   360         }
       
   361         self::setAttribute($data, $attribName, $convertedValues, $append);
       
   362     }
       
   363 
       
   364     /**
       
   365      * @param  integer $value
       
   366      * @param  boolean $utc
       
   367      * @return string|null
       
   368      */
       
   369     private static function _valueToLdapDateTime($value, $utc)
       
   370     {
       
   371         if (is_int($value)) {
       
   372             return Zend_Ldap_Converter::toLdapDateTime($value, $utc);
       
   373         }
       
   374         else return null;
       
   375     }
       
   376 
       
   377     /**
       
   378      * Gets a LDAP date/time attribute.
       
   379      *
       
   380      * @param  array   $data
       
   381      * @param  string  $attribName
       
   382      * @param  integer $index
       
   383      * @return array|integer
       
   384      */
       
   385     public static function getDateTimeAttribute(array $data, $attribName, $index = null)
       
   386     {
       
   387         $values = self::getAttribute($data, $attribName, $index);
       
   388         if (is_array($values)) {
       
   389             for ($i = 0; $i<count($values); $i++) {
       
   390                 $newVal = self::_valueFromLdapDateTime($values[$i]);
       
   391                 if ($newVal !== null) $values[$i] = $newVal;
       
   392             }
       
   393         }
       
   394         else {
       
   395 			$newVal = self::_valueFromLdapDateTime($values);
       
   396 			if ($newVal !== null) $values = $newVal;
       
   397 		}
       
   398         return $values;
       
   399     }
       
   400 
       
   401     /**
       
   402      * @param  string|DateTime $value
       
   403      * @return integer|null
       
   404      */
       
   405     private static function _valueFromLdapDateTime($value)
       
   406     {
       
   407         if ($value instanceof DateTime) {
       
   408             return $value->format('U');
       
   409         } else if (is_string($value)) {
       
   410             try {
       
   411                 return Zend_Ldap_Converter::fromLdapDateTime($value, false)->format('U');
       
   412             } catch (InvalidArgumentException $e) {
       
   413                 return null;
       
   414             }
       
   415         } else return null;
       
   416     }
       
   417 }