- Framework refactoring (I hope it's the last one):
rcube,rcmail,rcube_ui -> rcube,rcmail,rcube_utils
renamed main.inc into rcube_bc.inc
1 files renamed
1 files added
1 files deleted
17 files modified
| | |
| | | |
| | | // check if config files had errors |
| | | if ($err_str = $RCMAIL->config->get_error()) { |
| | | raise_error(array( |
| | | rcmail::raise_error(array( |
| | | 'code' => 601, |
| | | 'type' => 'php', |
| | | 'message' => $err_str), false, true); |
| | |
| | | |
| | | // check DB connections and exit on failure |
| | | if ($err_str = $RCMAIL->db->is_error()) { |
| | | raise_error(array( |
| | | rcmail::raise_error(array( |
| | | 'code' => 603, |
| | | 'type' => 'db', |
| | | 'message' => $err_str), FALSE, TRUE); |
| | |
| | | |
| | | // error steps |
| | | if ($RCMAIL->action == 'error' && !empty($_GET['_code'])) { |
| | | raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE); |
| | | rcmail::raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE); |
| | | } |
| | | |
| | | // check if https is required (for login) and redirect if necessary |
| | | if (empty($_SESSION['user_id']) && ($force_https = $RCMAIL->config->get('force_https', false))) { |
| | | $https_port = is_bool($force_https) ? 443 : $force_https; |
| | | if (!rcube_ui::https_check($https_port)) { |
| | | if (!rcube_utils::https_check($https_port)) { |
| | | $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']); |
| | | $host .= ($https_port != 443 ? ':' . $https_port : ''); |
| | | header('Location: https://' . $host . $_SERVER['REQUEST_URI']); |
| | |
| | | |
| | | // try to log in |
| | | if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { |
| | | $request_valid = $_SESSION['temp'] && $RCMAIL->check_request(rcube_ui::INPUT_POST, 'login'); |
| | | $request_valid = $_SESSION['temp'] && $RCMAIL->check_request(rcube_utils::INPUT_POST, 'login'); |
| | | |
| | | // purge the session in case of new login when a session already exists |
| | | $RCMAIL->kill_session(); |
| | | |
| | | $auth = $RCMAIL->plugins->exec_hook('authenticate', array( |
| | | 'host' => $RCMAIL->autoselect_host(), |
| | | 'user' => trim(rcube_ui::get_input_value('_user', rcube_ui::INPUT_POST)), |
| | | 'pass' => rcube_ui::get_input_value('_pass', rcube_ui::INPUT_POST, true, |
| | | 'user' => trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)), |
| | | 'pass' => rcube_utils::get_input_value('_pass', rcube_utils::INPUT_POST, true, |
| | | $RCMAIL->config->get('password_charset', 'ISO-8859-1')), |
| | | 'cookiecheck' => true, |
| | | 'valid' => $request_valid, |
| | |
| | | |
| | | // restore original request parameters |
| | | $query = array(); |
| | | if ($url = rcube_ui::get_input_value('_url', rcube_ui::INPUT_POST)) { |
| | | if ($url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST)) { |
| | | parse_str($url, $query); |
| | | |
| | | // prevent endless looping on login page |
| | |
| | | // not logged in -> show login page |
| | | if (empty($RCMAIL->user->ID)) { |
| | | // log session failures |
| | | $task = rcube_ui::get_input_value('_task', rcube_ui::INPUT_GPC); |
| | | $task = rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC); |
| | | if ($task && !in_array($task, array('login','logout')) && !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])) { |
| | | $RCMAIL->session->log("Aborted session " . $sess_id . "; no valid session data found"); |
| | | $session_error = true; |
| | |
| | | |
| | | // check client X-header to verify request origin |
| | | if ($OUTPUT->ajax_call) { |
| | | if (rcube_request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) { |
| | | if (rcube_utils::request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) { |
| | | header('HTTP/1.1 403 Forbidden'); |
| | | die("Invalid Request"); |
| | | } |
| | |
| | | |
| | | |
| | | // if we arrive here, something went wrong |
| | | raise_error(array( |
| | | rcmail::raise_error(array( |
| | | 'code' => 404, |
| | | 'type' => 'php', |
| | | 'line' => __LINE__, |
| | |
| | | require_once 'utils.php'; |
| | | require_once 'rcube_shared.inc'; |
| | | // deprecated aliases (to be removed) |
| | | require_once 'main.inc'; |
| | | require_once 'rcube_bc.inc'; |
| | | |
| | | session_start(); |
| | | |
| | |
| | | // application constants |
| | | define('RCMAIL_VERSION', '0.9-svn'); |
| | | define('RCMAIL_CHARSET', 'UTF-8'); |
| | | define('JS_OBJECT_NAME', 'rcmail'); |
| | | define('RCMAIL_START', microtime(true)); |
| | | |
| | | if (!defined('INSTALL_PATH')) { |
| | |
| | | PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error'); |
| | | |
| | | // backward compatybility (to be removed) |
| | | require_once INSTALL_PATH . 'program/include/main.inc'; |
| | | require_once INSTALL_PATH . 'program/include/rcube_bc.inc'; |
| | |
| | | | instances of all 'global' objects like db- and imap-connections | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | |
| | | private $action_map = array(); |
| | | |
| | | |
| | | const JS_OBJECT_NAME = 'rcmail'; |
| | | |
| | | /** |
| | | * This implements the 'singleton' design pattern |
| | | * |
| | |
| | | $this->session_configure(); |
| | | |
| | | // set task and action properties |
| | | $this->set_task(rcube_ui::get_input_value('_task', rcube_ui::INPUT_GPC)); |
| | | $this->action = asciiwords(rcube_ui::get_input_value('_action', rcube_ui::INPUT_GPC)); |
| | | $this->set_task(rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC)); |
| | | $this->action = asciiwords(rcube_utils::get_input_value('_action', rcube_utils::INPUT_GPC)); |
| | | |
| | | // reset some session parameters when changing task |
| | | if ($this->task != 'utils') { |
| | |
| | | ini_set('session.gc_maxlifetime', $lifetime * 2); |
| | | } |
| | | |
| | | ini_set('session.cookie_secure', rcube_ui::https_check()); |
| | | ini_set('session.cookie_secure', rcube_utils::https_check()); |
| | | ini_set('session.name', $sess_name ? $sess_name : 'roundcube_sessid'); |
| | | ini_set('session.use_cookies', 1); |
| | | ini_set('session.use_only_cookies', 1); |
| | |
| | | if (!$allowed) |
| | | return false; |
| | | } |
| | | else if (!empty($config['default_host']) && $host != self::parse_host($config['default_host'])) |
| | | else if (!empty($config['default_host']) && $host != rcube_utils::parse_host($config['default_host'])) |
| | | return false; |
| | | |
| | | // parse $host URL |
| | |
| | | // 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 .= '@'.self::parse_host($config['username_domain'][$host], $host); |
| | | $username .= '@'.rcube_utils::parse_host($config['username_domain'][$host], $host); |
| | | else if (is_string($config['username_domain'])) |
| | | $username .= '@'.self::parse_host($config['username_domain'], $host); |
| | | $username .= '@'.rcube_utils::parse_host($config['username_domain'], $host); |
| | | } |
| | | |
| | | // Convert username to lowercase. If storage backend |
| | |
| | | |
| | | // Here we need IDNA ASCII |
| | | // Only rcube_contacts class is using domain names in Unicode |
| | | $host = rcube_idn_to_ascii($host); |
| | | $host = rcube_utils::idn_to_ascii($host); |
| | | if (strpos($username, '@')) { |
| | | // lowercase domain name |
| | | list($local, $domain) = explode('@', $username); |
| | | $username = $local . '@' . mb_strtolower($domain); |
| | | $username = rcube_idn_to_ascii($username); |
| | | $username = rcube_utils::idn_to_ascii($username); |
| | | } |
| | | |
| | | // user already registered -> overwrite username |
| | | if ($user = rcube_user::query($username, $host)) |
| | | $username = $user->data['username']; |
| | | |
| | | if (!$this->storage) |
| | | $this->storage_init(); |
| | | $storage = $this->get_storage(); |
| | | |
| | | // try to log in |
| | | if (!($login = $this->storage->connect($host, $username, $pass, $port, $ssl))) { |
| | | if (!($login = $storage->connect($host, $username, $pass, $port, $ssl))) { |
| | | // try with lowercase |
| | | $username_lc = mb_strtolower($username); |
| | | if ($username_lc != $username) { |
| | |
| | | if (!$user && ($user = rcube_user::query($username_lc, $host))) |
| | | $username_lc = $user->data['username']; |
| | | |
| | | if ($login = $this->storage->connect($host, $username_lc, $pass, $port, $ssl)) |
| | | if ($login = $storage->connect($host, $username_lc, $pass, $port, $ssl)) |
| | | $username = $username_lc; |
| | | } |
| | | } |
| | |
| | | |
| | | // create default folders on first login |
| | | if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) { |
| | | $this->storage->create_default_folders(); |
| | | $storage->create_default_folders(); |
| | | } |
| | | |
| | | // set session vars |
| | |
| | | $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']); |
| | | |
| | | // force reloading complete list of subscribed mailboxes |
| | | $this->storage->clear_cache('mailboxes', true); |
| | | $storage->clear_cache('mailboxes', true); |
| | | |
| | | return true; |
| | | } |
| | |
| | | $host = null; |
| | | |
| | | if (is_array($default_host)) { |
| | | $post_host = rcube_ui::get_input_value('_host', rcube_ui::INPUT_POST); |
| | | $post_host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST); |
| | | |
| | | // direct match in default_host array |
| | | if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) { |
| | |
| | | } |
| | | |
| | | // try to select host by mail domain |
| | | list($user, $domain) = explode('@', rcube_ui::get_input_value('_user', rcube_ui::INPUT_POST)); |
| | | list($user, $domain) = explode('@', rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)); |
| | | if (!empty($domain)) { |
| | | foreach ($default_host as $storage_host => $mail_domains) { |
| | | if (is_array($mail_domains) && in_array_nocase($domain, $mail_domains)) { |
| | |
| | | } |
| | | } |
| | | else if (empty($default_host)) { |
| | | $host = rcube_ui::get_input_value('_host', rcube_ui::INPUT_POST); |
| | | $host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST); |
| | | } |
| | | else |
| | | $host = self::parse_host($default_host); |
| | | $host = rcube_utils::parse_host($default_host); |
| | | |
| | | return $host; |
| | | } |
| | |
| | | */ |
| | | public function logout_actions() |
| | | { |
| | | $config = $this->config->all(); |
| | | |
| | | // on logout action we're not connected to imap server |
| | | if (($config['logout_purge'] && !empty($config['trash_mbox'])) || $config['logout_expunge']) { |
| | | if (!$this->session->check_auth()) |
| | | return; |
| | | |
| | | $this->storage_connect(); |
| | | } |
| | | $config = $this->config->all(); |
| | | $storage = $this->get_storage(); |
| | | |
| | | if ($config['logout_purge'] && !empty($config['trash_mbox'])) { |
| | | $this->storage->clear_folder($config['trash_mbox']); |
| | | $storage->clear_folder($config['trash_mbox']); |
| | | } |
| | | |
| | | if ($config['logout_expunge']) { |
| | | $this->storage->expunge_folder('INBOX'); |
| | | $storage->expunge_folder('INBOX'); |
| | | } |
| | | |
| | | // Try to save unsaved user preferences |
| | |
| | | { |
| | | $sess_id = $_COOKIE[ini_get('session.name')]; |
| | | if (!$sess_id) $sess_id = session_id(); |
| | | $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->get_user_id() . $this->config->get('des_key') . $sess_id))); |
| | | |
| | | $plugin = $this->plugins->exec_hook('request_token', array( |
| | | 'value' => md5('RT' . $this->get_user_id() . $this->config->get('des_key') . $sess_id))); |
| | | |
| | | return $plugin['value']; |
| | | } |
| | | |
| | |
| | | * @param int Request method |
| | | * @return boolean True if request token is valid false if not |
| | | */ |
| | | public function check_request($mode = rcube_ui::INPUT_POST) |
| | | public function check_request($mode = rcube_utils::INPUT_POST) |
| | | { |
| | | $token = rcube_ui::get_input_value('_token', $mode); |
| | | $token = rcube_utils::get_input_value('_token', $mode); |
| | | $sess_id = $_COOKIE[ini_get('session.name')]; |
| | | return !empty($sess_id) && $token == $this->get_request_token(); |
| | | } |
| | |
| | | * Build a valid URL to this instance of Roundcube |
| | | * |
| | | * @param mixed Either a string with the action or url parameters as key-value pairs |
| | | * |
| | | * @return string Valid application URL |
| | | */ |
| | | public function url($p) |
| | |
| | | // write performance stats to logs/console |
| | | if ($this->config->get('devel_mode')) { |
| | | if (function_exists('memory_get_usage')) |
| | | $mem = rcube_ui::show_bytes(memory_get_usage()); |
| | | $mem = $this->show_bytes(memory_get_usage()); |
| | | if (function_exists('memory_get_peak_usage')) |
| | | $mem .= '/'.rcube_ui::show_bytes(memory_get_peak_usage()); |
| | | $mem .= '/'.$this->show_bytes(memory_get_peak_usage()); |
| | | |
| | | $log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : ''); |
| | | if (defined('RCMAIL_START')) |
| | |
| | | else |
| | | self::console($log); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Helper method to set a cookie with the current path and host settings |
| | | * |
| | | * @param string Cookie name |
| | | * @param string Cookie value |
| | | * @param string Expiration time |
| | | */ |
| | | public static function setcookie($name, $value, $exp = 0) |
| | | { |
| | | if (headers_sent()) |
| | | return; |
| | | |
| | | $cookie = session_get_cookie_params(); |
| | | |
| | | setcookie($name, $value, $exp, $cookie['path'], $cookie['domain'], |
| | | rcube_ui::https_check(), true); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | |
| | | /** |
| | | * E-mail address validation. |
| | | * |
| | | * @param string $email Email address |
| | | * @param boolean $dns_check True to check dns |
| | | * |
| | | * @return boolean True on success, False if address is invalid |
| | | */ |
| | | public function check_email($email, $dns_check=true) |
| | | { |
| | | // Check for invalid characters |
| | | if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $email)) { |
| | | return false; |
| | | } |
| | | |
| | | // Check for length limit specified by RFC 5321 (#1486453) |
| | | if (strlen($email) > 254) { |
| | | return false; |
| | | } |
| | | |
| | | $email_array = explode('@', $email); |
| | | |
| | | // Check that there's one @ symbol |
| | | if (count($email_array) < 2) { |
| | | return false; |
| | | } |
| | | |
| | | $domain_part = array_pop($email_array); |
| | | $local_part = implode('@', $email_array); |
| | | |
| | | // from PEAR::Validate |
| | | $regexp = '&^(?: |
| | | ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| #1 quoted name |
| | | ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) #2 OR dot-atom (RFC5322) |
| | | $&xi'; |
| | | |
| | | if (!preg_match($regexp, $local_part)) { |
| | | return false; |
| | | } |
| | | |
| | | // Check domain part |
| | | if (preg_match('/^\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]*$/', $domain_part)) { |
| | | return true; // IP address |
| | | } |
| | | else { |
| | | // If not an IP address |
| | | $domain_array = explode('.', $domain_part); |
| | | // Not enough parts to be a valid domain |
| | | if (sizeof($domain_array) < 2) { |
| | | return false; |
| | | } |
| | | |
| | | foreach ($domain_array as $part) { |
| | | if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | if (!$dns_check || !$this->config->get('email_dns_check')) { |
| | | return true; |
| | | } |
| | | |
| | | if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) { |
| | | $lookup = array(); |
| | | @exec("nslookup -type=MX " . escapeshellarg($domain_part) . " 2>&1", $lookup); |
| | | foreach ($lookup as $line) { |
| | | if (strpos($line, 'MX preference')) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // find MX record(s) |
| | | if (getmxrr($domain_part, $mx_records)) { |
| | | return true; |
| | | } |
| | | |
| | | // find any DNS record |
| | | if (checkdnsrr($domain_part, 'ANY')) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Write login data (name, ID, IP address) to the 'userlogins' log file. |
| | | */ |
| | | public function log_login() |
| | |
| | | |
| | | self::write_log('userlogins', |
| | | sprintf('Successful login for %s (ID: %d) from %s in session %s', |
| | | $user_name, $user_id, self::remote_ip(), session_id())); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check whether the HTTP referer matches the current request |
| | | * |
| | | * @return boolean True if referer is the same host+path, false if not |
| | | */ |
| | | public static function check_referer() |
| | | { |
| | | $uri = parse_url($_SERVER['REQUEST_URI']); |
| | | $referer = parse_url(rcube_request_header('Referer')); |
| | | return $referer['host'] == rcube_request_header('Host') && $referer['path'] == $uri['path']; |
| | | $user_name, $user_id, rcube_utils::remote_ip(), session_id())); |
| | | } |
| | | |
| | | |
| | |
| | | $tmp = unslashify($this->config->get('temp_dir')); |
| | | $expire = mktime() - 172800; // expire in 48 hours |
| | | |
| | | if ($dir = opendir($tmp)) { |
| | | if ($tmp && ($dir = opendir($tmp))) { |
| | | while (($fname = readdir($dir)) !== false) { |
| | | if ($fname{0} == '.') { |
| | | continue; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a HTML table based on the given data |
| | | * |
| | | * @param array Named table attributes |
| | | * @param mixed Table row data. Either a two-dimensional array or a valid SQL result set |
| | | * @param array List of cols to show |
| | | * @param string Name of the identifier col |
| | | * |
| | | * @return string HTML table code |
| | | */ |
| | | public function table_output($attrib, $table_data, $a_show_cols, $id_col) |
| | | { |
| | | $table = new html_table(/*array('cols' => count($a_show_cols))*/); |
| | | |
| | | // add table header |
| | | if (!$attrib['noheader']) { |
| | | foreach ($a_show_cols as $col) { |
| | | $table->add_header($col, $this->Q($this->gettext($col))); |
| | | } |
| | | } |
| | | |
| | | if (!is_array($table_data)) { |
| | | $db = $this->get_dbh(); |
| | | while ($table_data && ($sql_arr = $db->fetch_assoc($table_data))) { |
| | | $table->add_row(array('id' => 'rcmrow' . rcube_utils::html_identifier($sql_arr[$id_col]))); |
| | | |
| | | // format each col |
| | | foreach ($a_show_cols as $col) { |
| | | $table->add($col, $this->Q($sql_arr[$col])); |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | foreach ($table_data as $row_data) { |
| | | $class = !empty($row_data['class']) ? $row_data['class'] : ''; |
| | | $rowid = 'rcmrow' . rcube_utils::html_identifier($row_data[$id_col]); |
| | | |
| | | $table->add_row(array('id' => $rowid, 'class' => $class)); |
| | | |
| | | // format each col |
| | | foreach ($a_show_cols as $col) { |
| | | $table->add($col, $this->Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col])); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $table->show($attrib); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert the given date to a human readable form |
| | | * This uses the date formatting properties from config |
| | | * |
| | | * @param mixed Date representation (string, timestamp or DateTime object) |
| | | * @param string Date format to use |
| | | * @param bool Enables date convertion according to user timezone |
| | | * |
| | | * @return string Formatted date string |
| | | */ |
| | | public function format_date($date, $format = null, $convert = true) |
| | | { |
| | | if (is_object($date) && is_a($date, 'DateTime')) { |
| | | $timestamp = $date->format('U'); |
| | | } |
| | | else { |
| | | if (!empty($date)) { |
| | | $timestamp = rcube_strtotime($date); |
| | | } |
| | | |
| | | if (empty($timestamp)) { |
| | | return ''; |
| | | } |
| | | |
| | | try { |
| | | $date = new DateTime("@".$timestamp); |
| | | } |
| | | catch (Exception $e) { |
| | | return ''; |
| | | } |
| | | } |
| | | |
| | | if ($convert) { |
| | | try { |
| | | // convert to the right timezone |
| | | $stz = date_default_timezone_get(); |
| | | $tz = new DateTimeZone($this->config->get('timezone')); |
| | | $date->setTimezone($tz); |
| | | date_default_timezone_set($tz->getName()); |
| | | |
| | | $timestamp = $date->format('U'); |
| | | } |
| | | catch (Exception $e) { |
| | | } |
| | | } |
| | | |
| | | // define date format depending on current time |
| | | if (!$format) { |
| | | $now = time(); |
| | | $now_date = getdate($now); |
| | | $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']); |
| | | $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); |
| | | $pretty_date = $this->config->get('prettydate'); |
| | | |
| | | if ($pretty_date && $timestamp > $today_limit && $timestamp < $now) { |
| | | $format = $this->config->get('date_today', $this->config->get('time_format', 'H:i')); |
| | | $today = true; |
| | | } |
| | | else if ($pretty_date && $timestamp > $week_limit && $timestamp < $now) { |
| | | $format = $this->config->get('date_short', 'D H:i'); |
| | | } |
| | | else { |
| | | $format = $this->config->get('date_long', 'Y-m-d H:i'); |
| | | } |
| | | } |
| | | |
| | | // strftime() format |
| | | if (preg_match('/%[a-z]+/i', $format)) { |
| | | $format = strftime($format, $timestamp); |
| | | if ($stz) { |
| | | date_default_timezone_set($stz); |
| | | } |
| | | return $today ? ($this->gettext('today') . ' ' . $format) : $format; |
| | | } |
| | | |
| | | // parse format string manually in order to provide localized weekday and month names |
| | | // an alternative would be to convert the date() format string to fit with strftime() |
| | | $out = ''; |
| | | for ($i=0; $i<strlen($format); $i++) { |
| | | if ($format[$i] == "\\") { // skip escape chars |
| | | continue; |
| | | } |
| | | |
| | | // write char "as-is" |
| | | if ($format[$i] == ' ' || $format[$i-1] == "\\") { |
| | | $out .= $format[$i]; |
| | | } |
| | | // weekday (short) |
| | | else if ($format[$i] == 'D') { |
| | | $out .= $this->gettext(strtolower(date('D', $timestamp))); |
| | | } |
| | | // weekday long |
| | | else if ($format[$i] == 'l') { |
| | | $out .= $this->gettext(strtolower(date('l', $timestamp))); |
| | | } |
| | | // month name (short) |
| | | else if ($format[$i] == 'M') { |
| | | $out .= $this->gettext(strtolower(date('M', $timestamp))); |
| | | } |
| | | // month name (long) |
| | | else if ($format[$i] == 'F') { |
| | | $out .= $this->gettext('long'.strtolower(date('M', $timestamp))); |
| | | } |
| | | else if ($format[$i] == 'x') { |
| | | $out .= strftime('%x %X', $timestamp); |
| | | } |
| | | else { |
| | | $out .= date($format[$i], $timestamp); |
| | | } |
| | | } |
| | | |
| | | if ($today) { |
| | | $label = $this->gettext('today'); |
| | | // replcae $ character with "Today" label (#1486120) |
| | | if (strpos($out, '$') !== false) { |
| | | $out = preg_replace('/\$/', $label, $out, 1); |
| | | } |
| | | else { |
| | | $out = $label . ' ' . $out; |
| | | } |
| | | } |
| | | |
| | | if ($stz) { |
| | | date_default_timezone_set($stz); |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return folders list in HTML |
| | | * |
| | | * @param array $attrib Named parameters |
| | | * |
| | | * @return string HTML code for the gui object |
| | | */ |
| | | public function folder_list($attrib) |
| | | { |
| | | static $a_mailboxes; |
| | | |
| | | $attrib += array('maxlength' => 100, 'realnames' => false, 'unreadwrap' => ' (%s)'); |
| | | |
| | | $rcmail = rcmail::get_instance(); |
| | | $storage = $rcmail->get_storage(); |
| | | |
| | | // add some labels to client |
| | | $rcmail->output->add_label('purgefolderconfirm', 'deletemessagesconfirm'); |
| | | |
| | | $type = $attrib['type'] ? $attrib['type'] : 'ul'; |
| | | unset($attrib['type']); |
| | | |
| | | if ($type == 'ul' && !$attrib['id']) { |
| | | $attrib['id'] = 'rcmboxlist'; |
| | | } |
| | | |
| | | if (empty($attrib['folder_name'])) { |
| | | $attrib['folder_name'] = '*'; |
| | | } |
| | | |
| | | // get current folder |
| | | $mbox_name = $storage->get_folder(); |
| | | |
| | | // build the folders tree |
| | | if (empty($a_mailboxes)) { |
| | | // get mailbox list |
| | | $a_folders = $storage->list_folders_subscribed( |
| | | '', $attrib['folder_name'], $attrib['folder_filter']); |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | $a_mailboxes = array(); |
| | | |
| | | foreach ($a_folders as $folder) { |
| | | $rcmail->build_folder_tree($a_mailboxes, $folder, $delimiter); |
| | | } |
| | | } |
| | | |
| | | // allow plugins to alter the folder tree or to localize folder names |
| | | $hook = $rcmail->plugins->exec_hook('render_mailboxlist', array( |
| | | 'list' => $a_mailboxes, |
| | | 'delimiter' => $delimiter, |
| | | 'type' => $type, |
| | | 'attribs' => $attrib, |
| | | )); |
| | | |
| | | $a_mailboxes = $hook['list']; |
| | | $attrib = $hook['attribs']; |
| | | |
| | | if ($type == 'select') { |
| | | $select = new html_select($attrib); |
| | | |
| | | // add no-selection option |
| | | if ($attrib['noselection']) { |
| | | $select->add($rcmail->gettext($attrib['noselection']), ''); |
| | | } |
| | | |
| | | $rcmail->render_folder_tree_select($a_mailboxes, $mbox_name, $attrib['maxlength'], $select, $attrib['realnames']); |
| | | $out = $select->show($attrib['default']); |
| | | } |
| | | else { |
| | | $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->add_gui_object('mailboxlist', $attrib['id']); |
| | | $rcmail->output->set_env('mailboxes', $js_mailboxlist); |
| | | $rcmail->output->set_env('unreadwrap', $attrib['unreadwrap']); |
| | | $rcmail->output->set_env('collapsed_folders', (string)$rcmail->config->get('collapsed_folders')); |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return folders list as html_select object |
| | | * |
| | | * @param array $p Named parameters |
| | | * |
| | | * @return html_select HTML drop-down object |
| | | */ |
| | | public function folder_selector($p = array()) |
| | | { |
| | | $p += array('maxlength' => 100, 'realnames' => false); |
| | | $a_mailboxes = array(); |
| | | $storage = $this->get_storage(); |
| | | |
| | | if (empty($p['folder_name'])) { |
| | | $p['folder_name'] = '*'; |
| | | } |
| | | |
| | | if ($p['unsubscribed']) { |
| | | $list = $storage->list_folders('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | } |
| | | else { |
| | | $list = $storage->list_folders_subscribed('', $p['folder_name'], $p['folder_filter'], $p['folder_rights']); |
| | | } |
| | | |
| | | $delimiter = $storage->get_hierarchy_delimiter(); |
| | | |
| | | foreach ($list as $folder) { |
| | | if (empty($p['exceptions']) || !in_array($folder, $p['exceptions'])) { |
| | | $this->build_folder_tree($a_mailboxes, $folder, $delimiter); |
| | | } |
| | | } |
| | | |
| | | $select = new html_select($p); |
| | | |
| | | if ($p['noselection']) { |
| | | $select->add($p['noselection'], ''); |
| | | } |
| | | |
| | | $this->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p); |
| | | |
| | | return $select; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a hierarchical array of the mailbox list |
| | | */ |
| | | public function build_folder_tree(&$arrFolders, $folder, $delm = '/', $path = '') |
| | | { |
| | | // Handle namespace prefix |
| | | $prefix = ''; |
| | | if (!$path) { |
| | | $n_folder = $folder; |
| | | $folder = $this->storage->mod_folder($folder); |
| | | |
| | | if ($n_folder != $folder) { |
| | | $prefix = substr($n_folder, 0, -strlen($folder)); |
| | | } |
| | | } |
| | | |
| | | $pos = strpos($folder, $delm); |
| | | |
| | | if ($pos !== false) { |
| | | $subFolders = substr($folder, $pos+1); |
| | | $currentFolder = substr($folder, 0, $pos); |
| | | |
| | | // sometimes folder has a delimiter as the last character |
| | | if (!strlen($subFolders)) { |
| | | $virtual = false; |
| | | } |
| | | else if (!isset($arrFolders[$currentFolder])) { |
| | | $virtual = true; |
| | | } |
| | | else { |
| | | $virtual = $arrFolders[$currentFolder]['virtual']; |
| | | } |
| | | } |
| | | else { |
| | | $subFolders = false; |
| | | $currentFolder = $folder; |
| | | $virtual = false; |
| | | } |
| | | |
| | | $path .= $prefix . $currentFolder; |
| | | |
| | | if (!isset($arrFolders[$currentFolder])) { |
| | | $arrFolders[$currentFolder] = array( |
| | | 'id' => $path, |
| | | 'name' => rcube_charset::convert($currentFolder, 'UTF7-IMAP'), |
| | | 'virtual' => $virtual, |
| | | 'folders' => array()); |
| | | } |
| | | else { |
| | | $arrFolders[$currentFolder]['virtual'] = $virtual; |
| | | } |
| | | |
| | | if (strlen($subFolders)) { |
| | | $this->build_folder_tree($arrFolders[$currentFolder]['folders'], $subFolders, $delm, $path.$delm); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return html for a structured list <ul> for the mailbox tree |
| | | */ |
| | | public function render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $attrib, $nestLevel = 0) |
| | | { |
| | | $maxlength = intval($attrib['maxlength']); |
| | | $realnames = (bool)$attrib['realnames']; |
| | | $msgcounts = $this->storage->get_cache('messagecount'); |
| | | $collapsed = $this->config->get('collapsed_folders'); |
| | | |
| | | $out = ''; |
| | | foreach ($arrFolders as $key => $folder) { |
| | | $title = null; |
| | | $folder_class = $this->folder_classname($folder['id']); |
| | | $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false; |
| | | $unread = $msgcounts ? intval($msgcounts[$folder['id']]['UNSEEN']) : 0; |
| | | |
| | | if ($folder_class && !$realnames) { |
| | | $foldername = $this->gettext($folder_class); |
| | | } |
| | | else { |
| | | $foldername = $folder['name']; |
| | | |
| | | // shorten the folder name to a given length |
| | | if ($maxlength && $maxlength > 1) { |
| | | $fname = abbreviate_string($foldername, $maxlength); |
| | | if ($fname != $foldername) { |
| | | $title = $foldername; |
| | | } |
| | | $foldername = $fname; |
| | | } |
| | | } |
| | | |
| | | // make folder name safe for ids and class names |
| | | $folder_id = rcube_utils::html_identifier($folder['id'], true); |
| | | $classes = array('mailbox'); |
| | | |
| | | // set special class for Sent, Drafts, Trash and Junk |
| | | if ($folder_class) { |
| | | $classes[] = $folder_class; |
| | | } |
| | | |
| | | if ($folder['id'] == $mbox_name) { |
| | | $classes[] = 'selected'; |
| | | } |
| | | |
| | | if ($folder['virtual']) { |
| | | $classes[] = 'virtual'; |
| | | } |
| | | else if ($unread) { |
| | | $classes[] = 'unread'; |
| | | } |
| | | |
| | | $js_name = $this->JQ($folder['id']); |
| | | $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount', sprintf($attrib['unreadwrap'], $unread)) : ''); |
| | | $link_attrib = $folder['virtual'] ? array() : array( |
| | | 'href' => $this->url(array('_mbox' => $folder['id'])), |
| | | 'onclick' => sprintf("return %s.command('list','%s',this)", rcmail::JS_OBJECT_NAME, $js_name), |
| | | 'rel' => $folder['id'], |
| | | 'title' => $title, |
| | | ); |
| | | |
| | | $out .= html::tag('li', array( |
| | | 'id' => "rcmli".$folder_id, |
| | | 'class' => join(' ', $classes), |
| | | 'noclose' => true), |
| | | 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::JS_OBJECT_NAME, $js_name) |
| | | ), ' ') : '')); |
| | | |
| | | $jslist[$folder_id] = array( |
| | | 'id' => $folder['id'], |
| | | 'name' => $foldername, |
| | | 'virtual' => $folder['virtual'] |
| | | ); |
| | | |
| | | if (!empty($folder['folders'])) { |
| | | $out .= html::tag('ul', array('style' => ($is_collapsed ? "display:none;" : null)), |
| | | $this->render_folder_tree_html($folder['folders'], $mbox_name, $jslist, $attrib, $nestLevel+1)); |
| | | } |
| | | |
| | | $out .= "</li>\n"; |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return html for a flat list <select> for the mailbox tree |
| | | */ |
| | | public function render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames = false, $nestLevel = 0, $opts = array()) |
| | | { |
| | | $out = ''; |
| | | |
| | | foreach ($arrFolders as $key => $folder) { |
| | | // skip exceptions (and its subfolders) |
| | | if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) { |
| | | continue; |
| | | } |
| | | |
| | | // skip folders in which it isn't possible to create subfolders |
| | | if (!empty($opts['skip_noinferiors'])) { |
| | | $attrs = $this->storage->folder_attributes($folder['id']); |
| | | if ($attrs && in_array('\\Noinferiors', $attrs)) { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!$realnames && ($folder_class = $this->folder_classname($folder['id']))) { |
| | | $foldername = $this->gettext($folder_class); |
| | | } |
| | | else { |
| | | $foldername = $folder['name']; |
| | | |
| | | // shorten the folder name to a given length |
| | | if ($maxlength && $maxlength > 1) { |
| | | $foldername = abbreviate_string($foldername, $maxlength); |
| | | } |
| | | |
| | | $select->add(str_repeat(' ', $nestLevel*4) . $foldername, $folder['id']); |
| | | |
| | | if (!empty($folder['folders'])) { |
| | | $out .= $this->render_folder_tree_select($folder['folders'], $mbox_name, $maxlength, |
| | | $select, $realnames, $nestLevel+1, $opts); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Return internal name for the given folder if it matches the configured special folders |
| | | */ |
| | | public function folder_classname($folder_id) |
| | | { |
| | | if ($folder_id == 'INBOX') { |
| | | return 'inbox'; |
| | | } |
| | | |
| | | // for these mailboxes we have localized labels and css classes |
| | | foreach (array('sent', 'drafts', 'trash', 'junk') as $smbx) |
| | | { |
| | | if ($folder_id === $this->config->get($smbx.'_mbox')) { |
| | | return $smbx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Try to localize the given IMAP folder name. |
| | | * UTF-7 decode it in case no localized text was found |
| | | * |
| | | * @param string $name Folder name |
| | | * |
| | | * @return string Localized folder name in UTF-8 encoding |
| | | */ |
| | | public function localize_foldername($name) |
| | | { |
| | | if ($folder_class = $this->folder_classname($name)) { |
| | | return $this->gettext($folder_class); |
| | | } |
| | | else { |
| | | return rcube_charset::convert($name, 'UTF7-IMAP'); |
| | | } |
| | | } |
| | | |
| | | |
| | | public function localize_folderpath($path) |
| | | { |
| | | $protect_folders = $this->config->get('protect_default_folders'); |
| | | $default_folders = (array) $this->config->get('default_folders'); |
| | | $delimiter = $this->storage->get_hierarchy_delimiter(); |
| | | $path = explode($delimiter, $path); |
| | | $result = array(); |
| | | |
| | | foreach ($path as $idx => $dir) { |
| | | $directory = implode($delimiter, array_slice($path, 0, $idx+1)); |
| | | if ($protect_folders && in_array($directory, $default_folders)) { |
| | | unset($result); |
| | | $result[] = $this->localize_foldername($directory); |
| | | } |
| | | else { |
| | | $result[] = rcube_charset::convert($dir, 'UTF7-IMAP'); |
| | | } |
| | | } |
| | | |
| | | return implode($delimiter, $result); |
| | | } |
| | | |
| | | |
| | | public static function quota_display($attrib) |
| | | { |
| | | $rcmail = rcmail::get_instance(); |
| | | |
| | | if (!$attrib['id']) { |
| | | $attrib['id'] = 'rcmquotadisplay'; |
| | | } |
| | | |
| | | $_SESSION['quota_display'] = !empty($attrib['display']) ? $attrib['display'] : 'text'; |
| | | |
| | | $rcmail->output->add_gui_object('quotadisplay', $attrib['id']); |
| | | |
| | | $quota = $rcmail->quota_content($attrib); |
| | | |
| | | $rcmail->output->add_script('rcmail.set_quota('.rcube_output::json_serialize($quota).');', 'docready'); |
| | | |
| | | return html::span($attrib, ''); |
| | | } |
| | | |
| | | |
| | | public function quota_content($attrib = null) |
| | | { |
| | | $quota = $this->storage->get_quota(); |
| | | $quota = $this->plugins->exec_hook('quota', $quota); |
| | | |
| | | $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 (!isset($quota['percent'])) { |
| | | $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100)); |
| | | } |
| | | |
| | | $title = sprintf('%s / %s (%.0f%%)', |
| | | $this->show_bytes($quota['used'] * 1024), $this->show_bytes($quota['total'] * 1024), |
| | | $quota_result['percent']); |
| | | |
| | | $quota_result['title'] = $title; |
| | | |
| | | if ($attrib['width']) { |
| | | $quota_result['width'] = $attrib['width']; |
| | | } |
| | | if ($attrib['height']) { |
| | | $quota_result['height'] = $attrib['height']; |
| | | } |
| | | } |
| | | else { |
| | | $quota_result['title'] = $this->gettext('unknown'); |
| | | $quota_result['percent'] = 0; |
| | | } |
| | | |
| | | return $quota_result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Outputs error message according to server error/response codes |
| | | * |
| | | * @param string $fallback Fallback message label |
| | | * @param array $fallback_args Fallback message label arguments |
| | | */ |
| | | public function display_server_error($fallback = null, $fallback_args = null) |
| | | { |
| | | $err_code = $this->storage->get_error_code(); |
| | | $res_code = $this->storage->get_response_code(); |
| | | |
| | | if ($err_code < 0) { |
| | | $this->output->show_message('storageerror', 'error'); |
| | | } |
| | | else if ($res_code == rcube_storage::NOPERM) { |
| | | $this->output->show_message('errornoperm', 'error'); |
| | | } |
| | | else if ($res_code == rcube_storage::READONLY) { |
| | | $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) { |
| | | $this->output->show_message('errornoperm', 'error'); |
| | | } |
| | | else { |
| | | $this->output->show_message('servererrormsg', 'error', array('msg' => $err_str)); |
| | | } |
| | | } |
| | | else if ($fallback) { |
| | | $this->output->show_message($fallback, 'error', $fallback_args); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Output HTML editor scripts |
| | | * |
| | | * @param string $mode Editor mode |
| | | */ |
| | | public function html_editor($mode = '') |
| | | { |
| | | $hook = $this->plugins->exec_hook('html_editor', array('mode' => $mode)); |
| | | |
| | | if ($hook['abort']) { |
| | | return; |
| | | } |
| | | |
| | | $lang = strtolower($_SESSION['language']); |
| | | |
| | | // TinyMCE uses two-letter lang codes, with exception of Chinese |
| | | if (strpos($lang, 'zh_') === 0) { |
| | | $lang = str_replace('_', '-', $lang); |
| | | } |
| | | else { |
| | | $lang = substr($lang, 0, 2); |
| | | } |
| | | |
| | | if (!file_exists(INSTALL_PATH . 'program/js/tiny_mce/langs/'.$lang.'.js')) { |
| | | $lang = 'en'; |
| | | } |
| | | |
| | | $script = json_encode(array( |
| | | 'mode' => $mode, |
| | | 'lang' => $lang, |
| | | 'skin_path' => $this->output->get_skin_path(), |
| | | 'spellcheck' => intval($this->config->get('enable_spellcheck')), |
| | | 'spelldict' => intval($this->config->get('spellcheck_dictionary')) |
| | | )); |
| | | |
| | | $this->output->include_script('tiny_mce/tiny_mce.js'); |
| | | $this->output->include_script('editor.js'); |
| | | $this->output->add_script("rcmail_editor_init($script)", 'docready'); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replaces TinyMCE's emoticon images with plain-text representation |
| | | * |
| | | * @param string $html HTML content |
| | | * |
| | | * @return string HTML content |
| | | */ |
| | | public static function replace_emoticons($html) |
| | | { |
| | | $emoticons = array( |
| | | '8-)' => 'smiley-cool', |
| | | ':-#' => 'smiley-foot-in-mouth', |
| | | ':-*' => 'smiley-kiss', |
| | | ':-X' => 'smiley-sealed', |
| | | ':-P' => 'smiley-tongue-out', |
| | | ':-@' => 'smiley-yell', |
| | | ":'(" => 'smiley-cry', |
| | | ':-(' => 'smiley-frown', |
| | | ':-D' => 'smiley-laughing', |
| | | ':-)' => 'smiley-smile', |
| | | ':-S' => 'smiley-undecided', |
| | | ':-$' => 'smiley-embarassed', |
| | | 'O:-)' => 'smiley-innocent', |
| | | ':-|' => 'smiley-money-mouth', |
| | | ':-O' => 'smiley-surprised', |
| | | ';-)' => 'smiley-wink', |
| | | ); |
| | | |
| | | foreach ($emoticons as $idx => $file) { |
| | | // <img title="Cry" src="http://.../program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif" border="0" alt="Cry" /> |
| | | $search[] = '/<img title="[a-z ]+" src="https?:\/\/[a-z0-9_.\/-]+\/tiny_mce\/plugins\/emotions\/img\/'.$file.'.gif"[^>]+\/>/i'; |
| | | $replace[] = $idx; |
| | | } |
| | | |
| | | return preg_replace($search, $replace, $html); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * File upload progress handler. |
| | | */ |
| | | public function upload_progress() |
| | | { |
| | | $prefix = ini_get('apc.rfc1867_prefix'); |
| | | $params = array( |
| | | 'action' => $this->action, |
| | | 'name' => rcube_utils::get_input_value('_progress', rcube_utils::INPUT_GET), |
| | | ); |
| | | |
| | | if (function_exists('apc_fetch')) { |
| | | $status = apc_fetch($prefix . $params['name']); |
| | | |
| | | if (!empty($status)) { |
| | | $status['percent'] = round($status['current']/$status['total']*100); |
| | | $params = array_merge($status, $params); |
| | | } |
| | | } |
| | | |
| | | if (isset($params['percent'])) |
| | | $params['text'] = $this->gettext(array('name' => 'uploadprogress', 'vars' => array( |
| | | 'percent' => $params['percent'] . '%', |
| | | 'current' => $this->show_bytes($params['current']), |
| | | 'total' => $this->show_bytes($params['total']) |
| | | ))); |
| | | |
| | | $this->output->command('upload_progress_update', $params); |
| | | $this->output->send(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initializes file uploading interface. |
| | | */ |
| | | public function upload_init() |
| | | { |
| | | // Enable upload progress bar |
| | | if (($seconds = $this->config->get('upload_progress')) && ini_get('apc.rfc1867')) { |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | // find max filesize value |
| | | $max_filesize = parse_bytes(ini_get('upload_max_filesize')); |
| | | $max_postsize = parse_bytes(ini_get('post_max_size')); |
| | | if ($max_postsize && $max_postsize < $max_filesize) { |
| | | $max_filesize = $max_postsize; |
| | | } |
| | | |
| | | $this->output->set_env('max_filesize', $max_filesize); |
| | | $max_filesize = self::show_bytes($max_filesize); |
| | | $this->output->set_env('filesizeerror', $this->gettext(array( |
| | | 'name' => 'filesizeerror', 'vars' => array('size' => $max_filesize)))); |
| | | |
| | | return $max_filesize; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Initializes client-side autocompletion. |
| | | */ |
| | | public function autocomplete_init() |
| | | { |
| | | static $init; |
| | | |
| | | if ($init) { |
| | | return; |
| | | } |
| | | |
| | | $init = 1; |
| | | |
| | | if (($threads = (int)$this->config->get('autocomplete_threads')) > 0) { |
| | | $book_types = (array) $this->config->get('autocomplete_addressbooks', 'sql'); |
| | | if (count($book_types) > 1) { |
| | | $this->output->set_env('autocomplete_threads', $threads); |
| | | $this->output->set_env('autocomplete_sources', $book_types); |
| | | } |
| | | } |
| | | |
| | | $this->output->set_env('autocomplete_max', (int)$this->config->get('autocomplete_max', 15)); |
| | | $this->output->set_env('autocomplete_min_length', $this->config->get('autocomplete_min_length')); |
| | | $this->output->add_label('autocompletechars', 'autocompletemore'); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns supported font-family specifications |
| | | * |
| | | * @param string $font Font name |
| | | * |
| | | * @param string|array Font-family specification array or string (if $font is used) |
| | | */ |
| | | public static function font_defs($font = null) |
| | | { |
| | | $fonts = array( |
| | | 'Andale Mono' => '"Andale Mono",Times,monospace', |
| | | 'Arial' => 'Arial,Helvetica,sans-serif', |
| | | 'Arial Black' => '"Arial Black","Avant Garde",sans-serif', |
| | | 'Book Antiqua' => '"Book Antiqua",Palatino,serif', |
| | | 'Courier New' => '"Courier New",Courier,monospace', |
| | | 'Georgia' => 'Georgia,Palatino,serif', |
| | | 'Helvetica' => 'Helvetica,Arial,sans-serif', |
| | | 'Impact' => 'Impact,Chicago,sans-serif', |
| | | 'Tahoma' => 'Tahoma,Arial,Helvetica,sans-serif', |
| | | 'Terminal' => 'Terminal,Monaco,monospace', |
| | | 'Times New Roman' => '"Times New Roman",Times,serif', |
| | | 'Trebuchet MS' => '"Trebuchet MS",Geneva,sans-serif', |
| | | 'Verdana' => 'Verdana,Geneva,sans-serif', |
| | | ); |
| | | |
| | | if ($font) { |
| | | return $fonts[$font]; |
| | | } |
| | | |
| | | return $fonts; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a human readable string for a number of bytes |
| | | * |
| | | * @param int Number of bytes |
| | | * |
| | | * @return string Byte string |
| | | */ |
| | | public function show_bytes($bytes) |
| | | { |
| | | if ($bytes >= 1073741824) { |
| | | $gb = $bytes/1073741824; |
| | | $str = sprintf($gb>=10 ? "%d " : "%.1f ", $gb) . $this->gettext('GB'); |
| | | } |
| | | else if ($bytes >= 1048576) { |
| | | $mb = $bytes/1048576; |
| | | $str = sprintf($mb>=10 ? "%d " : "%.1f ", $mb) . $this->gettext('MB'); |
| | | } |
| | | else if ($bytes >= 1024) { |
| | | $str = sprintf("%d ", round($bytes/1024)) . $this->gettext('KB'); |
| | | } |
| | | else { |
| | | $str = sprintf('%d ', $bytes) . $this->gettext('B'); |
| | | } |
| | | |
| | | return $str; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Quote a given string. |
| | | * Shortcut function for rcube_utils::rep_specialchars_output() |
| | | * |
| | | * @return string HTML-quoted string |
| | | */ |
| | | public static function Q($str, $mode = 'strict', $newlines = true) |
| | | { |
| | | return rcube_utils::rep_specialchars_output($str, 'html', $mode, $newlines); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Quote a given string for javascript output. |
| | | * Shortcut function for rcube_utils::rep_specialchars_output() |
| | | * |
| | | * @return string JS-quoted string |
| | | */ |
| | | public static function JQ($str) |
| | | { |
| | | return rcube_utils::rep_specialchars_output($str, 'js'); |
| | | } |
| | | |
| | | |
| | | /************************************************************************ |
| | | ********* Deprecated methods (to be removed) ********* |
| | | ***********************************************************************/ |
| | | |
| | | public static function setcookie($name, $value, $exp = 0) |
| | | { |
| | | rcube_utils::setcookie($name, $value, $exp); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Use imagemagick or GD lib to read image properties |
| | | * |
| | | * @param string Absolute file path |
| | | * @return mixed Hash array with image props like type, width, height or False on error |
| | | */ |
| | | public static function imageprops($filepath) |
| | | { |
| | | $rcube = self::get_instance(); |
| | | if ($cmd = $rcube->config->get('im_identify_path', false)) { |
| | | list(, $type, $size) = explode(' ', strtolower(self::exec($cmd. ' 2>/dev/null {in}', array('in' => $filepath)))); |
| | | if ($size) |
| | | list($width, $height) = explode('x', $size); |
| | | } |
| | | else if (function_exists('getimagesize')) { |
| | | $imsize = @getimagesize($filepath); |
| | | $width = $imsize[0]; |
| | | $height = $imsize[1]; |
| | | $type = preg_replace('!image/!', '', $imsize['mime']); |
| | | } |
| | | |
| | | return $type ? array('type' => $type, 'width' => $width, 'height' => $height) : false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert an image to a given size and type using imagemagick (ensures input is an image) |
| | | * |
| | | * @param $p['in'] Input filename (mandatory) |
| | | * @param $p['out'] Output filename (mandatory) |
| | | * @param $p['size'] Width x height of resulting image, e.g. "160x60" |
| | | * @param $p['type'] Output file type, e.g. "jpg" |
| | | * @param $p['-opts'] Custom command line options to ImageMagick convert |
| | | * @return Success of convert as true/false |
| | | */ |
| | | public static function imageconvert($p) |
| | | { |
| | | $result = false; |
| | | $rcube = self::get_instance(); |
| | | $convert = $rcube->config->get('im_convert_path', false); |
| | | $identify = $rcube->config->get('im_identify_path', false); |
| | | |
| | | // imagemagick is required for this |
| | | if (!$convert) |
| | | return false; |
| | | |
| | | if (!(($imagetype = @exif_imagetype($p['in'])) && ($type = image_type_to_extension($imagetype, false)))) |
| | | list(, $type) = explode(' ', strtolower(self::exec($identify . ' 2>/dev/null {in}', $p))); # for things like eps |
| | | |
| | | $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps")); |
| | | $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75); |
| | | $p['-opts'] = array('-resize' => $p['size'].'>') + (array)$p['-opts']; |
| | | |
| | | if (in_array($type, explode(',', $p['types']))) # Valid type? |
| | | $result = self::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {in} {type}:{out}', $p) === ""; |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Construct shell command, execute it and return output as string. |
| | | * Keywords {keyword} are replaced with arguments |
| | | * |
| | |
| | | |
| | | return (string)shell_exec($cmd); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replaces hostname variables. |
| | | * |
| | | * @param string $name Hostname |
| | | * @param string $host Optional IMAP hostname |
| | | * |
| | | * @return string Hostname |
| | | */ |
| | | public static function parse_host($name, $host = '') |
| | | { |
| | | // %n - host |
| | | $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']); |
| | | // %d - domain name without first part, e.g. %n=mail.domain.tld, %d=domain.tld |
| | | $d = preg_replace('/^[^\.]+\./', '', $n); |
| | | // %h - IMAP host |
| | | $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; |
| | | // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld |
| | | $z = preg_replace('/^[^\.]+\./', '', $h); |
| | | // %s - domain name after the '@' from e-mail address provided at login screen. Returns FALSE if an invalid email is provided |
| | | if (strpos($name, '%s') !== false) { |
| | | $user_email = rcube_ui::get_input_value('_user', rcube_ui::INPUT_POST); |
| | | $user_email = rcube_idn_convert($user_email, true); |
| | | $matches = preg_match('/(.*)@([a-z0-9\.\-\[\]\:]+)/i', $user_email, $s); |
| | | if ($matches < 1 || filter_var($s[1]."@".$s[2], FILTER_VALIDATE_EMAIL) === false) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | $name = str_replace(array('%n', '%d', '%h', '%z', '%s'), array($n, $d, $h, $z, $s[2]), $name); |
| | | return $name; |
| | | } |
| | | |
| | | |
| | | /** |
| | |
| | | print '<br />'; |
| | | flush(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns remote IP address and forwarded addresses if found |
| | | * |
| | | * @return string Remote IP address(es) |
| | | */ |
| | | public static function remote_ip() |
| | | { |
| | | $address = $_SERVER['REMOTE_ADDR']; |
| | | |
| | | // append the NGINX X-Real-IP header, if set |
| | | if (!empty($_SERVER['HTTP_X_REAL_IP'])) { |
| | | $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP']; |
| | | } |
| | | // append the X-Forwarded-For header, if set |
| | | if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
| | | $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR']; |
| | | } |
| | | |
| | | if (!empty($remote_ip)) { |
| | | $address .= '(' . implode(',', $remote_ip) . ')'; |
| | | } |
| | | |
| | | return $address; |
| | | } |
| | | |
| | | |
| | |
| | | // check validity of email addresses |
| | | foreach ($this->get_col_values('email', $save_data, true) as $email) { |
| | | if (strlen($email)) { |
| | | if (!$rcmail->check_email(rcube_idn_to_ascii($email))) { |
| | | if (!rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { |
| | | $error = $rcmail->gettext(array('name' => 'emailformaterror', 'vars' => array('email' => $email))); |
| | | $this->set_error(self::ERROR_VALIDATE, $error); |
| | | return false; |
File was renamed from program/include/main.inc |
| | |
| | | */ |
| | | |
| | | // constants for input reading |
| | | define('RCUBE_INPUT_GET', rcube_ui::INPUT_GET); |
| | | define('RCUBE_INPUT_POST', rcube_ui::INPUT_POST); |
| | | define('RCUBE_INPUT_GPC', rcube_ui::INPUT_GPC); |
| | | define('RCUBE_INPUT_GET', rcube_utils::INPUT_GET); |
| | | define('RCUBE_INPUT_POST', rcube_utils::INPUT_POST); |
| | | define('RCUBE_INPUT_GPC', rcube_utils::INPUT_GPC); |
| | | |
| | | define('JS_OBJECT_NAME', rcmail::JS_OBJECT_NAME); |
| | | |
| | | function get_table_name($table) |
| | | { |
| | |
| | | |
| | | function rcmail_url($action, $p=array(), $task=null) |
| | | { |
| | | return rcube_ui::url($action, $p, $task); |
| | | return rcmail::get_instance()->url((array)$p + array('_action' => $action, 'task' => $task)); |
| | | } |
| | | |
| | | function rcmail_temp_gc() |
| | |
| | | |
| | | function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) |
| | | { |
| | | return rcube_ui::rep_specialchars_output($str, $enctype, $mode, $newlines); |
| | | return rcube_utils::rep_specialchars_output($str, $enctype, $mode, $newlines); |
| | | } |
| | | |
| | | function Q($str, $mode='strict', $newlines=TRUE) |
| | | { |
| | | return rcube_ui::Q($str, $mode, $newlines); |
| | | return rcmail::Q($str, $mode, $newlines); |
| | | } |
| | | |
| | | function JQ($str) |
| | | { |
| | | return rcube_ui::JQ($str); |
| | | return rcmail::JQ($str); |
| | | } |
| | | |
| | | function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL) |
| | | { |
| | | return rcube_ui::get_input_value($fname, $source, $allow_html, $charset); |
| | | return rcube_utils::get_input_value($fname, $source, $allow_html, $charset); |
| | | } |
| | | |
| | | function parse_input_value($value, $allow_html=FALSE, $charset=NULL) |
| | | { |
| | | return rcube_ui::parse_input_value($value, $allow_html, $charset); |
| | | return rcube_utils::parse_input_value($value, $allow_html, $charset); |
| | | } |
| | | |
| | | function request2param($mode = RCUBE_INPUT_GPC, $ignore = 'task|action') |
| | | { |
| | | return rcube_ui::request2param($mode, $ignore); |
| | | return rcube_utils::request2param($mode, $ignore); |
| | | } |
| | | |
| | | function html_identifier($str, $encode=false) |
| | | { |
| | | return rcube_ui::html_identifier($str, $encode); |
| | | return rcube_utils::html_identifier($str, $encode); |
| | | } |
| | | |
| | | function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col) |
| | | { |
| | | return rcube_ui::table_output($attrib, $table_data, $a_show_cols, $id_col); |
| | | return rcmail::get_instance()->table_output($attrib, $table_data, $a_show_cols, $id_col); |
| | | } |
| | | |
| | | function rcmail_get_edit_field($col, $value, $attrib, $type='text') |
| | | { |
| | | return rcube_ui::get_edit_field($col, $value, $attrib, $type); |
| | | return rcube_utils::get_edit_field($col, $value, $attrib, $type); |
| | | } |
| | | |
| | | function rcmail_mod_css_styles($source, $container_id, $allow_remote=false) |
| | | { |
| | | return rcube_ui::mod_css_styles($source, $container_id, $allow_remote); |
| | | return rcube_utils::mod_css_styles($source, $container_id, $allow_remote); |
| | | } |
| | | |
| | | function rcmail_xss_entity_decode($content) |
| | | { |
| | | return rcube_ui::xss_entity_decode($content); |
| | | return rcube_utils::xss_entity_decode($content); |
| | | } |
| | | |
| | | function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style')) |
| | |
| | | |
| | | function format_date($date, $format=NULL, $convert=true) |
| | | { |
| | | return rcube_ui::format_date($date, $format, $convert); |
| | | return rcmail::get_instance()->format_date($date, $format, $convert); |
| | | } |
| | | |
| | | function rcmail_mailbox_list($attrib) |
| | | { |
| | | return rcube_ui::folder_list($attrib); |
| | | return rcmail::get_instance()->folder_list($attrib); |
| | | } |
| | | |
| | | function rcmail_mailbox_select($attrib = array()) |
| | | { |
| | | return rcube_ui::folder_selector($attrib); |
| | | return rcmail::get_instance()->folder_selector($attrib); |
| | | } |
| | | |
| | | function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $attrib, $nestLevel = 0) |
| | | { |
| | | return rcube_ui::render_folder_tree_html($arrFolders, $mbox_name, $jslist, $attrib, $nestLevel); |
| | | return rcmail::get_instance()->render_folder_tree_html($arrFolders, $mbox_name, $jslist, $attrib, $nestLevel); |
| | | } |
| | | |
| | | function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames = false, $nestLevel = 0, $opts = array()) |
| | | { |
| | | return rcube_ui::render_folder_tree_select($arrFolders, $mbox_name, $maxlength, $select, $realnames, $nestLevel, $opts); |
| | | return rcmail::get_instance()->render_folder_tree_select($arrFolders, $mbox_name, $maxlength, $select, $realnames, $nestLevel, $opts); |
| | | } |
| | | |
| | | function rcmail_build_folder_tree(&$arrFolders, $folder, $delm = '/', $path = '') |
| | | { |
| | | return rcmail_ui::build_folder_tree($arrFolders, $folder, $delm, $path); |
| | | return rcmail::get_instance()->build_folder_tree($arrFolders, $folder, $delm, $path); |
| | | } |
| | | |
| | | function rcmail_folder_classname($folder_id) |
| | | { |
| | | return rcube_ui::folder_classname($folder_id); |
| | | return rcmail::get_instance()->folder_classname($folder_id); |
| | | } |
| | | |
| | | function rcmail_localize_foldername($name) |
| | | { |
| | | return rcube_ui::localize_foldername($name); |
| | | return rcmail::get_instance()->localize_foldername($name); |
| | | } |
| | | |
| | | function rcmail_localize_folderpath($path) |
| | | { |
| | | return rcube_ui::localize_folderpath($path); |
| | | return rcmail::get_instance()->localize_folderpath($path); |
| | | } |
| | | |
| | | function rcmail_quota_display($attrib) |
| | | { |
| | | return rcube_ui::quota_display($attrib); |
| | | return rcmail::get_instance()->quota_display($attrib); |
| | | } |
| | | |
| | | function rcmail_quota_content($attrib = null) |
| | | { |
| | | return rcube_ui::quota_content($attrib); |
| | | return rcmail::get_instance()->quota_content($attrib); |
| | | } |
| | | |
| | | function rcmail_display_server_error($fallback=null, $fallback_args=null) |
| | | { |
| | | rcube_ui::display_server_error($fallback, $fallback_args); |
| | | rcmail::get_instance()->display_server_error($fallback, $fallback_args); |
| | | } |
| | | |
| | | function rcmail_filetype2classname($mimetype, $filename) |
| | | { |
| | | return rcube_ui::file2class($mimetype, $filename); |
| | | return rcube_utils::file2class($mimetype, $filename); |
| | | } |
| | | |
| | | function rcube_html_editor($mode='') |
| | | { |
| | | rcube_ui::html_editor($mode); |
| | | rcmail::get_instance()->html_editor($mode); |
| | | } |
| | | |
| | | function rcmail_replace_emoticons($html) |
| | | { |
| | | return rcube_ui::replace_emoticons($html); |
| | | return rcmail::get_instance()->replace_emoticons($html); |
| | | } |
| | | |
| | | function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file=null, $smtp_opts=null) |
| | |
| | | |
| | | function rcmail_mem_check($need) |
| | | { |
| | | return rcube_ui::mem_check($need); |
| | | return rcube_utils::mem_check($need); |
| | | } |
| | | |
| | | function rcube_https_check($port=null, $use_https=true) |
| | | { |
| | | return rcube_ui::https_check($port, $use_https); |
| | | return rcube_utils::https_check($port, $use_https); |
| | | } |
| | | |
| | | function rcube_sess_unset($var_name=null) |
| | |
| | | |
| | | function rcube_parse_host($name, $host='') |
| | | { |
| | | return rcmail::parse_host($name, $host); |
| | | return rcube_utils::parse_host($name, $host); |
| | | } |
| | | |
| | | function check_email($email, $dns_check=true) |
| | | { |
| | | return rcmail::get_instance()->check_email($email, $dns_check); |
| | | return rcube_utils::check_email($email, $dns_check); |
| | | } |
| | | |
| | | function console() |
| | |
| | | |
| | | function rcmail_remote_ip() |
| | | { |
| | | return rcmail::remote_ip(); |
| | | return rcube_utils::remote_ip(); |
| | | } |
| | | |
| | | function rcube_check_referer() |
| | |
| | | |
| | | function rcube_upload_progress() |
| | | { |
| | | rcube_ui::upload_progress(); |
| | | rcmail::get_instance()->upload_progress(); |
| | | } |
| | | |
| | | function rcube_upload_init() |
| | | { |
| | | return rcube_ui::upload_init(); |
| | | return rcmail::get_instance()->upload_init(); |
| | | } |
| | | |
| | | function rcube_autocomplete_init() |
| | | { |
| | | rcube_ui::autocomplete_init(); |
| | | rcmail::get_instance()->autocomplete_init(); |
| | | } |
| | | |
| | | function rcube_fontdefs($font = null) |
| | | { |
| | | return rcube_ui::font_defs($font); |
| | | return rcmail::font_defs($font); |
| | | } |
| | | |
| | | function send_nocacheing_headers() |
| | |
| | | |
| | | function show_bytes($bytes) |
| | | { |
| | | return rcube_ui::show_bytes($bytes); |
| | | return rcmail::get_instance()->show_bytes($bytes); |
| | | } |
| | | |
| | | function rc_wordwrap($string, $width=75, $break="\n", $cut=false) |
| | |
| | | |
| | | function rc_request_header($name) |
| | | { |
| | | return rcube_request_header($name); |
| | | return rcube_utils::request_header($name); |
| | | } |
| | | |
| | | function rcube_explode_quoted_string($delimiter, $string) |
| | | { |
| | | return rcube_utils::explode_quoted_string($delimiter, $string); |
| | | } |
| | | |
| | | function rc_mime_content_type($path, $name, $failover = 'application/octet-stream', $is_stream=false) |
| | |
| | | { |
| | | return rcube_mime::image_content_type($data); |
| | | } |
| | | |
| | | function rcube_strtotime($date) |
| | | { |
| | | return rcube_utils::strtotime($date); |
| | | } |
| | | |
| | | function rcube_idn_to_ascii($str) |
| | | { |
| | | return rcube_utils::idn_to_ascii($str); |
| | | } |
| | | |
| | | function rcube_idn_to_utf8($str) |
| | | { |
| | | return rcube_utils::idn_to_utf8($str); |
| | | } |
| | |
| | | if (isset($this->prop['mail_domain'][$host])) |
| | | $domain = $this->prop['mail_domain'][$host]; |
| | | } |
| | | else if (!empty($this->prop['mail_domain'])) |
| | | $domain = rcmail::parse_host($this->prop['mail_domain']); |
| | | else if (!empty($this->prop['mail_domain'])) { |
| | | $domain = rcube_utils::parse_host($this->prop['mail_domain']); |
| | | } |
| | | |
| | | if ($encode) |
| | | $domain = rcube_idn_to_ascii($domain); |
| | | if ($encode) { |
| | | $domain = rcube_utils::idn_to_ascii($domain); |
| | | } |
| | | |
| | | return $domain; |
| | | } |
| | |
| | | else if ($this->conn->error) { |
| | | if ($pass && $user) { |
| | | $message = sprintf("Login failed for %s from %s. %s", |
| | | $user, rcmail::remote_ip(), $this->conn->error); |
| | | $user, rcube_utils::remote_ip(), $this->conn->error); |
| | | |
| | | rcube::raise_error(array('code' => 403, 'type' => 'imap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | |
| | | | program/include/rcube_imap_generic.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2010, The Roundcube Dev Team | |
| | | | Copyright (C) 2011, Kolab Systems AG | |
| | | | Copyright (C) 2005-2012, The Roundcube Dev Team | |
| | | | Copyright (C) 2011-2012, Kolab Systems AG | |
| | | | | |
| | | | Licensed under the GNU General Public License version 3 or | |
| | | | any later version with exceptions for skins & plugins. | |
| | |
| | | |
| | | */ |
| | | |
| | | // for backward copat. |
| | | // for backward compat. |
| | | class rcube_mail_header extends rcube_message_header { } |
| | | |
| | | |
| | |
| | | |
| | | foreach ($this->prop['hosts'] as $host) |
| | | { |
| | | $host = idn_to_ascii(rcmail::parse_host($host)); |
| | | $host = idn_to_ascii(rcube_utils::parse_host($host)); |
| | | $hostname = $host.($this->prop['port'] ? ':'.$this->prop['port'] : ''); |
| | | |
| | | $this->_debug("C: Connect [$hostname] [{$this->prop['name']}]"); |
| | |
| | | header("X-DNS-Prefetch-Control: off"); |
| | | |
| | | // We need to set the following headers to make downloads work using IE in HTTPS mode. |
| | | if ($this->browser->ie && rcube_ui::https_check()) { |
| | | if ($this->browser->ie && rcube_utils::https_check()) { |
| | | header('Pragma: private'); |
| | | header("Cache-Control: private, must-revalidate"); |
| | | } |
| | |
| | | $this->set_skin($this->config->get('skin')); |
| | | |
| | | // add common javascripts |
| | | $this->add_script('var '.JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top'); |
| | | $this->add_script('var '.rcmail::JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top'); |
| | | |
| | | // don't wait for page onload. Call init at the bottom of the page (delayed) |
| | | $this->add_script(JS_OBJECT_NAME.'.init();', 'docready'); |
| | | $this->add_script(rcmail::JS_OBJECT_NAME.'.init();', 'docready'); |
| | | |
| | | $this->scripts_path = 'program/js/'; |
| | | $this->include_script('jquery.min.js'); |
| | |
| | | */ |
| | | public function add_gui_object($obj, $id) |
| | | { |
| | | $this->add_script(JS_OBJECT_NAME.".gui_object('$obj', '$id');"); |
| | | $this->add_script(rcmail::JS_OBJECT_NAME.".gui_object('$obj', '$id');"); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | $out = ''; |
| | | if (!$this->framed && !empty($this->js_env)) { |
| | | $out .= JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n"; |
| | | $out .= rcmail::JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n"; |
| | | } |
| | | if (!empty($this->js_labels)) { |
| | | $this->command('add_label', $this->js_labels); |
| | |
| | | $parent = $this->framed || preg_match('/^parent\./', $method); |
| | | $out .= sprintf( |
| | | "%s.%s(%s);\n", |
| | | ($parent ? 'if(window.parent && parent.'.JS_OBJECT_NAME.') parent.' : '') . JS_OBJECT_NAME, |
| | | ($parent ? 'if(window.parent && parent.'.rcmail::JS_OBJECT_NAME.') parent.' : '') . rcmail::JS_OBJECT_NAME, |
| | | preg_replace('/^parent\./', '', $method), |
| | | implode(',', $args) |
| | | ); |
| | |
| | | "\$_SESSION['\\1']", |
| | | "\$this->app->config->get('\\1',get_boolean('\\3'))", |
| | | "\$this->env['\\1']", |
| | | "rcube_ui::get_input_value('\\1', rcube_ui::INPUT_GPC)", |
| | | "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)", |
| | | "\$_COOKIE['\\1']", |
| | | "\$this->browser->{'\\1'}", |
| | | $this->template_name, |
| | |
| | | } |
| | | break; |
| | | case 'request': |
| | | $value = rcube_ui::get_input_value($name, rcube_ui::INPUT_GPC); |
| | | $value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC); |
| | | break; |
| | | case 'session': |
| | | $value = $_SESSION[$name]; |
| | |
| | | if ($attrib['command']) { |
| | | $this->add_script(sprintf( |
| | | "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", |
| | | JS_OBJECT_NAME, |
| | | rcmail::JS_OBJECT_NAME, |
| | | $command, |
| | | $attrib['id'], |
| | | $attrib['type'], |
| | |
| | | // make valid href to specific buttons |
| | | if (in_array($attrib['command'], rcmail::$main_tasks)) { |
| | | $attrib['href'] = $this->app->url(array('task' => $attrib['command'])); |
| | | $attrib['onclick'] = sprintf("%s.command('switch-task','%s');return false", JS_OBJECT_NAME, $attrib['command']); |
| | | $attrib['onclick'] = sprintf("%s.command('switch-task','%s');return false", rcmail::JS_OBJECT_NAME, $attrib['command']); |
| | | } |
| | | else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) { |
| | | $attrib['href'] = $this->app->url(array('action' => $attrib['command'], 'task' => $attrib['task'])); |
| | |
| | | else if ($command && !$attrib['onclick']) { |
| | | $attrib['onclick'] = sprintf( |
| | | "return %s.command('%s','%s',this)", |
| | | JS_OBJECT_NAME, |
| | | rcmail::JS_OBJECT_NAME, |
| | | $command, |
| | | $attrib['prop'] |
| | | ); |
| | |
| | | $username = $this->app->user->get_username(); |
| | | } |
| | | |
| | | return rcube_idn_to_utf8($username); |
| | | return rcube_utils::idn_to_utf8($username); |
| | | } |
| | | |
| | | |
| | |
| | | $_SESSION['temp'] = true; |
| | | |
| | | // save original url |
| | | $url = rcube_ui::get_input_value('_url', rcube_ui::INPUT_POST); |
| | | $url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST); |
| | | if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING'])) |
| | | $url = $_SERVER['QUERY_STRING']; |
| | | |
| | |
| | | $table = new html_table(array('cols' => 2)); |
| | | |
| | | $table->add('title', html::label('rcmloginuser', html::quote($this->app->gettext('username')))); |
| | | $table->add('input', $input_user->show(rcube_ui::get_input_value('_user', rcube_ui::INPUT_GPC))); |
| | | $table->add('input', $input_user->show(rcube_utils::get_input_value('_user', rcube_utils::INPUT_GPC))); |
| | | |
| | | $table->add('title', html::label('rcmloginpwd', html::quote($this->app->gettext('password')))); |
| | | $table->add('input', $input_pass->show()); |
| | |
| | | // add host selection row |
| | | if (is_object($input_host) && !$hide_host) { |
| | | $table->add('title', html::label('rcmloginhost', html::quote($this->app->gettext('server')))); |
| | | $table->add('input', $input_host->show(rcube_ui::get_input_value('_host', rcube_ui::INPUT_GPC))); |
| | | $table->add('input', $input_host->show(rcube_utils::get_input_value('_host', rcube_utils::INPUT_GPC))); |
| | | } |
| | | |
| | | $out = $input_task->show(); |
| | |
| | | if (empty($attrib['form'])) { |
| | | $out = $this->form_tag(array( |
| | | 'name' => "rcmqsearchform", |
| | | 'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;", |
| | | 'onsubmit' => rcmail::JS_OBJECT_NAME . ".command('search');return false;", |
| | | 'style' => "display:inline"), |
| | | $out); |
| | | } |
| | |
| | | if ($override || !$this->message) { |
| | | if ($this->app->text_exists($message)) { |
| | | if (!empty($vars)) { |
| | | $vars = array_map(array('rcube_ui', 'Q'), $vars); |
| | | $vars = array_map(array('rcmail', 'Q'), $vars); |
| | | } |
| | | $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars)); |
| | | } |
| | |
| | | public function redirect($p = array(), $delay = 1) |
| | | { |
| | | $location = rcmail::get_instance()->url($p); |
| | | $this->remote_response(sprintf("window.setTimeout(function(){ %s.redirect('%s',true); }, %d);", JS_OBJECT_NAME, $location, $delay)); |
| | | $this->remote_response(sprintf("window.setTimeout(function(){ %s.redirect('%s',true); }, %d);", |
| | | rcmail::JS_OBJECT_NAME, $location, $delay)); |
| | | exit; |
| | | } |
| | | |
| | |
| | | $rcmail = rcmail::get_instance(); |
| | | $response['action'] = $rcmail->action; |
| | | |
| | | if ($unlock = rcube_ui::get_input_value('_unlock', rcube_ui::INPUT_GPC)) { |
| | | if ($unlock = rcube_utils::get_input_value('_unlock', rcube_utils::INPUT_GPC)) { |
| | | $response['unlock'] = $unlock; |
| | | } |
| | | |
| | |
| | | $this->vars = false; |
| | | $this->ip = $_SERVER['REMOTE_ADDR']; // update IP (might have changed) |
| | | $this->destroy(session_id()); |
| | | rcmail::setcookie($this->cookiename, '-del-', time() - 60); |
| | | rcube_utils::setcookie($this->cookiename, '-del-', time() - 60); |
| | | } |
| | | |
| | | |
| | |
| | | function set_auth_cookie() |
| | | { |
| | | $this->cookie = $this->_mkcookie($this->now); |
| | | rcmail::setcookie($this->cookiename, $this->cookie, 0); |
| | | rcube_utils::setcookie($this->cookiename, $this->cookie, 0); |
| | | $_COOKIE[$this->cookiename] = $this->cookie; |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Read a specific HTTP request header. |
| | | * |
| | | * @param string $name Header name |
| | | * |
| | | * @return mixed Header value or null if not available |
| | | */ |
| | | function rcube_request_header($name) |
| | | { |
| | | if (function_exists('getallheaders')) { |
| | | $hdrs = array_change_key_case(getallheaders(), CASE_UPPER); |
| | | $key = strtoupper($name); |
| | | } |
| | | else { |
| | | $key = 'HTTP_' . strtoupper(strtr($name, '-', '_')); |
| | | $hdrs = array_change_key_case($_SERVER, CASE_UPPER); |
| | | } |
| | | |
| | | return $hdrs[$key]; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Make sure the string ends with a slash |
| | | */ |
| | | function slashify($str) |
| | |
| | | |
| | | |
| | | /** |
| | | * Explode quoted string |
| | | * |
| | | * @param string Delimiter expression string for preg_match() |
| | | * @param string Input string |
| | | */ |
| | | function rcube_explode_quoted_string($delimiter, $string) |
| | | { |
| | | $result = array(); |
| | | $strlen = strlen($string); |
| | | |
| | | for ($q=$p=$i=0; $i < $strlen; $i++) { |
| | | if ($string[$i] == "\"" && $string[$i-1] != "\\") { |
| | | $q = $q ? false : true; |
| | | } |
| | | else if (!$q && preg_match("/$delimiter/", $string[$i])) { |
| | | $result[] = substr($string, $p, $i - $p); |
| | | $p = $i + 1; |
| | | } |
| | | } |
| | | |
| | | $result[] = substr($string, $p); |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Get all keys from array (recursive). |
| | | * |
| | | * @param array $array Input array |
| | |
| | | function strip_newlines($str) |
| | | { |
| | | return preg_replace('/[\r\n]/', '', $str); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Improved equivalent to strtotime() |
| | | * |
| | | * @param string $date Date string |
| | | * |
| | | * @return int Unix timestamp |
| | | */ |
| | | function rcube_strtotime($date) |
| | | { |
| | | // check for MS Outlook vCard date format YYYYMMDD |
| | | if (preg_match('/^([12][90]\d\d)([01]\d)(\d\d)$/', trim($date), $matches)) { |
| | | return mktime(0,0,0, intval($matches[2]), intval($matches[3]), intval($matches[1])); |
| | | } |
| | | else if (is_numeric($date)) { |
| | | return $date; |
| | | } |
| | | |
| | | // support non-standard "GMTXXXX" literal |
| | | $date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date); |
| | | |
| | | // if date parsing fails, we have a date in non-rfc format. |
| | | // remove token from the end and try again |
| | | while ((($ts = @strtotime($date)) === false) || ($ts < 0)) { |
| | | $d = explode(' ', $date); |
| | | array_pop($d); |
| | | if (!$d) { |
| | | break; |
| | | } |
| | | $date = implode(' ', $d); |
| | | } |
| | | |
| | | return $ts; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | function rcube_idn_to_ascii($str) |
| | | { |
| | | return rcube_idn_convert($str, true); |
| | | } |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | function rcube_idn_to_utf8($str) |
| | | { |
| | | return rcube_idn_convert($str, false); |
| | | } |
| | | |
| | | function rcube_idn_convert($input, $is_utf=false) |
| | | { |
| | | if ($at = strpos($input, '@')) { |
| | | $user = substr($input, 0, $at); |
| | | $domain = substr($input, $at+1); |
| | | } |
| | | else { |
| | | $domain = $input; |
| | | } |
| | | |
| | | $domain = $is_utf ? idn_to_ascii($domain) : idn_to_utf8($domain); |
| | | |
| | | if ($domain === false) { |
| | | return ''; |
| | | } |
| | | |
| | | return $at ? $user . '@' . $domain : $domain; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Use PHP5 autoload for dynamic class loading |
| | | * |
| | |
| | | |
| | | if ($fp = @fopen("$filename.php", 'r', true)) { |
| | | fclose($fp); |
| | | include_once("$filename.php"); |
| | | include_once "$filename.php"; |
| | | return true; |
| | | } |
| | | |
| | |
| | | 'smtp_auth_callbacks' => array(), |
| | | )); |
| | | |
| | | $smtp_host = rcmail::parse_host($CONFIG['smtp_server']); |
| | | $smtp_host = rcube_utils::parse_host($CONFIG['smtp_server']); |
| | | // when called from Installer it's possible to have empty $smtp_host here |
| | | if (!$smtp_host) $smtp_host = 'localhost'; |
| | | $smtp_port = is_numeric($CONFIG['smtp_port']) ? $CONFIG['smtp_port'] : 25; |
| | |
| | | $helo_host = 'localhost'; |
| | | |
| | | // IDNA Support |
| | | $smtp_host = rcube_idn_to_ascii($smtp_host); |
| | | $smtp_host = rcube_utils::idn_to_ascii($smtp_host); |
| | | |
| | | $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); |
| | | |
| | |
| | | { |
| | | // IDNA Support |
| | | if (strpos($smtp_user, '@')) { |
| | | $smtp_user = rcube_idn_to_ascii($smtp_user); |
| | | $smtp_user = rcube_utils::idn_to_ascii($smtp_user); |
| | | } |
| | | |
| | | $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls, $smtp_authz); |
| | |
| | | $recipients = implode(', ', $recipients); |
| | | |
| | | $addresses = array(); |
| | | $recipients = rcube_explode_quoted_string(',', $recipients); |
| | | $recipients = rcube_utils::explode_quoted_string(',', $recipients); |
| | | |
| | | reset($recipients); |
| | | while (list($k, $recipient) = each($recipients)) |
| | | { |
| | | $a = rcube_explode_quoted_string(' ', $recipient); |
| | | $a = rcube_utils::explode_quoted_string(' ', $recipient); |
| | | while (list($k2, $word) = each($a)) |
| | | { |
| | | if (strpos($word, "@") > 0 && $word[strlen($word)-1] != '"') |
| | |
| | | $i = $this->add($prefix . html::a(array( |
| | | 'href' => $url_prefix . $url, |
| | | 'target' => '_blank' |
| | | ), rcube_ui::Q($url)) . $suffix); |
| | | ), rcmail::Q($url)) . $suffix); |
| | | } |
| | | |
| | | // Return valid link for recognized schemes, otherwise, return the unmodified string for unrecognized schemes. |
| | |
| | | |
| | | $i = $this->add(html::a(array( |
| | | 'href' => 'mailto:' . $href, |
| | | 'onclick' => "return ".JS_OBJECT_NAME.".command('compose','".rcube_ui::JQ($href)."',this)", |
| | | ), rcube_ui::Q($href)) . $suffix); |
| | | 'onclick' => "return ".rcmail::JS_OBJECT_NAME.".command('compose','".rcmail::JQ($href)."',this)", |
| | | ), rcmail::Q($href)) . $suffix); |
| | | |
| | | return $i >= 0 ? $this->get_replacement($i) : ''; |
| | | } |
New file |
| | |
| | | <?php |
| | | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | program/include/rcube_utils.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2008-2012, The Roundcube Dev Team | |
| | | | Copyright (C) 2011-2012, Kolab Systems AG | |
| | | | | |
| | | | Licensed under the GNU General Public License version 3 or | |
| | | | any later version with exceptions for skins & plugins. | |
| | | | See the README file for a full license statement. | |
| | | | | |
| | | | PURPOSE: | |
| | | | Utility class providing common functions | |
| | | +-----------------------------------------------------------------------+ |
| | | | Author: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Author: Aleksander Machniak <alec@alec.pl> | |
| | | +-----------------------------------------------------------------------+ |
| | | |
| | | $Id$ |
| | | |
| | | */ |
| | | |
| | | |
| | | /** |
| | | * Utility class providing common functions |
| | | * |
| | | * @package Core |
| | | */ |
| | | class rcube_utils |
| | | { |
| | | // define constants for input reading |
| | | const INPUT_GET = 0x0101; |
| | | const INPUT_POST = 0x0102; |
| | | const INPUT_GPC = 0x0103; |
| | | |
| | | /** |
| | | * Helper method to set a cookie with the current path and host settings |
| | | * |
| | | * @param string Cookie name |
| | | * @param string Cookie value |
| | | * @param string Expiration time |
| | | */ |
| | | public static function setcookie($name, $value, $exp = 0) |
| | | { |
| | | if (headers_sent()) { |
| | | return; |
| | | } |
| | | |
| | | $cookie = session_get_cookie_params(); |
| | | $secure = self::https_check(); |
| | | |
| | | setcookie($name, $value, $exp, $cookie['path'], $cookie['domain'], $secure, true); |
| | | } |
| | | |
| | | /** |
| | | * E-mail address validation. |
| | | * |
| | | * @param string $email Email address |
| | | * @param boolean $dns_check True to check dns |
| | | * |
| | | * @return boolean True on success, False if address is invalid |
| | | */ |
| | | public static function check_email($email, $dns_check=true) |
| | | { |
| | | // Check for invalid characters |
| | | if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $email)) { |
| | | return false; |
| | | } |
| | | |
| | | // Check for length limit specified by RFC 5321 (#1486453) |
| | | if (strlen($email) > 254) { |
| | | return false; |
| | | } |
| | | |
| | | $email_array = explode('@', $email); |
| | | |
| | | // Check that there's one @ symbol |
| | | if (count($email_array) < 2) { |
| | | return false; |
| | | } |
| | | |
| | | $domain_part = array_pop($email_array); |
| | | $local_part = implode('@', $email_array); |
| | | |
| | | // from PEAR::Validate |
| | | $regexp = '&^(?: |
| | | ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| #1 quoted name |
| | | ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) #2 OR dot-atom (RFC5322) |
| | | $&xi'; |
| | | |
| | | if (!preg_match($regexp, $local_part)) { |
| | | return false; |
| | | } |
| | | |
| | | // Check domain part |
| | | if (preg_match('/^\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]*$/', $domain_part)) { |
| | | return true; // IP address |
| | | } |
| | | else { |
| | | // If not an IP address |
| | | $domain_array = explode('.', $domain_part); |
| | | // Not enough parts to be a valid domain |
| | | if (sizeof($domain_array) < 2) { |
| | | return false; |
| | | } |
| | | |
| | | foreach ($domain_array as $part) { |
| | | if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]))$/', $part)) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | $rcube = rcube::get_instance(); |
| | | |
| | | if (!$dns_check || !$rcube->config->get('email_dns_check')) { |
| | | return true; |
| | | } |
| | | |
| | | if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) { |
| | | $lookup = array(); |
| | | @exec("nslookup -type=MX " . escapeshellarg($domain_part) . " 2>&1", $lookup); |
| | | foreach ($lookup as $line) { |
| | | if (strpos($line, 'MX preference')) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // find MX record(s) |
| | | if (getmxrr($domain_part, $mx_records)) { |
| | | return true; |
| | | } |
| | | |
| | | // find any DNS record |
| | | if (checkdnsrr($domain_part, 'ANY')) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Check whether the HTTP referer matches the current request |
| | | * |
| | | * @return boolean True if referer is the same host+path, false if not |
| | | */ |
| | | public static function check_referer() |
| | | { |
| | | $uri = parse_url($_SERVER['REQUEST_URI']); |
| | | $referer = parse_url(rcube_request_header('Referer')); |
| | | return $referer['host'] == rcube_request_header('Host') && $referer['path'] == $uri['path']; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replacing specials characters to a specific encoding type |
| | | * |
| | | * @param string Input string |
| | | * @param string Encoding type: text|html|xml|js|url |
| | | * @param string Replace mode for tags: show|replace|remove |
| | | * @param boolean Convert newlines |
| | | * |
| | | * @return string The quoted string |
| | | */ |
| | | public static function rep_specialchars_output($str, $enctype = '', $mode = '', $newlines = true) |
| | | { |
| | | static $html_encode_arr = false; |
| | | static $js_rep_table = false; |
| | | static $xml_rep_table = false; |
| | | |
| | | // encode for HTML output |
| | | if ($enctype == 'html') { |
| | | if (!$html_encode_arr) { |
| | | $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS); |
| | | unset($html_encode_arr['?']); |
| | | } |
| | | |
| | | $encode_arr = $html_encode_arr; |
| | | |
| | | // don't replace quotes and html tags |
| | | if ($mode == 'show' || $mode == '') { |
| | | $ltpos = strpos($str, '<'); |
| | | if ($ltpos !== false && strpos($str, '>', $ltpos) !== false) { |
| | | unset($encode_arr['"']); |
| | | unset($encode_arr['<']); |
| | | unset($encode_arr['>']); |
| | | unset($encode_arr['&']); |
| | | } |
| | | } |
| | | else if ($mode == 'remove') { |
| | | $str = strip_tags($str); |
| | | } |
| | | |
| | | $out = strtr($str, $encode_arr); |
| | | |
| | | // avoid douple quotation of & |
| | | $out = preg_replace('/&([A-Za-z]{2,6}|#[0-9]{2,4});/', '&\\1;', $out); |
| | | |
| | | return $newlines ? nl2br($out) : $out; |
| | | } |
| | | |
| | | // if the replace tables for XML and JS are not yet defined |
| | | if ($js_rep_table === false) { |
| | | $js_rep_table = $xml_rep_table = array(); |
| | | $xml_rep_table['&'] = '&'; |
| | | |
| | | // can be increased to support more charsets |
| | | for ($c=160; $c<256; $c++) { |
| | | $xml_rep_table[chr($c)] = "&#$c;"; |
| | | } |
| | | |
| | | $xml_rep_table['"'] = '"'; |
| | | $js_rep_table['"'] = '\\"'; |
| | | $js_rep_table["'"] = "\\'"; |
| | | $js_rep_table["\\"] = "\\\\"; |
| | | // Unicode line and paragraph separators (#1486310) |
| | | $js_rep_table[chr(hexdec(E2)).chr(hexdec(80)).chr(hexdec(A8))] = '
'; |
| | | $js_rep_table[chr(hexdec(E2)).chr(hexdec(80)).chr(hexdec(A9))] = '
'; |
| | | } |
| | | |
| | | // encode for javascript use |
| | | if ($enctype == 'js') { |
| | | return preg_replace(array("/\r?\n/", "/\r/", '/<\\//'), array('\n', '\n', '<\\/'), strtr($str, $js_rep_table)); |
| | | } |
| | | |
| | | // encode for plaintext |
| | | if ($enctype == 'text') { |
| | | return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str); |
| | | } |
| | | |
| | | if ($enctype == 'url') { |
| | | return rawurlencode($str); |
| | | } |
| | | |
| | | // encode for XML |
| | | if ($enctype == 'xml') { |
| | | return strtr($str, $xml_rep_table); |
| | | } |
| | | |
| | | // no encoding given -> return original string |
| | | return $str; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Read input value and convert it for internal use |
| | | * Performs stripslashes() and charset conversion if necessary |
| | | * |
| | | * @param string Field name to read |
| | | * @param int Source to get value from (GPC) |
| | | * @param boolean Allow HTML tags in field value |
| | | * @param string Charset to convert into |
| | | * |
| | | * @return string Field value or NULL if not available |
| | | */ |
| | | public static function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL) |
| | | { |
| | | $value = NULL; |
| | | |
| | | if ($source == self::INPUT_GET) { |
| | | if (isset($_GET[$fname])) { |
| | | $value = $_GET[$fname]; |
| | | } |
| | | } |
| | | else if ($source == self::INPUT_POST) { |
| | | if (isset($_POST[$fname])) { |
| | | $value = $_POST[$fname]; |
| | | } |
| | | } |
| | | else if ($source == self::INPUT_GPC) { |
| | | if (isset($_POST[$fname])) { |
| | | $value = $_POST[$fname]; |
| | | } |
| | | else if (isset($_GET[$fname])) { |
| | | $value = $_GET[$fname]; |
| | | } |
| | | else if (isset($_COOKIE[$fname])) { |
| | | $value = $_COOKIE[$fname]; |
| | | } |
| | | } |
| | | |
| | | return self::parse_input_value($value, $allow_html, $charset); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parse/validate input value. See self::get_input_value() |
| | | * Performs stripslashes() and charset conversion if necessary |
| | | * |
| | | * @param string Input value |
| | | * @param boolean Allow HTML tags in field value |
| | | * @param string Charset to convert into |
| | | * |
| | | * @return string Parsed value |
| | | */ |
| | | public static function parse_input_value($value, $allow_html=FALSE, $charset=NULL) |
| | | { |
| | | global $OUTPUT; |
| | | |
| | | if (empty($value)) { |
| | | return $value; |
| | | } |
| | | |
| | | if (is_array($value)) { |
| | | foreach ($value as $idx => $val) { |
| | | $value[$idx] = self::parse_input_value($val, $allow_html, $charset); |
| | | } |
| | | return $value; |
| | | } |
| | | |
| | | // strip single quotes if magic_quotes_sybase is enabled |
| | | if (ini_get('magic_quotes_sybase')) { |
| | | $value = str_replace("''", "'", $value); |
| | | } |
| | | // strip slashes if magic_quotes enabled |
| | | else if (get_magic_quotes_gpc() || get_magic_quotes_runtime()) { |
| | | $value = stripslashes($value); |
| | | } |
| | | |
| | | // remove HTML tags if not allowed |
| | | if (!$allow_html) { |
| | | $value = strip_tags($value); |
| | | } |
| | | |
| | | $output_charset = is_object($OUTPUT) ? $OUTPUT->get_charset() : null; |
| | | |
| | | // remove invalid characters (#1488124) |
| | | if ($output_charset == 'UTF-8') { |
| | | $value = rcube_charset::clean($value); |
| | | } |
| | | |
| | | // convert to internal charset |
| | | if ($charset && $output_charset) { |
| | | $value = rcube_charset::convert($value, $output_charset, $charset); |
| | | } |
| | | |
| | | return $value; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert array of request parameters (prefixed with _) |
| | | * to a regular array with non-prefixed keys. |
| | | * |
| | | * @param int $mode Source to get value from (GPC) |
| | | * @param string $ignore PCRE expression to skip parameters by name |
| | | * |
| | | * @return array Hash array with all request parameters |
| | | */ |
| | | public static function request2param($mode = null, $ignore = 'task|action') |
| | | { |
| | | $out = array(); |
| | | $src = $mode == self::INPUT_GET ? $_GET : ($mode == self::INPUT_POST ? $_POST : $_REQUEST); |
| | | |
| | | foreach ($src as $key => $value) { |
| | | $fname = $key[0] == '_' ? substr($key, 1) : $key; |
| | | if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname)) { |
| | | $out[$fname] = self::get_input_value($key, $mode); |
| | | } |
| | | } |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Convert the given string into a valid HTML identifier |
| | | * Same functionality as done in app.js with rcube_webmail.html_identifier() |
| | | */ |
| | | public static function html_identifier($str, $encode=false) |
| | | { |
| | | if ($encode) { |
| | | return rtrim(strtr(base64_encode($str), '+/', '-_'), '='); |
| | | } |
| | | else { |
| | | return asciiwords($str, true, '_'); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create an edit field for inclusion on a form |
| | | * |
| | | * @param string col field name |
| | | * @param string value field value |
| | | * @param array attrib HTML element attributes for field |
| | | * @param string type HTML element type (default 'text') |
| | | * |
| | | * @return string HTML field definition |
| | | */ |
| | | public static function get_edit_field($col, $value, $attrib, $type = 'text') |
| | | { |
| | | static $colcounts = array(); |
| | | |
| | | $fname = '_'.$col; |
| | | $attrib['name'] = $fname . ($attrib['array'] ? '[]' : ''); |
| | | $attrib['class'] = trim($attrib['class'] . ' ff_' . $col); |
| | | |
| | | if ($type == 'checkbox') { |
| | | $attrib['value'] = '1'; |
| | | $input = new html_checkbox($attrib); |
| | | } |
| | | else if ($type == 'textarea') { |
| | | $attrib['cols'] = $attrib['size']; |
| | | $input = new html_textarea($attrib); |
| | | } |
| | | else if ($type == 'select') { |
| | | $input = new html_select($attrib); |
| | | $input->add('---', ''); |
| | | $input->add(array_values($attrib['options']), array_keys($attrib['options'])); |
| | | } |
| | | else if ($attrib['type'] == 'password') { |
| | | $input = new html_passwordfield($attrib); |
| | | } |
| | | else { |
| | | if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden') { |
| | | $attrib['type'] = 'text'; |
| | | } |
| | | $input = new html_inputfield($attrib); |
| | | } |
| | | |
| | | // use value from post |
| | | if (isset($_POST[$fname])) { |
| | | $postvalue = self::get_input_value($fname, self::INPUT_POST, true); |
| | | $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue; |
| | | } |
| | | |
| | | $out = $input->show($value); |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replace all css definitions with #container [def] |
| | | * and remove css-inlined scripting |
| | | * |
| | | * @param string CSS source code |
| | | * @param string Container ID to use as prefix |
| | | * |
| | | * @return string Modified CSS source |
| | | */ |
| | | public static function mod_css_styles($source, $container_id, $allow_remote=false) |
| | | { |
| | | $last_pos = 0; |
| | | $replacements = new rcube_string_replacer; |
| | | |
| | | // ignore the whole block if evil styles are detected |
| | | $source = self::xss_entity_decode($source); |
| | | $stripped = preg_replace('/[^a-z\(:;]/i', '', $source); |
| | | $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : ''); |
| | | if (preg_match("/$evilexpr/i", $stripped)) { |
| | | return '/* evil! */'; |
| | | } |
| | | |
| | | // cut out all contents between { and } |
| | | while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { |
| | | $styles = substr($source, $pos+1, $pos2-($pos+1)); |
| | | |
| | | // check every line of a style block... |
| | | if ($allow_remote) { |
| | | $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY); |
| | | foreach ($a_styles as $line) { |
| | | $stripped = preg_replace('/[^a-z\(:;]/i', '', $line); |
| | | // ... and only allow strict url() values |
| | | $regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims'; |
| | | if (stripos($stripped, 'url(') && !preg_match($regexp, $line)) { |
| | | $a_styles = array('/* evil! */'); |
| | | break; |
| | | } |
| | | } |
| | | $styles = join(";\n", $a_styles); |
| | | } |
| | | |
| | | $key = $replacements->add($styles); |
| | | $source = substr($source, 0, $pos+1) |
| | | . $replacements->get_replacement($key) |
| | | . substr($source, $pos2, strlen($source)-$pos2); |
| | | $last_pos = $pos+2; |
| | | } |
| | | |
| | | // remove html comments and add #container to each tag selector. |
| | | // also replace body definition because we also stripped off the <body> tag |
| | | $styles = preg_replace( |
| | | array( |
| | | '/(^\s*<!--)|(-->\s*$)/', |
| | | '/(^\s*|,\s*|\}\s*)([a-z0-9\._#\*][a-z0-9\.\-_]*)/im', |
| | | '/'.preg_quote($container_id, '/').'\s+body/i', |
| | | ), |
| | | array( |
| | | '', |
| | | "\\1#$container_id \\2", |
| | | $container_id, |
| | | ), |
| | | $source); |
| | | |
| | | // put block contents back in |
| | | $styles = $replacements->resolve($styles); |
| | | |
| | | return $styles; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Generate CSS classes from mimetype and filename extension |
| | | * |
| | | * @param string $mimetype Mimetype |
| | | * @param string $filename Filename |
| | | * |
| | | * @return string CSS classes separated by space |
| | | */ |
| | | public static function file2class($mimetype, $filename) |
| | | { |
| | | list($primary, $secondary) = explode('/', $mimetype); |
| | | |
| | | $classes = array($primary ? $primary : 'unknown'); |
| | | if ($secondary) { |
| | | $classes[] = $secondary; |
| | | } |
| | | if (preg_match('/\.([a-z0-9]+)$/i', $filename, $m)) { |
| | | $classes[] = $m[1]; |
| | | } |
| | | |
| | | return strtolower(join(" ", $classes)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Decode escaped entities used by known XSS exploits. |
| | | * See http://downloads.securityfocus.com/vulnerabilities/exploits/26800.eml for examples |
| | | * |
| | | * @param string CSS content to decode |
| | | * |
| | | * @return string Decoded string |
| | | */ |
| | | public static function xss_entity_decode($content) |
| | | { |
| | | $out = html_entity_decode(html_entity_decode($content)); |
| | | $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', |
| | | array(self, 'xss_entity_decode_callback'), $out); |
| | | $out = preg_replace('#/\*.*\*/#Ums', '', $out); |
| | | |
| | | return $out; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * preg_replace_callback callback for xss_entity_decode |
| | | * |
| | | * @param array $matches Result from preg_replace_callback |
| | | * |
| | | * @return string Decoded entity |
| | | */ |
| | | public static function xss_entity_decode_callback($matches) |
| | | { |
| | | return chr(hexdec($matches[1])); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check if we can process not exceeding memory_limit |
| | | * |
| | | * @param integer Required amount of memory |
| | | * |
| | | * @return boolean True if memory won't be exceeded, False otherwise |
| | | */ |
| | | public static function mem_check($need) |
| | | { |
| | | $mem_limit = parse_bytes(ini_get('memory_limit')); |
| | | $memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB |
| | | |
| | | return $mem_limit > 0 && $memory + $need > $mem_limit ? false : true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Check if working in SSL mode |
| | | * |
| | | * @param integer $port HTTPS port number |
| | | * @param boolean $use_https Enables 'use_https' option checking |
| | | * |
| | | * @return boolean |
| | | */ |
| | | public static function https_check($port=null, $use_https=true) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') { |
| | | return true; |
| | | } |
| | | if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') { |
| | | return true; |
| | | } |
| | | if ($port && $_SERVER['SERVER_PORT'] == $port) { |
| | | return true; |
| | | } |
| | | if ($use_https && isset($RCMAIL) && $RCMAIL->config->get('use_https')) { |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Replaces hostname variables. |
| | | * |
| | | * @param string $name Hostname |
| | | * @param string $host Optional IMAP hostname |
| | | * |
| | | * @return string Hostname |
| | | */ |
| | | public static function parse_host($name, $host = '') |
| | | { |
| | | // %n - host |
| | | $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']); |
| | | // %d - domain name without first part, e.g. %n=mail.domain.tld, %d=domain.tld |
| | | $d = preg_replace('/^[^\.]+\./', '', $n); |
| | | // %h - IMAP host |
| | | $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host; |
| | | // %z - IMAP domain without first part, e.g. %h=imap.domain.tld, %z=domain.tld |
| | | $z = preg_replace('/^[^\.]+\./', '', $h); |
| | | // %s - domain name after the '@' from e-mail address provided at login screen. Returns FALSE if an invalid email is provided |
| | | if (strpos($name, '%s') !== false) { |
| | | $user_email = self::get_input_value('_user', self::INPUT_POST); |
| | | $user_email = rcube_idn_convert($user_email, true); |
| | | $matches = preg_match('/(.*)@([a-z0-9\.\-\[\]\:]+)/i', $user_email, $s); |
| | | if ($matches < 1 || filter_var($s[1]."@".$s[2], FILTER_VALIDATE_EMAIL) === false) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | $name = str_replace(array('%n', '%d', '%h', '%z', '%s'), array($n, $d, $h, $z, $s[2]), $name); |
| | | return $name; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns remote IP address and forwarded addresses if found |
| | | * |
| | | * @return string Remote IP address(es) |
| | | */ |
| | | public static function remote_ip() |
| | | { |
| | | $address = $_SERVER['REMOTE_ADDR']; |
| | | |
| | | // append the NGINX X-Real-IP header, if set |
| | | if (!empty($_SERVER['HTTP_X_REAL_IP'])) { |
| | | $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP']; |
| | | } |
| | | // append the X-Forwarded-For header, if set |
| | | if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
| | | $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR']; |
| | | } |
| | | |
| | | if (!empty($remote_ip)) { |
| | | $address .= '(' . implode(',', $remote_ip) . ')'; |
| | | } |
| | | |
| | | return $address; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Read a specific HTTP request header. |
| | | * |
| | | * @param string $name Header name |
| | | * |
| | | * @return mixed Header value or null if not available |
| | | */ |
| | | public static function request_header($name) |
| | | { |
| | | if (function_exists('getallheaders')) { |
| | | $hdrs = array_change_key_case(getallheaders(), CASE_UPPER); |
| | | $key = strtoupper($name); |
| | | } |
| | | else { |
| | | $key = 'HTTP_' . strtoupper(strtr($name, '-', '_')); |
| | | $hdrs = array_change_key_case($_SERVER, CASE_UPPER); |
| | | } |
| | | |
| | | return $hdrs[$key]; |
| | | } |
| | | |
| | | /** |
| | | * Explode quoted string |
| | | * |
| | | * @param string Delimiter expression string for preg_match() |
| | | * @param string Input string |
| | | * |
| | | * @return array String items |
| | | */ |
| | | public static function explode_quoted_string($delimiter, $string) |
| | | { |
| | | $result = array(); |
| | | $strlen = strlen($string); |
| | | |
| | | for ($q=$p=$i=0; $i < $strlen; $i++) { |
| | | if ($string[$i] == "\"" && $string[$i-1] != "\\") { |
| | | $q = $q ? false : true; |
| | | } |
| | | else if (!$q && preg_match("/$delimiter/", $string[$i])) { |
| | | $result[] = substr($string, $p, $i - $p); |
| | | $p = $i + 1; |
| | | } |
| | | } |
| | | |
| | | $result[] = substr($string, $p); |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Improved equivalent to strtotime() |
| | | * |
| | | * @param string $date Date string |
| | | * |
| | | * @return int Unix timestamp |
| | | */ |
| | | public static function strtotime($date) |
| | | { |
| | | // check for MS Outlook vCard date format YYYYMMDD |
| | | if (preg_match('/^([12][90]\d\d)([01]\d)(\d\d)$/', trim($date), $matches)) { |
| | | return mktime(0,0,0, intval($matches[2]), intval($matches[3]), intval($matches[1])); |
| | | } |
| | | else if (is_numeric($date)) { |
| | | return $date; |
| | | } |
| | | |
| | | // support non-standard "GMTXXXX" literal |
| | | $date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date); |
| | | |
| | | // if date parsing fails, we have a date in non-rfc format. |
| | | // remove token from the end and try again |
| | | while ((($ts = @strtotime($date)) === false) || ($ts < 0)) { |
| | | $d = explode(' ', $date); |
| | | array_pop($d); |
| | | if (!$d) { |
| | | break; |
| | | } |
| | | $date = implode(' ', $d); |
| | | } |
| | | |
| | | return $ts; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | public static function idn_to_ascii($str) |
| | | { |
| | | return self::idn_convert($str, true); |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Idn_to_ascii wrapper. |
| | | * Intl/Idn modules version of this function doesn't work with e-mail address |
| | | */ |
| | | public static function idn_to_utf8($str) |
| | | { |
| | | return self::idn_convert($str, false); |
| | | } |
| | | |
| | | |
| | | public static function idn_convert($input, $is_utf=false) |
| | | { |
| | | if ($at = strpos($input, '@')) { |
| | | $user = substr($input, 0, $at); |
| | | $domain = substr($input, $at+1); |
| | | } |
| | | else { |
| | | $domain = $input; |
| | | } |
| | | |
| | | $domain = $is_utf ? idn_to_ascii($domain) : idn_to_utf8($domain); |
| | | |
| | | if ($domain === false) { |
| | | return ''; |
| | | } |
| | | |
| | | return $at ? $user . '@' . $domain : $domain; |
| | | } |
| | | |
| | | } |