Added basic support for message highlighting. Note that this needs quite
[squirrelmail.git] / functions / addressbook.php
CommitLineData
5100704d 1<?php
2
3 /**
4 ** addressbook.php
5 **
6 ** Functions and classes for the addressbook system.
7 **
8 **/
9
10 $addressbook_php = true;
11
12 // Include backends here.
13 include("../functions/abook_local_file.php");
14 include("../functions/abook_ldap_server.php");
15
16 // Create and initialize an addressbook object.
17 // Returns the created object
0d273153 18 function addressbook_init($showerr = true, $onlylocal = false) {
5100704d 19 global $data_dir, $username, $ldap_server;
20
21 // Create a new addressbook object
22 $abook = new AddressBook;
23
24 // Always add a local backend
25 $filename = sprintf("%s%s.abook", $data_dir, $username);
26 $r = $abook->add_backend("local_file", Array("filename" => $filename,
27 "create" => true));
0d273153 28 if(!$r && $showerr) {
1e62e50e 29 printf(_("Error opening file %s"), $filename);
5100704d 30 exit;
31 }
0d273153 32
33 if($onlylocal)
34 return $abook;
5100704d 35
36 // Load configured LDAP servers
1ed2b1e0 37 if(is_array($ldap_server)) {
38 reset($ldap_server);
39 while(list($key,$param) = each($ldap_server)) {
40 if(is_array($param)) {
41 $r = $abook->add_backend("ldap_server", $param);
42 if(!$r && $showerr) {
43 printf("&nbsp;"._("Error initializing LDAP server %s:").
44 "<BR>\n", $param["host"]);
45 printf("&nbsp;".$abook->error);
46 exit;
47 }
48 }
49 }
799b9070 50 }
5100704d 51
52 // Return the initialized object
53 return $abook;
54 }
55
56
57
58 /**
59 ** This is the main address book class that connect all the
60 ** backends and provide services to the functions above.
61 **
62 **/
63 class AddressBook {
64 var $backends = array();
65 var $numbackends = 0;
66 var $error = "";
ce916cdf 67 var $localbackend = 0;
1ed2b1e0 68 var $localbackendname = "";
5100704d 69
70 // Constructor function.
71 function AddressBook() {
1ed2b1e0 72 $localbackendname = _("Personal address book");
5100704d 73 }
74
75 // Return an array of backends of a given type,
76 // or all backends if no type is specified.
77 function get_backend_list($type = "") {
78 $ret = array();
79 for($i = 1 ; $i <= $this->numbackends ; $i++) {
80 if(empty($type) || $type == $this->backends[$i]->btype) {
81 array_push($ret, &$this->backends[$i]);
82 }
83 }
84 return $ret;
85 }
86
87
88 // ========================== Public ========================
89
90 // Add a new backend. $backend is the name of a backend
91 // (without the abook_ prefix), and $param is an optional
92 // mixed variable that is passed to the backend constructor.
93 // See each of the backend classes for valid parameters.
94 function add_backend($backend, $param = "") {
95 $backend_name = "abook_".$backend;
96 eval("\$newback = new $backend_name(\$param);");
97 if(!empty($newback->error)) {
98 $this->error = $newback->error;
99 return false;
100 }
101
102 $this->numbackends++;
103
104 $newback->bnum = $this->numbackends;
105 $this->backends[$this->numbackends] = $newback;
ce916cdf 106
107 // Store ID of first local backend added
1ed2b1e0 108 if($this->localbackend == 0 && $newback->btype == "local") {
ce916cdf 109 $this->localbackend = $this->numbackends;
1ed2b1e0 110 $this->localbackendname = $newback->sname;
111 }
ce916cdf 112
5100704d 113 return $this->numbackends;
114 }
115
116
117 // Return a list of addresses matching expression in
118 // all backends of a given type.
119 function search($expression, $btype = "") {
120 $ret = array();
0d273153 121 $this->error = "";
5100704d 122
123 $sel = $this->get_backend_list($btype);
0d273153 124 $failed = 0;
5100704d 125 for($i = 0 ; $i < sizeof($sel) ; $i++) {
126 $backend = &$sel[$i];
127 $backend->error = "";
128 $res = $backend->search($expression);
129 if(is_array($res)) {
130 $ret = array_merge($ret, $res);
131 } else {
0d273153 132 $this->error = $this->error . "<br>\n". $backend->error;
133 $failed++;
5100704d 134 }
135 }
136
0d273153 137 // Only fail if all backends failed
138 if($failed >= sizeof($sel))
139 return false;
140
5100704d 141 return $ret;
142 }
143
144
145 // Return a sorted search
146 function s_search($expression, $btype = "") {
0d273153 147
5100704d 148 $ret = $this->search($expression, $btype);
0d273153 149 if(!is_array($ret))
150 return $ret;
5100704d 151
152 // Inline function - Not nice, but still..
153 function cmp($a,$b) {
154 if($a["backend"] > $b["backend"])
155 return 1;
156 else if($a["backend"] < $b["backend"])
157 return -1;
158
159 return (strtolower($a["name"]) > strtolower($b["name"])) ? 1 : -1;
160 }
161
162 usort($ret, 'cmp');
163 return $ret;
164 }
165
166
167 // Lookup an address by alias. Only possible in
168 // local backends.
1ed2b1e0 169 function lookup($alias, $bnum = -1) {
5100704d 170 $ret = array();
171
1ed2b1e0 172 if($bnum > -1) {
173 $res = $this->backends[$bnum]->lookup($alias);
174 if(is_array($res)) {
175 return $res;
176 } else {
177 $this->error = $backend->error;
178 return false;
179 }
180 }
181
5100704d 182 $sel = $this->get_backend_list("local");
183 for($i = 0 ; $i < sizeof($sel) ; $i++) {
184 $backend = &$sel[$i];
185 $backend->error = "";
186 $res = $backend->lookup($alias);
187 if(is_array($res)) {
1ed2b1e0 188 if(!empty($res))
189 return $res;
5100704d 190 } else {
191 $this->error = $backend->error;
192 return false;
193 }
194 }
195
196 return $ret;
197 }
198
199
200 // Return all addresses
201 function list_addr() {
202 $ret = array();
203
204 $sel = $this->get_backend_list("local");
205 for($i = 0 ; $i < sizeof($sel) ; $i++) {
206 $backend = &$sel[$i];
207 $backend->error = "";
208 $res = $backend->list_addr();
209 if(is_array($res)) {
210 $ret = array_merge($ret, $res);
211 } else {
212 $this->error = $backend->error;
213 return false;
214 }
215 }
216
217 return $ret;
218 }
219
220
221 // Create a new address from $userdata, in backend $bnum.
222 // Return the backend number that the/ address was added
223 // to, or false if it failed.
224 function add($userdata, $bnum) {
225
226 // Validate data
227 if(!is_array($userdata)) {
228 $this->error = _("Invalid input data");
229 return false;
230 }
cca9bc69 231 if(empty($userdata["firstname"]) &&
5100704d 232 empty($userdata["lastname"])) {
233 $this->error = _("Name is missing");
234 return false;
235 }
236 if(empty($userdata["email"])) {
237 $this->error = _("E-mail address is missing");
238 return false;
239 }
240 if(empty($userdata["nickname"])) {
241 $userdata["nickname"] = $userdata["email"];
242 }
243
1ed2b1e0 244 if(eregi("[\: \|\#\"\!]", $userdata["nickname"])) {
245 $this->error = _("Nickname contain illegal characters");
246 return false;
247 }
248
5100704d 249 // Check that specified backend accept new entries
250 if(!$this->backends[$bnum]->writeable) {
1e62e50e 251 $this->error = _("Addressbook is read-only");
5100704d 252 return false;
253 }
254
255 // Add address to backend
256 $res = $this->backends[$bnum]->add($userdata);
257 if($res) {
258 return $bnum;
259 } else {
260 $this->error = $this->backends[$bnum]->error;
261 return false;
262 }
263
264 return false; // Not reached
1ed2b1e0 265 } // end of add()
5100704d 266
1ed2b1e0 267
268 // Remove the user identified by $alias from backend $bnum
269 // If $alias is an array, all users in the array are removed.
270 function remove($alias, $bnum) {
271
272 // Check input
273 if(empty($alias))
274 return true;
275
276 // Convert string to single element array
277 if(!is_array($alias))
278 $alias = array(0 => $alias);
279
280 // Check that specified backend is writable
281 if(!$this->backends[$bnum]->writeable) {
282 $this->error = _("Addressbook is read-only");
283 return false;
284 }
285
286 // Remove user from backend
287 $res = $this->backends[$bnum]->remove($alias);
288 if($res) {
289 return $bnum;
290 } else {
291 $this->error = $this->backends[$bnum]->error;
292 return false;
293 }
294
295 return false; // Not reached
296 } // end of remove()
297
298
299 // Remove the user identified by $alias from backend $bnum
300 // If $alias is an array, all users in the array are removed.
301 function modify($alias, $userdata, $bnum) {
302
303 // Check input
304 if(empty($alias) || !is_string($alias))
305 return true;
306
307 // Validate data
308 if(!is_array($userdata)) {
309 $this->error = _("Invalid input data");
310 return false;
311 }
312 if(empty($userdata["firstname"]) &&
313 empty($userdata["lastname"])) {
314 $this->error = _("Name is missing");
315 return false;
316 }
317 if(empty($userdata["email"])) {
318 $this->error = _("E-mail address is missing");
319 return false;
320 }
321 if(empty($userdata["nickname"])) {
322 $userdata["nickname"] = $userdata["email"];
323 }
324
325 // Check that specified backend is writable
326 if(!$this->backends[$bnum]->writeable) {
327 $this->error = _("Addressbook $bnum is read-only");
328 return false;
329 }
330
331 // Modify user in backend
332 $res = $this->backends[$bnum]->modify($alias, $userdata);
333 if($res) {
334 return $bnum;
335 } else {
336 $this->error = $this->backends[$bnum]->error;
337 return false;
338 }
339
340 return false; // Not reached
341 } // end of modify()
342
343 } // End of class Addressbook
5100704d 344
345
346 /**
347 ** Generic backend that all other backends extend
348 **/
349 class addressbook_backend {
350
351 // Variables that all backends must provide.
352 var $btype = "dummy";
353 var $bname = "dummy";
354 var $sname = "Dummy backend";
355
356 // Variables common for all backends, but that
357 // should not be changed by the backends.
358 var $bnum = -1;
359 var $error = "";
360 var $writeable = false;
361
362 function set_error($string) {
363 $this->error = "[" . $this->sname . "] " . $string;
364 return false;
365 }
366
367
368 // ========================== Public ========================
369
370 function search($expression) {
371 $this->set_error("search not implemented");
372 return false;
373 }
374
375 function lookup($alias) {
376 $this->set_error("lookup not implemented");
377 return false;
378 }
379
380 function list_addr() {
381 $this->set_error("list_addr not implemented");
382 return false;
383 }
384
385 function add($userdata) {
386 $this->set_error("add not implemented");
387 return false;
388 }
389
1ed2b1e0 390 function remove($alias) {
391 $this->set_error("delete not implemented");
392 return false;
393 }
394
395 function modify($alias, $newuserdata) {
396 $this->set_error("modify not implemented");
397 return false;
398 }
399
5100704d 400 }
401
402?>