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