Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F256630
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
95 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php
index 73651f95f..920041da1 100644
--- a/program/lib/Roundcube/rcube_config.php
+++ b/program/lib/Roundcube/rcube_config.php
@@ -1,916 +1,924 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Class to read configuration settings |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
/**
* Configuration class for Roundcube
*
* @package Framework
* @subpackage Core
*/
class rcube_config
{
const DEFAULT_SKIN = 'elastic';
public $system_skin = 'elastic';
private $env = '';
private $paths = array();
private $prop = array();
private $errors = array();
private $userprefs = array();
private $immutable = array();
private $client_tz;
/**
* Renamed options
*
* @var array
*/
private $legacy_props = array(
// new name => old name
'mail_pagesize' => 'pagesize',
'addressbook_pagesize' => 'pagesize',
'reply_mode' => 'top_posting',
'refresh_interval' => 'keep_alive',
'min_refresh_interval' => 'min_keep_alive',
'messages_cache_ttl' => 'message_cache_lifetime',
'mail_read_time' => 'preview_pane_mark_read',
'session_debug' => 'log_session',
'redundant_attachments_cache_ttl' => 'redundant_attachments_memcache_ttl',
);
/**
* Object constructor
*
* @param string $env Environment suffix for config files to load
*/
public function __construct($env = '')
{
$this->env = $env;
if ($paths = getenv('RCUBE_CONFIG_PATH')) {
$this->paths = explode(PATH_SEPARATOR, $paths);
// make all paths absolute
foreach ($this->paths as $i => $path) {
if (!rcube_utils::is_absolute_path($path)) {
if ($realpath = realpath(RCUBE_INSTALL_PATH . $path)) {
$this->paths[$i] = unslashify($realpath) . '/';
}
else {
unset($this->paths[$i]);
}
}
else {
$this->paths[$i] = unslashify($path) . '/';
}
}
}
if (defined('RCUBE_CONFIG_DIR') && !in_array(RCUBE_CONFIG_DIR, $this->paths)) {
$this->paths[] = RCUBE_CONFIG_DIR;
}
if (empty($this->paths)) {
$this->paths[] = RCUBE_INSTALL_PATH . 'config/';
}
$this->load();
// Defaults, that we do not require you to configure,
// but contain information that is used in various locations in the code:
if (empty($this->prop['contactlist_fields'])) {
$this->set('contactlist_fields', array('name', 'firstname', 'surname', 'email'));
}
}
/**
* @brief Guess the type the string may fit into.
*
* Look inside the string to determine what type might be best as a container.
*
* @param mixed $value The value to inspect
*
* @return The guess at the type.
*/
private function guess_type($value)
{
$type = 'string';
// array requires hint to be passed.
if (preg_match('/^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$/', $value)) {
$type = 'double';
}
else if (preg_match('/^\d+$/', $value)) {
$type = 'integer';
}
else if (preg_match('/^(t(rue)?)|(f(alse)?)$/i', $value)) {
$type = 'boolean';
}
return $type;
}
/**
* @brief Parse environment variable into PHP type.
*
* Perform an appropriate parsing of the string to create the desired PHP type.
*
* @param string $string String to parse into PHP type
* @param string $type Type of value to return
*
* @return Appropriately typed interpretation of $string.
*/
private function parse_env($string, $type)
{
$_ = $string;
switch ($type) {
case 'boolean':
$_ = (boolean) $_;
break;
case 'integer':
$_ = (integer) $_;
break;
case 'double':
$_ = (double) $_;
break;
case 'string':
break;
case 'array':
$_ = json_decode($_, true);
break;
case 'object':
$_ = json_decode($_, false);
break;
case 'resource':
case 'NULL':
default:
$_ = $this->parse_env($_, $this->guess_type($_));
}
return $_;
}
/**
* @brief Get environment variable value.
*
* Retrieve an environment variable's value or if it's not found, return the
* provided default value.
*
* @param string $varname Environment variable name
* @param mixed $default_value Default value to return if necessary
* @param string $type Type of value to return
*
* @return Value of the environment variable or default if not found.
*/
private function getenv_default($varname, $default_value, $type = null)
{
$value = getenv($varname);
if ($value === false) {
$value = $default_value;
}
else {
$value = $this->parse_env($value, $type ?: gettype($default_value));
}
return $value;
}
/**
* Load config from local config file
*/
private function load()
{
// Load default settings
if (!$this->load_from_file('defaults.inc.php')) {
$this->errors[] = 'defaults.inc.php was not found.';
}
// load main config file
if (!$this->load_from_file('config.inc.php')) {
// Old configuration files
if (!$this->load_from_file('main.inc.php') || !$this->load_from_file('db.inc.php')) {
$this->errors[] = 'config.inc.php was not found.';
}
else if (rand(1,100) == 10) { // log warning on every 100th request (average)
trigger_error("config.inc.php was not found. Please migrate your config by running bin/update.sh", E_USER_WARNING);
}
}
// load host-specific configuration
$this->load_host_config();
// set skin (with fallback to old 'skin_path' property)
if (empty($this->prop['skin'])) {
if (!empty($this->prop['skin_path'])) {
$this->prop['skin'] = str_replace('skins/', '', unslashify($this->prop['skin_path']));
}
else {
$this->prop['skin'] = self::DEFAULT_SKIN;
}
}
if ($this->prop['skin'] == 'default') {
$this->prop['skin'] = self::DEFAULT_SKIN;
}
$this->system_skin = $this->prop['skin'];
// fix paths
foreach (array('log_dir' => 'logs', 'temp_dir' => 'temp') as $key => $dir) {
foreach (array($this->prop[$key], '../' . $this->prop[$key], RCUBE_INSTALL_PATH . $dir) as $path) {
if ($path && ($realpath = realpath(unslashify($path)))) {
$this->prop[$key] = $realpath;
break;
}
}
}
// fix default imap folders encoding
foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder) {
$this->prop[$folder] = rcube_charset::convert($this->prop[$folder], RCUBE_CHARSET, 'UTF7-IMAP');
}
// set PHP error logging according to config
$error_log = $this->prop['log_driver'] ?: 'file';
if ($error_log == 'file') {
$error_log = $this->prop['log_dir'] . '/errors';
$error_log .= isset($this->prop['log_file_ext']) ? $this->prop['log_file_ext'] : '.log';
}
if ($error_log && $error_log != 'stdout') {
ini_set('error_log', $error_log);
}
+ // set default screen layouts
+ $this->prop['supported_layouts'] = array('widescreen', 'desktop', 'list');
+
// remove deprecated properties
unset($this->prop['dst_active']);
}
/**
* Load a host-specific config file if configured
* This will merge the host specific configuration with the given one
*/
private function load_host_config()
{
if (empty($this->prop['include_host_config'])) {
return;
}
foreach (array('HTTP_HOST', 'SERVER_NAME', 'SERVER_ADDR') as $key) {
$fname = null;
$name = $_SERVER[$key];
if (!$name) {
continue;
}
if (is_array($this->prop['include_host_config'])) {
$fname = $this->prop['include_host_config'][$name];
}
else {
$fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $name) . '.inc.php';
}
if ($fname && $this->load_from_file($fname)) {
return;
}
}
}
/**
* Read configuration from a file
* and merge with the already stored config values
*
* @param string $file Name of the config file to be loaded
*
* @return booelan True on success, false on failure
*/
public function load_from_file($file)
{
$success = false;
foreach ($this->resolve_paths($file) as $fpath) {
if ($fpath && is_file($fpath) && is_readable($fpath)) {
// use output buffering, we don't need any output here
ob_start();
include($fpath);
ob_end_clean();
if (is_array($config)) {
$this->merge($config);
$success = true;
}
// deprecated name of config variable
if (is_array($rcmail_config)) {
$this->merge($rcmail_config);
$success = true;
}
}
}
return $success;
}
/**
* Helper method to resolve absolute paths to the given config file.
* This also takes the 'env' property into account.
*
* @param string $file Filename or absolute file path
* @param boolean $use_env Return -$env file path if exists
*
* @return array List of candidates in config dir path(s)
*/
public function resolve_paths($file, $use_env = true)
{
$files = array();
$abs_path = rcube_utils::is_absolute_path($file);
foreach ($this->paths as $basepath) {
$realpath = $abs_path ? $file : realpath($basepath . '/' . $file);
// check if <file>-<env>.inc.php exists
if ($use_env && !empty($this->env)) {
$envfile = preg_replace('/\.(inc.php)$/', '-' . $this->env . '.\\1', $file);
$envfile = $abs_path ? $envfile : realpath($basepath . '/' . $envfile);
if (is_file($envfile)) {
$realpath = $envfile;
}
}
if ($realpath) {
$files[] = $realpath;
// no need to continue the loop if an absolute file path is given
if ($abs_path) {
break;
}
}
}
return $files;
}
/**
* Getter for a specific config parameter
*
* @param string $name Parameter name
* @param mixed $def Default value if not set
*
* @return mixed The requested config value
*/
public function get($name, $def = null)
{
if (isset($this->prop[$name])) {
$result = $this->prop[$name];
}
else {
$result = $def;
}
$result = $this->getenv_default('ROUNDCUBE_' . strtoupper($name), $result);
$rcube = rcube::get_instance();
if ($name == 'timezone') {
if (empty($result) || $result == 'auto') {
$result = $this->client_timezone();
}
}
else if ($name == 'client_mimetypes') {
if (!$result && !$def) {
$result = 'text/plain,text/html'
. ',image/jpeg,image/gif,image/png,image/bmp,image/tiff,image/webp'
. ',application/x-javascript,application/pdf,application/x-shockwave-flash';
}
if ($result && is_string($result)) {
$result = explode(',', $result);
}
}
+ else if ($name == 'layout') {
+ if (!in_array($result, $this->prop['supported_layouts'])) {
+ $result = $this->prop['supported_layouts'][0];
+ }
+ }
$plugin = $rcube->plugins->exec_hook('config_get', array(
'name' => $name, 'default' => $def, 'result' => $result));
return $plugin['result'];
}
/**
* Setter for a config parameter
*
* @param string $name Parameter name
* @param mixed $value Parameter value
* @param bool $immutable Make the value immutable
*/
public function set($name, $value, $immutable = false)
{
$this->prop[$name] = $value;
if ($immutable) {
$this->immutable[$name] = $value;
}
}
/**
* Override config options with the given values (eg. user prefs)
*
* @param array $prefs Hash array with config props to merge over
*/
public function merge($prefs)
{
$prefs = $this->fix_legacy_props($prefs);
$this->prop = array_merge($this->prop, $prefs, $this->userprefs, $this->immutable);
}
/**
* Merge the given prefs over the current config
* and make sure that they survive further merging.
*
* @param array $prefs Hash array with user prefs
*/
public function set_user_prefs($prefs)
{
$prefs = $this->fix_legacy_props($prefs);
// Honor the dont_override setting for any existing user preferences
$dont_override = $this->get('dont_override');
if (is_array($dont_override) && !empty($dont_override)) {
foreach ($dont_override as $key) {
unset($prefs[$key]);
}
}
if ($prefs['skin'] == 'default') {
$prefs['skin'] = $this->system_skin;
}
$skins_allowed = $this->get('skins_allowed');
if (!empty($prefs['skin']) && !empty($skins_allowed) && !in_array($prefs['skin'], (array) $skins_allowed)) {
unset($prefs['skin']);
}
$this->userprefs = $prefs;
$this->prop = array_merge($this->prop, $prefs);
}
/**
* Getter for all config options
*
* @return array Hash array containing all config properties
*/
public function all()
{
$props = $this->prop;
foreach ($props as $prop_name => $prop_value) {
$props[$prop_name] = $this->getenv_default('ROUNDCUBE_' . strtoupper($prop_name), $prop_value);
}
$rcube = rcube::get_instance();
$plugin = $rcube->plugins->exec_hook('config_get', array(
'name' => '*', 'result' => $props));
return $plugin['result'];
}
/**
* Some options set as immutable that are also listed
* in dont_override should not be stored permanently
* in user preferences. Here's the list of these
*
* @return array List of transient options
*/
public function transient_options()
{
return array_intersect(array_keys($this->immutable), (array) $this->get('dont_override'));
}
/**
* Special getter for user's timezone offset including DST
*
* @return float Timezone offset (in hours)
* @deprecated
*/
public function get_timezone()
{
if ($tz = $this->get('timezone')) {
try {
$tz = new DateTimeZone($tz);
return $tz->getOffset(new DateTime('now')) / 3600;
}
catch (Exception $e) {
}
}
return 0;
}
/**
* Return requested DES crypto key.
*
* @param string $key Crypto key name
*
* @return string Crypto key
*/
public function get_crypto_key($key)
{
// Bomb out if the requested key does not exist
if (!array_key_exists($key, $this->prop) || empty($this->prop[$key])) {
rcube::raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Request for unconfigured crypto key \"$key\""
), true, true);
}
return $this->prop[$key];
}
/**
* Return configured crypto method.
*
* @return string Crypto method
*/
public function get_crypto_method()
{
return $this->get('cipher_method') ?: 'DES-EDE3-CBC';
}
/**
* Try to autodetect operating system and find the correct line endings
*
* @return string The appropriate mail header delimiter
* @deprecated Since 1.3 we don't use mail()
*/
public function header_delimiter()
{
// use the configured delimiter for headers
if (!empty($this->prop['mail_header_delimiter'])) {
$delim = $this->prop['mail_header_delimiter'];
if ($delim == "\n" || $delim == "\r\n") {
return $delim;
}
else {
rcube::raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid mail_header_delimiter setting"
), true, false);
}
}
$php_os = strtolower(substr(PHP_OS, 0, 3));
if ($php_os == 'win')
return "\r\n";
if ($php_os == 'mac')
return "\r\n";
return "\n";
}
/**
* Returns list of configured PGP key servers
*
* @return array|null List of keyservers' URLs
*/
public function keyservers()
{
$list = (array) $this->prop['keyservers'];
foreach ($list as $idx => $host) {
if (!preg_match('|^[a-z]+://|', $host)) {
$host = "https://$host";
}
$list[$idx] = slashify($host);
}
return !empty($list) ? $list : null;
}
/**
* Return the mail domain configured for the given host
*
* @param string $host IMAP host
* @param boolean $encode If true, domain name will be converted to IDN ASCII
*
* @return string Resolved SMTP host
*/
public function mail_domain($host, $encode=true)
{
$domain = $host;
if (is_array($this->prop['mail_domain'])) {
if (isset($this->prop['mail_domain'][$host])) {
$domain = $this->prop['mail_domain'][$host];
}
}
else if (!empty($this->prop['mail_domain'])) {
$domain = rcube_utils::parse_host($this->prop['mail_domain']);
}
if ($encode) {
$domain = rcube_utils::idn_to_ascii($domain);
}
return $domain;
}
/**
* Getter for error state
*
* @return mixed Error message on error, False if no errors
*/
public function get_error()
{
return empty($this->errors) ? false : implode("\n", $this->errors);
}
/**
* Internal getter for client's (browser) timezone identifier
*/
private function client_timezone()
{
if ($this->client_tz) {
return $this->client_tz;
}
// @TODO: remove this legacy timezone handling in the future
$props = $this->fix_legacy_props(array('timezone' => $_SESSION['timezone']));
if (!empty($props['timezone'])) {
// Prevent from using deprecated timezone names
$props['timezone'] = $this->resolve_timezone_alias($props['timezone']);
try {
$tz = new DateTimeZone($props['timezone']);
return $this->client_tz = $tz->getName();
}
catch (Exception $e) { /* gracefully ignore */ }
}
// fallback to server's timezone
return date_default_timezone_get();
}
/**
* Convert legacy options into new ones
*
* @param array $props Hash array with config props
*
* @return array Converted config props
*/
private function fix_legacy_props($props)
{
foreach ($this->legacy_props as $new => $old) {
if (isset($props[$old])) {
if (!isset($props[$new])) {
$props[$new] = $props[$old];
}
unset($props[$old]);
}
}
// convert deprecated numeric timezone value
if (isset($props['timezone']) && is_numeric($props['timezone'])) {
if ($tz = self::timezone_name_from_abbr($props['timezone'])) {
$props['timezone'] = $tz;
}
else {
unset($props['timezone']);
}
}
// translate old `preview_pane` settings to `layout`
if (isset($props['preview_pane']) && !isset($props['layout'])) {
$props['layout'] = $props['preview_pane'] ? 'desktop' : 'list';
unset($props['preview_pane']);
}
// translate old `display_version` settings to `display_product_info`
if (isset($props['display_version']) && !isset($props['display_product_info'])) {
$props['display_product_info'] = $props['display_version'] ? 2 : 1;
unset($props['display_version']);
}
return $props;
}
/**
* timezone_name_from_abbr() replacement. Converts timezone offset
* into timezone name abbreviation.
*
* @param float $offset Timezone offset (in hours)
*
* @return string Timezone abbreviation
*/
static public function timezone_name_from_abbr($offset)
{
// List of timezones here is not complete - https://bugs.php.net/bug.php?id=44780
if ($tz = timezone_name_from_abbr('', $offset * 3600, 0)) {
return $tz;
}
// try with more complete list (#1489261)
$timezones = array(
'-660' => "Pacific/Apia",
'-600' => "Pacific/Honolulu",
'-570' => "Pacific/Marquesas",
'-540' => "America/Anchorage",
'-480' => "America/Los_Angeles",
'-420' => "America/Denver",
'-360' => "America/Chicago",
'-300' => "America/New_York",
'-270' => "America/Caracas",
'-240' => "America/Halifax",
'-210' => "Canada/Newfoundland",
'-180' => "America/Sao_Paulo",
'-60' => "Atlantic/Azores",
'0' => "Europe/London",
'60' => "Europe/Paris",
'120' => "Europe/Helsinki",
'180' => "Europe/Moscow",
'210' => "Asia/Tehran",
'240' => "Asia/Dubai",
'270' => "Asia/Kabul",
'300' => "Asia/Karachi",
'330' => "Asia/Kolkata",
'345' => "Asia/Katmandu",
'360' => "Asia/Yekaterinburg",
'390' => "Asia/Rangoon",
'420' => "Asia/Krasnoyarsk",
'480' => "Asia/Shanghai",
'525' => "Australia/Eucla",
'540' => "Asia/Tokyo",
'570' => "Australia/Adelaide",
'600' => "Australia/Melbourne",
'630' => "Australia/Lord_Howe",
'660' => "Asia/Vladivostok",
'690' => "Pacific/Norfolk",
'720' => "Pacific/Auckland",
'765' => "Pacific/Chatham",
'780' => "Pacific/Enderbury",
'840' => "Pacific/Kiritimati",
);
return $timezones[(string) intval($offset * 60)];
}
/**
* Replace deprecated timezone name with a valid one.
*
* @param string $tzname Timezone name
*
* @return string Timezone name
*/
static public function resolve_timezone_alias($tzname)
{
// http://www.php.net/manual/en/timezones.others.php
// https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
$deprecated_timezones = array(
'Australia/ACT' => 'Australia/Sydney',
'Australia/LHI' => 'Australia/Lord_Howe',
'Australia/North' => 'Australia/Darwin',
'Australia/NSW' => 'Australia/Sydney',
'Australia/Queensland' => 'Australia/Brisbane',
'Australia/South' => 'Australia/Adelaide',
'Australia/Adelaide' => 'Australia/Hobart',
'Australia/Tasmania' => 'Australia/Hobart',
'Australia/Victoria' => 'Australia/Melbourne',
'Australia/West' => 'Australia/Perth',
'Brazil/Acre' => 'America/Rio_Branco',
'Brazil/DeNoronha' => 'America/Noronha',
'Brazil/East' => 'America/Sao_Paulo',
'Brazil/West' => 'America/Manaus',
'Canada/Atlantic' => 'America/Halifax',
'Canada/Central' => 'America/Winnipeg',
'Canada/Eastern' => 'America/Toronto',
'Canada/Mountain' => 'America/Edmonton',
'Canada/Newfoundland' => 'America/St_Johns',
'Canada/Pacific' => 'America/Vancouver',
'Canada/Saskatchewan' => 'America/Regina',
'Canada/Yukon' => 'America/Whitehorse',
'CET' => 'Europe/Berlin',
'Chile/Continental' => 'America/Santiago',
'Chile/EasterIsland' => 'Pacific/Easter',
'CST6CDT' => 'America/Chicago',
'Cuba' => ' America/Havana',
'EET' => 'Europe/Berlin',
'Egypt' => 'Africa/Cairo',
'Eire' => 'Europe/Dublin',
'EST' => 'America/New_York',
'EST5EDT' => 'America/New_York',
'Factory' => 'UTC', // ?
'GB' => 'Europe/London',
'GB-Eire' => 'Europe/London',
'GMT' => 'UTC',
'GMT+0' => 'UTC',
'GMT-0' => 'UTC',
'GMT0' => 'UTC',
'Greenwich' => 'UTC',
'Hongkong' => 'Asia/Hong_Kong',
'HST' => 'Pacific/Honolulu',
'Iceland' => 'Atlantic/Reykjavik',
'Iran' => 'Asia/Tehran',
'Israel' => 'Asia/Jerusalem',
'Jamaica' => 'America/Jamaica',
'Japan' => 'Asia/Tokyo',
'Kwajalein' => 'Pacific/Kwajalein',
'Libya' => 'Africa/Tripoli',
'MET' => 'Europe/Berlin',
'Mexico/BajaNorte' => 'America/Tijuana',
'Mexico/BajaSur' => 'America/Mazatlan',
'Mexico/General' => 'America/Mexico_City',
'MST' => 'America/Denver',
'MST7MDT' => 'America/Denver',
'Navajo' => 'America/Denver',
'NZ' => 'Pacific/Auckland',
'NZ-CHAT' => 'Pacific/Chatham',
'Poland' => 'Europe/Warsaw',
'Portugal' => 'Europe/Lisbon',
'PRC' => 'Asia/Shanghai',
'PST8PDT' => 'America/Los_Angeles',
'ROC' => 'Asia/Taipei',
'ROK' => 'Asia/Seoul',
'Singapore' => 'Asia/Singapore',
'Turkey' => 'Europe/Istanbul',
'UCT' => 'UTC',
'Universal' => 'UTC',
'US/Alaska' => 'America/Anchorage',
'US/Aleutian' => 'America/Adak',
'US/Arizona' => 'America/Phoenix',
'US/Central' => 'America/Chicago',
'US/East-Indiana' => 'America/Indiana/Indianapolis',
'US/Eastern' => 'America/New_York',
'US/Hawaii' => 'Pacific/Honolulu',
'US/Indiana-Starke' => 'America/Indiana/Knox',
'US/Michigan' => 'America/Detroit',
'US/Mountain' => 'America/Denver',
'US/Pacific' => 'America/Los_Angeles',
'US/Pacific-New' => 'America/Los_Angeles',
'US/Samoa' => 'Pacific/Pago_Pago',
'W-SU' => 'Europe/Moscow',
'WET' => 'Europe/Berlin',
'Z' => 'UTC',
'Zulu' => 'UTC',
// Some of these Etc/X zones are not deprecated, but still problematic
'Etc/GMT' => 'UTC',
'Etc/GMT+0' => 'UTC',
'Etc/GMT+1' => 'Atlantic/Azores',
'Etc/GMT+10' => 'Pacific/Honolulu',
'Etc/GMT+11' => 'Pacific/Midway',
'Etc/GMT+12' => 'Pacific/Auckland',
'Etc/GMT+2' => 'America/Noronha',
'Etc/GMT+3' => 'America/Argentina/Buenos_Aires',
'Etc/GMT+4' => 'America/Manaus',
'Etc/GMT+5' => 'America/New_York',
'Etc/GMT+6' => 'America/Chicago',
'Etc/GMT+7' => 'America/Denver',
'Etc/GMT+8' => 'America/Los_Angeles',
'Etc/GMT+9' => 'America/Anchorage',
'Etc/GMT-0' => 'UTC',
'Etc/GMT-1' => 'Europe/Berlin',
'Etc/GMT-10' => 'Australia/Sydney',
'Etc/GMT-11' => 'Pacific/Norfolk',
'Etc/GMT-12' => 'Pacific/Auckland',
'Etc/GMT-13' => 'Pacific/Apia',
'Etc/GMT-14' => 'Pacific/Kiritimati',
'Etc/GMT-2' => 'Africa/Cairo',
'Etc/GMT-3' => 'Europe/Moscow',
'Etc/GMT-4' => 'Europe/Samara',
'Etc/GMT-5' => 'Asia/Yekaterinburg',
'Etc/GMT-6' => 'Asia/Almaty',
'Etc/GMT-7' => 'Asia/Bangkok',
'Etc/GMT-8' => 'Asia/Hong_Kong',
'Etc/GMT-9' => 'Asia/Tokyo',
'Etc/GMT0' => 'UTC',
'Etc/Greenwich' => 'UTC',
'Etc/UCT' => 'UTC',
'Etc/Universal' => 'UTC',
'Etc/UTC' => 'UTC',
'Etc/Zulu' => 'UTC',
);
return $deprecated_timezones[$tzname] ?: $tzname;
}
}
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index 5008cae4e..eb82d3c85 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -1,1489 +1,1496 @@
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Provide functionality for user's settings & preferences |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
if (!$OUTPUT->ajax_call) {
$OUTPUT->set_pagetitle($RCMAIL->gettext('preferences'));
}
// register UI objects
$OUTPUT->add_handlers(array(
'settingstabs' => 'rcmail_settings_tabs',
'sectionslist' => 'rcmail_sections_list',
'identitieslist' => 'rcmail_identities_list',
));
// register action aliases
$RCMAIL->register_action_map(array(
'folders' => 'folders.inc',
'rename-folder' => 'folders.inc',
'delete-folder' => 'folders.inc',
'subscribe' => 'folders.inc',
'unsubscribe' => 'folders.inc',
'purge' => 'folders.inc',
'folder-size' => 'folders.inc',
'add-folder' => 'edit_folder.inc',
'add-identity' => 'edit_identity.inc',
'add-response' => 'edit_response.inc',
'save-response' => 'edit_response.inc',
'delete-response' => 'responses.inc',
'delete-identity' => 'identities.inc',
'upload-display' => 'upload.inc',
));
function rcmail_sections_list($attrib)
{
global $RCMAIL;
// add id to message list table if not specified
if (!strlen($attrib['id'])) {
$attrib['id'] = 'rcmsectionslist';
}
list($list, $cols) = rcmail_user_prefs();
// create XHTML table
$out = $RCMAIL->table_output($attrib, $list, $cols, 'id');
// set client env
$RCMAIL->output->add_gui_object('sectionslist', $attrib['id']);
$RCMAIL->output->include_script('list.js');
return $out;
}
function rcmail_identities_list($attrib)
{
global $OUTPUT, $RCMAIL;
// add id to message list table if not specified
if (!strlen($attrib['id'])) {
$attrib['id'] = 'rcmIdentitiesList';
}
// get identities list and define 'mail' column
$list = $RCMAIL->user->list_emails();
foreach ($list as $idx => $row) {
$list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_utils::idn_to_utf8($row['email']) . '>');
}
// get all identites from DB and define list of cols to be displayed
$plugin = $RCMAIL->plugins->exec_hook('identities_list', array(
'list' => $list,
'cols' => array('mail')
));
// @TODO: use <UL> instead of <TABLE> for identities list
// create XHTML table
$out = $RCMAIL->table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id');
// set client env
$OUTPUT->add_gui_object('identitieslist', $attrib['id']);
return $out;
}
// similar function as in /steps/addressbook/edit.inc
function get_form_tags($attrib, $action, $id = null, $hidden = null)
{
global $EDIT_FORM, $RCMAIL;
$form_start = $form_end = '';
if (empty($EDIT_FORM)) {
$request_key = $action . (isset($id) ? '.'.$id : '');
$form_start = $RCMAIL->output->request_form(array(
'name' => 'form',
'method' => 'post',
'task' => $RCMAIL->task,
'action' => $action,
'request' => $request_key,
'noclose' => true
) + $attrib);
if (is_array($hidden)) {
$hiddenfields = new html_hiddenfield($hidden);
$form_start .= $hiddenfields->show();
}
$form_end = !strlen($attrib['form']) ? '</form>' : '';
$EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form';
$RCMAIL->output->add_gui_object('editform', $EDIT_FORM);
}
return array($form_start, $form_end);
}
function rcmail_user_prefs($current = null)
{
global $RCMAIL;
$sections['general'] = array('id' => 'general', 'section' => $RCMAIL->gettext('uisettings'));
$sections['mailbox'] = array('id' => 'mailbox', 'section' => $RCMAIL->gettext('mailboxview'));
$sections['mailview'] = array('id' => 'mailview','section' => $RCMAIL->gettext('messagesdisplaying'));
$sections['compose'] = array('id' => 'compose', 'section' => $RCMAIL->gettext('messagescomposition'));
$sections['addressbook'] = array('id' => 'addressbook','section' => $RCMAIL->gettext('contacts'));
$sections['folders'] = array('id' => 'folders', 'section' => $RCMAIL->gettext('specialfolders'));
$sections['server'] = array('id' => 'server', 'section' => $RCMAIL->gettext('serversettings'));
// hook + define list cols
$plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list',
array('list' => $sections, 'cols' => array('section')));
$sections = $plugin['list'];
$config = $RCMAIL->config->all();
$no_override = array_flip((array)$RCMAIL->config->get('dont_override'));
foreach ($sections as $idx => $sect) {
$sections[$idx]['class'] = $sect['class'] ?: $idx;
if ($current && $sect['id'] != $current) {
continue;
}
$blocks = array();
switch ($sect['id']) {
// general
case 'general':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'skin' => array('name' => rcube::Q($RCMAIL->gettext('skin'))),
'browser' => array('name' => rcube::Q($RCMAIL->gettext('browseroptions'))),
'advanced'=> array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
// language selection
if (!isset($no_override['language'])) {
if (!$current) {
continue 2;
}
$a_lang = $RCMAIL->list_languages();
asort($a_lang);
$field_id = 'rcmfd_lang';
$select = new html_select(array('name' => '_language', 'id' => $field_id));
$select->add(array_values($a_lang), array_keys($a_lang));
$blocks['main']['options']['language'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('language'))),
'content' => $select->show($RCMAIL->user->language),
);
}
// timezone selection
if (!isset($no_override['timezone'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_timezone';
$select = new html_select(array('name' => '_timezone', 'id' => $field_id));
$select->add($RCMAIL->gettext('autodetect'), 'auto');
$zones = array();
foreach (DateTimeZone::listIdentifiers() as $i => $tzs) {
if ($data = rcmail_timezone_standard_time_data($tzs)) {
$zones[$data['key']] = array($tzs, $data['offset']);
}
}
ksort($zones);
foreach ($zones as $zone) {
list($tzs, $offset) = $zone;
$select->add('(GMT ' . $offset . ') ' . rcmail_timezone_label($tzs), $tzs);
}
$blocks['main']['options']['timezone'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('timezone'))),
'content' => $select->show((string)$config['timezone']),
);
}
// date/time formatting
if (!isset($no_override['time_format'])) {
if (!$current) {
continue 2;
}
$reftime = mktime(7,30,0);
$defaults = array('G:i', 'H:i', 'g:i a', 'h:i A');
$formats = (array)$RCMAIL->config->get('time_formats', $defaults);
$field_id = 'rcmfd_time_format';
$select = new html_select(array('name' => '_time_format', 'id' => $field_id));
foreach ($formats as $choice) {
$select->add(date($choice, $reftime), $choice);
}
$blocks['main']['options']['time_format'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('timeformat'))),
'content' => $select->show($RCMAIL->config->get('time_format')),
);
}
if (!isset($no_override['date_format'])) {
if (!$current) {
continue 2;
}
$refdate = mktime(12,30,0,7,24);
$defaults = array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y');
$formats = (array)$RCMAIL->config->get('date_formats', $defaults);
$field_id = 'rcmfd_date_format';
$select = new html_select(array('name' => '_date_format', 'id' => $field_id));
foreach ($formats as $choice) {
$select->add(date($choice, $refdate), $choice);
}
$blocks['main']['options']['date_format'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('dateformat'))),
'content' => $select->show($config['date_format']),
);
}
// Show checkbox for toggling 'pretty dates'
if (!isset($no_override['prettydate'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_prettydate';
$input = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['prettydate'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('prettydate'))),
'content' => $input->show($config['prettydate']?1:0),
);
}
// "display after delete" checkbox
if (!isset($no_override['display_next'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_displaynext';
$input = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['display_next'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('displaynext'))),
'content' => $input->show($config['display_next']?1:0),
);
}
if (!isset($no_override['refresh_interval'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_refresh_interval';
$select = new html_select(array('name' => '_refresh_interval', 'id' => $field_id));
$select->add($RCMAIL->gettext('never'), 0);
foreach (array(1, 3, 5, 10, 15, 30, 60) as $min) {
if (!$config['min_refresh_interval'] || $config['min_refresh_interval'] <= $min * 60) {
$label = $RCMAIL->gettext(array('name' => 'everynminutes', 'vars' => array('n' => $min)));
$select->add($label, $min);
}
}
$blocks['main']['options']['refresh_interval'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('refreshinterval'))),
'content' => $select->show($config['refresh_interval']/60),
);
}
// show drop-down for available skins
if (!isset($no_override['skin'])) {
if (!$current) {
continue 2;
}
$skins = rcmail_get_skins();
if (count($skins) > 1) {
$field_id = 'rcmfd_skin';
$input = new html_radiobutton(array('name'=>'_skin'));
foreach ($skins as $skin) {
$skinname = ucfirst($skin);
$author_link = $license_link = '';
$meta = @json_decode(@file_get_contents(INSTALL_PATH . "skins/$skin/meta.json"), true);
if (is_array($meta) && $meta['name']) {
$skinname = $meta['name'];
$author_link = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), rcube::Q($meta['author'])) : rcube::Q($meta['author']);
$license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank', 'tabindex' => '-1'), rcube::Q($meta['license'])) : rcube::Q($meta['license']);
}
$img = html::img(array(
'src' => $RCMAIL->output->asset_url("skins/$skin/thumbnail.png"),
'class' => 'skinthumbnail',
'alt' => $skin,
'width' => 64,
'height' => 64,
'onerror' => "this.src = rcmail.assets_path('program/resources/blank.gif'); this.onerror = null",
));
$skinnames[] = mb_strtolower($skinname);
$blocks['skin']['options'][$skin]['content'] = html::label(array('class' => 'skinselection'),
html::span('skinitem', $input->show($config['skin'], array('value' => $skin, 'id' => $field_id.$skin))) .
html::span('skinitem', $img) .
html::span('skinitem', html::span('skinname', rcube::Q($skinname)) . html::br() .
html::span('skinauthor', $author_link ? 'by ' . $author_link : '') . html::br() .
html::span('skinlicense', $license_link ? $RCMAIL->gettext('license').': ' . $license_link : ''))
);
}
array_multisort($blocks['skin']['options'], SORT_ASC, SORT_STRING, $skinnames);
}
}
// standard_windows option decides if new windows should be
// opened as popups or standard windows (which can be handled by browsers as tabs)
if (!isset($no_override['standard_windows'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_standard_windows';
$checkbox = new html_checkbox(array('name' => '_standard_windows', 'id' => $field_id, 'value' => 1));
$blocks['browser']['options']['standard_windows'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('standardwindows'))),
'content' => $checkbox->show($config['standard_windows']?1:0),
);
}
if ($current) {
$product_name = $RCMAIL->config->get('product_name', 'Roundcube Webmail');
$RCMAIL->output->add_script(sprintf("%s.check_protocol_handler('%s', '#mailtoprotohandler');",
rcmail_output::JS_OBJECT_NAME, rcube::JQ($product_name)), 'docready');
}
$blocks['browser']['options']['mailtoprotohandler'] = array(
'content' => html::a(array(
'href' => '#',
'id' => 'mailtoprotohandler'
),
rcube::Q($RCMAIL->gettext('mailtoprotohandler'))) .
html::span('mailtoprotohandler-status', ''),
);
break;
// Mailbox view (mail screen)
case 'mailbox':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'new_message' => array('name' => rcube::Q($RCMAIL->gettext('newmessage'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
- if (!isset($no_override['layout'])) {
+ if (!isset($no_override['layout']) && count($config['supported_layouts']) > 1) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_layout';
$select = new html_select(array('name' => '_layout', 'id' => $field_id));
- $select->add($RCMAIL->gettext('layoutwidescreendesc'), 'widescreen');
- $select->add($RCMAIL->gettext('layoutdesktopdesc'), 'desktop');
- $select->add($RCMAIL->gettext('layoutlistdesc'), 'list');
+ $layouts = array(
+ 'widescreen' => 'layoutwidescreendesc',
+ 'desktop' => 'layoutdesktopdesc',
+ 'list' => 'layoutlistdesc'
+ );
+
+ $available_layouts = array_intersect_key($layouts, array_flip($config['supported_layouts']));
+ foreach ($available_layouts as $val => $label) {
+ $select->add($RCMAIL->gettext($label), $val);
+ }
$blocks['main']['options']['layout'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('layout'))),
'content' => $select->show($config['layout'] ?: 'widescreen'),
);
}
// show config parameter for auto marking the previewed message as read
if (!isset($no_override['mail_read_time'])) {
if (!$current) {
continue 2;
}
// apply default if config option is not set at all
$config['mail_read_time'] = intval($RCMAIL->config->get('mail_read_time'));
$field_id = 'rcmfd_mail_read_time';
$select = new html_select(array('name' => '_mail_read_time', 'id' => $field_id));
$select->add($RCMAIL->gettext('never'), -1);
$select->add($RCMAIL->gettext('immediately'), 0);
foreach (array(5, 10, 20, 30) as $sec) {
$label = $RCMAIL->gettext(array('name' => 'afternseconds', 'vars' => array('n' => $sec)));
$select->add($label, $sec);
}
$blocks['main']['options']['mail_read_time'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('automarkread'))),
'content' => $select->show($config['mail_read_time']),
);
}
if (!isset($no_override['mdn_requests'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_mdn_requests';
$select = new html_select(array('name' => '_mdn_requests', 'id' => $field_id));
$select->add($RCMAIL->gettext('askuser'), 0);
$select->add($RCMAIL->gettext('autosend'), 1);
$select->add($RCMAIL->gettext('autosendknown'), 3);
$select->add($RCMAIL->gettext('autosendknownignore'), 4);
$select->add($RCMAIL->gettext('ignorerequest'), 2);
$blocks['main']['options']['mdn_requests'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('mdnrequests'))),
'content' => $select->show($config['mdn_requests']),
);
}
if (!isset($no_override['autoexpand_threads'])) {
if (!$current) {
continue 2;
}
$storage = $RCMAIL->get_storage();
$supported = $storage->get_capability('THREAD');
if ($supported) {
$field_id = 'rcmfd_autoexpand_threads';
$select = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id));
$select->add($RCMAIL->gettext('never'), 0);
$select->add($RCMAIL->gettext('do_expand'), 1);
$select->add($RCMAIL->gettext('expand_only_unread'), 2);
$blocks['main']['options']['autoexpand_threads'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('autoexpand_threads'))),
'content' => $select->show($config['autoexpand_threads']),
);
}
}
// show page size selection
if (!isset($no_override['mail_pagesize'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_mail_pagesize';
$input = new html_inputfield(array('name' => '_mail_pagesize', 'id' => $field_id, 'size' => 5));
$size = intval($config['mail_pagesize'] ?: $config['pagesize']);
$blocks['main']['options']['pagesize'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('pagesize'))),
'content' => $input->show($size ?: 50),
);
}
if (!isset($no_override['check_all_folders'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_check_all_folders';
$input = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1));
$blocks['new_message']['options']['check_all_folders'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('checkallfolders'))),
'content' => $input->show($config['check_all_folders']?1:0),
);
}
break;
// Message viewing
case 'mailview':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
// show checkbox to open message view in new window
if (!isset($no_override['message_extwin'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_message_extwin';
$input = new html_checkbox(array('name' => '_message_extwin', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['message_extwin'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('showinextwin'))),
'content' => $input->show($config['message_extwin']?1:0),
);
}
// show checkbox to show email instead of name
if (!isset($no_override['message_show_email'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_message_show_email';
$input = new html_checkbox(array('name' => '_message_show_email', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['message_show_email'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('showemail'))),
'content' => $input->show($config['message_show_email']?1:0),
);
}
// show checkbox for HTML/plaintext messages
if (!isset($no_override['prefer_html'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_htmlmsg';
$input = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1,
'onchange' => "$('#rcmfd_show_images').prop('disabled', !this.checked).val(0)"));
$blocks['main']['options']['prefer_html'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('preferhtml'))),
'content' => $input->show($config['prefer_html']?1:0),
);
}
if (!isset($no_override['default_charset'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_default_charset';
$blocks['advanced']['options']['default_charset'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('defaultcharset'))),
'content' => $RCMAIL->output->charset_selector(array(
'id' => $field_id, 'name' => '_default_charset', 'selected' => $config['default_charset']
)));
}
if (!isset($no_override['show_images'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_show_images';
$input = new html_select(array('name' => '_show_images', 'id' => $field_id,
'disabled' => !$config['prefer_html']));
$input->add($RCMAIL->gettext('never'), 0);
$input->add($RCMAIL->gettext('fromknownsenders'), 1);
$input->add($RCMAIL->gettext('always'), 2);
$blocks['main']['options']['show_images'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('allowremoteresources'))),
'content' => $input->show($config['prefer_html'] ? $config['show_images'] : 0),
);
}
if (!isset($no_override['inline_images'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_inline_images';
$input = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['inline_images'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('showinlineimages'))),
'content' => $input->show($config['inline_images']?1:0),
);
}
break;
// Mail composition
case 'compose':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'sig' => array('name' => rcube::Q($RCMAIL->gettext('signatureoptions'))),
'spellcheck' => array('name' => rcube::Q($RCMAIL->gettext('spellcheckoptions'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
// show checkbox to compose messages in a new window
if (!isset($no_override['compose_extwin'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfdcompose_extwin';
$input = new html_checkbox(array('name' => '_compose_extwin', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['compose_extwin'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('composeextwin'))),
'content' => $input->show($config['compose_extwin']?1:0),
);
}
if (!isset($no_override['htmleditor'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_htmleditor';
$select = new html_select(array('name' => '_htmleditor', 'id' => $field_id));
$select->add($RCMAIL->gettext('never'), 0);
$select->add($RCMAIL->gettext('htmlonreply'), 2);
$select->add($RCMAIL->gettext('htmlonreplyandforward'), 3);
$select->add($RCMAIL->gettext('always'), 1);
$select->add($RCMAIL->gettext('alwaysbutplain'), 4);
$blocks['main']['options']['htmleditor'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('htmleditor'))),
'content' => $select->show(intval($config['htmleditor'])),
);
}
if (!isset($no_override['draft_autosave'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_autosave';
$select = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox'])));
$select->add($RCMAIL->gettext('never'), 0);
foreach (array(1, 3, 5, 10) as $i => $min) {
$label = $RCMAIL->gettext(array('name' => 'everynminutes', 'vars' => array('n' => $min)));
$select->add($label, $min*60);
}
$blocks['main']['options']['draft_autosave'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('autosavedraft'))),
'content' => $select->show($config['draft_autosave']),
);
}
if (!isset($no_override['mime_param_folding'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_param_folding';
$select = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id));
$select->add($RCMAIL->gettext('2231folding'), 0);
$select->add($RCMAIL->gettext('miscfolding'), 1);
$select->add($RCMAIL->gettext('2047folding'), 2);
$blocks['advanced']['options']['mime_param_folding'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('mimeparamfolding'))),
'content' => $select->show($config['mime_param_folding']),
);
}
if (!isset($no_override['force_7bit'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_force_7bit';
$input = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1));
$blocks['advanced']['options']['force_7bit'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('force7bit'))),
'content' => $input->show($config['force_7bit']?1:0),
);
}
if (!isset($no_override['mdn_default'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_mdn_default';
$input = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['mdn_default'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('reqmdn'))),
'content' => $input->show($config['mdn_default']?1:0),
);
}
if (!isset($no_override['dsn_default'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_dsn_default';
$input = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['dsn_default'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('reqdsn'))),
'content' => $input->show($config['dsn_default']?1:0),
);
}
if (!isset($no_override['reply_same_folder'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_reply_same_folder';
$input = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['reply_same_folder'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('replysamefolder'))),
'content' => $input->show($config['reply_same_folder']?1:0),
);
}
if (!isset($no_override['reply_mode'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_reply_mode';
$select = new html_select(array('name' => '_reply_mode', 'id' => $field_id));
$select->add($RCMAIL->gettext('replyempty'), -1);
$select->add($RCMAIL->gettext('replybottomposting'), 0);
$select->add($RCMAIL->gettext('replytopposting'), 1);
$select->add($RCMAIL->gettext('replytoppostingnoindent'), 2);
$blocks['main']['options']['reply_mode'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('whenreplying'))),
'content' => $select->show(intval($config['reply_mode'])),
);
}
if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_spellcheck_before_send';
$input = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
$blocks['spellcheck']['options']['spellcheck_before_send'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('spellcheckbeforesend'))),
'content' => $input->show($config['spellcheck_before_send']?1:0),
);
}
if ($config['enable_spellcheck']) {
if (!$current) {
continue 2;
}
foreach (array('syms', 'nums', 'caps') as $key) {
$key = 'spellcheck_ignore_'.$key;
if (!isset($no_override[$key])) {
$input = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1));
$blocks['spellcheck']['options'][$key] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext(str_replace('_', '', $key)))),
'content' => $input->show($config[$key]?1:0),
);
}
}
}
if (!isset($no_override['show_sig'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_show_sig';
$select = new html_select(array('name' => '_show_sig', 'id' => $field_id));
$select->add($RCMAIL->gettext('never'), 0);
$select->add($RCMAIL->gettext('always'), 1);
$select->add($RCMAIL->gettext('newmessageonly'), 2);
$select->add($RCMAIL->gettext('replyandforwardonly'), 3);
$blocks['sig']['options']['show_sig'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('autoaddsignature'))),
'content' => $select->show($RCMAIL->config->get('show_sig', 1)),
);
}
if (!isset($no_override['sig_below'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_sig_below';
$input = new html_checkbox(array('name' => '_sig_below', 'id' => $field_id, 'value' => 1));
$blocks['sig']['options']['sig_below'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('sigbelow'))),
'content' => $input->show($RCMAIL->config->get('sig_below') ? 1 : 0),
);
}
if (!isset($no_override['strip_existing_sig'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_strip_existing_sig';
$input = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1));
$blocks['sig']['options']['strip_existing_sig'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('replyremovesignature'))),
'content' => $input->show($config['strip_existing_sig']?1:0),
);
}
if (!isset($no_override['sig_separator'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_sig_separator';
$input = new html_checkbox(array('name' => '_sig_separator', 'id' => $field_id, 'value' => 1));
$blocks['sig']['options']['sig_separator'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('sigseparator'))),
'content' => $input->show($RCMAIL->config->get('sig_separator') ? 1 : 0),
);
}
if (!isset($no_override['forward_attachment'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_forward_attachment';
$select = new html_select(array('name' => '_forward_attachment', 'id' => $field_id));
$select->add($RCMAIL->gettext('inline'), 0);
$select->add($RCMAIL->gettext('asattachment'), 1);
$blocks['main']['options']['forward_attachment'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('forwardmode'))),
'content' => $select->show(intval($config['forward_attachment'])),
);
}
if (!isset($no_override['default_font']) || !isset($no_override['default_font_size'])) {
if (!$current) {
continue 2;
}
// Default font size
$field_id = 'rcmfd_default_font_size';
$select_default_font_size = new html_select(array('name' => '_default_font_size', 'id' => $field_id));
$fontsizes = array('', '8pt', '9pt', '10pt', '11pt', '12pt', '14pt', '18pt', '24pt', '36pt');
foreach ($fontsizes as $size) {
$select_default_font_size->add($size, $size);
}
// Default font
$field_id = 'rcmfd_default_font';
$select_default_font = new html_select(array('name' => '_default_font', 'id' => $field_id));
$select_default_font->add('', '');
$fonts = rcmail::font_defs();
foreach (array_keys($fonts) as $fname) {
$select_default_font->add($fname, $fname);
}
$blocks['main']['options']['default_font'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('defaultfont'))),
'content' => html::div('input-group', $select_default_font->show($RCMAIL->config->get('default_font', 1)) .
$select_default_font_size->show($RCMAIL->config->get('default_font_size', 1)))
);
}
if (!isset($no_override['reply_all_mode'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_reply_all_mode';
$select = new html_select(array('name' => '_reply_all_mode', 'id' => $field_id));
$select->add($RCMAIL->gettext('replyalldefault'), 0);
$select->add($RCMAIL->gettext('replyalllist'), 1);
$blocks['main']['options']['reply_all_mode'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('replyallmode'))),
'content' => $select->show(intval($config['reply_all_mode'])),
);
}
if (!isset($no_override['compose_save_localstorage'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_compose_save_localstorage';
$input = new html_checkbox(array('name' => '_compose_save_localstorage', 'id' => $field_id, 'value' => 1));
$blocks['advanced']['options']['compose_save_localstorage'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('savelocalstorage'))),
'content' => $input->show($config['compose_save_localstorage']?1:0),
);
}
break;
// Addressbook config
case 'addressbook':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
if (!isset($no_override['default_addressbook'])
&& (!$current || ($books = $RCMAIL->get_address_sources(true, true)))
) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_default_addressbook';
$select = new html_select(array('name' => '_default_addressbook', 'id' => $field_id));
foreach ($books as $book) {
$select->add(html_entity_decode($book['name'], ENT_COMPAT, 'UTF-8'), $book['id']);
}
$blocks['main']['options']['default_addressbook'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('defaultabook'))),
'content' => $select->show($config['default_addressbook']),
);
}
// show addressbook listing mode selection
if (!isset($no_override['addressbook_name_listing'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_addressbook_name_listing';
$select = new html_select(array('name' => '_addressbook_name_listing', 'id' => $field_id));
$select->add($RCMAIL->gettext('name'), 0);
$select->add($RCMAIL->gettext('firstname') . ' ' . $RCMAIL->gettext('surname'), 1);
$select->add($RCMAIL->gettext('surname') . ' ' . $RCMAIL->gettext('firstname'), 2);
$select->add($RCMAIL->gettext('surname') . ', ' . $RCMAIL->gettext('firstname'), 3);
$blocks['main']['options']['list_name_listing'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('listnamedisplay'))),
'content' => $select->show($config['addressbook_name_listing']),
);
}
// show addressbook sort column
if (!isset($no_override['addressbook_sort_col'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_addressbook_sort_col';
$select = new html_select(array('name' => '_addressbook_sort_col', 'id' => $field_id));
$select->add($RCMAIL->gettext('name'), 'name');
$select->add($RCMAIL->gettext('firstname'), 'firstname');
$select->add($RCMAIL->gettext('surname'), 'surname');
$blocks['main']['options']['sort_col'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('listsorting'))),
'content' => $select->show($config['addressbook_sort_col']),
);
}
// show addressbook page size selection
if (!isset($no_override['addressbook_pagesize'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_addressbook_pagesize';
$input = new html_inputfield(array('name' => '_addressbook_pagesize', 'id' => $field_id, 'size' => 5));
$size = intval($config['addressbook_pagesize'] ?: $config['pagesize']);
$blocks['main']['options']['pagesize'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('pagesize'))),
'content' => $input->show($size ?: 50),
);
}
if (!isset($no_override['autocomplete_single'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_autocomplete_single';
$checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['autocomplete_single'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('autocompletesingle'))),
'content' => $checkbox->show($config['autocomplete_single']?1:0),
);
}
break;
// Special IMAP folders
case 'folders':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
if (!isset($no_override['show_real_foldernames'])) {
if (!$current) {
continue 2;
}
$field_id = 'show_real_foldernames';
$input = new html_checkbox(array('name' => '_show_real_foldernames', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['show_real_foldernames'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('show_real_foldernames'))),
'content' => $input->show($config['show_real_foldernames']?1:0),
);
}
// Configure special folders
$set = array('drafts_mbox', 'sent_mbox', 'junk_mbox', 'trash_mbox');
if ($current && count(array_intersect($no_override, $set)) < 4) {
$select = $RCMAIL->folder_selector(array(
'noselection' => '---',
'realnames' => true,
'maxlength' => 30,
'folder_filter' => 'mail',
'folder_rights' => 'w',
));
// #1486114, #1488279, #1489219
$onchange = "if ($(this).val() == 'INBOX') $(this).val('')";
}
if (!isset($no_override['drafts_mbox'])) {
if (!$current) {
continue 2;
}
$attrs = array('id' => '_drafts_mbox', 'name' => '_drafts_mbox', 'onchange' => $onchange);
$blocks['main']['options']['drafts_mbox'] = array(
'title' => html::label($attrs['id'], rcube::Q($RCMAIL->gettext('drafts'))),
'content' => $select->show($config['drafts_mbox'], $attrs),
);
}
if (!isset($no_override['sent_mbox'])) {
if (!$current) {
continue 2;
}
$attrs = array('id' => '_sent_mbox', 'name' => '_sent_mbox', 'onchange' => '');
$blocks['main']['options']['sent_mbox'] = array(
'title' => html::label($attrs['id'], rcube::Q($RCMAIL->gettext('sent'))),
'content' => $select->show($config['sent_mbox'], $attrs),
);
}
if (!isset($no_override['junk_mbox'])) {
if (!$current) {
continue 2;
}
$attrs = array('id' => '_junk_mbox', 'name' => '_junk_mbox', 'onchange' => $onchange);
$blocks['main']['options']['junk_mbox'] = array(
'title' => html::label($attrs['id'], rcube::Q($RCMAIL->gettext('junk'))),
'content' => $select->show($config['junk_mbox'], $attrs),
);
}
if (!isset($no_override['trash_mbox'])) {
if (!$current) {
continue 2;
}
$attrs = array('id' => '_trash_mbox', 'name' => '_trash_mbox', 'onchange' => $onchange);
$blocks['main']['options']['trash_mbox'] = array(
'title' => html::label($attrs['id'], rcube::Q($RCMAIL->gettext('trash'))),
'content' => $select->show($config['trash_mbox'], $attrs),
);
}
break;
// Server settings
case 'server':
$blocks = array(
'main' => array('name' => rcube::Q($RCMAIL->gettext('mainoptions'))),
'maintenance' => array('name' => rcube::Q($RCMAIL->gettext('maintenance'))),
'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))),
);
if (!isset($no_override['read_when_deleted'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_read_deleted';
$input = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['read_when_deleted'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('readwhendeleted'))),
'content' => $input->show($config['read_when_deleted']?1:0),
);
}
if (!isset($no_override['flag_for_deletion'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_flag_for_deletion';
$input = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['flag_for_deletion'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('flagfordeletion'))),
'content' => $input->show($config['flag_for_deletion']?1:0),
);
}
// don't show deleted messages
if (!isset($no_override['skip_deleted'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_skip_deleted';
$input = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['skip_deleted'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('skipdeleted'))),
'content' => $input->show($config['skip_deleted']?1:0),
);
}
if (!isset($no_override['delete_junk'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_delete_junk';
$input = new html_checkbox(array('name' => '_delete_junk', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['delete_junk'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('deletejunk'))),
'content' => $input->show($config['delete_junk']?1:0),
);
}
// Trash purging on logout
if (!isset($no_override['logout_purge'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_logout_purge';
$input = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
$blocks['maintenance']['options']['logout_purge'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('logoutclear'))),
'content' => $input->show($config['logout_purge']?1:0),
);
}
// INBOX compacting on logout
if (!isset($no_override['logout_expunge'])) {
if (!$current) {
continue 2;
}
$field_id = 'rcmfd_logout_expunge';
$input = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
$blocks['maintenance']['options']['logout_expunge'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('logoutcompact'))),
'content' => $input->show($config['logout_expunge']?1:0),
);
}
}
$found = false;
$data = $RCMAIL->plugins->exec_hook('preferences_list',
array('section' => $sect['id'], 'blocks' => $blocks, 'current' => $current));
$advanced_prefs = (array) $RCMAIL->config->get('advanced_prefs');
// create output
foreach ($data['blocks'] as $key => $block) {
if (!empty($block['content']) || !empty($block['options'])) {
$found = true;
}
// move some options to the 'advanced' block as configured by admin
if ($key != 'advanced') {
foreach ($advanced_prefs as $opt) {
if ($block['options'][$opt]) {
$data['blocks']['advanced']['options'][$opt] = $block['options'][$opt];
unset($data['blocks'][$key]['options'][$opt]);
}
}
}
}
// move 'advanced' block to the end of the list
if (!empty($data['blocks']['advanced'])) {
$adv = $data['blocks']['advanced'];
unset($data['blocks']['advanced']);
$data['blocks']['advanced'] = $adv;
}
if (!$found)
unset($sections[$idx]);
else
$sections[$idx]['blocks'] = $data['blocks'];
// allow plugins to add a header to each section
$data = $RCMAIL->plugins->exec_hook('preferences_section_header',
array('section' => $sect['id'], 'header' => '', 'current' => $current));
if (!empty($data['header'])) {
$sections[$idx]['header'] = $data['header'];
}
}
return array($sections, $plugin['cols']);
}
function rcmail_get_skins()
{
global $RCMAIL;
$path = RCUBE_INSTALL_PATH . 'skins';
$skins = array();
$dir = opendir($path);
$limit = (array) $RCMAIL->config->get('skins_allowed');
if (!$dir) {
return false;
}
while (($file = readdir($dir)) !== false) {
$filename = $path . '/' . $file;
if ($file[0] != '.'
&& (empty($limit) || in_array($file, $limit))
&& is_dir($filename) && is_readable($filename)
) {
$skins[] = $file;
}
}
closedir($dir);
return $skins;
}
function rcmail_folder_options($mailbox)
{
global $RCMAIL;
$options = $RCMAIL->get_storage()->folder_info($mailbox);
$options['protected'] = $options['is_root']
|| strtoupper($mailbox) === 'INBOX'
|| ($options['special'] && $RCMAIL->config->get('protect_default_folders'));
return $options;
}
/**
* Updates (or creates) folder row in the subscriptions table
*
* @param string $name Folder name
* @param string $oldname Old folder name (for update)
* @param bool $subscribe Checks subscription checkbox
* @param string $class CSS class name for folder row
*/
function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class_name=null)
{
global $RCMAIL;
$storage = $RCMAIL->get_storage();
$delimiter = $storage->get_hierarchy_delimiter();
$options = rcmail_folder_options($name);
$name_utf8 = rcube_charset::convert($name, 'UTF7-IMAP');
$foldersplit = explode($delimiter, $storage->mod_folder($name));
$level = count($foldersplit) - 1;
$display_name = $options['protected'] ? $RCMAIL->localize_foldername($name) : rcube_charset::convert($foldersplit[$level], 'UTF7-IMAP');
$class_name = trim($class_name . ' mailbox');
if ($oldname === null) {
$RCMAIL->output->command('add_folder_row', $name, $name_utf8, $display_name,
$options['protected'] || $options['noselect'], $subscribe, $class_name);
}
else {
$RCMAIL->output->command('replace_folder_row', $oldname, $name, $name_utf8, $display_name,
$options['protected'] || $options['noselect'], $class_name);
}
}
/**
* Render the list of settings sections (AKA tabs)
*/
function rcmail_settings_tabs($attrib)
{
global $RCMAIL, $OUTPUT;
// add default attributes
$attrib += array('tagname' => 'span', 'idprefix' => 'settingstab', 'selclass' => 'selected');
$default_actions = array(
array('action' => 'preferences', 'type' => 'link', 'label' => 'preferences', 'title' => 'editpreferences'),
array('action' => 'folders', 'type' => 'link', 'label' => 'folders', 'title' => 'managefolders'),
array('action' => 'identities', 'type' => 'link', 'label' => 'identities', 'title' => 'manageidentities'),
array('action' => 'responses', 'type' => 'link', 'label' => 'responses', 'title' => 'manageresponses'),
);
$disabled_actions = (array) $RCMAIL->config->get('disabled_actions');
// get all identites from DB and define list of cols to be displayed
$plugin = $RCMAIL->plugins->exec_hook('settings_actions', array(
'actions' => $default_actions,
'attrib' => $attrib,
));
$selected = $RCMAIL->action ?: 'preferences';
$attrib = $plugin['attrib'];
$tagname = $attrib['tagname'];
$tabs = array();
foreach ($plugin['actions'] as $action) {
if (!$action['command'] && $action['action']) {
$action['prop'] = $action['action'];
$action['command'] = 'show';
}
else if ($action['command'] != 'show') {
// Backwards compatibility, show command added in 1.4
$action['prop'] = $action['command'];
$action['command'] = 'show';
}
$cmd = $action['prop'] ?: $action['action'];
$id = $action['id'] ?: $cmd;
if (in_array('settings.' . $cmd, $disabled_actions)) {
continue;
}
if (!$action['href']) {
$action['href'] = $RCMAIL->url(array('_action' => $cmd));
}
$button = $OUTPUT->button($action + array('type' => 'link'));
$attr = $attrib;
if (!empty($id)) {
$attr['id'] = preg_replace('/[^a-z0-9]/i', '', $attrib['idprefix'] . $id);
}
$classnames = array($attrib['class']);
if (!empty($action['class'])) {
$classnames[] = $action['class'];
}
else if (!empty($cmd)) {
$classnames[] = $cmd;
}
if ($cmd == $selected) {
$classnames[] = $attrib['selclass'];
}
$attr['class'] = join(' ', $classnames);
$tabs[] = html::tag($tagname, $attr, $button, html::$common_attrib);
}
return join('', $tabs);
}
/**
* Localize timezone identifiers
*/
function rcmail_timezone_label($tz)
{
static $labels;
if ($labels === null) {
$labels = array();
$lang = $_SESSION['language'];
if ($lang && $lang != 'en_US') {
if (file_exists(RCUBE_LOCALIZATION_DIR . "$lang/timezones.inc")) {
include RCUBE_LOCALIZATION_DIR . "$lang/timezones.inc";
}
}
}
if (empty($labels)) {
return str_replace('_', ' ', $tz);
}
$tokens = explode('/', $tz);
$key = 'tz';
foreach ($tokens as $i => $token) {
$idx = strtolower($token);
$token = str_replace('_', ' ', $token);
$key .= ":$idx";
$tokens[$i] = $labels[$key] ?: $token;
}
return implode('/', $tokens);
}
/**
* Returns timezone offset in standard time
*/
function rcmail_timezone_standard_time_data($tzname)
{
try {
$tz = new DateTimeZone($tzname);
$date = new DateTime(null, $tz);
$count = 12;
// Move back for a month (up to 12 times) until non-DST date is found
while ($count > 0 && $date->format('I')) {
$date->sub(new DateInterval('P1M'));
$count--;
}
$offset = $date->format('Z') + 45000;
$sortkey = sprintf('%06d.%s', $offset, $tzname);
return array(
'key' => $sortkey,
'offset' => $date->format('P'),
);
}
catch (Exception $e) {}
}
diff --git a/skins/elastic/meta.json b/skins/elastic/meta.json
index 249e22661..bf41c4be5 100644
--- a/skins/elastic/meta.json
+++ b/skins/elastic/meta.json
@@ -1,18 +1,18 @@
{
"name": "Elastic",
"author": "Aleksander Machniak",
"license": "Creative Commons Attribution-ShareAlike",
"license-url": "http://creativecommons.org/licenses/by-sa/3.0/",
"config": {
- "layout": "widescreen",
+ "supported_layouts": ["widescreen"],
"jquery_ui_colors_theme": "bootstrap",
"embed_css_location": "/styles/embed.css",
"editor_css_location": "/styles/embed.css",
"media_browser_css_location": "none"
},
"meta": {
"viewport": "width=device-width, initial-scale=1.0, shrink-to-fit=no, maximum-scale=1.0",
"theme-color": "#f4f4f4",
"msapplication-navbutton-color": "#f4f4f4"
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jun 8, 8:10 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
196652
Default Alt Text
(95 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment