• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List

E:/E/GEAMP/www/openbiz/openbiz/others/Zend/Ldap.php

00001 <?php
00002 
00029 class Zend_Ldap
00030 {
00031     const SEARCH_SCOPE_SUB  = 1;
00032     const SEARCH_SCOPE_ONE  = 2;
00033     const SEARCH_SCOPE_BASE = 3;
00034 
00035     const ACCTNAME_FORM_DN        = 1;
00036     const ACCTNAME_FORM_USERNAME  = 2;
00037     const ACCTNAME_FORM_BACKSLASH = 3;
00038     const ACCTNAME_FORM_PRINCIPAL = 4;
00039 
00045     private $_connectString;
00046 
00052     protected $_options = null;
00053 
00059     protected $_resource = null;
00060 
00066     protected $_rootDse = null;
00067 
00073     protected $_schema = null;
00074 
00080     public static function filterEscape($str)
00081     {
00085         require_once 'Zend/Ldap/Filter/Abstract.php';
00086         return Zend_Ldap_Filter_Abstract::escapeValue($str);
00087     }
00088 
00097     public static function explodeDn($dn, array &$keys = null, array &$vals = null)
00098     {
00102         require_once 'Zend/Ldap/Dn.php';
00103         return Zend_Ldap_Dn::checkDn($dn, $keys, $vals);
00104     }
00105 
00112     public function __construct($options = array())
00113     {
00114         $this->setOptions($options);
00115     }
00116 
00122     public function __destruct()
00123     {
00124         $this->disconnect();
00125     }
00126 
00130     public function getResource()
00131     {
00132         return $this->_resource;
00133     }
00134 
00140     public function getLastErrorCode()
00141     {
00142         $ret = @ldap_get_option($this->getResource(), LDAP_OPT_ERROR_NUMBER, $err);
00143         if ($ret === true) {
00144             if ($err <= -1 && $err >= -17) {
00148                 require_once 'Zend/Ldap/Exception.php';
00149                 /* For some reason draft-ietf-ldapext-ldap-c-api-xx.txt error
00150                  * codes in OpenLDAP are negative values from -1 to -17.
00151                  */
00152                 $err = Zend_Ldap_Exception::LDAP_SERVER_DOWN + (-$err - 1);
00153             }
00154             return $err;
00155         }
00156         return 0;
00157     }
00158 
00166     public function getLastError(&$errorCode = null, array &$errorMessages = null)
00167     {
00168         $errorCode = $this->getLastErrorCode();
00169         $errorMessages = array();
00170 
00171         /* The various error retrieval functions can return
00172          * different things so we just try to collect what we
00173          * can and eliminate dupes.
00174          */
00175         $estr1 = @ldap_error($this->getResource());
00176         if ($errorCode !== 0 && $estr1 === 'Success') {
00177             $estr1 = @ldap_err2str($errorCode);
00178         }
00179         if (!empty($estr1)) {
00180             $errorMessages[] = $estr1;
00181         }
00182 
00183         @ldap_get_option($this->getResource(), LDAP_OPT_ERROR_STRING, $estr2);
00184         if (!empty($estr2) && !in_array($estr2, $errorMessages)) {
00185             $errorMessages[] = $estr2;
00186         }
00187 
00188         $message = '';
00189         if ($errorCode > 0) {
00190             $message = '0x' . dechex($errorCode) . ' ';
00191         } else {
00192             $message = '';
00193         }
00194         if (count($errorMessages) > 0) {
00195             $message .= '(' . implode('; ', $errorMessages) . ')';
00196         } else {
00197             $message .= '(no error message from LDAP)';
00198         }
00199         return $message;
00200     }
00201 
00226     public function setOptions($options)
00227     {
00228         if ($options instanceof Zend_Config) {
00229             $options = $options->toArray();
00230         }
00231 
00232         $permittedOptions = array(
00233             'host'                   => null,
00234             'port'                   => 0,
00235             'useSsl'                 => false,
00236             'username'               => null,
00237             'password'               => null,
00238             'bindRequiresDn'         => false,
00239             'baseDn'                 => null,
00240             'accountCanonicalForm'   => null,
00241             'accountDomainName'      => null,
00242             'accountDomainNameShort' => null,
00243             'accountFilterFormat'    => null,
00244             'allowEmptyPassword'     => false,
00245             'useStartTls'            => false,
00246             'optReferrals'           => false,
00247             'tryUsernameSplit'       => true,
00248         );
00249 
00250         foreach ($permittedOptions as $key => $val) {
00251             if (array_key_exists($key, $options)) {
00252                 $val = $options[$key];
00253                 unset($options[$key]);
00254                 /* Enforce typing. This eliminates issues like Zend_Config_Ini
00255                  * returning '1' as a string (ZF-3163).
00256                  */
00257                 switch ($key) {
00258                     case 'port':
00259                     case 'accountCanonicalForm':
00260                         $permittedOptions[$key] = (int)$val;
00261                         break;
00262                     case 'useSsl':
00263                     case 'bindRequiresDn':
00264                     case 'allowEmptyPassword':
00265                     case 'useStartTls':
00266                     case 'optReferrals':
00267                     case 'tryUsernameSplit':
00268                         $permittedOptions[$key] = ($val === true ||
00269                                 $val === '1' || strcasecmp($val, 'true') == 0);
00270                         break;
00271                     default:
00272                         $permittedOptions[$key] = trim($val);
00273                         break;
00274                 }
00275             }
00276         }
00277         if (count($options) > 0) {
00278             $key = key($options);
00282             require_once 'Zend/Ldap/Exception.php';
00283             throw new Zend_Ldap_Exception(null, "Unknown Zend_Ldap option: $key");
00284         }
00285         $this->_options = $permittedOptions;
00286         return $this;
00287     }
00288 
00292     public function getOptions()
00293     {
00294         return $this->_options;
00295     }
00296 
00300     protected function _getHost()
00301     {
00302         return $this->_options['host'];
00303     }
00304 
00308     protected function _getPort()
00309     {
00310         return $this->_options['port'];
00311     }
00312 
00316     protected function _getUseSsl()
00317     {
00318         return $this->_options['useSsl'];
00319     }
00320 
00324     protected function _getUsername()
00325     {
00326         return $this->_options['username'];
00327     }
00328 
00332     protected function _getPassword()
00333     {
00334         return $this->_options['password'];
00335     }
00336 
00340     protected function _getBindRequiresDn()
00341     {
00342         return $this->_options['bindRequiresDn'];
00343     }
00344 
00350     public function getBaseDn()
00351     {
00352         return $this->_options['baseDn'];
00353     }
00354 
00359     protected function _getAccountCanonicalForm()
00360     {
00361         /* Account names should always be qualified with a domain. In some scenarios
00362          * using non-qualified account names can lead to security vulnerabilities. If
00363          * no account canonical form is specified, we guess based in what domain
00364          * names have been supplied.
00365          */
00366 
00367         $accountCanonicalForm = $this->_options['accountCanonicalForm'];
00368         if (!$accountCanonicalForm) {
00369             $accountDomainName = $this->_getAccountDomainName();
00370             $accountDomainNameShort = $this->_getAccountDomainNameShort();
00371             if ($accountDomainNameShort) {
00372                 $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_BACKSLASH;
00373             } else if ($accountDomainName) {
00374                 $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_PRINCIPAL;
00375             } else {
00376                 $accountCanonicalForm = Zend_Ldap::ACCTNAME_FORM_USERNAME;
00377             }
00378         }
00379 
00380         return $accountCanonicalForm;
00381     }
00382 
00386     protected function _getAccountDomainName()
00387     {
00388         return $this->_options['accountDomainName'];
00389     }
00390 
00394     protected function _getAccountDomainNameShort()
00395     {
00396         return $this->_options['accountDomainNameShort'];
00397     }
00398 
00403     protected function _getAccountFilterFormat()
00404     {
00405         return $this->_options['accountFilterFormat'];
00406     }
00407 
00411     protected function _getAllowEmptyPassword()
00412     {
00413         return $this->_options['allowEmptyPassword'];
00414     }
00415 
00419     protected function _getUseStartTls()
00420     {
00421         return $this->_options['useStartTls'];
00422     }
00423 
00427     protected function _getOptReferrals()
00428     {
00429         return $this->_options['optReferrals'];
00430     }
00431 
00435     protected function _getTryUsernameSplit()
00436     {
00437         return $this->_options['tryUsernameSplit'];
00438     }
00439 
00443     protected function _getAccountFilter($acctname)
00444     {
00448         require_once 'Zend/Ldap/Filter/Abstract.php';
00449         $this->_splitName($acctname, $dname, $aname);
00450         $accountFilterFormat = $this->_getAccountFilterFormat();
00451         $aname = Zend_Ldap_Filter_Abstract::escapeValue($aname);
00452         if ($accountFilterFormat) {
00453             return sprintf($accountFilterFormat, $aname);
00454         }
00455         if (!$this->_getBindRequiresDn()) {
00456             // is there a better way to detect this?
00457             return sprintf("(&(objectClass=user)(sAMAccountName=%s))", $aname);
00458         }
00459         return sprintf("(&(objectClass=posixAccount)(uid=%s))", $aname);
00460     }
00461 
00468     protected function _splitName($name, &$dname, &$aname)
00469     {
00470         $dname = null;
00471         $aname = $name;
00472 
00473         if (!$this->_getTryUsernameSplit()) {
00474             return;
00475         }
00476 
00477         $pos = strpos($name, '@');
00478         if ($pos) {
00479             $dname = substr($name, $pos + 1);
00480             $aname = substr($name, 0, $pos);
00481         } else {
00482             $pos = strpos($name, '\\');
00483             if ($pos) {
00484                 $dname = substr($name, 0, $pos);
00485                 $aname = substr($name, $pos + 1);
00486             }
00487         }
00488     }
00489 
00495     protected function _getAccountDn($acctname)
00496     {
00500         require_once 'Zend/Ldap/Dn.php';
00501         if (Zend_Ldap_Dn::checkDn($acctname)) return $acctname;
00502         $acctname = $this->getCanonicalAccountName($acctname, Zend_Ldap::ACCTNAME_FORM_USERNAME);
00503         $acct = $this->_getAccount($acctname, array('dn'));
00504         return $acct['dn'];
00505     }
00506 
00511     protected function _isPossibleAuthority($dname)
00512     {
00513         if ($dname === null) {
00514             return true;
00515         }
00516         $accountDomainName = $this->_getAccountDomainName();
00517         $accountDomainNameShort = $this->_getAccountDomainNameShort();
00518         if ($accountDomainName === null && $accountDomainNameShort === null) {
00519             return true;
00520         }
00521         if (strcasecmp($dname, $accountDomainName) == 0) {
00522             return true;
00523         }
00524         if (strcasecmp($dname, $accountDomainNameShort) == 0) {
00525             return true;
00526         }
00527         return false;
00528     }
00529 
00536     public function getCanonicalAccountName($acctname, $form = 0)
00537     {
00538         $this->_splitName($acctname, $dname, $uname);
00539 
00540         if (!$this->_isPossibleAuthority($dname)) {
00544             require_once 'Zend/Ldap/Exception.php';
00545             throw new Zend_Ldap_Exception(null,
00546                 "Binding domain is not an authority for user: $acctname",
00547                 Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH);
00548         }
00549 
00550         if (!$uname) {
00554             require_once 'Zend/Ldap/Exception.php';
00555             throw new Zend_Ldap_Exception(null, "Invalid account name syntax: $acctname");
00556         }
00557 
00558         if (function_exists('mb_strtolower')) {
00559             $uname = mb_strtolower($uname, 'UTF-8');
00560         } else {
00561             $uname = strtolower($uname);
00562         }
00563 
00564         if ($form === 0) {
00565             $form = $this->_getAccountCanonicalForm();
00566         }
00567 
00568         switch ($form) {
00569             case Zend_Ldap::ACCTNAME_FORM_DN:
00570                 return $this->_getAccountDn($acctname);
00571             case Zend_Ldap::ACCTNAME_FORM_USERNAME:
00572                 return $uname;
00573             case Zend_Ldap::ACCTNAME_FORM_BACKSLASH:
00574                 $accountDomainNameShort = $this->_getAccountDomainNameShort();
00575                 if (!$accountDomainNameShort) {
00579                     require_once 'Zend/Ldap/Exception.php';
00580                     throw new Zend_Ldap_Exception(null, 'Option required: accountDomainNameShort');
00581                 }
00582                 return "$accountDomainNameShort\\$uname";
00583             case Zend_Ldap::ACCTNAME_FORM_PRINCIPAL:
00584                 $accountDomainName = $this->_getAccountDomainName();
00585                 if (!$accountDomainName) {
00589                     require_once 'Zend/Ldap/Exception.php';
00590                     throw new Zend_Ldap_Exception(null, 'Option required: accountDomainName');
00591                 }
00592                 return "$uname@$accountDomainName";
00593             default:
00597                 require_once 'Zend/Ldap/Exception.php';
00598                 throw new Zend_Ldap_Exception(null, "Unknown canonical name form: $form");
00599         }
00600     }
00601 
00607     protected function _getAccount($acctname, array $attrs = null)
00608     {
00609         $baseDn = $this->getBaseDn();
00610         if (!$baseDn) {
00614             require_once 'Zend/Ldap/Exception.php';
00615             throw new Zend_Ldap_Exception(null, 'Base DN not set');
00616         }
00617 
00618         $accountFilter = $this->_getAccountFilter($acctname);
00619         if (!$accountFilter) {
00623             require_once 'Zend/Ldap/Exception.php';
00624             throw new Zend_Ldap_Exception(null, 'Invalid account filter');
00625         }
00626 
00627         if (!is_resource($this->getResource())) {
00628             $this->bind();
00629         }
00630 
00631         $accounts = $this->search($accountFilter, $baseDn, self::SEARCH_SCOPE_SUB, $attrs);
00632         $count = $accounts->count();
00633         if ($count === 1) {
00634             $acct = $accounts->getFirst();
00635             $accounts->close();
00636             return $acct;
00637         } else if ($count === 0) {
00641             require_once 'Zend/Ldap/Exception.php';
00642             $code = Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT;
00643             $str = "No object found for: $accountFilter";
00644         } else {
00648             require_once 'Zend/Ldap/Exception.php';
00649             $code = Zend_Ldap_Exception::LDAP_OPERATIONS_ERROR;
00650             $str = "Unexpected result count ($count) for: $accountFilter";
00651         }
00652         $accounts->close();
00656         require_once 'Zend/Ldap/Exception.php';
00657         throw new Zend_Ldap_Exception($this, $str, $code);
00658     }
00659 
00663     public function disconnect()
00664     {
00665         if (is_resource($this->getResource())) {
00666             if (!extension_loaded('ldap')) {
00670                 require_once 'Zend/Ldap/Exception.php';
00671                 throw new Zend_Ldap_Exception(null, 'LDAP extension not loaded',
00672                     Zend_Ldap_Exception::LDAP_X_EXTENSION_NOT_LOADED);
00673             }
00674             @ldap_unbind($this->getResource());
00675         }
00676         $this->_resource = null;
00677         return $this;
00678     }
00679 
00688     public function connect($host = null, $port = null, $useSsl = null, $useStartTls = null)
00689     {
00690         if ($host === null) {
00691             $host = $this->_getHost();
00692         }
00693         if ($port === null) {
00694             $port = $this->_getPort();
00695         } else {
00696             $port = (int)$port;
00697         }
00698         if ($useSsl === null) {
00699             $useSsl = $this->_getUseSsl();
00700         } else {
00701             $useSsl = (bool)$useSsl;
00702         }
00703         if ($useStartTls === null) {
00704             $useStartTls = $this->_getUseStartTls();
00705         } else {
00706             $useStartTls = (bool)$useStartTls;
00707         }
00708 
00709         if (!$host) {
00713             require_once 'Zend/Ldap/Exception.php';
00714             throw new Zend_Ldap_Exception(null, 'A host parameter is required');
00715         }
00716 
00717         /* To connect using SSL it seems the client tries to verify the server
00718          * certificate by default. One way to disable this behavior is to set
00719          * 'TLS_REQCERT never' in OpenLDAP's ldap.conf and restarting Apache. Or,
00720          * if you really care about the server's cert you can put a cert on the
00721          * web server.
00722          */
00723         $url = ($useSsl) ? "ldaps://$host" : "ldap://$host";
00724         if ($port) {
00725             $url .= ":$port";
00726         }
00727 
00728         /* Because ldap_connect doesn't really try to connect, any connect error
00729          * will actually occur during the ldap_bind call. Therefore, we save the
00730          * connect string here for reporting it in error handling in bind().
00731          */
00732         $this->_connectString = $url;
00733 
00734         $this->disconnect();
00735 
00736         if (!extension_loaded('ldap')) {
00740             require_once 'Zend/Ldap/Exception.php';
00741             throw new Zend_Ldap_Exception(null, 'LDAP extension not loaded',
00742                 Zend_Ldap_Exception::LDAP_X_EXTENSION_NOT_LOADED);
00743         }
00744 
00745         /* Only OpenLDAP 2.2 + supports URLs so if SSL is not requested, just
00746          * use the old form.
00747          */
00748         $resource = ($useSsl) ? @ldap_connect($url) : @ldap_connect($host, $port);
00749 
00750         if (is_resource($resource) === true) {
00751             $this->_resource = $resource;
00752 
00753             $optReferrals = ($this->_getOptReferrals()) ? 1 : 0;
00754             if (@ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3) &&
00755                         @ldap_set_option($resource, LDAP_OPT_REFERRALS, $optReferrals)) {
00756                 if ($useSsl || !$useStartTls || @ldap_start_tls($resource)) {
00757                     return $this;
00758                 }
00759             }
00760 
00764             require_once 'Zend/Ldap/Exception.php';
00765             $zle = new Zend_Ldap_Exception($this, "$host:$port");
00766             $this->disconnect();
00767             throw $zle;
00768         }
00772         require_once 'Zend/Ldap/Exception.php';
00773         throw new Zend_Ldap_Exception(null, "Failed to connect to LDAP server: $host:$port");
00774     }
00775 
00782     public function bind($username = null, $password = null)
00783     {
00784         $moreCreds = true;
00785 
00786         if ($username === null) {
00787             $username = $this->_getUsername();
00788             $password = $this->_getPassword();
00789             $moreCreds = false;
00790         }
00791 
00792         if ($username === null) {
00793             /* Perform anonymous bind
00794              */
00795             $password = null;
00796         } else {
00797             /* Check to make sure the username is in DN form.
00798              */
00802             require_once 'Zend/Ldap/Dn.php';
00803             if (!Zend_Ldap_Dn::checkDn($username)) {
00804                 if ($this->_getBindRequiresDn()) {
00805                     /* moreCreds stops an infinite loop if _getUsername does not
00806                      * return a DN and the bind requires it
00807                      */
00808                     if ($moreCreds) {
00809                         try {
00810                             $username = $this->_getAccountDn($username);
00811                         } catch (Zend_Ldap_Exception $zle) {
00812                             switch ($zle->getCode()) {
00813                                 case Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT:
00814                                 case Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH:
00815                                 case Zend_Ldap_Exception::LDAP_X_EXTENSION_NOT_LOADED:
00816                                     throw $zle;
00817                             }
00818                             throw new Zend_Ldap_Exception(null,
00819                                 'Failed to retrieve DN for account: ' . $username .
00820                                 ' [' . $zle->getMessage() . ']',
00821                                 Zend_Ldap_Exception::LDAP_OPERATIONS_ERROR);
00822                         }
00823                     } else {
00827                         require_once 'Zend/Ldap/Exception.php';
00828                         throw new Zend_Ldap_Exception(null, 'Binding requires username in DN form');
00829                     }
00830                 } else {
00831                     $username = $this->getCanonicalAccountName($username,
00832                         $this->_getAccountCanonicalForm());
00833                 }
00834             }
00835         }
00836 
00837         if (!is_resource($this->getResource())) {
00838             $this->connect();
00839         }
00840 
00841         if ($username !== null && $password === '' && $this->_getAllowEmptyPassword() !== true) {
00845             require_once 'Zend/Ldap/Exception.php';
00846             $zle = new Zend_Ldap_Exception(null,
00847                 'Empty password not allowed - see allowEmptyPassword option.');
00848         } else {
00849             if (@ldap_bind($this->getResource(), $username, $password)) {
00850                 return $this;
00851             }
00852 
00853             $message = ($username === null) ? $this->_connectString : $username;
00857             require_once 'Zend/Ldap/Exception.php';
00858             switch ($this->getLastErrorCode()) {
00859                 case Zend_Ldap_Exception::LDAP_SERVER_DOWN:
00860                     /* If the error is related to establishing a connection rather than binding,
00861                      * the connect string is more informative than the username.
00862                      */
00863                     $message = $this->_connectString;
00864             }
00865 
00866             $zle = new Zend_Ldap_Exception($this, $message);
00867         }
00868         $this->disconnect();
00869         throw $zle;
00870     }
00871 
00884     public function search($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB,
00885         array $attributes = array(), $sort = null, $collectionClass = null)
00886     {
00887         if ($basedn === null) {
00888             $basedn = $this->getBaseDn();
00889         }
00890         else if ($basedn instanceof Zend_Ldap_Dn) {
00891             $basedn = $basedn->toString();
00892         }
00893 
00894         if ($filter instanceof Zend_Ldap_Filter_Abstract) {
00895             $filter = $filter->toString();
00896         }
00897 
00898         switch ($scope) {
00899             case self::SEARCH_SCOPE_ONE:
00900                 $search = @ldap_list($this->getResource(), $basedn, $filter, $attributes);
00901                 break;
00902             case self::SEARCH_SCOPE_BASE:
00903                 $search = @ldap_read($this->getResource(), $basedn, $filter, $attributes);
00904                 break;
00905             case self::SEARCH_SCOPE_SUB:
00906             default:
00907                 $search = @ldap_search($this->getResource(), $basedn, $filter, $attributes);
00908                 break;
00909         }
00910 
00911         if($search === false) {
00915             require_once 'Zend/Ldap/Exception.php';
00916             throw new Zend_Ldap_Exception($this, 'searching: ' . $filter);
00917         }
00918         if (!is_null($sort) && is_string($sort)) {
00919             $isSorted = @ldap_sort($this->getResource(), $search, $sort);
00920             if($search === false) {
00924                 require_once 'Zend/Ldap/Exception.php';
00925                 throw new Zend_Ldap_Exception($this, 'sorting: ' . $sort);
00926             }
00927         }
00928 
00932         require_once 'Zend/Ldap/Collection/Iterator/Default.php';
00933         $iterator = new Zend_Ldap_Collection_Iterator_Default($this, $search);
00934         if ($collectionClass === null) {
00938             require_once 'Zend/Ldap/Collection.php';
00939             return new Zend_Ldap_Collection($iterator);
00940         } else {
00941             $collectionClass = (string)$collectionClass;
00942             if (!class_exists($collectionClass)) {
00946                 require_once 'Zend/Ldap/Exception.php';
00947                 throw new Zend_Ldap_Exception(null,
00948                     "Class '$collectionClass' can not be found");
00949             }
00950             if (!is_subclass_of($collectionClass, 'Zend_Ldap_Collection')) {
00954                 require_once 'Zend/Ldap/Exception.php';
00955                 throw new Zend_Ldap_Exception(null,
00956                     "Class '$collectionClass' must subclass 'Zend_Ldap_Collection'");
00957             }
00958             return new $collectionClass($iterator);
00959         }
00960     }
00961 
00971     public function count($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB)
00972     {
00973         try {
00974             $result = $this->search($filter, $basedn, $scope, array('dn'), null);
00975         } catch (Zend_Ldap_Exception $e) {
00976             if ($e->getCode() === Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT) return 0;
00977             else throw $e;
00978         }
00979         return $result->count();
00980     }
00981 
00989     public function countChildren($dn)
00990     {
00991         return $this->count('(objectClass=*)', $dn, self::SEARCH_SCOPE_ONE);
00992     }
00993 
01001     public function exists($dn)
01002     {
01003         return ($this->count('(objectClass=*)', $dn, self::SEARCH_SCOPE_BASE) == 1);
01004     }
01005 
01017     public function searchEntries($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB,
01018         array $attributes = array(), $sort = null)
01019     {
01020         $result = $this->search($filter, $basedn, $scope, $attributes, $sort);
01021         return $result->toArray();
01022     }
01023 
01033     public function getEntry($dn, array $attributes = array(), $throwOnNotFound = false)
01034     {
01035         try {
01036             $result = $this->search("(objectClass=*)", $dn, self::SEARCH_SCOPE_BASE,
01037                 $attributes, null);
01038             return $result->getFirst();
01039         } catch (Zend_Ldap_Exception $e){
01040             if ($throwOnNotFound !== false) throw $e;
01041         }
01042         return null;
01043     }
01044 
01052     public static function prepareLdapEntryArray(array &$entry)
01053     {
01054         if (array_key_exists('dn', $entry)) unset($entry['dn']);
01055         foreach ($entry as $key => $value) {
01056             if (is_array($value)) {
01057                 foreach ($value as $i => $v) {
01058                     if (is_null($v)) unset($value[$i]);
01059                     else if (!is_scalar($v)) {
01060                         throw new InvalidArgumentException('Only scalar values allowed in LDAP data');
01061                     } else {
01062                         $v = (string)$v;
01063                         if (strlen($v) == 0) {
01064                             unset($value[$i]);
01065                         } else {
01066                             $value[$i] = $v;
01067                         }
01068                     }
01069                 }
01070                 $entry[$key] = array_values($value);
01071             } else {
01072                 if (is_null($value)) $entry[$key] = array();
01073                 else if (!is_scalar($value)) {
01074                     throw new InvalidArgumentException('Only scalar values allowed in LDAP data');
01075                 } else {
01076                     $value = (string)$value;
01077                     if (strlen($value) == 0) {
01078                         $entry[$key] = array();
01079                     } else {
01080                         $entry[$key] = array($value);
01081                     }
01082                 }
01083             }
01084         }
01085         $entry = array_change_key_case($entry, CASE_LOWER);
01086     }
01087 
01096     public function add($dn, array $entry)
01097     {
01098         if (!($dn instanceof Zend_Ldap_Dn)) {
01099             $dn = Zend_Ldap_Dn::factory($dn, null);
01100         }
01101         self::prepareLdapEntryArray($entry);
01102         foreach ($entry as $key => $value) {
01103             if (is_array($value) && count($value) === 0) {
01104                 unset($entry[$key]);
01105             }
01106         }
01107 
01108         $rdnParts = $dn->getRdn(Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER);
01109         foreach ($rdnParts as $key => $value) {
01110             $value = Zend_Ldap_Dn::unescapeValue($value);
01111             if (!array_key_exists($key, $entry) ||
01112                     !in_array($value, $entry[$key]) ||
01113                     count($entry[$key]) !== 1) {
01114                 $entry[$key] = array($value);
01115             }
01116         }
01117         $adAttributes = array('distinguishedname', 'instancetype', 'name', 'objectcategory',
01118             'objectguid', 'usnchanged', 'usncreated', 'whenchanged', 'whencreated');
01119         foreach ($adAttributes as $attr) {
01120             if (array_key_exists($attr, $entry)) {
01121                 unset($entry[$attr]);
01122             }
01123         }
01124 
01125         $isAdded = @ldap_add($this->getResource(), $dn->toString(), $entry);
01126         if($isAdded === false) {
01130             require_once 'Zend/Ldap/Exception.php';
01131             throw new Zend_Ldap_Exception($this, 'adding: ' . $dn->toString());
01132         }
01133         return $this;
01134     }
01135 
01144     public function update($dn, array $entry)
01145     {
01146         if (!($dn instanceof Zend_Ldap_Dn)) {
01147             $dn = Zend_Ldap_Dn::factory($dn, null);
01148         }
01149         self::prepareLdapEntryArray($entry);
01150 
01151         $rdnParts = $dn->getRdn(Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER);
01152         $adAttributes = array('distinguishedname', 'instancetype', 'name', 'objectcategory',
01153             'objectguid', 'usnchanged', 'usncreated', 'whenchanged', 'whencreated');
01154         $stripAttributes = array_merge(array_keys($rdnParts), $adAttributes);
01155         foreach ($stripAttributes as $attr) {
01156             if (array_key_exists($attr, $entry)) {
01157                 unset($entry[$attr]);
01158             }
01159         }
01160 
01161         if (count($entry) > 0) {
01162             $isModified = @ldap_modify($this->getResource(), $dn->toString(), $entry);
01163             if($isModified === false) {
01167                 require_once 'Zend/Ldap/Exception.php';
01168                 throw new Zend_Ldap_Exception($this, 'updating: ' . $dn->toString());
01169             }
01170         }
01171         return $this;
01172     }
01173 
01185     public function save($dn, array $entry)
01186     {
01187         if ($dn instanceof Zend_Ldap_Dn) {
01188             $dn = $dn->toString();
01189         }
01190         if ($this->exists($dn)) $this->update($dn, $entry);
01191         else $this->add($dn, $entry);
01192         return $this;
01193     }
01194 
01203     public function delete($dn, $recursively = false)
01204     {
01205         if ($dn instanceof Zend_Ldap_Dn) {
01206             $dn = $dn->toString();
01207         }
01208         if ($recursively === true) {
01209             if ($this->countChildren($dn)>0) {
01210                 $children = $this->_getChildrenDns($dn);
01211                 foreach ($children as $c) {
01212                     $this->delete($c, true);
01213                 }
01214             }
01215         }
01216         $isDeleted = @ldap_delete($this->getResource(), $dn);
01217         if($isDeleted === false) {
01221             require_once 'Zend/Ldap/Exception.php';
01222             throw new Zend_Ldap_Exception($this, 'deleting: ' . $dn);
01223         }
01224         return $this;
01225     }
01226 
01236     protected function _getChildrenDns($parentDn)
01237     {
01238         if ($parentDn instanceof Zend_Ldap_Dn) {
01239             $parentDn = $parentDn->toString();
01240         }
01241         $children = array();
01242         $search = @ldap_list($this->getResource(), $parentDn, '(objectClass=*)', array('dn'));
01243         for ($entry = @ldap_first_entry($this->getResource(), $search);
01244                 $entry !== false;
01245                 $entry = @ldap_next_entry($this->getResource(), $entry)) {
01246             $childDn = @ldap_get_dn($this->getResource(), $entry);
01247             if ($childDn === false) {
01251                 require_once 'Zend/Ldap/Exception.php';
01252                 throw new Zend_Ldap_Exception($this, 'getting dn');
01253             }
01254             $children[] = $childDn;
01255         }
01256         @ldap_free_result($search);
01257         return $children;
01258     }
01259 
01270     public function moveToSubtree($from, $to, $recursively = false, $alwaysEmulate = false)
01271     {
01272         if ($from instanceof Zend_Ldap_Dn) {
01273             $orgDnParts = $from->toArray();
01274         } else {
01275             $orgDnParts = Zend_Ldap_Dn::explodeDn($from);
01276         }
01277 
01278         if ($to instanceof Zend_Ldap_Dn) {
01279             $newParentDnParts = $to->toArray();
01280         } else {
01281             $newParentDnParts = Zend_Ldap_Dn::explodeDn($to);
01282         }
01283 
01284         $newDnParts = array_merge(array(array_shift($orgDnParts)), $newParentDnParts);
01285         $newDn = Zend_Ldap_Dn::fromArray($newDnParts);
01286         return $this->rename($from, $newDn, $recursively, $alwaysEmulate);
01287     }
01288 
01301     public function move($from, $to, $recursively = false, $alwaysEmulate = false)
01302     {
01303         return $this->rename($from, $to, $recursively, $alwaysEmulate);
01304     }
01305 
01318     public function rename($from, $to, $recursively = false, $alwaysEmulate = false)
01319     {
01320         $emulate = (bool)$alwaysEmulate;
01321         if (!function_exists('ldap_rename')) $emulate = true;
01322         else if ($recursively) $emulate = true;
01323 
01324         if ($emulate === false) {
01325             if ($from instanceof Zend_Ldap_Dn) {
01326                 $from = $from->toString();
01327             }
01328 
01329             if ($to instanceof Zend_Ldap_Dn) {
01330                 $newDnParts = $to->toArray();
01331             } else {
01332                 $newDnParts = Zend_Ldap_Dn::explodeDn($to);
01333             }
01334 
01335             $newRdn = Zend_Ldap_Dn::implodeRdn(array_shift($newDnParts));
01336             $newParent = Zend_Ldap_Dn::implodeDn($newDnParts);
01337             $isOK = @ldap_rename($this->getResource(), $from, $newRdn, $newParent, true);
01338             if($isOK === false) {
01342                 require_once 'Zend/Ldap/Exception.php';
01343                 throw new Zend_Ldap_Exception($this, 'renaming ' . $from . ' to ' . $to);
01344             }
01345             else if (!$this->exists($to)) $emulate = true;
01346         }
01347         if ($emulate) {
01348             $this->copy($from, $to, $recursively);
01349             $this->delete($from, $recursively);
01350         }
01351         return $this;
01352     }
01353 
01363     public function copyToSubtree($from, $to, $recursively = false)
01364     {
01365         if ($from instanceof Zend_Ldap_Dn) {
01366             $orgDnParts = $from->toArray();
01367         } else {
01368             $orgDnParts = Zend_Ldap_Dn::explodeDn($from);
01369         }
01370 
01371         if ($to instanceof Zend_Ldap_Dn) {
01372             $newParentDnParts = $to->toArray();
01373         } else {
01374             $newParentDnParts = Zend_Ldap_Dn::explodeDn($to);
01375         }
01376 
01377         $newDnParts = array_merge(array(array_shift($orgDnParts)), $newParentDnParts);
01378         $newDn = Zend_Ldap_Dn::fromArray($newDnParts);
01379         return $this->copy($from, $newDn, $recursively);
01380     }
01381 
01391     public function copy($from, $to, $recursively = false)
01392     {
01393         $entry = $this->getEntry($from, array(), true);
01394 
01395         if ($to instanceof Zend_Ldap_Dn) {
01396             $toDnParts = $to->toArray();
01397         } else {
01398             $toDnParts = Zend_Ldap_Dn::explodeDn($to);
01399         }
01400         $this->add($to, $entry);
01401 
01402         if ($recursively === true && $this->countChildren($from)>0) {
01403             $children = $this->_getChildrenDns($from);
01404             foreach ($children as $c) {
01405                 $cDnParts = Zend_Ldap_Dn::explodeDn($c);
01406                 $newChildParts = array_merge(array(array_shift($cDnParts)), $toDnParts);
01407                 $newChild = Zend_Ldap_Dn::implodeDn($newChildParts);
01408                 $this->copy($c, $newChild, true);
01409             }
01410         }
01411         return $this;
01412     }
01413 
01421     public function getNode($dn)
01422     {
01426         require_once 'Zend/Ldap/Node.php';
01427         return Zend_Ldap_Node::fromLdap($dn, $this);
01428     }
01429 
01436     public function getBaseNode()
01437     {
01438         return $this->getNode($this->getBaseDn(), $this);
01439     }
01440 
01447     public function getRootDse()
01448     {
01449         if ($this->_rootDse === null) {
01453             require_once 'Zend/Ldap/Node/RootDse.php';
01454             $this->_rootDse = Zend_Ldap_Node_RootDse::create($this);
01455         }
01456         return $this->_rootDse;
01457     }
01458 
01465     public function getSchema()
01466     {
01467         if ($this->_schema === null) {
01471             require_once 'Zend/Ldap/Node/Schema.php';
01472             $this->_schema = Zend_Ldap_Node_Schema::create($this);
01473         }
01474         return $this->_schema;
01475     }
01476 }

Generated on Thu Apr 19 2012 17:01:17 for openbiz by  doxygen 1.7.2