|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /* 00003 V5.14 8 Sept 2011 (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved. 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. 00007 Set tabs to 8. 00008 00009 Revision 1: (02/25/2005) Updated codebase to include the _inject_bind_options function. This allows 00010 users to access the options in the ldap_set_option function appropriately. Most importantly 00011 LDAP Version 3 is now supported. See the examples for more information. Also fixed some minor 00012 bugs that surfaced when PHP error levels were set high. 00013 00014 Joshua Eldridge (joshuae74#hotmail.com) 00015 */ 00016 00017 // security - hide paths 00018 if (!defined('ADODB_DIR')) die(); 00019 00020 if (!defined('LDAP_ASSOC')) { 00021 define('LDAP_ASSOC',ADODB_FETCH_ASSOC); 00022 define('LDAP_NUM',ADODB_FETCH_NUM); 00023 define('LDAP_BOTH',ADODB_FETCH_BOTH); 00024 } 00025 00026 class ADODB_ldap extends ADOConnection { 00027 var $databaseType = 'ldap'; 00028 var $dataProvider = 'ldap'; 00029 00030 # Connection information 00031 var $username = false; 00032 var $password = false; 00033 00034 # Used during searches 00035 var $filter; 00036 var $dn; 00037 var $version; 00038 var $port = 389; 00039 00040 # Options configuration information 00041 var $LDAP_CONNECT_OPTIONS; 00042 00043 # error on binding, eg. "Binding: invalid credentials" 00044 var $_bind_errmsg = "Binding: %s"; 00045 00046 function ADODB_ldap() 00047 { 00048 } 00049 00050 // returns true or false 00051 00052 function _connect( $host, $username, $password, $ldapbase) 00053 { 00054 global $LDAP_CONNECT_OPTIONS; 00055 00056 if ( !function_exists( 'ldap_connect' ) ) return null; 00057 00058 if (strpos('ldap://',$host) === 0 || strpos('ldaps://',$host) === 0) { 00059 $this->_connectionID = @ldap_connect($host); 00060 } else { 00061 $conn_info = array( $host,$this->port); 00062 00063 if ( strstr( $host, ':' ) ) { 00064 $conn_info = explode( ':', $host ); 00065 } 00066 00067 $this->_connectionID = @ldap_connect( $conn_info[0], $conn_info[1] ); 00068 } 00069 if (!$this->_connectionID) { 00070 $e = 'Could not connect to ' . $conn_info[0]; 00071 $this->_errorMsg = $e; 00072 if ($this->debug) ADOConnection::outp($e); 00073 return false; 00074 } 00075 if( count( $LDAP_CONNECT_OPTIONS ) > 0 ) { 00076 $this->_inject_bind_options( $LDAP_CONNECT_OPTIONS ); 00077 } 00078 00079 if ($username) { 00080 $bind = @ldap_bind( $this->_connectionID, $username, $password ); 00081 } else { 00082 $username = 'anonymous'; 00083 $bind = @ldap_bind( $this->_connectionID ); 00084 } 00085 00086 if (!$bind) { 00087 $e = sprintf($this->_bind_errmsg,ldap_error($this->_connectionID)); 00088 $this->_errorMsg = $e; 00089 if ($this->debug) ADOConnection::outp($e); 00090 return false; 00091 } 00092 $this->_errorMsg = ''; 00093 $this->database = $ldapbase; 00094 return $this->_connectionID; 00095 } 00096 00097 /* 00098 Valid Domain Values for LDAP Options: 00099 00100 LDAP_OPT_DEREF (integer) 00101 LDAP_OPT_SIZELIMIT (integer) 00102 LDAP_OPT_TIMELIMIT (integer) 00103 LDAP_OPT_PROTOCOL_VERSION (integer) 00104 LDAP_OPT_ERROR_NUMBER (integer) 00105 LDAP_OPT_REFERRALS (boolean) 00106 LDAP_OPT_RESTART (boolean) 00107 LDAP_OPT_HOST_NAME (string) 00108 LDAP_OPT_ERROR_STRING (string) 00109 LDAP_OPT_MATCHED_DN (string) 00110 LDAP_OPT_SERVER_CONTROLS (array) 00111 LDAP_OPT_CLIENT_CONTROLS (array) 00112 00113 Make sure to set this BEFORE calling Connect() 00114 00115 Example: 00116 00117 $LDAP_CONNECT_OPTIONS = Array( 00118 Array ( 00119 "OPTION_NAME"=>LDAP_OPT_DEREF, 00120 "OPTION_VALUE"=>2 00121 ), 00122 Array ( 00123 "OPTION_NAME"=>LDAP_OPT_SIZELIMIT, 00124 "OPTION_VALUE"=>100 00125 ), 00126 Array ( 00127 "OPTION_NAME"=>LDAP_OPT_TIMELIMIT, 00128 "OPTION_VALUE"=>30 00129 ), 00130 Array ( 00131 "OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION, 00132 "OPTION_VALUE"=>3 00133 ), 00134 Array ( 00135 "OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER, 00136 "OPTION_VALUE"=>13 00137 ), 00138 Array ( 00139 "OPTION_NAME"=>LDAP_OPT_REFERRALS, 00140 "OPTION_VALUE"=>FALSE 00141 ), 00142 Array ( 00143 "OPTION_NAME"=>LDAP_OPT_RESTART, 00144 "OPTION_VALUE"=>FALSE 00145 ) 00146 ); 00147 */ 00148 00149 function _inject_bind_options( $options ) { 00150 foreach( $options as $option ) { 00151 ldap_set_option( $this->_connectionID, $option["OPTION_NAME"], $option["OPTION_VALUE"] ) 00152 or die( "Unable to set server option: " . $option["OPTION_NAME"] ); 00153 } 00154 } 00155 00156 /* returns _queryID or false */ 00157 function _query($sql,$inputarr=false) 00158 { 00159 $rs = @ldap_search( $this->_connectionID, $this->database, $sql ); 00160 $this->_errorMsg = ($rs) ? '' : 'Search error on '.$sql.': '.ldap_error($this->_connectionID); 00161 return $rs; 00162 } 00163 00164 function ErrorMsg() 00165 { 00166 return $this->_errorMsg; 00167 } 00168 00169 function ErrorNo() 00170 { 00171 return @ldap_errno($this->_connectionID); 00172 } 00173 00174 /* closes the LDAP connection */ 00175 function _close() 00176 { 00177 @ldap_close( $this->_connectionID ); 00178 $this->_connectionID = false; 00179 } 00180 00181 function SelectDB($db) { 00182 $this->database = $db; 00183 return true; 00184 } // SelectDB 00185 00186 function ServerInfo() 00187 { 00188 if( !empty( $this->version ) ) return $this->version; 00189 $version = array(); 00190 /* 00191 Determines how aliases are handled during search. 00192 LDAP_DEREF_NEVER (0x00) 00193 LDAP_DEREF_SEARCHING (0x01) 00194 LDAP_DEREF_FINDING (0x02) 00195 LDAP_DEREF_ALWAYS (0x03) 00196 The LDAP_DEREF_SEARCHING value means aliases are dereferenced during the search but 00197 not when locating the base object of the search. The LDAP_DEREF_FINDING value means 00198 aliases are dereferenced when locating the base object but not during the search. 00199 Default: LDAP_DEREF_NEVER 00200 */ 00201 ldap_get_option( $this->_connectionID, LDAP_OPT_DEREF, $version['LDAP_OPT_DEREF'] ) ; 00202 switch ( $version['LDAP_OPT_DEREF'] ) { 00203 case 0: 00204 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER'; 00205 case 1: 00206 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING'; 00207 case 2: 00208 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING'; 00209 case 3: 00210 $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_ALWAYS'; 00211 } 00212 00213 /* 00214 A limit on the number of entries to return from a search. 00215 LDAP_NO_LIMIT (0) means no limit. 00216 Default: LDAP_NO_LIMIT 00217 */ 00218 ldap_get_option( $this->_connectionID, LDAP_OPT_SIZELIMIT, $version['LDAP_OPT_SIZELIMIT'] ); 00219 if ( $version['LDAP_OPT_SIZELIMIT'] == 0 ) { 00220 $version['LDAP_OPT_SIZELIMIT'] = 'LDAP_NO_LIMIT'; 00221 } 00222 00223 /* 00224 A limit on the number of seconds to spend on a search. 00225 LDAP_NO_LIMIT (0) means no limit. 00226 Default: LDAP_NO_LIMIT 00227 */ 00228 ldap_get_option( $this->_connectionID, LDAP_OPT_TIMELIMIT, $version['LDAP_OPT_TIMELIMIT'] ); 00229 if ( $version['LDAP_OPT_TIMELIMIT'] == 0 ) { 00230 $version['LDAP_OPT_TIMELIMIT'] = 'LDAP_NO_LIMIT'; 00231 } 00232 00233 /* 00234 Determines whether the LDAP library automatically follows referrals returned by LDAP servers or not. 00235 LDAP_OPT_ON 00236 LDAP_OPT_OFF 00237 Default: ON 00238 */ 00239 ldap_get_option( $this->_connectionID, LDAP_OPT_REFERRALS, $version['LDAP_OPT_REFERRALS'] ); 00240 if ( $version['LDAP_OPT_REFERRALS'] == 0 ) { 00241 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_OFF'; 00242 } else { 00243 $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON'; 00244 00245 } 00246 /* 00247 Determines whether LDAP I/O operations are automatically restarted if they abort prematurely. 00248 LDAP_OPT_ON 00249 LDAP_OPT_OFF 00250 Default: OFF 00251 */ 00252 ldap_get_option( $this->_connectionID, LDAP_OPT_RESTART, $version['LDAP_OPT_RESTART'] ); 00253 if ( $version['LDAP_OPT_RESTART'] == 0 ) { 00254 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_OFF'; 00255 } else { 00256 $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_ON'; 00257 00258 } 00259 /* 00260 This option indicates the version of the LDAP protocol used when communicating with the primary LDAP server. 00261 LDAP_VERSION2 (2) 00262 LDAP_VERSION3 (3) 00263 Default: LDAP_VERSION2 (2) 00264 */ 00265 ldap_get_option( $this->_connectionID, LDAP_OPT_PROTOCOL_VERSION, $version['LDAP_OPT_PROTOCOL_VERSION'] ); 00266 if ( $version['LDAP_OPT_PROTOCOL_VERSION'] == 2 ) { 00267 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION2'; 00268 } else { 00269 $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION3'; 00270 00271 } 00272 /* The host name (or list of hosts) for the primary LDAP server. */ 00273 ldap_get_option( $this->_connectionID, LDAP_OPT_HOST_NAME, $version['LDAP_OPT_HOST_NAME'] ); 00274 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_NUMBER, $version['LDAP_OPT_ERROR_NUMBER'] ); 00275 ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_STRING, $version['LDAP_OPT_ERROR_STRING'] ); 00276 ldap_get_option( $this->_connectionID, LDAP_OPT_MATCHED_DN, $version['LDAP_OPT_MATCHED_DN'] ); 00277 00278 return $this->version = $version; 00279 00280 } 00281 } 00282 00283 /*-------------------------------------------------------------------------------------- 00284 Class Name: Recordset 00285 --------------------------------------------------------------------------------------*/ 00286 00287 class ADORecordSet_ldap extends ADORecordSet{ 00288 00289 var $databaseType = "ldap"; 00290 var $canSeek = false; 00291 var $_entryID; /* keeps track of the entry resource identifier */ 00292 00293 function ADORecordSet_ldap($queryID,$mode=false) 00294 { 00295 if ($mode === false) { 00296 global $ADODB_FETCH_MODE; 00297 $mode = $ADODB_FETCH_MODE; 00298 } 00299 switch ($mode) 00300 { 00301 case ADODB_FETCH_NUM: 00302 $this->fetchMode = LDAP_NUM; 00303 break; 00304 case ADODB_FETCH_ASSOC: 00305 $this->fetchMode = LDAP_ASSOC; 00306 break; 00307 case ADODB_FETCH_DEFAULT: 00308 case ADODB_FETCH_BOTH: 00309 default: 00310 $this->fetchMode = LDAP_BOTH; 00311 break; 00312 } 00313 00314 $this->ADORecordSet($queryID); 00315 } 00316 00317 function _initrs() 00318 { 00319 /* 00320 This could be teaked to respect the $COUNTRECS directive from ADODB 00321 It's currently being used in the _fetch() function and the 00322 GetAssoc() function 00323 */ 00324 $this->_numOfRows = ldap_count_entries( $this->connection->_connectionID, $this->_queryID ); 00325 00326 } 00327 00328 /* 00329 Return whole recordset as a multi-dimensional associative array 00330 */ 00331 function GetAssoc($force_array = false, $first2cols = false) 00332 { 00333 $records = $this->_numOfRows; 00334 $results = array(); 00335 for ( $i=0; $i < $records; $i++ ) { 00336 foreach ( $this->fields as $k=>$v ) { 00337 if ( is_array( $v ) ) { 00338 if ( $v['count'] == 1 ) { 00339 $results[$i][$k] = $v[0]; 00340 } else { 00341 array_shift( $v ); 00342 $results[$i][$k] = $v; 00343 } 00344 } 00345 } 00346 } 00347 00348 return $results; 00349 } 00350 00351 function GetRowAssoc() 00352 { 00353 $results = array(); 00354 foreach ( $this->fields as $k=>$v ) { 00355 if ( is_array( $v ) ) { 00356 if ( $v['count'] == 1 ) { 00357 $results[$k] = $v[0]; 00358 } else { 00359 array_shift( $v ); 00360 $results[$k] = $v; 00361 } 00362 } 00363 } 00364 00365 return $results; 00366 } 00367 00368 function GetRowNums() 00369 { 00370 $results = array(); 00371 foreach ( $this->fields as $k=>$v ) { 00372 static $i = 0; 00373 if (is_array( $v )) { 00374 if ( $v['count'] == 1 ) { 00375 $results[$i] = $v[0]; 00376 } else { 00377 array_shift( $v ); 00378 $results[$i] = $v; 00379 } 00380 $i++; 00381 } 00382 } 00383 return $results; 00384 } 00385 00386 function _fetch() 00387 { 00388 if ( $this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0 ) 00389 return false; 00390 00391 if ( $this->_currentRow == 0 ) { 00392 $this->_entryID = ldap_first_entry( $this->connection->_connectionID, $this->_queryID ); 00393 } else { 00394 $this->_entryID = ldap_next_entry( $this->connection->_connectionID, $this->_entryID ); 00395 } 00396 00397 $this->fields = ldap_get_attributes( $this->connection->_connectionID, $this->_entryID ); 00398 $this->_numOfFields = $this->fields['count']; 00399 switch ( $this->fetchMode ) { 00400 00401 case LDAP_ASSOC: 00402 $this->fields = $this->GetRowAssoc(); 00403 break; 00404 00405 case LDAP_NUM: 00406 $this->fields = array_merge($this->GetRowNums(),$this->GetRowAssoc()); 00407 break; 00408 00409 case LDAP_BOTH: 00410 default: 00411 $this->fields = $this->GetRowNums(); 00412 break; 00413 } 00414 return ( is_array( $this->fields ) ); 00415 } 00416 00417 function _close() { 00418 @ldap_free_result( $this->_queryID ); 00419 $this->_queryID = false; 00420 } 00421 00422 } 00423 ?>