LDAP server hostname/IP-address ** base => LDAP server root (base dn). Empty string allowed. ** ? port => LDAP server TCP port number (default: 389) ** ? charset => LDAP server charset (default: utf-8) ** ? name => Name for LDAP server (default "LDAP: hostname") ** Used to tag the result data ** ? maxrows => Maximum # of rows in search result ** ? timeout => Timeout for LDAP operations (in seconds, default: 30) ** Might not work for all LDAP libraries or servers. ** ** NOTE. This class should not be used directly. Use the ** "AddressBook" class instead. ** ** $Id$ **/ class abook_ldap_server extends addressbook_backend { var $btype = 'remote'; var $bname = 'ldap_server'; // Parameters changed by class var $sname = 'LDAP'; // Service name var $server = ''; // LDAP server name var $port = 389; // LDAP server port var $basedn = ''; // LDAP base DN var $charset = 'utf-8'; // LDAP server charset var $linkid = false; // PHP LDAP link ID var $bound = false; // True if LDAP server is bound var $maxrows = 250; // Max rows in result var $timeout = 30; // Timeout for LDAP operations (in seconds) // Constructor. Connects to database function abook_ldap_server($param) { if(!function_exists('ldap_connect')) { $this->set_error('LDAP support missing from PHP'); return; } if(is_array($param)) { $this->server = $param['host']; $this->basedn = $param['base']; if(!empty($param['port'])) $this->port = $param['port']; if(!empty($param['charset'])) $this->charset = strtolower($param['charset']); if(isset($param['maxrows'])) $this->maxrows = $param['maxrows']; if(isset($param['timeout'])) $this->timeout = $param['timeout']; if(empty($param['name'])) $this->sname = 'LDAP: ' . $param['host']; else $this->sname = $param['name']; $this->open(true); } else { $this->set_error('Invalid argument to constructor'); } } // Open the LDAP server. New connection if $new is true function open($new = false) { $this->error = ''; // Connection is already open if($this->linkid != false && !$new) return true; $this->linkid = @ldap_connect($this->server, $this->port); if(!$this->linkid) if(function_exists('ldap_error')) return $this->set_error(ldap_error($this->linkid)); else return $this->set_error('ldap_connect failed'); if(!@ldap_bind($this->linkid)) if(function_exists('ldap_error')) return $this->set_error(ldap_error($this->linkid)); else return $this->set_error('ldap_bind failed'); $this->bound = true; return true; } // Encode iso8859-1 string to the charset used by this LDAP server function charset_encode($str) { if($this->charset == 'utf-8') { if(function_exists('utf8_encode')) return utf8_encode($str); else return $str; } else { return $str; } } // Decode from charset used by this LDAP server to iso8859-1 function charset_decode($str) { if($this->charset == 'utf-8') { if(function_exists('utf8_decode')) return utf8_decode($str); else return $str; } else { return $str; } } // ========================== Public ======================== // Search the LDAP server function search($expr) { // To be replaced by advanded search expression parsing if(is_array($expr)) return false; // Encode the expression $expr = $this->charset_encode($expr); if(strstr($expr, "*") === false) $expr = "*$expr*"; $expression = "cn=$expr"; // Make sure connection is there if(!$this->open()) return false; // Do the search. Use improved ldap_search() if PHP version is // 4.0.2 or newer. if(sqCheckPHPVersion(4, 0, 2)) { $sret = @ldap_search($this->linkid, $this->basedn, $expression, array('dn', 'o', 'ou', 'sn', 'givenname', 'cn', 'mail', 'telephonenumber'), 0, $this->maxrows, $this->timeout); } else { $sret = @ldap_search($this->linkid, $this->basedn, $expression, array('dn', 'o', 'ou', 'sn', 'givenname', 'cn', 'mail', 'telephonenumber')); } // Should get error from server using the ldap_error() function, // but it only exist in the PHP LDAP documentation. if(!$sret) if(function_exists('ldap_error')) return $this->set_error(ldap_error($this->linkid)); else return $this->set_error('ldap_search failed'); if(@ldap_count_entries($this->linkid, $sret) <= 0) return array(); // Get results $ret = array(); $returned_rows = 0; $res = @ldap_get_entries($this->linkid, $sret); for($i = 0 ; $i < $res['count'] ; $i++) { $row = $res[$i]; // Extract data common for all e-mail addresses // of an object. Use only the first name $nickname = $this->charset_decode($row['dn']); $fullname = $this->charset_decode($row['cn'][0]); if(empty($row['telephonenumber'][0])) $phone = ''; else $phone = $this->charset_decode($row['telephonenumber'][0]); if(!empty($row['ou'][0])) $label = $this->charset_decode($row['ou'][0]); else if(!empty($row['o'][0])) $label = $this->charset_decode($row['o'][0]); else $label = ''; if(empty($row['givenname'][0])) $firstname = ''; else $firstname = $this->charset_decode($row['givenname'][0]); if(empty($row['sn'][0])) $surname = ''; else $surname = $this->charset_decode($row['sn'][0]); // Add one row to result for each e-mail address if(isset($row['mail']['count'])) { for($j = 0 ; $j < $row['mail']['count'] ; $j++) { array_push($ret, array('nickname' => $nickname, 'name' => $fullname, 'firstname' => $firstname, 'lastname' => $surname, 'email' => $row['mail'][$j], 'label' => $label, 'phone' => $phone, 'backend' => $this->bnum, 'source' => &$this->sname)); // Limit number of hits $returned_rows++; if(($returned_rows >= $this->maxrows) && ($this->maxrows > 0) ) { ldap_free_result($sret); return $ret; } } // for($j ...) } // isset($row['mail']['count']) } ldap_free_result($sret); return $ret; } // end search() // If you run a tiny LDAP server and you want the "List All" button // to show EVERYONE, then uncomment this tiny block of code: // // function list_addr() { // return $this->search("*"); // } // // Careful with this -- it could get quite large for big sites. } ?>