From 59478e06c25303a790a0840ab2ac30662c4ef781 Mon Sep 17 00:00:00 2001 From: Hugues Hiegel Date: Tue, 5 Aug 2014 16:46:22 +0200 Subject: c'est la merde.. --- program/include/bc.php | 16 +- program/include/iniset.php | 9 +- program/include/rcmail.php | 393 +- program/include/rcmail_output_html.php | 145 +- program/js/app.js | 7016 +------------------- program/js/common.js | 724 +- program/js/editor.js | 2 +- program/js/googiespell.js | 1136 +--- program/js/jquery.min.js | 3 +- program/js/jstz.min.js | 13 +- program/js/list.js | 1607 +---- program/lib/Crypt/GPG.php | 2542 +++++++ program/lib/Crypt/GPG/DecryptStatusHandler.php | 336 + program/lib/Crypt/GPG/Engine.php | 1758 +++++ program/lib/Crypt/GPG/Exceptions.php | 473 ++ program/lib/Crypt/GPG/Key.php | 223 + program/lib/Crypt/GPG/Signature.php | 428 ++ program/lib/Crypt/GPG/SubKey.php | 649 ++ program/lib/Crypt/GPG/UserId.php | 373 ++ program/lib/Crypt/GPG/VerifyStatusHandler.php | 216 + program/lib/Net/Sieve.php | 1274 ++++ program/lib/Roundcube/bootstrap.php | 30 +- program/lib/Roundcube/html.php | 70 +- program/lib/Roundcube/rcube.php | 302 +- program/lib/Roundcube/rcube_addressbook.php | 32 +- program/lib/Roundcube/rcube_base_replacer.php | 2 +- program/lib/Roundcube/rcube_browser.php | 2 +- program/lib/Roundcube/rcube_cache.php | 45 +- program/lib/Roundcube/rcube_config.php | 251 +- program/lib/Roundcube/rcube_contacts.php | 4 - program/lib/Roundcube/rcube_content_filter.php | 2 +- program/lib/Roundcube/rcube_csv2vcard.php | 49 +- program/lib/Roundcube/rcube_db.php | 107 +- program/lib/Roundcube/rcube_db_mssql.php | 32 +- program/lib/Roundcube/rcube_db_mysql.php | 23 +- program/lib/Roundcube/rcube_db_pgsql.php | 47 +- program/lib/Roundcube/rcube_db_sqlite.php | 47 +- program/lib/Roundcube/rcube_db_sqlsrv.php | 29 +- program/lib/Roundcube/rcube_enriched.php | 2 +- program/lib/Roundcube/rcube_image.php | 99 +- program/lib/Roundcube/rcube_imap.php | 279 +- program/lib/Roundcube/rcube_imap_cache.php | 219 +- program/lib/Roundcube/rcube_imap_generic.php | 282 +- program/lib/Roundcube/rcube_ldap.php | 1322 ++-- program/lib/Roundcube/rcube_ldap_generic.php | 6 + program/lib/Roundcube/rcube_message.php | 107 +- program/lib/Roundcube/rcube_mime.php | 32 +- program/lib/Roundcube/rcube_plugin.php | 36 +- program/lib/Roundcube/rcube_plugin_api.php | 122 +- program/lib/Roundcube/rcube_result_set.php | 47 +- program/lib/Roundcube/rcube_session.php | 142 +- program/lib/Roundcube/rcube_smtp.php | 12 +- program/lib/Roundcube/rcube_spellcheck_atd.php | 204 + program/lib/Roundcube/rcube_spellcheck_enchant.php | 182 + program/lib/Roundcube/rcube_spellcheck_engine.php | 91 + program/lib/Roundcube/rcube_spellcheck_googie.php | 176 + program/lib/Roundcube/rcube_spellcheck_pspell.php | 189 + program/lib/Roundcube/rcube_spellchecker.php | 163 +- program/lib/Roundcube/rcube_storage.php | 22 +- program/lib/Roundcube/rcube_string_replacer.php | 13 +- program/lib/Roundcube/rcube_user.php | 9 +- program/lib/Roundcube/rcube_utils.php | 84 +- program/lib/Roundcube/rcube_vcard.php | 15 +- program/lib/Roundcube/rcube_washtml.php | 21 +- program/localization/ar_SA/labels.inc | 5 - program/localization/ar_SA/messages.inc | 9 +- program/localization/ast/labels.inc | 5 - program/localization/ast/messages.inc | 9 +- program/localization/az_AZ/labels.inc | 5 - program/localization/az_AZ/messages.inc | 9 +- program/localization/be_BE/labels.inc | 5 - program/localization/be_BE/messages.inc | 9 +- program/localization/bg_BG/labels.inc | 5 - program/localization/bg_BG/messages.inc | 9 +- program/localization/bn_BD/labels.inc | 5 - program/localization/bn_BD/messages.inc | 9 +- program/localization/br/labels.inc | 5 - program/localization/br/messages.inc | 9 +- program/localization/bs_BA/labels.inc | 7 +- program/localization/bs_BA/messages.inc | 9 +- program/localization/ca_ES/labels.inc | 5 - program/localization/ca_ES/messages.inc | 9 +- program/localization/cs_CZ/labels.inc | 7 +- program/localization/cs_CZ/messages.inc | 6 +- program/localization/cy_GB/labels.inc | 7 +- program/localization/cy_GB/messages.inc | 9 +- program/localization/da_DK/labels.inc | 7 +- program/localization/da_DK/messages.inc | 9 +- program/localization/de_CH/labels.inc | 5 - program/localization/de_CH/messages.inc | 2 - program/localization/de_DE/labels.inc | 7 +- program/localization/de_DE/messages.inc | 9 +- program/localization/el_GR/labels.inc | 5 - program/localization/el_GR/messages.inc | 9 +- program/localization/en_GB/labels.inc | 5 - program/localization/en_GB/messages.inc | 13 +- program/localization/en_US/csv2vcard.inc | 19 +- program/localization/en_US/labels.inc | 20 +- program/localization/en_US/labels.inc.orig | 537 ++ program/localization/en_US/messages.inc | 19 +- program/localization/eo/labels.inc | 5 - program/localization/eo/messages.inc | 9 +- program/localization/es_AR/labels.inc | 5 - program/localization/es_AR/messages.inc | 9 +- program/localization/es_ES/labels.inc | 7 +- program/localization/es_ES/messages.inc | 2 - program/localization/et_EE/labels.inc | 5 +- program/localization/et_EE/messages.inc | 2 - program/localization/eu_ES/labels.inc | 5 - program/localization/eu_ES/messages.inc | 195 +- program/localization/fa_AF/labels.inc | 5 - program/localization/fa_AF/messages.inc | 55 +- program/localization/fa_IR/labels.inc | 5 - program/localization/fa_IR/messages.inc | 163 +- program/localization/fi_FI/labels.inc | 3 - program/localization/fi_FI/messages.inc | 4 +- program/localization/fr_FR/labels.inc | 9 +- program/localization/fr_FR/messages.inc | 210 +- program/localization/fy_NL/labels.inc | 5 - program/localization/fy_NL/messages.inc | 171 +- program/localization/ga_IE/labels.inc | 5 - program/localization/ga_IE/messages.inc | 9 +- program/localization/gl_ES/labels.inc | 7 +- program/localization/gl_ES/messages.inc | 2 - program/localization/he_IL/labels.inc | 5 - program/localization/he_IL/messages.inc | 2 - program/localization/hi_IN/labels.inc | 5 - program/localization/hi_IN/messages.inc | 9 +- program/localization/hr_HR/labels.inc | 5 - program/localization/hr_HR/messages.inc | 9 +- program/localization/hu_HU/labels.inc | 5 - program/localization/hu_HU/messages.inc | 9 +- program/localization/hy_AM/labels.inc | 5 - program/localization/hy_AM/messages.inc | 9 +- program/localization/ia/labels.inc | 5 - program/localization/ia/messages.inc | 9 +- program/localization/id_ID/labels.inc | 18 +- program/localization/id_ID/messages.inc | 11 +- program/localization/index.inc | 2 - program/localization/is_IS/labels.inc | 5 - program/localization/is_IS/messages.inc | 9 +- program/localization/it_IT/labels.inc | 5 - program/localization/it_IT/messages.inc | 11 +- program/localization/ja_JP/labels.inc | 5 - program/localization/ja_JP/messages.inc | 9 +- program/localization/ka_GE/labels.inc | 5 - program/localization/ka_GE/messages.inc | 9 +- program/localization/km_KH/labels.inc | 5 - program/localization/km_KH/messages.inc | 9 +- program/localization/ko_KR/labels.inc | 5 - program/localization/ko_KR/messages.inc | 9 +- program/localization/ku/labels.inc | 5 - program/localization/ku/messages.inc | 9 +- program/localization/lb_LU/labels.inc | 77 +- program/localization/lb_LU/messages.inc | 7 +- program/localization/lt_LT/labels.inc | 5 - program/localization/lt_LT/messages.inc | 9 +- program/localization/lv_LV/labels.inc | 323 +- program/localization/lv_LV/messages.inc | 90 +- program/localization/mk_MK/labels.inc | 5 - program/localization/mk_MK/messages.inc | 9 +- program/localization/ml_IN/labels.inc | 5 - program/localization/ml_IN/messages.inc | 9 +- program/localization/mr_IN/labels.inc | 5 - program/localization/mr_IN/messages.inc | 9 +- program/localization/ms_MY/labels.inc | 5 - program/localization/ms_MY/messages.inc | 9 +- program/localization/nb_NO/labels.inc | 5 - program/localization/nb_NO/messages.inc | 9 +- program/localization/ne_NP/labels.inc | 5 - program/localization/ne_NP/messages.inc | 9 +- program/localization/nl_BE/labels.inc | 5 - program/localization/nl_BE/messages.inc | 9 +- program/localization/nl_NL/labels.inc | 5 - program/localization/nl_NL/messages.inc | 9 +- program/localization/nn_NO/labels.inc | 5 - program/localization/nn_NO/messages.inc | 9 +- program/localization/pl_PL/labels.inc | 5 - program/localization/pl_PL/messages.inc | 2 - program/localization/ps/labels.inc | 5 - program/localization/ps/messages.inc | 9 +- program/localization/pt_BR/labels.inc | 9 +- program/localization/pt_BR/messages.inc | 9 +- program/localization/pt_PT/labels.inc | 5 - program/localization/pt_PT/messages.inc | 9 +- program/localization/ro_RO/labels.inc | 3 - program/localization/ro_RO/messages.inc | 62 +- program/localization/ru_RU/labels.inc | 20 +- program/localization/ru_RU/messages.inc | 175 +- program/localization/si_LK/labels.inc | 5 - program/localization/si_LK/messages.inc | 9 +- program/localization/sk_SK/labels.inc | 5 - program/localization/sk_SK/messages.inc | 9 +- program/localization/sl_SI/labels.inc | 13 +- program/localization/sl_SI/messages.inc | 2 - program/localization/sq_AL/labels.inc | 5 - program/localization/sq_AL/messages.inc | 9 +- program/localization/sr_CS/labels.inc | 5 - program/localization/sr_CS/messages.inc | 9 +- program/localization/sv_SE/labels.inc | 5 - program/localization/sv_SE/messages.inc | 63 +- program/localization/ta_IN/labels.inc | 5 - program/localization/ta_IN/messages.inc | 9 +- program/localization/th_TH/labels.inc | 5 - program/localization/th_TH/messages.inc | 9 +- program/localization/tr_TR/labels.inc | 7 +- program/localization/tr_TR/messages.inc | 2 - program/localization/uk_UA/labels.inc | 533 +- program/localization/uk_UA/messages.inc | 115 +- program/localization/ur_PK/labels.inc | 40 + program/localization/ur_PK/messages.inc | 18 + program/localization/vi_VN/labels.inc | 5 - program/localization/vi_VN/messages.inc | 9 +- program/localization/zh_CN/labels.inc | 5 - program/localization/zh_CN/messages.inc | 136 +- program/localization/zh_TW/labels.inc | 5 - program/localization/zh_TW/messages.inc | 9 +- program/steps/addressbook/copy.inc | 12 +- program/steps/addressbook/delete.inc | 38 +- program/steps/addressbook/export.inc | 113 +- program/steps/addressbook/func.inc | 187 +- program/steps/addressbook/import.inc | 71 +- program/steps/addressbook/list.inc | 49 +- program/steps/addressbook/save.inc | 29 +- program/steps/addressbook/show.inc | 63 +- program/steps/addressbook/undo.inc | 25 +- program/steps/mail/attachments.inc | 5 +- program/steps/mail/check_recent.inc | 9 +- program/steps/mail/compose.inc | 103 +- program/steps/mail/func.inc | 336 +- program/steps/mail/func.inc.orig | 1964 ++++++ program/steps/mail/get.inc | 86 +- program/steps/mail/list.inc | 1 + program/steps/mail/list_contacts.inc | 29 +- program/steps/mail/move_del.inc | 11 +- program/steps/mail/sendmail.inc | 30 +- program/steps/mail/show.inc | 61 +- program/steps/mail/show.inc.orig | 315 + program/steps/settings/about.inc | 67 +- program/steps/settings/edit_folder.inc | 5 +- program/steps/settings/edit_prefs.inc | 2 +- program/steps/settings/edit_response.inc | 107 + program/steps/settings/folders.inc | 16 +- program/steps/settings/func.inc | 1961 +++--- program/steps/settings/responses.inc | 128 + program/steps/settings/save_prefs.inc | 4 - program/steps/utils/save_pref.inc | 22 +- program/steps/utils/spell.inc | 7 - program/steps/utils/spell_html.inc | 5 - 249 files changed, 16930 insertions(+), 17146 deletions(-) mode change 100644 => 120000 program/js/jquery.min.js create mode 100644 program/lib/Crypt/GPG.php create mode 100644 program/lib/Crypt/GPG/DecryptStatusHandler.php create mode 100644 program/lib/Crypt/GPG/Engine.php create mode 100644 program/lib/Crypt/GPG/Exceptions.php create mode 100644 program/lib/Crypt/GPG/Key.php create mode 100644 program/lib/Crypt/GPG/Signature.php create mode 100644 program/lib/Crypt/GPG/SubKey.php create mode 100644 program/lib/Crypt/GPG/UserId.php create mode 100644 program/lib/Crypt/GPG/VerifyStatusHandler.php create mode 100644 program/lib/Net/Sieve.php create mode 100644 program/lib/Roundcube/rcube_spellcheck_atd.php create mode 100644 program/lib/Roundcube/rcube_spellcheck_enchant.php create mode 100644 program/lib/Roundcube/rcube_spellcheck_engine.php create mode 100644 program/lib/Roundcube/rcube_spellcheck_googie.php create mode 100644 program/lib/Roundcube/rcube_spellcheck_pspell.php create mode 100644 program/localization/en_US/labels.inc.orig mode change 100755 => 100644 program/localization/ga_IE/labels.inc mode change 100755 => 100644 program/localization/ga_IE/messages.inc mode change 100755 => 100644 program/localization/ka_GE/labels.inc mode change 100755 => 100644 program/localization/ka_GE/messages.inc mode change 100755 => 100644 program/localization/mk_MK/labels.inc mode change 100755 => 100644 program/localization/mk_MK/messages.inc mode change 100755 => 100644 program/localization/mr_IN/labels.inc mode change 100755 => 100644 program/localization/mr_IN/messages.inc mode change 100755 => 100644 program/localization/ps/labels.inc mode change 100755 => 100644 program/localization/ps/messages.inc create mode 100644 program/localization/ur_PK/labels.inc create mode 100644 program/localization/ur_PK/messages.inc create mode 100644 program/steps/mail/func.inc.orig create mode 100644 program/steps/mail/show.inc.orig create mode 100644 program/steps/settings/edit_response.inc create mode 100644 program/steps/settings/responses.inc (limited to 'program') 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 + */ + // 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))) { @@ -734,6 +722,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 * @@ -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')) @@ -938,6 +953,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 * @@ -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'), ' '); - } - - $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) + ), ' ') : '')); + + $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('/]|\\\\>)+)(?/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('%s', $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 @@ -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, '