diff options
Diffstat (limited to 'program/include')
-rw-r--r-- | program/include/bc.php | 14 | ||||
-rw-r--r-- | program/include/iniset.php | 20 | ||||
-rw-r--r-- | program/include/rcmail.php | 279 | ||||
-rw-r--r-- | program/include/rcmail_output_html.php | 129 |
4 files changed, 113 insertions, 329 deletions
diff --git a/program/include/bc.php b/program/include/bc.php index d8356338d..a7d7b5ac1 100644 --- a/program/include/bc.php +++ b/program/include/bc.php @@ -62,7 +62,7 @@ function rcmail_url($action, $p=array(), $task=null) function rcmail_temp_gc() { - $rcmail = rcmail::get_instance()->temp_gc(); + rcmail::get_instance()->gc_temp(); } function rcube_charset_convert($str, $from, $to=NULL) @@ -287,7 +287,7 @@ function rcmail_remote_ip() function rcube_check_referer() { - return rcmail::check_referer(); + return rcube_utils::check_referer(); } function rcube_timer() @@ -405,6 +405,16 @@ function enriched_to_html($data) return rcube_enriched::to_html($data); } +function strip_quotes($str) +{ + return str_replace(array("'", '"'), '', $str); +} + +function strip_newlines($str) +{ + return preg_replace('/[\r\n]/', '', $str); +} + class rcube_html_page extends rcmail_html_page { } diff --git a/program/include/iniset.php b/program/include/iniset.php index b32ae4e8e..919cc7682 100644 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -24,21 +24,6 @@ define('RCMAIL_VERSION', '1.0-git'); define('RCMAIL_START', microtime(true)); -$config = array( - // Some users are not using Installer, so we'll check some - // critical PHP settings here. Only these, which doesn't provide - // an error/warning in the logs later. See (#1486307). - 'suhosin.session.encrypt' => 0, - 'session.auto_start' => 0, - 'file_uploads' => 1, -); -foreach ($config as $optname => $optval) { - if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) { - die("ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n" - ."Check your PHP configuration (including php_admin_flag)."); - } -} - if (!defined('INSTALL_PATH')) { define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/'); } @@ -75,6 +60,11 @@ require_once 'Roundcube/bootstrap.php'; // register autoloader for rcmail app classes spl_autoload_register('rcmail_autoload'); +// include composer autoloader (if available) +if (file_exists('vendor/autoload.php')) { + require 'vendor/autoload.php'; +} + // backward compatybility (to be removed) require_once INSTALL_PATH . 'program/include/bc.php'; diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 1bde4034f..800eddac6 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -51,6 +51,7 @@ class rcmail extends rcube */ public $action = ''; public $comm_path = './'; + public $filename = ''; private $address_books = array(); private $action_map = array(); @@ -65,12 +66,13 @@ class rcmail extends rcube /** * This implements the 'singleton' design pattern * + * @param string Environment name to run (e.g. live, dev, test) * @return rcmail The one and only instance */ - static function get_instance() + static function get_instance($env = '') { if (!self::$instance || !is_a(self::$instance, 'rcmail')) { - self::$instance = new rcmail(); + self::$instance = new rcmail($env); self::$instance->startup(); // init AFTER object was linked with self::$instance } @@ -86,6 +88,10 @@ class rcmail extends rcube { $this->init(self::INIT_WITH_DB | self::INIT_WITH_PLUGINS); + // set filename if not index.php + if (($basename = basename($_SERVER['SCRIPT_FILENAME'])) && $basename != 'index.php') + $this->filename = $basename; + // start session $this->session_init(); @@ -98,7 +104,10 @@ class rcmail extends rcube // reset some session parameters when changing task if ($this->task != 'utils') { - if ($this->session && $_SESSION['task'] != $this->task) + // we reset list page when switching to another task + // but only to the main task interface - empty action (#1489076) + // this will prevent from unintentional page reset on cross-task requests + if ($this->session && $_SESSION['task'] != $this->task && empty($this->action)) $this->session->remove('page'); // set current task to session $_SESSION['task'] = $this->task; @@ -159,7 +168,7 @@ class rcmail extends rcube setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8'); // workaround for http://bugs.php.net/bug.php?id=18556 - if (in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { + if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) { setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8'); } } @@ -225,6 +234,11 @@ class rcmail extends rcube } if (!$contacts) { + // there's no default, just return + if ($default) { + return null; + } + self::raise_error(array( 'code' => 700, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, @@ -258,13 +272,13 @@ class rcmail extends rcube */ public function get_address_sources($writeable = false, $skip_hidden = false) { - $abook_type = strtolower($this->config->get('address_book_type')); - $ldap_config = $this->config->get('ldap_public'); + $abook_type = (string) $this->config->get('address_book_type'); + $ldap_config = (array) $this->config->get('ldap_public'); $autocomplete = (array) $this->config->get('autocomplete_addressbooks'); - $list = array(); + $list = array(); // We are using the DB address book or a plugin address book - if ($abook_type != 'ldap' && $abook_type != '') { + if (!empty($abook_type) && strtolower($abook_type) != 'ldap') { if (!isset($this->address_books['0'])) $this->address_books['0'] = new rcube_contacts($this->db, $this->get_user_id()); $list['0'] = array( @@ -277,8 +291,7 @@ class rcmail extends rcube ); } - if ($ldap_config) { - $ldap_config = (array) $ldap_config; + if (!empty($ldap_config)) { foreach ($ldap_config as $id => $prop) { // handle misconfiguration if (empty($prop) || !is_array($prop)) { @@ -287,7 +300,7 @@ class rcmail extends rcube $list[$id] = array( 'id' => $id, 'name' => html::quote($prop['name']), - 'groups' => is_array($prop['groups']), + 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']), 'readonly' => !$prop['writable'], 'hidden' => $prop['hidden'], 'autocomplete' => in_array($id, $autocomplete) @@ -594,7 +607,7 @@ class rcmail extends rcube $post_host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST); $post_user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST); - list($user, $domain) = explode('@', $post_user); + list(, $domain) = explode('@', $post_user); // direct match in default_host array if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) { @@ -698,28 +711,6 @@ class rcmail extends rcube /** - * Create unique authorization hash - * - * @param string Session ID - * @param int Timestamp - * @return string The generated auth hash - */ - private function get_auth_hash($sess_id, $ts) - { - $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s', - $sess_id, - $ts, - $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***', - $_SERVER['HTTP_USER_AGENT']); - - if (function_exists('sha1')) - return sha1($auth_string); - else - return md5($auth_string); - } - - - /** * Build a valid URL to this instance of Roundcube * * @param mixed Either a string with the action or url parameters as key-value pairs @@ -739,7 +730,7 @@ class rcmail extends rcube $p['_task'] = $task; unset($p['task']); - $url = './'; + $url = './' . $this->filename; $delm = '?'; foreach (array_reverse($p) as $key => $val) { if ($val !== '' && $val !== null) { @@ -764,11 +755,6 @@ class rcmail extends rcube $book->close(); } - // before closing the database connection, write session data - if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) { - session_write_close(); - } - // write performance stats to logs/console if ($this->config->get('devel_mode')) { if (function_exists('memory_get_usage')) @@ -929,189 +915,6 @@ class rcmail extends rcube /** - * Send the given message using the configured method. - * - * @param object $message Reference to Mail_MIME object - * @param string $from Sender address string - * @param array $mailto Array of recipient address strings - * @param array $error SMTP error array (reference) - * @param string $body_file Location of file with saved message body (reference), - * used when delay_file_io is enabled - * @param array $options SMTP options (e.g. DSN request) - * - * @return boolean Send status. - */ - public function deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null) - { - $plugin = $this->plugins->exec_hook('message_before_send', array( - 'message' => $message, - 'from' => $from, - 'mailto' => $mailto, - 'options' => $options, - )); - - $from = $plugin['from']; - $mailto = $plugin['mailto']; - $options = $plugin['options']; - $message = $plugin['message']; - $headers = $message->headers(); - - // send thru SMTP server using custom SMTP library - if ($this->config->get('smtp_server')) { - // generate list of recipients - $a_recipients = array($mailto); - - if (strlen($headers['Cc'])) - $a_recipients[] = $headers['Cc']; - if (strlen($headers['Bcc'])) - $a_recipients[] = $headers['Bcc']; - - // clean Bcc from header for recipients - $send_headers = $headers; - unset($send_headers['Bcc']); - // here too, it because txtHeaders() below use $message->_headers not only $send_headers - unset($message->_headers['Bcc']); - - $smtp_headers = $message->txtHeaders($send_headers, true); - - if ($message->getParam('delay_file_io')) { - // use common temp dir - $temp_dir = $this->config->get('temp_dir'); - $body_file = tempnam($temp_dir, 'rcmMsg'); - if (PEAR::isError($mime_result = $message->saveMessageBody($body_file))) { - self::raise_error(array('code' => 650, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Could not create message: ".$mime_result->getMessage()), - TRUE, FALSE); - return false; - } - $msg_body = fopen($body_file, 'r'); - } - else { - $msg_body = $message->get(); - } - - // send message - if (!is_object($this->smtp)) { - $this->smtp_init(true); - } - - $sent = $this->smtp->send_mail($from, $a_recipients, $smtp_headers, $msg_body, $options); - $response = $this->smtp->get_response(); - $error = $this->smtp->get_error(); - - // log error - if (!$sent) { - self::raise_error(array('code' => 800, 'type' => 'smtp', - 'line' => __LINE__, 'file' => __FILE__, - 'message' => "SMTP error: ".join("\n", $response)), TRUE, FALSE); - } - } - // send mail using PHP's mail() function - else { - // unset some headers because they will be added by the mail() function - $headers_enc = $message->headers($headers); - $headers_php = $message->_headers; - unset($headers_php['To'], $headers_php['Subject']); - - // reset stored headers and overwrite - $message->_headers = array(); - $header_str = $message->txtHeaders($headers_php); - - // #1485779 - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - if (preg_match_all('/<([^@]+@[^>]+)>/', $headers_enc['To'], $m)) { - $headers_enc['To'] = implode(', ', $m[1]); - } - } - - $msg_body = $message->get(); - - if (PEAR::isError($msg_body)) { - self::raise_error(array('code' => 650, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Could not create message: ".$msg_body->getMessage()), - TRUE, FALSE); - } - else { - $delim = $this->config->header_delimiter(); - $to = $headers_enc['To']; - $subject = $headers_enc['Subject']; - $header_str = rtrim($header_str); - - if ($delim != "\r\n") { - $header_str = str_replace("\r\n", $delim, $header_str); - $msg_body = str_replace("\r\n", $delim, $msg_body); - $to = str_replace("\r\n", $delim, $to); - $subject = str_replace("\r\n", $delim, $subject); - } - - if (ini_get('safe_mode')) - $sent = mail($to, $subject, $msg_body, $header_str); - else - $sent = mail($to, $subject, $msg_body, $header_str, "-f$from"); - } - } - - if ($sent) { - $this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body)); - - // remove MDN headers after sending - unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']); - - // get all recipients - if ($headers['Cc']) - $mailto .= $headers['Cc']; - if ($headers['Bcc']) - $mailto .= $headers['Bcc']; - if (preg_match_all('/<([^@]+@[^>]+)>/', $mailto, $m)) - $mailto = implode(', ', array_unique($m[1])); - - if ($this->config->get('smtp_log')) { - self::write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s", - $this->user->get_username(), - $_SERVER['REMOTE_ADDR'], - $mailto, - !empty($response) ? join('; ', $response) : '')); - } - } - - if (is_resource($msg_body)) { - fclose($msg_body); - } - - $message->_headers = array(); - $message->headers($headers); - - return $sent; - } - - - /** - * Unique Message-ID generator. - * - * @return string Message-ID - */ - public function gen_message_id() - { - $local_part = md5(uniqid('rcmail'.mt_rand(),true)); - $domain_part = $this->user->get_username('domain'); - - // Try to find FQDN, some spamfilters doesn't like 'localhost' (#1486924) - if (!preg_match('/\.[a-z]+$/i', $domain_part)) { - foreach (array($_SERVER['HTTP_HOST'], $_SERVER['SERVER_NAME']) as $host) { - $host = preg_replace('/:[0-9]+$/', '', $host); - if ($host && preg_match('/\.[a-z]+$/i', $host)) { - $domain_part = $host; - } - } - } - - return sprintf('<%s@%s>', $local_part, $domain_part); - } - - - /** * Returns RFC2822 formatted current date in user's timezone * * @return string Date @@ -1165,7 +968,7 @@ class rcmail extends rcube */ public function table_output($attrib, $table_data, $a_show_cols, $id_col) { - $table = new html_table(/*array('cols' => count($a_show_cols))*/); + $table = new html_table($attrib); // add table header if (!$attrib['noheader']) { @@ -1528,9 +1331,10 @@ class rcmail extends rcube $realnames = (bool)$attrib['realnames']; $msgcounts = $this->storage->get_cache('messagecount'); $collapsed = $this->config->get('collapsed_folders'); + $realnames = $this->config->get('show_real_foldernames'); $out = ''; - foreach ($arrFolders as $key => $folder) { + foreach ($arrFolders as $folder) { $title = null; $folder_class = $this->folder_classname($folder['id']); $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false; @@ -1616,7 +1420,7 @@ class rcmail extends rcube { $out = ''; - foreach ($arrFolders as $key => $folder) { + foreach ($arrFolders as $folder) { // skip exceptions (and its subfolders) if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) { continue; @@ -1684,8 +1488,10 @@ class rcmail extends rcube */ public function localize_foldername($name, $with_path = true) { + $realnames = $this->config->get('show_real_foldernames'); + // try to localize path of the folder - if ($with_path) { + if ($with_path && !$realnames) { $storage = $this->get_storage(); $delimiter = $storage->get_hierarchy_delimiter(); $path = explode($delimiter, $name); @@ -1702,12 +1508,11 @@ class rcmail extends rcube } } - if ($folder_class = $this->folder_classname($name)) { + if (!$realnames && ($folder_class = $this->folder_classname($name))) { return $this->gettext($folder_class); } - else { - return rcube_charset::convert($name, 'UTF7-IMAP'); - } + + return rcube_charset::convert($name, 'UTF7-IMAP'); } @@ -1762,11 +1567,7 @@ class rcmail extends rcube $quota_result = (array) $quota; $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; - if (!$quota['total'] && $this->config->get('quota_zero_as_unlimited')) { - $quota_result['title'] = $this->gettext('unlimited'); - $quota_result['percent'] = 0; - } - else if ($quota['total']) { + if ($quota['total'] > 0) { if (!isset($quota['percent'])) { $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100)); } @@ -1785,7 +1586,8 @@ class rcmail extends rcube } } else { - $quota_result['title'] = $this->gettext('unknown'); + $unlimited = $this->config->get('quota_zero_as_unlimited'); + $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown'); $quota_result['percent'] = 0; } @@ -1964,7 +1766,8 @@ class rcmail extends rcube public function upload_init() { // Enable upload progress bar - if (($seconds = $this->config->get('upload_progress')) && ini_get('apc.rfc1867')) { + $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')) { $this->output->set_env('upload_progress_name', $field_name); $this->output->set_env('upload_progress_time', (int) $seconds); diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 6100269b9..998779509 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -67,11 +67,12 @@ class rcmail_output_html extends rcmail_output //$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')); // add cookie info $this->set_env('cookie_domain', ini_get('session.cookie_domain')); $this->set_env('cookie_path', ini_get('session.cookie_path')); - $this->set_env('cookie_secure', ini_get('session.cookie_secure')); + $this->set_env('cookie_secure', filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN)); // load the correct skin (in case user-defined) $skin = $this->config->get('skin'); @@ -105,7 +106,6 @@ class rcmail_output_html extends rcmail_output )); } - /** * Set environment variable * @@ -121,7 +121,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Getter for the current page title * @@ -145,17 +144,17 @@ class rcmail_output_html extends rcmail_output return $title; } - /** * Set skin */ public function set_skin($skin) { $valid = false; + $path = RCUBE_INSTALL_PATH . 'skins/'; - if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) { - $skin_path = 'skins/'.$skin; - $valid = true; + if (!empty($skin) && is_dir($path . $skin) && is_readable($path . $skin)) { + $skin_path = 'skins/' . $skin; + $valid = true; } else { $skin_path = $this->config->get('skin_path'); @@ -183,13 +182,16 @@ class rcmail_output_html extends rcmail_output $this->skin_paths[] = $skin_path; // read meta file and check for dependecies - $meta = @json_decode(@file_get_contents($skin_path.'/meta.json'), true); - if ($meta['extends'] && is_dir('skins/' . $meta['extends'])) { - $this->load_skin('skins/' . $meta['extends']); + $meta = @file_get_contents(RCUBE_INSTALL_PATH . $skin_path . '/meta.json'); + $meta = @json_decode($meta, true); + if ($meta['extends']) { + $path = RCUBE_INSTALL_PATH . 'skins/'; + if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) { + $this->load_skin('skins/' . $meta['extends']); + } } } - /** * Check if a specific template exists * @@ -198,16 +200,17 @@ class rcmail_output_html extends rcmail_output */ public function template_exists($name) { - $found = false; foreach ($this->skin_paths as $skin_path) { - $filename = $skin_path . '/templates/' . $name . '.html'; - $found = (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name])); - if ($found) - break; + $filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html'; + if ((is_file($filename) && is_readable($filename)) + || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name])) + ) { + return true; + } } - return $found; - } + return false; + } /** * Find the given file in the current skin path stack @@ -233,7 +236,6 @@ class rcmail_output_html extends rcmail_output return false; } - /** * Register a GUI object to the client script * @@ -246,7 +248,6 @@ class rcmail_output_html extends rcmail_output $this->add_script(self::JS_OBJECT_NAME.".gui_object('$obj', '$id');"); } - /** * Call a client method * @@ -262,7 +263,6 @@ class rcmail_output_html extends rcmail_output $this->js_commands[] = $cmd; } - /** * Add a localized label to the client environment */ @@ -277,7 +277,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Invoke display_message command * @@ -304,7 +303,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Delete all stored env variables and commands * @@ -327,7 +325,6 @@ class rcmail_output_html extends rcmail_output $this->body = ''; } - /** * Redirect to a certain url * @@ -343,7 +340,6 @@ class rcmail_output_html extends rcmail_output exit; } - /** * Send the request output to the client. * This will either parse a skin tempalte or send an AJAX response @@ -377,7 +373,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Process template and write to stdOut * @@ -413,7 +408,6 @@ class rcmail_output_html extends rcmail_output $this->_write($template, $this->config->get('skin_path')); } - /** * Parse a specific skin template and deliver to stdout (or return) * @@ -538,7 +532,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Return executable javascript code for all registered commands * @@ -570,7 +563,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Make URLs starting with a slash point to skin directory * @@ -590,7 +582,6 @@ class rcmail_output_html extends rcmail_output return $str; } - /** * Show error page and terminate script execution * @@ -625,7 +616,6 @@ class rcmail_output_html extends rcmail_output array($this, 'globals_callback'), $input); } - /** * Callback funtion for preg_replace_callback() in parse_with_globals() */ @@ -634,7 +624,6 @@ class rcmail_output_html extends rcmail_output return $GLOBALS[$matches[1]]; } - /** * Correct absolute paths in images and other tags * add timestamp to .js and .css filename @@ -646,7 +635,6 @@ class rcmail_output_html extends rcmail_output array($this, 'file_callback'), $output); } - /** * Callback function for preg_replace_callback in write() * @@ -655,7 +643,7 @@ class rcmail_output_html extends rcmail_output protected function file_callback($matches) { $file = $matches[3]; - $file[0] = preg_replace('!^/this/!', '/', $file[0]); + $file = preg_replace('!^/this/!', '/', $file); // correct absolute paths if ($file[0] == '/') { @@ -672,7 +660,6 @@ class rcmail_output_html extends rcmail_output return $matches[1] . '=' . $matches[2] . $file . $matches[4]; } - /** * Public wrapper to dipp into template parsing. * @@ -689,7 +676,6 @@ class rcmail_output_html extends rcmail_output return $input; } - /** * Parse for conditional tags * @@ -727,21 +713,18 @@ class rcmail_output_html extends rcmail_output return $input; } - /** * Determines if a given condition is met * - * @todo Get rid off eval() once I understand what this does. * @todo Extend this to allow real conditions, not just "set" * @param string Condition statement * @return boolean True if condition is met, False if not */ protected function check_condition($condition) { - return eval("return (".$this->parse_expression($condition).");"); + return $this->eval_expression($condition); } - /** * Inserts hidden field with CSRF-prevention-token into POST forms */ @@ -758,16 +741,16 @@ class rcmail_output_html extends rcmail_output return $out; } - /** - * Parses expression and replaces variables + * Parse & evaluate a given expression and return its result. + * + * @param string Expression statement * - * @param string Expression statement - * @return string Expression value + * @return mixed Expression result */ - protected function parse_expression($expression) + protected function eval_expression ($expression) { - return preg_replace( + $expression = preg_replace( array( '/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i', @@ -779,16 +762,30 @@ class rcmail_output_html extends rcmail_output ), array( "\$_SESSION['\\1']", - "\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))", - "\$this->env['\\1']", + "\$app->config->get('\\1',rcube_utils::get_boolean('\\3'))", + "\$env['\\1']", "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)", "\$_COOKIE['\\1']", - "\$this->browser->{'\\1'}", + "\$browser->{'\\1'}", $this->template_name, ), - $expression); - } + $expression + ); + + $fn = create_function('$app,$browser,$env', "return ($expression);"); + if (!$fn) { + rcube::raise_error(array( + 'code' => 505, + 'type' => 'php', + 'file' => __FILE__, + 'line' => __LINE__, + 'message' => "Expression parse error on: ($expression)"), true, false); + return null; + } + + return $fn($this->app, $this->browser, $this->env); + } /** * Search for special tags in input and replace them @@ -804,7 +801,6 @@ class rcmail_output_html extends rcmail_output return preg_replace_callback('/<roundcube:([-_a-z]+)\s+((?:[^>]|\\\\>)+)(?<!\\\\)>/Ui', array($this, 'xml_command'), $input); } - /** * Callback function for parsing an xml command tag * and turn it into real html content @@ -839,7 +835,7 @@ class rcmail_output_html extends rcmail_output // show a label case 'label': if ($attrib['expression']) - $attrib['name'] = eval("return " . $this->parse_expression($attrib['expression']) .";"); + $attrib['name'] = $this->eval_expression($attrib['expression']); if ($attrib['name'] || $attrib['command']) { // @FIXME: 'noshow' is useless, remove? @@ -873,6 +869,7 @@ class rcmail_output_html extends rcmail_output // include a file case 'include': $old_base_path = $this->base_path; + if (!empty($attrib['skin_path'])) $attrib['skinpath'] = $attrib['skin_path']; if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attrib['skinpath'])) { $this->base_path = preg_replace('!plugins/\w+/!', '', $skin_path); // set base_path to core skin directory (not plugin's skin) $path = realpath($path); @@ -970,8 +967,7 @@ class rcmail_output_html extends rcmail_output // return code for a specified eval expression case 'exp': - $value = $this->parse_expression($attrib['expression']); - return eval("return html::quote($value);"); + return html::quote($this->eval_expression($attrib['expression'])); // return variable case 'var': @@ -1008,12 +1004,13 @@ class rcmail_output_html extends rcmail_output } return html::quote($value); - break; + + case 'form': + return $this->form_tag($attrib); } return ''; } - /** * Include a specific file and return it's contents * @@ -1030,7 +1027,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Create and register a button * @@ -1186,7 +1182,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Link an external script file * @@ -1217,7 +1212,6 @@ class rcmail_output_html extends rcmail_output $this->script_files[$position][] = $file; } - /** * Add inline javascript code * @@ -1234,7 +1228,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Link an external css file * @@ -1245,7 +1238,6 @@ class rcmail_output_html extends rcmail_output $this->css_files[] = $file; } - /** * Add HTML code to the page header * @@ -1256,7 +1248,6 @@ class rcmail_output_html extends rcmail_output $this->header .= "\n" . $str; } - /** * Add HTML code to the page footer * To be added right befor </body> @@ -1268,7 +1259,6 @@ class rcmail_output_html extends rcmail_output $this->footer .= "\n" . $str; } - /** * Process template and write to stdOut * @@ -1393,7 +1383,6 @@ class rcmail_output_html extends rcmail_output } } - /** * Returns iframe object, registers some related env variables * @@ -1424,7 +1413,6 @@ class rcmail_output_html extends rcmail_output /* ************* common functions delivering gui objects ************** */ - /** * Create a form tag with the necessary hidden fields * @@ -1446,12 +1434,11 @@ class rcmail_output_html extends rcmail_output $attrib['noclose'] = true; return html::tag('form', - $attrib + array('action' => "./", 'method' => "get"), + $attrib + array('action' => $this->app->comm_path, 'method' => "get"), $hidden . $content, array('id','class','style','name','method','action','enctype','onsubmit')); } - /** * Build a form tag with a unique request token * @@ -1482,7 +1469,6 @@ class rcmail_output_html extends rcmail_output return $this->form_tag($attrib, $hidden->show() . $content); } - /** * GUI object 'username' * Showing IMAP username of the current session @@ -1514,7 +1500,6 @@ class rcmail_output_html extends rcmail_output return rcube_utils::idn_to_utf8($username); } - /** * GUI object 'loginform' * Returns code for the webmail login form @@ -1614,7 +1599,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * GUI object 'preloader' * Loads javascript code for images preloading @@ -1637,7 +1621,6 @@ class rcmail_output_html extends rcmail_output }', 'docready'); } - /** * GUI object 'searchform' * Returns code for search function @@ -1676,7 +1659,6 @@ class rcmail_output_html extends rcmail_output return $out; } - /** * Builder for GUI object 'message' * @@ -1694,7 +1676,6 @@ class rcmail_output_html extends rcmail_output return html::div($attrib, ''); } - /** * GUI object 'charsetselector' * |