Commit 4c8280fbef2dea855495371d6ba327e7025b236b

Authored by nbm
1 parent 5d45e263

Add Net_LDAP 0.6.6 from PEAR, licensed under the GNU LGPL


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4831 c91229c3-7414-0410-bfa2-8a42b809f60b
thirdparty/pear/Net/LDAP.php 0 → 100644
  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$
  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$
  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 + * the value for any attribute in the årray is a ref­
  390 + * erence to an empty string the all instances of the
  391 + * attribute will be deleted.
  392 + *
  393 + * changes
  394 + * This is an alternative to add, delete and replace
  395 + * where the whole operation can be given in a single
  396 + * argument. The argument should be a array
  397 + *
  398 + * Values in the ARRAY are used in pairs, the first
  399 + * is the operation add, delete or replace and the
  400 + * second is a reference to an ARRAY of attribute
  401 + * values.
  402 + *
  403 + * The attribute value list is also used in pairs.
  404 + * The first value in each pair is the attribute name
  405 + * and the second is a reference to a list of values.
  406 + *
  407 + * Example:
  408 + * $ldap->modify ( $dn, array (changes => array(
  409 + * 'delete' => array('faxNumber' => ''),
  410 + * 'add' => array('sn' => 'Barr'),
  411 + * 'replace' => array(email => 'tarjei@nu.no'))));
  412 + *
  413 + * @access public
  414 + * @param string
  415 + * @param array
  416 + * @return mixed Net_LDAP_Error or true
  417 + */
  418 + function modify($dn , $params = array())
  419 + {
  420 + if (is_object($dn)) {
  421 + $dn = $dn->dn();
  422 + }
  423 + // since $params['dn'] is not used in net::ldap now:
  424 + if (isset($params['dn'])) {
  425 + return $this->raiseError("This feature will not be implemented!");
  426 + }
  427 + // new code from rafael at krysciak dot de
  428 + if(array_key_exists('changes', $params)) {
  429 + $_params = $params;
  430 + } else {
  431 + $_params['changes'] = $params;
  432 + }
  433 + if (is_array($_params['changes'])) {
  434 + foreach($_params['changes'] AS $option => $atrr) {
  435 + switch($option) {
  436 + case 'add':
  437 + $command = $dn_exists ? 'ldap_mod_add':'ldap_add';
  438 + break;
  439 + case 'replace':
  440 + $command = 'ldap_mod_replace';
  441 + break;
  442 + case 'delete':
  443 + $command = 'ldap_mod_del';
  444 + // to delete an attribute with a specific value you
  445 + // need a hash array('attr_name' => array('attr_value_1', ... ,'attr_value_n'))
  446 + // the hash array('attr_name' => 'attr_value') will be converted
  447 + // automatically to array('attr_name' => array('attr_value'))
  448 + foreach($atrr AS $atrr_field => $atrr_value) {
  449 + if(!is_array($atrr_value)) {
  450 + $atrr[$atrr_field] = array($atrr_value);
  451 + }
  452 + }
  453 + break;
  454 + default:
  455 + return $this->raiseError("Net_LDAP::modify: not supported option " . $option);
  456 + break;
  457 + } // end switch($option) {
  458 +
  459 + if(!@call_user_func($command, $this->_link, $dn, $atrr)) {
  460 + return $this->raiseError("Net_LDAP::modify: $dn not modified because:" . ldap_error($this->_link), ldap_errno($this->_link));
  461 + }
  462 + } // end foreach($_params['changes'] AS $option => $atrr) {
  463 + } // end if (is_array($_params['changes'])) {
  464 + // everything went fine :)
  465 + return true;
  466 +
  467 + /* old broken code see bug#2987
  468 + if (isset($params['changes'])) {
  469 +
  470 + if (isset($params['changes']['add']) &&
  471 + !@ldap_modify($this->_link, $dn, $params['changes']['add'])) {
  472 +
  473 + return $this->raiseError("Net_LDAP::modify: $dn not modified because:" . ldap_error($this->_link),
  474 + ldap_errno($this->_link));
  475 + }
  476 +
  477 + if (isset($params['changes']['replace']) &&
  478 + !@ldap_modify($this->_link, $dn, $params['changes']['replace'])) {
  479 +
  480 + return $this->raiseError("Net_LDAP::modify: replace change didn't work: " . ldap_error($this->_link),
  481 + ldap_errno($this->_link));
  482 + }
  483 +
  484 + if (isset($params['changes']['delete']) &&
  485 + !@ldap_mod_del($this->_link, $dn, $params['changes']['delete'])) {
  486 +
  487 + return $this->raiseError("Net_LDAP::modify:delete did not work" . ldap_error($this->_link),
  488 + ldap_errno($this->_link));
  489 + }
  490 + }
  491 +
  492 + if (isset($params['add']) && !@ldap_add($this->_link, $dn, $params['add'])) {
  493 + return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  494 + }
  495 +
  496 + if (isset($params['replace']) && !@ldap_modify($this->_link, $dn, $params['replace'])) {
  497 + return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  498 + }
  499 +
  500 + if (isset($params['delete'])) {
  501 + // since you delete an attribute by making it empty:
  502 + foreach ($params['delete'] as $k) {
  503 + $params['delete'][$k] = '';
  504 + }
  505 +
  506 + if (!@ldap_modify($this->_link, $dn, $params['delete'])) {
  507 + return $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  508 + }
  509 + }
  510 + // everything went fine :)
  511 + return true;
  512 + */
  513 +
  514 + }
  515 +
  516 + /**
  517 + * Run a ldap query
  518 + *
  519 + * Search is used to query the ldap-database.
  520 + * $base and $filter may be ommitted. BaseDN and default filter will then be used.
  521 + * Params may contain:
  522 + *
  523 + * scope: The scope which will be used for searching
  524 + * base - Just one entry
  525 + * sub - The whole tree
  526 + * one - Immediately below $base
  527 + * sizelimit: Limit the number of entries returned (default: 0),
  528 + * timelimit: Limit the time spent for searching (default: 0),
  529 + * attrsonly: If true, the search will only return the attribute names, NO values
  530 + * attributes: Array of attribute names, which the entry should contain. It is good practice
  531 + * to limit this to just the ones you need, so by default this function does not
  532 + * return any attributes at all.
  533 + * [NOT IMPLEMENTED]
  534 + * deref: By default aliases are dereferenced to locate the base object for the search, but not when
  535 + * searching subordinates of the base object. This may be changed by specifying one of the
  536 + * following values:
  537 + *
  538 + * never - Do not dereference aliases in searching or in locating the base object of the search.
  539 + * search - Dereference aliases in subordinates of the base object in searching, but not in
  540 + * locating the base object of the search.
  541 + * find
  542 + * always
  543 + *
  544 + * @access public
  545 + * @param string LDAP searchbase
  546 + * @param string LDAP search filter
  547 + * @param array Array of options
  548 + * @return object mixed Net_LDAP_Search or Net_LDAP_Error
  549 + */
  550 + function search($base = null, $filter = null, $params = array())
  551 + {
  552 + if (is_null($base)) {
  553 + $base = $this->_config['base'];
  554 + }
  555 + if (is_null($filter)) {
  556 + $filter = $this->_config['filter'];
  557 + }
  558 +
  559 + /* setting searchparameters */
  560 + (isset($params['sizelimit'])) ? $sizelimit = $params['sizelimit'] : $sizelimit = 0;
  561 + (isset($params['timelimit'])) ? $timelimit = $params['timelimit'] : $timelimit = 0;
  562 + (isset($params['attrsonly'])) ? $attrsonly = $params['attrsonly'] : $attrsonly = 0;
  563 + (isset($params['attributes'])) ? $attributes = $params['attributes'] : $attributes = array('');
  564 +
  565 + if (!is_array($attributes)) {
  566 + $this->raiseError("The param attributes must be an array!");
  567 + }
  568 +
  569 + /* scoping makes searches faster! */
  570 + $scope = (isset($params['scope']) ? $params['scope'] : $this->_config['scope']);
  571 +
  572 + switch ($scope) {
  573 + case 'one':
  574 + $search_function = 'ldap_list';
  575 + break;
  576 + case 'base':
  577 + $search_function = 'ldap_read';
  578 + break;
  579 + default:
  580 + $search_function = 'ldap_search';
  581 + }
  582 +
  583 + $search = @call_user_func($search_function,
  584 + $this->_link,
  585 + $base,
  586 + $filter,
  587 + $attributes,
  588 + $attrsonly,
  589 + $sizelimit,
  590 + $timelimit);
  591 +
  592 + if ($err = ldap_errno($this->_link)) {
  593 +
  594 + if ($err == 32) {
  595 + // Errorcode 32 = no such object, i.e. a nullresult.
  596 + return $obj =& new Net_LDAP_Search ($search, $this->_link);
  597 +
  598 + // Errorcode 4 = sizelimit exeeded. this will be handled better in time...
  599 + //} elseif ($err == 4) {
  600 + // return $obj = & new Net_LDAP_Search ($search, $this->_link);
  601 +
  602 + } elseif ($err == 87) {
  603 + // bad search filter
  604 + return $this->raiseError($this->errorMessage($err) . "($filter)", $err);
  605 + } else {
  606 + $msg = "\nParameters:\nBase: $base\nFilter: $filter\nScope: $scope";
  607 + return $this->raiseError($this->errorMessage($err) . $msg, $err);
  608 + }
  609 + } else {
  610 + @$obj =& new Net_LDAP_Search($search, $this->_link);
  611 + return $obj;
  612 + }
  613 +
  614 + }
  615 +
  616 + /**
  617 + * Set an LDAP option
  618 + *
  619 + * @access public
  620 + * @param string Option to set
  621 + * @param mixed Value to set Option to
  622 + * @return mixed Net_LDAP_Error or true
  623 + */
  624 + function setOption($option, $value)
  625 + {
  626 + if ($this->_link) {
  627 + if (defined($option)) {
  628 + if (@ldap_set_option($this->_link, constant($option), $value)) {
  629 + return true;
  630 + } else {
  631 + $err = @ldap_errno($this->_link);
  632 + if ($err) {
  633 + $msg = @ldap_err2str($err);
  634 + } else {
  635 + $err = NET_LDAP_ERROR;
  636 + $msg = $this->errorMessage($err);
  637 + }
  638 + return $this->raiseError($msg, $err);
  639 + }
  640 + } else {
  641 + return $this->raiseError("Unkown Option requested");
  642 + }
  643 + } else {
  644 + return $this->raiseError("No LDAP connection");
  645 + }
  646 + }
  647 +
  648 + /**
  649 + * Get an LDAP option value
  650 + *
  651 + * @access public
  652 + * @param string Option to get
  653 + * @return mixed Net_LDAP_Error or option value
  654 + */
  655 + function getOption($option)
  656 + {
  657 + if ($this->_link) {
  658 + if (defined($option)) {
  659 + if (@ldap_get_option($this->_link, constant($option), $value)) {
  660 + return $value;
  661 + } else {
  662 + $err = @ldap_errno($this->_link);
  663 + if ($err) {
  664 + $msg = @ldap_err2str($err);
  665 + } else {
  666 + $err = NET_LDAP_ERROR;
  667 + $msg = $this->errorMessage($err);
  668 + }
  669 + return $this->raiseError($msg, $err);
  670 + }
  671 + } else {
  672 + $this->raiseError("Unkown Option requested");
  673 + }
  674 + } else {
  675 + $this->raiseError("No LDAP connection");
  676 + }
  677 + }
  678 +
  679 + /**
  680 + * Get the LDAP_PROTOCOL_VERSION that is used on the connection.
  681 + *
  682 + * A lot of ldap functionality is defined by what protocol version the ldap server speaks.
  683 + * This might be 2 or 3.
  684 + *
  685 + * @return int
  686 + */
  687 + function getLDAPVersion()
  688 + {
  689 + if($this->_link) {
  690 + $version = $this->getOption("LDAP_OPT_PROTOCOL_VERSION");
  691 + } else {
  692 + $version = $this->_config['version'];
  693 + }
  694 + return $version;
  695 + }
  696 +
  697 + /**
  698 + * Set the LDAP_PROTOCOL_VERSION that is used on the connection.
  699 + *
  700 + * @param int Version to set
  701 + * @return mixed Net_LDAP_Error or TRUE
  702 + */
  703 + function setLDAPVersion($version = 0)
  704 + {
  705 + if (!$version) {
  706 + $version = $this->_config['version'];
  707 + }
  708 + return $this->setOption("LDAP_OPT_PROTOCOL_VERSION", $version);
  709 + }
  710 +
  711 + /**
  712 + * Get the Net_LDAP version.
  713 + *
  714 + * Return the Net_LDAP version
  715 + *
  716 + * @return string Net_LDAP version
  717 + */
  718 + function getVersion ()
  719 + {
  720 + return $this->_version;
  721 + }
  722 +
  723 + /**
  724 + * Tell if a dn already exists
  725 + *
  726 + * @param string
  727 + * @return boolean
  728 + */
  729 + function dnExists($dn)
  730 + {
  731 + $dns = explode(",",$dn);
  732 + $filter = array_shift($dns);
  733 + $base= implode($dns,',');
  734 + //$base = $dn;
  735 + //$filter = '(objectclass=*)';
  736 +
  737 + $result = @ldap_list($this->_link, $base, $filter, array(), 1, 1);
  738 + if (ldap_errno($this->_link) == 32) {
  739 + return false;
  740 + }
  741 + if (ldap_errno($this->_link) != 0) {
  742 + $this->raiseError(ldap_error($this->_link), ldap_errno($this->_link));
  743 + }
  744 + if (@ldap_count_entries($this->_link, $result)) {
  745 + return true;
  746 + }
  747 + return false;
  748 + }
  749 +
  750 +
  751 + /**
  752 + * Get a specific entry based on the dn
  753 + *
  754 + * @param string dn
  755 + * @param array Array of Attributes to select
  756 + * @return object Net_LDAP_Entry or Net_LDAP_Error
  757 + */
  758 + function &getEntry($dn, $attr = array(''))
  759 + {
  760 + $result = $this->search($dn, '(objectClass=*)', array('scope' => 'base', 'attributes' => $attr));
  761 + if (Net_LDAP::isError($result)) {
  762 + return $result;
  763 + }
  764 + $entry = $result->shiftEntry();
  765 + if (false == $entry) {
  766 + return $this->raiseError('Could not fetch entry');
  767 + }
  768 + return $entry;
  769 + }
  770 +
  771 +
  772 + /**
  773 + * Returns the string for an ldap errorcode.
  774 + *
  775 + * Made to be able to make better errorhandling
  776 + * Function based on DB::errorMessage()
  777 + * Tip: The best description of the errorcodes is found here: http://www.directory-info.com/LDAP/LDAPErrorCodes.html
  778 + *
  779 + * @param int Error code
  780 + * @return string The errorstring for the error.
  781 + */
  782 + function errorMessage($errorcode)
  783 + {
  784 + $errorMessages = array(
  785 + 0x00 => "LDAP_SUCCESS",
  786 + 0x01 => "LDAP_OPERATIONS_ERROR",
  787 + 0x02 => "LDAP_PROTOCOL_ERROR",
  788 + 0x03 => "LDAP_TIMELIMIT_EXCEEDED",
  789 + 0x04 => "LDAP_SIZELIMIT_EXCEEDED",
  790 + 0x05 => "LDAP_COMPARE_FALSE",
  791 + 0x06 => "LDAP_COMPARE_TRUE",
  792 + 0x07 => "LDAP_AUTH_METHOD_NOT_SUPPORTED",
  793 + 0x08 => "LDAP_STRONG_AUTH_REQUIRED",
  794 + 0x09 => "LDAP_PARTIAL_RESULTS",
  795 + 0x0a => "LDAP_REFERRAL",
  796 + 0x0b => "LDAP_ADMINLIMIT_EXCEEDED",
  797 + 0x0c => "LDAP_UNAVAILABLE_CRITICAL_EXTENSION",
  798 + 0x0d => "LDAP_CONFIDENTIALITY_REQUIRED",
  799 + 0x0e => "LDAP_SASL_BIND_INPROGRESS",
  800 + 0x10 => "LDAP_NO_SUCH_ATTRIBUTE",
  801 + 0x11 => "LDAP_UNDEFINED_TYPE",
  802 + 0x12 => "LDAP_INAPPROPRIATE_MATCHING",
  803 + 0x13 => "LDAP_CONSTRAINT_VIOLATION",
  804 + 0x14 => "LDAP_TYPE_OR_VALUE_EXISTS",
  805 + 0x15 => "LDAP_INVALID_SYNTAX",
  806 + 0x20 => "LDAP_NO_SUCH_OBJECT",
  807 + 0x21 => "LDAP_ALIAS_PROBLEM",
  808 + 0x22 => "LDAP_INVALID_DN_SYNTAX",
  809 + 0x23 => "LDAP_IS_LEAF",
  810 + 0x24 => "LDAP_ALIAS_DEREF_PROBLEM",
  811 + 0x30 => "LDAP_INAPPROPRIATE_AUTH",
  812 + 0x31 => "LDAP_INVALID_CREDENTIALS",
  813 + 0x32 => "LDAP_INSUFFICIENT_ACCESS",
  814 + 0x33 => "LDAP_BUSY",
  815 + 0x34 => "LDAP_UNAVAILABLE",
  816 + 0x35 => "LDAP_UNWILLING_TO_PERFORM",
  817 + 0x36 => "LDAP_LOOP_DETECT",
  818 + 0x3C => "LDAP_SORT_CONTROL_MISSING",
  819 + 0x3D => "LDAP_INDEX_RANGE_ERROR",
  820 + 0x40 => "LDAP_NAMING_VIOLATION",
  821 + 0x41 => "LDAP_OBJECT_CLASS_VIOLATION",
  822 + 0x42 => "LDAP_NOT_ALLOWED_ON_NONLEAF",
  823 + 0x43 => "LDAP_NOT_ALLOWED_ON_RDN",
  824 + 0x44 => "LDAP_ALREADY_EXISTS",
  825 + 0x45 => "LDAP_NO_OBJECT_CLASS_MODS",
  826 + 0x46 => "LDAP_RESULTS_TOO_LARGE",
  827 + 0x47 => "LDAP_AFFECTS_MULTIPLE_DSAS",
  828 + 0x50 => "LDAP_OTHER",
  829 + 0x51 => "LDAP_SERVER_DOWN",
  830 + 0x52 => "LDAP_LOCAL_ERROR",
  831 + 0x53 => "LDAP_ENCODING_ERROR",
  832 + 0x54 => "LDAP_DECODING_ERROR",
  833 + 0x55 => "LDAP_TIMEOUT",
  834 + 0x56 => "LDAP_AUTH_UNKNOWN",
  835 + 0x57 => "LDAP_FILTER_ERROR",
  836 + 0x58 => "LDAP_USER_CANCELLED",
  837 + 0x59 => "LDAP_PARAM_ERROR",
  838 + 0x5a => "LDAP_NO_MEMORY",
  839 + 0x5b => "LDAP_CONNECT_ERROR",
  840 + 0x5c => "LDAP_NOT_SUPPORTED",
  841 + 0x5d => "LDAP_CONTROL_NOT_FOUND",
  842 + 0x5e => "LDAP_NO_RESULTS_RETURNED",
  843 + 0x5f => "LDAP_MORE_RESULTS_TO_RETURN",
  844 + 0x60 => "LDAP_CLIENT_LOOP",
  845 + 0x61 => "LDAP_REFERRAL_LIMIT_EXCEEDED",
  846 + 1000 => "Unknown Net_LDAP error"
  847 + );
  848 +
  849 + return isset($errorMessages[$errorcode]) ? $errorMessages[$errorcode] : $errorMessages[NET_LDAP_ERROR];
  850 + }
  851 +
  852 + /**
  853 + * Tell whether value is a Net_LDAP_Error or not
  854 + *
  855 + * @access public
  856 + * @param mixed
  857 + * @return boolean
  858 + */
  859 + function isError($value)
  860 + {
  861 + return (is_a($value, "Net_LDAP_Error") || parent::isError($value));
  862 + }
  863 +
  864 + /**
  865 + * gets a root dse object
  866 + *
  867 + * @access public
  868 + * @author Jan Wagner <wagner@netsols.de>
  869 + * @param array Array of attributes to search for
  870 + * @return object mixed Net_LDAP_Error or Net_LDAP_RootDSE
  871 + */
  872 + function &rootDse($attrs = null)
  873 + {
  874 + require_once('Net/LDAP/RootDSE.php');
  875 +
  876 + if (is_array($attrs) && count($attrs) > 0 ) {
  877 + $attributes = $attrs;
  878 + } else {
  879 + $attributes = array('namingContexts',
  880 + 'altServer',
  881 + 'supportedExtension',
  882 + 'supportedControl',
  883 + 'supportedSASLMechanisms',
  884 + 'supportedLDAPVersion',
  885 + 'subschemaSubentry' );
  886 + }
  887 + $result = $this->search('', '(objectClass=*)', array('attributes' => $attributes, 'scope' => 'base'));
  888 + if (Net_LDAP::isError($result)) return $result;
  889 +
  890 + $entry = $result->shift_entry();
  891 + if (false === $entry) return $this->raiseError('Could not fetch RootDSE entry');
  892 +
  893 + return new Net_LDAP_RootDSE($entry);
  894 + }
  895 +
  896 + /**
  897 + * alias function of rootDse() for perl-ldap interface
  898 + *
  899 + * @access public
  900 + * @see rootDse()
  901 + */
  902 + function &root_dse()
  903 + {
  904 + $args = func_get_args();
  905 + return call_user_func_array(array($this, 'rootDse'), $args);
  906 + }
  907 +
  908 + /**
  909 + * get a schema object
  910 + *
  911 + * @access public
  912 + * @author Jan Wagner <wagner@netsols.de>
  913 + * @param string Subschema entry dn
  914 + * @return object mixed Net_LDAP_Schema or Net_LDAP_Error
  915 + */
  916 + function &schema($dn = null)
  917 + {
  918 + require_once('Net/LDAP/Schema.php');
  919 +
  920 + $schema =& new Net_LDAP_Schema();
  921 +
  922 + if (is_null($dn)) {
  923 + // get the subschema entry via root dse
  924 + $dse = $this->rootDSE(array('subschemaSubentry'));
  925 + if (false == Net_LDAP::isError($dse)) {
  926 + $base = $dse->getValue('subschemaSubentry', 'single');
  927 + if (!Net_LDAP::isError($base)) {
  928 + $dn = $base;
  929 + }
  930 + }
  931 + }
  932 + if (is_null($dn)) {
  933 + $dn = 'cn=Subschema';
  934 + }
  935 +
  936 + // fetch the subschema entry
  937 + $result = $this->search($dn, '(objectClass=*)',
  938 + array('attributes' => array_values($schema->types), 'scope' => 'base'));
  939 + if (Net_LDAP::isError($result)) {
  940 + return $result;
  941 + }
  942 +
  943 + $entry = $result->shift_entry();
  944 + if (false === $entry) {
  945 + return $this->raiseError('Could not fetch Subschema entry');
  946 + }
  947 +
  948 + $schema->parse($entry);
  949 +
  950 + return $schema;
  951 + }
  952 +
  953 + /**
  954 + * Encodes given attributes to UTF8 if needed
  955 + *
  956 + * This function takes attributes in an array and then checks against the schema if they need
  957 + * UTF8 encoding. If that is so, they will be encoded. An encoded array will be returned and
  958 + * can be used for adding or modifying.
  959 + *
  960 + * @access public
  961 + * @param array Array of attributes
  962 + * @return array Array of UTF8 encoded attributes
  963 + */
  964 + function utf8Encode($attributes)
  965 + {
  966 + return $this->_utf8($attributes, 'utf8_encode');
  967 + }
  968 +
  969 + /**
  970 + * Decodes the given attribute values
  971 + *
  972 + * @access public
  973 + * @param array Array of attributes
  974 + * @return array Array with decoded attribute values
  975 + */
  976 + function utf8Decode($attributes)
  977 + {
  978 + return $this->_utf8($attributes, 'utf8_decode');
  979 + }
  980 +
  981 + /**
  982 + * Encodes or decodes attribute values if needed
  983 + *
  984 + * @access private
  985 + * @param array Array of attributes
  986 + * @param array Function to apply to attribute values
  987 + * @return array Array of attributes with function applied to values
  988 + */
  989 + function _utf8($attributes, $function)
  990 + {
  991 + if (!$this->_schema) {
  992 + $this->_schema = $this->schema();
  993 + }
  994 +
  995 + if (!$this->_link || Net_LDAP::isError($this->_schema) || !function_exists($function)) {
  996 + return $attributes;
  997 + }
  998 +
  999 + if (is_array($attributes) && count($attributes) > 0) {
  1000 +
  1001 + foreach( $attributes as $k => $v ) {
  1002 +
  1003 + if (!isset($this->_schemaAttrs[$k])) {
  1004 +
  1005 + $attr = $this->_schema->get('attribute', $k);
  1006 + if (Net_LDAP::isError($attr)) {
  1007 + continue;
  1008 + }
  1009 +
  1010 + if (false !== strpos($attr['syntax'], '1.3.6.1.4.1.1466.115.121.1.15')) {
  1011 + $encode = true;
  1012 + } else {
  1013 + $encode = false;
  1014 + }
  1015 + $this->_schemaAttrs[$k] = $encode;
  1016 +
  1017 + } else {
  1018 + $encode = $this->_schemaAttrs[$k];
  1019 + }
  1020 +
  1021 + if ($encode) {
  1022 + if (is_array($v)) {
  1023 + foreach ($v as $ak => $av) {
  1024 + $v[$ak] = call_user_func($function, $av );
  1025 + }
  1026 + } else {
  1027 + $v = call_user_func($function, $v);
  1028 + }
  1029 + }
  1030 + $attributes[$k] = $v;
  1031 + }
  1032 + }
  1033 + return $attributes;
  1034 + }
  1035 +}
  1036 +
  1037 +/**
  1038 + * Net_LDAP_Error implements a class for reporting portable LDAP error messages.
  1039 + *
  1040 + * @package Net_LDAP
  1041 + */
  1042 +class Net_LDAP_Error extends PEAR_Error
  1043 +{
  1044 + /**
  1045 + * Net_LDAP_Error constructor.
  1046 + *
  1047 + * @param mixed Net_LDAP error code, or string with error message.
  1048 + * @param integer what "error mode" to operate in
  1049 + * @param integer what error level to use for $mode & PEAR_ERROR_TRIGGER
  1050 + * @param mixed additional debug info, such as the last query
  1051 + * @access public
  1052 + * @see PEAR_Error
  1053 + */
  1054 + function Net_LDAP_Error($code = NET_LDAP_ERROR, $mode = PEAR_ERROR_RETURN,
  1055 + $level = E_USER_NOTICE, $debuginfo = null)
  1056 + {
  1057 + $mode = PEAR_ERROR_RETURN;
  1058 + if (is_int($code)) {
  1059 + $this->PEAR_Error('Net_LDAP_Error: ' . Net_LDAP::errorMessage($code), $code, $mode, $level, $debuginfo);
  1060 + } else {
  1061 + $this->PEAR_Error("Net_LDAP_Error: $code", NET_LDAP_ERROR, $mode, $level, $debuginfo);
  1062 + }
  1063 + }
  1064 +}
  1065 +?>
... ...
thirdparty/pear/Net/LDAP/Entry.php 0 → 100644
  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 +// +--------------------------------------------------------------------------+
  24 +//
  25 +// $Id$
  26 +
  27 +/**
  28 + * This class represents an LDAP entry
  29 + *
  30 + * @package Net_LDAP
  31 + * @author Tarjei Huse
  32 + * @version $Revision$
  33 + */
  34 +class Net_LDAP_Entry extends PEAR
  35 +{
  36 + /**#@+
  37 + * Array of the attributes
  38 + *
  39 + * @access private
  40 + * @var array
  41 + */
  42 + var $_attrs = array();
  43 +
  44 + /**
  45 + * Array of attributes to be deleted upon update()
  46 + */
  47 + var $_delAttrs = array();
  48 +
  49 + /**
  50 + * Array of attributes to be modified upon update()
  51 + */
  52 + var $_modAttrs = array();
  53 +
  54 + /**
  55 + * Array of attributes to be added upon update()
  56 + */
  57 + var $_addAttrs = array();
  58 + /**#@-*/
  59 +
  60 + /**
  61 + * The distinguished name of the entry
  62 + *
  63 + * @access private
  64 + * @var string
  65 + */
  66 + var $_dn = '';
  67 +
  68 + /**
  69 + * LDAP resource link
  70 + *
  71 + * @access private
  72 + * @var resource
  73 + */
  74 + var $_link = null;
  75 +
  76 + /**
  77 + * Value of old DN if DN has changed
  78 + *
  79 + * @access private
  80 + * @var string
  81 + */
  82 + var $_olddn = '';
  83 +
  84 + /**#@+
  85 + * Array of errors for debugging class
  86 + *
  87 + * @access private
  88 + */
  89 + var $_error = array();
  90 +
  91 + /**
  92 + * updatechecks
  93 + */
  94 + var $updateCheck = array('newdn' => false,
  95 + 'modify' => false,
  96 + 'newEntry' => true
  97 + ); // since the entry is not changed before the update();
  98 +
  99 + /**
  100 + * Net_LDAP_Schema object TO BE REMOVED
  101 + */
  102 + var $_schema;
  103 + /**#@-*/
  104 +
  105 + /** Constructor
  106 + *
  107 + * @param - link - ldap_resource_link, dn = string entry dn, attributes - array entry attributes array.
  108 + * @return - none
  109 + **/
  110 + function Net_LDAP_Entry($link = null, $dn = null, $attributes = null)
  111 + {
  112 + if (!is_null($link)) {
  113 + $this->_link = $link;
  114 + }
  115 + if (!is_null($dn)) {
  116 + $this->_set_dn($dn);
  117 + }
  118 + if (is_array($attributes) && count($attributes) > 0) {
  119 + $this->_set_attributes($attributes);
  120 + } else {
  121 + $this->updateCheck['newEntry'] = true;
  122 + }
  123 + }
  124 +
  125 + /**
  126 + * Set the reasourcelink to the ldapserver.
  127 + *
  128 + * @access private
  129 + * @param resource LDAP link
  130 + */
  131 + function _set_link(&$link)
  132 + {
  133 + $this->_link = $link;
  134 + }
  135 +
  136 + /**
  137 + * set the entrys DN
  138 + *
  139 + * @access private
  140 + * @param string
  141 + */
  142 + function _set_dn($dn)
  143 + {
  144 + $this->_dn = $dn;
  145 + }
  146 +
  147 + /**
  148 + * sets the internal array of the entrys attributes.
  149 + *
  150 + * @access private
  151 + * @param array
  152 + */
  153 + function _set_attributes($attributes= array())
  154 + {
  155 + $this->_attrs = $attributes;
  156 + // this is the sign that the entry exists in the first place:
  157 + $this->updateCheck['newEntry'] = false;
  158 + }
  159 +
  160 + /**
  161 + * removes [count] entries from the array.
  162 + *
  163 + * remove all the count elements in the array:
  164 + * Used before ldap_modify, ldap_add
  165 + *
  166 + * @access private
  167 + * @return array Cleaned array of attributes
  168 + */
  169 + function _clean_entry()
  170 + {
  171 + $attributes = array();
  172 +
  173 + for ($i=0; $i < $this->_attrs['count'] ; $i++) {
  174 +
  175 + $attr = $this->_attrs[$i];
  176 +
  177 + if ($this->_attrs[$attr]['count'] == 1) {
  178 + $attributes[$this->_attrs[$i]] = $this->_attrs[$attr][0];
  179 + } else {
  180 + $attributes[$attr] = $this->_attrs[$attr];
  181 + unset ($attributes[ $attr ]['count']);
  182 + }
  183 + }
  184 +
  185 + return $attributes;
  186 +
  187 + }
  188 +
  189 + /**
  190 + * returns an assosiative array of all the attributes in the array
  191 + *
  192 + * attributes - returns an assosiative array of all the attributes in the array
  193 + * of the form array ('attributename'=>'singelvalue' , 'attribute'=>array('multiple','values'))
  194 + *
  195 + * @param none
  196 + * @return array Array of attributes and values.
  197 + */
  198 + function attributes()
  199 + {
  200 + return $this->_clean_entry();
  201 + }
  202 +
  203 + /**
  204 + * Add one or more attribute to the entry
  205 + *
  206 + * The values given will be added to the values which already exist for the given attributes.
  207 + * usage:
  208 + * $entry->add ( array('sn'=>'huse',objectclass=>array(top,posixAccount)))
  209 + *
  210 + * @param array Array of attributes
  211 + * @return mixed Net_Ldap_Error if error, else true.
  212 + */
  213 + function add($attr = array())
  214 + {
  215 + if (!isset($this->_attrs['count'])) {
  216 + $this->_attrs['count'] = 0;
  217 + }
  218 + if (!is_array($attr)) {
  219 + return $this->raiseError("Net_LDAP::add : the parameter supplied is not an array, $attr", 1000);
  220 + }
  221 + /* if you passed an empty array, that is your problem! */
  222 + if (count ($attr)==0) {
  223 + return true;
  224 + }
  225 + foreach ($attr as $k => $v ) {
  226 + // empty entrys should not be added to the entry.
  227 + if ($v == '') {
  228 + continue;
  229 + }
  230 +
  231 + if ($this->exists($k)) {
  232 + if (!is_array($this->_attrs[$k])) {
  233 + return $this->raiseError("Possible malformed array as parameter to Net_LDAP::add().");
  234 + }
  235 + array_push($this->_attrs[$k],$v);
  236 + $this->_attrs[$k]['count']++;
  237 + } else {
  238 + $this->_attrs[$k][0] = $v;
  239 + $this->_attrs[$k]['count'] = 1;
  240 + $this->_attrs[$this->_attrs['count']] = $k;
  241 + $this->_attrs['count']++;
  242 + }
  243 + // Fix for bug #952
  244 + if (empty($this->_addAttrs[$k])) {
  245 + $this->_addAttrs[$k] = array();
  246 + }
  247 + if (false == is_array($v)) {
  248 + $v = array($v);
  249 + }
  250 + foreach ($v as $value) {
  251 + array_push($this->_addAttrs[$k], $value);
  252 + }
  253 + }
  254 + return true;
  255 + }
  256 +
  257 + /**
  258 + * Set or get the DN for the object
  259 + *
  260 + * If a new dn is supplied, this will move the object when running $obj->update();
  261 + *
  262 + * @param string DN
  263 + */
  264 + function dn($newdn = '')
  265 + {
  266 + if ($newdn == '') {
  267 + return $this->_dn;
  268 + }
  269 +
  270 + $this->_olddn = $this->_dn;
  271 + $this->_dn = $newdn;
  272 + $this->updateCheck['newdn'] = true;
  273 + }
  274 +
  275 + /**
  276 + * check if a certain attribute exists in the directory
  277 + *
  278 + * @param string attribute name.
  279 + * @return boolean
  280 + */
  281 + function exists($attr)
  282 + {
  283 + if (array_key_exists($attr, $this->_attrs)) {
  284 + return true;
  285 + }
  286 + return false;
  287 + }
  288 +
  289 + /**
  290 + * get_value get the values for a attribute
  291 + *
  292 + * returns either an array or a string
  293 + * possible values for option:
  294 + * alloptions - returns an array with the values + a countfield.
  295 + * i.e.: array (count=>1, 'sn'=>'huse');
  296 + * single - returns the, first value in the array as a string.
  297 + *
  298 + * @param $attr string attribute name
  299 + * @param $options array
  300 + */
  301 + function get_value($attr = '', $options = '')
  302 + {
  303 + if (array_key_exists($attr, $this->_attrs)) {
  304 +
  305 + if ($options == 'single') {
  306 + if (is_array($this->_attrs[$attr])) {
  307 + return $this->_attrs[$attr][0];
  308 + } else {
  309 + return $this->_attrs[$attr];
  310 + }
  311 + }
  312 +
  313 + $value = $this->_attrs[$attr];
  314 +
  315 + if (!$options == 'alloptions') {
  316 + unset ($value['count']);
  317 + }
  318 + return $value;
  319 + } else {
  320 + return '';
  321 + }
  322 + }
  323 +
  324 + /**
  325 + * add/delete/modify attributes
  326 + *
  327 + * this function tries to do all the things that replace(),delete() and add() does on an object.
  328 + * Syntax:
  329 + * array ( 'attribute' => newval, 'delattribute' => '', newattrivute => newval);
  330 + * Note: You cannot use this function to modify parts of an attribute. You must modify the whole attribute.
  331 + * You may call the function many times before running $entry->update();
  332 + *
  333 + * @param array attributes to be modified
  334 + * @return mixed errorObject if failure, true if success.
  335 + */
  336 + function modify($attrs = array()) {
  337 +
  338 + if (!is_array($attrs) || count ($attrs) < 1 ) {
  339 + return $this->raiseError("You did not supply an array as expected",1000);
  340 + }
  341 +
  342 + foreach ($attrs as $k => $v) {
  343 + // empty values are deleted (ldap v3 handling is in update() )
  344 + if ($v == '' && $this->exists($k)) {
  345 + $this->_delAttrs[$k] = '';
  346 + continue;
  347 + }
  348 + /* existing attributes are modified*/
  349 + if ($this->exists($k) ) {
  350 + if (is_array($v)) {
  351 + $this->_modAttrs[$k] = $v;
  352 + } else {
  353 + $this->_modAttrs[$k][0] = $v;
  354 + }
  355 + } else {
  356 + /* new ones are created */
  357 + if (is_array($v) ) {
  358 + // an empty array is deleted...
  359 + if (count($v) == 0 ) {
  360 + $this->_delAttrs[$k] = '';
  361 + } else {
  362 + $this->_addAttrs[$k] = $v;
  363 + }
  364 + } else {
  365 + // dont't add empty attributes
  366 + if ($v != null) $this->_addAttrs[$k][0] = $v;
  367 + }
  368 + }
  369 + }
  370 + return true;
  371 + }
  372 +
  373 +
  374 + /**
  375 + * replace a certain attributes value
  376 + *
  377 + * replace - replace a certain attributes value
  378 + * example:
  379 + * $entry->replace(array('uid'=>array('tarjei')));
  380 + *
  381 + * @param array attributes to be replaced
  382 + * @return mixed error if failure, true if sucess.
  383 + */
  384 + function replace($attrs = array() )
  385 + {
  386 + foreach ($attrs as $k => $v) {
  387 +
  388 + if ($this->exists($k)) {
  389 +
  390 + if (is_array($v)) {
  391 + $this->_attrs[$k] = $v;
  392 + $this->_attrs[$k]['count'] = count($v);
  393 + $this->_modAttrs[$k] = $v;
  394 + } else {
  395 + $this->_attrs[$k]['count'] = 1;
  396 + $this->_attrs[$k][0] = $v;
  397 + $this->_modAttrs[$k][0] = $v;
  398 + }
  399 + } else {
  400 + return $this->raiseError("Attribute $k does not exist",16); // 16 = no such attribute exists.
  401 + }
  402 + }
  403 + return true;
  404 + }
  405 +
  406 + /**
  407 + * delete attributes
  408 + *
  409 + * Use this function to delete certain attributes from an object.
  410 + *
  411 + * @param - array of attributes to be deleted
  412 + * @return mixed Net_Ldap_Error if failure, true if success.
  413 + */
  414 + function delete($attrs = array())
  415 + {
  416 + foreach ($attrs as $k => $v) {
  417 +
  418 + if ($this->exists ($k)) {
  419 + // if v is a null, then remove the whole attribute, else only the value.
  420 + if ($v == '') {
  421 + unset($this->_attrs[$k]);
  422 + $this->_delAttrs[$k] = "";
  423 + // else we remove only the correct value.
  424 + } else {
  425 + for ($i = 0;$i< $this->_attrs[$k]['count'];$i++) {
  426 + if ($this->_attrs[$k][$i] == $v ) {
  427 + unset ($this->_attrs[$k][$i]);
  428 + $this->_delAttrs[$k] = $v;
  429 + continue;
  430 + }
  431 + }
  432 + }
  433 + } else {
  434 + $this->raiseError("You tried to delete a nonexisting attribute!",16);
  435 + }
  436 + }
  437 + return true;
  438 + }
  439 +
  440 + /**
  441 + * update the Entry in LDAP
  442 + *
  443 + * After modifying an object, you must run update() to
  444 + * make the updates on the ldap server. Before that, they only exists in the object.
  445 + *
  446 + * @param object Net_LDAP
  447 + * @return mixed Net_LDAP_Error object on failure or true on success
  448 + */
  449 + function update ($ldapObject = null)
  450 + {
  451 + if ($ldapObject == null && $this->_link == null ) {
  452 + $this->raiseError("No link to database");
  453 + }
  454 +
  455 + if ($ldapObject != null) {
  456 + $this->_link =& $ldapObject->_link;
  457 + }
  458 +
  459 + //if it's a new
  460 + if ($this->updateCheck['newdn'] && !$this->updateCheck['newEntry']) {
  461 + if (@ldap_get_option( $this->_link, LDAP_OPT_PROTOCOL_VERSION, $version) && $version != 3) {
  462 + return $this->raiseError("Moving or renaming an dn is only supported in LDAP V3!", 80);
  463 + }
  464 +
  465 + $newparent = ldap_explode_dn($this->_dn, 0);
  466 + unset($newparent['count']);
  467 + $relativeDn = array_shift($newparent);
  468 + $newparent = join(',', $newparent);
  469 +
  470 + if (!@ldap_rename($this->_link, $this->_olddn, $relativeDn, $newparent, true)) {
  471 + return $this->raiseError("DN not renamed: " . ldap_error($this->_link), ldap_errno($this->_link));
  472 + }
  473 + }
  474 +
  475 + if ($this->updateCheck['newEntry']) {
  476 + //print "<br>"; print_r($this->_clean_entry());
  477 +
  478 + if (!@ldap_add($this->_link, $this->dn(), $this->_clean_entry()) ) {
  479 + return $this->raiseError("Entry" . $this->dn() . " not added!" .
  480 + ldap_error($this->_link), ldap_errno($this->_link));
  481 + } else {
  482 + return true;
  483 + }
  484 + // update existing entry
  485 + } else {
  486 + $this->_error['first'] = $this->_modAttrs;
  487 + $this->_error['count'] = count($this->_modAttrs);
  488 +
  489 + // modified attributes
  490 + if (( count($this->_modAttrs)>0) &&
  491 + !ldap_modify($this->_link, $this->dn(), $this->_modAttrs))
  492 + {
  493 + return $this->raiseError("Entry " . $this->dn() . " not modified(attribs not modified): " .
  494 + ldap_error($this->_link),ldap_errno($this->_link));
  495 + }
  496 +
  497 + // attributes to be deleted
  498 + if (( count($this->_delAttrs) > 0 ))
  499 + {
  500 + // in ldap v3 we need to supply the old attribute values for deleting
  501 + if (@ldap_get_option( $this->_link, LDAP_OPT_PROTOCOL_VERSION, $version) && $version == 3) {
  502 + foreach ( $this->_delAttrs as $k => $v ) {
  503 + if ( $v == '' && $this->exists($k) ) {
  504 + $this->_delAttrs[$k] = $this->get_value( $k );
  505 + }
  506 + }
  507 + }
  508 + if ( !ldap_mod_del($this->_link, $this->dn(), $this->_delAttrs) ) {
  509 + return $this->raiseError("Entry " . $this->dn() . " not modified (attributes not deleted): " .
  510 + ldap_error($this->_link),ldap_errno($this->_link));
  511 + }
  512 + }
  513 +
  514 + // new attributes
  515 + if ((count($this->_addAttrs)) > 0 && !ldap_modify($this->_link, $this->dn(), $this->_addAttrs)) {
  516 + return $this->raiseError( "Entry " . $this->dn() . " not modified (attributes not added): " .
  517 + ldap_error($this->_link),ldap_errno($this->_link));
  518 + }
  519 + return true;
  520 + }
  521 + }
  522 +}
  523 +
  524 +?>
... ...
thirdparty/pear/Net/LDAP/RootDSE.php 0 → 100644
  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: Jan Wagner |
  23 +// +--------------------------------------------------------------------------+
  24 +//
  25 +// $Id$
  26 +
  27 +/**
  28 + * Getting the rootDSE entry of a LDAP server
  29 + *
  30 + * @package Net_LDAP
  31 + * @author Jan Wagner <wagner@netsols.de>
  32 + * @version $Revision$
  33 + */
  34 +class Net_LDAP_RootDSE extends PEAR
  35 +{
  36 + /**
  37 + * @access private
  38 + * @var object Net_LDAP_Entry
  39 + **/
  40 + var $_entry;
  41 +
  42 + /**
  43 + * class constructor
  44 + *
  45 + * @param object Net_LDAP_Entry
  46 + */
  47 + function Net_LDAP_RootDSE(&$entry)
  48 + {
  49 + $this->_entry = $entry;
  50 + }
  51 +
  52 + /**
  53 + * Gets the requested attribute value
  54 + *
  55 + * Same usuage as Net_LDAP_Entry::get_value()
  56 + *
  57 + * @access public
  58 + * @param string Attribute name
  59 + * @param array Array of options
  60 + * @return mixed Net_LDAP_Error object or attribute values
  61 + * @see Net_LDAP_Entry::get_value()
  62 + */
  63 + function getValue($attr = '', $options = '')
  64 + {
  65 + return $this->_entry->get_value($attr, $options);
  66 + }
  67 +
  68 + /**
  69 + * alias function of getValue() for perl-ldap interface
  70 + *
  71 + * @see getValue()
  72 + */
  73 + function get_value()
  74 + {
  75 + $args = func_get_args();
  76 + return call_user_func_array(array($this, 'getValue' ), $args);
  77 + }
  78 +
  79 + /**
  80 + * Determines if the extension is supported
  81 + *
  82 + * @access public
  83 + * @param array Array of oids to check
  84 + * @return boolean
  85 + */
  86 + function supportedExtension($oids)
  87 + {
  88 + return $this->_checkAttr($oids, 'supportedExtension');
  89 + }
  90 +
  91 + /**
  92 + * alias function of supportedExtension() for perl-ldap interface
  93 + *
  94 + * @see supportedExtension()
  95 + */
  96 + function supported_extension()
  97 + {
  98 + $args = func_get_args();
  99 + return call_user_func_array(array($this, 'supportedExtension'), $args);
  100 + }
  101 +
  102 + /**
  103 + * Determines if the version is supported
  104 + *
  105 + * @access public
  106 + * @param array Versions to check
  107 + * @return boolean
  108 + */
  109 + function supportedVersion($versions)
  110 + {
  111 + return $this->_checkAttr($versions, 'supportedLDAPVersion');
  112 + }
  113 +
  114 + /**
  115 + * alias function of supportedVersion() for perl-ldap interface
  116 + *
  117 + * @see supportedVersion()
  118 + */
  119 + function supported_version()
  120 + {
  121 + $args = func_get_args();
  122 + return call_user_func_array(array($this, 'supportedVersion'), $args);
  123 + }
  124 +
  125 + /**
  126 + * Determines if the control is supported
  127 + *
  128 + * @access public
  129 + * @param array Control oids to check
  130 + * @return boolean
  131 + */
  132 + function supportedControl($oids)
  133 + {
  134 + return $this->_checkAttr($oids, 'supportedControl');
  135 + }
  136 +
  137 + /**
  138 + * alias function of supportedControl() for perl-ldap interface
  139 + *
  140 + * @see supportedControl()
  141 + */
  142 + function supported_control()
  143 + {
  144 + $args = func_get_args();
  145 + return call_user_func_array(array($this, 'supportedControl' ), $args);
  146 + }
  147 +
  148 + /**
  149 + * Determines if the sasl mechanism is supported
  150 + *
  151 + * @access public
  152 + * @param array SASL mechanisms to check
  153 + * @return boolean
  154 + */
  155 + function supportedSASLMechanism($mechlist)
  156 + {
  157 + return $this->_checkAttr($mechlist, 'supportedSASLMechanisms');
  158 + }
  159 +
  160 + /**
  161 + * alias function of supportedSASLMechanism() for perl-ldap interface
  162 + *
  163 + * @see supportedSASLMechanism()
  164 + */
  165 + function supported_sasl_mechanism()
  166 + {
  167 + $args = func_get_args();
  168 + return call_user_func_array(array($this, 'supportedSASLMechanism'), $args);
  169 + }
  170 +
  171 + /**
  172 + * Checks for existance of value in attribute
  173 + *
  174 + * @access private
  175 + * @param array $values values to check
  176 + * @param attr $attr attribute name
  177 + * @return boolean
  178 + */
  179 + function _checkAttr($values, $attr)
  180 + {
  181 + if (!is_array($values)) $values = array($values);
  182 +
  183 + foreach ($values as $value) {
  184 + if (!@in_array($value, $this->get_value($attr))) {
  185 + return false;
  186 + }
  187 + }
  188 + return true;
  189 + }
  190 +}
  191 +
  192 +?>
0 193 \ No newline at end of file
... ...
thirdparty/pear/Net/LDAP/Schema.php 0 → 100644
  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: Jan Wagner |
  23 +// +--------------------------------------------------------------------------+
  24 +//
  25 +// $Id$
  26 +
  27 +/**
  28 + * Load an LDAP Schema and provide information
  29 + *
  30 + * This class takes a Subschema entry, parses this information
  31 + * and makes it available in an array. Most of the code has been
  32 + * inspired by perl-ldap( http://perl-ldap.sourceforge.net).
  33 + * You will find portions of their implementation in here.
  34 + *
  35 + * @package Net_LDAP
  36 + * @author Jan Wagner <wagner@netsols.de>
  37 + * @version $Revision$
  38 + */
  39 + class Net_LDAP_Schema extends PEAR
  40 + {
  41 + /**
  42 + * Map of entry types to ldap attributes of subschema entry
  43 + *
  44 + * @access public
  45 + * @var array
  46 + */
  47 + var $types = array('attribute' => 'attributeTypes',
  48 + 'ditcontentrule' => 'dITContentRules',
  49 + 'ditstructurerule' => 'dITStructureRules',
  50 + 'matchingrule' => 'matchingRules',
  51 + 'matchingruleuse' => 'matchingRuleUse',
  52 + 'nameform' => 'nameForms',
  53 + 'objectclass' => 'objectClasses',
  54 + 'syntax' => 'ldapSyntaxes');
  55 +
  56 + /**#@+
  57 + * Array of entries belonging to this type
  58 + *
  59 + * @access private
  60 + * @var array
  61 + */
  62 + var $_attributeTypes = array();
  63 + var $_matchingRules = array();
  64 + var $_matchingRuleUse = array();
  65 + var $_ldapSyntaxes = array();
  66 + var $_objectClasses = array();
  67 + var $_dITContentRules = array();
  68 + var $_dITStructureRules = array();
  69 + var $_nameForms = array();
  70 + /**#@-*/
  71 +
  72 + /**
  73 + * hash of all fetched oids
  74 + *
  75 + * @access private
  76 + * @var array
  77 + */
  78 + var $_oids = array();
  79 +
  80 + /**
  81 + * constructor of the class
  82 + *
  83 + * @access protected
  84 + */
  85 + function Net_LDAP_Schema()
  86 + {
  87 + $this->PEAR('Net_LDAP_Error'); // default error class
  88 + }
  89 +
  90 + /**
  91 + * Return a hash of entries for the given type
  92 + *
  93 + * Returns a hash of entry for th givene type. Types may be:
  94 + * objectclasses, attributes, ditcontentrules, ditstructurerules, matchingrules,
  95 + * matchingruleuses, nameforms, syntaxes
  96 + *
  97 + * @access public
  98 + * @param string Type to fetch
  99 + * @return mixed Array or Net_LDAP_Error
  100 + */
  101 + function &getAll($type)
  102 + {
  103 + $map = array('objectclasses' => &$this->_objectClasses,
  104 + 'attributes' => &$this->_attributeTypes,
  105 + 'ditcontentrules' => &$this->_dITContentRules,
  106 + 'ditstructurerules' => &$this->_dITStructureRules,
  107 + 'matchingrules' => &$this->_matchingRules,
  108 + 'matchingruleuses' => &$this->_matchingRuleUse,
  109 + 'nameforms' => &$this->_nameForms,
  110 + 'syntaxes' => &$this->_ldapSyntaxes );
  111 +
  112 + $key = strtolower($type);
  113 + return ((key_exists($key, $map)) ? $map[$key] : $this->raiseError("Unknown type $type"));
  114 + }
  115 +
  116 + /**
  117 + * Return a specific entry
  118 + *
  119 + * @access public
  120 + * @param string Type of name
  121 + * @param string Name or OID to fetch
  122 + * @return mixed Entry or Net_LDAP_Error
  123 + */
  124 + function &get($type, $name)
  125 + {
  126 + $type = strtolower($type);
  127 + if (false == key_exists($type, $this->types)) {
  128 + return $this->raiseError("No such type $type");
  129 + }
  130 +
  131 + $name = strtolower($name);
  132 + $type_var = &$this->{'_' . $this->types[$type]};
  133 +
  134 + if( key_exists($name, $type_var)) {
  135 + return $type_var[$name];
  136 + } elseif(key_exists($name, $this->_oids) && $this->_oids[$name]['type'] == $type) {
  137 + return $this->_oids[$name];
  138 + } else {
  139 + return $this->raiseError("Could not find $type $name");
  140 + }
  141 + }
  142 +
  143 +
  144 + /**
  145 + * Fetches attributes that MAY be present in the given objectclass
  146 + *
  147 + * @access public
  148 + * @param string Name or OID of objectclass
  149 + * @return mixed Array with attributes or Net_LDAP_Error
  150 + */
  151 + function may($oc)
  152 + {
  153 + return $this->_getAttr($oc, 'may');
  154 + }
  155 +
  156 + /**
  157 + * Fetches attributes that MUST be present in the given objectclass
  158 + *
  159 + * @access public
  160 + * @param string Name or OID of objectclass
  161 + * @return mixed Array with attributes or Net_LDAP_Error
  162 + */
  163 + function must($oc)
  164 + {
  165 + return $this->_getAttr($oc, 'must');
  166 + }
  167 +
  168 + /**
  169 + * Fetches the given attribute from the given objectclass
  170 + *
  171 + * @access private
  172 + * @param string Name or OID of objectclass
  173 + * @param string Name of attribute to fetch
  174 + * @return mixed The attribute or Net_LDAP_Error
  175 + */
  176 + function _getAttr($oc, $attr)
  177 + {
  178 + $oc = strtolower($oc);
  179 + if (key_exists($oc, $this->_objectClasses) && key_exists($attr, $this->_objectClasses[$oc])) {
  180 + return $this->_objectClasses[$oc][$attr];
  181 + }
  182 + elseif (key_exists($oc, $this->_oids) &&
  183 + $this->_oids[$oc]['type'] == 'objectclass' &&
  184 + key_exists($attr, $this->_oids[$oc])) {
  185 + return $this->_oids[$oc][$attr];
  186 + } else {
  187 + return $this->raiseError("Could not find $attr attributes for $oc ");
  188 + }
  189 + }
  190 +
  191 + /**
  192 + * Returns the name(s) of the immediate superclass(es)
  193 + *
  194 + * @param string Name or OID of objectclass
  195 + * @return mixed Array of names or Net_LDAP_Error
  196 + */
  197 + function superclass($oc)
  198 + {
  199 + $o = $this->get('objectclass', $oc);
  200 + if (Net_LDAP::isError($o)) {
  201 + return $o;
  202 + }
  203 + return (key_exists('sup', $o) ? $o['sup'] : array());
  204 + }
  205 +
  206 + /**
  207 + * Parses the schema of the given Subschema entry
  208 + *
  209 + * @access public
  210 + * @param object Net_LDAP_Entry Subschema entry
  211 + */
  212 + function parse(&$entry)
  213 + {
  214 + foreach ($this->types as $type => $attr)
  215 + {
  216 + // initialize map type to entry
  217 + $type_var = '_' . $attr;
  218 + $this->{$type_var} = array();
  219 +
  220 + // get values for this type
  221 + $values = $entry->get_value($attr);
  222 +
  223 + if (is_array($values))
  224 + {
  225 + foreach ($values as $value) {
  226 +
  227 + unset($schema_entry); // this was a real mess without it
  228 +
  229 + // get the schema entry
  230 + $schema_entry = $this->_parse_entry($value);
  231 +
  232 + // set the type
  233 + $schema_entry['type'] = $type;
  234 +
  235 + // save a ref in $_oids
  236 + $this->_oids[$schema_entry['oid']] =& $schema_entry;
  237 +
  238 + // save refs for all names in type map
  239 + $names = $schema_entry['aliases'];
  240 + array_push($names, $schema_entry['name']);
  241 + foreach ($names as $name) {
  242 + $this->{$type_var}[strtolower($name)] =& $schema_entry;
  243 + }
  244 + }
  245 + }
  246 + }
  247 + }
  248 +
  249 + /**
  250 + * parses an attribute value into a schema entry
  251 + *
  252 + * @access private
  253 + * @param string Attribute value
  254 + * @return mixed Schema entry array or false
  255 + */
  256 + function &_parse_entry($value)
  257 + {
  258 + // tokens that have no value associated
  259 + $noValue = array('single-value',
  260 + 'obsolete',
  261 + 'collective',
  262 + 'no-user-modification',
  263 + 'abstract',
  264 + 'structural',
  265 + 'auxiliary');
  266 +
  267 + // tokens that can have multiple values
  268 + $multiValue = array('must', 'may', 'sup');
  269 +
  270 + $schema_entry = array('aliases' => array()); // initilization
  271 +
  272 + $tokens = $this->_tokenize($value); // get an array of tokens
  273 +
  274 + // remove surrounding brackets
  275 + if ($tokens[0] == '(') array_shift($tokens);
  276 + if ($tokens[count($tokens) - 1] == ')') array_pop($tokens); // -1 doesnt work on arrays :-(
  277 +
  278 + $schema_entry['oid'] = array_shift($tokens); // first token is the oid
  279 +
  280 + // cycle over the tokens until none are left
  281 + while (count($tokens) > 0) {
  282 + $token = strtolower(array_shift($tokens));
  283 + if (in_array($token, $noValue)) {
  284 + $schema_entry[$token] = 1; // single value token
  285 + } else {
  286 + // this one follows a string or a list if it is multivalued
  287 + if (($schema_entry[$token] = array_shift($tokens)) == '(') {
  288 + // this creates the list of values and cycles through the tokens
  289 + // until the end of the list is reached ')'
  290 + $schema_entry[$token] = array();
  291 + while ($tmp = array_shift($tokens)) {
  292 + if ($tmp == ')') break;
  293 + if ($tmp != '$') array_push($schema_entry[$token], $tmp);
  294 + }
  295 + }
  296 + // create a array if the value should be multivalued but was not
  297 + if (in_array($token, $multiValue ) && !is_array($schema_entry[$token])) {
  298 + $schema_entry[$token] = array($schema_entry[$token]);
  299 + }
  300 + }
  301 + }
  302 + // get max length from syntax
  303 + if (key_exists('syntax', $schema_entry)) {
  304 + if (preg_match('/{(\d+)}/', $schema_entry['syntax'], $matches)) {
  305 + $schema_entry['max_length'] = $matches[1];
  306 + }
  307 + }
  308 + // force a name
  309 + if (empty($schema_entry['name'])) {
  310 + $schema_entry['name'] = $schema_entry['oid'];
  311 + }
  312 + // make one name the default and put the other ones into aliases
  313 + if (is_array($schema_entry['name'])) {
  314 + $aliases = $schema_entry['name'];
  315 + $schema_entry['name'] = array_shift($aliases);
  316 + $schema_entry['aliases'] = $aliases;
  317 + }
  318 + return $schema_entry;
  319 + }
  320 +
  321 + /**
  322 + * tokenizes the given value into an array of tokens
  323 + *
  324 + * @access private
  325 + * @param string String to parse
  326 + * @return array Array of tokens
  327 + */
  328 + function _tokenize($value)
  329 + {
  330 + $tokens = array(); // array of tokens
  331 + $matches = array(); // matches[0] full pattern match, [1,2,3] subpatterns
  332 +
  333 + // this one is taken from perl-ldap, modified for php
  334 + $pattern = "/\s* (?:([()]) | ([^'\s()]+) | '((?:[^']+|'[^\s)])*)') \s*/x";
  335 +
  336 + /**
  337 + * This one matches one big pattern wherin only one of the three subpatterns matched
  338 + * We are interested in the subpatterns that matched. If it matched its value will be
  339 + * non-empty and so it is a token. Tokens may be round brackets, a string, or a string
  340 + * enclosed by '
  341 + */
  342 + preg_match_all($pattern, $value, $matches);
  343 +
  344 + for ($i = 0; $i < count($matches[0]); $i++) { // number of tokens (full pattern match)
  345 + for ($j = 1; $j < 4; $j++) { // each subpattern
  346 + if (null != trim($matches[$j][$i])) { // pattern match in this subpattern
  347 + $tokens[$i] = trim($matches[$j][$i]); // this is the token
  348 + }
  349 + }
  350 + }
  351 + return $tokens;
  352 + }
  353 + }
  354 +
  355 +?>
0 356 \ No newline at end of file
... ...
thirdparty/pear/Net/LDAP/Search.php 0 → 100644
  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 +// +--------------------------------------------------------------------------+
  24 +//
  25 +// $Id$
  26 +
  27 +/**
  28 + * Result set of an LDAP search
  29 + *
  30 + * @author Tarjei Huse
  31 + * @version $Revision$
  32 + * @package Net_LDAP
  33 + */
  34 +class Net_LDAP_Search extends PEAR
  35 +{
  36 + /**
  37 + * Search result identifier
  38 + *
  39 + * @access private
  40 + * @var resource
  41 + */
  42 + var $_search;
  43 +
  44 + /**
  45 + * LDAP resource link
  46 + *
  47 + * @access private
  48 + * @var resource
  49 + */
  50 + var $_link;
  51 +
  52 + /**
  53 + * Array of entries
  54 + *
  55 + * @access private
  56 + * @var array
  57 + */
  58 + var $_entries = array();
  59 +
  60 + /**
  61 + * Result entry identifier
  62 + *
  63 + * @access private
  64 + * @var resource
  65 + */
  66 + var $_elink = null;
  67 +
  68 + /**
  69 + * The errorcode the search got
  70 + *
  71 + * Some errorcodes might be of interest, but might not be best handled as errors.
  72 + * examples: 4 - LDAP_SIZELIMIT_EXCEEDED - indecates a huge search.
  73 + * Incomplete results are returned. If you just want to check if there's anything in the search.
  74 + * than this is a point to handle.
  75 + * 32 - no such object - search here returns a count of 0.
  76 + *
  77 + * @access private
  78 + * @var int
  79 + */
  80 + var $_errorCode = 0; // if not set - sucess!
  81 +
  82 + /**
  83 + * Constructor
  84 + *
  85 + * @access protected
  86 + * @param resource Search result identifier
  87 + * @param resource Link identifier
  88 + */
  89 + function Net_LDAP_Search (&$search, &$link)
  90 + {
  91 + $this->_setSearch($search, $link);
  92 + $this->_errorCode = ldap_errno($link);
  93 + }
  94 +
  95 + /**
  96 + * Returns an assosiative array of entry objects
  97 + *
  98 + * @return array Array of entry objects.
  99 + */
  100 + function entries()
  101 + {
  102 + if ($this->count() == 0) {
  103 + return array();
  104 + }
  105 +
  106 + $this->_elink = @ldap_first_entry( $this->_link,$this->_search);
  107 + $entry = new Net_LDAP_Entry($this->_link,
  108 + @ldap_get_dn($this->_link, $this->_elink),
  109 + @ldap_get_attributes($this->_link, $this->_elink));
  110 + array_push($this->_entries, $entry);
  111 +
  112 + while ($this->_elink = @ldap_next_entry($this->_link,$this->_elink)) {
  113 + $entry = new Net_LDAP_Entry($this->_link,
  114 + @ldap_get_dn($this->_link, $this->_elink),
  115 + @ldap_get_attributes($this->_link, $this->_elink));
  116 + array_push($this->_entries, $entry);
  117 + }
  118 + return $this->_entries;
  119 + }
  120 +
  121 + /**
  122 + * Get the next entry in the searchresult.
  123 + *
  124 + * @return mixed Net_LDAP_Entry object or false
  125 + */
  126 + function shiftEntry()
  127 + {
  128 + if ($this->count() == 0 ) {
  129 + return false;
  130 + }
  131 +
  132 + if (is_null($this->_elink)) {
  133 + $this->_elink = @ldap_first_entry($this->_link, $this->_search);
  134 + $entry = new Net_LDAP_Entry($this->_link,
  135 + ldap_get_dn($this->_link, $this->_elink),
  136 + ldap_get_attributes($this->_link, $this->_elink));
  137 + } else {
  138 + if (!$this->_elink = ldap_next_entry($this->_link, $this->_elink)) {
  139 + return false;
  140 + }
  141 + $entry = new Net_LDAP_Entry($this->_link,
  142 + ldap_get_dn($this->_link,$this->_elink),
  143 + ldap_get_attributes($this->_link,$this->_elink));
  144 + }
  145 + return $entry;
  146 + }
  147 +
  148 + /**
  149 + * alias function of shiftEntry() for perl-ldap interface
  150 + *
  151 + * @see shiftEntry()
  152 + */
  153 + function shift_entry()
  154 + {
  155 + $args = func_get_args();
  156 + return call_user_func_array(array($this, 'shiftEntry'), $args);
  157 + }
  158 +
  159 + /**
  160 + * Retrieve the last entry of the searchset. NOT IMPLEMENTED
  161 + *
  162 + * @return object Net_LDAP_Error
  163 + */
  164 + function pop_entry ()
  165 + {
  166 + $this->raiseError("Not implemented");
  167 + }
  168 +
  169 + /**
  170 + * Return entries sorted NOT IMPLEMENTED
  171 + *
  172 + * @param array Array of sort attributes
  173 + * @return object Net_LDAP_Error
  174 + */
  175 + function sorted ($attrs = array())
  176 + {
  177 + $this->raiseError("Not impelented");
  178 + }
  179 +
  180 + /**
  181 + * Return entries as object NOT IMPLEMENTED
  182 + *
  183 + * @return object Net_LDAP_Error
  184 + */
  185 + function as_struct ()
  186 + {
  187 + $this->raiseError("Not implemented");
  188 + }
  189 +
  190 + /**
  191 + * Set the searchobjects resourcelinks
  192 + *
  193 + * @access private
  194 + * @param resource Search result identifier
  195 + * @param resource Resource link identifier
  196 + */
  197 + function _setSearch(&$search,&$link)
  198 + {
  199 + $this->_search = $search;
  200 + $this->_link = $link;
  201 + }
  202 +
  203 + /**
  204 + * Returns the number of entries in the searchresult
  205 + *
  206 + * @return int Number of entries in search.
  207 + */
  208 + function count()
  209 + {
  210 + /* this catches the situation where OL returned errno 32 = no such object! */
  211 + if (!$this->_search) {
  212 + return 0;
  213 + }
  214 + return @ldap_count_entries($this->_link, $this->_search);
  215 + }
  216 +
  217 + /**
  218 + * Get the errorcode the object got in its search.
  219 + *
  220 + * @return int The ldap error number.
  221 + */
  222 + function getErrorCode()
  223 + {
  224 + return $this->_errorCode;
  225 + }
  226 +
  227 + /** Destructor
  228 + *
  229 + * @access protected
  230 + */
  231 + function _Net_LDAP_Search()
  232 + {
  233 + @ldap_free_result($this->_search);
  234 + }
  235 +
  236 + /**
  237 + * Closes search result
  238 + */
  239 + function done()
  240 + {
  241 + $this->_Net_LDAP_Search();
  242 + }
  243 +}
  244 +
  245 +?>
... ...
thirdparty/pear/Net/LDAP/Util.php 0 → 100644
  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: Jan Wagner |
  23 +// +--------------------------------------------------------------------------+
  24 +//
  25 +// $Id$
  26 +
  27 +/**
  28 + * Utility Class for Net_LDAP
  29 + *
  30 + * @package Net_LDAP
  31 + * @author Jan Wagner <wagner@netsols.de>
  32 + * @version $Revision$
  33 + */
  34 +class Net_LDAP_Util extends PEAR
  35 +{
  36 + /**
  37 + * Reference to LDAP object
  38 + *
  39 + * @access private
  40 + * @var object Net_LDAP
  41 + */
  42 + var $_ldap = null;
  43 +
  44 + /**
  45 + * Net_LDAP_Schema object
  46 + *
  47 + * @access private
  48 + * @var object Net_LDAP_Schema
  49 + */
  50 + var $_schema = null;
  51 +
  52 + /**
  53 + * Constructur
  54 + *
  55 + * Takes an LDAP object by reference and saves it. Then the schema will be fetched.
  56 + *
  57 + * @access public
  58 + * @param object Net_LDAP
  59 + */
  60 + function Net_LDAP_Util(&$ldap)
  61 + {
  62 + if (is_object($ldap) && (strtolower(get_class($ldap)) == 'net_ldap')) {
  63 + $this->_ldap = $ldap;
  64 + $this->_schema = $this->_ldap->schema();
  65 + if (Net_LDAP::isError($this->_schema)) $this->_schema = null;
  66 + }
  67 + }
  68 +
  69 + /**
  70 + * Encodes given attributes to UTF8 if needed
  71 + *
  72 + * This function takes attributes in an array and then checks against the schema if they need
  73 + * UTF8 encoding. If that is so, they will be encoded. An encoded array will be returned and
  74 + * can be used for adding or modifying.
  75 + *
  76 + * @access public
  77 + * @param array Array of attributes
  78 + * @return array Array of UTF8 encoded attributes
  79 + */
  80 + function utf8Encode($attributes)
  81 + {
  82 + return $this->_utf8($attributes, 'utf8_encode');
  83 + }
  84 +
  85 + /**
  86 + * Decodes the given attribute values
  87 + *
  88 + * @access public
  89 + * @param array Array of attributes
  90 + * @return array Array with decoded attribute values
  91 + */
  92 + function utf8Decode($attributes)
  93 + {
  94 + return $this->_utf8($attributes, 'utf8_decode');
  95 + }
  96 +
  97 + /**
  98 + * Encodes or decodes attribute values if needed
  99 + *
  100 + * @access private
  101 + * @param array Array of attributes
  102 + * @param array Function to apply to attribute values
  103 + * @return array Array of attributes with function applied to values
  104 + */
  105 + function _utf8($attributes, $function)
  106 + {
  107 + if (!$this->_ldap || !$this->_schema || !function_exists($function)) {
  108 + return $attributes;
  109 + }
  110 + if (is_array($attributes) && count($attributes) > 0) {
  111 + foreach( $attributes as $k => $v ) {
  112 + $attr = $this->_schema->get('attribute', $k);
  113 + if (Net_LDAP::isError($attr)) {
  114 + continue;
  115 + }
  116 + if (false !== strpos($attr['syntax'], '1.3.6.1.4.1.1466.115.121.1.15')) {
  117 + if (is_array($v)) {
  118 + foreach ($v as $ak => $av ) {
  119 + $v[$ak] = call_user_func($function, $av );
  120 + }
  121 + } else {
  122 + $v = call_user_func($function, $v);
  123 + }
  124 + }
  125 + $attributes[$k] = $v;
  126 + }
  127 + }
  128 + return $attributes;
  129 + }
  130 +}
  131 +
  132 +?>
... ...
thirdparty/pear/Net/LDAP/fg.php 0 → 100644
  1 +<?php
  2 +
  3 +require_once('../../../../config/dmsDefaults.php');
  4 +require_once(KT_LIB_DIR . '/authentication/authenticationutil.inc.php');
  5 +require_once(KT_LIB_DIR . '/authentication/authenticationsource.inc.php');
  6 +
  7 +require_once('Net/LDAP.php');
  8 +
  9 +$oKTConfig =& KTConfig::getSingleton();
  10 +
  11 +$oAuthenticator = KTAuthenticationUtil::getAuthenticatorForSource(2);
  12 +
  13 +$config = array(
  14 + 'dn' => $oAuthenticator->sSearchUser,
  15 + 'password' => $oAuthenticator->sSearchPassword,
  16 + 'host' => $oAuthenticator->sLdapServer,
  17 + 'base' => $oAuthenticator->sBaseDN,
  18 +);
  19 +
  20 +$oLdap =& Net_LDAP::connect($config);
  21 +if (PEAR::isError($oLdap)) {
  22 + var_dump($oLdap);
  23 + exit(0);
  24 +}
  25 +
  26 +$aParams = array(
  27 + 'scope' => 'sub',
  28 + 'attributes' => array('cn', 'dn', 'displayClass'),
  29 +);
  30 +$rootDn = $oAuthenticator->sBaseDN;
  31 +if (is_array($rootDn)) {
  32 + $rootDn = join(",", $rootDn);
  33 +}
  34 +$oResults = $oLdap->search($rootDn, '(objectClass=group)', $aParams);
  35 +foreach ($oResults->entries() as $oEntry) {
  36 + var_dump($oEntry->dn());
  37 +}
  38 +
... ...