From 99cdca46b7bcc46fe6affd9e9f9f60a546b2e5b8 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli <thomas@roundcube.net> Date: Thu, 05 Jun 2014 03:18:07 -0400 Subject: [PATCH] Merge branch 'dev-accessibility' --- program/include/rcmail.php | 230 ++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 152 insertions(+), 78 deletions(-) diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 4aa3ded..1a22792 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -139,6 +139,8 @@ if ($this->user && $this->user->ID) $task = !$task ? 'mail' : $task; + else if (php_sapi_name() == 'cli') + $task = 'cli'; else $task = 'login'; @@ -426,7 +428,8 @@ } // add some basic labels to client - $this->output->add_label('loading', 'servererror', 'requesttimedout', 'refreshing'); + $this->output->add_label('loading', 'servererror', 'connerror', 'requesttimedout', + 'refreshing', 'windowopenerror'); return $this->output; } @@ -492,30 +495,18 @@ $username_domain = $this->config->get('username_domain'); $login_lc = $this->config->get('login_lc', 2); - if (!$host) { - $host = $default_host; - } - - // Validate that selected host is in the list of configured hosts - if (is_array($default_host)) { - $allowed = false; - - foreach ($default_host as $key => $host_allowed) { - if (!is_numeric($key)) { - $host_allowed = $key; - } - if ($host == $host_allowed) { - $allowed = true; - break; - } + // host is validated in rcmail::autoselect_host(), so here + // we'll only handle unset host (if possible) + if (!$host && !empty($default_host)) { + if (is_array($default_host)) { + list($key, $val) = each($default_host); + $host = is_numeric($key) ? $val : $key; + } + else { + $host = $default_host; } - if (!$allowed) { - $host = null; - } - } - else if (!empty($default_host) && $host != rcube_utils::parse_host($default_host)) { - $host = null; + $host = rcube_utils::parse_host($host); } if (!$host) { @@ -644,10 +635,8 @@ // fix some old settings according to namespace prefix $this->fix_namespace_settings($user); - // create default folders on login - if ($this->config->get('create_default_folders')) { - $storage->create_default_folders(); - } + // set/create special folders + $this->set_special_folders(); // clear all mailboxes related cache(s) $storage->clear_cache('mailboxes', true); @@ -840,7 +829,10 @@ } // write performance stats to logs/console - if ($this->config->get('devel_mode')) { + if ($this->config->get('devel_mode') || $this->config->get('performance_stats')) { + // make sure logged numbers use unified format + setlocale(LC_NUMERIC, 'en_US.utf8', 'en_US.UTF-8', 'en_US', 'C'); + if (function_exists('memory_get_usage')) $mem = $this->show_bytes(memory_get_usage()); if (function_exists('memory_get_peak_usage')) @@ -923,14 +915,6 @@ if ($value = $prefs[$opt]) { if ($value != 'INBOX' && !preg_match($regexp, $value)) { $prefs[$opt] = $prefix.$value; - } - } - } - - if (!empty($prefs['default_folders'])) { - foreach ($prefs['default_folders'] as $idx => $name) { - if ($name != 'INBOX' && !preg_match($regexp, $name)) { - $prefs['default_folders'][$idx] = $prefix.$name; } } } @@ -1093,14 +1077,17 @@ } else { foreach ($table_data as $row_data) { - $class = !empty($row_data['class']) ? $row_data['class'] : ''; + $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 ($a_show_cols as $col) { - $table->add($col, $this->Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col])); + $val = is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]; + $table->add($col, empty($attrib['ishtml']) ? $this->Q($val) : $val); } } } @@ -1162,11 +1149,11 @@ $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); $pretty_date = $this->config->get('prettydate'); - if ($pretty_date && $timestamp > $today_limit && $timestamp < $now) { + if ($pretty_date && $timestamp > $today_limit && $timestamp <= $now) { $format = $this->config->get('date_today', $this->config->get('time_format', 'H:i')); $today = true; } - else if ($pretty_date && $timestamp > $week_limit && $timestamp < $now) { + else if ($pretty_date && $timestamp > $week_limit && $timestamp <= $now) { $format = $this->config->get('date_short', 'D H:i'); } else { @@ -1506,7 +1493,7 @@ $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount', 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)", rcmail_output::JS_OBJECT_NAME, $js_name), + 'onclick' => sprintf("return %s.command('list','%s',this,event)", rcmail_output::JS_OBJECT_NAME, $js_name), 'rel' => $folder['id'], 'title' => $title, ); @@ -1613,9 +1600,13 @@ * * @return string Localized folder name in UTF-8 encoding */ - public function localize_foldername($name, $with_path = true) + public function localize_foldername($name, $with_path = false) { $realnames = $this->config->get('show_real_foldernames'); + + if (!$realnames && ($folder_class = $this->folder_classname($name))) { + return $this->gettext($folder_class); + } // try to localize path of the folder if ($with_path && !$realnames) { @@ -1625,7 +1616,7 @@ $count = count($path); if ($count > 1) { - for ($i = 0; $i < $count; $i++) { + for ($i = 1; $i < $count; $i++) { $folder = implode($delimiter, array_slice($path, 0, -$i)); if ($folder_class = $this->folder_classname($folder)) { $name = implode($delimiter, array_slice($path, $count - $i)); @@ -1635,10 +1626,6 @@ } } - if (!$realnames && ($folder_class = $this->folder_classname($name))) { - return $this->gettext($folder_class); - } - return rcube_charset::convert($name, 'UTF7-IMAP'); } @@ -1646,14 +1633,13 @@ public function localize_folderpath($path) { $protect_folders = $this->config->get('protect_default_folders'); - $default_folders = (array) $this->config->get('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 && in_array($directory, $default_folders)) { + if ($protect_folders && $this->storage->is_special_folder($directory)) { unset($result); $result[] = $this->localize_foldername($directory); } @@ -1787,31 +1773,36 @@ return; } - $lang = strtolower($_SESSION['language']); + $lang_codes = array($_SESSION['language']); - // TinyMCE uses two-letter lang codes, with exception of Chinese - if (strpos($lang, 'zh_') === 0) { - $lang = str_replace('_', '-', $lang); - } - else { - $lang = substr($lang, 0, 2); + if ($pos = strpos($_SESSION['language'], '_')) { + $lang_codes[] = substr($_SESSION['language'], 0, $pos); } - if (!file_exists(INSTALL_PATH . 'program/js/tiny_mce/langs/'.$lang.'.js')) { + foreach ($lang_codes as $code) { + if (file_exists(INSTALL_PATH . 'program/js/tinymce/langs/'.$code.'.js')) { + $lang = $code; + break; + } + } + + if (empty($lang)) { $lang = 'en'; } - $script = json_encode(array( + $config = array( 'mode' => $mode, 'lang' => $lang, 'skin_path' => $this->output->get_skin_path(), 'spellcheck' => intval($this->config->get('enable_spellcheck')), 'spelldict' => intval($this->config->get('spellcheck_dictionary')) - )); + ); - $this->output->include_script('tiny_mce/tiny_mce.js'); + $this->output->add_label('selectimage', 'addimage', 'selectmedia', 'addmedia'); + $this->output->set_env('editor_config', $config); + $this->output->include_css('program/js/tinymce/roundcube/browser.css'); + $this->output->include_script('tinymce/tinymce.min.js'); $this->output->include_script('editor.js'); - $this->output->add_script("rcmail_editor_init($script)", 'docready'); } /** @@ -1843,8 +1834,8 @@ ); foreach ($emoticons as $idx => $file) { - // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" /> - $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i'; + // <img title="Cry" src="http://.../program/js/tinymce/plugins/emoticons/img/smiley-cry.gif" border="0" alt="Cry" /> + $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tinymce\/plugins\/emoticons\/img\/'.$file.'.gif"[^>]+\/>/i'; $replace[] = $idx; } @@ -1856,27 +1847,52 @@ */ public function upload_progress() { - $prefix = ini_get('apc.rfc1867_prefix'); $params = array( 'action' => $this->action, - 'name' => rcube_utils::get_input_value('_progress', rcube_utils::INPUT_GET), + 'name' => rcube_utils::get_input_value('_progress', rcube_utils::INPUT_GET), ); - if (function_exists('apc_fetch')) { - $status = apc_fetch($prefix . $params['name']); + if (function_exists('uploadprogress_get_info')) { + $status = uploadprogress_get_info($params['name']); if (!empty($status)) { - $status['percent'] = round($status['current']/$status['total']*100); - $params = array_merge($status, $params); + $params['current'] = $status['bytes_uploaded']; + $params['total'] = $status['bytes_total']; } } - if (isset($params['percent'])) - $params['text'] = $this->gettext(array('name' => 'uploadprogress', 'vars' => array( - 'percent' => $params['percent'] . '%', - 'current' => $this->show_bytes($params['current']), - 'total' => $this->show_bytes($params['total']) - ))); + if (!isset($status) && filter_var(ini_get('apc.rfc1867'), FILTER_VALIDATE_BOOLEAN) + && ini_get('apc.rfc1867_name') + ) { + $prefix = ini_get('apc.rfc1867_prefix'); + $status = apc_fetch($prefix . $params['name']); + + if (!empty($status)) { + $params['current'] = $status['current']; + $params['total'] = $status['total']; + } + } + + if (!isset($status) && filter_var(ini_get('session.upload_progress.enabled'), FILTER_VALIDATE_BOOLEAN) + && ini_get('session.upload_progress.name') + ) { + $key = ini_get('session.upload_progress.prefix') . $params['name']; + + $params['total'] = $_SESSION[$key]['content_length']; + $params['current'] = $_SESSION[$key]['bytes_processed']; + } + + if (!empty($params['total'])) { + $params['percent'] = round($status['current']/$status['total']*100); + $params['text'] = $this->gettext(array( + 'name' => 'uploadprogress', + 'vars' => array( + 'percent' => $params['percent'] . '%', + 'current' => $this->show_bytes($params['current']), + 'total' => $this->show_bytes($params['total']) + ) + )); + } $this->output->command('upload_progress_update', $params); $this->output->send(); @@ -1888,9 +1904,18 @@ public function upload_init() { // Enable upload progress bar - $rfc1867 = filter_var(ini_get('apc.rfc1867'), FILTER_VALIDATE_BOOLEAN); - if ($rfc1867 && ($seconds = $this->config->get('upload_progress'))) { - if ($field_name = ini_get('apc.rfc1867_name')) { + if ($seconds = $this->config->get('upload_progress')) { + if (function_exists('uploadprogress_get_info')) { + $field_name = 'UPLOAD_IDENTIFIER'; + } + if (!$field_name && filter_var(ini_get('apc.rfc1867'), FILTER_VALIDATE_BOOLEAN)) { + $field_name = ini_get('apc.rfc1867_name'); + } + if (!$field_name && filter_var(ini_get('session.upload_progress.enabled'), FILTER_VALIDATE_BOOLEAN)) { + $field_name = ini_get('session.upload_progress.name'); + } + + if ($field_name) { $this->output->set_env('upload_progress_name', $field_name); $this->output->set_env('upload_progress_time', (int) $seconds); } @@ -2021,6 +2046,55 @@ return $size; } + /** + * Returns message UID(s) and IMAP folder(s) from GET/POST data + * + * @param string UID value to decode + * @param string Default mailbox value (if not encoded in UIDs) + * @return array List of message UIDs per folder + */ + public static function get_uids($uids = null, $mbox = 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', RCUBE_INPUT_GPC); + $_mbox = $mbox ?: (string)rcube_utils::get_input_value('_mbox', RCUBE_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) { + // 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; + if ($uid == '*') + $result[$mbox] = $uid; + else + $result[$mbox][] = $uid; + } + } + + return $result; + } + /************************************************************************ ********* Deprecated methods (to be removed) ********* -- Gitblit v1.9.1