diff options
author | alecpl <alec@alec.pl> | 2010-12-03 10:58:40 +0000 |
---|---|---|
committer | alecpl <alec@alec.pl> | 2010-12-03 10:58:40 +0000 |
commit | af3c045ecf4865361981f4c9aa392dfe1f93ac90 (patch) | |
tree | 5d82d0c7e056c020033d13f0b0037cd8c7c220f8 /program/steps | |
parent | a5ee723f4254d8c7a4f8bf236c3e0a6bec8a5676 (diff) |
- New Folder Manager UI
- Fix invalid Request when creating a folder (#1487443)
- Add folder size and quota indicator in folder manager (#1485780)
- Add possibility to move a subfolder into root folder (#1486791)
Diffstat (limited to 'program/steps')
-rw-r--r-- | program/steps/mail/func.inc | 59 | ||||
-rw-r--r-- | program/steps/settings/edit_folder.inc | 294 | ||||
-rw-r--r-- | program/steps/settings/folders.inc | 370 | ||||
-rw-r--r-- | program/steps/settings/manage_folders.inc | 443 | ||||
-rw-r--r-- | program/steps/settings/save_folder.inc | 176 |
5 files changed, 840 insertions, 502 deletions
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 4803956b6..9e485eb36 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -436,65 +436,6 @@ function rcmail_messagecount_display($attrib) } -function rcmail_quota_display($attrib) - { - global $OUTPUT; - - if (!$attrib['id']) - $attrib['id'] = 'rcmquotadisplay'; - - if(isset($attrib['display'])) - $_SESSION['quota_display'] = $attrib['display']; - - $OUTPUT->add_gui_object('quotadisplay', $attrib['id']); - - $quota = rcmail_quota_content($attrib); - - $OUTPUT->add_script('$(document).ready(function(){ - rcmail.set_quota('.json_serialize($quota).')});', 'foot'); - - return html::span($attrib, ''); - } - - -function rcmail_quota_content($attrib=NULL) - { - global $COMM_PATH, $RCMAIL; - - $quota = $RCMAIL->imap->get_quota(); - $quota = $RCMAIL->plugins->exec_hook('quota', $quota); - - $quota_result = (array) $quota; - $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; - - if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited')) { - $quota_result['title'] = rcube_label('unlimited'); - $quota_result['percent'] = 0; - } - else if ($quota['total']) { - if (!isset($quota['percent'])) - $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100)); - - $title = sprintf('%s / %s (%.0f%%)', - show_bytes($quota['used'] * 1024), show_bytes($quota['total'] * 1024), - $quota_result['percent']); - - $quota_result['title'] = $title; - - if ($attrib['width']) - $quota_result['width'] = $attrib['width']; - if ($attrib['height']) - $quota_result['height'] = $attrib['height']; - } - else { - $quota_result['title'] = rcube_label('unknown'); - $quota_result['percent'] = 0; - } - - return $quota_result; - } - - function rcmail_get_messagecount_text($count=NULL, $page=NULL) { global $RCMAIL, $IMAP; diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc new file mode 100644 index 000000000..3a7c0d946 --- /dev/null +++ b/program/steps/settings/edit_folder.inc @@ -0,0 +1,294 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/settings/edit_folder.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Provide functionality to create/edit a folder | + | | + +-----------------------------------------------------------------------+ + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + +// WARNING: folder names in UI are encoded with RCMAIL_CHARSET + +// init IMAP connection +$RCMAIL->imap_connect(); + +function rcube_folder_form($attrib) +{ + global $RCMAIL; + + // edited folder name (empty in create-folder mode) + $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); + $mbox_imap = rcube_charset_convert($mbox, RCMAIL_CHARSET, 'UTF7-IMAP'); + + // predefined path for new folder + $parent = trim(get_input_value('_path', RCUBE_INPUT_GPC, true)); + $parent_imap = rcube_charset_convert($parent, RCMAIL_CHARSET, 'UTF7-IMAP'); + + $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); + $special = (strlen($mbox_imap) && in_array($mbox_imap, (array) $RCMAIL->config->get('default_imap_folders'))); + $protected = ($special && $RCMAIL->config->get('protect_default_folders')); + $threading_supported = $RCMAIL->imap->get_capability('thread=references') + || $IMAP->get_capability('thread=orderedsubject') + || $IMAP->get_capability('thread=refs'); + + // Get mailbox stats (messages count, etc.), mailbox name and parent + if (strlen($mbox)) { + $msgcount = $RCMAIL->imap->messagecount($mbox_imap, 'ALL', true, false); + + $path = explode($delimiter, $mbox_imap); + $folder = array_pop($path); + $path = implode($delimiter, $path); + + $folder = rcube_charset_convert($folder, 'UTF7-IMAP'); + + $hidden_fields = array('name' => '_mbox', 'value' => $mbox); + } + else { + $path = $parent_imap; + } + + $form = array(); + + // General tab + $form['props'] = array( + 'name' => rcube_label('properties'), + ); + + // Location (name) + if ($protected) + $foldername = rcmail_localize_foldername($mbox_imap); + else { + if (isset($_POST['_name'])) + $folder = trim(get_input_value('_name', RCUBE_INPUT_POST, true)); + + $foldername = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30)); + $foldername = $foldername->show($folder); + + if ($special) + $foldername .= ' (' . rcmail_localize_foldername($mbox_imap) .')'; + } + + $form['props']['fieldsets']['location'] = array( + 'name' => rcube_label('location'), + 'content' => array( + 'name' => array( + 'label' => rcube_label('foldername'), + 'value' => $foldername, + ), + ), + ); + + if (strlen($path)) { + $radio1 = new html_radiobutton(array('name' => '_parent', 'value' => '')); + $radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path)); + $selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path; + + $html_path = str_replace($delimiter, ' » ', rcmail_localize_folderpath($path)); + + $folderpath = $radio1->show($selected) . Q(rcube_label('none')) . ' ' + .$radio2->show($selected) . Q($html_path); + + $form['props']['fieldsets']['location']['content']['path'] = array( + 'label' => rcube_label('parentfolder'), + 'value' => $folderpath, + ); + } + + // Settings + $form['props']['fieldsets']['settings'] = array( + 'name' => rcube_label('settings'), + ); + + // Settings: threading + if ($threading_supported) { + $select = new html_select(array('name' => '_viewmode', 'id' => '_listmode')); + $select->add(rcube_label('list'), 0); + $select->add(rcube_label('threads'), 1); + + if (isset($_POST['_viewmode'])) { + $value = (int) $_POST['_viewmode']; + } + else if (strlen($mbox_imap)) { + $a_threaded = $RCMAIL->config->get('message_threading', array()); + $value = (int) isset($a_threaded[$mbox_imap]); + } + + $form['props']['fieldsets']['settings']['content']['viewmode'] = array( + 'label' => rcube_label('listmode'), + 'value' => $select->show($value), + ); + } +/* + // Settings: sorting column + $select = new html_select(array('name' => '_sortcol', 'id' => '_sortcol')); + $select->add(rcube_label('nonesort'), ''); + $select->add(rcube_label('arrival'), 'arrival'); + $select->add(rcube_label('sentdate'), 'date'); + $select->add(rcube_label('subject'), 'subject'); + $select->add(rcube_label('fromto'), 'from'); + $select->add(rcube_label('replyto'), 'replyto'); + $select->add(rcube_label('cc'), 'cc'); + $select->add(rcube_label('size'), 'size'); + + $value = isset($_POST['_sortcol']) ? $_POST['_sortcol'] : ''; + + $form['props']['fieldsets']['settings']['content']['sortcol'] = array( + 'label' => rcube_label('listsorting'), + 'value' => $select->show($value), + ); + + // Settings: sorting order + $select = new html_select(array('name' => '_sortord', 'id' => '_sortord')); + $select->add(rcube_label('asc'), 'ASC'); + $select->add(rcube_label('desc'), 'DESC'); + + $value = isset($_POST['_sortord']) ? $_POST['_sortord'] : ''; + + $form['props']['fieldsets']['settings']['content']['sortord'] = array( + 'label' => rcube_label('listorder'), + 'value' => $select->show(), + ); +*/ + // Information (count, size) - Edit mode + if (strlen($mbox)) { + // Number of messages + $form['props']['fieldsets']['info'] = array( + 'name' => rcube_label('info'), + 'content' => array( + 'count' => array( + 'label' => rcube_label('messagecount'), + 'value' => (int) $msgcount, + ), + ), + ); + + // Size + if ($msgcount) { + // create link with folder-size command + $onclick = sprintf("return %s.command('folder-size', '%s', this)", + JS_OBJECT_NAME, JQ($mbox_imap)); + $size = html::a(array('href' => '#', 'onclick' => $onclick, 'id' => 'folder-size'), + rcube_label('getfoldersize')); + } + else { + // no messages -> zero size + $size = 0; + } + $form['props']['fieldsets']['info']['content']['size'] = array( + 'label' => rcube_label('size'), + 'value' => $size, + ); + } + + // Allow plugins to modify folder form content + $plugin = $RCMAIL->plugins->exec_hook('folder_form', array('form' => $form)); + + $form = $plugin['form']; + + // Set form tags and hidden fields + list($form_start, $form_end) = get_form_tags($attrib, 'save-folder', null, $hidden_fields); + + unset($attrib['form']); + + // return the complete edit form as table + $out = "$form_start\n"; + + // Create form output + foreach ($form as $tab) { + if (!empty($tab['fieldsets']) && is_array($tab['fieldsets'])) { + $content = ''; + foreach ($tab['fieldsets'] as $fieldset) { + $subcontent = rcmail_get_form_part($fieldset); + if ($subcontent) { + $content .= html::tag('fieldset', null, html::tag('legend', null, Q($fieldset['name'])) . $subcontent) ."\n"; + } + } + } + else { + $content = rcmail_get_form_part($tab); + } + + if ($content) { + $out .= html::tag('fieldset', null, html::tag('legend', null, Q($tab['name'])) . $content) ."\n"; + } + } + + $out .= "\n$form_end"; + + $RCMAIL->output->set_env('messagecount', (int) $msgcount); + + return $out; +} + +function rcmail_get_form_part($form) +{ + $content = ''; + + if (is_array($form['content']) && !empty($form['content'])) { + $table = new html_table(array('cols' => 2)); + foreach ($form['content'] as $col => $colprop) { + $colprop['id'] = '_'.$col; + $label = !empty($colprop['label']) ? $colprop['label'] : rcube_label($col); + + $table->add('title', sprintf('<label for="%s">%s</label>', $colprop['id'], Q($label))); + $table->add(null, $colprop['value']); + } + $content = $table->show(); + } + else { + $content = $tag['content']; + } + + return $content; +} + +function rcmail_localize_folderpath($path) +{ + global $RCMAIL; + + $protect_folders = $RCMAIL->config->get('protect_default_folders'); + $default_folders = (array) $RCMAIL->config->get('default_imap_folders'); + $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); + $path = explode($delimiter, $path); + $result = array(); + + foreach ($path as $idx => $dir) { + $directory = implode($delimiter, array_slice($path, 0, $idx+1)); + if ($protect_folders && in_array($directory, $default_folders)) { + unset($result); + $result[] = rcmail_localize_foldername($directory); + } + else if ($protect_folders && in_array($dir, $default_folders)) { + $result[] = rcmail_localize_foldername($dir); + } + else { + $result[] = rcube_charset_convert($dir, 'UTF7-IMAP'); + } + } + + return implode($delimiter, $result); +} + + +//$OUTPUT->set_pagetitle(rcube_label('folders')); + +// register UI objects +$OUTPUT->add_handlers(array( + 'folderdetails' => 'rcube_folder_form', +)); + +$OUTPUT->add_label('nonamewarning'); + +$OUTPUT->send('folderedit'); diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc new file mode 100644 index 000000000..b90487a07 --- /dev/null +++ b/program/steps/settings/folders.inc @@ -0,0 +1,370 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/settings/folders.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Provide functionality of folders management | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + +// WARNING: folder names in UI are encoded with RCMAIL_CHARSET + +// init IMAP connection +$RCMAIL->imap_connect(); + +// subscribe mailbox +if ($RCMAIL->action == 'subscribe') +{ + $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); + if (strlen($mbox)) { + $result = $IMAP->subscribe(array($mbox)); + + // Handle virtual (non-existing) folders + if (!$result && $IMAP->get_error_code() == -1 && + strpos($IMAP->get_error_str(), '[TRYCREATE]') + ) { + $result = $IMAP->create_mailbox($mbox, true); + if ($result) { + // @TODO: remove 'virtual' class of folder's row + } + } + + if ($result) + $OUTPUT->show_message('foldersubscribed', 'confirmation'); + else + $OUTPUT->show_message('errorsaving', 'error'); + } +} + +// unsubscribe mailbox +else if ($RCMAIL->action == 'unsubscribe') +{ + $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); + if (strlen($mbox)) { + $result = $IMAP->unsubscribe(array($mbox)); + if ($result) + $OUTPUT->show_message('folderunsubscribed', 'confirmation'); + else + $OUTPUT->show_message('errorsaving', 'error'); + } +} + +// delete an existing mailbox +else if ($RCMAIL->action == 'delete-folder') +{ + $a_mboxes = $IMAP->list_unsubscribed(); + $delimiter = $IMAP->get_hierarchy_delimiter(); + + $mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true); + $mbox = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); + + if (strlen($mbox)) + $deleted = $IMAP->delete_mailbox(array($mbox)); + + if ($OUTPUT->ajax_call && $deleted) { + // Remove folder rows + $OUTPUT->command('remove_folder_row', $mbox_utf8); + foreach ($a_mboxes as $folder) { + if (preg_match('/^'. preg_quote($mbox.$delimiter, '/') .'/', $folder)) { + $OUTPUT->command('remove_folder_row', rcube_charset_convert($folder, 'UTF7-IMAP')); + } + } + $OUTPUT->show_message('folderdeleted', 'confirmation'); + // Clear content frame + $OUTPUT->command('subscription_select'); + $OUTPUT->command('set_quota', rcmail_quota_content()); + } + else if (!$deleted) { + $OUTPUT->show_message('errorsaving', 'error'); + } +} + +// rename an existing mailbox +else if ($RCMAIL->action == 'rename-folder') +{ + $name_utf8 = trim(get_input_value('_folder_newname', RCUBE_INPUT_POST, true)); + $oldname_utf8 = trim(get_input_value('_folder_oldname', RCUBE_INPUT_POST, true)); + + if (strlen($name_utf8) && strlen($oldname_utf8)) { + $name = rcube_charset_convert($name_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); + $oldname = rcube_charset_convert($oldname_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); + + $rename = rcmail_rename_folder($oldname, $name); + } + + if ($rename && $OUTPUT->ajax_call) { + $folderlist = $IMAP->list_unsubscribed(); + $delimiter = $IMAP->get_hierarchy_delimiter(); + + $regexp = '/^' . preg_quote($name . $delimiter, '/') . '/'; + + // subfolders + for ($x=sizeof($folderlist)-1; $x>=0; $x--) { + if (preg_match($regexp, $folderlist[$x])) { + $oldfolder = $oldname . $delimiter . preg_replace($regexp, '', $folderlist[$x]); + $foldersplit = explode($delimiter, $folderlist[$x]); + $level = count($foldersplit) - 1; + $display_rename = str_repeat(' ', $level) + . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP'); + + $before = isset($folderlist[$x+1]) ? rcube_charset_convert($folderlist[$x+1], 'UTF7-IMAP') : false; + + $OUTPUT->command('replace_folder_row', rcube_charset_convert($oldfolder, 'UTF7-IMAP'), + rcube_charset_convert($folderlist[$x], 'UTF7-IMAP'), $display_rename, $before); + } + } + + $foldersplit = explode($delimiter, $name); + $level = count($foldersplit) - 1; + $display_rename = str_repeat(' ', $level) . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP'); + $index = array_search($name, $folderlist); + $before = $index !== false && isset($folderlist[$index+1]) ? rcube_charset_convert($folderlist[$index+1], 'UTF7-IMAP') : false; + + $OUTPUT->command('replace_folder_row', $oldname_utf8, + rcube_charset_convert($name, 'UTF7-IMAP'), $display_rename, $before); + } + else if (!$rename) { + $OUTPUT->show_message('errorsaving', 'error'); + } +} + +// clear mailbox +else if ($RCMAIL->action == 'purge') +{ + $mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true); + $mbox = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); + $delimiter = $IMAP->get_hierarchy_delimiter(); + $trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/'; + + // we should only be purging trash (or their subfolders) + if (!strlen($CONFIG['trash_mbox']) || $mbox == $CONFIG['trash_mbox'] + || preg_match($trash_regexp, $mbox) + ) { + $success = $IMAP->clear_mailbox($mbox); + $delete = true; + } + // copy to Trash + else { + $success = $IMAP->move_message('1:*', $CONFIG['trash_mbox'], $mbox); + $delete = false; + } + + if ($success) { + $OUTPUT->set_env('messagecount', 0); + if ($delete) { + $OUTPUT->show_message('folderpurged', 'confirmation'); + $OUTPUT->command('set_quota', rcmail_quota_content()); + } + else { + $OUTPUT->show_message('messagemoved', 'confirmation'); + } + $_SESSION['unseen_count'][$mbox] = 0; + $OUTPUT->command('show_folder', $mbox_utf8, null, true); + } + else { + $OUTPUT->show_message('errorsaving', 'error'); + } +} + +// get mailbox size +else if ($RCMAIL->action == 'folder-size') +{ + $name = trim(get_input_value('_mbox', RCUBE_INPUT_POST, true)); + + $size = $IMAP->get_mailbox_size($name); + + // @TODO: check quota and show percentage usage of specified mailbox? + + if ($size !== false) { + $OUTPUT->command('folder_size_update', show_bytes($size)); + } +} + +if ($OUTPUT->ajax_call) + $OUTPUT->send(); + + +// build table with all folders listed by server +function rcube_subscription_form($attrib) +{ + global $RCMAIL, $IMAP, $CONFIG, $OUTPUT; + + list($form_start, $form_end) = get_form_tags($attrib, 'folders'); + unset($attrib['form']); + + if (!$attrib['id']) + $attrib['id'] = 'rcmSubscriptionlist'; + + $table = new html_table(); + + if ($attrib['noheader'] !== true && $attrib['noheader'] != "true") { + // add table header + $table->add_header('name', rcube_label('foldername')); + $table->add_header('subscribed', ''); + } + + // get folders from server + $IMAP->clear_cache('mailboxes'); + + $a_unsubscribed = $IMAP->list_unsubscribed(); + $a_subscribed = $IMAP->list_mailboxes(); + $delimiter = $IMAP->get_hierarchy_delimiter(); + $a_js_folders = array(); + $seen = array(); + $list_folders = array(); + + // pre-process folders list + foreach ($a_unsubscribed as $i => $folder) { + $foldersplit = explode($delimiter, $folder); + $name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP'); + $parent_folder = join($delimiter, $foldersplit); + $level = count($foldersplit); + + // add any necessary "virtual" parent folders + if ($parent_folder && !$seen[$parent_folder]) { + for ($i=1; $i<=$level; $i++) { + $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); + if ($ancestor_folder && !$seen[$ancestor_folder]++) { + $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); + $list_folders[] = array( + 'id' => $ancestor_folder, + 'name' => $ancestor_name, + 'level' => $i-1, + 'virtual' => true, + ); + } + } + } + + $seen[$folder]++; + + $list_folders[] = array( + 'id' => $folder, + 'name' => $name, + 'level' => $level, + ); + } + + unset($seen); + + $checkbox_subscribe = new html_checkbox(array( + 'name' => '_subscribed[]', + 'title' => rcube_label('changesubscription'), + 'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)", + )); + + // create list of available folders + foreach ($list_folders as $i => $folder) { + $idx = $i + 1; + $subscribed = in_array($folder['id'], $a_subscribed); + $protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders'])); + $classes = array($i%2 ? 'even' : 'odd'); + + $folder_js = Q($folder['id']); + $folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP'); + $display_folder = str_repeat(' ', $folder['level']) + . Q($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']); + + if ($folder['virtual']) { + $classes[] = 'virtual'; + } + + if (!$protected) { + $opts = $IMAP->mailbox_options($folder['id']); + $noselect = in_array('\\Noselect', $opts); + } + + $table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes))); + + $table->add('name', $display_folder); + $table->add('subscribed', $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''), + array('value' => $folder_utf8, 'disabled' => ($protected || $noselect) ? 'disabled' : ''))); + + $a_js_folders['rcmrow'.$idx] = array($folder_utf8, Q($display_folder), $protected || $folder['virtual']); + } + + $RCMAIL->plugins->exec_hook('folders_list', array('table' => $table)); + + $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); + $OUTPUT->set_env('subscriptionrows', $a_js_folders); + $OUTPUT->set_env('defaultfolders', $CONFIG['default_imap_folders']); + $OUTPUT->set_env('delimiter', $delimiter); + + return $form_start . $table->show($attrib) . $form_end; +} + +function rcmail_folder_frame($attrib) +{ + global $OUTPUT; + + if (!$attrib['id']) + $attrib['id'] = 'rcmfolderframe'; + + $attrib['name'] = $attrib['id']; + + $OUTPUT->set_env('contentframe', $attrib['name']); + $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif'); + + return html::iframe($attrib); +} + +function rcmail_rename_folder($oldname, $newname) +{ + global $RCMAIL; + + $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); + $rename = $RCMAIL->imap->rename_mailbox($oldname, $newname); + + // update per-folder options for modified folder and its subfolders + if ($rename !== false) { + $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); + $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; + + foreach ($a_threaded as $key => $val) { + if ($key == $oldname) { + unset($a_threaded[$key]); + $a_threaded[$newname] = true; + } + else if (preg_match($oldprefix, $key)) { + unset($a_threaded[$key]); + $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = true; + } + } + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); + + return true; + } + + return false; +} + +$OUTPUT->set_pagetitle(rcube_label('folders')); +$OUTPUT->include_script('list.js'); +$OUTPUT->set_env('quota', $IMAP->get_capability('QUOTA')); + +// add some labels to client +$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting', + 'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota'); + +// register UI objects +$OUTPUT->add_handlers(array( + 'foldersubscription' => 'rcube_subscription_form', + 'folderframe' => 'rcmail_folder_frame', + 'quotadisplay' => 'rcmail_quota_display', +)); + +$OUTPUT->send('folders'); + diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc deleted file mode 100644 index 3a5d909e4..000000000 --- a/program/steps/settings/manage_folders.inc +++ /dev/null @@ -1,443 +0,0 @@ -<?php - -/* - +-----------------------------------------------------------------------+ - | program/steps/settings/manage_folders.inc | - | | - | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | - | Licensed under the GNU GPL | - | | - | PURPOSE: | - | Provide functionality to create/delete/rename folders | - | | - +-----------------------------------------------------------------------+ - | Author: Thomas Bruederli <roundcube@gmail.com> | - +-----------------------------------------------------------------------+ - - $Id$ - -*/ - -// WARNING: folder names in UI are encoded with RCMAIL_CHARSET - -// init IMAP connection -$RCMAIL->imap_connect(); - -// subscribe to one or more mailboxes -if ($RCMAIL->action=='subscribe') - { - $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); - if (strlen($mbox)) - $IMAP->subscribe(array($mbox)); - } - -// unsubscribe one or more mailboxes -else if ($RCMAIL->action=='unsubscribe') - { - $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); - if (strlen($mbox)) - $IMAP->unsubscribe(array($mbox)); - } - -// enable threading for one or more mailboxes -else if ($RCMAIL->action=='enable-threading') - { - $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); - if (strlen($mbox)) - rcube_set_threading($mbox, true); - } - -// enable threading for one or more mailboxes -else if ($RCMAIL->action=='disable-threading') - { - $mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP'); - if (strlen($mbox)) - rcube_set_threading($mbox, false); - } - -// create a new mailbox -else if ($RCMAIL->action=='create-folder') - { - if (strlen(trim($_POST['_name']))) - { - $name = trim(get_input_value('_name', RCUBE_INPUT_POST, true, 'UTF7-IMAP')); - $create = $IMAP->create_mailbox($name, TRUE); - } - - if ($create && $OUTPUT->ajax_call) - { - $delimiter = $IMAP->get_hierarchy_delimiter(); - $folderlist = $IMAP->list_unsubscribed(); - $index = array_search($create, $folderlist); - $before = $index !== false && isset($folderlist[$index+1]) ? rcube_charset_convert($folderlist[$index+1], 'UTF7-IMAP') : false; - - $create = rcube_charset_convert($create, 'UTF7-IMAP'); - $foldersplit = explode($delimiter, $create); - $display_create = str_repeat(' ', substr_count($create, $delimiter)) - . Q($foldersplit[count($foldersplit)-1]); - - $OUTPUT->command('add_folder_row', $create, $display_create, false, $before); - } - else if (!$create) - { - $OUTPUT->show_message('errorsaving', 'error'); - } - } - -// rename a mailbox -else if ($RCMAIL->action=='rename-folder') - { - if (strlen(trim($_POST['_folder_oldname'])) && strlen(trim($_POST['_folder_newname']))) - { - $name_utf8 = trim(get_input_value('_folder_newname', RCUBE_INPUT_POST, true)); - $oldname_utf8 = get_input_value('_folder_oldname', RCUBE_INPUT_POST, true); - $name = rcube_charset_convert($name_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); - $oldname = rcube_charset_convert($oldname_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); - - $rename = $IMAP->rename_mailbox($oldname, $name); - } - - // update per-folder options for modified folder and its subfolders - if ($rename) { - $a_threaded = $RCMAIL->config->get('message_threading', array()); - $delimiter = $IMAP->get_hierarchy_delimiter(); - $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; - foreach ($a_threaded as $key => $val) - if ($key == $oldname) { - unset($a_threaded[$key]); - $a_threaded[$name] = true; - } - else if (preg_match($oldprefix, $key)) { - unset($a_threaded[$key]); - $a_threaded[preg_replace($oldprefix, $name.$delimiter, $key)] = true; - } - - $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); - } - - if ($rename && $OUTPUT->ajax_call) - { - $folderlist = $IMAP->list_unsubscribed(); - $delimiter = $IMAP->get_hierarchy_delimiter(); - - $regexp = '/^' . preg_quote($rename . $delimiter, '/') . '/'; - - // subfolders - for ($x=sizeof($folderlist)-1; $x>=0; $x--) - { - if (preg_match($regexp, $folderlist[$x])) - { - $oldfolder = $oldname . $delimiter . preg_replace($regexp, '', $folderlist[$x]); - $foldersplit = explode($delimiter, $folderlist[$x]); - $level = count($foldersplit) - 1; - $display_rename = str_repeat(' ', $level) - . Q(rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP')); - - $before = isset($folderlist[$x+1]) ? rcube_charset_convert($folderlist[$x+1], 'UTF7-IMAP') : false; - - $OUTPUT->command('replace_folder_row', rcube_charset_convert($oldfolder, 'UTF7-IMAP'), - rcube_charset_convert($folderlist[$x], 'UTF7-IMAP'), $display_rename, $before); - } - } - - $foldersplit = explode($delimiter, $rename); - $level = count($foldersplit) - 1; - $display_rename = str_repeat(' ', $level) . Q(rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP')); - $index = array_search($rename, $folderlist); - $before = $index !== false && isset($folderlist[$index+1]) ? rcube_charset_convert($folderlist[$index+1], 'UTF7-IMAP') : false; - - $OUTPUT->command('replace_folder_row', $oldname_utf8, rcube_charset_convert($rename, 'UTF7-IMAP'), $display_rename, $before); - $OUTPUT->command('reset_folder_rename'); - } - else if (!$rename && $OUTPUT->ajax_call) - { - $OUTPUT->command('reset_folder_rename'); - $OUTPUT->show_message('errorsaving', 'error'); - } - else if (!$rename) - $OUTPUT->show_message('errorsaving', 'error'); - } - -// delete an existing IMAP mailbox -else if ($RCMAIL->action=='delete-folder') - { - $a_mboxes = $IMAP->list_unsubscribed(); - $delimiter = $IMAP->get_hierarchy_delimiter(); - - $mboxes_utf8 = get_input_value('_mboxes', RCUBE_INPUT_POST, true); - $mboxes = rcube_charset_convert($mboxes_utf8, RCMAIL_CHARSET, 'UTF7-IMAP'); - - if (strlen($mboxes)) - $deleted = $IMAP->delete_mailbox(array($mboxes)); - - if ($OUTPUT->ajax_call && $deleted) - { - $OUTPUT->command('remove_folder_row', $mboxes_utf8); - foreach ($a_mboxes as $mbox) - { - if (preg_match('/^'. preg_quote($mboxes.$delimiter, '/') .'/', $mbox)) - { - $OUTPUT->command('remove_folder_row', rcube_charset_convert($mbox, 'UTF7-IMAP')); - } - } - $OUTPUT->show_message('folderdeleted', 'confirmation'); - } - else if (!$deleted) - { - $OUTPUT->show_message('errorsaving', 'error'); - } - } - -if ($OUTPUT->ajax_call) - $OUTPUT->send(); - - -// build table with all folders listed by server -function rcube_subscription_form($attrib) - { - global $RCMAIL, $IMAP, $CONFIG, $OUTPUT; - - $threading_supported = $IMAP->get_capability('thread=references') - || $IMAP->get_capability('thread=orderedsubject') - || $IMAP->get_capability('thread=refs'); - - list($form_start, $form_end) = get_form_tags($attrib, 'folders'); - unset($attrib['form']); - - if (!$attrib['id']) - $attrib['id'] = 'rcmSubscriptionlist'; - - $table = new html_table(); - - // add table header - $table->add_header('name', rcube_label('foldername')); - $table->add_header('msgcount', rcube_label('messagecount')); - $table->add_header('subscribed', rcube_label('subscribed')); - if ($threading_supported) - $table->add_header('threaded', rcube_label('threaded')); - $table->add_header('rename', ' '); - $table->add_header('delete', ' '); - - // get folders from server - $IMAP->clear_cache('mailboxes'); - - $a_unsubscribed = $IMAP->list_unsubscribed(); - $a_subscribed = $IMAP->list_mailboxes(); - $a_threaded = $a_threaded_copy = $RCMAIL->config->get('message_threading', array()); - $delimiter = $IMAP->get_hierarchy_delimiter(); - $a_js_folders = $seen = $list_folders = array(); - - // pre-process folders list - foreach ($a_unsubscribed as $i => $folder) { - $foldersplit = explode($delimiter, $folder); - $name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP'); - $parent_folder = join($delimiter, $foldersplit); - $level = count($foldersplit); - - // add any necessary "virtual" parent folders - if ($parent_folder && !$seen[$parent_folder]) { - for ($i=1; $i<=$level; $i++) { - $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); - if ($ancestor_folder && !$seen[$ancestor_folder]++) { - $ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP'); - $list_folders[] = array('id' => $ancestor_folder, 'name' => $ancestor_name, 'level' => $i-1, 'virtual' => true); - } - } - } - - unset($a_threaded_copy[$folder]); - - $list_folders[] = array('id' => $folder, 'name' => $name, 'level' => $level); - $seen[$folder]++; - } - - unset($seen); - - // remove 'message_threading' option for not existing folders - if ($a_threaded_copy) { - foreach ($a_threaded_copy as $key => $val) - unset($a_threaded[$key]); - unset($a_threaded_copy); - $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); - } - - $checkbox_subscribe = new html_checkbox(array( - 'name' => '_subscribed[]', - 'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)", - )); - $checkbox_threaded = new html_checkbox(array( - 'name' => '_threaded[]', - 'onclick' => JS_OBJECT_NAME.".command(this.checked?'enable-threading':'disable-threading',this.value)", - )); - - if (!empty($attrib['deleteicon'])) - $del_button = html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))); - else - $del_button = rcube_label('delete'); - - if (!empty($attrib['renameicon'])) - $edit_button = html::img(array('src' => $CONFIG['skin_path'] . $attrib['renameicon'], 'alt' => rcube_label('rename'))); - else - $edit_button = rcube_label('rename'); - - // create list of available folders - foreach ($list_folders as $i => $folder) { - $idx = $i + 1; - $subscribed = in_array($folder['id'], $a_subscribed); - $threaded = $a_threaded[$folder['id']]; - $protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders'])); - $classes = array($i%2 ? 'even' : 'odd'); - $folder_js = Q($folder['id']); - $display_folder = str_repeat(' ', $folder['level']) . Q($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']); - $folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP'); - - if ($folder['virtual']) { - $classes[] = 'virtual'; - } - - if (!$protected) { - $opts = $IMAP->mailbox_options($folder['id']); - $noselect = in_array('\\Noselect', $opts); - } - - $table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes))); - - $table->add('name', $display_folder); - $table->add('msgcount', (($folder['virtual'] || $noselect) ? '' : $IMAP->messagecount($folder['id'], 'ALL', false, false))); - $table->add('subscribed', $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''), - array('value' => $folder_utf8, 'disabled' => ($protected || $noselect) ? 'disabled' : ''))); - if ($threading_supported) { - $table->add('threaded', $folder['virtual'] ? '' : - $checkbox_threaded->show(($threaded ? $folder_utf8 : ''), array('value' => $folder_utf8))); - } - - // add rename and delete buttons - if (!$protected && !$folder['virtual']) { - $table->add('rename', html::a(array('href' => "#rename", 'title' => rcube_label('renamefolder')), $edit_button)); - $table->add('delete', html::a(array('href' => "#delete", 'title' => rcube_label('deletefolder')), $del_button)); - } - else { - $table->add('rename', ' '); - $table->add('delete', ' '); - } - - $a_js_folders['rcmrow'.$idx] = array($folder_utf8, Q($display_folder), $protected || $folder['virtual']); - } - - rcmail::get_instance()->plugins->exec_hook('folders_list', array('table' => $table)); - - $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); - $OUTPUT->set_env('subscriptionrows', $a_js_folders); - $OUTPUT->set_env('defaultfolders', $CONFIG['default_imap_folders']); - $OUTPUT->set_env('delimiter', $delimiter); - - return $form_start . $table->show($attrib) . $form_end; - } - - -function rcube_create_folder_form($attrib) - { - global $OUTPUT; - - list($form_start, $form_end) = get_form_tags($attrib, 'create-folder'); - unset($attrib['form']); - - if ($attrib['hintbox']) - $OUTPUT->add_gui_object('createfolderhint', $attrib['hintbox']); - - // return the complete edit form as table - $out = "$form_start\n"; - - $input = new html_inputfield(array('name' => '_folder_name')); - $out .= $input->show(); - - if (get_boolean($attrib['button'])) - { - $button = new html_inputfield(array('type' => 'button', - 'value' => rcube_label('create'), - 'onclick' => JS_OBJECT_NAME.".command('create-folder',this.form)")); - $out .= $button->show(); - } - - $out .= "\n$form_end"; - - return $out; - } - -function rcube_rename_folder_form($attrib) - { - global $CONFIG, $IMAP; - - list($form_start, $form_end) = get_form_tags($attrib, 'rename-folder'); - unset($attrib['form']); - - // return the complete edit form as table - $out = "$form_start\n"; - - $a_unsubscribed = $IMAP->list_unsubscribed(); - $select_folder = new html_select(array('name' => '_folder_oldname', 'id' => 'rcmfd_oldfolder')); - - foreach ($a_unsubscribed as $i => $folder) - { - if ($CONFIG['protect_default_folders'] == TRUE && in_array($folder,$CONFIG['default_imap_folders'])) - continue; - - $select_folder->add($folder); - } - - $out .= $select_folder->show(); - - $out .= " to "; - $inputtwo = new html_inputfield(array('name' => '_folder_newname')); - $out .= $inputtwo->show(); - - if (get_boolean($attrib['button'])) - { - $button = new html_inputfield(array('type' => 'button', - 'value' => rcube_label('rename'), - 'onclick' => JS_OBJECT_NAME.".command('rename-folder',this.form)")); - $out .= $button->show(); - } - - $out .= "\n$form_end"; - - return $out; - } - - -// (un)set 'threading' for selected folder -function rcube_set_threading($mbox, $state=true) - { - global $RCMAIL; - $mbox = (array)$mbox; - $a_prefs = (array)$RCMAIL->config->get('message_threading'); - - if ($state) { - foreach ($mbox as $box) - $a_prefs[$box] = true; - } - else { - foreach ($mbox as $box) - unset($a_prefs[$box]); - } - - $RCMAIL->user->save_prefs(array('message_threading' => $a_prefs)); - } - - -$OUTPUT->set_pagetitle(rcube_label('folders')); -$OUTPUT->include_script('list.js'); - -// register UI objects -$OUTPUT->add_handlers(array( - 'foldersubscription' => 'rcube_subscription_form', - 'createfolder' => 'rcube_create_folder_form', - 'renamefolder' => 'rcube_rename_folder_form' -)); - -// add some labels to client -$OUTPUT->add_label('deletefolderconfirm','addsubfolderhint','forbiddencharacter','folderdeleting','folderrenaming','foldercreating','foldermoving'); - -$OUTPUT->send('managefolders'); - diff --git a/program/steps/settings/save_folder.inc b/program/steps/settings/save_folder.inc new file mode 100644 index 000000000..da646a56e --- /dev/null +++ b/program/steps/settings/save_folder.inc @@ -0,0 +1,176 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/settings/save_folder.inc | + | | + | This file is part of the Roundcube Webmail client | + | Copyright (C) 2005-2009, Roundcube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Provide functionality to create/edit a folder | + | | + +-----------------------------------------------------------------------+ + | Author: Aleksander Machniak <alec@alec.pl> | + +-----------------------------------------------------------------------+ + + $Id$ + +*/ + +// WARNING: folder names in UI are encoded with RCMAIL_CHARSET + +// init IMAP connection +$RCMAIL->imap_connect(); + + +$name = trim(get_input_value('_name', RCUBE_INPUT_POST, true)); +$old = trim(get_input_value('_mbox', RCUBE_INPUT_POST, true)); +$path = trim(get_input_value('_parent', RCUBE_INPUT_POST, true)); + +$name_imap = rcube_charset_convert($name, RCMAIL_CHARSET, 'UTF7-IMAP'); +$old_imap = rcube_charset_convert($old, RCMAIL_CHARSET, 'UTF7-IMAP'); +// $path is in UTF7-IMAP already + +$delimiter = $IMAP->get_hierarchy_delimiter(); +$special = (strlen($old_imap) && in_array($old_imap, (array) $RCMAIL->config->get('default_imap_folders'))); +$protected = ($special && $RCMAIL->config->get('protect_default_folders')); + + +// Folder name checks +if ($protected) { +} +else if (!strlen($name)) { + $error = rcube_label('cannotbeempty'); +} +else if (mb_strlen($name) > 128) { + $error = rcube_label('nametoolong'); +} +else { + // these characters are problematic e.g. when used in LIST/LSUB + foreach (array($delimiter, '%', '*') as $char) { + if (strpos($name, $delimiter) !== false) { + $error = rcube_label('forbiddencharacter') . " ($char)"; + break; + } + } +} + +if ($error) { + $OUTPUT->command('display_message', $error, 'error'); +} +else { + if ($protected) { + $name_imap = $old_imap; + } + else if (strlen($path)) { + $name_imap = $path . $delimiter . $name_imap; + } + + $folder['name'] = $name_imap; + $folder['oldname'] = $old_imap; + $folder['settings'] = array( + // List view mode: 0-list, 1-threads + 'view_mode' => (int) get_input_value('_viewmode', RCUBE_INPUT_POST), + 'sort_column' => get_input_value('_sortcol', RCUBE_INPUT_POST), + 'sort_order' => get_input_value('_sortord', RCUBE_INPUT_POST), + ); +} + +// create a new mailbox +if (!$error && !strlen($old)) { + + $plugin = $RCMAIL->plugins->exec_hook('folder_create', array('record' => $folder)); + + $folder = $plugin['record']; + + if (!$plugin['abort']) { + $created = $IMAP->create_mailbox($folder['name'], TRUE); + } + else { + $created = $plugin['result']; + } + + if ($created) { + // Save folder settings + if (isset($_POST['_viewmode'])) { + $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); + + if ($_POST['_viewmode']) + $a_threaded[$folder['name']] = true; + else + unset($a_threaded[$folder['name']]); + + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); + } + + $OUTPUT->show_message('foldercreated', 'confirmation'); + $OUTPUT->command('reload', 250); + $OUTPUT->send('iframe'); + } + else { + // show error message + $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error', null, false); + } +} + +// update a mailbox +else if (!$error) { + $plugin = $RCMAIL->plugins->exec_hook('folder_update', array('record' => $folder)); + + $folder = $plugin['record']; + $rename = ($folder['oldname'] != $folder['name']); + + if (!$plugin['abort']) { + if ($rename) { + $updated = $RCMAIL->imap->rename_mailbox($folder['oldname'], $folder['name']); + } + else { + $updated = true; + } + } + else { + $updated = $plugin['result']; + } + + if ($updated) { + // Update folder settings, + if (isset($_POST['_viewmode'])) { + $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); + + // In case of name change update names of childrens in settings + if ($rename) { + $delimiter = $RCMAIL->imap->get_hierarchy_delimiter(); + $oldprefix = '/^' . preg_quote($folder['oldname'] . $delimiter, '/') . '/'; + foreach ($a_threaded as $key => $val) { + if ($key == $folder['oldname']) { + unset($a_threaded[$key]); + } + else if (preg_match($oldprefix, $key)) { + unset($a_threaded[$key]); + $a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = true; + } + } + } + if ($_POST['_viewmode']) + $a_threaded[$folder['name']] = true; + else + unset($a_threaded[$folder['name']]); + + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); + } + + $OUTPUT->show_message('folderupdated', 'confirmation'); + if ($rename) { + $OUTPUT->command('reload', 250); + $OUTPUT->send('iframe'); + } + } + else { + // show error message + $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error', null, false); + } +} + +rcmail_overwrite_action('edit-folder'); |