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(" "._("Error initializing LDAP server %s:"). |
44 | "<BR>\n", $param["host"]); |
45 | printf(" ".$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 | ?> |