Net_LDAP
[ class tree: Net_LDAP ] [ index: Net_LDAP ] [ all elements ]

Source for file LDAP.php

Documentation is available at LDAP.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +--------------------------------------------------------------------------+
  4. // | Net_LDAP                                                                 |
  5. // +--------------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                    |
  7. // +--------------------------------------------------------------------------+
  8. // | This library is free software; you can redistribute it and/or            |
  9. // | modify it under the terms of the GNU Lesser General Public               |
  10. // | License as published by the Free Software Foundation; either             |
  11. // | version 2.1 of the License, or (at your option) any later version.       |
  12. // |                                                                          |
  13. // | This library is distributed in the hope that it will be useful,          |
  14. // | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        |
  16. // | Lesser General Public License for more details.                          |
  17. // |                                                                          |
  18. // | You should have received a copy of the GNU Lesser General Public         |
  19. // | License along with this library; if not, write to the Free Software      |
  20. // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA |
  21. // +--------------------------------------------------------------------------+
  22. // | Authors: Tarjej Huse                                                     |
  23. // |          Jan Wagner                                                      |
  24. // +--------------------------------------------------------------------------+
  25. //
  26. // $Id: LDAP.php,v 1.19.2.10 2005/03/01 12:27:36 jw Exp $
  27.  
  28. require_once('PEAR.php');
  29. require_once('LDAP/Entry.php');
  30. require_once('LDAP/Search.php');
  31.  
  32.  
  33. /**
  34.  *  Error constants for errors that are not LDAP errors
  35.  */
  36.  
  37. define ('NET_LDAP_ERROR'1000);
  38.  
  39.  
  40. /**
  41.  * Net_LDAP - manipulate LDAP servers the right way!
  42.  *
  43.  * @author Tarjei Huse
  44.  * @author Jan Wagner
  45.  * @version $Revision: 1.19.2.10 $
  46.  * @package Net_LDAP
  47.  */
  48.  class Net_LDAP extends PEAR
  49. {
  50.     /**
  51.      * Class configuration array
  52.      *
  53.      * dn       = the DN to bind as.
  54.      * host     = the ldap host to connect to
  55.      * password = no explanation needed
  56.      * base     = ldap base
  57.      * port     = the server port
  58.      * tls      = when set, ldap_start_tls() is run after connecting.
  59.      * version  = ldap version (defaults to v 3)
  60.      * filter   = default search filter
  61.      * scope    = default search scope
  62.      *
  63.      * @access private
  64.      * @var array 
  65.      */
  66.      var $_config = array('dn' => '',
  67.                           'host' => 'localhost',
  68.                           'password' => '',
  69.                           'tls' => false,
  70.                           'base' => '',
  71.                           'port' => 389,
  72.                           'version' => 3,
  73.                           'options' => array(),
  74.                           'filter' => '(objectClass=*)',
  75.                           'scope' => 'sub');
  76.  
  77.     /**
  78.      * LDAP resource link.
  79.      *
  80.      * @access private
  81.      * @var resource 
  82.      */
  83.     var $_link;
  84.  
  85.     /**
  86.      * Net_LDAP Release Version
  87.      *
  88.      * @access private
  89.      * @var string 
  90.      */
  91.     var $_version "0.6.6";
  92.     
  93.     /**
  94.      * Net_LDAP_Schema object
  95.      *
  96.      * @access private
  97.      * @var object Net_LDAP_Schema 
  98.      */
  99.     var $_schema = null;
  100.     
  101.     /**
  102.      * Cache for attribute encoding checks
  103.      *
  104.      * @access private
  105.      * @var array Hash with attribute names as key and boolean value
  106.      *             to determine whether they should be utf8 encoded or not.
  107.      */
  108.     var $_schemaAttrs = array();
  109.  
  110.     /**
  111.      * Net_LDAP constructor
  112.      *
  113.      * Sets the config array
  114.      *
  115.      * @access protected
  116.      * @param array Configuration array
  117.      * @return void 
  118.      * @see $_config
  119.      */
  120.     function Net_LDAP($_config = array())
  121.     {
  122.         $this->PEAR('Net_LDAP_Error');
  123.         
  124.         foreach ($_config as $k => $v{
  125.             $this->_config[$k$v;
  126.         }
  127.     }
  128.     
  129.     /**
  130.      * Creates the initial ldap-object
  131.      *
  132.      * Static function that returns either an error object or the new Net_LDAP object.
  133.      * Something like a factory. Takes a config array with the needed parameters.
  134.      *
  135.      * @access public
  136.      * @param array Configuration array
  137.      * @return mixed object Net_LDAP_Error or Net_LDAP
  138.      * @see $_config
  139.      */
  140.     function &connect($config = array())
  141.     {
  142.         if (!function_exists('ldap_connect')){
  143.             return $this->raiseError("It seems that you do not have the ldap-extension installed. Please install it before using this package.");
  144.         }
  145.         @$obj =new Net_LDAP($config);
  146.         $err  $obj->bind();
  147.  
  148.         if (Net_LDAP::isError($err)) {
  149.             return $err;
  150.         }
  151.         return $obj;
  152.     }
  153.  
  154.     /**
  155.      * Bind to the ldap-server
  156.      *
  157.      * The function may be used if you do not create the object using Net_LDAP::connect.
  158.      *
  159.      * @access public
  160.      * @param array Configuration array
  161.      * @return mixed Net_LDAP_Error or true
  162.      * @see $_config
  163.      */
  164.     function bind($config = array())
  165.     {
  166.         foreach ($config as $k => $v{
  167.             $this->_config[$k$v;
  168.         }
  169.  
  170.         if ($this->_config['host']{
  171.              $this->_link @ldap_connect($this->_config['host']$this->_config['port']);
  172.         else {
  173.              return $this->raiseError("Host not defined in config. {$this->_config['host']}");
  174.         }
  175.  
  176.         if (!$this->_link{            
  177.             // there is no good errorcode for this one! I chose 52.
  178.             return $this->raiseError("Could not connect to server. ldap_connect failed."52);
  179.         }
  180.         // You must set the version and start tls BEFORE binding!
  181.         
  182.         if ($this->_config['version'!= 2 && Net_LDAP::isError($msg $this->setLDAPVersion())) {
  183.             return $msg;
  184.         }
  185.         
  186.         if ($this->_config['tls'&& Net_LDAP::isError($msg $this->startTLS())) {
  187.             return $msg;
  188.         }
  189.         
  190.         if (isset($this->_config['options']&&
  191.             is_array($this->_config['options']&&
  192.             count($this->_config['options']))
  193.         {
  194.             foreach ($this->_config['options'as $opt => $val{
  195.                 $err $this->setOption($opt$val);
  196.                 if (Net_LDAP::isError($err)) {
  197.                     return $err;
  198.                 }
  199.             }
  200.         }
  201.         
  202.         if (isset($this->_config['dn']&& isset($this->_config['password'])) {
  203.              $bind @ldap_bind($this->_link$this->_config['dn']$this->_config['password']);
  204.         else {
  205.              $bind @ldap_bind($this->_link);
  206.         }
  207.  
  208.         if (!$bind{
  209.              return $this->raiseError("Bind failed " @ldap_error($this->_link)@ldap_errno($this->_link));
  210.         }
  211.  
  212.         return true;
  213.     }
  214.  
  215.     /**
  216.      * ReBind to the ldap-server using another dn and password
  217.      *
  218.      * The function may be used if you do not create the object using Net_LDAP::connect.
  219.      *
  220.      * @access public
  221.      * @param string $dn - the DN to bind as.
  222.      *         string $password - the bassword to use.
  223.      * @return mixed Net_LDAP_Error or true
  224.      * @see $_config
  225.      */
  226.    
  227.     function reBind ($dn = null$password = null
  228.     {
  229.        
  230.         if ($dn && $password {
  231.             $bind @ldap_bind($this->_link$dn$password);
  232.         else {
  233.             $bind @ldap_bind($this->_link);
  234.         }
  235.  
  236.         if (!$bind{
  237.             return $this->raiseError("Bind failed " @ldap_error($this->_link)@ldap_errno($this->_link));
  238.         }
  239.         return true;
  240.     }
  241.     
  242.     /**
  243.      * Starts an encrypted session
  244.      *
  245.      * @access public
  246.      * @return mixed True or Net_LDAP_Error
  247.      */
  248.     function startTLS()
  249.     {
  250.         if (!@ldap_start_tls($this->_link)) {
  251.             return $this->raiseError("TLS not started. Error:" @ldap_error($this->_link)@ldap_errno($this->_link));
  252.         }
  253.         return true;
  254.     }
  255.     
  256.     /**
  257.      * alias function of startTLS() for perl-ldap interface
  258.      * 
  259.      * @see startTLS()
  260.      */
  261.     function start_tls(
  262.     {
  263.         $args func_get_args();
  264.         return call_user_func_array(array($this'startTLS' )$args);
  265.     }
  266.  
  267.     /**
  268.      * Close LDAP connection.
  269.      *
  270.      * Closes the connection. Use this when the session is over.
  271.      *
  272.      * @return void 
  273.      */
  274.     function done()
  275.     {
  276.         $this->_Net_LDAP();
  277.     }
  278.  
  279.     /**
  280.      * Destructor
  281.      *
  282.      * @access private
  283.      */
  284.     function _Net_LDAP()
  285.     {
  286.         @ldap_close($this->_link);
  287.     }
  288.  
  289.     /**
  290.      * Add a new entryobject to a directory.
  291.      *
  292.      * Use add to add a new Net_LDAP_Entry object to the directory.
  293.      *
  294.      * @param object Net_LDAP_Entry 
  295.      * @return mixed Net_LDAP_Error or true
  296.      */
  297.     function add($entry)
  298.     {
  299.         if (@ldap_add($this->_link$entry->dn()$entry->attributes())) {
  300.              return true;
  301.         else {
  302.              return $this->raiseError("Could not add entry " $entry->dn(" " @ldap_error($this->_link),
  303.                                        @ldap_errno($this->_link));
  304.         }
  305.     }
  306.  
  307.     /**
  308.      * Delete an entry from the directory
  309.      *
  310.      * The object may either be a string representing the dn or a Net_LDAP_Entry object.
  311.      * The param array may contain a boolean value named recursive. When set, all subentries
  312.      * of the Entry will be deleted as well
  313.      *
  314.      * @access public
  315.      * @param mixed string or Net_LDAP_Entry
  316.      * @param array 
  317.      * @return mixed Net_LDAP_Error or true
  318.      */
  319.     function delete($dn$param = array())
  320.     {
  321.         if (is_object($dn&& strtolower(get_class($dn)) == 'net_ldap_entry'{
  322.              $dn $dn->dn();
  323.         else {
  324.             if (!is_string($dn)) {
  325.                 // this is what the server would say: invalid_dn_syntax.
  326.                 return $this->raiseError("$dn not a string nor an entryobject!"34)
  327.             }
  328.         }
  329.         
  330.         if ($param['recursive'{
  331.             $searchresult @ldap_list($this->_link$dn'(objectClass=*)'array());
  332.             
  333.             if ($searchresult{
  334.                 $entries @ldap_get_entries($this->_link$searchresult);
  335.  
  336.                 for ($i=0; $i<$entries['count']$i++{
  337.                     $result $this->delete($entries[$i]['dn']array('recursive' => true));
  338.                     if (!$result{
  339.                         $errno @ldap_errno($this->_link);
  340.                         return $this->raiseMessage ("Net_LDAP::delete: " $this->errorMessage($errno)$errno);
  341.                     }                
  342.                     if(PEAR::isError($result)){
  343.                         return $result;
  344.                     }                
  345.                 }
  346.             }
  347.         }
  348.         if (!@ldap_delete($this->_link$dn)) {
  349.             $error = ldap_errno($this->_link );                
  350.             if ($error == 66{
  351.                 /* entry has subentries */
  352.                 return $this->raiseError('Net_LDAP::delete: Cound not delete entry ' $dn .
  353.                                          ' because of subentries. Use the recursive param to delete them.')
  354.             else {
  355.                 return $this->raiseError("Net_LDAP::delete: Could not delete entry " $dn ." because: ".
  356.                                          $this->errorMessage($error),  $error);
  357.             }
  358.         }
  359.         return true;
  360.     }
  361.  
  362.     /**
  363.      * Modify an ldapentry
  364.      *
  365.      * This is taken from the perlpod of net::ldap, and explains things quite nicely.
  366.      * modify ( DN, OPTIONS )
  367.      * Modify the contents of DN on the server. DN May be a
  368.      * string or a Net::LDAP::Entry object.
  369.      *
  370.      * dn  This option is here for compatibility only, and
  371.      * may be removed in future.  Previous releases did
  372.      * not take the DN argument which replaces this
  373.      * option.
  374.      *
  375.      * add The add option should be a reference to a HASH.
  376.      * The values of the HASH are the attributes to add,
  377.      * and the values may be a string or a reference to a
  378.      * list of values.
  379.      *
  380.      * delete
  381.      * A reference to an ARRAY of attributes to delete.
  382.      * TODO: This does not support deleting one or two values yet - use
  383.      * replace.
  384.      *
  385.      * replace
  386.      * The <replace> option takes a argument in the same
  387.      * form as add, but will cause any existing
  388.      * attributes with the same name to be replaced. If
  389.      * erence to an empty string the all instances of the
  390.      * attribute will be deleted.
  391.      *
  392.      * changes
  393.      * This is an alternative to add, delete and replace
  394.      * where the whole operation can be given in a single
  395.      * argument. The argument should be a array
  396.      *
  397.      * Values in the ARRAY are used in pairs, the first
  398.      * is the operation add, delete or replace and the
  399.      * second is a reference to an ARRAY of attribute
  400.      * values.
  401.      *
  402.      * The attribute value list is also used in pairs.
  403.      * The first value in each pair is the attribute name
  404.      * and the second is a reference to a list of values.
  405.      *
  406.      * Example:
  407.      * $ldap->modify ( $dn, array (changes => array(
  408.      * 'delete' => array('faxNumber' => ''),
  409.      * 'add' => array('sn' => 'Barr'),
  410.      * 'replace' => array(email => 'tarjei@nu.no'))));
  411.      *
  412.      * @access public
  413.      * @param string 
  414.      * @param array 
  415.      * @return mixed Net_LDAP_Error or true
  416.      */
  417.     function modify($dn $params = array())
  418.     {
  419.         if (is_object($dn)) {
  420.              $dn $dn->dn();
  421.         }
  422.          // since $params['dn'] is not used in net::ldap now:
  423.         if (isset($params['dn'])) {
  424.              return $this->raiseError("This feature will not be implemented!");
  425.         }
  426.         // new code from rafael at krysciak dot de
  427.         if(array_key_exists('changes'$params)) {
  428.             $_params $params;
  429.         else {
  430.             $_params['changes'$params;
  431.         }
  432.         if (is_array($_params['changes'])) {
  433.             foreach($_params['changes'AS $option => $atrr{
  434.                 switch($option{
  435.                     case 'add':
  436.                         $command $dn_exists 'ldap_mod_add':'ldap_add';
  437.                     break;
  438.                     case 'replace':
  439.                         $command 'ldap_mod_replace';
  440.                     break;
  441.                     case 'delete':
  442.                         $command 'ldap_mod_del';
  443.                                                 // to delete an attribute with a specific value you
  444.                                                 // need a hash array('attr_name' => array('attr_value_1', ... ,'attr_value_n'))
  445.                                                 // the hash array('attr_name' => 'attr_value') will be converted
  446.                                                 // automatically to array('attr_name' => array('attr_value'))
  447.                         foreach($atrr AS $atrr_field => $atrr_value{
  448.                             if(!is_array($atrr_value)) {
  449.                                 $atrr[$atrr_field= array($atrr_value);
  450.                             }
  451.                         }
  452.                     break;
  453.                     default:
  454.                         return $this->raiseError("Net_LDAP::modify: not supported option " $option);
  455.                     break;
  456.                 // end switch($option) {
  457.  
  458.                 if(!@call_user_func($command$this->_link$dn$atrr)) {
  459.                    return $this->raiseError("Net_LDAP::modify: $dn not modified because:" . ldap_error($this->_link)ldap_errno($this->_link));
  460.                 }
  461.             // end foreach($_params['changes'] AS $option => $atrr) {
  462.         // end if (is_array($_params['changes'])) {
  463.         // everything went fine :)
  464.         return true;        
  465.  
  466.         /* old broken code see bug#2987
  467.         if (isset($params['changes'])) {
  468.  
  469.              if (isset($params['changes']['add']) &&
  470.                  !@ldap_modify($this->_link, $dn, $params['changes']['add'])) {
  471.  
  472.                  return $this->raiseError("Net_LDAP::modify: $dn not modified because:" . ldap_error($this->_link),
  473.                                            ldap_errno($this->_link));
  474.              }
  475.  
  476.              if (isset($params['changes']['replace']) &&
  477.                  !@ldap_modify($this->_link, $dn, $params['changes']['replace'])) {
  478.  
  479.                  return $this->raiseError("Net_LDAP::modify: replace change didn't work: " . ldap_error($this->_link),
  480.                                           ldap_errno($this->_link));
  481.              }
  482.  
  483.              if (isset($params['changes']['delete']) &&
  484.                  !@ldap_mod_del($this->_link, $dn, $params['changes']['delete'])) {
  485.  
  486.                  return $this->raiseError("Net_LDAP::modify:delete did not work" . ldap_error($this->_link),
  487.                                           ldap_errno($this->_link));
  488.              }
  489.         }
  490.  
  491.         if (isset($params['add']) && !@ldap_add($this->_link, $dn, $params['add'])) {
  492.             return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  493.         }
  494.  
  495.         if (isset($params['replace']) && !@ldap_modify($this->_link, $dn, $params['replace'])) {
  496.             return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  497.         }
  498.  
  499.         if (isset($params['delete'])) {
  500.              // since you delete an attribute by making it empty:
  501.             foreach ($params['delete'] as $k) {
  502.                 $params['delete'][$k] = '';
  503.             }
  504.  
  505.             if (!@ldap_modify($this->_link, $dn, $params['delete'])) {
  506.                  return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  507.             }
  508.         }
  509.         // everything went fine :)
  510.         return true;
  511.         */
  512.         
  513.     }
  514.  
  515.     /**
  516.      * Run a ldap query
  517.      *
  518.      * Search is used to query the ldap-database.
  519.      * $base and $filter may be ommitted. BaseDN and default filter will then be used.
  520.      * Params may contain:
  521.      *
  522.      * scope: The scope which will be used for searching
  523.      *        base - Just one entry
  524.      *        sub  - The whole tree
  525.      *        one  - Immediately below $base
  526.      * sizelimit: Limit the number of entries returned (default: 0),
  527.      * timelimit: Limit the time spent for searching (default: 0),
  528.      * attrsonly: If true, the search will only return the attribute names, NO values
  529.      * attributes: Array of attribute names, which the entry should contain. It is good practice
  530.      *             to limit this to just the ones you need, so by default this function does not
  531.      *             return any attributes at all.
  532.      * [NOT IMPLEMENTED]
  533.      * deref: By default aliases are dereferenced to locate the base object for the search, but not when
  534.      *        searching subordinates of the base object. This may be changed by specifying one of the
  535.      *        following values:
  536.      *       
  537.      *        never  - Do not dereference aliases in searching or in locating the base object of the search.
  538.      *        search - Dereference aliases in subordinates of the base object in searching, but not in
  539.      *                locating the base object of the search.
  540.      *        find
  541.      *        always
  542.      *
  543.      * @access public
  544.      * @param string LDAP searchbase
  545.      * @param string LDAP search filter
  546.      * @param array Array of options
  547.      * @return object mixed Net_LDAP_Search or Net_LDAP_Error
  548.      */
  549.     function search($base = null$filter = null$params = array())
  550.     {        
  551.         if (is_null($base)) {
  552.             $base $this->_config['base'];
  553.         }
  554.         if (is_null($filter)) {
  555.             $filter $this->_config['filter'];
  556.         }        
  557.         
  558.         /* setting searchparameters  */
  559.         (isset($params['sizelimit']))  $sizelimit  $params['sizelimit']  $sizelimit = 0;
  560.         (isset($params['timelimit']))  $timelimit  $params['timelimit']  $timelimit = 0;
  561.         (isset($params['attrsonly']))  $attrsonly  $params['attrsonly']  $attrsonly = 0;        
  562.         (isset($params['attributes'])) $attributes $params['attributes'$attributes = array('');        
  563.        
  564.         if (!is_array($attributes)) {
  565.             $this->raiseError("The param attributes must be an array!");
  566.         }
  567.        
  568.         /* scoping makes searches faster!  */                         
  569.         $scope (isset($params['scope']$params['scope'$this->_config['scope']);
  570.         
  571.         switch ($scope{
  572.             case 'one':
  573.                 $search_function 'ldap_list';
  574.                 break;
  575.             case 'base':
  576.                 $search_function 'ldap_read';
  577.                 break;
  578.             default:
  579.                 $search_function 'ldap_search';
  580.         }               
  581.                 
  582.         $search @call_user_func($search_function
  583.                                   $this->_link,
  584.                                   $base,
  585.                                   $filter,
  586.                                   $attributes,
  587.                                   $attrsonly,
  588.                                   $sizelimit,
  589.                                   $timelimit);
  590.  
  591.         if ($err = ldap_errno($this->_link)) 
  592.  
  593.             if ($err == 32{
  594.                 // Errorcode 32 = no such object, i.e. a nullresult.
  595.                 return $obj =new Net_LDAP_Search ($search$this->_link)
  596.                 
  597.             // Errorcode 4 = sizelimit exeeded. this will be handled better in time...
  598.             //} elseif ($err == 4) {
  599.             //    return $obj = & new Net_LDAP_Search ($search, $this->_link); 
  600.             
  601.             elseif ($err == 87{
  602.                 // bad search filter
  603.                 return $this->raiseError($this->errorMessage($err. "($filter)"$err);
  604.             else {
  605.                 $msg = "\nParameters:\nBase: $base\nFilter: $filter\nScope: $scope";
  606.                 return $this->raiseError($this->errorMessage($err$msg$err);                 
  607.             }
  608.         else {
  609.             @$obj =new Net_LDAP_Search($search$this->_link);
  610.            return $obj;
  611.         }
  612.  
  613.     }
  614.  
  615.     /**
  616.      * Set an LDAP option
  617.      *
  618.      * @access public
  619.      * @param string Option to set
  620.      * @param mixed Value to set Option to
  621.      * @return mixed Net_LDAP_Error or true
  622.      */
  623.     function setOption($option$value)
  624.     {
  625.         if ($this->_link{
  626.             if (defined($option)) {
  627.                 if (@ldap_set_option($this->_linkconstant($option)$value)) {
  628.                     return true;
  629.                 else {
  630.                     $err @ldap_errno($this->_link);
  631.                     if ($err{
  632.                         $msg @ldap_err2str($err);                        
  633.                     else {
  634.                         $err NET_LDAP_ERROR;
  635.                         $msg $this->errorMessage($err);
  636.                     
  637.                     return $this->raiseError($msg$err);
  638.                 }
  639.             else {
  640.                 return $this->raiseError("Unkown Option requested");
  641.             }    
  642.         else {
  643.             return $this->raiseError("No LDAP connection");
  644.         }
  645.     }
  646.  
  647.     /**
  648.      * Get an LDAP option value
  649.      *
  650.      * @access public
  651.      * @param string Option to get
  652.      * @return mixed Net_LDAP_Error or option value
  653.      */
  654.     function getOption($option)
  655.     {
  656.         if ($this->_link{
  657.             if (defined($option)) {
  658.                 if (@ldap_get_option($this->_linkconstant($option)$value)) {
  659.                     return $value;
  660.                 else {
  661.                     $err @ldap_errno($this->_link);
  662.                     if ($err{
  663.                         $msg @ldap_err2str($err);                        
  664.                     else {
  665.                         $err NET_LDAP_ERROR;
  666.                         $msg $this->errorMessage($err);
  667.                     
  668.                     return $this->raiseError($msg$err);
  669.                 }
  670.             else {
  671.                 $this->raiseError("Unkown Option requested");
  672.             }    
  673.         else {
  674.             $this->raiseError("No LDAP connection");
  675.         }
  676.     }
  677.  
  678.     /**
  679.      * Get the LDAP_PROTOCOL_VERSION that is used on the connection.
  680.      *
  681.      * A lot of ldap functionality is defined by what protocol version the ldap server speaks.
  682.      * This might be 2 or 3.
  683.      *
  684.      * @return int 
  685.      */
  686.     function getLDAPVersion()
  687.     {
  688.         if($this->_link{
  689.             $version $this->getOption("LDAP_OPT_PROTOCOL_VERSION");
  690.         else {
  691.             $version $this->_config['version'];
  692.         }
  693.         return $version;
  694.     }
  695.  
  696.     /**
  697.      * Set the LDAP_PROTOCOL_VERSION that is used on the connection.
  698.      *
  699.      * @param int Version to set
  700.      * @return mixed Net_LDAP_Error or TRUE
  701.      */
  702.     function setLDAPVersion($version = 0)
  703.     {
  704.         if (!$version{
  705.             $version $this->_config['version'];
  706.         }
  707.         return $this->setOption("LDAP_OPT_PROTOCOL_VERSION"$version);
  708.     }
  709.  
  710.     /**
  711.      * Get the Net_LDAP version.
  712.      *
  713.      * Return the Net_LDAP version
  714.      *
  715.      * @return string Net_LDAP version
  716.      */
  717.     function getVersion ()
  718.     {
  719.         return $this->_version;
  720.     }
  721.  
  722.     /**
  723.      * Tell if a dn already exists
  724.      *
  725.      * @param string 
  726.      * @return boolean 
  727.      */
  728.     function dnExists($dn)
  729.     {
  730.         $dns explode(",",$dn);
  731.         $filter array_shift($dns);
  732.         $baseimplode($dns,',');
  733.         //$base = $dn;        
  734.         //$filter = '(objectclass=*)';
  735.         
  736.         $result @ldap_list($this->_link$base$filterarray()11);
  737.         if (ldap_errno($this->_link== 32{
  738.             return false;
  739.         }
  740.         if (ldap_errno($this->_link!= 0{
  741.             $this->raiseError(ldap_error($this->_link)ldap_errno($this->_link));
  742.         }
  743.         if (@ldap_count_entries($this->_link$result)) {
  744.             return true;
  745.         }
  746.         return false;
  747.     }
  748.     
  749.  
  750.    /**
  751.     * Get a specific entry based on the dn
  752.     *
  753.     * @param string dn
  754.     * @param array Array of Attributes to select
  755.     * @return object Net_LDAP_Entry or Net_LDAP_Error
  756.     */
  757.    function &getEntry($dn$attr = array(''))
  758.    {
  759.         $result $this->search($dn'(objectClass=*)'array('scope' => 'base''attributes' => $attr));
  760.         if (Net_LDAP::isError($result)) {
  761.             return $result;
  762.         }
  763.         $entry $result->shiftEntry();
  764.         if (false == $entry{
  765.             return $this->raiseError('Could not fetch entry');
  766.         }
  767.         return $entry;
  768.    }
  769.    
  770.  
  771.     /**
  772.      * Returns the string for an ldap errorcode.
  773.      *
  774.      * Made to be able to make better errorhandling
  775.      * Function based on DB::errorMessage()
  776.      * Tip: The best description of the errorcodes is found here: http://www.directory-info.com/LDAP/LDAPErrorCodes.html
  777.      *
  778.      * @param int Error code
  779.      * @return string The errorstring for the error.
  780.      */
  781.     function errorMessage($errorcode)
  782.     {
  783.         $errorMessages = array(
  784.                               0x00 => "LDAP_SUCCESS",
  785.                               0x01 => "LDAP_OPERATIONS_ERROR",
  786.                               0x02 => "LDAP_PROTOCOL_ERROR",
  787.                               0x03 => "LDAP_TIMELIMIT_EXCEEDED",
  788.                               0x04 => "LDAP_SIZELIMIT_EXCEEDED",
  789.                               0x05 => "LDAP_COMPARE_FALSE",
  790.                               0x06 => "LDAP_COMPARE_TRUE",
  791.                               0x07 => "LDAP_AUTH_METHOD_NOT_SUPPORTED",
  792.                               0x08 => "LDAP_STRONG_AUTH_REQUIRED",
  793.                               0x09 => "LDAP_PARTIAL_RESULTS",
  794.                               0x0a => "LDAP_REFERRAL",
  795.                               0x0b => "LDAP_ADMINLIMIT_EXCEEDED",
  796.                               0x0c => "LDAP_UNAVAILABLE_CRITICAL_EXTENSION",
  797.                               0x0d => "LDAP_CONFIDENTIALITY_REQUIRED",
  798.                               0x0e => "LDAP_SASL_BIND_INPROGRESS",
  799.                               0x10 => "LDAP_NO_SUCH_ATTRIBUTE",
  800.                               0x11 => "LDAP_UNDEFINED_TYPE",
  801.                               0x12 => "LDAP_INAPPROPRIATE_MATCHING",
  802.                               0x13 => "LDAP_CONSTRAINT_VIOLATION",
  803.                               0x14 => "LDAP_TYPE_OR_VALUE_EXISTS",
  804.                               0x15 => "LDAP_INVALID_SYNTAX",
  805.                               0x20 => "LDAP_NO_SUCH_OBJECT",
  806.                               0x21 => "LDAP_ALIAS_PROBLEM",
  807.                               0x22 => "LDAP_INVALID_DN_SYNTAX",
  808.                               0x23 => "LDAP_IS_LEAF",
  809.                               0x24 => "LDAP_ALIAS_DEREF_PROBLEM",
  810.                               0x30 => "LDAP_INAPPROPRIATE_AUTH",
  811.                               0x31 => "LDAP_INVALID_CREDENTIALS",
  812.                               0x32 => "LDAP_INSUFFICIENT_ACCESS",
  813.                               0x33 => "LDAP_BUSY",
  814.                               0x34 => "LDAP_UNAVAILABLE",
  815.                               0x35 => "LDAP_UNWILLING_TO_PERFORM",
  816.                               0x36 => "LDAP_LOOP_DETECT",
  817.                               0x3C => "LDAP_SORT_CONTROL_MISSING",
  818.                               0x3D => "LDAP_INDEX_RANGE_ERROR",
  819.                               0x40 => "LDAP_NAMING_VIOLATION",
  820.                               0x41 => "LDAP_OBJECT_CLASS_VIOLATION",
  821.                               0x42 => "LDAP_NOT_ALLOWED_ON_NONLEAF",
  822.                               0x43 => "LDAP_NOT_ALLOWED_ON_RDN",
  823.                               0x44 => "LDAP_ALREADY_EXISTS",
  824.                               0x45 => "LDAP_NO_OBJECT_CLASS_MODS",
  825.                               0x46 => "LDAP_RESULTS_TOO_LARGE",
  826.                               0x47 => "LDAP_AFFECTS_MULTIPLE_DSAS",
  827.                               0x50 => "LDAP_OTHER",
  828.                               0x51 => "LDAP_SERVER_DOWN",
  829.                               0x52 => "LDAP_LOCAL_ERROR",
  830.                               0x53 => "LDAP_ENCODING_ERROR",
  831.                               0x54 => "LDAP_DECODING_ERROR",
  832.                               0x55 => "LDAP_TIMEOUT",
  833.                               0x56 => "LDAP_AUTH_UNKNOWN",
  834.                               0x57 => "LDAP_FILTER_ERROR",
  835.                               0x58 => "LDAP_USER_CANCELLED",
  836.                               0x59 => "LDAP_PARAM_ERROR",
  837.                               0x5a => "LDAP_NO_MEMORY",
  838.                               0x5b => "LDAP_CONNECT_ERROR",
  839.                               0x5c => "LDAP_NOT_SUPPORTED",
  840.                               0x5d => "LDAP_CONTROL_NOT_FOUND",
  841.                               0x5e => "LDAP_NO_RESULTS_RETURNED",
  842.                               0x5f => "LDAP_MORE_RESULTS_TO_RETURN",
  843.                               0x60 => "LDAP_CLIENT_LOOP",
  844.                               0x61 => "LDAP_REFERRAL_LIMIT_EXCEEDED",
  845.                               1000 => "Unknown Net_LDAP error" 
  846.                               );
  847.  
  848.          return isset($errorMessages[$errorcode]$errorMessages[$errorcode$errorMessages[NET_LDAP_ERROR];
  849.     }
  850.  
  851.     /**
  852.      * Tell whether value is a Net_LDAP_Error or not
  853.      *
  854.      * @access public
  855.      * @param mixed 
  856.      * @return boolean 
  857.      */
  858.     function isError($value)
  859.     {
  860.         return (is_a($value"Net_LDAP_Error"|| parent::isError($value));
  861.     }
  862.  
  863.     /**
  864.      * gets a root dse object
  865.      *
  866.      * @access public
  867.      * @author Jan Wagner <wagner@netsols.de>
  868.      * @param array Array of attributes to search for
  869.      * @return object mixed Net_LDAP_Error or Net_LDAP_RootDSE
  870.      */
  871.     function &rootDse($attrs = null
  872.     {
  873.         require_once('Net/LDAP/RootDSE.php');
  874.         
  875.         if (is_array($attrs&& count($attrs> 0 {
  876.             $attributes $attrs;
  877.         else {
  878.             $attributes = array('namingContexts',
  879.                                 'altServer',
  880.                                 'supportedExtension',
  881.                                 'supportedControl',
  882.                                 'supportedSASLMechanisms',
  883.                                 'supportedLDAPVersion',
  884.                                 'subschemaSubentry' );
  885.         }
  886.         $result $this->search('''(objectClass=*)'array('attributes' => $attributes'scope' => 'base'));
  887.         if (Net_LDAP::isError($result)) return $result;
  888.  
  889.         $entry $result->shift_entry();
  890.         if (false === $entryreturn $this->raiseError('Could not fetch RootDSE entry');
  891.  
  892.         return new Net_LDAP_RootDSE($entry);
  893.     }
  894.     
  895.     /**
  896.      * alias function of rootDse() for perl-ldap interface
  897.      *
  898.      * @access public
  899.      * @see rootDse()
  900.      */
  901.     function &root_dse(
  902.     {
  903.         $args func_get_args();
  904.         return call_user_func_array(array($this'rootDse')$args);
  905.     }
  906.     
  907.     /**
  908.      * get a schema object
  909.      *
  910.      * @access public
  911.      * @author Jan Wagner <wagner@netsols.de>
  912.      * @param string Subschema entry dn
  913.      * @return object mixed Net_LDAP_Schema or Net_LDAP_Error
  914.      */
  915.      function &schema($dn = null)
  916.      {
  917.         require_once('Net/LDAP/Schema.php');
  918.         
  919.         $schema =new Net_LDAP_Schema();
  920.  
  921.         if (is_null($dn)) {
  922.             // get the subschema entry via root dse
  923.             $dse $this->rootDSE(array('subschemaSubentry'));
  924.             if (false == Net_LDAP::isError($dse)) {
  925.                 $base $dse->getValue('subschemaSubentry''single');
  926.                 if (!Net_LDAP::isError($base)) {
  927.                     $dn $base;
  928.                 }
  929.             }
  930.         }
  931.         if (is_null($dn)) {
  932.             $dn 'cn=Subschema';
  933.         }        
  934.         
  935.         // fetch the subschema entry
  936.         $result $this->search($dn'(objectClass=*)',
  937.                                  array('attributes' => array_values($schema->types)'scope' => 'base'));
  938.         if (Net_LDAP::isError($result)) {
  939.             return $result;
  940.         }
  941.  
  942.         $entry $result->shift_entry();
  943.         if (false === $entry{
  944.             return $this->raiseError('Could not fetch Subschema entry');
  945.         }
  946.         
  947.         $schema->parse($entry);
  948.  
  949.         return $schema;
  950.     }
  951.  
  952.     /**
  953.      * Encodes given attributes to UTF8 if needed
  954.      *
  955.      * This function takes attributes in an array and then checks against the schema if they need
  956.      * UTF8 encoding. If that is so, they will be encoded. An encoded array will be returned and
  957.      * can be used for adding or modifying.
  958.      *
  959.      * @access public
  960.      * @param array Array of attributes
  961.      * @return array Array of UTF8 encoded attributes
  962.      */
  963.     function utf8Encode($attributes)
  964.     {
  965.         return $this->_utf8($attributes'utf8_encode');
  966.     }
  967.  
  968.     /**
  969.      * Decodes the given attribute values
  970.      *
  971.      * @access public
  972.      * @param array Array of attributes
  973.      * @return array Array with decoded attribute values
  974.      */
  975.     function utf8Decode($attributes)
  976.     {
  977.         return $this->_utf8($attributes'utf8_decode');
  978.     }
  979.  
  980.     /**
  981.      * Encodes or decodes attribute values if needed
  982.      *
  983.      * @access private
  984.      * @param array Array of attributes
  985.      * @param array Function to apply to attribute values
  986.      * @return array Array of attributes with function applied to values
  987.      */
  988.     function _utf8($attributes$function)
  989.     {
  990.         if (!$this->_schema{
  991.             $this->_schema $this->schema();
  992.         }
  993.  
  994.         if (!$this->_link || Net_LDAP::isError($this->_schema|| !function_exists($function)) {
  995.            return $attributes;
  996.         }
  997.  
  998.         if (is_array($attributes&& count($attributes> 0{
  999.             
  1000.             foreach$attributes as $k => $v {
  1001.                 
  1002.                 if (!isset($this->_schemaAttrs[$k])) {
  1003.  
  1004.                     $attr $this->_schema->get('attribute'$k);
  1005.                     if (Net_LDAP::isError($attr)) {
  1006.                         continue;
  1007.                     }
  1008.  
  1009.                     if (false !== strpos($attr['syntax']'1.3.6.1.4.1.1466.115.121.1.15')) {
  1010.                         $encode = true;
  1011.                     else {
  1012.                         $encode = false;
  1013.                     }                  
  1014.                     $this->_schemaAttrs[$k$encode;
  1015.                   
  1016.                 else {
  1017.                     $encode $this->_schemaAttrs[$k];
  1018.                 }
  1019.  
  1020.                 if ($encode{
  1021.                     if (is_array($v)) {
  1022.                         foreach ($v as $ak => $av{
  1023.                             $v[$akcall_user_func($function$av );
  1024.                         }
  1025.                     else {
  1026.                         $v call_user_func($function$v);
  1027.                     }
  1028.                 }
  1029.                 $attributes[$k$v;
  1030.             }
  1031.         }
  1032.         return $attributes;
  1033.     }
  1034. }
  1035.  
  1036. /**
  1037.  * Net_LDAP_Error implements a class for reporting portable LDAP error messages.
  1038.  *
  1039.  * @package Net_LDAP
  1040.  */
  1041. class Net_LDAP_Error extends PEAR_Error
  1042. {
  1043.     /**
  1044.      * Net_LDAP_Error constructor.
  1045.      *
  1046.      * @param mixed Net_LDAP error code, or string with error message.
  1047.      * @param integer what "error mode" to operate in
  1048.      * @param integer what error level to use for $mode & PEAR_ERROR_TRIGGER
  1049.      * @param mixed additional debug info, such as the last query
  1050.      * @access public
  1051.      * @see PEAR_Error
  1052.      */
  1053.     function Net_LDAP_Error($code = NET_LDAP_ERROR$mode = PEAR_ERROR_RETURN,
  1054.                             $level = E_USER_NOTICE$debuginfo = null)
  1055.     {
  1056.         if (is_int($code)) {
  1057.             $this->PEAR_Error('Net_LDAP_Error: ' Net_LDAP::errorMessage($code)$code$mode$level$debuginfo);
  1058.         else {
  1059.             $this->PEAR_Error("Net_LDAP_Error: $code"NET_LDAP_ERROR$mode$level$debuginfo);
  1060.         }
  1061.     }
  1062. }
  1063. ?>

Documentation generated on Mon, 11 Mar 2019 14:26:18 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.