1 | <?php
|
---|
2 | /*
|
---|
3 | V4.94 23 Jan 2007 (c) 2000-2007 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 | ?> |
---|