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(" "._("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. |
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 | ?> |