Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / adodb / drivers / adodb-ldap.inc.php
blob147cd9eda40b5d0d70a2c52ef44a08ad9b50d8e1
1 <?php
2 /*
3 V4.98 13 Feb 2008 (c) 2000-2008 John Lim (jlim#natsoft.com.my). All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence.
7 Set tabs to 8.
9 Revision 1: (02/25/2005) Updated codebase to include the _inject_bind_options function. This allows
10 users to access the options in the ldap_set_option function appropriately. Most importantly
11 LDAP Version 3 is now supported. See the examples for more information. Also fixed some minor
12 bugs that surfaced when PHP error levels were set high.
14 Joshua Eldridge (joshuae74#hotmail.com)
15 */
17 // security - hide paths
18 if (!defined('ADODB_DIR')) die();
20 if (!defined('LDAP_ASSOC')) {
21 define('LDAP_ASSOC',ADODB_FETCH_ASSOC);
22 define('LDAP_NUM',ADODB_FETCH_NUM);
23 define('LDAP_BOTH',ADODB_FETCH_BOTH);
26 class ADODB_ldap extends ADOConnection {
27 var $databaseType = 'ldap';
28 var $dataProvider = 'ldap';
30 # Connection information
31 var $username = false;
32 var $password = false;
34 # Used during searches
35 var $filter;
36 var $dn;
37 var $version;
38 var $port = 389;
40 # Options configuration information
41 var $LDAP_CONNECT_OPTIONS;
43 # error on binding, eg. "Binding: invalid credentials"
44 var $_bind_errmsg = "Binding: %s";
46 function ADODB_ldap()
50 // returns true or false
51 function _connect( $host, $username, $password, $ldapbase)
53 global $LDAP_CONNECT_OPTIONS;
55 if ( !function_exists( 'ldap_connect' ) ) return null;
57 $conn_info = array( $host,$this->port);
59 if ( strstr( $host, ':' ) ) {
60 $conn_info = split( ':', $host );
63 $this->_connectionID = @ldap_connect( $conn_info[0], $conn_info[1] );
64 if (!$this->_connectionID) {
65 $e = 'Could not connect to ' . $conn_info[0];
66 $this->_errorMsg = $e;
67 if ($this->debug) ADOConnection::outp($e);
68 return false;
70 if( count( $LDAP_CONNECT_OPTIONS ) > 0 ) {
71 $this->_inject_bind_options( $LDAP_CONNECT_OPTIONS );
74 if ($username) {
75 $bind = @ldap_bind( $this->_connectionID, $username, $password );
76 } else {
77 $username = 'anonymous';
78 $bind = @ldap_bind( $this->_connectionID );
81 if (!$bind) {
82 $e = sprintf($this->_bind_errmsg,ldap_error($this->_connectionID));;
83 $this->_errorMsg = $e;
84 if ($this->debug) ADOConnection::outp($e);
85 return false;
87 $this->_errorMsg = '';
88 $this->database = $ldapbase;
89 return $this->_connectionID;
93 Valid Domain Values for LDAP Options:
95 LDAP_OPT_DEREF (integer)
96 LDAP_OPT_SIZELIMIT (integer)
97 LDAP_OPT_TIMELIMIT (integer)
98 LDAP_OPT_PROTOCOL_VERSION (integer)
99 LDAP_OPT_ERROR_NUMBER (integer)
100 LDAP_OPT_REFERRALS (boolean)
101 LDAP_OPT_RESTART (boolean)
102 LDAP_OPT_HOST_NAME (string)
103 LDAP_OPT_ERROR_STRING (string)
104 LDAP_OPT_MATCHED_DN (string)
105 LDAP_OPT_SERVER_CONTROLS (array)
106 LDAP_OPT_CLIENT_CONTROLS (array)
108 Make sure to set this BEFORE calling Connect()
110 Example:
112 $LDAP_CONNECT_OPTIONS = Array(
113 Array (
114 "OPTION_NAME"=>LDAP_OPT_DEREF,
115 "OPTION_VALUE"=>2
117 Array (
118 "OPTION_NAME"=>LDAP_OPT_SIZELIMIT,
119 "OPTION_VALUE"=>100
121 Array (
122 "OPTION_NAME"=>LDAP_OPT_TIMELIMIT,
123 "OPTION_VALUE"=>30
125 Array (
126 "OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION,
127 "OPTION_VALUE"=>3
129 Array (
130 "OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER,
131 "OPTION_VALUE"=>13
133 Array (
134 "OPTION_NAME"=>LDAP_OPT_REFERRALS,
135 "OPTION_VALUE"=>FALSE
137 Array (
138 "OPTION_NAME"=>LDAP_OPT_RESTART,
139 "OPTION_VALUE"=>FALSE
144 function _inject_bind_options( $options ) {
145 foreach( $options as $option ) {
146 ldap_set_option( $this->_connectionID, $option["OPTION_NAME"], $option["OPTION_VALUE"] )
147 or die( "Unable to set server option: " . $option["OPTION_NAME"] );
151 /* returns _queryID or false */
152 function _query($sql,$inputarr)
154 $rs = @ldap_search( $this->_connectionID, $this->database, $sql );
155 $this->_errorMsg = ($rs) ? '' : 'Search error on '.$sql.': '. ldap_error($this->_connectionID);
156 return $rs;
159 function ErrorMsg()
161 return $this->_errorMsg;
164 function ErrorNo()
166 return @ldap_errno($this->_connectionID);
169 /* closes the LDAP connection */
170 function _close()
172 @ldap_close( $this->_connectionID );
173 $this->_connectionID = false;
176 function SelectDB($db) {
177 $this->database = $db;
178 return true;
179 } // SelectDB
181 function ServerInfo()
183 if( !empty( $this->version ) ) return $this->version;
184 $version = array();
186 Determines how aliases are handled during search.
187 LDAP_DEREF_NEVER (0x00)
188 LDAP_DEREF_SEARCHING (0x01)
189 LDAP_DEREF_FINDING (0x02)
190 LDAP_DEREF_ALWAYS (0x03)
191 The LDAP_DEREF_SEARCHING value means aliases are dereferenced during the search but
192 not when locating the base object of the search. The LDAP_DEREF_FINDING value means
193 aliases are dereferenced when locating the base object but not during the search.
194 Default: LDAP_DEREF_NEVER
196 ldap_get_option( $this->_connectionID, LDAP_OPT_DEREF, $version['LDAP_OPT_DEREF'] ) ;
197 switch ( $version['LDAP_OPT_DEREF'] ) {
198 case 0:
199 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER';
200 case 1:
201 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING';
202 case 2:
203 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING';
204 case 3:
205 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_ALWAYS';
209 A limit on the number of entries to return from a search.
210 LDAP_NO_LIMIT (0) means no limit.
211 Default: LDAP_NO_LIMIT
213 ldap_get_option( $this->_connectionID, LDAP_OPT_SIZELIMIT, $version['LDAP_OPT_SIZELIMIT'] );
214 if ( $version['LDAP_OPT_SIZELIMIT'] == 0 ) {
215 $version['LDAP_OPT_SIZELIMIT'] = 'LDAP_NO_LIMIT';
219 A limit on the number of seconds to spend on a search.
220 LDAP_NO_LIMIT (0) means no limit.
221 Default: LDAP_NO_LIMIT
223 ldap_get_option( $this->_connectionID, LDAP_OPT_TIMELIMIT, $version['LDAP_OPT_TIMELIMIT'] );
224 if ( $version['LDAP_OPT_TIMELIMIT'] == 0 ) {
225 $version['LDAP_OPT_TIMELIMIT'] = 'LDAP_NO_LIMIT';
229 Determines whether the LDAP library automatically follows referrals returned by LDAP servers or not.
230 LDAP_OPT_ON
231 LDAP_OPT_OFF
232 Default: ON
234 ldap_get_option( $this->_connectionID, LDAP_OPT_REFERRALS, $version['LDAP_OPT_REFERRALS'] );
235 if ( $version['LDAP_OPT_REFERRALS'] == 0 ) {
236 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_OFF';
237 } else {
238 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON';
242 Determines whether LDAP I/O operations are automatically restarted if they abort prematurely.
243 LDAP_OPT_ON
244 LDAP_OPT_OFF
245 Default: OFF
247 ldap_get_option( $this->_connectionID, LDAP_OPT_RESTART, $version['LDAP_OPT_RESTART'] );
248 if ( $version['LDAP_OPT_RESTART'] == 0 ) {
249 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_OFF';
250 } else {
251 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_ON';
255 This option indicates the version of the LDAP protocol used when communicating with the primary LDAP server.
256 LDAP_VERSION2 (2)
257 LDAP_VERSION3 (3)
258 Default: LDAP_VERSION2 (2)
260 ldap_get_option( $this->_connectionID, LDAP_OPT_PROTOCOL_VERSION, $version['LDAP_OPT_PROTOCOL_VERSION'] );
261 if ( $version['LDAP_OPT_PROTOCOL_VERSION'] == 2 ) {
262 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION2';
263 } else {
264 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION3';
267 /* The host name (or list of hosts) for the primary LDAP server. */
268 ldap_get_option( $this->_connectionID, LDAP_OPT_HOST_NAME, $version['LDAP_OPT_HOST_NAME'] );
269 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_NUMBER, $version['LDAP_OPT_ERROR_NUMBER'] );
270 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_STRING, $version['LDAP_OPT_ERROR_STRING'] );
271 ldap_get_option( $this->_connectionID, LDAP_OPT_MATCHED_DN, $version['LDAP_OPT_MATCHED_DN'] );
273 return $this->version = $version;
278 /*--------------------------------------------------------------------------------------
279 Class Name: Recordset
280 --------------------------------------------------------------------------------------*/
282 class ADORecordSet_ldap extends ADORecordSet{
284 var $databaseType = "ldap";
285 var $canSeek = false;
286 var $_entryID; /* keeps track of the entry resource identifier */
288 function ADORecordSet_ldap($queryID,$mode=false)
290 if ($mode === false) {
291 global $ADODB_FETCH_MODE;
292 $mode = $ADODB_FETCH_MODE;
294 switch ($mode)
296 case ADODB_FETCH_NUM:
297 $this->fetchMode = LDAP_NUM;
298 break;
299 case ADODB_FETCH_ASSOC:
300 $this->fetchMode = LDAP_ASSOC;
301 break;
302 case ADODB_FETCH_DEFAULT:
303 case ADODB_FETCH_BOTH:
304 default:
305 $this->fetchMode = LDAP_BOTH;
306 break;
309 $this->ADORecordSet($queryID);
312 function _initrs()
315 This could be teaked to respect the $COUNTRECS directive from ADODB
316 It's currently being used in the _fetch() function and the
317 GetAssoc() function
319 $this->_numOfRows = ldap_count_entries( $this->connection->_connectionID, $this->_queryID );
324 Return whole recordset as a multi-dimensional associative array
326 function &GetAssoc($force_array = false, $first2cols = false)
328 $records = $this->_numOfRows;
329 $results = array();
330 for ( $i=0; $i < $records; $i++ ) {
331 foreach ( $this->fields as $k=>$v ) {
332 if ( is_array( $v ) ) {
333 if ( $v['count'] == 1 ) {
334 $results[$i][$k] = $v[0];
335 } else {
336 array_shift( $v );
337 $results[$i][$k] = $v;
343 return $results;
346 function &GetRowAssoc()
348 $results = array();
349 foreach ( $this->fields as $k=>$v ) {
350 if ( is_array( $v ) ) {
351 if ( $v['count'] == 1 ) {
352 $results[$k] = $v[0];
353 } else {
354 array_shift( $v );
355 $results[$k] = $v;
360 return $results;
363 function GetRowNums()
365 $results = array();
366 foreach ( $this->fields as $k=>$v ) {
367 static $i = 0;
368 if (is_array( $v )) {
369 if ( $v['count'] == 1 ) {
370 $results[$i] = $v[0];
371 } else {
372 array_shift( $v );
373 $results[$i] = $v;
375 $i++;
378 return $results;
381 function _fetch()
383 if ( $this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0 )
384 return false;
386 if ( $this->_currentRow == 0 ) {
387 $this->_entryID = ldap_first_entry( $this->connection->_connectionID, $this->_queryID );
388 } else {
389 $this->_entryID = ldap_next_entry( $this->connection->_connectionID, $this->_entryID );
392 $this->fields = ldap_get_attributes( $this->connection->_connectionID, $this->_entryID );
393 $this->_numOfFields = $this->fields['count'];
394 switch ( $this->fetchMode ) {
396 case LDAP_ASSOC:
397 $this->fields = $this->GetRowAssoc();
398 break;
400 case LDAP_NUM:
401 $this->fields = array_merge($this->GetRowNums(),$this->GetRowAssoc());
402 break;
404 case LDAP_BOTH:
405 default:
406 $this->fields = $this->GetRowNums();
407 break;
409 return ( is_array( $this->fields ) );
412 function _close() {
413 @ldap_free_result( $this->_queryID );
414 $this->_queryID = false;