Mercurial > hg > rc2
comparison program/steps/settings/folders.inc @ 0:4681f974d28b
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:52:31 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4681f974d28b |
---|---|
1 <?php | |
2 | |
3 /** | |
4 +-----------------------------------------------------------------------+ | |
5 | program/steps/settings/folders.inc | | |
6 | | | |
7 | This file is part of the Roundcube Webmail client | | |
8 | Copyright (C) 2005-2013, The Roundcube Dev Team | | |
9 | | | |
10 | Licensed under the GNU General Public License version 3 or | | |
11 | any later version with exceptions for skins & plugins. | | |
12 | See the README file for a full license statement. | | |
13 | | | |
14 | PURPOSE: | | |
15 | Provide functionality of folders management | | |
16 | | | |
17 +-----------------------------------------------------------------------+ | |
18 | Author: Thomas Bruederli <roundcube@gmail.com> | | |
19 | Author: Aleksander Machniak <alec@alec.pl> | | |
20 +-----------------------------------------------------------------------+ | |
21 */ | |
22 | |
23 // init IMAP connection | |
24 $STORAGE = $RCMAIL->get_storage(); | |
25 | |
26 // subscribe mailbox | |
27 if ($RCMAIL->action == 'subscribe') { | |
28 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); | |
29 | |
30 if (strlen($mbox)) { | |
31 $result = $STORAGE->subscribe(array($mbox)); | |
32 | |
33 // Handle virtual (non-existing) folders | |
34 if (!$result && $STORAGE->get_error_code() == -1 && | |
35 $STORAGE->get_response_code() == rcube_storage::TRYCREATE | |
36 ) { | |
37 $result = $STORAGE->create_folder($mbox, true); | |
38 if ($result) { | |
39 // @TODO: remove 'virtual' class of folder's row | |
40 } | |
41 } | |
42 | |
43 if ($result) { | |
44 // Handle subscription of protected folder (#1487656) | |
45 if ($RCMAIL->config->get('protect_default_folders') | |
46 && $STORAGE->is_special_folder($mbox) | |
47 ) { | |
48 $OUTPUT->command('disable_subscription', $mbox); | |
49 } | |
50 | |
51 $OUTPUT->show_message('foldersubscribed', 'confirmation'); | |
52 } | |
53 else { | |
54 $RCMAIL->display_server_error('errorsaving'); | |
55 $OUTPUT->command('reset_subscription', $mbox, false); | |
56 } | |
57 } | |
58 } | |
59 // unsubscribe mailbox | |
60 else if ($RCMAIL->action == 'unsubscribe') { | |
61 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); | |
62 | |
63 if (strlen($mbox)) { | |
64 $result = $STORAGE->unsubscribe(array($mbox)); | |
65 | |
66 if ($result) { | |
67 $OUTPUT->show_message('folderunsubscribed', 'confirmation'); | |
68 } | |
69 else { | |
70 $RCMAIL->display_server_error('errorsaving'); | |
71 $OUTPUT->command('reset_subscription', $mbox, true); | |
72 } | |
73 } | |
74 } | |
75 // delete an existing mailbox | |
76 else if ($RCMAIL->action == 'delete-folder') { | |
77 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); | |
78 | |
79 if (strlen($mbox)) { | |
80 $plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox)); | |
81 | |
82 if (!$plugin['abort']) { | |
83 $deleted = $STORAGE->delete_folder($plugin['name']); | |
84 } | |
85 else { | |
86 $deleted = $plugin['result']; | |
87 } | |
88 | |
89 // #1488692: update session | |
90 if ($deleted && $_SESSION['mbox'] === $mbox) { | |
91 $RCMAIL->session->remove('mbox'); | |
92 } | |
93 } | |
94 | |
95 if ($OUTPUT->ajax_call && $deleted) { | |
96 // Remove folder and subfolders rows | |
97 $OUTPUT->command('remove_folder_row', $mbox); | |
98 $OUTPUT->show_message('folderdeleted', 'confirmation'); | |
99 // Clear content frame | |
100 $OUTPUT->command('subscription_select'); | |
101 $OUTPUT->command('set_quota', $RCMAIL->quota_content()); | |
102 } | |
103 else if (!$deleted) { | |
104 $RCMAIL->display_server_error('errorsaving'); | |
105 } | |
106 } | |
107 // rename an existing mailbox | |
108 else if ($RCMAIL->action == 'rename-folder') { | |
109 $name = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true)); | |
110 $oldname = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true); | |
111 | |
112 if (strlen($name) && strlen($oldname)) { | |
113 $rename = rcmail_rename_folder($oldname, $name); | |
114 } | |
115 | |
116 if ($rename && $OUTPUT->ajax_call) { | |
117 rcmail_update_folder_row($name, $oldname); | |
118 } | |
119 else if (!$rename) { | |
120 $RCMAIL->display_server_error('errorsaving'); | |
121 } | |
122 } | |
123 // clear mailbox | |
124 else if ($RCMAIL->action == 'purge') { | |
125 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); | |
126 $delimiter = $STORAGE->get_hierarchy_delimiter(); | |
127 $trash_mbox = $RCMAIL->config->get('trash_mbox'); | |
128 $trash_regexp = '/^' . preg_quote($trash . $delimiter, '/') . '/'; | |
129 | |
130 // we should only be purging trash (or their subfolders) | |
131 if (!strlen($trash_mbox) || $mbox === $trash_mbox | |
132 || preg_match($trash_regexp, $mbox) | |
133 ) { | |
134 $success = $STORAGE->delete_message('*', $mbox); | |
135 $delete = true; | |
136 } | |
137 // move to Trash | |
138 else { | |
139 $success = $STORAGE->move_message('1:*', $trash_mbox, $mbox); | |
140 $delete = false; | |
141 } | |
142 | |
143 if ($success) { | |
144 $OUTPUT->set_env('messagecount', 0); | |
145 if ($delete) { | |
146 $OUTPUT->show_message('folderpurged', 'confirmation'); | |
147 $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox)); | |
148 } | |
149 else { | |
150 $OUTPUT->show_message('messagemoved', 'confirmation'); | |
151 } | |
152 $_SESSION['unseen_count'][$mbox] = 0; | |
153 $OUTPUT->command('show_folder', $mbox, null, true); | |
154 } | |
155 else { | |
156 $RCMAIL->display_server_error('errorsaving'); | |
157 } | |
158 } | |
159 // get mailbox size | |
160 else if ($RCMAIL->action == 'folder-size') { | |
161 $name = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); | |
162 | |
163 $size = $STORAGE->folder_size($name); | |
164 | |
165 // @TODO: check quota and show percentage usage of specified mailbox? | |
166 | |
167 if ($size !== false) { | |
168 $OUTPUT->command('folder_size_update', $RCMAIL->show_bytes($size)); | |
169 } | |
170 else { | |
171 $RCMAIL->display_server_error(); | |
172 } | |
173 } | |
174 | |
175 if ($OUTPUT->ajax_call) { | |
176 $OUTPUT->send(); | |
177 } | |
178 | |
179 $OUTPUT->set_pagetitle($RCMAIL->gettext('folders')); | |
180 $OUTPUT->set_env('prefix_ns', $STORAGE->get_namespace('prefix')); | |
181 $OUTPUT->set_env('quota', (bool) $STORAGE->get_capability('QUOTA')); | |
182 $OUTPUT->include_script('treelist.js'); | |
183 | |
184 // add some labels to client | |
185 $OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting', | |
186 'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota'); | |
187 | |
188 // register UI objects | |
189 $OUTPUT->add_handlers(array( | |
190 'foldersubscription' => 'rcmail_subscription_form', | |
191 'folderframe' => 'rcmail_folder_frame', | |
192 'folderfilter' => 'rcmail_folder_filter', | |
193 'quotadisplay' => array($RCMAIL, 'quota_display'), | |
194 )); | |
195 | |
196 $OUTPUT->send('folders'); | |
197 | |
198 | |
199 // build table with all folders listed by server | |
200 function rcmail_subscription_form($attrib) | |
201 { | |
202 global $RCMAIL, $OUTPUT; | |
203 | |
204 list($form_start, $form_end) = get_form_tags($attrib, 'folders'); | |
205 unset($attrib['form']); | |
206 | |
207 if (!$attrib['id']) { | |
208 $attrib['id'] = 'rcmSubscriptionlist'; | |
209 } | |
210 | |
211 $STORAGE = $RCMAIL->get_storage(); | |
212 | |
213 // get folders from server | |
214 $STORAGE->clear_cache('mailboxes', true); | |
215 | |
216 $a_unsubscribed = $STORAGE->list_folders(); | |
217 $a_subscribed = $STORAGE->list_folders_subscribed('', '*', null, null, true); // unsorted | |
218 $delimiter = $STORAGE->get_hierarchy_delimiter(); | |
219 $namespace = $STORAGE->get_namespace(); | |
220 $special_folders = array_flip(array_merge(array('inbox' => 'INBOX'), $STORAGE->get_special_folders())); | |
221 $protect_default = $RCMAIL->config->get('protect_default_folders'); | |
222 $seen = array(); | |
223 $list_folders = array(); | |
224 | |
225 // pre-process folders list | |
226 foreach ($a_unsubscribed as $i => $folder) { | |
227 $folder_id = $folder; | |
228 $folder = $STORAGE->mod_folder($folder); | |
229 $foldersplit = explode($delimiter, $folder); | |
230 $name = rcube_charset::convert(array_pop($foldersplit), 'UTF7-IMAP'); | |
231 $parent_folder = join($delimiter, $foldersplit); | |
232 $level = count($foldersplit); | |
233 | |
234 // add any necessary "virtual" parent folders | |
235 if ($parent_folder && !isset($seen[$parent_folder])) { | |
236 for ($i=1; $i<=$level; $i++) { | |
237 $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); | |
238 if ($ancestor_folder && !$seen[$ancestor_folder]++) { | |
239 $ancestor_name = rcube_charset::convert($foldersplit[$i-1], 'UTF7-IMAP'); | |
240 $list_folders[] = array( | |
241 'id' => $ancestor_folder, | |
242 'name' => $ancestor_name, | |
243 'level' => $i-1, | |
244 'virtual' => true, | |
245 ); | |
246 } | |
247 } | |
248 } | |
249 | |
250 // Handle properly INBOX.INBOX situation | |
251 if (isset($seen[$folder])) { | |
252 continue; | |
253 } | |
254 | |
255 $seen[$folder]++; | |
256 | |
257 $list_folders[] = array( | |
258 'id' => $folder_id, | |
259 'name' => $name, | |
260 'level' => $level, | |
261 ); | |
262 } | |
263 | |
264 unset($seen); | |
265 | |
266 $checkbox_subscribe = new html_checkbox(array( | |
267 'name' => '_subscribed[]', | |
268 'title' => $RCMAIL->gettext('changesubscription'), | |
269 'onclick' => rcmail_output::JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)", | |
270 )); | |
271 | |
272 $js_folders = array(); | |
273 $folders = array(); | |
274 $collapsed = (string) $RCMAIL->config->get('collapsed_folders'); | |
275 | |
276 // create list of available folders | |
277 foreach ($list_folders as $i => $folder) { | |
278 $sub_key = array_search($folder['id'], $a_subscribed); | |
279 $subscribed = $sub_key !== false; | |
280 $special = $folder['id'] == 'INBOX' || isset($special_folders[$folder['id']]); | |
281 $protected = $folder['id'] == 'INBOX' || ($protect_default && $special); | |
282 $noselect = false; | |
283 $classes = array(); | |
284 | |
285 $folder_utf8 = rcube_charset::convert($folder['id'], 'UTF7-IMAP'); | |
286 $display_folder = rcube::Q($special ? $RCMAIL->localize_foldername($folder['id'], false, true) : $folder['name']); | |
287 | |
288 if ($folder['virtual']) { | |
289 $classes[] = 'virtual'; | |
290 } | |
291 | |
292 // Check \Noselect flag (of existing folder) | |
293 if (!$protected && in_array($folder['id'], $a_unsubscribed)) { | |
294 $attrs = $STORAGE->folder_attributes($folder['id']); | |
295 $noselect = in_array_nocase('\\Noselect', $attrs); | |
296 } | |
297 | |
298 $disabled = (($protected && $subscribed) || $noselect); | |
299 | |
300 // Below we will disable subscription option for "virtual" folders | |
301 // according to namespaces, but only if they aren't already subscribed. | |
302 // User should be able to unsubscribe from the folder | |
303 // even if it doesn't exists or is not accessible (OTRS:1000059) | |
304 if (!$subscribed && !$disabled && !empty($namespace) && $folder['virtual']) { | |
305 // check if the folder is a namespace prefix, then disable subscription option on it | |
306 if (!$disabled && $folder['level'] == 0) { | |
307 $fname = $folder['id'] . $delimiter; | |
308 foreach ($namespace as $ns) { | |
309 if (is_array($ns)) { | |
310 foreach ($ns as $item) { | |
311 if ($item[0] === $fname) { | |
312 $disabled = true; | |
313 break 2; | |
314 } | |
315 } | |
316 } | |
317 } | |
318 } | |
319 // check if the folder is an other users virtual-root folder, then disable subscription option on it | |
320 if (!$disabled && $folder['level'] == 1 && !empty($namespace['other'])) { | |
321 $parts = explode($delimiter, $folder['id']); | |
322 $fname = $parts[0] . $delimiter; | |
323 foreach ($namespace['other'] as $item) { | |
324 if ($item[0] === $fname) { | |
325 $disabled = true; | |
326 break; | |
327 } | |
328 } | |
329 } | |
330 // check if the folder is shared, then disable subscription option on it (if not subscribed already) | |
331 if (!$disabled) { | |
332 $tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']); | |
333 foreach ($tmp_ns as $item) { | |
334 if (strlen($item[0]) && strpos($folder['id'], $item[0]) === 0) { | |
335 $disabled = true; | |
336 break; | |
337 } | |
338 } | |
339 } | |
340 } | |
341 | |
342 $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false; | |
343 $folder_id = rcube_utils::html_identifier($folder['id'], true); | |
344 | |
345 if ($folder_class = $RCMAIL->folder_classname($folder['id'])) { | |
346 $classes[] = $folder_class; | |
347 } | |
348 | |
349 $folders[$folder['id']] = array( | |
350 'idx' => $folder_id, | |
351 'folder_imap' => $folder['id'], | |
352 'folder' => $folder_utf8, | |
353 'display' => $display_folder, | |
354 'protected' => $protected || $folder['virtual'], | |
355 'class' => join(' ', $classes), | |
356 'subscribed' => $subscribed, | |
357 'level' => $folder['level'], | |
358 'collapsed' => $is_collapsed, | |
359 'content' => html::a(array('href' => '#'), $display_folder) | |
360 . $checkbox_subscribe->show(($subscribed ? $folder['id'] : ''), | |
361 array('value' => $folder['id'], 'disabled' => $disabled ? 'disabled' : '')) | |
362 ); | |
363 } | |
364 | |
365 $plugin = $RCMAIL->plugins->exec_hook('folders_list', array('list' => $folders)); | |
366 | |
367 // add drop-target representing 'root' | |
368 $root = array( | |
369 'idx' => rcube_utils::html_identifier('*', true), | |
370 'folder_imap' => '*', | |
371 'folder' => '', | |
372 'display' => '', | |
373 'protected' => true, | |
374 'class' => 'root', | |
375 'content' => '<span> </span>', | |
376 ); | |
377 | |
378 $folders = array(); | |
379 $plugin['list'] = array_values($plugin['list']); | |
380 | |
381 array_unshift($plugin['list'], $root); | |
382 | |
383 for ($i = 0, $length = count($plugin['list']); $i<$length; $i++) { | |
384 $folders[] = rcmail_folder_tree_element($plugin['list'], $i, $js_folders); | |
385 } | |
386 | |
387 $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); | |
388 $OUTPUT->set_env('subscriptionrows', $js_folders); | |
389 $OUTPUT->set_env('defaultfolders', array_keys($special_folders)); | |
390 $OUTPUT->set_env('collapsed_folders', $collapsed); | |
391 $OUTPUT->set_env('delimiter', $delimiter); | |
392 | |
393 return $form_start . html::tag('ul', $attrib, implode('', $folders), html::$common_attrib) . $form_end; | |
394 } | |
395 | |
396 function rcmail_folder_tree_element($folders, &$key, &$js_folders) | |
397 { | |
398 $data = $folders[$key]; | |
399 $idx = 'rcmli' . $data['idx']; | |
400 | |
401 $js_folders[$data['folder_imap']] = array($data['folder'], $data['display'], $data['protected']); | |
402 $content = $data['content']; | |
403 $attribs = array( | |
404 'id' => $idx, | |
405 'class' => trim($data['class'] . ' mailbox') | |
406 ); | |
407 | |
408 $children = array(); | |
409 while ($folders[$key+1] && $folders[$key+1]['level'] > $data['level']) { | |
410 $key++; | |
411 $children[] = rcmail_folder_tree_element($folders, $key, $js_folders); | |
412 } | |
413 | |
414 if (!empty($children)) { | |
415 $content .= html::div('treetoggle ' . ($data['collapsed'] ? 'collapsed' : 'expanded'), ' ') | |
416 . html::tag('ul', array('style' => ($data['collapsed'] ? "display:none" : null)), | |
417 implode("\n", $children)); | |
418 } | |
419 | |
420 return html::tag('li', $attribs, $content); | |
421 } | |
422 | |
423 function rcmail_folder_frame($attrib) | |
424 { | |
425 global $OUTPUT; | |
426 | |
427 if (!$attrib['id']) { | |
428 $attrib['id'] = 'rcmfolderframe'; | |
429 } | |
430 | |
431 return $OUTPUT->frame($attrib, true); | |
432 } | |
433 | |
434 function rcmail_folder_filter($attrib) | |
435 { | |
436 global $RCMAIL; | |
437 | |
438 $storage = $RCMAIL->get_storage(); | |
439 $namespace = $storage->get_namespace(); | |
440 | |
441 if (empty($namespace['personal']) && empty($namespace['shared']) && empty($namespace['other'])) { | |
442 return ''; | |
443 } | |
444 | |
445 if (!$attrib['id']) { | |
446 $attrib['id'] = 'rcmfolderfilter'; | |
447 } | |
448 | |
449 $attrib['onchange'] = rcmail_output::JS_OBJECT_NAME . '.folder_filter(this.value)'; | |
450 | |
451 $roots = array(); | |
452 $select = new html_select($attrib); | |
453 $select->add($RCMAIL->gettext('all'), '---'); | |
454 | |
455 foreach (array_keys($namespace) as $type) { | |
456 foreach ((array)$namespace[$type] as $ns) { | |
457 $root = rtrim($ns[0], $ns[1]); | |
458 $label = $RCMAIL->gettext('namespace.' . $type); | |
459 | |
460 if (count($namespace[$type]) > 1) { | |
461 $label .= ' (' . rcube_charset::convert($root, 'UTF7-IMAP', RCUBE_CHARSET) . ')'; | |
462 } | |
463 | |
464 $select->add($label, $root); | |
465 | |
466 if (strlen($root)) { | |
467 $roots[] = $root; | |
468 } | |
469 } | |
470 } | |
471 | |
472 $RCMAIL->output->add_gui_object('foldersfilter', $attrib['id']); | |
473 $RCMAIL->output->set_env('ns_roots', $roots); | |
474 | |
475 return $select->show(); | |
476 } | |
477 | |
478 function rcmail_rename_folder($oldname, $newname) | |
479 { | |
480 global $RCMAIL; | |
481 | |
482 $storage = $RCMAIL->get_storage(); | |
483 $delimiter = $storage->get_hierarchy_delimiter(); | |
484 | |
485 $plugin = $RCMAIL->plugins->exec_hook('folder_rename', array( | |
486 'oldname' => $oldname, 'newname' => $newname)); | |
487 | |
488 if (!$plugin['abort']) { | |
489 $renamed = $storage->rename_folder($oldname, $newname); | |
490 } | |
491 else { | |
492 $renamed = $plugin['result']; | |
493 } | |
494 | |
495 // update per-folder options for modified folder and its subfolders | |
496 if ($renamed) { | |
497 $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); | |
498 $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; | |
499 | |
500 foreach ($a_threaded as $key => $val) { | |
501 if ($key == $oldname) { | |
502 unset($a_threaded[$key]); | |
503 $a_threaded[$newname] = $val; | |
504 } | |
505 else if (preg_match($oldprefix, $key)) { | |
506 unset($a_threaded[$key]); | |
507 $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = $val; | |
508 } | |
509 } | |
510 | |
511 $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); | |
512 | |
513 // #1488692: update session | |
514 if ($_SESSION['mbox'] === $oldname) { | |
515 $_SESSION['mbox'] = $newname; | |
516 } | |
517 | |
518 return true; | |
519 } | |
520 | |
521 return false; | |
522 } |