Changed language-code link.
[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
95a4d303 36 // Load configured LDAP servers (if PHP has LDAP support)
37 if(is_array($ldap_server) && function_exists("ldap_connect")) {
1ed2b1e0 38 reset($ldap_server);
fb16d219 39 while(list($undef,$param) = each($ldap_server)) {
1ed2b1e0 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.
2f73dc15 119 function search($expression, $bnum = -1) {
5100704d 120 $ret = array();
0d273153 121 $this->error = "";
5100704d 122
2f73dc15 123 // Search all backends
124 if($bnum == -1) {
125 $sel = $this->get_backend_list("");
126 $failed = 0;
127 for($i = 0 ; $i < sizeof($sel) ; $i++) {
128 $backend = &$sel[$i];
129 $backend->error = "";
130 $res = $backend->search($expression);
131 if(is_array($res)) {
132 $ret = array_merge($ret, $res);
133 } else {
134 $this->error = $this->error . "<br>\n". $backend->error;
135 $failed++;
136 }
5100704d 137 }
2f73dc15 138
139 // Only fail if all backends failed
140 if($failed >= sizeof($sel))
141 return false;
142
5100704d 143 }
144
2f73dc15 145 // Search only one backend
146 else {
147 $ret = $this->backends[$bnum]->search($expression);
148 if(!is_array($ret)) {
149 $this->error = $this->error . "<br>\n". $this->backends[$bnum]->error;
150 return false;
151 }
152 }
0d273153 153
5100704d 154 return $ret;
155 }
156
157
158 // Return a sorted search
2f73dc15 159 function s_search($expression, $bnum = -1) {
0d273153 160
2f73dc15 161 $ret = $this->search($expression, $bnum);
0d273153 162 if(!is_array($ret))
163 return $ret;
5100704d 164
165 // Inline function - Not nice, but still..
166 function cmp($a,$b) {
167 if($a["backend"] > $b["backend"])
168 return 1;
169 else if($a["backend"] < $b["backend"])
170 return -1;
171
172 return (strtolower($a["name"]) > strtolower($b["name"])) ? 1 : -1;
173 }
174
175 usort($ret, 'cmp');
176 return $ret;
177 }
178
179
180 // Lookup an address by alias. Only possible in
181 // local backends.
1ed2b1e0 182 function lookup($alias, $bnum = -1) {
5100704d 183 $ret = array();
184
1ed2b1e0 185 if($bnum > -1) {
186 $res = $this->backends[$bnum]->lookup($alias);
187 if(is_array($res)) {
188 return $res;
189 } else {
190 $this->error = $backend->error;
191 return false;
192 }
193 }
194
5100704d 195 $sel = $this->get_backend_list("local");
196 for($i = 0 ; $i < sizeof($sel) ; $i++) {
197 $backend = &$sel[$i];
198 $backend->error = "";
199 $res = $backend->lookup($alias);
200 if(is_array($res)) {
1ed2b1e0 201 if(!empty($res))
202 return $res;
5100704d 203 } else {
204 $this->error = $backend->error;
205 return false;
206 }
207 }
208
209 return $ret;
210 }
211
212
213 // Return all addresses
2f73dc15 214 function list_addr($bnum = -1) {
5100704d 215 $ret = array();
216
2f73dc15 217 if($bnum == -1)
218 $sel = $this->get_backend_list("local");
219 else
220 $sel = array(0 => &$this->backends[$bnum]);
221
5100704d 222 for($i = 0 ; $i < sizeof($sel) ; $i++) {
223 $backend = &$sel[$i];
224 $backend->error = "";
225 $res = $backend->list_addr();
226 if(is_array($res)) {
227 $ret = array_merge($ret, $res);
228 } else {
229 $this->error = $backend->error;
230 return false;
231 }
232 }
233
234 return $ret;
235 }
236
237
238 // Create a new address from $userdata, in backend $bnum.
239 // Return the backend number that the/ address was added
240 // to, or false if it failed.
241 function add($userdata, $bnum) {
242
243 // Validate data
244 if(!is_array($userdata)) {
245 $this->error = _("Invalid input data");
246 return false;
247 }
cca9bc69 248 if(empty($userdata["firstname"]) &&
5100704d 249 empty($userdata["lastname"])) {
250 $this->error = _("Name is missing");
251 return false;
252 }
253 if(empty($userdata["email"])) {
254 $this->error = _("E-mail address is missing");
255 return false;
256 }
257 if(empty($userdata["nickname"])) {
258 $userdata["nickname"] = $userdata["email"];
259 }
260
1ed2b1e0 261 if(eregi("[\: \|\#\"\!]", $userdata["nickname"])) {
262 $this->error = _("Nickname contain illegal characters");
263 return false;
264 }
265
5100704d 266 // Check that specified backend accept new entries
267 if(!$this->backends[$bnum]->writeable) {
1e62e50e 268 $this->error = _("Addressbook is read-only");
5100704d 269 return false;
270 }
271
272 // Add address to backend
273 $res = $this->backends[$bnum]->add($userdata);
274 if($res) {
275 return $bnum;
276 } else {
277 $this->error = $this->backends[$bnum]->error;
278 return false;
279 }
280
281 return false; // Not reached
1ed2b1e0 282 } // end of add()
5100704d 283
1ed2b1e0 284
285 // Remove the user identified by $alias from backend $bnum
286 // If $alias is an array, all users in the array are removed.
287 function remove($alias, $bnum) {
288
289 // Check input
290 if(empty($alias))
291 return true;
292
293 // Convert string to single element array
294 if(!is_array($alias))
295 $alias = array(0 => $alias);
296
297 // Check that specified backend is writable
298 if(!$this->backends[$bnum]->writeable) {
299 $this->error = _("Addressbook is read-only");
300 return false;
301 }
302
303 // Remove user from backend
304 $res = $this->backends[$bnum]->remove($alias);
305 if($res) {
306 return $bnum;
307 } else {
308 $this->error = $this->backends[$bnum]->error;
309 return false;
310 }
311
312 return false; // Not reached
313 } // end of remove()
314
315
316 // Remove the user identified by $alias from backend $bnum
317 // If $alias is an array, all users in the array are removed.
318 function modify($alias, $userdata, $bnum) {
319
320 // Check input
321 if(empty($alias) || !is_string($alias))
322 return true;
323
324 // Validate data
325 if(!is_array($userdata)) {
326 $this->error = _("Invalid input data");
327 return false;
328 }
329 if(empty($userdata["firstname"]) &&
330 empty($userdata["lastname"])) {
331 $this->error = _("Name is missing");
332 return false;
333 }
334 if(empty($userdata["email"])) {
335 $this->error = _("E-mail address is missing");
336 return false;
337 }
338 if(empty($userdata["nickname"])) {
339 $userdata["nickname"] = $userdata["email"];
340 }
341
342 // Check that specified backend is writable
343 if(!$this->backends[$bnum]->writeable) {
2ad42ea3 344 $this->error = sprintf(_("Addressbook %s is read-only", $bnum));
1ed2b1e0 345 return false;
346 }
347
348 // Modify user in backend
349 $res = $this->backends[$bnum]->modify($alias, $userdata);
350 if($res) {
351 return $bnum;
352 } else {
353 $this->error = $this->backends[$bnum]->error;
354 return false;
355 }
356
357 return false; // Not reached
358 } // end of modify()
359
360 } // End of class Addressbook
5100704d 361
362
363 /**
364 ** Generic backend that all other backends extend
365 **/
366 class addressbook_backend {
367
368 // Variables that all backends must provide.
369 var $btype = "dummy";
370 var $bname = "dummy";
371 var $sname = "Dummy backend";
372
373 // Variables common for all backends, but that
374 // should not be changed by the backends.
375 var $bnum = -1;
376 var $error = "";
377 var $writeable = false;
378
379 function set_error($string) {
380 $this->error = "[" . $this->sname . "] " . $string;
381 return false;
382 }
383
384
385 // ========================== Public ========================
386
387 function search($expression) {
388 $this->set_error("search not implemented");
389 return false;
390 }
391
392 function lookup($alias) {
393 $this->set_error("lookup not implemented");
394 return false;
395 }
396
397 function list_addr() {
398 $this->set_error("list_addr not implemented");
399 return false;
400 }
401
402 function add($userdata) {
403 $this->set_error("add not implemented");
404 return false;
405 }
406
1ed2b1e0 407 function remove($alias) {
408 $this->set_error("delete not implemented");
409 return false;
410 }
411
412 function modify($alias, $newuserdata) {
413 $this->set_error("modify not implemented");
414 return false;
415 }
416
5100704d 417 }
418
419?>