See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
1 <?php 2 /** 3 * LDAP driver. 4 * 5 * Provides a subset of ADOdb commands, allowing read-only access to an LDAP database. 6 * 7 * This file is part of ADOdb, a Database Abstraction Layer library for PHP. 8 * 9 * @package ADOdb 10 * @link https://adodb.org Project's web site and documentation 11 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker 12 * 13 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause 14 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, 15 * any later version. This means you can use it in proprietary products. 16 * See the LICENSE.md file distributed with this source code for details. 17 * @license BSD-3-Clause 18 * @license LGPL-2.1-or-later 19 * 20 * @copyright 2000-2013 John Lim 21 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community 22 * @author Joshua Eldridge <joshuae74@hotmail.com> 23 */ 24 25 // security - hide paths 26 if (!defined('ADODB_DIR')) die(); 27 28 if (!defined('LDAP_ASSOC')) { 29 define('LDAP_ASSOC',ADODB_FETCH_ASSOC); 30 define('LDAP_NUM',ADODB_FETCH_NUM); 31 define('LDAP_BOTH',ADODB_FETCH_BOTH); 32 } 33 34 class ADODB_ldap extends ADOConnection { 35 var $databaseType = 'ldap'; 36 var $dataProvider = 'ldap'; 37 38 # Connection information 39 var $username = false; 40 var $password = false; 41 42 # Used during searches 43 var $filter; 44 var $dn; 45 var $version; 46 var $port = 389; 47 48 # Options configuration information 49 var $LDAP_CONNECT_OPTIONS; 50 51 # error on binding, eg. "Binding: invalid credentials" 52 var $_bind_errmsg = "Binding: %s"; 53 54 // returns true or false 55 56 function _connect( $host, $username, $password, $ldapbase) 57 { 58 global $LDAP_CONNECT_OPTIONS; 59 60 if ( !function_exists( 'ldap_connect' ) ) return null; 61 62 if (strpos($host,'ldap://') === 0 || strpos($host,'ldaps://') === 0) { 63 $this->_connectionID = @ldap_connect($host); 64 } else { 65 $conn_info = array( $host,$this->port); 66 67 if ( strstr( $host, ':' ) ) { 68 $conn_info = explode( ':', $host ); 69 } 70 71 $this->_connectionID = @ldap_connect( $conn_info[0], $conn_info[1] ); 72 } 73 if (!$this->_connectionID) { 74 $e = 'Could not connect to ' . $conn_info[0]; 75 $this->_errorMsg = $e; 76 if ($this->debug) ADOConnection::outp($e); 77 return false; 78 } 79 if( count( $LDAP_CONNECT_OPTIONS ) > 0 ) { 80 $this->_inject_bind_options( $LDAP_CONNECT_OPTIONS ); 81 } 82 83 if ($username) { 84 $bind = @ldap_bind( $this->_connectionID, $username, $password ); 85 } else { 86 $username = 'anonymous'; 87 $bind = @ldap_bind( $this->_connectionID ); 88 } 89 90 if (!$bind) { 91 $e = sprintf($this->_bind_errmsg,ldap_error($this->_connectionID)); 92 $this->_errorMsg = $e; 93 if ($this->debug) ADOConnection::outp($e); 94 return false; 95 } 96 $this->_errorMsg = ''; 97 $this->database = $ldapbase; 98 return $this->_connectionID; 99 } 100 101 /* 102 Valid Domain Values for LDAP Options: 103 104 LDAP_OPT_DEREF (integer) 105 LDAP_OPT_SIZELIMIT (integer) 106 LDAP_OPT_TIMELIMIT (integer) 107 LDAP_OPT_PROTOCOL_VERSION (integer) 108 LDAP_OPT_ERROR_NUMBER (integer) 109 LDAP_OPT_REFERRALS (boolean) 110 LDAP_OPT_RESTART (boolean) 111 LDAP_OPT_HOST_NAME (string) 112 LDAP_OPT_ERROR_STRING (string) 113 LDAP_OPT_MATCHED_DN (string) 114 LDAP_OPT_SERVER_CONTROLS (array) 115 LDAP_OPT_CLIENT_CONTROLS (array) 116 117 Make sure to set this BEFORE calling Connect() 118 119 Example: 120 121 $LDAP_CONNECT_OPTIONS = Array( 122 Array ( 123 "OPTION_NAME"=>LDAP_OPT_DEREF, 124 "OPTION_VALUE"=>2 125 ), 126 Array ( 127 "OPTION_NAME"=>LDAP_OPT_SIZELIMIT, 128 "OPTION_VALUE"=>100 129 ), 130 Array ( 131 "OPTION_NAME"=>LDAP_OPT_TIMELIMIT, 132 "OPTION_VALUE"=>30 133 ), 134 Array ( 135 "OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION, 136 "OPTION_VALUE"=>3 137 ), 138 Array ( 139 "OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER, 140 "OPTION_VALUE"=>13 141 ), 142 Array ( 143 "OPTION_NAME"=>LDAP_OPT_REFERRALS, 144 "OPTION_VALUE"=>FALSE 145 ), 146 Array ( 147 "OPTION_NAME"=>LDAP_OPT_RESTART, 148 "OPTION_VALUE"=>FALSE 149 ) 150 ); 151 */ 152 153 function _inject_bind_options( $options ) { 154 foreach( $options as $option ) { 155 ldap_set_option( $this->_connectionID, $option["OPTION_NAME"], $option["OPTION_VALUE"] ) 156 or die( "Unable to set server option: " . $option["OPTION_NAME"] ); 157 } 158 } 159 160 /* returns _queryID or false */ 161 function _query($sql,$inputarr=false) 162 { 163 $rs = @ldap_search( $this->_connectionID, $this->database, $sql ); 164 $this->_errorMsg = ($rs) ? '' : 'Search error on '.$sql.': '.ldap_error($this->_connectionID); 165 return $rs; 166 } 167 168 function ErrorMsg() 169 { 170 return $this->_errorMsg; 171 } 172 173 function ErrorNo() 174 { 175 return @ldap_errno($this->_connectionID); 176 } 177 178 /* closes the LDAP connection */ 179 function _close() 180 { 181 @ldap_close( $this->_connectionID ); 182 $this->_connectionID = false; 183 } 184 185 function SelectDB($db) { 186 $this->database = $db; 187 return true; 188 } // SelectDB 189 190 function ServerInfo() 191 { 192 if( !empty( $this->version ) ) { 193 return $this->version; 194 } 195 196 $version = array(); 197 /* 198 Determines how aliases are handled during search. 199 LDAP_DEREF_NEVER (0x00) 200 LDAP_DEREF_SEARCHING (0x01) 201 LDAP_DEREF_FINDING (0x02) 202 LDAP_DEREF_ALWAYS (0x03) 203 The LDAP_DEREF_SEARCHING value means aliases are dereferenced during the search but 204 not when locating the base object of the search. The LDAP_DEREF_FINDING value means 205 aliases are dereferenced when locating the base object but not during the search. 206 Default: LDAP_DEREF_NEVER 207 */ 208 ldap_get_option( $this->_connectionID, LDAP_OPT_DEREF, $version['LDAP_OPT_DEREF'] ) ; 209 switch ( $version['LDAP_OPT_DEREF'] ) { 210 case 0: 211 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER'; 212 case 1: 213 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING'; 214 case 2: 215 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING'; 216 case 3: 217 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_ALWAYS'; 218 } 219 220 /* 221 A limit on the number of entries to return from a search. 222 LDAP_NO_LIMIT (0) means no limit. 223 Default: LDAP_NO_LIMIT 224 */ 225 ldap_get_option( $this->_connectionID, LDAP_OPT_SIZELIMIT, $version['LDAP_OPT_SIZELIMIT'] ); 226 if ( $version['LDAP_OPT_SIZELIMIT'] == 0 ) { 227 $version['LDAP_OPT_SIZELIMIT'] = 'LDAP_NO_LIMIT'; 228 } 229 230 /* 231 A limit on the number of seconds to spend on a search. 232 LDAP_NO_LIMIT (0) means no limit. 233 Default: LDAP_NO_LIMIT 234 */ 235 ldap_get_option( $this->_connectionID, LDAP_OPT_TIMELIMIT, $version['LDAP_OPT_TIMELIMIT'] ); 236 if ( $version['LDAP_OPT_TIMELIMIT'] == 0 ) { 237 $version['LDAP_OPT_TIMELIMIT'] = 'LDAP_NO_LIMIT'; 238 } 239 240 /* 241 Determines whether the LDAP library automatically follows referrals returned by LDAP servers or not. 242 LDAP_OPT_ON 243 LDAP_OPT_OFF 244 Default: ON 245 */ 246 ldap_get_option( $this->_connectionID, LDAP_OPT_REFERRALS, $version['LDAP_OPT_REFERRALS'] ); 247 if ( $version['LDAP_OPT_REFERRALS'] == 0 ) { 248 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_OFF'; 249 } else { 250 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON'; 251 } 252 253 /* 254 Determines whether LDAP I/O operations are automatically restarted if they abort prematurely. 255 LDAP_OPT_ON 256 LDAP_OPT_OFF 257 Default: OFF 258 */ 259 ldap_get_option( $this->_connectionID, LDAP_OPT_RESTART, $version['LDAP_OPT_RESTART'] ); 260 if ( $version['LDAP_OPT_RESTART'] == 0 ) { 261 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_OFF'; 262 } else { 263 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_ON'; 264 } 265 266 /* 267 This option indicates the version of the LDAP protocol used when communicating with the primary LDAP server. 268 LDAP_VERSION2 (2) 269 LDAP_VERSION3 (3) 270 Default: LDAP_VERSION2 (2) 271 */ 272 ldap_get_option( $this->_connectionID, LDAP_OPT_PROTOCOL_VERSION, $version['LDAP_OPT_PROTOCOL_VERSION'] ); 273 if ( $version['LDAP_OPT_PROTOCOL_VERSION'] == 2 ) { 274 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION2'; 275 } else { 276 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION3'; 277 } 278 279 /* The host name (or list of hosts) for the primary LDAP server. */ 280 ldap_get_option( $this->_connectionID, LDAP_OPT_HOST_NAME, $version['LDAP_OPT_HOST_NAME'] ); 281 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_NUMBER, $version['LDAP_OPT_ERROR_NUMBER'] ); 282 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_STRING, $version['LDAP_OPT_ERROR_STRING'] ); 283 ldap_get_option( $this->_connectionID, LDAP_OPT_MATCHED_DN, $version['LDAP_OPT_MATCHED_DN'] ); 284 285 return $this->version = $version; 286 } 287 } 288 289 /*-------------------------------------------------------------------------------------- 290 Class Name: Recordset 291 --------------------------------------------------------------------------------------*/ 292 293 class ADORecordSet_ldap extends ADORecordSet{ 294 295 var $databaseType = "ldap"; 296 var $canSeek = false; 297 var $_entryID; /* keeps track of the entry resource identifier */ 298 299 function __construct($queryID,$mode=false) 300 { 301 if ($mode === false) { 302 global $ADODB_FETCH_MODE; 303 $mode = $ADODB_FETCH_MODE; 304 } 305 switch ($mode) 306 { 307 case ADODB_FETCH_NUM: 308 $this->fetchMode = LDAP_NUM; 309 break; 310 case ADODB_FETCH_ASSOC: 311 $this->fetchMode = LDAP_ASSOC; 312 break; 313 case ADODB_FETCH_DEFAULT: 314 case ADODB_FETCH_BOTH: 315 default: 316 $this->fetchMode = LDAP_BOTH; 317 break; 318 } 319 320 parent::__construct($queryID); 321 } 322 323 function _initrs() 324 { 325 /* 326 This could be teaked to respect the $COUNTRECS directive from ADODB 327 It's currently being used in the _fetch() function and the 328 GetAssoc() function 329 */ 330 $this->_numOfRows = ldap_count_entries( $this->connection->_connectionID, $this->_queryID ); 331 } 332 333 /* 334 Return whole recordset as a multi-dimensional associative array 335 */ 336 function GetAssoc($force_array = false, $first2cols = false, $fetchMode = -1) 337 { 338 $records = $this->_numOfRows; 339 $results = array(); 340 for ( $i=0; $i < $records; $i++ ) { 341 foreach ( $this->fields as $k=>$v ) { 342 if ( is_array( $v ) ) { 343 if ( $v['count'] == 1 ) { 344 $results[$i][$k] = $v[0]; 345 } else { 346 array_shift( $v ); 347 $results[$i][$k] = $v; 348 } 349 } 350 } 351 } 352 353 return $results; 354 } 355 356 function GetRowAssoc($upper = ADODB_ASSOC_CASE) 357 { 358 $results = array(); 359 foreach ( $this->fields as $k=>$v ) { 360 if ( is_array( $v ) ) { 361 if ( $v['count'] == 1 ) { 362 $results[$k] = $v[0]; 363 } else { 364 array_shift( $v ); 365 $results[$k] = $v; 366 } 367 } 368 } 369 370 return $results; 371 } 372 373 function GetRowNums() 374 { 375 $results = array(); 376 foreach ( $this->fields as $k=>$v ) { 377 static $i = 0; 378 if (is_array( $v )) { 379 if ( $v['count'] == 1 ) { 380 $results[$i] = $v[0]; 381 } else { 382 array_shift( $v ); 383 $results[$i] = $v; 384 } 385 $i++; 386 } 387 } 388 return $results; 389 } 390 391 function _fetch() 392 { 393 if ( $this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0 ) { 394 return false; 395 } 396 397 if ( $this->_currentRow == 0 ) { 398 $this->_entryID = ldap_first_entry( $this->connection->_connectionID, $this->_queryID ); 399 } else { 400 $this->_entryID = ldap_next_entry( $this->connection->_connectionID, $this->_entryID ); 401 } 402 403 $this->fields = ldap_get_attributes( $this->connection->_connectionID, $this->_entryID ); 404 $this->_numOfFields = $this->fields['count']; 405 406 switch ( $this->fetchMode ) { 407 408 case LDAP_ASSOC: 409 $this->fields = $this->GetRowAssoc(); 410 break; 411 412 case LDAP_NUM: 413 $this->fields = array_merge($this->GetRowNums(),$this->GetRowAssoc()); 414 break; 415 416 case LDAP_BOTH: 417 default: 418 $this->fields = $this->GetRowNums(); 419 break; 420 } 421 422 return is_array( $this->fields ); 423 } 424 425 function _close() { 426 @ldap_free_result( $this->_queryID ); 427 $this->_queryID = false; 428 } 429 430 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body