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.
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)
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
40 # Options configuration information
41 var $LDAP_CONNECT_OPTIONS;
43 # error on binding, eg. "Binding: invalid credentials"
44 var $_bind_errmsg = "Binding: %s";
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);
70 if( count( $LDAP_CONNECT_OPTIONS ) > 0 ) {
71 $this->_inject_bind_options( $LDAP_CONNECT_OPTIONS );
75 $bind = @ldap_bind
( $this->_connectionID
, $username, $password );
77 $username = 'anonymous';
78 $bind = @ldap_bind
( $this->_connectionID
);
82 $e = sprintf($this->_bind_errmsg
,ldap_error($this->_connectionID
));;
83 $this->_errorMsg
= $e;
84 if ($this->debug
) ADOConnection
::outp($e);
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()
112 $LDAP_CONNECT_OPTIONS = Array(
114 "OPTION_NAME"=>LDAP_OPT_DEREF,
118 "OPTION_NAME"=>LDAP_OPT_SIZELIMIT,
122 "OPTION_NAME"=>LDAP_OPT_TIMELIMIT,
126 "OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION,
130 "OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER,
134 "OPTION_NAME"=>LDAP_OPT_REFERRALS,
135 "OPTION_VALUE"=>FALSE
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
);
161 return $this->_errorMsg
;
166 return @ldap_errno
($this->_connectionID
);
169 /* closes the LDAP connection */
172 @ldap_close
( $this->_connectionID
);
173 $this->_connectionID
= false;
176 function SelectDB($db) {
177 $this->database
= $db;
181 function ServerInfo()
183 if( !empty( $this->version
) ) return $this->version
;
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'] ) {
199 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER';
201 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING';
203 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING';
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.
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';
238 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON';
242 Determines whether LDAP I/O operations are automatically restarted if they abort prematurely.
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';
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.
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';
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;
296 case ADODB_FETCH_NUM
:
297 $this->fetchMode
= LDAP_NUM
;
299 case ADODB_FETCH_ASSOC
:
300 $this->fetchMode
= LDAP_ASSOC
;
302 case ADODB_FETCH_DEFAULT
:
303 case ADODB_FETCH_BOTH
:
305 $this->fetchMode
= LDAP_BOTH
;
309 $this->ADORecordSet($queryID);
315 This could be teaked to respect the $COUNTRECS directive from ADODB
316 It's currently being used in the _fetch() function and the
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
;
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];
337 $results[$i][$k] = $v;
346 function &GetRowAssoc()
349 foreach ( $this->fields
as $k=>$v ) {
350 if ( is_array( $v ) ) {
351 if ( $v['count'] == 1 ) {
352 $results[$k] = $v[0];
363 function GetRowNums()
366 foreach ( $this->fields
as $k=>$v ) {
368 if (is_array( $v )) {
369 if ( $v['count'] == 1 ) {
370 $results[$i] = $v[0];
383 if ( $this->_currentRow
>= $this->_numOfRows
&& $this->_numOfRows
>= 0 )
386 if ( $this->_currentRow
== 0 ) {
387 $this->_entryID
= ldap_first_entry( $this->connection
->_connectionID
, $this->_queryID
);
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
) {
397 $this->fields
= $this->GetRowAssoc();
401 $this->fields
= array_merge($this->GetRowNums(),$this->GetRowAssoc());
406 $this->fields
= $this->GetRowNums();
409 return ( is_array( $this->fields
) );
413 @ldap_free_result
( $this->_queryID
);
414 $this->_queryID
= false;