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