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