** -> *
[squirrelmail.git] / functions / abook_ldap_server.php
CommitLineData
5100704d 1<?php
2
2ba13803 3 /**
7350889b 4 * abook_ldap_server.php
5 *
6 * Copyright (c) 1999-2001 The Squirrelmail Development Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
8 *
9 * Address book backend for LDAP server
10 *
11 * An array with the following elements must be passed to
12 * the class constructor (elements marked ? are optional):
13 *
14 * host => LDAP server hostname/IP-address
15 * base => LDAP server root (base dn). Empty string allowed.
16 * ? port => LDAP server TCP port number (default: 389)
17 * ? charset => LDAP server charset (default: utf-8)
18 * ? name => Name for LDAP server (default "LDAP: hostname")
19 * Used to tag the result data
20 * ? maxrows => Maximum # of rows in search result
21 * ? timeout => Timeout for LDAP operations (in seconds, default: 30)
22 * Might not work for all LDAP libraries or servers.
23 *
24 * NOTE. This class should not be used directly. Use the
25 * "AddressBook" class instead.
26 *
27 * $Id$
28 */
5100704d 29
30 class abook_ldap_server extends addressbook_backend {
91be2362 31 var $btype = 'remote';
32 var $bname = 'ldap_server';
5100704d 33
34 // Parameters changed by class
91be2362 35 var $sname = 'LDAP'; // Service name
36 var $server = ''; // LDAP server name
5100704d 37 var $port = 389; // LDAP server port
91be2362 38 var $basedn = ''; // LDAP base DN
39 var $charset = 'utf-8'; // LDAP server charset
5100704d 40 var $linkid = false; // PHP LDAP link ID
41 var $bound = false; // True if LDAP server is bound
42 var $maxrows = 250; // Max rows in result
b33afbcf 43 var $timeout = 30; // Timeout for LDAP operations (in seconds)
5100704d 44
45 // Constructor. Connects to database
46 function abook_ldap_server($param) {
91be2362 47 if(!function_exists('ldap_connect')) {
48 $this->set_error('LDAP support missing from PHP');
1688203f 49 return;
50 }
5100704d 51 if(is_array($param)) {
91be2362 52 $this->server = $param['host'];
53 $this->basedn = $param['base'];
54 if(!empty($param['port']))
55 $this->port = $param['port'];
56 if(!empty($param['charset']))
57 $this->charset = strtolower($param['charset']);
58 if(isset($param['maxrows']))
59 $this->maxrows = $param['maxrows'];
60 if(isset($param['timeout']))
61 $this->timeout = $param['timeout'];
62 if(empty($param['name']))
63 $this->sname = 'LDAP: ' . $param['host'];
5100704d 64 else
91be2362 65 $this->sname = $param['name'];
5100704d 66
67 $this->open(true);
68 } else {
91be2362 69 $this->set_error('Invalid argument to constructor');
5100704d 70 }
71 }
72
73
74 // Open the LDAP server. New connection if $new is true
75 function open($new = false) {
91be2362 76 $this->error = '';
5100704d 77
78 // Connection is already open
79 if($this->linkid != false && !$new)
80 return true;
81
82 $this->linkid = @ldap_connect($this->server, $this->port);
83 if(!$this->linkid)
91be2362 84 if(function_exists('ldap_error'))
5100704d 85 return $this->set_error(ldap_error($this->linkid));
86 else
91be2362 87 return $this->set_error('ldap_connect failed');
5100704d 88
89 if(!@ldap_bind($this->linkid))
91be2362 90 if(function_exists('ldap_error'))
5100704d 91 return $this->set_error(ldap_error($this->linkid));
92 else
91be2362 93 return $this->set_error('ldap_bind failed');
5100704d 94
95 $this->bound = true;
96
97 return true;
98 }
99
100
101 // Encode iso8859-1 string to the charset used by this LDAP server
102 function charset_encode($str) {
91be2362 103 if($this->charset == 'utf-8') {
104 if(function_exists('utf8_encode'))
5100704d 105 return utf8_encode($str);
106 else
107 return $str;
108 } else {
109 return $str;
110 }
111 }
112
113
114 // Decode from charset used by this LDAP server to iso8859-1
115 function charset_decode($str) {
91be2362 116 if($this->charset == 'utf-8') {
117 if(function_exists('utf8_decode'))
5100704d 118 return utf8_decode($str);
119 else
120 return $str;
121 } else {
122 return $str;
123 }
124 }
125
126
127 // ========================== Public ========================
128
129 // Search the LDAP server
130 function search($expr) {
131
132 // To be replaced by advanded search expression parsing
133 if(is_array($expr)) return false;
134
135 // Encode the expression
136 $expr = $this->charset_encode($expr);
146e0c45 137 if(strstr($expr, "*") === false)
84db4e6c 138 $expr = "*$expr*";
5100704d 139 $expression = "cn=$expr";
140
141 // Make sure connection is there
142 if(!$this->open())
143 return false;
144
b33afbcf 145 // Do the search. Use improved ldap_search() if PHP version is
146 // 4.0.2 or newer.
147 if(sqCheckPHPVersion(4, 0, 2)) {
148 $sret = @ldap_search($this->linkid, $this->basedn, $expression,
91be2362 149 array('dn', 'o', 'ou', 'sn', 'givenname',
150 'cn', 'mail', 'telephonenumber'),
b33afbcf 151 0, $this->maxrows, $this->timeout);
152 } else {
153 $sret = @ldap_search($this->linkid, $this->basedn, $expression,
91be2362 154 array('dn', 'o', 'ou', 'sn', 'givenname',
155 'cn', 'mail', 'telephonenumber'));
b33afbcf 156 }
5100704d 157
158 // Should get error from server using the ldap_error() function,
159 // but it only exist in the PHP LDAP documentation.
160 if(!$sret)
91be2362 161 if(function_exists('ldap_error'))
5100704d 162 return $this->set_error(ldap_error($this->linkid));
163 else
91be2362 164 return $this->set_error('ldap_search failed');
5100704d 165
166 if(@ldap_count_entries($this->linkid, $sret) <= 0)
167 return array();
168
169 // Get results
170 $ret = array();
171 $returned_rows = 0;
172 $res = @ldap_get_entries($this->linkid, $sret);
91be2362 173 for($i = 0 ; $i < $res['count'] ; $i++) {
5100704d 174 $row = $res[$i];
175
176 // Extract data common for all e-mail addresses
177 // of an object. Use only the first name
91be2362 178 $nickname = $this->charset_decode($row['dn']);
179 $fullname = $this->charset_decode($row['cn'][0]);
5100704d 180
91be2362 181 if(empty($row['telephonenumber'][0])) $phone = '';
182 else $phone = $this->charset_decode($row['telephonenumber'][0]);
5100704d 183
91be2362 184 if(!empty($row['ou'][0]))
185 $label = $this->charset_decode($row['ou'][0]);
186 else if(!empty($row['o'][0]))
187 $label = $this->charset_decode($row['o'][0]);
5100704d 188 else
91be2362 189 $label = '';
5100704d 190
91be2362 191 if(empty($row['givenname'][0])) $firstname = '';
192 else $firstname = $this->charset_decode($row['givenname'][0]);
5100704d 193
91be2362 194 if(empty($row['sn'][0])) $surname = '';
195 else $surname = $this->charset_decode($row['sn'][0]);
5100704d 196
197 // Add one row to result for each e-mail address
7609273d 198 if(isset($row['mail']['count'])) {
199 for($j = 0 ; $j < $row['mail']['count'] ; $j++) {
200 array_push($ret, array('nickname' => $nickname,
201 'name' => $fullname,
202 'firstname' => $firstname,
203 'lastname' => $surname,
204 'email' => $row['mail'][$j],
205 'label' => $label,
206 'phone' => $phone,
207 'backend' => $this->bnum,
208 'source' => &$this->sname));
209
210 // Limit number of hits
211 $returned_rows++;
212 if(($returned_rows >= $this->maxrows) &&
213 ($this->maxrows > 0) ) {
214 ldap_free_result($sret);
215 return $ret;
216 }
217
218 } // for($j ...)
219
220 } // isset($row['mail']['count'])
221
5100704d 222 }
223
224 ldap_free_result($sret);
225 return $ret;
226 } // end search()
227
aeee871f 228
229 // If you run a tiny LDAP server and you want the "List All" button
230 // to show EVERYONE, then uncomment this tiny block of code:
231 //
232 // function list_addr() {
233 // return $this->search("*");
234 // }
235 //
236 // Careful with this -- it could get quite large for big sites.
5100704d 237 }
238?>