source: moodle/trunk/fuentes/lib/adodb/drivers/adodb-ldap.inc.php @ 1331

Last change on this file since 1331 was 1331, checked in by jrpelegrina, 3 years ago

Updated to moodle 3.0.3

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