summaryrefslogtreecommitdiff
path: root/program/include
diff options
context:
space:
mode:
Diffstat (limited to 'program/include')
-rw-r--r--program/include/bc.php16
-rw-r--r--program/include/iniset.php9
-rw-r--r--program/include/rcmail.php393
-rw-r--r--program/include/rcmail_output_html.php145
4 files changed, 362 insertions, 201 deletions
diff --git a/program/include/bc.php b/program/include/bc.php
index a7d7b5ac1..af2e51210 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::get_instance()->gc_temp();
+ $rcmail = rcmail::get_instance()->temp_gc();
}
function rcube_charset_convert($str, $from, $to=NULL)
@@ -205,9 +205,9 @@ function rcmail_quota_content($attrib = null)
return rcmail::get_instance()->quota_content($attrib);
}
-function rcmail_display_server_error($fallback=null, $fallback_args=null, $suffix='')
+function rcmail_display_server_error($fallback=null, $fallback_args=null)
{
- rcmail::get_instance()->display_server_error($fallback, $fallback_args, $suffix);
+ rcmail::get_instance()->display_server_error($fallback, $fallback_args);
}
function rcmail_filetype2classname($mimetype, $filename)
@@ -405,16 +405,6 @@ 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 919cc7682..e4fa956ef 100644
--- a/program/include/iniset.php
+++ b/program/include/iniset.php
@@ -21,11 +21,11 @@
*/
// application constants
-define('RCMAIL_VERSION', '1.0-git');
+define('RCMAIL_VERSION', '0.9.5');
define('RCMAIL_START', microtime(true));
if (!defined('INSTALL_PATH')) {
- define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');
+ define('INSTALL_PATH', '/var/lib/roundcube/');
}
if (!defined('RCMAIL_CONFIG_DIR')) {
@@ -60,11 +60,6 @@ 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 0483f0e18..c9350bdd9 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -51,7 +51,6 @@ class rcmail extends rcube
*/
public $action = '';
public $comm_path = './';
- public $filename = '';
private $address_books = array();
private $action_map = array();
@@ -66,13 +65,12 @@ 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($env = '')
+ static function get_instance()
{
if (!self::$instance || !is_a(self::$instance, 'rcmail')) {
- self::$instance = new rcmail($env);
+ self::$instance = new rcmail();
self::$instance->startup(); // init AFTER object was linked with self::$instance
}
@@ -88,10 +86,6 @@ 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();
@@ -132,7 +126,7 @@ class rcmail extends rcube
*/
public function set_task($task)
{
- $task = asciiwords($task, true);
+ $task = asciiwords($task);
if ($this->user && $this->user->ID)
$task = !$task ? 'mail' : $task;
@@ -168,7 +162,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 (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
+ if (in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8');
}
}
@@ -289,13 +283,13 @@ class rcmail extends rcube
*/
public function get_address_sources($writeable = false, $skip_hidden = false)
{
- $abook_type = (string) $this->config->get('address_book_type');
- $ldap_config = (array) $this->config->get('ldap_public');
+ $abook_type = strtolower($this->config->get('address_book_type'));
+ $ldap_config = $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 (!empty($abook_type) && strtolower($abook_type) != 'ldap') {
+ if ($abook_type != 'ldap' && $abook_type != '') {
if (!isset($this->address_books['0']))
$this->address_books['0'] = new rcube_contacts($this->db, $this->get_user_id());
$list['0'] = array(
@@ -308,7 +302,8 @@ class rcmail extends rcube
);
}
- if (!empty($ldap_config)) {
+ if ($ldap_config) {
+ $ldap_config = (array) $ldap_config;
foreach ($ldap_config as $id => $prop) {
// handle misconfiguration
if (empty($prop) || !is_array($prop)) {
@@ -317,7 +312,7 @@ class rcmail extends rcube
$list[$id] = array(
'id' => $id,
'name' => html::quote($prop['name']),
- 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']),
+ 'groups' => is_array($prop['groups']),
'readonly' => !$prop['writable'],
'hidden' => $prop['hidden'],
'autocomplete' => in_array($id, $autocomplete)
@@ -481,22 +476,15 @@ class rcmail extends rcube
$port = $config['default_port'];
}
- // Check if we need to add/force domain to username
- if (!empty($config['username_domain'])) {
- $domain = is_array($config['username_domain']) ? $config['username_domain'][$host] : $config['username_domain'];
-
- if ($domain = rcube_utils::parse_host((string)$domain, $host)) {
- $pos = strpos($username, '@');
-
- // force configured domains
- if (!empty($config['username_domain_forced']) && $pos !== false) {
- $username = substr($username, 0, $pos) . '@' . $domain;
- }
- // just add domain if not specified
- else if ($pos === false) {
- $username .= '@' . $domain;
- }
- }
+ /* Modify username with domain if required
+ Inspired by Marco <P0L0_notspam_binware.org>
+ */
+ // Check if we need to add domain
+ if (!empty($config['username_domain']) && strpos($username, '@') === false) {
+ if (is_array($config['username_domain']) && isset($config['username_domain'][$host]))
+ $username .= '@'.rcube_utils::parse_host($config['username_domain'][$host], $host);
+ else if (is_string($config['username_domain']))
+ $username .= '@'.rcube_utils::parse_host($config['username_domain'], $host);
}
if (!isset($config['login_lc'])) {
@@ -631,7 +619,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(, $domain) = explode('@', $post_user);
+ list($user, $domain) = explode('@', $post_user);
// direct match in default_host array
if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) {
@@ -735,6 +723,28 @@ 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
@@ -754,7 +764,7 @@ class rcmail extends rcube
$p['_task'] = $task;
unset($p['task']);
- $url = './' . $this->filename;
+ $url = './';
$delm = '?';
foreach (array_reverse($p) as $key => $val) {
if ($val !== '' && $val !== null) {
@@ -779,6 +789,11 @@ 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'))
@@ -939,6 +954,193 @@ 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,
+ ));
+
+ if ($plugin['abort']) {
+ return isset($plugin['result']) ? $plugin['result'] : false;
+ }
+
+ $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 (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN))
+ $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
@@ -961,32 +1163,22 @@ class rcmail extends rcube
/**
* Write login data (name, ID, IP address) to the 'userlogins' log file.
*/
- public function log_login($user = null, $failed_login = false, $error_code = 0)
+ public function log_login()
{
if (!$this->config->get('log_logins')) {
return;
}
- // failed login
- if ($failed_login) {
- $message = sprintf('Failed login for %s from %s in session %s (error: %d)',
- $user, rcube_utils::remote_ip(), session_id(), $error_code);
- }
- // successful login
- else {
- $user_name = $this->get_user_name();
- $user_id = $this->get_user_id();
+ $user_name = $this->get_user_name();
+ $user_id = $this->get_user_id();
- if (!$user_id) {
- return;
- }
-
- $message = sprintf('Successful login for %s (ID: %d) from %s in session %s',
- $user_name, $user_id, rcube_utils::remote_ip(), session_id());
+ if (!$user_id) {
+ return;
}
- // log login
- self::write_log('userlogins', $message);
+ self::write_log('userlogins',
+ sprintf('Successful login for %s (ID: %d) from %s in session %s',
+ $user_name, $user_id, rcube_utils::remote_ip(), session_id()));
}
@@ -1002,7 +1194,7 @@ class rcmail extends rcube
*/
public function table_output($attrib, $table_data, $a_show_cols, $id_col)
{
- $table = new html_table($attrib);
+ $table = new html_table(/*array('cols' => count($a_show_cols))*/);
// add table header
if (!$attrib['noheader']) {
@@ -1243,7 +1435,6 @@ class rcmail extends rcube
$js_mailboxlist = array();
$out = html::tag('ul', $attrib, $rcmail->render_folder_tree_html($a_mailboxes, $mbox_name, $js_mailboxlist, $attrib), html::$common_attrib);
- $rcmail->output->include_script('treelist.js');
$rcmail->output->add_gui_object('mailboxlist', $attrib['id']);
$rcmail->output->set_env('mailboxes', $js_mailboxlist);
$rcmail->output->set_env('unreadwrap', $attrib['unreadwrap']);
@@ -1365,10 +1556,9 @@ 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 $folder) {
+ foreach ($arrFolders as $key => $folder) {
$title = null;
$folder_class = $this->folder_classname($folder['id']);
$is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false;
@@ -1423,13 +1613,14 @@ class rcmail extends rcube
'id' => "rcmli".$folder_id,
'class' => join(' ', $classes),
'noclose' => true),
- html::a($link_attrib, $html_name));
-
- if (!empty($folder['folders'])) {
- $out .= html::div('treetoggle ' . ($is_collapsed ? 'collapsed' : 'expanded'), '&nbsp;');
- }
-
- $jslist[$folder['id']] = array(
+ html::a($link_attrib, $html_name) .
+ (!empty($folder['folders']) ? html::div(array(
+ 'class' => ($is_collapsed ? 'collapsed' : 'expanded'),
+ 'style' => "position:absolute",
+ 'onclick' => sprintf("%s.command('collapse-folder', '%s')", rcmail_output::JS_OBJECT_NAME, $js_name)
+ ), '&nbsp;') : ''));
+
+ $jslist[$folder_id] = array(
'id' => $folder['id'],
'name' => $foldername,
'virtual' => $folder['virtual']
@@ -1454,7 +1645,7 @@ class rcmail extends rcube
{
$out = '';
- foreach ($arrFolders as $folder) {
+ foreach ($arrFolders as $key => $folder) {
// skip exceptions (and its subfolders)
if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
continue;
@@ -1515,38 +1706,18 @@ class rcmail extends rcube
* Try to localize the given IMAP folder name.
* UTF-7 decode it in case no localized text was found
*
- * @param string $name Folder name
- * @param bool $with_path Enable path localization
+ * @param string $name Folder name
*
* @return string Localized folder name in UTF-8 encoding
*/
- public function localize_foldername($name, $with_path = true)
+ public function localize_foldername($name)
{
- $realnames = $this->config->get('show_real_foldernames');
-
- // try to localize path of the folder
- if ($with_path && !$realnames) {
- $storage = $this->get_storage();
- $delimiter = $storage->get_hierarchy_delimiter();
- $path = explode($delimiter, $name);
- $count = count($path);
-
- if ($count > 1) {
- for ($i = 0; $i < $count; $i++) {
- $folder = implode($delimiter, array_slice($path, 0, -$i));
- if ($folder_class = $this->folder_classname($folder)) {
- $name = implode($delimiter, array_slice($path, $count - $i));
- return $this->gettext($folder_class) . $delimiter . rcube_charset::convert($name, 'UTF7-IMAP');
- }
- }
- }
- }
-
- if (!$realnames && ($folder_class = $this->folder_classname($name))) {
+ if ($folder_class = $this->folder_classname($name)) {
return $this->gettext($folder_class);
}
-
- return rcube_charset::convert($name, 'UTF7-IMAP');
+ else {
+ return rcube_charset::convert($name, 'UTF7-IMAP');
+ }
}
@@ -1601,7 +1772,11 @@ class rcmail extends rcube
$quota_result = (array) $quota;
$quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
- if ($quota['total'] > 0) {
+ 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 (!isset($quota['percent'])) {
$quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
}
@@ -1620,8 +1795,7 @@ class rcmail extends rcube
}
}
else {
- $unlimited = $this->config->get('quota_zero_as_unlimited');
- $quota_result['title'] = $this->gettext($unlimited ? 'unlimited' : 'unknown');
+ $quota_result['title'] = $this->gettext('unknown');
$quota_result['percent'] = 0;
}
@@ -1634,51 +1808,32 @@ class rcmail extends rcube
*
* @param string $fallback Fallback message label
* @param array $fallback_args Fallback message label arguments
- * @param string $suffix Message label suffix
*/
- public function display_server_error($fallback = null, $fallback_args = null, $suffix = '')
+ public function display_server_error($fallback = null, $fallback_args = null)
{
$err_code = $this->storage->get_error_code();
$res_code = $this->storage->get_response_code();
- $args = array();
if ($res_code == rcube_storage::NOPERM) {
- $error = 'errornoperm';
+ $this->output->show_message('errornoperm', 'error');
}
else if ($res_code == rcube_storage::READONLY) {
- $error = 'errorreadonly';
- }
- else if ($res_code == rcube_storage::OVERQUOTA) {
- $error = 'errorroverquota';
+ $this->output->show_message('errorreadonly', 'error');
}
else if ($err_code && ($err_str = $this->storage->get_error_str())) {
// try to detect access rights problem and display appropriate message
if (stripos($err_str, 'Permission denied') !== false) {
- $error = 'errornoperm';
- }
- // try to detect full mailbox problem and display appropriate message
- // there can be e.g. "Quota exceeded" or "quotum would exceed"
- else if (stripos($err_str, 'quot') !== false && stripos($err_str, 'exceed') !== false) {
- $error = 'erroroverquota';
+ $this->output->show_message('errornoperm', 'error');
}
else {
- $error = 'servererrormsg';
- $args = array('msg' => $err_str);
+ $this->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
}
}
else if ($err_code < 0) {
- $error = 'storageerror';
+ $this->output->show_message('storageerror', 'error');
}
else if ($fallback) {
- $error = $fallback;
- $args = $fallback_args;
- }
-
- if ($error) {
- if ($suffix && $this->text_exists($error . $suffix)) {
- $error .= $suffix;
- }
- $this->output->show_message($error, 'error', $args);
+ $this->output->show_message($fallback, 'error', $fallback_args);
}
}
diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php
index a2ec29ca3..465d92f83 100644
--- a/program/include/rcmail_output_html.php
+++ b/program/include/rcmail_output_html.php
@@ -67,7 +67,6 @@ 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'));
@@ -106,6 +105,7 @@ class rcmail_output_html extends rcmail_output
));
}
+
/**
* Set environment variable
*
@@ -121,6 +121,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Getter for the current page title
*
@@ -144,17 +145,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($path . $skin) && is_readable($path . $skin)) {
- $skin_path = 'skins/' . $skin;
- $valid = true;
+ if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) {
+ $skin_path = 'skins/'.$skin;
+ $valid = true;
}
else {
$skin_path = $this->config->get('skin_path');
@@ -182,16 +183,13 @@ class rcmail_output_html extends rcmail_output
$this->skin_paths[] = $skin_path;
// read meta file and check for dependecies
- $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']);
- }
+ $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']);
}
}
+
/**
* Check if a specific template exists
*
@@ -200,18 +198,17 @@ class rcmail_output_html extends rcmail_output
*/
public function template_exists($name)
{
+ $found = false;
foreach ($this->skin_paths as $skin_path) {
- $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;
- }
+ $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;
}
-
- return false;
+ return $found;
}
+
/**
* Find the given file in the current skin path stack
*
@@ -236,6 +233,7 @@ class rcmail_output_html extends rcmail_output
return false;
}
+
/**
* Register a GUI object to the client script
*
@@ -248,6 +246,7 @@ class rcmail_output_html extends rcmail_output
$this->add_script(self::JS_OBJECT_NAME.".gui_object('$obj', '$id');");
}
+
/**
* Call a client method
*
@@ -263,6 +262,7 @@ class rcmail_output_html extends rcmail_output
$this->js_commands[] = $cmd;
}
+
/**
* Add a localized label to the client environment
*/
@@ -277,6 +277,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Invoke display_message command
*
@@ -303,6 +304,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Delete all stored env variables and commands
*
@@ -325,6 +327,7 @@ class rcmail_output_html extends rcmail_output
$this->body = '';
}
+
/**
* Redirect to a certain url
*
@@ -340,6 +343,7 @@ 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
@@ -373,6 +377,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Process template and write to stdOut
*
@@ -408,6 +413,7 @@ 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)
*
@@ -532,6 +538,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Return executable javascript code for all registered commands
*
@@ -563,6 +570,7 @@ class rcmail_output_html extends rcmail_output
return $out;
}
+
/**
* Make URLs starting with a slash point to skin directory
*
@@ -582,6 +590,7 @@ class rcmail_output_html extends rcmail_output
return $str;
}
+
/**
* Show error page and terminate script execution
*
@@ -616,6 +625,7 @@ class rcmail_output_html extends rcmail_output
array($this, 'globals_callback'), $input);
}
+
/**
* Callback funtion for preg_replace_callback() in parse_with_globals()
*/
@@ -624,6 +634,7 @@ 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
@@ -635,6 +646,7 @@ class rcmail_output_html extends rcmail_output
array($this, 'file_callback'), $output);
}
+
/**
* Callback function for preg_replace_callback in write()
*
@@ -643,7 +655,7 @@ class rcmail_output_html extends rcmail_output
protected function file_callback($matches)
{
$file = $matches[3];
- $file = preg_replace('!^/this/!', '/', $file);
+ $file[0] = preg_replace('!^/this/!', '/', $file[0]);
// correct absolute paths
if ($file[0] == '/') {
@@ -660,6 +672,7 @@ class rcmail_output_html extends rcmail_output
return $matches[1] . '=' . $matches[2] . $file . $matches[4];
}
+
/**
* Public wrapper to dipp into template parsing.
*
@@ -676,6 +689,7 @@ class rcmail_output_html extends rcmail_output
return $input;
}
+
/**
* Parse for conditional tags
*
@@ -713,18 +727,21 @@ 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 $this->eval_expression($condition);
+ return eval("return (".$this->parse_expression($condition).");");
}
+
/**
* Inserts hidden field with CSRF-prevention-token into POST forms
*/
@@ -741,16 +758,16 @@ class rcmail_output_html extends rcmail_output
return $out;
}
+
/**
- * Parse & evaluate a given expression and return its result.
- *
- * @param string Expression statement
+ * Parses expression and replaces variables
*
- * @return mixed Expression result
+ * @param string Expression statement
+ * @return string Expression value
*/
- protected function eval_expression ($expression)
+ protected function parse_expression($expression)
{
- $expression = preg_replace(
+ return preg_replace(
array(
'/session:([a-z0-9_]+)/i',
'/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i',
@@ -762,31 +779,17 @@ class rcmail_output_html extends rcmail_output
),
array(
"\$_SESSION['\\1']",
- "\$app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
- "\$env['\\1']",
+ "\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
+ "\$this->env['\\1']",
"rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)",
"\$_COOKIE['\\1']",
- "\$browser->{'\\1'}",
+ "\$this->browser->{'\\1'}",
$this->template_name,
),
- $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);
+ $expression);
}
+
/**
* Search for special tags in input and replace them
* with the appropriate content
@@ -801,6 +804,7 @@ 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
@@ -835,7 +839,7 @@ class rcmail_output_html extends rcmail_output
// show a label
case 'label':
if ($attrib['expression'])
- $attrib['name'] = $this->eval_expression($attrib['expression']);
+ $attrib['name'] = eval("return " . $this->parse_expression($attrib['expression']) .";");
if ($attrib['name'] || $attrib['command']) {
// @FIXME: 'noshow' is useless, remove?
@@ -967,7 +971,8 @@ class rcmail_output_html extends rcmail_output
// return code for a specified eval expression
case 'exp':
- return html::quote($this->eval_expression($attrib['expression']));
+ $value = $this->parse_expression($attrib['expression']);
+ return eval("return html::quote($value);");
// return variable
case 'var':
@@ -1004,13 +1009,12 @@ class rcmail_output_html extends rcmail_output
}
return html::quote($value);
-
- case 'form':
- return $this->form_tag($attrib);
+ break;
}
return '';
}
+
/**
* Include a specific file and return it's contents
*
@@ -1027,6 +1031,7 @@ class rcmail_output_html extends rcmail_output
return $out;
}
+
/**
* Create and register a button
*
@@ -1175,13 +1180,10 @@ class rcmail_output_html extends rcmail_output
$out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
}
- if ($attrib['wrapper']) {
- $out = html::tag($attrib['wrapper'], null, $out);
- }
-
return $out;
}
+
/**
* Link an external script file
*
@@ -1212,6 +1214,7 @@ class rcmail_output_html extends rcmail_output
$this->script_files[$position][] = $file;
}
+
/**
* Add inline javascript code
*
@@ -1228,6 +1231,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Link an external css file
*
@@ -1238,6 +1242,7 @@ class rcmail_output_html extends rcmail_output
$this->css_files[] = $file;
}
+
/**
* Add HTML code to the page header
*
@@ -1248,6 +1253,7 @@ class rcmail_output_html extends rcmail_output
$this->header .= "\n" . $str;
}
+
/**
* Add HTML code to the page footer
* To be added right befor </body>
@@ -1259,6 +1265,7 @@ class rcmail_output_html extends rcmail_output
$this->footer .= "\n" . $str;
}
+
/**
* Process template and write to stdOut
*
@@ -1267,7 +1274,12 @@ class rcmail_output_html extends rcmail_output
*/
public function _write($templ = '', $base_path = '')
{
- $output = empty($templ) ? $this->default_template : trim($templ);
+ $output = trim($templ);
+
+ if (empty($output)) {
+ $output = $this->default_template;
+ $is_empty = true;
+ }
// set default page title
if (empty($this->pagetitle)) {
@@ -1358,8 +1370,8 @@ class rcmail_output_html extends rcmail_output
}
// add css files in head, before scripts, for speed up with parallel downloads
- if (!empty($this->css_files) &&
- (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>')))
+ if (!empty($this->css_files) && !$is_empty
+ && (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>')))
) {
$css = '';
foreach ($this->css_files as $file) {
@@ -1383,6 +1395,7 @@ class rcmail_output_html extends rcmail_output
}
}
+
/**
* Returns iframe object, registers some related env variables
*
@@ -1413,6 +1426,7 @@ class rcmail_output_html extends rcmail_output
/* ************* common functions delivering gui objects ************** */
+
/**
* Create a form tag with the necessary hidden fields
*
@@ -1434,11 +1448,12 @@ class rcmail_output_html extends rcmail_output
$attrib['noclose'] = true;
return html::tag('form',
- $attrib + array('action' => $this->app->comm_path, 'method' => "get"),
+ $attrib + array('action' => "./", 'method' => "get"),
$hidden . $content,
array('id','class','style','name','method','action','enctype','onsubmit'));
}
+
/**
* Build a form tag with a unique request token
*
@@ -1469,6 +1484,7 @@ 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
@@ -1500,6 +1516,7 @@ class rcmail_output_html extends rcmail_output
return rcube_utils::idn_to_utf8($username);
}
+
/**
* GUI object 'loginform'
* Returns code for the webmail login form
@@ -1531,9 +1548,9 @@ class rcmail_output_html extends rcmail_output
$input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
$input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
$input_url = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
- $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'required' => 'required')
+ $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
+ $attrib + $user_attrib);
- $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'required' => 'required')
+ $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd')
+ $attrib + $pass_attrib);
$input_host = null;
@@ -1599,6 +1616,7 @@ class rcmail_output_html extends rcmail_output
return $out;
}
+
/**
* GUI object 'preloader'
* Loads javascript code for images preloading
@@ -1621,6 +1639,7 @@ class rcmail_output_html extends rcmail_output
}', 'docready');
}
+
/**
* GUI object 'searchform'
* Returns code for search function
@@ -1659,6 +1678,7 @@ class rcmail_output_html extends rcmail_output
return $out;
}
+
/**
* Builder for GUI object 'message'
*
@@ -1676,6 +1696,7 @@ class rcmail_output_html extends rcmail_output
return html::div($attrib, '');
}
+
/**
* GUI object 'charsetselector'
*