diff options
Diffstat (limited to 'program/include')
-rw-r--r-- | program/include/iniset.php | 2 | ||||
-rw-r--r-- | program/include/rcmail.php | 130 | ||||
-rw-r--r-- | program/include/rcmail_install.php | 60 | ||||
-rw-r--r-- | program/include/rcmail_output_html.php | 135 |
4 files changed, 167 insertions, 160 deletions
diff --git a/program/include/iniset.php b/program/include/iniset.php index cb72ae15b..5c3065489 100644 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -61,7 +61,7 @@ require_once 'Roundcube/bootstrap.php'; spl_autoload_register('rcmail_autoload'); // include composer autoloader (if available) -if (file_exists('vendor/autoload.php')) { +if (@file_exists('vendor/autoload.php')) { require 'vendor/autoload.php'; } diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 5a5d4cb83..1a227927e 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -428,7 +428,8 @@ class rcmail extends rcube } // add some basic labels to client - $this->output->add_label('loading', 'servererror', 'connerror', 'requesttimedout', 'refreshing'); + $this->output->add_label('loading', 'servererror', 'connerror', 'requesttimedout', + 'refreshing', 'windowopenerror'); return $this->output; } @@ -494,30 +495,18 @@ class rcmail extends rcube $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; } - - if (!$allowed) { - $host = null; + else { + $host = $default_host; } - } - else if (!empty($default_host) && $host != rcube_utils::parse_host($default_host)) { - $host = null; + + $host = rcube_utils::parse_host($host); } if (!$host) { @@ -840,7 +829,7 @@ class rcmail extends rcube } // 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'); @@ -1784,31 +1773,36 @@ class rcmail extends rcube 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); + if ($pos = strpos($_SESSION['language'], '_')) { + $lang_codes[] = substr($_SESSION['language'], 0, $pos); } - else { - $lang = substr($lang, 0, 2); + + foreach ($lang_codes as $code) { + if (file_exists(INSTALL_PATH . 'program/js/tinymce/langs/'.$code.'.js')) { + $lang = $code; + break; + } } - if (!file_exists(INSTALL_PATH . 'program/js/tiny_mce/langs/'.$lang.'.js')) { + 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'); } /** @@ -1840,8 +1834,8 @@ class rcmail extends rcube ); 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; } @@ -1853,27 +1847,52 @@ class rcmail extends rcube */ 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')) { + if (function_exists('uploadprogress_get_info')) { + $status = uploadprogress_get_info($params['name']); + + if (!empty($status)) { + $params['current'] = $status['bytes_uploaded']; + $params['total'] = $status['bytes_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)) { - $status['percent'] = round($status['current']/$status['total']*100); - $params = array_merge($status, $params); + $params['current'] = $status['current']; + $params['total'] = $status['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('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(); @@ -1885,9 +1904,18 @@ class rcmail extends rcube 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); } diff --git a/program/include/rcmail_install.php b/program/include/rcmail_install.php index ca06f10b7..eec21ec7e 100644 --- a/program/include/rcmail_install.php +++ b/program/include/rcmail_install.php @@ -710,7 +710,8 @@ class rcmail_install // read schema file from /SQL/* $fname = INSTALL_PATH . "SQL/$engine.initial.sql"; if ($sql = @file_get_contents($fname)) { - $this->exec_sql($sql, $DB); + $DB->set_option('table_prefix', $this->config['db_prefix']); + $DB->exec_script($sql); } else { $this->fail('DB Schema', "Cannot read the schema file: $fname"); @@ -745,63 +746,6 @@ class rcmail_install /** - * Execute the given SQL queries on the database connection - * - * @param string SQL queries to execute - * @param object rcube_db Database connection - * @return boolen True on success, False on error - */ - function exec_sql($sql, $DB) - { - $sql = $this->fix_table_names($sql, $DB); - $buff = ''; - foreach (explode("\n", $sql) as $line) { - if (preg_match('/^--/', $line) || trim($line) == '') - continue; - - $buff .= $line . "\n"; - if (preg_match('/(;|^GO)$/', trim($line))) { - $DB->query($buff); - $buff = ''; - if ($DB->is_error()) - break; - } - } - - return !$DB->is_error(); - } - - - /** - * Parse SQL file and fix table names according to db_prefix - * Note: This need to be a complete database initial file - */ - private function fix_table_names($sql, $DB) - { - if (empty($this->config['db_prefix'])) { - return $sql; - } - - // replace table names - if (preg_match_all('/CREATE TABLE (\[dbo\]\.|IF NOT EXISTS )?[`"\[\]]*([^`"\[\] \r\n]+)/i', $sql, $matches)) { - foreach ($matches[2] as $table) { - $real_table = $this->config['db_prefix'] . $table; - $sql = preg_replace("/([^a-zA-Z0-9_])$table([^a-zA-Z0-9_])/", "\\1$real_table\\2", $sql); - } - } - // replace sequence names - if ($DB->db_provider == 'postgres' && preg_match_all('/CREATE SEQUENCE (IF NOT EXISTS )?"?([^" \n\r]+)/i', $sql, $matches)) { - foreach ($matches[2] as $sequence) { - $real_sequence = $this->config['db_prefix'] . $sequence; - $sql = preg_replace("/([^a-zA-Z0-9_])$sequence([^a-zA-Z0-9_])/", "\\1$real_sequence\\2", $sql); - } - } - - return $sql; - } - - - /** * Handler for Roundcube errors */ function raise_error($p) diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index e8b5c9828..6594209f6 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -5,7 +5,7 @@ | program/include/rcmail_output_html.php | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2006-2013, The Roundcube Dev Team | + | Copyright (C) 2006-2014, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -30,16 +30,16 @@ class rcmail_output_html extends rcmail_output { public $type = 'html'; - protected $message = null; - protected $js_env = array(); - protected $js_labels = array(); - protected $js_commands = array(); - protected $skin_paths = array(); + protected $message; protected $template_name; + protected $js_env = array(); + protected $js_labels = array(); + protected $js_commands = array(); + protected $skin_paths = array(); protected $scripts_path = ''; protected $script_files = array(); - protected $css_files = array(); - protected $scripts = array(); + protected $css_files = array(); + protected $scripts = array(); protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; protected $header = ''; protected $footer = ''; @@ -58,8 +58,6 @@ class rcmail_output_html extends rcmail_output /** * Constructor - * - * @todo Replace $this->config with the real rcube_config object */ public function __construct($task = null, $framed = false) { @@ -67,10 +65,10 @@ class rcmail_output_html extends rcmail_output $this->devel_mode = $this->config->get('devel_mode'); - //$this->framed = $framed; $this->set_env('task', $task); $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin')); $this->set_env('standard_windows', (bool) $this->config->get('standard_windows')); + $this->set_env('locale', $_SESSION['language']); // add cookie info $this->set_env('cookie_domain', ini_get('session.cookie_domain')); @@ -84,7 +82,7 @@ class rcmail_output_html extends rcmail_output if (!empty($_REQUEST['_extwin'])) $this->set_env('extwin', 1); - if ($this->framed || !empty($_REQUEST['_framed'])) + if ($this->framed || $framed) $this->set_env('framed', 1); $lic = <<<EOF @@ -209,6 +207,14 @@ EOF; // read meta file and check for dependecies $meta = @file_get_contents(RCUBE_INSTALL_PATH . $skin_path . '/meta.json'); $meta = @json_decode($meta, true); + + $meta['path'] = $skin_path; + $skin_id = end(explode('/', $skin_path)); + if (!$meta['name']) { + $meta['name'] = $skin_id; + } + $this->skins[$skin_id] = $meta; + if ($meta['extends']) { $path = RCUBE_INSTALL_PATH . 'skins/'; if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) { @@ -248,8 +254,9 @@ EOF; public function get_skin_file($file, &$skin_path = null, $add_path = null) { $skin_paths = $this->skin_paths; - if ($add_path) + if ($add_path) { array_unshift($skin_paths, $add_path); + } foreach ($skin_paths as $skin_path) { $path = realpath($skin_path . $file); @@ -283,9 +290,9 @@ EOF; { $cmd = func_get_args(); if (strpos($cmd[0], 'plugin.') !== false) - $this->js_commands[] = array('triggerEvent', $cmd[0], $cmd[1]); + $this->js_commands[] = array('triggerEvent', $cmd[0], $cmd[1]); else - $this->js_commands[] = $cmd; + $this->js_commands[] = $cmd; } /** @@ -295,7 +302,7 @@ EOF; { $args = func_get_args(); if (count($args) == 1 && is_array($args[0])) - $args = $args[0]; + $args = $args[0]; foreach ($args as $name) { $this->js_labels[$name] = $this->app->gettext($name); @@ -336,13 +343,13 @@ EOF; public function reset($all = false) { $framed = $this->framed; - $env = $all ? null : array_intersect_key($this->env, array('extwin'=>1, 'framed'=>1)); + $env = $all ? null : array_intersect_key($this->env, array('extwin'=>1, 'framed'=>1)); parent::reset(); // let some env variables survive - $this->env = $this->js_env = $env; - $this->framed = $framed || $this->env['framed']; + $this->env = $this->js_env = $env; + $this->framed = $framed || $this->env['framed']; $this->js_labels = array(); $this->js_commands = array(); $this->script_files = array(); @@ -421,20 +428,27 @@ EOF; array_unshift($this->js_commands, array('hide_message', $unlock)); } - if (!empty($this->script_files)) - $this->set_env('request_token', $this->app->get_request_token()); + if (!empty($this->script_files)) { + $this->set_env('request_token', $this->app->get_request_token()); + } + + $commands = $this->get_js_commands($framed); - // write all env variables to client - if ($commands = $this->get_js_commands()) { - $js = $this->framed ? "if (window.parent) {\n" : ''; - $js .= $commands . ($this->framed ? ' }' : ''); - $this->add_script($js, 'head_top'); + // if all js commands go to parent window we can ignore all + // script files and skip rcube_webmail initialization (#1489792) + if ($framed) { + $this->scripts = array(); + $this->script_files = array(); } + // write all javascript commands + $this->add_script($commands, 'head_top'); + // send clickjacking protection headers - $iframe = $this->framed || !empty($_REQUEST['_framed']); - if (!headers_sent() && ($xframe = $this->app->config->get('x_frame_options', 'sameorigin'))) + $iframe = $this->framed || $this->env['framed']; + if (!headers_sent() && ($xframe = $this->app->config->get('x_frame_options', 'sameorigin'))) { header('X-Frame-Options: ' . ($iframe && $xframe == 'deny' ? 'sameorigin' : $xframe)); + } // call super method $this->_write($template, $this->config->get('skin_path')); @@ -451,15 +465,15 @@ EOF; */ function parse($name = 'main', $exit = true, $write = true) { - $plugin = false; - $realname = $name; + $plugin = false; + $realname = $name; $this->template_name = $realname; $temp = explode('.', $name, 2); if (count($temp) > 1) { - $plugin = $temp[0]; - $name = $temp[1]; - $skin_dir = $plugin . '/skins/' . $this->config->get('skin'); + $plugin = $temp[0]; + $name = $temp[1]; + $skin_dir = $plugin . '/skins/' . $this->config->get('skin'); // apply skin search escalation list to plugin directory $plugin_skin_paths = array(); @@ -556,27 +570,47 @@ EOF; * * @return string $out */ - protected function get_js_commands() + protected function get_js_commands(&$framed = null) { - $out = ''; if (!$this->framed && !empty($this->js_env)) { - $out .= self::JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n"; + $this->command('set_env', $this->js_env); } + if (!empty($this->js_labels)) { $this->command('add_label', $this->js_labels); } + + $out = ''; + $parent_commands = 0; + foreach ($this->js_commands as $i => $args) { $method = array_shift($args); + $parent = $this->framed || preg_match('/^parent\./', $method); + foreach ($args as $i => $arg) { $args[$i] = self::json_serialize($arg); } - $parent = $this->framed || preg_match('/^parent\./', $method); - $out .= sprintf( - "%s.%s(%s);\n", - ($parent ? 'if(window.parent && parent.'.self::JS_OBJECT_NAME.') parent.' : '') . self::JS_OBJECT_NAME, - preg_replace('/^parent\./', '', $method), - implode(',', $args) - ); + + if ($parent) { + $parent_commands++; + $method = preg_replace('/^parent\./', '', $method); + $parent_prefix = 'if (window.parent && parent.' . self::JS_OBJECT_NAME . ') parent.'; + $method = $parent_prefix . self::JS_OBJECT_NAME . '.' . $method; + } + else { + $method = self::JS_OBJECT_NAME . '.' . $method; + } + + $out .= sprintf("%s(%s);\n", $method, implode(',', $args)); + } + + $framed = $parent_prefix && $parent_commands == count($this->js_commands); + + // make the output more compact if all commands go to parent window + if ($framed) { + $out = "if (window.parent && parent." . self::JS_OBJECT_NAME . ") {\n" + . str_replace($parent_prefix, "\tparent.", $out) + . "}\n"; } return $out; @@ -592,13 +626,14 @@ EOF; public function abs_url($str, $search_path = false) { if ($str[0] == '/') { - if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path))) + if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path))) { return $file_url; + } return $this->base_path . $str; } - else - return $str; + + return $str; } /** @@ -1243,7 +1278,7 @@ EOF; // generate html code for button if ($btn_content) { - $attrib_str = html::attrib_string($attrib, array_merge($link_attrib, array('data-*'))); + $attrib_str = html::attrib_string($attrib, $link_attrib); $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); } @@ -1333,7 +1368,7 @@ EOF; $output = trim($templ); if (empty($output)) { - $output = $this->default_template; + $output = html::doctype('html5') . "\n" . $this->default_template; $is_empty = true; } @@ -1498,7 +1533,7 @@ EOF; */ public function form_tag($attrib, $content = null) { - if ($this->framed || !empty($_REQUEST['_framed'])) { + if ($this->framed || $this->env['framed']) { $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); $hidden = $hiddenfield->show(); } @@ -1538,7 +1573,7 @@ EOF; // we already have a <form> tag if ($attrib['form']) { - if ($this->framed || !empty($_REQUEST['_framed'])) + if ($this->framed || $this->env['framed']) $hidden->add(array('name' => '_framed', 'value' => '1')); return $hidden->show() . $content; } |