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

Last change on this file since 136 was 136, checked in by mabarracus, 3 years ago

Ported code to xenial

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