Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/roundcube/roundcubemail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2020-11-01 13:25:38 +0300
committerGitHub <noreply@github.com>2020-11-01 13:25:38 +0300
commit545a1569f115b5c8aa0be78061258d5f116d7b4b (patch)
treea76645a856cf148f839a74a9de5cedd21054922e /program/include/rcmail.php
parent2829f302755f8492fb095735f3fc89688727e1a3 (diff)
Steps -> Actions refactoring (#7688)
* Move action handling code to rcmail class * Add rcmail_action class * Add action aliases * Get rid of $OUTPUT global * Move some methods from rcmail to rcmail_action * PHP8 compat. fixes * Add framework for testing actions * Fix obvious code mistakes
Diffstat (limited to 'program/include/rcmail.php')
-rw-r--r--program/include/rcmail.php1180
1 files changed, 145 insertions, 1035 deletions
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 7d30673ad..f0ca1d275 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -52,10 +52,11 @@ class rcmail extends rcube
public $filename = '';
public $default_skin;
public $login_error;
+ public $oauth;
- private $address_books = array();
- private $action_map = array();
-
+ private $address_books = [];
+ private $action_map = [];
+ private $action_args = [];
const ERROR_STORAGE = -2;
const ERROR_INVALID_REQUEST = 1;
@@ -136,10 +137,10 @@ class rcmail extends rcube
// init output class (not in CLI mode)
if (!empty($_REQUEST['_remote'])) {
- $GLOBALS['OUTPUT'] = $this->json_init();
+ $this->json_init();
}
else if (!empty($_SERVER['REMOTE_ADDR'])) {
- $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
+ $this->load_gui(!empty($_REQUEST['_framed']));
}
// load oauth manager
@@ -209,6 +210,87 @@ class rcmail extends rcube
}
/**
+ * Handle the request. All request pre-checks are NOT done here.
+ */
+ public function action_handler()
+ {
+ // we're ready, user is authenticated and the request is safe
+ $plugin = $this->plugins->exec_hook('ready', ['task' => $this->task, 'action' => $this->action]);
+
+ $this->set_task($plugin['task']);
+ $this->action = $plugin['action'];
+
+ // handle special actions
+ if ($this->action == 'keep-alive') {
+ $this->output->reset();
+ $this->plugins->exec_hook('keep_alive', []);
+ $this->output->send();
+ }
+
+ $task = $this->action == 'save-pref' ? 'utils' : $this->task;
+ $task = $task == 'addressbook' ? 'contacts' : $task;
+ $task_class = "rcmail_action_{$task}_index";
+
+ // execute the action index handler
+ if (class_exists($task_class)) {
+ $task_handler = new $task_class;
+ $task_handler->run();
+ }
+
+ // allow 5 "redirects" to another action
+ $redirects = 0;
+ while ($redirects < 5) {
+ // execute a plugin action
+ if (preg_match('/^plugin\./', $this->action)) {
+ $this->plugins->exec_action($this->action);
+ break;
+ }
+
+ // execute action registered to a plugin task
+ if ($this->plugins->is_plugin_task($this->task)) {
+ if (!$this->action) $this->action = 'index';
+ $this->plugins->exec_action("{$this->task}.{$this->action}");
+ break;
+ }
+
+ $action = !empty($this->action) ? $this->action : 'index';
+
+ // handle deprecated action names
+ if (!empty($task_handler) && !empty($task_handler::$aliases[$action])) {
+ $action = $task_handler::$aliases[$action];
+ }
+
+ $action = str_replace('-', '_', $action);
+ $class = "rcmail_action_{$task}_{$action}";
+
+ // Run the action (except the index)
+ if ($class != $task_class && class_exists($class)) {
+ $handler = new $class;
+ if (!$handler->checks()) {
+ break;
+ }
+ $handler->run($this->action_args);
+ $redirects++;
+ }
+ else {
+ break;
+ }
+ }
+
+ if ($this->action == 'refresh') {
+ $last = intval(rcube_utils::get_input_value('_last', rcube_utils::INPUT_GPC));
+ $this->plugins->exec_hook('refresh', ['last' => $last]);
+ }
+
+ // parse main template (default)
+ $this->output->send($this->task);
+
+ // if we arrive here, something went wrong
+ $error = ['code' => 404, 'line' => __LINE__, 'file' => __FILE__, 'message' => "Invalid request"];
+ rcmail::raise_error($error, true, true);
+ }
+
+ /**
* Return instance of the internal address book class
*
* @param string $id Address book identifier. It accepts also special values:
@@ -514,7 +596,7 @@ class rcmail extends rcube
public function json_init()
{
if (!($this->output instanceof rcmail_output_json)) {
- $this->output = new rcmail_output_json($this->task);
+ $this->output = new rcmail_output_json();
}
return $this->output;
@@ -1055,34 +1137,6 @@ class rcmail extends rcube
}
/**
- * Registers action aliases for current task
- *
- * @param array $map Alias-to-filename hash array
- */
- public function register_action_map($map)
- {
- if (is_array($map)) {
- foreach ($map as $idx => $val) {
- $this->action_map[$idx] = $val;
- }
- }
- }
-
- /**
- * Returns current action filename
- *
- * @param array $map Alias-to-filename hash array
- */
- public function get_action_file()
- {
- if (!empty($this->action_map[$this->action])) {
- return $this->action_map[$this->action];
- }
-
- return strtr($this->action, '-', '_') . '.inc';
- }
-
- /**
* Fixes some user preferences according to namespace handling change.
* Old Roundcube versions were using folder names with removed namespace prefix.
* Now we need to add the prefix on servers where personal namespace has prefix.
@@ -1184,10 +1238,12 @@ class rcmail extends rcube
* Overwrite action variable
*
* @param string $action New action value
+ * @param array $args Arguments to be passed to the next action
*/
- public function overwrite_action($action)
+ public function overwrite_action($action, $args = [])
{
- $this->action = $action;
+ $this->action = $action;
+ $this->action_args = array_merge($this->action_args, $args);
$this->output->set_env('action', $action);
}
@@ -1195,14 +1251,12 @@ class rcmail extends rcube
* Set environment variables for specified config options
*
* @param array $options List of configuration option names
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::set_env_config()
*/
public function set_env_config($options)
{
- foreach ((array) $options as $option) {
- if ($this->config->get($option)) {
- $this->output->set_env($option, true);
- }
- }
+ rcmail_action::set_env_config($options);
}
/**
@@ -1420,47 +1474,11 @@ class rcmail extends rcube
* @param string $id_col Name of the identifier col
*
* @return string HTML table code
+ * @deprecated since 1.5-beta, use rcmail_action::table_output()
*/
public function table_output($attrib, $table_data, $show_cols, $id_col)
{
- $table = new html_table($attrib);
-
- // add table header
- if (!$attrib['noheader']) {
- foreach ($show_cols as $col) {
- $table->add_header($col, $this->Q($this->gettext($col)));
- }
- }
-
- if (!is_array($table_data)) {
- $db = $this->get_dbh();
- while ($table_data && ($sql_arr = $db->fetch_assoc($table_data))) {
- $table->add_row(array('id' => 'rcmrow' . rcube_utils::html_identifier($sql_arr[$id_col])));
-
- // format each col
- foreach ($show_cols as $col) {
- $table->add($col, $this->Q($sql_arr[$col]));
- }
- }
- }
- else {
- foreach ($table_data as $row_data) {
- $class = !empty($row_data['class']) ? $row_data['class'] : null;
- if (!empty($attrib['rowclass']))
- $class = trim($class . ' ' . $attrib['rowclass']);
- $rowid = 'rcmrow' . rcube_utils::html_identifier($row_data[$id_col]);
-
- $table->add_row(array('id' => $rowid, 'class' => $class));
-
- // format each col
- foreach ($show_cols as $col) {
- $val = is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col];
- $table->add($col, empty($attrib['ishtml']) ? $this->Q($val) : $val);
- }
- }
- }
-
- return $table->show($attrib);
+ return rcmail_action::table_output($attrib, $table_data, $show_cols, $id_col);
}
/**
@@ -1600,96 +1618,11 @@ class rcmail extends rcube
* @param array $attrib Named parameters
*
* @return string HTML code for the gui object
+ * @deprecated since 1.5-beta, use rcmail_action::folder_list()
*/
public function folder_list($attrib)
{
- static $a_mailboxes;
-
- $attrib += array('maxlength' => 100, 'realnames' => false, 'unreadwrap' => ' (%s)');
-
- $type = !empty($attrib['type']) ? $attrib['type'] : 'ul';
- unset($attrib['type']);
-
- if ($type == 'ul' && empty($attrib['id'])) {
- $attrib['id'] = 'rcmboxlist';
- }
-
- if (empty($attrib['folder_name'])) {
- $attrib['folder_name'] = '*';
- }
-
- // get current folder
- $storage = $this->get_storage();
- $mbox_name = $storage->get_folder();
- $delimiter = $storage->get_hierarchy_delimiter();
-
- // build the folders tree
- if (empty($a_mailboxes)) {
- // get mailbox list
- $a_mailboxes = array();
- $a_folders = $storage->list_folders_subscribed(
- '',
- $attrib['folder_name'],
- isset($attrib['folder_filter']) ? $attrib['folder_filter'] : null
- );
-
- foreach ($a_folders as $folder) {
- $this->build_folder_tree($a_mailboxes, $folder, $delimiter);
- }
- }
-
- // allow plugins to alter the folder tree or to localize folder names
- $hook = $this->plugins->exec_hook('render_mailboxlist', array(
- 'list' => $a_mailboxes,
- 'delimiter' => $delimiter,
- 'type' => $type,
- 'attribs' => $attrib,
- ));
-
- $a_mailboxes = $hook['list'];
- $attrib = $hook['attribs'];
-
- if ($type == 'select') {
- $attrib['is_escaped'] = true;
- $select = new html_select($attrib);
-
- // add no-selection option
- if (!empty($attrib['noselection'])) {
- $select->add(html::quote($this->gettext($attrib['noselection'])), '');
- }
-
- $maxlength = isset($attrib['maxlength']) ? $attrib['maxlength'] : null;
- $realnames = isset($attrib['realnames']) ? $attrib['realnames'] : null;
- $default = isset($attrib['default']) ? $attrib['default'] : null;
-
- $this->render_folder_tree_select($a_mailboxes, $mbox_name, $maxlength, $select, $realnames);
- $out = $select->show($default);
- }
- else {
- $out = '';
- $js_mailboxlist = array();
- $tree = $this->render_folder_tree_html($a_mailboxes, $mbox_name, $js_mailboxlist, $attrib);
-
- if ($type != 'js') {
- $out = html::tag('ul', $attrib, $tree, html::$common_attrib);
-
- $this->output->include_script('treelist.js');
- $this->output->add_gui_object('mailboxlist', $attrib['id']);
- $this->output->set_env('unreadwrap', isset($attrib['unreadwrap']) ? $attrib['unreadwrap'] : false);
- $this->output->set_env('collapsed_folders', (string) $this->config->get('collapsed_folders'));
- }
-
- $this->output->set_env('mailboxes', $js_mailboxlist);
-
- // we can't use object keys in javascript because they are unordered
- // we need sorted folders list for folder-selector widget
- $this->output->set_env('mailboxes_list', array_keys($js_mailboxlist));
- }
-
- // add some labels to client
- $this->output->add_label('purgefolderconfirm', 'deletemessagesconfirm');
-
- return $out;
+ return rcmail_action::folder_list($attrib);
}
/**
@@ -1698,268 +1631,11 @@ class rcmail extends rcube
* @param array $p Named parameters
*
* @return html_select HTML drop-down object
+ * @deprecated since 1.5-beta, use rcmail_action::folder_selector()
*/
- public function folder_selector($p = array())
- {
- $realnames = $this->config->get('show_real_foldernames');
- $p += array('maxlength' => 100, 'realnames' => $realnames, 'is_escaped' => true);
- $a_mailboxes = array();
- $storage = $this->get_storage();
-
- if (empty($p['folder_name'])) {
- $p['folder_name'] = '*';
- }
-
- if ($p['unsubscribed']) {
- $list = $storage->list_folders('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
- }
- else {
- $list = $storage->list_folders_subscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']);
- }
-
- $delimiter = $storage->get_hierarchy_delimiter();
-
- if (!empty($p['exceptions'])) {
- $list = array_diff($list, (array) $p['exceptions']);
- }
-
- if (!empty($p['additional'])) {
- foreach ($p['additional'] as $add_folder) {
- $add_items = explode($delimiter, $add_folder);
- $folder = '';
- while (count($add_items)) {
- $folder .= array_shift($add_items);
-
- // @TODO: sorting
- if (!in_array($folder, $list)) {
- $list[] = $folder;
- }
-
- $folder .= $delimiter;
- }
- }
- }
-
- foreach ($list as $folder) {
- $this->build_folder_tree($a_mailboxes, $folder, $delimiter);
- }
-
- // allow plugins to alter the folder tree or to localize folder names
- $hook = $this->plugins->exec_hook('render_folder_selector', array(
- 'list' => $a_mailboxes,
- 'delimiter' => $delimiter,
- 'attribs' => $p,
- ));
-
- $a_mailboxes = $hook['list'];
- $p = $hook['attribs'];
-
- $select = new html_select($p);
-
- if ($p['noselection']) {
- $select->add(html::quote($p['noselection']), '');
- }
-
- $this->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
-
- return $select;
- }
-
- /**
- * Create a hierarchical array of the mailbox list
- */
- public function build_folder_tree(&$arrFolders, $folder, $delm = '/', $path = '')
+ public function folder_selector($p = [])
{
- // Handle namespace prefix
- $prefix = '';
- if (!$path) {
- $n_folder = $folder;
- $folder = $this->storage->mod_folder($folder);
-
- if ($n_folder != $folder) {
- $prefix = substr($n_folder, 0, -strlen($folder));
- }
- }
-
- $pos = strpos($folder, $delm);
-
- if ($pos !== false) {
- $subFolders = substr($folder, $pos+1);
- $currentFolder = substr($folder, 0, $pos);
-
- // sometimes folder has a delimiter as the last character
- if (!strlen($subFolders)) {
- $virtual = false;
- }
- else if (!isset($arrFolders[$currentFolder])) {
- $virtual = true;
- }
- else {
- $virtual = $arrFolders[$currentFolder]['virtual'];
- }
- }
- else {
- $subFolders = false;
- $currentFolder = $folder;
- $virtual = false;
- }
-
- $path .= $prefix . $currentFolder;
-
- if (!isset($arrFolders[$currentFolder])) {
- $arrFolders[$currentFolder] = array(
- 'id' => $path,
- 'name' => rcube_charset::convert($currentFolder, 'UTF7-IMAP'),
- 'virtual' => $virtual,
- 'folders' => array()
- );
- }
- else {
- $arrFolders[$currentFolder]['virtual'] = $virtual;
- }
-
- if (strlen($subFolders)) {
- $this->build_folder_tree($arrFolders[$currentFolder]['folders'], $subFolders, $delm, $path.$delm);
- }
- }
-
- /**
- * Return html for a structured list &lt;ul&gt; for the mailbox tree
- */
- public function render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $attrib, $nestLevel = 0)
- {
- $maxlength = intval($attrib['maxlength']);
- $realnames = (bool)$attrib['realnames'];
- $msgcounts = $this->storage->get_cache('messagecount');
- $collapsed = $this->config->get('collapsed_folders');
- $realnames = $this->config->get('show_real_foldernames');
-
- $out = '';
- foreach ($arrFolders as $folder) {
- $title = null;
- $folder_class = $this->folder_classname($folder['id']);
- $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false;
- $unread = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0;
-
- if ($folder_class && !$realnames && $this->text_exists($folder_class)) {
- $foldername = $this->gettext($folder_class);
- }
- else {
- $foldername = $folder['name'];
-
- // shorten the folder name to a given length
- if ($maxlength && $maxlength > 1) {
- $fname = abbreviate_string($foldername, $maxlength);
- if ($fname != $foldername) {
- $title = $foldername;
- }
- $foldername = $fname;
- }
- }
-
- // make folder name safe for ids and class names
- $folder_id = rcube_utils::html_identifier($folder['id'], true);
- $classes = array('mailbox');
-
- // set special class for Sent, Drafts, Trash and Junk
- if ($folder_class) {
- $classes[] = $folder_class;
- }
-
- if ($folder['id'] == $mbox_name) {
- $classes[] = 'selected';
- }
-
- if ($folder['virtual']) {
- $classes[] = 'virtual';
- }
- else if ($unread) {
- $classes[] = 'unread';
- }
-
- $js_name = $this->JQ($folder['id']);
- $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount skip-content', sprintf($attrib['unreadwrap'], $unread)) : '');
- $link_attrib = $folder['virtual'] ? array() : array(
- 'href' => $this->url(array('_mbox' => $folder['id'])),
- 'onclick' => sprintf("return %s.command('list','%s',this,event)", rcmail_output::JS_OBJECT_NAME, $js_name),
- 'rel' => $folder['id'],
- 'title' => $title,
- );
-
- $out .= html::tag('li', array(
- 'id' => "rcmli" . $folder_id,
- 'class' => implode(' ', $classes),
- 'noclose' => true
- ),
- html::a($link_attrib, $html_name));
-
- if (!empty($folder['folders'])) {
- $out .= html::div('treetoggle ' . ($is_collapsed ? 'collapsed' : 'expanded'), '&nbsp;');
- }
-
- $jslist[$folder['id']] = array(
- 'id' => $folder['id'],
- 'name' => $foldername,
- 'virtual' => $folder['virtual'],
- );
-
- if (!empty($folder_class)) {
- $jslist[$folder['id']]['class'] = $folder_class;
- }
-
- if (!empty($folder['folders'])) {
- $out .= html::tag('ul', array('style' => ($is_collapsed ? "display:none;" : null)),
- $this->render_folder_tree_html($folder['folders'], $mbox_name, $jslist, $attrib, $nestLevel+1));
- }
-
- $out .= "</li>\n";
- }
-
- return $out;
- }
-
- /**
- * Return html for a flat list <select> for the mailbox tree
- */
- public function render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames = false, $nestLevel = 0, $opts = array())
- {
- $out = '';
-
- foreach ($arrFolders as $folder) {
- // skip exceptions (and its subfolders)
- if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
- continue;
- }
-
- // skip folders in which it isn't possible to create subfolders
- if (!empty($opts['skip_noinferiors'])) {
- $attrs = $this->storage->folder_attributes($folder['id']);
- if ($attrs && in_array_nocase('\\Noinferiors', $attrs)) {
- continue;
- }
- }
-
- if (!$realnames && ($folder_class = $this->folder_classname($folder['id'])) && $this->text_exists($folder_class)) {
- $foldername = $this->gettext($folder_class);
- }
- else {
- $foldername = $folder['name'];
-
- // shorten the folder name to a given length
- if ($maxlength && $maxlength > 1) {
- $foldername = abbreviate_string($foldername, $maxlength);
- }
- }
-
- $select->add(str_repeat('&nbsp;', $nestLevel*4) . html::quote($foldername), $folder['id']);
-
- if (!empty($folder['folders'])) {
- $out .= $this->render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
- $select, $realnames, $nestLevel+1, $opts);
- }
- }
-
- return $out;
+ return rcmail_action::folder_selector($p);
}
/**
@@ -1969,37 +1645,11 @@ class rcmail extends rcube
* @param string $folder_id IMAP Folder name
*
* @return string|null CSS class name
+ * @deprecated since 1.5-beta, use rcmail_action::folder_classname()
*/
public function folder_classname($folder_id)
{
- static $classes;
-
- if ($classes === null) {
- $classes = array('INBOX' => 'inbox');
-
- // for these mailboxes we have css classes
- foreach (array('sent', 'drafts', 'trash', 'junk') as $type) {
- if (($mbox = $this->config->get($type . '_mbox')) && !isset($classes[$mbox])) {
- $classes[$mbox] = $type;
- }
- }
-
- $storage = $this->get_storage();
-
- // add classes for shared/other user namespace roots
- foreach (array('other', 'shared') as $ns_name) {
- if ($ns = $storage->get_namespace($ns_name)) {
- foreach ($ns as $root) {
- $root = substr($root[0], 0, -1);
- if (strlen($root) && !isset($classes[$root])) {
- $classes[$root] = "ns-$ns_name";
- }
- }
- }
- }
- }
-
- return !empty($classes[$folder_id]) ? $classes[$folder_id] : null;
+ return rcmail_action::folder_classname($folder_id);
}
/**
@@ -2011,70 +1661,21 @@ class rcmail extends rcube
* @param bool $path_remove Remove the path
*
* @return string Localized folder name in UTF-8 encoding
+ * @deprecated since 1.5-beta, use rcmail_action::localize_foldername()
*/
public function localize_foldername($name, $with_path = false, $path_remove = false)
{
- $realnames = $this->config->get('show_real_foldernames');
-
- if (!$realnames && ($folder_class = $this->folder_classname($name)) && $this->text_exists($folder_class)) {
- return $this->gettext($folder_class);
- }
-
- $storage = $this->get_storage();
- $delimiter = $storage->get_hierarchy_delimiter();
-
- // Remove the path
- if ($path_remove) {
- if (strpos($name, $delimiter)) {
- $path = explode($delimiter, $name);
- $name = array_pop($path);
- }
- }
- // try to localize path of the folder
- else if ($with_path && !$realnames) {
- $path = explode($delimiter, $name);
- $count = count($path);
-
- if ($count > 1) {
- for ($i = 1; $i < $count; $i++) {
- $folder = implode($delimiter, array_slice($path, 0, -$i));
- $folder_class = $this->folder_classname($folder);
-
- if ($folder_class && $this->text_exists($folder_class)) {
- $name = implode($delimiter, array_slice($path, $count - $i));
- $name = rcube_charset::convert($name, 'UTF7-IMAP');
-
- return $this->gettext($folder_class) . $delimiter . $name;
- }
- }
- }
- }
-
- return rcube_charset::convert($name, 'UTF7-IMAP');
+ return rcmail_action::localize_foldername($name, $with_path, $path_remove);
}
/**
* Localize folder path
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::localize_folderpath()
*/
public function localize_folderpath($path)
{
- $protect_folders = $this->config->get('protect_default_folders');
- $delimiter = $this->storage->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 && $this->storage->is_special_folder($directory)) {
- unset($result);
- $result[] = $this->localize_foldername($directory);
- }
- else {
- $result[] = rcube_charset::convert($dir, 'UTF7-IMAP');
- }
- }
-
- return implode($delimiter, $result);
+ return rcmail_action::localize_folderpath($path);
}
/**
@@ -2083,24 +1684,11 @@ class rcmail extends rcube
* @param array $attrib Named parameters
*
* @return string HTML code for the quota indicator object
+ * @deprecated since 1.5-beta, use rcmail_action::quota_display()
*/
public static function quota_display($attrib)
{
- $rcmail = rcmail::get_instance();
-
- if (empty($attrib['id'])) {
- $attrib['id'] = 'rcmquotadisplay';
- }
-
- $_SESSION['quota_display'] = !empty($attrib['display']) ? $attrib['display'] : 'text';
-
- $rcmail->output->add_gui_object('quotadisplay', $attrib['id']);
-
- $quota = $rcmail->quota_content($attrib);
-
- $rcmail->output->add_script('rcmail.set_quota('.rcube_output::json_serialize($quota).');', 'docready');
-
- return html::span($attrib, '&nbsp;');
+ return rcmail_action::quota_display($attrib);
}
/**
@@ -2110,81 +1698,11 @@ class rcmail extends rcube
* @param array $folder Current folder
*
* @return array Quota information
+ * @deprecated since 1.5-beta, use rcmail_action::quota_content()
*/
public function quota_content($attrib = null, $folder = null)
{
- $quota = $this->storage->get_quota($folder);
- $quota = $this->plugins->exec_hook('quota', $quota);
-
- $quota_result = (array) $quota;
- $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
- $quota_result['folder'] = $folder !== null && $folder !== '' ? $folder : 'INBOX';
-
- if ($quota['total'] > 0) {
- if (!isset($quota['percent'])) {
- $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
- }
-
- $title = $this->gettext('quota') . ': ' . sprintf('%s / %s (%.0f%%)',
- $this->show_bytes($quota['used'] * 1024),
- $this->show_bytes($quota['total'] * 1024),
- $quota_result['percent']
- );
-
- $quota_result['title'] = $title;
-
- if (!empty($attrib['width'])) {
- $quota_result['width'] = $attrib['width'];
- }
- if (!empty($attrib['height'])) {
- $quota_result['height'] = $attrib['height'];
- }
-
- // build a table of quota types/roots info
- if (($root_cnt = count($quota_result['all'])) > 1 || count($quota_result['all'][key($quota_result['all'])]) > 1) {
- $table = new html_table(array('cols' => 3, 'class' => 'quota-info'));
-
- $table->add_header(null, self::Q($this->gettext('quotatype')));
- $table->add_header(null, self::Q($this->gettext('quotatotal')));
- $table->add_header(null, self::Q($this->gettext('quotaused')));
-
- foreach ($quota_result['all'] as $root => $data) {
- if ($root_cnt > 1 && $root) {
- $table->add(array('colspan' => 3, 'class' => 'root'), self::Q($root));
- }
-
- if ($storage = $data['storage']) {
- $percent = min(100, round(($storage['used']/max(1,$storage['total']))*100));
-
- $table->add('name', self::Q($this->gettext('quotastorage')));
- $table->add(null, $this->show_bytes($storage['total'] * 1024));
- $table->add(null, sprintf('%s (%.0f%%)', $this->show_bytes($storage['used'] * 1024), $percent));
- }
- if ($message = $data['message']) {
- $percent = min(100, round(($message['used']/max(1,$message['total']))*100));
-
- $table->add('name', self::Q($this->gettext('quotamessage')));
- $table->add(null, intval($message['total']));
- $table->add(null, sprintf('%d (%.0f%%)', $message['used'], $percent));
- }
- }
-
- $quota_result['table'] = $table->show();
- }
- }
- else {
- $unlimited = $this->config->get('quota_zero_as_unlimited');
- $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown');
- $quota_result['percent'] = 0;
- }
-
- // cleanup
- unset($quota_result['abort']);
- if (empty($quota_result['table'])) {
- unset($quota_result['all']);
- }
-
- return $quota_result;
+ return rcmail_action::quota_content($attrib, $folder);
}
/**
@@ -2194,170 +1712,34 @@ class rcmail extends rcube
* @param array $fallback_args Fallback message label arguments
* @param string $suffix Message label suffix
* @param array $params Additional parameters (type, prefix)
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::display_server_error()
*/
- public function display_server_error($fallback = null, $fallback_args = null, $suffix = '', $params = array())
+ public function display_server_error($fallback = null, $fallback_args = null, $suffix = '', $params = [])
{
- $err_code = $this->storage->get_error_code();
- $res_code = $this->storage->get_response_code();
- $args = array();
-
- if ($res_code == rcube_storage::NOPERM) {
- $error = 'errornoperm';
- }
- else if ($res_code == rcube_storage::READONLY) {
- $error = 'errorreadonly';
- }
- else if ($res_code == rcube_storage::OVERQUOTA) {
- $error = 'erroroverquota';
- }
- else if ($err_code && ($err_str = $this->storage->get_error_str())) {
- // try to detect access rights problem and display appropriate message
- if (stripos($err_str, 'Permission denied') !== false) {
- $error = 'errornoperm';
- }
- // try to detect full mailbox problem and display appropriate message
- // there can be e.g. "Quota exceeded" / "quotum would exceed" / "Over quota"
- else if (stripos($err_str, 'quot') !== false && preg_match('/exceed|over/i', $err_str)) {
- $error = 'erroroverquota';
- }
- else {
- $error = 'servererrormsg';
- $args = array('msg' => rcube::Q($err_str));
- }
- }
- else if ($err_code < 0) {
- $error = 'storageerror';
- }
- else if ($fallback) {
- $error = $fallback;
- $args = $fallback_args;
- $params['prefix'] = false;
- }
-
- if (!empty($error)) {
- if ($suffix && $this->text_exists($error . $suffix)) {
- $error .= $suffix;
- }
-
- $msg = $this->gettext(array('name' => $error, 'vars' => $args));
-
- if ($params['prefix'] && $fallback) {
- $msg = $this->gettext(array('name' => $fallback, 'vars' => $fallback_args)) . ' ' . $msg;
- }
-
- $this->output->show_message($msg, $params['type'] ?: 'error');
- }
+ rcmail_action::display_server_error($fallback, $fallback_args, $suffix, $params);
}
/**
* Displays an error message on storage fatal errors
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::storage_fatal_error()
*/
public function storage_fatal_error()
{
- $err_code = $this->storage->get_error_code();
- switch ($err_code) {
- // Not all are really fatal, but these should catch
- // connection/authentication errors the best we can
- case rcube_imap_generic::ERROR_NO:
- case rcube_imap_generic::ERROR_BAD:
- case rcube_imap_generic::ERROR_BYE:
- $this->display_server_error();
- }
+ rcmail_action::storage_fatal_error();
}
/**
* Output HTML editor scripts
*
* @param string $mode Editor mode
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::html_editor()
*/
public function html_editor($mode = '')
{
- $spellcheck = intval($this->config->get('enable_spellcheck'));
- $spelldict = intval($this->config->get('spellcheck_dictionary'));
- $disabled_plugins = array();
- $disabled_buttons = array();
- $extra_plugins = array();
- $extra_buttons = array();
-
- if (!$spellcheck) {
- $disabled_plugins[] = 'spellchecker';
- }
-
- $hook = $this->plugins->exec_hook('html_editor', array(
- 'mode' => $mode,
- 'disabled_plugins' => $disabled_plugins,
- 'disabled_buttons' => $disabled_buttons,
- 'extra_plugins' => $extra_plugins,
- 'extra_buttons' => $extra_buttons,
- ));
-
- if ($hook['abort']) {
- return;
- }
-
- $lang_codes = array($_SESSION['language']);
- $assets_dir = $this->config->get('assets_dir') ?: INSTALL_PATH;
- $skin_path = $this->output->get_skin_path();
-
- if ($pos = strpos($_SESSION['language'], '_')) {
- $lang_codes[] = substr($_SESSION['language'], 0, $pos);
- }
-
- foreach ($lang_codes as $code) {
- if (file_exists("$assets_dir/program/js/tinymce/langs/$code.js")) {
- $lang = $code;
- break;
- }
- }
-
- if (empty($lang)) {
- $lang = 'en';
- }
-
- $config = array(
- 'mode' => $mode,
- 'lang' => $lang,
- 'skin_path' => $skin_path,
- 'spellcheck' => $spellcheck, // deprecated
- 'spelldict' => $spelldict,
- 'content_css' => 'program/resources/tinymce/content.css',
- 'disabled_plugins' => $hook['disabled_plugins'],
- 'disabled_buttons' => $hook['disabled_buttons'],
- 'extra_plugins' => $hook['extra_plugins'],
- 'extra_buttons' => $hook['extra_buttons'],
- );
-
- if ($path = $this->config->get('editor_css_location')) {
- if ($path = $this->find_asset($skin_path . $path)) {
- $config['content_css'] = $path;
- }
- }
-
- $font_family = $this->output->get_env('default_font');
- $font_size = $this->output->get_env('default_font_size');
- $style = array();
-
- if ($font_family) {
- $style[] = "font-family: $font_family;";
- }
- if ($font_size) {
- $style[] = "font-size: $font_size;";
- }
- if (!empty($style)) {
- $config['content_style'] = "body {" . implode(' ', $style) . "}";
- }
-
- $this->output->set_env('editor_config', $config);
- $this->output->add_label('selectimage', 'addimage', 'selectmedia', 'addmedia', 'close');
-
- if ($path = $this->config->get('media_browser_css_location', 'program/resources/tinymce/browser.css')) {
- if ($path != 'none' && ($path = $this->find_asset($path))) {
- $this->output->include_css($path);
- }
- }
-
- $this->output->include_script('tinymce/tinymce.min.js');
- $this->output->include_script('editor.js');
+ rcmail_action::html_editor($mode);
}
/**
@@ -2377,29 +1759,11 @@ class rcmail extends rcube
* @param int $max_size Optional maximum file size in bytes
*
* @return string Human-readable file size limit
+ * @deprecated since 1.5-beta, use rcmail_action::upload_init()
*/
public function upload_init($max_size = null)
{
- // find max filesize value
- $max_filesize = rcube_utils::max_upload_size();
- if ($max_size && $max_size < $max_filesize) {
- $max_filesize = $max_size;
- }
-
- $max_filesize_txt = $this->show_bytes($max_filesize);
- $this->output->set_env('max_filesize', $max_filesize);
- $this->output->set_env('filesizeerror', $this->gettext(array(
- 'name' => 'filesizeerror', 'vars' => array('size' => $max_filesize_txt))));
-
- if ($max_filecount = ini_get('max_file_uploads')) {
- $this->output->set_env('max_filecount', $max_filecount);
- $this->output->set_env('filecounterror', $this->gettext(array(
- 'name' => 'filecounterror', 'vars' => array('count' => $max_filecount))));
- }
-
- $this->output->add_label('uploadprogress', 'GB', 'MB', 'KB', 'B');
-
- return $max_filesize_txt;
+ return rcmail_action::upload_init($max_size);
}
/**
@@ -2412,164 +1776,33 @@ class rcmail extends rcube
* @param int $max_size Maximum upload size
*
* @return string HTML output
+ * @deprecated since 1.5-beta, use rcmail_action::upload_form()
*/
- public function upload_form($attrib, $name, $action, $input_attr = array(), $max_size = null)
+ public function upload_form($attrib, $name, $action, $input_attr = [], $max_size = null)
{
- // Get filesize, enable upload progress bar
- $max_filesize = $this->upload_init($max_size);
-
- $hint = html::div('hint', $this->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize))));
-
- if (!empty($attrib['mode']) && $attrib['mode'] == 'hint') {
- return $hint;
- }
-
- // set defaults
- $attrib += array('id' => 'rcmUploadbox', 'buttons' => 'yes');
-
- $event = rcmail_output::JS_OBJECT_NAME . ".command('$action', this.form)";
- $form_id = $attrib['id'] . 'Frm';
-
- // Default attributes of file input and form
- $input_attr += array(
- 'id' => $attrib['id'] . 'Input',
- 'type' => 'file',
- 'name' => '_attachments[]',
- 'class' => 'form-control',
- );
-
- $form_attr = array(
- 'id' => $form_id,
- 'name' => $name,
- 'method' => 'post',
- 'enctype' => 'multipart/form-data'
- );
-
- if (!empty($attrib['mode']) && $attrib['mode'] == 'smart') {
- unset($attrib['buttons']);
- $form_attr['class'] = 'smart-upload';
- $input_attr = array_merge($input_attr, array(
- // #5854: Chrome does not execute onchange when selecting the same file.
- // To fix this we reset the input using null value.
- 'onchange' => "$event; this.value=null",
- 'class' => 'smart-upload',
- 'tabindex' => '-1',
- ));
- }
-
- $input = new html_inputfield($input_attr);
- $content = $attrib['prefix'] . $input->show();
-
- if (empty($attrib['mode']) || $attrib['mode'] != 'smart') {
- $content = html::div(null, $content . $hint);
- }
-
- if (rcube_utils::get_boolean($attrib['buttons'])) {
- $button = new html_inputfield(array('type' => 'button'));
- $content .= html::div('buttons',
- $button->show($this->gettext('close'), array('class' => 'button', 'onclick' => "$('#{$attrib['id']}').hide()")) . ' ' .
- $button->show($this->gettext('upload'), array('class' => 'button mainaction', 'onclick' => $event))
- );
- }
-
- $this->output->add_gui_object($name, $form_id);
-
- return html::div($attrib, $this->output->form_tag($form_attr, $content));
+ return rcmail_action::upload_form($attrib, $name, $action, $input_attr, $max_size);
}
/**
* Outputs uploaded file content (with image thumbnails support
*
* @param array $file Upload file data
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::display_uploaded_file()
*/
public function display_uploaded_file($file)
{
- if (empty($file)) {
- return;
- }
-
- $file = $this->plugins->exec_hook('attachment_display', $file);
-
- if ($file['status']) {
- if (empty($file['size'])) {
- $file['size'] = $file['data'] ? strlen($file['data']) : @filesize($file['path']);
- }
-
- // generate image thumbnail for file browser in HTML editor
- if (!empty($_GET['_thumbnail'])) {
- $thumbnail_size = 80;
- $mimetype = $file['mimetype'];
- $file_ident = $file['id'] . ':' . $file['mimetype'] . ':' . $file['size'];
- $thumb_name = 'thumb' . md5($file_ident . ':' . $this->user->ID . ':' . $thumbnail_size);
- $cache_file = rcube_utils::temp_filename($thumb_name, false, false);
-
- // render thumbnail image if not done yet
- if (!is_file($cache_file)) {
- if (!$file['path']) {
- $orig_name = $filename = $cache_file . '.tmp';
- file_put_contents($orig_name, $file['data']);
- }
- else {
- $filename = $file['path'];
- }
-
- $image = new rcube_image($filename);
- if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) {
- $mimetype = 'image/' . $imgtype;
-
- if (!empty($orig_name)) {
- unlink($orig_name);
- }
- }
- }
-
- if (is_file($cache_file)) {
- // cache for 1h
- $this->output->future_expire_header(3600);
- header('Content-Type: ' . $mimetype);
- header('Content-Length: ' . filesize($cache_file));
-
- readfile($cache_file);
- exit;
- }
- }
-
- header('Content-Type: ' . $file['mimetype']);
- header('Content-Length: ' . $file['size']);
-
- if ($file['data']) {
- echo $file['data'];
- }
- else if ($file['path']) {
- readfile($file['path']);
- }
- }
+ rcmail_action::display_uploaded_file($file);
}
/**
* Initializes client-side autocompletion.
+ *
+ * @deprecated since 1.5-beta, use rcmail_action::autocomplete_init()
*/
public function autocomplete_init()
{
- static $init;
-
- if ($init) {
- return;
- }
-
- $init = 1;
-
- if (($threads = (int)$this->config->get('autocomplete_threads')) > 0) {
- $book_types = (array) $this->config->get('autocomplete_addressbooks', 'sql');
- if (count($book_types) > 1) {
- $this->output->set_env('autocomplete_threads', $threads);
- $this->output->set_env('autocomplete_sources', $book_types);
- }
- }
-
- $this->output->set_env('autocomplete_max', (int)$this->config->get('autocomplete_max', 15));
- $this->output->set_env('autocomplete_min_length', $this->config->get('autocomplete_min_length'));
- $this->output->add_label('autocompletechars', 'autocompletemore');
+ rcmail_action::autocomplete_init();
}
/**
@@ -2577,31 +1810,12 @@ class rcmail extends rcube
*
* @param string $font Font name
*
- * @param string|array Font-family specification array or string (if $font is used)
+ * @return string|array Font-family specification array or string (if $font is used)
+ * @deprecated since 1.5-beta, use rcmail_action::autocomplete_init()
*/
public static function font_defs($font = null)
{
- $fonts = array(
- 'Andale Mono' => '"Andale Mono",Times,monospace',
- 'Arial' => 'Arial,Helvetica,sans-serif',
- 'Arial Black' => '"Arial Black","Avant Garde",sans-serif',
- 'Book Antiqua' => '"Book Antiqua",Palatino,serif',
- 'Courier New' => '"Courier New",Courier,monospace',
- 'Georgia' => 'Georgia,Palatino,serif',
- 'Helvetica' => 'Helvetica,Arial,sans-serif',
- 'Impact' => 'Impact,Chicago,sans-serif',
- 'Tahoma' => 'Tahoma,Arial,Helvetica,sans-serif',
- 'Terminal' => 'Terminal,Monaco,monospace',
- 'Times New Roman' => '"Times New Roman",Times,serif',
- 'Trebuchet MS' => '"Trebuchet MS",Geneva,sans-serif',
- 'Verdana' => 'Verdana,Geneva,sans-serif',
- );
-
- if ($font) {
- return $fonts[$font];
- }
-
- return $fonts;
+ return rcmail_action::font_defs($font);
}
/**
@@ -2611,38 +1825,11 @@ class rcmail extends rcube
* @param string &$unit Size unit
*
* @return string Byte string
+ * @deprecated since 1.5-beta, use rcmail_action::show_bytes()
*/
public function show_bytes($bytes, &$unit = null)
{
- // Plugins may want to display different units
- $plugin = $this->plugins->exec_hook('show_bytes', array('bytes' => $bytes, 'unit' => null));
-
- $unit = $plugin['unit'];
-
- if (isset($plugin['result'])) {
- return $plugin['result'];
- }
-
- if ($bytes >= 1073741824) {
- $unit = 'GB';
- $gb = $bytes/1073741824;
- $str = sprintf($gb >= 10 ? "%d " : "%.1f ", $gb) . $this->gettext($unit);
- }
- else if ($bytes >= 1048576) {
- $unit = 'MB';
- $mb = $bytes/1048576;
- $str = sprintf($mb >= 10 ? "%d " : "%.1f ", $mb) . $this->gettext($unit);
- }
- else if ($bytes >= 1024) {
- $unit = 'KB';
- $str = sprintf("%d ", round($bytes/1024)) . $this->gettext($unit);
- }
- else {
- $unit = 'B';
- $str = sprintf('%d ', $bytes) . $this->gettext($unit);
- }
-
- return $str;
+ return rcmail_action::show_bytes($bytes, $unit);
}
/**
@@ -2651,31 +1838,11 @@ class rcmail extends rcube
* @param rcube_message_part $part Message part
*
* @return string Part size (and unit)
+ * @deprecated since 1.5-beta, use rcmail_action::message_part_size()
*/
public function message_part_size($part)
{
- if (isset($part->d_parameters['size'])) {
- $size = $this->show_bytes((int)$part->d_parameters['size']);
- }
- else {
- $size = $part->size;
-
- if ($size === 0) {
- $part->exact_size = true;
- }
-
- if ($part->encoding == 'base64') {
- $size = $size / 1.33;
- }
-
- $size = $this->show_bytes($size);
- }
-
- if (!$part->exact_size) {
- $size = '~' . $size;
- }
-
- return $size;
+ return rcmail_action::message_part_size($part);
}
/**
@@ -2687,56 +1854,11 @@ class rcmail extends rcube
* @param int $mode Request mode. Default: rcube_utils::INPUT_GPC.
*
* @return array List of message UIDs per folder
+ * @deprecated since 1.5-beta, use rcmail_action::get_uids()
*/
public static function get_uids($uids = null, $mbox = null, &$is_multifolder = false, $mode = null)
{
- // message UID (or comma-separated list of IDs) is provided in
- // the form of <ID>-<MBOX>[,<ID>-<MBOX>]*
-
- $_uid = $uids ?: rcube_utils::get_input_value('_uid', $mode ?: rcube_utils::INPUT_GPC);
- $_mbox = $mbox ?: (string) rcube_utils::get_input_value('_mbox', $mode ?: rcube_utils::INPUT_GPC);
-
- // already a hash array
- if (is_array($_uid) && !isset($_uid[0])) {
- return $_uid;
- }
-
- $result = array();
-
- // special case: *
- if ($_uid == '*' && is_object($_SESSION['search'][1]) && $_SESSION['search'][1]->multi) {
- $is_multifolder = true;
- // extract the full list of UIDs per folder from the search set
- foreach ($_SESSION['search'][1]->sets as $subset) {
- $mbox = $subset->get_parameters('MAILBOX');
- $result[$mbox] = $subset->get();
- }
- }
- else {
- if (is_string($_uid)) {
- $_uid = explode(',', $_uid);
- }
-
- // create a per-folder UIDs array
- foreach ((array)$_uid as $uid) {
- list($uid, $mbox) = explode('-', $uid, 2);
- if (!strlen($mbox)) {
- $mbox = $_mbox;
- }
- else {
- $is_multifolder = true;
- }
-
- if ($uid == '*') {
- $result[$mbox] = $uid;
- }
- else if (preg_match('/^[0-9:.]+$/', $uid)) {
- $result[$mbox][] = $uid;
- }
- }
- }
-
- return $result;
+ return rcmail_action::get_uids($uids, $mbox, $is_multifolder, $mode);
}
/**
@@ -2745,23 +1867,11 @@ class rcmail extends rcube
* @param string $name File name
*
* @return string File content
+ * @deprecated since 1.5-beta, use rcmail_action::get_resource_content()
*/
public function get_resource_content($name)
{
- if (!strpos($name, '/')) {
- $name = "program/resources/$name";
- }
-
- $assets_dir = $this->config->get('assets_dir');
-
- if ($assets_dir) {
- $path = slashify($assets_dir) . $name;
- if (@file_exists($path)) {
- $name = $path;
- }
- }
-
- return file_get_contents($name, false);
+ return rcmail_action::get_resource_content($name);
}
/**