abdfb4d0 |
1 | <?php |
134e4174 |
2 | |
35586184 |
3 | /** |
4 | * addressbook.php |
5 | * |
35586184 |
6 | * Manage personal address book. |
7 | * |
4b5049de |
8 | * @copyright © 1999-2007 The SquirrelMail Project Team |
4b4abf93 |
9 | * @license http://opensource.org/licenses/gpl-license.php GNU Public License |
30967a1e |
10 | * @version $Id$ |
8f6f9ba5 |
11 | * @package squirrelmail |
de00443c |
12 | * @subpackage addressbook |
35586184 |
13 | */ |
14 | |
ebd2391c |
15 | /** This is the addressbook page */ |
16 | define('PAGE_NAME', 'addressbook'); |
17 | |
30967a1e |
18 | /** |
202bcbcc |
19 | * Include the SquirrelMail initialization file. |
30967a1e |
20 | */ |
202bcbcc |
21 | include('../include/init.php'); |
86725763 |
22 | |
8f6f9ba5 |
23 | /** SquirrelMail required files. */ |
df4162cb |
24 | /* address book functions */ |
202bcbcc |
25 | require_once(SM_PATH . 'functions/addressbook.php'); |
3f92c0c7 |
26 | include_once(SM_PATH . 'templates/util_addressbook.php'); |
27 | |
df4162cb |
28 | /* form functions */ |
202bcbcc |
29 | require_once(SM_PATH . 'functions/forms.php'); |
ffd8224c |
30 | |
8f6f9ba5 |
31 | /** lets get the global vars we may need */ |
0b97a708 |
32 | |
33 | /* From the address form */ |
a71b394e |
34 | sqgetGlobalVar('addaddr', $addaddr, SQ_POST); |
35 | sqgetGlobalVar('editaddr', $editaddr, SQ_POST); |
36 | sqgetGlobalVar('deladdr', $deladdr, SQ_POST); |
f4f64c58 |
37 | sqgetGlobalVar('compose_to', $compose_to, SQ_POST); |
a71b394e |
38 | sqgetGlobalVar('sel', $sel, SQ_POST); |
39 | sqgetGlobalVar('oldnick', $oldnick, SQ_POST); |
40 | sqgetGlobalVar('backend', $backend, SQ_POST); |
41 | sqgetGlobalVar('doedit', $doedit, SQ_POST); |
4fe67ca6 |
42 | $page_size = $abook_show_num; |
43 | if (!sqGetGlobalVar('page_number', $page_number, SQ_FORM)) |
44 | if (!sqGetGlobalVar('current_page_number', $page_number, SQ_FORM)) |
45 | $page_number = 1; |
46 | if (!sqGetGlobalVar('show_all', $show_all, SQ_FORM)) |
47 | $show_all = 0; |
0b97a708 |
48 | |
08e71631 |
49 | /* Get sorting order */ |
50 | $abook_sort_order = get_abook_sort(); |
51 | |
703fa6b5 |
52 | /* Create page header before addressbook_init in order to display error messages correctly. */ |
876fdb60 |
53 | displayPageHeader($color); |
703fa6b5 |
54 | |
de00443c |
55 | /* Open addressbook with error messages on. |
56 | remote backends (LDAP) are enabled because they can be used. (list_addr function) |
57 | */ |
58 | $abook = addressbook_init(true, false); |
ced653f3 |
59 | |
4fe67ca6 |
60 | // FIXME: do we really have to stop use of address book when localbackend is not present? |
daba719e |
61 | if($abook->localbackend == 0) { |
a71b394e |
62 | plain_error_message(_("No personal address book is defined. Contact administrator.")); |
daba719e |
63 | exit(); |
64 | } |
ffd8224c |
65 | |
a71b394e |
66 | $current_backend = $abook->localbackend; |
caa596b2 |
67 | if (sqgetGlobalVar('new_bnum', $new_backend, SQ_FORM) |
68 | && array_key_exists($new_backend, $abook->backends)) { |
a71b394e |
69 | $current_backend = (int) $new_backend; |
70 | } |
71 | |
72 | $abook_selection = ' '; |
73 | $list_backends = array(); |
74 | if (count($abook->backends) > 1) { |
75 | foreach($abook->get_backend_list() as $oBackend) { |
76 | if ($oBackend->listing) { |
77 | $list_backends[$oBackend->bnum]=$oBackend->sname; |
78 | } |
79 | } |
80 | if (count($list_backends)>1) { |
81 | $abook_selection = addSelect('new_bnum',$list_backends,$current_backend,true) |
82 | .addSubmit(_("Change"),'change_abook'); |
83 | } |
84 | } |
85 | |
daba719e |
86 | $defdata = array(); |
87 | $formerror = ''; |
88 | $abortform = false; |
89 | $showaddrlist = true; |
90 | $defselected = array(); |
07dcee9f |
91 | $form_url = 'addressbook.php'; |
daba719e |
92 | |
f6c945b9 |
93 | /* Handle user's actions */ |
1e12d1ff |
94 | if(sqgetGlobalVar('REQUEST_METHOD', $req_method, SQ_SERVER) && $req_method == 'POST') { |
daba719e |
95 | |
f6c945b9 |
96 | /************************************************** |
97 | * Add new address * |
98 | **************************************************/ |
39b26252 |
99 | if (isset($addaddr)) { |
a123157f |
100 | if (isset($backend)) { |
101 | $r = $abook->add($addaddr, $backend); |
102 | } else { |
103 | $r = $abook->add($addaddr, $abook->localbackend); |
c6554ec0 |
104 | } |
ffd8224c |
105 | |
f6c945b9 |
106 | /* Handle error messages */ |
107 | if (!$r) { |
108 | /* Remove backend name from error string */ |
ffd8224c |
109 | $errstr = $abook->error; |
110 | $errstr = ereg_replace('^\[.*\] *', '', $errstr); |
111 | |
112 | $formerror = $errstr; |
113 | $showaddrlist = false; |
114 | $defdata = $addaddr; |
115 | } |
daba719e |
116 | } else { |
ffd8224c |
117 | |
f6c945b9 |
118 | /************************************************ |
119 | * Delete address(es) * |
120 | ************************************************/ |
121 | if ((!empty($deladdr)) && sizeof($sel) > 0) { |
daba719e |
122 | $orig_sel = $sel; |
123 | sort($sel); |
124 | |
f4f64c58 |
125 | /* The selected addresses are identified by "backend_nickname". * |
f6c945b9 |
126 | * Sort the list and process one backend at the time */ |
daba719e |
127 | $prevback = -1; |
128 | $subsel = array(); |
129 | $delfailed = false; |
130 | |
f6c945b9 |
131 | for ($i = 0 ; (($i < sizeof($sel)) && !$delfailed) ; $i++) { |
f4f64c58 |
132 | list($sbackend, $snick) = explode('_', $sel[$i], 2); |
daba719e |
133 | |
f6c945b9 |
134 | /* When we get to a new backend, process addresses in * |
135 | * previous one. */ |
136 | if ($prevback != $sbackend && $prevback != -1) { |
daba719e |
137 | |
138 | $r = $abook->remove($subsel, $prevback); |
f6c945b9 |
139 | if (!$r) { |
daba719e |
140 | $formerror = $abook->error; |
141 | $i = sizeof($sel); |
142 | $delfailed = true; |
143 | break; |
144 | } |
145 | $subsel = array(); |
146 | } |
147 | |
f6c945b9 |
148 | /* Queue for processing */ |
daba719e |
149 | array_push($subsel, $snick); |
150 | $prevback = $sbackend; |
ffd8224c |
151 | } |
ffd8224c |
152 | |
f6c945b9 |
153 | if (!$delfailed) { |
daba719e |
154 | $r = $abook->remove($subsel, $prevback); |
f6c945b9 |
155 | if (!$r) { /* Handle errors */ |
daba719e |
156 | $formerror = $abook->error; |
157 | $delfailed = true; |
158 | } |
ffd8224c |
159 | } |
ffd8224c |
160 | |
f6c945b9 |
161 | if ($delfailed) { |
daba719e |
162 | $showaddrlist = true; |
163 | $defselected = $orig_sel; |
ffd8224c |
164 | } |
ffd8224c |
165 | |
f4f64c58 |
166 | /************************************************ |
167 | * Compose to selected address(es) * |
168 | ************************************************/ |
169 | } else if ((!empty($compose_to)) && sizeof($sel) > 0) { |
170 | $orig_sel = $sel; |
171 | sort($sel); |
172 | |
173 | // The selected addresses are identified by "backend_nickname" |
174 | $lookup_failed = false; |
175 | $send_to = ''; |
176 | |
177 | for ($i = 0 ; (($i < sizeof($sel)) && !$lookup_failed) ; $i++) { |
178 | list($sbackend, $snick) = explode('_', $sel[$i], 2); |
179 | |
180 | $data = $abook->lookup($snick, $sbackend); |
181 | |
182 | if (!$data) { |
183 | $formerror = $abook->error; |
184 | $lookup_failed = true; |
185 | break; |
186 | } else { |
187 | $addr = $abook->full_address($data); |
188 | if (!empty($addr)) |
189 | $send_to .= $addr . ', '; |
190 | } |
191 | } |
192 | |
193 | |
194 | if ($lookup_failed || empty($send_to)) { |
195 | $showaddrlist = true; |
196 | $defselected = $sel; |
197 | } |
198 | |
199 | |
200 | // send off to compose screen |
201 | else { |
202 | $send_to = trim($send_to, ', '); |
203 | header('Location: ' . $base_uri . 'src/compose.php?send_to=' . rawurlencode($send_to)); |
204 | exit; |
205 | } |
206 | |
daba719e |
207 | } else { |
208 | |
f6c945b9 |
209 | /*********************************************** |
210 | * Update/modify address * |
211 | ***********************************************/ |
212 | if (!empty($editaddr)) { |
f6c945b9 |
213 | /* Stage one: Copy data into form */ |
daba719e |
214 | if (isset($sel) && sizeof($sel) > 0) { |
215 | if(sizeof($sel) > 1) { |
216 | $formerror = _("You can only edit one address at the time"); |
217 | $showaddrlist = true; |
218 | $defselected = $sel; |
219 | } else { |
220 | $abortform = true; |
f4f64c58 |
221 | list($ebackend, $enick) = explode('_', current($sel), 2); |
daba719e |
222 | $olddata = $abook->lookup($enick, $ebackend); |
5b61a40d |
223 | // Test if $olddata really contains anything and return an error message if it doesn't |
224 | if (!$olddata) { |
225 | error_box(nl2br(htmlspecialchars($abook->error))); |
226 | } else { |
227 | /* Display the "new address" form */ |
caa596b2 |
228 | echo abook_create_form($form_url, 'editaddr', |
229 | _("Update address"), |
230 | _("Update address"), |
231 | $current_backend, |
232 | $olddata); |
5b61a40d |
233 | echo addHidden('oldnick', $olddata['nickname']). |
234 | addHidden('backend', $olddata['backend']). |
235 | addHidden('doedit', '1'). |
236 | '</form>'; |
237 | } |
daba719e |
238 | } |
3e87f870 |
239 | } elseif ($doedit == 1) { |
f6c945b9 |
240 | /* Stage two: Write new data */ |
3e87f870 |
241 | $newdata = $editaddr; |
242 | $r = $abook->modify($oldnick, $newdata, $backend); |
daba719e |
243 | |
3e87f870 |
244 | /* Handle error messages */ |
245 | if (!$r) { |
246 | /* Display error */ |
3c656c5f |
247 | plain_error_message( nl2br(htmlspecialchars($abook->error))); |
3e87f870 |
248 | |
249 | /* Display the "new address" form again */ |
caa596b2 |
250 | echo abook_create_form($form_url, 'editaddr', |
251 | _("Update address"), |
252 | _("Update address"), |
253 | $current_backend, |
254 | $newdata); |
3e87f870 |
255 | echo addHidden('oldnick', $oldnick). |
256 | addHidden('backend', $backend). |
257 | addHidden('doedit', '1'). |
258 | "\n" . '</form>'; |
daba719e |
259 | $abortform = true; |
260 | } |
3e87f870 |
261 | } else { |
262 | /** |
f8a1ed5a |
263 | * $editaddr is set, but $sel (address selection in address listing) |
264 | * and $doedit (address edit form) are not set. |
3e87f870 |
265 | * Assume that user clicked on "Edit address" without selecting any address. |
266 | */ |
267 | $formerror = _("Please select address that you want to edit"); |
268 | $showaddrlist = true; |
269 | } /* end of edit stage detection */ |
f4f64c58 |
270 | } /* !empty($editaddr) - Update/modify address */ |
271 | } /* (!empty($deladdr)) && sizeof($sel) > 0 - Delete address(es) |
272 | or (!empty($compose_to)) && sizeof($sel) > 0 - Compose to address(es) */ |
273 | } /* !empty($addaddr['nickname']) - Add new address */ |
daba719e |
274 | |
275 | // Some times we end output before forms are printed |
276 | if($abortform) { |
4fe67ca6 |
277 | //FIXME: use footer.tpl; remove HTML from core |
056a005c |
278 | echo "</body></html>\n"; |
279 | exit(); |
ffd8224c |
280 | } |
daba719e |
281 | } |
ffd8224c |
282 | |
283 | |
f6c945b9 |
284 | /* =================================================================== * |
285 | * The following is only executed on a GET request, or on a POST when * |
286 | * a user is added, or when "delete" or "modify" was successful. * |
287 | * =================================================================== */ |
ffd8224c |
288 | |
f6c945b9 |
289 | /* Display error messages */ |
290 | if (!empty($formerror)) { |
a71b394e |
291 | plain_error_message(nl2br(htmlspecialchars($formerror))); |
daba719e |
292 | } |
ffd8224c |
293 | |
294 | |
f6c945b9 |
295 | /* Display the address management part */ |
a71b394e |
296 | $addresses = array(); |
297 | while (list($k, $backend) = each ($abook->backends)) { |
298 | $a = array(); |
299 | $a['BackendID'] = $backend->bnum; |
300 | $a['BackendSource'] = $backend->sname; |
301 | $a['BackendWritable'] = $backend->writeable; |
302 | $a['Addresses'] = array(); |
303 | |
4fe67ca6 |
304 | // don't do address lookup if we are not viewing that backend |
305 | // |
306 | if ($backend->bnum == $current_backend) { |
307 | $alist = $abook->list_addr($backend->bnum); |
5b1c13d3 |
308 | |
4fe67ca6 |
309 | /* check return (array with data or boolean false) */ |
310 | if (is_array($alist)) { |
311 | usort($alist,'alistcmp'); |
312 | |
313 | $a['Addresses'] = formatAddressList($alist); |
a71b394e |
314 | |
4fe67ca6 |
315 | $addresses[$backend->bnum] = $a; |
316 | } else { |
317 | // list_addr() returns boolean |
318 | plain_error_message(nl2br(htmlspecialchars($abook->error))); |
319 | } |
5b1c13d3 |
320 | } else { |
4fe67ca6 |
321 | $addresses[$backend->bnum] = $a; |
322 | } |
323 | } |
324 | |
325 | |
326 | $current_page_args = array( |
327 | 'abook_sort_order' => $abook_sort_order, |
328 | 'new_bnum' => $current_backend, |
329 | 'page_number' => $page_number, |
330 | ); |
331 | |
332 | |
333 | // note that plugins can add to $current_page_args as well as |
334 | // filter the address list |
335 | // |
336 | $temp = array(&$addresses, &$current_backend, &$page_number, &$current_page_args); |
337 | do_hook('abook_list_filter', $temp); |
338 | |
339 | |
340 | // NOTE to address book backend authors and plugin authors: if a backend does |
341 | // pagination (which might be more efficient), it needs to place a key |
342 | // in every address listing it returns called "paginated", whose value |
343 | // should evaluate to boolean TRUE. However, if a plugin will also be |
344 | // used on the hook above to filter the addresses (perhaps by group), then |
345 | // the backend should be made compatible with the filtering plugin and |
346 | // should do the actual filtering too. Otherwise, the backend will paginate |
347 | // before filtering has taken place, the output of which is clearly wrong. |
348 | // It is proposed that filtering be based on a GET/POST variable called |
349 | // "abook_groups_X" where X is the current backend number. The value of |
350 | // this varaible would be an array of possible filter names, which the |
351 | // plugin and the backend would both know about. The plugin would only |
352 | // filter based on that value if the backend didn't already do it. The |
353 | // backend can insert a "grouped" key into all address listings, whose |
354 | // value evaluates to boolean TRUE, telling the plugin not to do any |
355 | // filtering itself. For an example of this implementation, see the |
356 | // Address Book Grouping and Pagination plugin. |
357 | |
358 | |
359 | // if no pagination was done by a plugin or the abook |
360 | // backend (which is indicated by the presence of a |
361 | // "paginated" key within all of the address entries |
362 | // in the list of addresses for the backend currently |
363 | // being viewed), then we provide default pagination |
364 | // |
365 | $total_addresses = 0; |
366 | if (!$show_all |
367 | && is_array($addresses[$current_backend]['Addresses']) |
368 | && empty($addresses[$current_backend]['Addresses'][0]['paginated'])) { |
369 | |
370 | // at this point, we assume the current list is |
371 | // the *full* list |
372 | // |
373 | $total_addresses = sizeof($addresses[$current_backend]['Addresses']); |
374 | |
375 | // iterate through all the entries, building list of addresses |
376 | // to keep based on current page |
377 | // |
378 | $new_address_list = array(); |
379 | $total_pages = ceil($total_addresses / $page_size); |
380 | if ($page_number > $total_pages) $page_number = $total_pages; |
381 | $page_count = 1; |
382 | $page_item_count = 0; |
383 | foreach ($addresses[$current_backend]['Addresses'] as $addr) { |
384 | $page_item_count++; |
385 | if ($page_item_count > $page_size) { |
386 | $page_count++; |
387 | $page_item_count = 1; |
388 | } |
389 | if ($page_count == $page_number) |
390 | $new_address_list[] = $addr; |
5b1c13d3 |
391 | } |
4fe67ca6 |
392 | $addresses[$current_backend]['Addresses'] = $new_address_list; |
393 | |
a71b394e |
394 | } |
daba719e |
395 | |
396 | |
a71b394e |
397 | if ($showaddrlist) { |
a71b394e |
398 | |
4fe67ca6 |
399 | $oTemplate->assign('show_all', $show_all); |
400 | $oTemplate->assign('page_number', $page_number); |
401 | $oTemplate->assign('page_size', $page_size); |
402 | $oTemplate->assign('total_addresses', $total_addresses); |
403 | $oTemplate->assign('abook_compact_paginator', $abook_compact_paginator); |
404 | $oTemplate->assign('abook_page_selector', $abook_page_selector); |
405 | $oTemplate->assign('current_page_args', $current_page_args); |
406 | $oTemplate->assign('abook_page_selector_max', $abook_page_selector_max); |
a71b394e |
407 | $oTemplate->assign('addresses', $addresses); |
408 | $oTemplate->assign('current_backend', $current_backend); |
409 | $oTemplate->assign('backends', $list_backends); |
a140c3b1 |
410 | $oTemplate->assign('abook_has_extra_field', $abook->add_extra_field); |
4fe67ca6 |
411 | $oTemplate->assign('compose_new_win', $compose_new_win); |
412 | $oTemplate->assign('compose_height', $compose_height); |
413 | $oTemplate->assign('compose_width', $compose_width); |
414 | $oTemplate->assign('form_action', $form_url); |
a71b394e |
415 | |
416 | $oTemplate->display('addressbook_list.tpl'); |
417 | |
a71b394e |
418 | } |
419 | |
f6c945b9 |
420 | /* Display the "new address" form */ |
caa596b2 |
421 | //FIXME: Remove HTML from here! (echo abook_create_form() is OK, since it is all template based output |
c1ac62d4 |
422 | echo '<a name="AddAddress"></a>' . "\n"; |
caa596b2 |
423 | echo abook_create_form($form_url, 'addaddr', |
424 | _("Add to address book"), |
425 | _("Add address"), |
426 | $current_backend, |
427 | $defdata); |
fc93f97c |
428 | echo "</form>\n"; |
daba719e |
429 | |
df4162cb |
430 | /* Hook for extra address book blocks */ |
6e515418 |
431 | do_hook('addressbook_bottom', $null); |
a71b394e |
432 | |
5c4ff7bf |
433 | $oTemplate->display('footer.tpl'); |