Page MenuHomePhorge

No OneTemporary

Size
317 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/index.php b/index.php
index 550ee0c33..6f761a4ee 100644
--- a/index.php
+++ b/index.php
@@ -1,275 +1,275 @@
<?php
/*
+-------------------------------------------------------------------------+
| Roundcube Webmail IMAP Client |
| Version 0.8-svn |
| |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License version 2 |
| as published by the Free Software Foundation. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License along |
| with this program; if not, write to the Free Software Foundation, Inc., |
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| |
+-------------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-------------------------------------------------------------------------+
$Id$
*/
// include environment
require_once 'program/include/iniset.php';
// init application, start session, init output class, etc.
$RCMAIL = rcmail::get_instance();
// Make the whole PHP output non-cacheable (#1487797)
send_nocacheing_headers();
// turn on output buffering
ob_start();
// check if config files had errors
if ($err_str = $RCMAIL->config->get_error()) {
raise_error(array(
'code' => 601,
'type' => 'php',
'message' => $err_str), false, true);
}
// check DB connections and exit on failure
if ($err_str = $DB->is_error()) {
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);
}
// 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_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']);
exit;
}
}
// trigger startup plugin hook
$startup = $RCMAIL->plugins->exec_hook('startup', array('task' => $RCMAIL->task, 'action' => $RCMAIL->action));
$RCMAIL->set_task($startup['task']);
$RCMAIL->action = $startup['action'];
// try to log in
if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') {
$request_valid = $_SESSION['temp'] && $RCMAIL->check_request(RCUBE_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(get_input_value('_user', RCUBE_INPUT_POST)),
'pass' => get_input_value('_pass', RCUBE_INPUT_POST, true,
$RCMAIL->config->get('password_charset', 'ISO-8859-1')),
'cookiecheck' => true,
'valid' => $request_valid,
));
// check if client supports cookies
if ($auth['cookiecheck'] && empty($_COOKIE)) {
$OUTPUT->show_message("cookiesdisabled", 'warning');
}
else if ($auth['valid'] && !$auth['abort'] &&
!empty($auth['host']) && !empty($auth['user']) &&
$RCMAIL->login($auth['user'], $auth['pass'], $auth['host'])
) {
// create new session ID, don't destroy the current session
// it was destroyed already by $RCMAIL->kill_session() above
$RCMAIL->session->remove('temp');
$RCMAIL->session->regenerate_id(false);
// send auth cookie if necessary
$RCMAIL->session->set_auth_cookie();
// log successful login
rcmail_log_login();
// restore original request parameters
$query = array();
if ($url = get_input_value('_url', RCUBE_INPUT_POST)) {
parse_str($url, $query);
// prevent endless looping on login page
if ($query['_task'] == 'login')
unset($query['_task']);
}
// allow plugins to control the redirect url after login success
$redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail'));
unset($redir['abort'], $redir['_err']);
// send redirect
$OUTPUT->redirect($redir);
}
else {
- $error_code = is_object($IMAP) ? $IMAP->get_error_code() : -1;
+ $error_code = (isset($RCMAIL->imap) && is_object($RCMAIL->imap)) ? $RCMAIL->imap->get_error_code() : 1;
$OUTPUT->show_message($error_code < -1 ? 'imaperror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning');
$RCMAIL->plugins->exec_hook('login_failed', array(
'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user']));
$RCMAIL->kill_session();
}
}
// end session (after optional referer check)
else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL->config->get('referer_check') || rcube_check_referer())) {
$userdata = array('user' => $_SESSION['username'], 'host' => $_SESSION['imap_host'], 'lang' => $RCMAIL->user->language);
$OUTPUT->show_message('loggedout');
$RCMAIL->logout_actions();
$RCMAIL->kill_session();
$RCMAIL->plugins->exec_hook('logout_after', $userdata);
}
// check session and auth cookie
else if ($RCMAIL->task != 'login' && $_SESSION['user_id'] && $RCMAIL->action != 'send') {
if (!$RCMAIL->session->check_auth()) {
$RCMAIL->kill_session();
$session_error = true;
}
}
// not logged in -> show login page
if (empty($RCMAIL->user->ID)) {
// log session failures
if (($task = get_input_value('_task', RCUBE_INPUT_GPC)) && !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;
}
if ($OUTPUT->ajax_call)
$OUTPUT->redirect(array('_err' => 'session'), 2000);
if (!empty($_REQUEST['_framed']))
$OUTPUT->command('redirect', $RCMAIL->url(array('_err' => 'session')));
// check if installer is still active
if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) {
$OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"),
html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") .
html::p(null, "The install script of your Roundcube installation is still stored in its default location!") .
html::p(null, "Please <b>remove</b> the whole <tt>installer</tt> folder from the Roundcube directory because .
these files may expose sensitive configuration data like server passwords and encryption keys
to the public. Make sure you cannot access the <a href=\"./installer/\">installer script</a> from your browser.")
)
);
}
if ($session_error || $_REQUEST['_err'] == 'session')
$OUTPUT->show_message('sessionerror', 'error', null, true, -1);
$RCMAIL->set_task('login');
$OUTPUT->send('login');
}
// CSRF prevention
else {
// don't check for valid request tokens in these actions
$request_check_whitelist = array('login'=>1, 'spell'=>1);
// check client X-header to verify request origin
if ($OUTPUT->ajax_call) {
if (rc_request_header('X-Roundcube-Request') != $RCMAIL->get_request_token() && !$RCMAIL->config->get('devel_mode')) {
header('HTTP/1.1 403 Forbidden');
die("Invalid Request");
}
}
// check request token in POST form submissions
else if (!empty($_POST) && !$request_check_whitelist[$RCMAIL->action] && !$RCMAIL->check_request()) {
$OUTPUT->show_message('invalidrequest', 'error');
$OUTPUT->send($RCMAIL->task);
}
// check referer if configured
if (!$request_check_whitelist[$RCMAIL->action] && $RCMAIL->config->get('referer_check') && !rcube_check_referer()) {
raise_error(array(
'code' => 403,
'type' => 'php',
'message' => "Referer check failed"), true, true);
}
}
// we're ready, user is authenticated and the request is safe
$plugin = $RCMAIL->plugins->exec_hook('ready', array('task' => $RCMAIL->task, 'action' => $RCMAIL->action));
$RCMAIL->set_task($plugin['task']);
$RCMAIL->action = $plugin['action'];
// handle special actions
if ($RCMAIL->action == 'keep-alive') {
$OUTPUT->reset();
$RCMAIL->plugins->exec_hook('keep_alive', array());
$OUTPUT->send();
}
else if ($RCMAIL->action == 'save-pref') {
include INSTALL_PATH . 'program/steps/utils/save_pref.inc';
}
// include task specific functions
if (is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/func.inc'))
include_once $incfile;
// allow 5 "redirects" to another action
$redirects = 0; $incstep = null;
while ($redirects < 5) {
// execute a plugin action
if ($RCMAIL->plugins->is_plugin_task($RCMAIL->task)) {
if (!$RCMAIL->action) $RCMAIL->action = 'index';
$RCMAIL->plugins->exec_action($RCMAIL->task.'.'.$RCMAIL->action);
break;
}
else if (preg_match('/^plugin\./', $RCMAIL->action)) {
$RCMAIL->plugins->exec_action($RCMAIL->action);
break;
}
// try to include the step file
else if (($stepfile = $RCMAIL->get_action_file())
&& is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/'.$stepfile)
) {
include $incfile;
$redirects++;
}
else {
break;
}
}
// parse main template (default)
$OUTPUT->send($RCMAIL->task);
// if we arrive here, something went wrong
raise_error(array(
'code' => 404,
'type' => 'php',
'line' => __LINE__,
'file' => __FILE__,
'message' => "Invalid request"), true, true);
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 733573f1c..9f26450a1 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -1,1691 +1,1690 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcmail.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2008-2011, The Roundcube Dev Team |
| Copyright (C) 2011, Kolab Systems AG |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Application class providing core functions and holding |
| instances of all 'global' objects like db- and imap-connections |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
/**
* Application class of Roundcube Webmail
* implemented as singleton
*
* @package Core
*/
class rcmail
{
/**
* Main tasks.
*
* @var array
*/
static public $main_tasks = array('mail','settings','addressbook','login','logout','utils','dummy');
/**
* Singleton instace of rcmail
*
* @var rcmail
*/
static private $instance;
/**
* Stores instance of rcube_config.
*
* @var rcube_config
*/
public $config;
/**
* Stores rcube_user instance.
*
* @var rcube_user
*/
public $user;
/**
* Instace of database class.
*
* @var rcube_mdb2
*/
public $db;
/**
* Instace of Memcache class.
*
* @var rcube_mdb2
*/
public $memcache;
/**
* Instace of rcube_session class.
*
* @var rcube_session
*/
public $session;
/**
* Instance of rcube_smtp class.
*
* @var rcube_smtp
*/
public $smtp;
/**
* Instance of rcube_imap class.
*
* @var rcube_imap
*/
public $imap;
/**
* Instance of rcube_template class.
*
* @var rcube_template
*/
public $output;
/**
* Instance of rcube_plugin_api.
*
* @var rcube_plugin_api
*/
public $plugins;
/**
* Current task.
*
* @var string
*/
public $task;
/**
* Current action.
*
* @var string
*/
public $action = '';
public $comm_path = './';
private $texts;
private $address_books = array();
private $caches = array();
private $action_map = array();
private $shutdown_functions = array();
/**
* This implements the 'singleton' design pattern
*
* @return rcmail The one and only instance
*/
static function get_instance()
{
if (!self::$instance) {
self::$instance = new rcmail();
self::$instance->startup(); // init AFTER object was linked with self::$instance
}
return self::$instance;
}
/**
* Private constructor
*/
private function __construct()
{
// load configuration
$this->config = new rcube_config();
register_shutdown_function(array($this, 'shutdown'));
}
/**
* Initial startup function
* to register session, create database and imap connections
*
* @todo Remove global vars $DB, $USER
*/
private function startup()
{
// initialize syslog
if ($this->config->get('log_driver') == 'syslog') {
$syslog_id = $this->config->get('syslog_id', 'roundcube');
$syslog_facility = $this->config->get('syslog_facility', LOG_USER);
openlog($syslog_id, LOG_ODELAY, $syslog_facility);
}
// connect to database
$GLOBALS['DB'] = $this->get_dbh();
// start session
$this->session_init();
// create user object
$this->set_user(new rcube_user($_SESSION['user_id']));
// configure session (after user config merge!)
$this->session_configure();
// set task and action properties
$this->set_task(get_input_value('_task', RCUBE_INPUT_GPC));
$this->action = asciiwords(get_input_value('_action', RCUBE_INPUT_GPC));
// reset some session parameters when changing task
if ($this->task != 'utils') {
if ($this->session && $_SESSION['task'] != $this->task)
$this->session->remove('page');
// set current task to session
$_SESSION['task'] = $this->task;
}
// init output class
if (!empty($_REQUEST['_remote']))
$GLOBALS['OUTPUT'] = $this->json_init();
else
$GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
// create plugin API and load plugins
$this->plugins = rcube_plugin_api::get_instance();
// init plugins
$this->plugins->init();
}
/**
* Setter for application task
*
* @param string Task to set
*/
public function set_task($task)
{
$task = asciiwords($task);
if ($this->user && $this->user->ID)
$task = !$task ? 'mail' : $task;
else
$task = 'login';
$this->task = $task;
$this->comm_path = $this->url(array('task' => $this->task));
if ($this->output)
$this->output->set_env('task', $this->task);
}
/**
* Setter for system user object
*
* @param rcube_user Current user instance
*/
public function set_user($user)
{
if (is_object($user)) {
$this->user = $user;
$GLOBALS['USER'] = $this->user;
// overwrite config with user preferences
$this->config->set_user_prefs((array)$this->user->get_prefs());
}
$_SESSION['language'] = $this->user->language = $this->language_prop($this->config->get('language', $_SESSION['language']));
// set localization
setlocale(LC_ALL, $_SESSION['language'] . '.utf8', 'en_US.utf8');
// workaround for http://bugs.php.net/bug.php?id=18556
if (in_array($_SESSION['language'], array('tr_TR', 'ku', 'az_AZ')))
setlocale(LC_CTYPE, 'en_US' . '.utf8');
}
/**
* Check the given string and return a valid language code
*
* @param string Language code
* @return string Valid language code
*/
private function language_prop($lang)
{
static $rcube_languages, $rcube_language_aliases;
// user HTTP_ACCEPT_LANGUAGE if no language is specified
if (empty($lang) || $lang == 'auto') {
$accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$lang = str_replace('-', '_', $accept_langs[0]);
}
if (empty($rcube_languages)) {
@include(INSTALL_PATH . 'program/localization/index.inc');
}
// check if we have an alias for that language
if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) {
$lang = $rcube_language_aliases[$lang];
}
// try the first two chars
else if (!isset($rcube_languages[$lang])) {
$short = substr($lang, 0, 2);
// check if we have an alias for the short language code
if (!isset($rcube_languages[$short]) && isset($rcube_language_aliases[$short])) {
$lang = $rcube_language_aliases[$short];
}
// expand 'nn' to 'nn_NN'
else if (!isset($rcube_languages[$short])) {
$lang = $short.'_'.strtoupper($short);
}
}
if (!isset($rcube_languages[$lang]) || !is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
$lang = 'en_US';
}
return $lang;
}
/**
* Get the current database connection
*
* @return rcube_mdb2 Database connection object
*/
public function get_dbh()
{
if (!$this->db) {
$config_all = $this->config->all();
$this->db = new rcube_mdb2($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
$this->db->sqlite_initials = INSTALL_PATH . 'SQL/sqlite.initial.sql';
$this->db->set_debug((bool)$config_all['sql_debug']);
}
return $this->db;
}
/**
* Get global handle for memcache access
*
* @return object Memcache
*/
public function get_memcache()
{
if (!isset($this->memcache)) {
// no memcache support in PHP
if (!class_exists('Memcache')) {
$this->memcache = false;
return false;
}
$this->memcache = new Memcache;
$this->mc_available = 0;
// add alll configured hosts to pool
$pconnect = $this->config->get('memcache_pconnect', true);
foreach ($this->config->get('memcache_hosts', array()) as $host) {
list($host, $port) = explode(':', $host);
if (!$port) $port = 11211;
$this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
}
// test connection and failover (will result in $this->mc_available == 0 on complete failure)
$this->memcache->increment('__CONNECTIONTEST__', 1); // NOP if key doesn't exist
if (!$this->mc_available)
$this->memcache = false;
}
return $this->memcache;
}
/**
* Callback for memcache failure
*/
public function memcache_failure($host, $port)
{
static $seen = array();
// only report once
if (!$seen["$host:$port"]++) {
$this->mc_available--;
raise_error(array('code' => 604, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => "Memcache failure on host $host:$port"),
true, false);
}
}
/**
* Initialize and get cache object
*
* @param string $name Cache identifier
* @param string $type Cache type ('db', 'apc' or 'memcache')
* @param int $ttl Expiration time for cache items in seconds
* @param bool $packed Enables/disables data serialization
*
* @return rcube_cache Cache object
*/
public function get_cache($name, $type='db', $ttl=0, $packed=true)
{
if (!isset($this->caches[$name])) {
$this->caches[$name] = new rcube_cache($type, $_SESSION['user_id'], $name, $ttl, $packed);
}
return $this->caches[$name];
}
/**
* Return instance of the internal address book class
*
* @param string Address book identifier
* @param boolean True if the address book needs to be writeable
*
* @return rcube_contacts Address book object
*/
public function get_address_book($id, $writeable = false)
{
$contacts = null;
$ldap_config = (array)$this->config->get('ldap_public');
$abook_type = strtolower($this->config->get('address_book_type'));
// 'sql' is the alias for '0' used by autocomplete
if ($id == 'sql')
$id = '0';
// use existing instance
if (isset($this->address_books[$id]) && is_object($this->address_books[$id])
&& is_a($this->address_books[$id], 'rcube_addressbook')
&& (!$writeable || !$this->address_books[$id]->readonly)
) {
$contacts = $this->address_books[$id];
}
else if ($id && $ldap_config[$id]) {
$contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['imap_host']));
}
else if ($id === '0') {
$contacts = new rcube_contacts($this->db, $this->user->ID);
}
else {
$plugin = $this->plugins->exec_hook('addressbook_get', array('id' => $id, 'writeable' => $writeable));
// plugin returned instance of a rcube_addressbook
if ($plugin['instance'] instanceof rcube_addressbook) {
$contacts = $plugin['instance'];
}
// get first source from the list
else if (!$id) {
$source = reset($this->get_address_sources($writeable));
if (!empty($source)) {
$contacts = $this->get_address_book($source['id']);
if ($contacts)
$id = $source['id'];
}
}
}
if (!$contacts) {
raise_error(array(
'code' => 700, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Addressbook source ($id) not found!"),
true, true);
}
// add to the 'books' array for shutdown function
$this->address_books[$id] = $contacts;
return $contacts;
}
/**
* Return address books list
*
* @param boolean True if the address book needs to be writeable
*
* @return array Address books array
*/
public function get_address_sources($writeable = false)
{
$abook_type = strtolower($this->config->get('address_book_type'));
$ldap_config = $this->config->get('ldap_public');
$autocomplete = (array) $this->config->get('autocomplete_addressbooks');
$list = array();
// We are using the DB address book
if ($abook_type != 'ldap') {
if (!isset($this->address_books['0']))
$this->address_books['0'] = new rcube_contacts($this->db, $this->user->ID);
$list['0'] = array(
'id' => '0',
'name' => rcube_label('personaladrbook'),
'groups' => $this->address_books['0']->groups,
'readonly' => $this->address_books['0']->readonly,
'autocomplete' => in_array('sql', $autocomplete),
'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
);
}
if ($ldap_config) {
$ldap_config = (array) $ldap_config;
foreach ($ldap_config as $id => $prop)
$list[$id] = array(
'id' => $id,
'name' => $prop['name'],
'groups' => is_array($prop['groups']),
'readonly' => !$prop['writable'],
'hidden' => $prop['hidden'],
'autocomplete' => in_array($id, $autocomplete)
);
}
$plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list));
$list = $plugin['sources'];
foreach ($list as $idx => $item) {
// register source for shutdown function
if (!is_object($this->address_books[$item['id']]))
$this->address_books[$item['id']] = $item;
// remove from list if not writeable as requested
if ($writeable && $item['readonly'])
unset($list[$idx]);
}
return $list;
}
/**
* Init output object for GUI and add common scripts.
* This will instantiate a rcmail_template object and set
* environment vars according to the current session and configuration
*
* @param boolean True if this request is loaded in a (i)frame
* @return rcube_template Reference to HTML output object
*/
public function load_gui($framed = false)
{
// init output page
if (!($this->output instanceof rcube_template))
$this->output = new rcube_template($this->task, $framed);
// set keep-alive/check-recent interval
if ($this->session && ($keep_alive = $this->session->get_keep_alive())) {
$this->output->set_env('keep_alive', $keep_alive);
}
if ($framed) {
$this->comm_path .= '&_framed=1';
$this->output->set_env('framed', true);
}
$this->output->set_env('task', $this->task);
$this->output->set_env('action', $this->action);
$this->output->set_env('comm_path', $this->comm_path);
$this->output->set_charset(RCMAIL_CHARSET);
// add some basic labels to client
$this->output->add_label('loading', 'servererror');
return $this->output;
}
/**
* Create an output object for JSON responses
*
* @return rcube_json_output Reference to JSON output object
*/
public function json_init()
{
if (!($this->output instanceof rcube_json_output))
$this->output = new rcube_json_output($this->task);
return $this->output;
}
/**
* Create SMTP object and connect to server
*
* @param boolean True if connection should be established
*/
public function smtp_init($connect = false)
{
$this->smtp = new rcube_smtp();
if ($connect)
$this->smtp->connect();
}
/**
* Create global IMAP object and connect to server
*
* @param boolean True if connection should be established
- * @todo Remove global $IMAP
*/
public function imap_init($connect = false)
{
// already initialized
if (is_object($this->imap))
return;
$this->imap = new rcube_imap();
$this->imap->skip_deleted = $this->config->get('skip_deleted');
// enable caching of imap data
$imap_cache = $this->config->get('imap_cache');
$messages_cache = $this->config->get('messages_cache');
// for backward compatybility
if ($imap_cache === null && $messages_cache === null && $this->config->get('enable_caching')) {
$imap_cache = 'db';
$messages_cache = true;
}
if ($imap_cache)
$this->imap->set_caching($imap_cache);
if ($messages_cache)
$this->imap->set_messages_caching(true);
// set pagesize from config
$this->imap->set_pagesize($this->config->get('pagesize', 50));
// Setting root and delimiter before establishing the connection
// can save time detecting them using NAMESPACE and LIST
$options = array(
'auth_type' => $this->config->get('imap_auth_type', 'check'),
'auth_cid' => $this->config->get('imap_auth_cid'),
'auth_pw' => $this->config->get('imap_auth_pw'),
'debug' => (bool) $this->config->get('imap_debug', 0),
'force_caps' => (bool) $this->config->get('imap_force_caps'),
'timeout' => (int) $this->config->get('imap_timeout', 0),
);
$this->imap->set_options($options);
// set global object for backward compatibility
$GLOBALS['IMAP'] = $this->imap;
$hook = $this->plugins->exec_hook('imap_init', array('fetch_headers' => $this->imap->fetch_add_headers));
if ($hook['fetch_headers'])
$this->imap->fetch_add_headers = $hook['fetch_headers'];
// support this parameter for backward compatibility but log warning
if ($connect) {
$this->imap_connect();
raise_error(array(
'code' => 800, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "rcube::imap_init(true) is deprecated, use rcube::imap_connect() instead"),
true, false);
}
}
/**
* Connect to IMAP server with stored session data
*
* @return bool True on success, false on error
*/
public function imap_connect()
{
if (!$this->imap)
$this->imap_init();
if ($_SESSION['imap_host'] && !$this->imap->conn->connected()) {
if (!$this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])) {
if ($this->output)
$this->output->show_message($this->imap->get_error_code() == -1 ? 'imaperror' : 'sessionerror', 'error');
}
else {
$this->set_imap_prop();
return $this->imap->conn;
}
}
return false;
}
/**
* Create session object and start the session.
*/
public function session_init()
{
// session started (Installer?)
if (session_id())
return;
$sess_name = $this->config->get('session_name');
$sess_domain = $this->config->get('session_domain');
$lifetime = $this->config->get('session_lifetime', 0) * 60;
// set session domain
if ($sess_domain) {
ini_set('session.cookie_domain', $sess_domain);
}
// set session garbage collecting time according to session_lifetime
if ($lifetime) {
ini_set('session.gc_maxlifetime', $lifetime * 2);
}
ini_set('session.cookie_secure', rcube_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);
ini_set('session.serialize_handler', 'php');
// use database for storing session data
$this->session = new rcube_session($this->get_dbh(), $this->config);
$this->session->register_gc_handler('rcmail_temp_gc');
if ($this->config->get('enable_caching'))
$this->session->register_gc_handler('rcmail_cache_gc');
// start PHP session (if not in CLI mode)
if ($_SERVER['REMOTE_ADDR'])
session_start();
// set initial session vars
if (!$_SESSION['user_id'])
$_SESSION['temp'] = true;
}
/**
* Configure session object internals
*/
public function session_configure()
{
if (!$this->session)
return;
$lifetime = $this->config->get('session_lifetime', 0) * 60;
// set keep-alive/check-recent interval
if ($keep_alive = $this->config->get('keep_alive')) {
// be sure that it's less than session lifetime
if ($lifetime)
$keep_alive = min($keep_alive, $lifetime - 30);
$keep_alive = max(60, $keep_alive);
$this->session->set_keep_alive($keep_alive);
}
$this->session->set_secret($this->config->get('des_key') . $_SERVER['HTTP_USER_AGENT']);
$this->session->set_ip_check($this->config->get('ip_check'));
}
/**
* Perfom login to the IMAP server and to the webmail service.
* This will also create a new user entry if auto_create_user is configured.
*
* @param string IMAP user name
* @param string IMAP password
* @param string IMAP host
* @return boolean True on success, False on failure
*/
function login($username, $pass, $host=NULL)
{
$user = NULL;
$config = $this->config->all();
if (!$host)
$host = $config['default_host'];
// Validate that selected host is in the list of configured hosts
if (is_array($config['default_host'])) {
$allowed = false;
foreach ($config['default_host'] as $key => $host_allowed) {
if (!is_numeric($key))
$host_allowed = $key;
if ($host == $host_allowed) {
$allowed = true;
break;
}
}
if (!$allowed)
return false;
}
else if (!empty($config['default_host']) && $host != rcube_parse_host($config['default_host']))
return false;
// parse $host URL
$a_host = parse_url($host);
if ($a_host['host']) {
$host = $a_host['host'];
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
if (!empty($a_host['port']))
$imap_port = $a_host['port'];
else if ($imap_ssl && $imap_ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143))
$imap_port = 993;
}
$imap_port = $imap_port ? $imap_port : $config['default_port'];
/* Modify username with domain if required
Inspired by Marco <P0L0_notspam_binware.org>
*/
// Check if we need to add domain
if (!empty($config['username_domain']) && strpos($username, '@') === false) {
if (is_array($config['username_domain']) && isset($config['username_domain'][$host]))
$username .= '@'.rcube_parse_host($config['username_domain'][$host], $host);
else if (is_string($config['username_domain']))
$username .= '@'.rcube_parse_host($config['username_domain'], $host);
}
// Convert username to lowercase. If IMAP backend
// is case-insensitive we need to store always the same username (#1487113)
if ($config['login_lc']) {
$username = mb_strtolower($username);
}
// try to resolve email address from virtuser table
if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) {
$username = $virtuser;
}
// Here we need IDNA ASCII
// Only rcube_contacts class is using domain names in Unicode
$host = rcube_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);
}
// user already registered -> overwrite username
if ($user = rcube_user::query($username, $host))
$username = $user->data['username'];
if (!$this->imap)
$this->imap_init();
// try IMAP login
if (!($imap_login = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl))) {
// try with lowercase
$username_lc = mb_strtolower($username);
if ($username_lc != $username) {
// try to find user record again -> overwrite username
if (!$user && ($user = rcube_user::query($username_lc, $host)))
$username_lc = $user->data['username'];
if ($imap_login = $this->imap->connect($host, $username_lc, $pass, $imap_port, $imap_ssl))
$username = $username_lc;
}
}
// exit if IMAP login failed
if (!$imap_login)
return false;
// user already registered -> update user's record
if (is_object($user)) {
// update last login timestamp
$user->touch();
}
// create new system user
else if ($config['auto_create_user']) {
if ($created = rcube_user::create($username, $host)) {
$user = $created;
}
else {
raise_error(array(
'code' => 620, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Failed to create a user record. Maybe aborted by a plugin?"
), true, false);
}
}
else {
raise_error(array(
'code' => 621, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Access denied for new user $username. 'auto_create_user' is disabled"
), true, false);
}
// login succeeded
if (is_object($user) && $user->ID) {
// Configure environment
$this->set_user($user);
$this->set_imap_prop();
$this->session_configure();
// fix some old settings according to namespace prefix
$this->fix_namespace_settings($user);
// create default folders on first login
if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) {
$this->imap->create_default_folders();
}
// set session vars
$_SESSION['user_id'] = $user->ID;
$_SESSION['username'] = $user->data['username'];
$_SESSION['imap_host'] = $host;
$_SESSION['imap_port'] = $imap_port;
$_SESSION['imap_ssl'] = $imap_ssl;
$_SESSION['password'] = $this->encrypt($pass);
$_SESSION['login_time'] = mktime();
if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_')
$_SESSION['timezone'] = floatval($_REQUEST['_timezone']);
if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_')
$_SESSION['dst_active'] = intval($_REQUEST['_dstactive']);
// force reloading complete list of subscribed mailboxes
$this->imap->clear_cache('mailboxes', true);
return true;
}
return false;
}
/**
* Set root dir and last stored mailbox
* This must be done AFTER connecting to the server!
*/
public function set_imap_prop()
{
$this->imap->set_charset($this->config->get('default_charset', RCMAIL_CHARSET));
if ($default_folders = $this->config->get('default_imap_folders')) {
$this->imap->set_default_mailboxes($default_folders);
}
if (isset($_SESSION['mbox'])) {
$this->imap->set_mailbox($_SESSION['mbox']);
}
if (isset($_SESSION['page'])) {
$this->imap->set_page($_SESSION['page']);
}
}
/**
* Auto-select IMAP host based on the posted login information
*
* @return string Selected IMAP host
*/
public function autoselect_host()
{
$default_host = $this->config->get('default_host');
$host = null;
if (is_array($default_host)) {
$post_host = get_input_value('_host', RCUBE_INPUT_POST);
// direct match in default_host array
if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) {
$host = $post_host;
}
// try to select host by mail domain
list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST));
if (!empty($domain)) {
foreach ($default_host as $imap_host => $mail_domains) {
if (is_array($mail_domains) && in_array($domain, $mail_domains)) {
$host = $imap_host;
break;
}
}
}
// take the first entry if $host is still an array
if (empty($host)) {
$host = array_shift($default_host);
}
}
else if (empty($default_host)) {
$host = get_input_value('_host', RCUBE_INPUT_POST);
}
else
$host = rcube_parse_host($default_host);
return $host;
}
/**
* Get localized text in the desired language
*
* @param mixed $attrib Named parameters array or label name
* @param string $domain Label domain (plugin) name
*
* @return string Localized text
*/
public function gettext($attrib, $domain=null)
{
// load localization files if not done yet
if (empty($this->texts))
$this->load_language();
// extract attributes
if (is_string($attrib))
$attrib = array('name' => $attrib);
$name = $attrib['name'] ? $attrib['name'] : '';
// attrib contain text values: use them from now
if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
$this->texts[$name] = $setval;
// check for text with domain
if ($domain && ($text = $this->texts[$domain.'.'.$name]))
;
// text does not exist
else if (!($text = $this->texts[$name])) {
return "[$name]";
}
// replace vars in text
if (is_array($attrib['vars'])) {
foreach ($attrib['vars'] as $var_key => $var_value)
$text = str_replace($var_key[0]!='$' ? '$'.$var_key : $var_key, $var_value, $text);
}
// format output
if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst'])
return ucfirst($text);
else if ($attrib['uppercase'])
return mb_strtoupper($text);
else if ($attrib['lowercase'])
return mb_strtolower($text);
return strtr($text, array('\n' => "\n"));
}
/**
* Check if the given text label exists
*
* @param string $name Label name
* @param string $domain Label domain (plugin) name or '*' for all domains
* @param string $ref_domain Sets domain name if label is found
*
* @return boolean True if text exists (either in the current language or in en_US)
*/
public function text_exists($name, $domain = null, &$ref_domain = null)
{
// load localization files if not done yet
if (empty($this->texts))
$this->load_language();
if (isset($this->texts[$name])) {
$ref_domain = '';
return true;
}
// any of loaded domains (plugins)
if ($domain == '*') {
foreach ($this->plugins->loaded_plugins() as $domain)
if (isset($this->texts[$domain.'.'.$name])) {
$ref_domain = $domain;
return true;
}
}
// specified domain
else if ($domain) {
$ref_domain = $domain;
return isset($this->texts[$domain.'.'.$name]);
}
return false;
}
/**
* Load a localization package
*
* @param string Language ID
*/
public function load_language($lang = null, $add = array())
{
$lang = $this->language_prop(($lang ? $lang : $_SESSION['language']));
// load localized texts
if (empty($this->texts) || $lang != $_SESSION['language']) {
$this->texts = array();
// handle empty lines after closing PHP tag in localization files
ob_start();
// get english labels (these should be complete)
@include(INSTALL_PATH . 'program/localization/en_US/labels.inc');
@include(INSTALL_PATH . 'program/localization/en_US/messages.inc');
if (is_array($labels))
$this->texts = $labels;
if (is_array($messages))
$this->texts = array_merge($this->texts, $messages);
// include user language files
if ($lang != 'en' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc');
include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc');
if (is_array($labels))
$this->texts = array_merge($this->texts, $labels);
if (is_array($messages))
$this->texts = array_merge($this->texts, $messages);
}
ob_end_clean();
$_SESSION['language'] = $lang;
}
// append additional texts (from plugin)
if (is_array($add) && !empty($add))
$this->texts += $add;
}
/**
* Read directory program/localization and return a list of available languages
*
* @return array List of available localizations
*/
public function list_languages()
{
static $sa_languages = array();
if (!sizeof($sa_languages)) {
@include(INSTALL_PATH . 'program/localization/index.inc');
if ($dh = @opendir(INSTALL_PATH . 'program/localization')) {
while (($name = readdir($dh)) !== false) {
if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name))
continue;
if ($label = $rcube_languages[$name])
$sa_languages[$name] = $label;
}
closedir($dh);
}
}
return $sa_languages;
}
/**
* Destroy session data and remove cookie
*/
public function kill_session()
{
$this->plugins->exec_hook('session_destroy');
$this->session->kill();
$_SESSION = array('language' => $this->user->language, 'temp' => true);
$this->user->reset();
}
/**
* Do server side actions on logout
*/
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->imap_connect();
}
if ($config['logout_purge'] && !empty($config['trash_mbox'])) {
$this->imap->clear_mailbox($config['trash_mbox']);
}
if ($config['logout_expunge']) {
$this->imap->expunge('INBOX');
}
// Try to save unsaved user preferences
if (!empty($_SESSION['preferences'])) {
$this->user->save_prefs(unserialize($_SESSION['preferences']));
}
}
/**
* Function to be executed in script shutdown
* Registered with register_shutdown_function()
*/
public function shutdown()
{
foreach ($this->shutdown_functions as $function)
call_user_func($function);
if (is_object($this->smtp))
$this->smtp->disconnect();
foreach ($this->address_books as $book) {
if (is_object($book) && is_a($book, 'rcube_addressbook'))
$book->close();
}
foreach ($this->caches as $cache) {
if (is_object($cache))
$cache->close();
}
if (is_object($this->imap))
$this->imap->close();
// before closing the database connection, write session data
if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
session_write_close();
}
// write performance stats to logs/console
if ($this->config->get('devel_mode')) {
if (function_exists('memory_get_usage'))
$mem = show_bytes(memory_get_usage());
if (function_exists('memory_get_peak_usage'))
$mem .= '/'.show_bytes(memory_get_peak_usage());
$log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : '');
if (defined('RCMAIL_START'))
rcube_print_time(RCMAIL_START, $log);
else
console($log);
}
}
/**
* Registers shutdown function to be executed on shutdown.
* The functions will be executed before destroying any
* objects like smtp, imap, session, etc.
*
* @param callback Function callback
*/
public function add_shutdown_function($function)
{
$this->shutdown_functions[] = $function;
}
/**
* Generate a unique token to be used in a form request
*
* @return string The request token
*/
public function get_request_token()
{
$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->user->ID . $this->config->get('des_key') . $sess_id)));
return $plugin['value'];
}
/**
* Check if the current request contains a valid token
*
* @param int Request method
* @return boolean True if request token is valid false if not
*/
public function check_request($mode = RCUBE_INPUT_POST)
{
$token = get_input_value('_token', $mode);
$sess_id = $_COOKIE[ini_get('session.name')];
return !empty($sess_id) && $token == $this->get_request_token();
}
/**
* Create unique authorization hash
*
* @param string Session ID
* @param int Timestamp
* @return string The generated auth hash
*/
private function get_auth_hash($sess_id, $ts)
{
$auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s',
$sess_id,
$ts,
$this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***',
$_SERVER['HTTP_USER_AGENT']);
if (function_exists('sha1'))
return sha1($auth_string);
else
return md5($auth_string);
}
/**
* Encrypt using 3DES
*
* @param string $clear clear text input
* @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
* @param boolean $base64 whether or not to base64_encode() the result before returning
*
* @return string encrypted text
*/
public function encrypt($clear, $key = 'des_key', $base64 = true)
{
if (!$clear)
return '';
/*-
* Add a single canary byte to the end of the clear text, which
* will help find out how much of padding will need to be removed
* upon decryption; see http://php.net/mcrypt_generic#68082
*/
$clear = pack("a*H2", $clear, "80");
if (function_exists('mcrypt_module_open') &&
($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")))
{
$iv = $this->create_iv(mcrypt_enc_get_iv_size($td));
mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
$cipher = $iv . mcrypt_generic($td, $clear);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
else {
@include_once 'des.inc';
if (function_exists('des')) {
$des_iv_size = 8;
$iv = $this->create_iv($des_iv_size);
$cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv);
}
else {
raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available"
), true, true);
}
}
return $base64 ? base64_encode($cipher) : $cipher;
}
/**
* Decrypt 3DES-encrypted string
*
* @param string $cipher encrypted text
* @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
* @param boolean $base64 whether or not input is base64-encoded
*
* @return string decrypted text
*/
public function decrypt($cipher, $key = 'des_key', $base64 = true)
{
if (!$cipher)
return '';
$cipher = $base64 ? base64_decode($cipher) : $cipher;
if (function_exists('mcrypt_module_open') &&
($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, "")))
{
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = substr($cipher, 0, $iv_size);
// session corruption? (#1485970)
if (strlen($iv) < $iv_size)
return '';
$cipher = substr($cipher, $iv_size);
mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
$clear = mdecrypt_generic($td, $cipher);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
else {
@include_once 'des.inc';
if (function_exists('des')) {
$des_iv_size = 8;
$iv = substr($cipher, 0, $des_iv_size);
$cipher = substr($cipher, $des_iv_size);
$clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv);
}
else {
raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available"
), true, true);
}
}
/*-
* Trim PHP's padding and the canary byte; see note in
* rcmail::encrypt() and http://php.net/mcrypt_generic#68082
*/
$clear = substr(rtrim($clear, "\0"), 0, -1);
return $clear;
}
/**
* Generates encryption initialization vector (IV)
*
* @param int Vector size
* @return string Vector string
*/
private function create_iv($size)
{
// mcrypt_create_iv() can be slow when system lacks entrophy
// we'll generate IV vector manually
$iv = '';
for ($i = 0; $i < $size; $i++)
$iv .= chr(mt_rand(0, 255));
return $iv;
}
/**
* 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)
{
if (!is_array($p))
$p = array('_action' => @func_get_arg(0));
$task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task);
$p['_task'] = $task;
unset($p['task']);
$url = './';
$delm = '?';
foreach (array_reverse($p) as $key => $val) {
if ($val !== '') {
$par = $key[0] == '_' ? $key : '_'.$key;
$url .= $delm.urlencode($par).'='.urlencode($val);
$delm = '&';
}
}
return $url;
}
/**
* 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)
{
$rcmail = rcmail::get_instance();
if ($cmd = $rcmail->config->get('im_identify_path', false)) {
list(, $type, $size) = explode(' ', strtolower(rcmail::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;
$rcmail = rcmail::get_instance();
$convert = $rcmail->config->get('im_convert_path', false);
$identify = $rcmail->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(rcmail::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 = rcmail::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
*
* @param $cmd Format string with {keywords} to be replaced
* @param $values (zero, one or more arrays can be passed)
* @return output of command. shell errors not detectable
*/
public static function exec(/* $cmd, $values1 = array(), ... */)
{
$args = func_get_args();
$cmd = array_shift($args);
$values = $replacements = array();
// merge values into one array
foreach ($args as $arg)
$values += (array)$arg;
preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER);
foreach ($matches as $tags) {
list(, $tag, $option, $key) = $tags;
$parts = array();
if ($option) {
foreach ((array)$values["-$key"] as $key => $value) {
if ($value === true || $value === false || $value === null)
$parts[] = $value ? $key : "";
else foreach ((array)$value as $val)
$parts[] = "$key " . escapeshellarg($val);
}
}
else {
foreach ((array)$values[$key] as $value)
$parts[] = escapeshellarg($value);
}
$replacements[$tag] = join(" ", $parts);
}
// use strtr behaviour of going through source string once
$cmd = strtr($cmd, $replacements);
return (string)shell_exec($cmd);
}
/**
* 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_https_check(), true);
}
/**
* Registers action aliases for current task
*
* @param array $map Alias-to-filename hash array
*/
public function register_action_map($map)
{
if (is_array($map)) {
foreach ($map as $idx => $val) {
$this->action_map[$idx] = $val;
}
}
}
/**
* Returns current action filename
*
* @param array $map Alias-to-filename hash array
*/
public function get_action_file()
{
if (!empty($this->action_map[$this->action])) {
return $this->action_map[$this->action];
}
return strtr($this->action, '-', '_') . '.inc';
}
/**
* Fixes some user preferences according to namespace handling change.
* Old Roundcube versions were using folder names with removed namespace prefix.
* Now we need to add the prefix on servers where personal namespace has prefix.
*
* @param rcube_user $user User object
*/
private function fix_namespace_settings($user)
{
$prefix = $this->imap->get_namespace('prefix');
$prefix_len = strlen($prefix);
if (!$prefix_len)
return;
$prefs = $this->config->all();
if (!empty($prefs['namespace_fixed']))
return;
// Build namespace prefix regexp
$ns = $this->imap->get_namespace();
$regexp = array();
foreach ($ns as $entry) {
if (!empty($entry)) {
foreach ($entry as $item) {
if (strlen($item[0])) {
$regexp[] = preg_quote($item[0], '/');
}
}
}
}
$regexp = '/^('. implode('|', $regexp).')/';
// Fix preferences
$opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
foreach ($opts as $opt) {
if ($value = $prefs[$opt]) {
if ($value != 'INBOX' && !preg_match($regexp, $value)) {
$prefs[$opt] = $prefix.$value;
}
}
}
if (!empty($prefs['default_imap_folders'])) {
foreach ($prefs['default_imap_folders'] as $idx => $name) {
if ($name != 'INBOX' && !preg_match($regexp, $name)) {
$prefs['default_imap_folders'][$idx] = $prefix.$name;
}
}
}
if (!empty($prefs['search_mods'])) {
$folders = array();
foreach ($prefs['search_mods'] as $idx => $value) {
if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
$idx = $prefix.$idx;
}
$folders[$idx] = $value;
}
$prefs['search_mods'] = $folders;
}
if (!empty($prefs['message_threading'])) {
$folders = array();
foreach ($prefs['message_threading'] as $idx => $value) {
if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
$idx = $prefix.$idx;
}
$folders[$prefix.$idx] = $value;
}
$prefs['message_threading'] = $folders;
}
if (!empty($prefs['collapsed_folders'])) {
$folders = explode('&&', $prefs['collapsed_folders']);
$count = count($folders);
$folders_str = '';
if ($count) {
$folders[0] = substr($folders[0], 1);
$folders[$count-1] = substr($folders[$count-1], 0, -1);
}
foreach ($folders as $value) {
if ($value != 'INBOX' && !preg_match($regexp, $value)) {
$value = $prefix.$value;
}
$folders_str .= '&'.$value.'&';
}
$prefs['collapsed_folders'] = $folders_str;
}
$prefs['namespace_fixed'] = true;
// save updated preferences and reset imap settings (default folders)
$user->save_prefs($prefs);
$this->set_imap_prop();
}
}
diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc
index a4feb7b58..0120852a9 100644
--- a/program/steps/mail/addcontact.inc
+++ b/program/steps/mail/addcontact.inc
@@ -1,94 +1,94 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/addcontact.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Add the submitted contact to the users address book |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
return;
$abook = $RCMAIL->config->get('default_addressbook');
// Get configured addressbook
$CONTACTS = $RCMAIL->get_address_book($abook, true);
// Get first writeable addressbook if the configured doesn't exist
// This can happen when user deleted the addressbook (e.g. Kolab folder)
if ($abook == null || !is_object($CONTACTS)) {
$source = reset($RCMAIL->get_address_sources(true));
$CONTACTS = $RCMAIL->get_address_book($source['id'], true);
}
if (!empty($_POST['_address']) && is_object($CONTACTS))
{
- $contact_arr = $IMAP->decode_address_list(get_input_value('_address', RCUBE_INPUT_POST, true), 1, false);
+ $contact_arr = $RCMAIL->imap->decode_address_list(get_input_value('_address', RCUBE_INPUT_POST, true), 1, false);
if (!empty($contact_arr[1]['mailto'])) {
$contact = array(
'email' => $contact_arr[1]['mailto'],
'name' => $contact_arr[1]['name']
);
// Validity checks
if (empty($contact['email'])) {
$OUTPUT->show_message('errorsavingcontact', 'error');
$OUTPUT->send();
}
$email = rcube_idn_to_ascii($contact['email']);
if (!check_email($email, false)) {
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $contact['email']));
$OUTPUT->send();
}
$contact['email'] = rcube_idn_to_utf8($contact['email']);
$contact['name'] = rcube_addressbook::compose_display_name($contact);
// validate contact record
if (!$CONTACTS->validate($contact, true)) {
$error = $CONTACTS->get_error();
// TODO: show dialog to complete record
// if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { }
$OUTPUT->show_message($error['message'] ? $error['message'] : 'errorsavingcontact', 'error');
$OUTPUT->send();
}
// check for existing contacts
$existing = $CONTACTS->search('email', $contact['email'], 1, false);
if ($done = $existing->count)
$OUTPUT->show_message('contactexists', 'warning');
else {
$plugin = $RCMAIL->plugins->exec_hook('contact_create', array('record' => $contact, 'source' => null));
$contact = $plugin['record'];
$done = !$plugin['abort'] ? $CONTACTS->insert($contact) : $plugin['result'];
if ($done)
$OUTPUT->show_message('addedsuccessfully', 'confirmation');
}
}
}
if (!$done)
$OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsavingcontact', 'error');
$OUTPUT->send();
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index ab0d3c818..498bf0ce1 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -1,103 +1,103 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/check_recent.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2010, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Check for recent messages, in all mailboxes |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
-$current = $IMAP->get_mailbox_name();
+$current = $RCMAIL->imap->get_mailbox_name();
$check_all = !empty($_GET['_refresh']) || (bool)$RCMAIL->config->get('check_all_folders');
// list of folders to check
if ($check_all) {
- $a_mailboxes = $IMAP->list_mailboxes('', '*', 'mail');
+ $a_mailboxes = $RCMAIL->imap->list_mailboxes('', '*', 'mail');
}
else {
$a_mailboxes = (array) $current;
if ($a_mailboxes[0] != 'INBOX')
$a_mailboxes[] = 'INBOX';
}
// check recent/unseen counts
foreach ($a_mailboxes as $mbox_name) {
$is_current = $mbox_name == $current;
if ($is_current) {
// Synchronize mailbox cache, handle flag changes
- $IMAP->mailbox_sync($mbox_name);
+ $RCMAIL->imap->mailbox_sync($mbox_name);
}
// Get mailbox status
- $status = $IMAP->mailbox_status($mbox_name);
+ $status = $RCMAIL->imap->mailbox_status($mbox_name);
if ($status & 1) {
// trigger plugin hook
$RCMAIL->plugins->exec_hook('new_messages',
array('mailbox' => $mbox_name, 'is_current' => $is_current));
}
rcmail_send_unread_count($mbox_name, true, null,
(!$is_current && ($status & 1)) ? 'recent' : '');
if ($status && $is_current) {
// refresh saved search set
$search_request = get_input_value('_search', RCUBE_INPUT_GPC);
if ($search_request && isset($_SESSION['search'])
&& $_SESSION['search_request'] == $search_request
) {
- $_SESSION['search'] = $IMAP->refresh_search();
+ $_SESSION['search'] = $RCMAIL->imap->refresh_search();
}
if (!empty($_GET['_quota']))
$OUTPUT->command('set_quota', rcmail_quota_content());
// "No-list" mode, don't get messages
if (empty($_GET['_list']))
continue;
// get overall message count; allow caching because rcube_imap::mailbox_status() did a refresh
- $all_count = $IMAP->messagecount(null, $IMAP->threading ? 'THREADS' : 'ALL');
+ $all_count = $RCMAIL->imap->messagecount(null, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
// check current page if we're not on the first page
- if ($all_count && $IMAP->list_page > 1) {
- $remaining = $all_count - $IMAP->page_size * ($IMAP->list_page - 1);
+ if ($all_count && $RCMAIL->imap->list_page > 1) {
+ $remaining = $all_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1);
if ($remaining <= 0) {
- $IMAP->set_page($IMAP->list_page-1);
- $_SESSION['page'] = $IMAP->list_page;
+ $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1);
+ $_SESSION['page'] = $RCMAIL->imap->list_page;
}
}
$OUTPUT->set_env('messagecount', $all_count);
- $OUTPUT->set_env('pagecount', ceil($all_count/$IMAP->page_size));
+ $OUTPUT->set_env('pagecount', ceil($all_count/$RCMAIL->imap->page_size));
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count), $mbox_name);
- $OUTPUT->set_env('current_page', $all_count ? $IMAP->list_page : 1);
+ $OUTPUT->set_env('current_page', $all_count ? $RCMAIL->imap->list_page : 1);
// remove old rows (and clear selection if new list is empty)
$OUTPUT->command('message_list.clear', $all_count ? false : true);
if ($all_count) {
- $a_headers = $IMAP->list_headers($mbox_name, null, $_SESSION['sort_col'], $_SESSION['sort_order']);
+ $a_headers = $RCMAIL->imap->list_headers($mbox_name, null, $_SESSION['sort_col'], $_SESSION['sort_order']);
// add message rows
rcmail_js_message_list($a_headers, false);
// remove messages that don't exists from list selection array
$OUTPUT->command('update_selection');
}
}
}
$RCMAIL->plugins->exec_hook('keep_alive', array());
$OUTPUT->send();
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 03619f1a2..c3863e448 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -1,1497 +1,1497 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/compose.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Compose a new mail message with all headers and attachments |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// define constants for message compose mode
define('RCUBE_COMPOSE_REPLY', 0x0106);
define('RCUBE_COMPOSE_FORWARD', 0x0107);
define('RCUBE_COMPOSE_DRAFT', 0x0108);
define('RCUBE_COMPOSE_EDIT', 0x0109);
$MESSAGE_FORM = null;
$MESSAGE = null;
$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET);
$COMPOSE = null;
if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID])
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
// give replicated session storage some time to synchronize
$retries = 0;
while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) {
usleep(500000);
$RCMAIL->session->reload();
if ($_SESSION['compose_data_'.$COMPOSE_ID])
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
}
// Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or
// if a compose-ID is given (i.e. when the compose step is opened in a new window/tab).
if (!is_array($COMPOSE))
{
// Infinite redirect prevention in case of broken session (#1487028)
if ($COMPOSE_ID)
raise_error(array('code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, true);
$COMPOSE_ID = uniqid(mt_rand());
$_SESSION['compose_data_'.$COMPOSE_ID] = array(
'id' => $COMPOSE_ID,
'param' => request2param(RCUBE_INPUT_GET),
- 'mailbox' => $IMAP->get_mailbox_name(),
+ 'mailbox' => $RCMAIL->imap->get_mailbox_name(),
);
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
// process values like "mailto:foo@bar.com?subject=new+message&cc=another"
if ($COMPOSE['param']['to']) {
// #1486037: remove "mailto:" prefix
$COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $COMPOSE['param']['to']);
$mailto = explode('?', $COMPOSE['param']['to']);
if (count($mailto) > 1) {
$COMPOSE['param']['to'] = $mailto[0];
parse_str($mailto[1], $query);
foreach ($query as $f => $val)
$COMPOSE['param'][$f] = $val;
}
}
// select folder where to save the sent message
$COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
// pipe compose parameters thru plugins
$plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE);
$COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']);
// add attachments listed by message_compose hook
if (is_array($plugin['attachments'])) {
foreach ($plugin['attachments'] as $attach) {
// we have structured data
if (is_array($attach)) {
$attachment = $attach;
}
// only a file path is given
else {
$filename = basename($attach);
$attachment = array(
'group' => $COMPOSE_ID,
'name' => $filename,
'mimetype' => rc_mime_content_type($attach, $filename),
'path' => $attach,
);
}
// save attachment if valid
if (($attachment['data'] && $attachment['name']) || ($attachment['path'] && file_exists($attachment['path']))) {
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment);
}
if ($attachment['status'] && !$attachment['abort']) {
unset($attachment['data'], $attachment['status'], $attachment['abort']);
$COMPOSE['attachments'][$attachment['id']] = $attachment;
}
}
}
// check if folder for saving sent messages exists and is subscribed (#1486802)
if ($sent_folder = $COMPOSE['param']['sent_mbox']) {
rcmail_check_sent_folder($sent_folder, true);
}
// redirect to a unique URL with all parameters stored in session
$OUTPUT->redirect(array('_action' => 'compose', '_id' => $COMPOSE['id']));
}
// add some labels to client
$OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel',
'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage',
'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
'fileuploaderror', 'sendmessage');
$OUTPUT->set_env('compose_id', $COMPOSE['id']);
// add config parameters to client script
if (!empty($CONFIG['drafts_mbox'])) {
$OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
$OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']);
}
// set current mailbox in client environment
-$OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
+$OUTPUT->set_env('mailbox', $RCMAIL->imap->get_mailbox_name());
$OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false));
$OUTPUT->set_env('top_posting', $RCMAIL->config->get('top_posting', false));
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
// use jquery UI for showing prompt() dialogs
$RCMAIL->plugins->load_plugin('jqueryui');
// default font for HTML editor
$font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana'));
if ($font && !is_array($font)) {
$OUTPUT->set_env('default_font', $font);
}
// get reference message and set compose mode
if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']);
$compose_mode = RCUBE_COMPOSE_DRAFT;
}
else if ($msg_uid = $COMPOSE['param']['reply_uid'])
$compose_mode = RCUBE_COMPOSE_REPLY;
else if ($msg_uid = $COMPOSE['param']['forward_uid'])
$compose_mode = RCUBE_COMPOSE_FORWARD;
else if ($msg_uid = $COMPOSE['param']['uid'])
$compose_mode = RCUBE_COMPOSE_EDIT;
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
if ($config_show_sig == 1)
$OUTPUT->set_env('show_sig', true);
else if ($config_show_sig == 2 && (empty($compose_mode) || $compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT))
$OUTPUT->set_env('show_sig', true);
else if ($config_show_sig == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD))
$OUTPUT->set_env('show_sig', true);
else
$OUTPUT->set_env('show_sig', false);
// set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72);
if (!empty($msg_uid))
{
// similar as in program/steps/mail/show.inc
// re-set 'prefer_html' to have possibility to use html part for compose
$CONFIG['prefer_html'] = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
$MESSAGE = new rcube_message($msg_uid);
// make sure message is marked as read
if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']))
- $IMAP->set_flag($msg_uid, 'SEEN');
+ $RCMAIL->imap->set_flag($msg_uid, 'SEEN');
if (!empty($MESSAGE->headers->charset))
- $IMAP->set_charset($MESSAGE->headers->charset);
+ $RCMAIL->imap->set_charset($MESSAGE->headers->charset);
if ($compose_mode == RCUBE_COMPOSE_REPLY)
{
$COMPOSE['reply_uid'] = $msg_uid;
$COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID;
$COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
if (!empty($COMPOSE['param']['all']))
$MESSAGE->reply_all = $COMPOSE['param']['all'];
$OUTPUT->set_env('compose_mode', 'reply');
// Save the sent message in the same folder of the message being replied to
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox'])
&& rcmail_check_sent_folder($sent_folder, false)
) {
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
{
if ($MESSAGE->headers->others['x-draft-info'])
{
// get reply_uid/forward_uid to flag the original message when sending
$info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
if ($info['type'] == 'reply')
$COMPOSE['reply_uid'] = $info['uid'];
else if ($info['type'] == 'forward')
$COMPOSE['forward_uid'] = $info['uid'];
$COMPOSE['mailbox'] = $info['folder'];
// Save the sent message in the same folder of the message being replied to
if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder'])
&& rcmail_check_sent_folder($sent_folder, false)
) {
$COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
if ($MESSAGE->headers->in_reply_to)
$COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
$COMPOSE['references'] = $MESSAGE->headers->references;
}
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
{
$COMPOSE['forward_uid'] = $msg_uid;
$OUTPUT->set_env('compose_mode', 'forward');
if (!empty($COMPOSE['param']['attachment']))
$MESSAGE->forward_attachment = true;
}
}
$MESSAGE->compose = array();
// get user's identities
$MESSAGE->identities = $USER->list_identities();
if (count($MESSAGE->identities))
{
foreach ($MESSAGE->identities as $idx => $ident) {
$email = mb_strtolower(rcube_idn_to_utf8($ident['email']));
$MESSAGE->identities[$idx]['email_ascii'] = $ident['email'];
$MESSAGE->identities[$idx]['ident'] = format_email_recipient($ident['email'], $ident['name']);
$MESSAGE->identities[$idx]['email'] = $email;
}
}
// Set From field value
if (!empty($_POST['_from'])) {
$MESSAGE->compose['from'] = get_input_value('_from', RCUBE_INPUT_POST);
}
else if (!empty($COMPOSE['param']['from'])) {
$MESSAGE->compose['from'] = $COMPOSE['param']['from'];
}
else if (count($MESSAGE->identities)) {
$a_recipients = array();
$a_names = array();
// extract all recipients of the reply-message
if (is_object($MESSAGE->headers) && in_array($compose_mode, array(RCUBE_COMPOSE_REPLY, RCUBE_COMPOSE_FORWARD)))
{
- $a_to = $IMAP->decode_address_list($MESSAGE->headers->to);
+ $a_to = $RCMAIL->imap->decode_address_list($MESSAGE->headers->to);
foreach ($a_to as $addr) {
if (!empty($addr['mailto'])) {
$a_recipients[] = strtolower($addr['mailto']);
$a_names[] = $addr['name'];
}
}
if (!empty($MESSAGE->headers->cc)) {
- $a_cc = $IMAP->decode_address_list($MESSAGE->headers->cc);
+ $a_cc = $RCMAIL->imap->decode_address_list($MESSAGE->headers->cc);
foreach ($a_cc as $addr) {
if (!empty($addr['mailto'])) {
$a_recipients[] = strtolower($addr['mailto']);
$a_names[] = $addr['name'];
}
}
}
}
$from_idx = null;
$default_identity = null;
$return_path = $MESSAGE->headers->others['return-path'];
// Select identity
foreach ($MESSAGE->identities as $idx => $ident) {
// save default identity ID
if ($ident['standard']) {
$default_identity = $idx;
}
// use From header
if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
if ($MESSAGE->headers->from == $ident['ident']) {
$from_idx = $idx;
break;
}
}
// reply to yourself
else if ($compose_mode == RCUBE_COMPOSE_REPLY && $MESSAGE->headers->from == $ident['ident']) {
$from_idx = $idx;
break;
}
// use replied message recipients
else if (($found = array_search($ident['email_ascii'], $a_recipients)) !== false) {
// match identity name, prefer default identity
if ($from_idx === null || ($a_names[$found] && $ident['name'] && $a_names[$found] == $ident['name'])) {
$from_idx = $idx;
}
}
}
// Fallback using Return-Path
if ($from_idx === null && $return_path) {
foreach ($MESSAGE->identities as $idx => $ident) {
if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) {
$from_idx = $idx;
break;
}
}
}
// Still no ID, use default/first identity
if ($from_idx === null) {
$from_idx = $default_identity !== null ? $default_identity : key(reset($MESSAGE->identities));
}
$ident = $MESSAGE->identities[$from_idx];
$from_id = $ident['identity_id'];
$MESSAGE->compose['from_email'] = $ident['email'];
$MESSAGE->compose['from'] = $from_id;
}
// Set other headers
$a_recipients = array();
$parts = array('to', 'cc', 'bcc', 'replyto', 'followupto');
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
foreach ($parts as $header) {
$fvalue = '';
$decode_header = true;
// we have a set of recipients stored is session
if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto'])
&& $_SESSION['mailto'][$mailto_id]
) {
$fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
$decode_header = false;
// make session to not grow up too much
unset($_SESSION['mailto'][$mailto_id]);
$COMPOSE['param']['to'] = $fvalue;
}
else if (!empty($_POST['_'.$header])) {
$fvalue = get_input_value('_'.$header, RCUBE_INPUT_POST, TRUE);
}
else if (!empty($COMPOSE['param'][$header])) {
$fvalue = $COMPOSE['param'][$header];
}
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
// get recipent address(es) out of the message headers
if ($header == 'to') {
$mailfollowup = $MESSAGE->headers->others['mail-followup-to'];
$mailreplyto = $MESSAGE->headers->others['mail-reply-to'];
// Reply to mailing list...
if ($MESSAGE->reply_all == 'list' && $mailfollowup)
$fvalue = $mailfollowup;
else if ($MESSAGE->reply_all == 'list'
&& preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m))
$fvalue = $m[1];
// Reply to...
else if ($MESSAGE->reply_all && $mailfollowup)
$fvalue = $mailfollowup;
else if ($mailreplyto)
$fvalue = $mailreplyto;
else if (!empty($MESSAGE->headers->replyto))
$fvalue = $MESSAGE->headers->replyto;
else if (!empty($MESSAGE->headers->from))
$fvalue = $MESSAGE->headers->from;
// Reply to message sent by yourself (#1487074)
if (!empty($ident) && $fvalue == $ident['ident']) {
$fvalue = $MESSAGE->headers->to;
}
}
// add recipient of original message if reply to all
else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') {
if ($v = $MESSAGE->headers->to)
$fvalue .= $v;
if ($v = $MESSAGE->headers->cc)
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
}
}
else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
// get drafted headers
if ($header=='to' && !empty($MESSAGE->headers->to))
$fvalue = $MESSAGE->get_header('to');
else if ($header=='cc' && !empty($MESSAGE->headers->cc))
$fvalue = $MESSAGE->get_header('cc');
else if ($header=='bcc' && !empty($MESSAGE->headers->bcc))
$fvalue = $MESSAGE->get_header('bcc');
else if ($header=='replyto' && !empty($MESSAGE->headers->others['mail-reply-to']))
$fvalue = $MESSAGE->get_header('mail-reply-to');
else if ($header=='replyto' && !empty($MESSAGE->headers->replyto))
$fvalue = $MESSAGE->get_header('reply-to');
else if ($header=='followupto' && !empty($MESSAGE->headers->others['mail-followup-to']))
$fvalue = $MESSAGE->get_header('mail-followup-to');
}
// split recipients and put them back together in a unique way
if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) {
- $to_addresses = $IMAP->decode_address_list($fvalue, null, $decode_header);
+ $to_addresses = $RCMAIL->imap->decode_address_list($fvalue, null, $decode_header);
$fvalue = array();
foreach ($to_addresses as $addr_part) {
if (empty($addr_part['mailto']))
continue;
$mailto = mb_strtolower(rcube_idn_to_utf8($addr_part['mailto']));
if (!in_array($mailto, $a_recipients)
&& ($header == 'to' || empty($MESSAGE->compose['from_email']) || $mailto != $MESSAGE->compose['from_email'])
) {
if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name'])
$string = format_email_recipient($mailto, $addr_part['name']);
else
$string = $mailto;
$fvalue[] = $string;
$a_recipients[] = $addr_part['mailto'];
}
}
$fvalue = implode($separator, $fvalue);
}
$MESSAGE->compose[$header] = $fvalue;
}
unset($a_recipients);
// process $MESSAGE body/attachments, set $MESSAGE_BODY/$HTML_MODE vars and some session data
$MESSAGE_BODY = rcmail_prepare_message_body();
/****** compose mode functions ********/
function rcmail_compose_headers($attrib)
{
global $MESSAGE;
list($form_start, $form_end) = get_form_tags($attrib);
$out = '';
$part = strtolower($attrib['part']);
switch ($part)
{
case 'from':
return $form_start . rcmail_compose_header_from($attrib);
case 'to':
case 'cc':
case 'bcc':
$fname = '_' . $part;
$header = $param = $part;
$allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex');
$field_type = 'html_textarea';
break;
case 'replyto':
case 'reply-to':
$fname = '_replyto';
$param = 'replyto';
$header = 'reply-to';
case 'followupto':
case 'followup-to':
if (!$fname) {
$fname = '_followupto';
$param = 'followupto';
$header = 'mail-followup-to';
}
$allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
$field_type = 'html_inputfield';
break;
}
if ($fname && $field_type)
{
// pass the following attributes to the form class
$field_attrib = array('name' => $fname, 'spellcheck' => 'false');
foreach ($attrib as $attr => $value)
if (in_array($attr, $allow_attrib))
$field_attrib[$attr] = $value;
// create teaxtarea object
$input = new $field_type($field_attrib);
$out = $input->show($MESSAGE->compose[$param]);
}
if ($form_start)
$out = $form_start.$out;
// configure autocompletion
rcube_autocomplete_init();
return $out;
}
function rcmail_compose_header_from($attrib)
{
global $MESSAGE, $OUTPUT;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
foreach ($attrib as $attr => $value)
if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
$field_attrib[$attr] = $value;
if (count($MESSAGE->identities))
{
$a_signatures = array();
$field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)";
$select_from = new html_select($field_attrib);
// create SELECT element
foreach ($MESSAGE->identities as $sql_arr)
{
$identity_id = $sql_arr['identity_id'];
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
// add signature to array
if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig']))
{
$a_signatures[$identity_id]['text'] = $sql_arr['signature'];
$a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
if ($a_signatures[$identity_id]['is_html'])
{
$h2t = new html2text($a_signatures[$identity_id]['text'], false, false);
$a_signatures[$identity_id]['plain_text'] = trim($h2t->get_text());
}
}
}
$out = $select_from->show($MESSAGE->compose['from']);
// add signatures to client
$OUTPUT->set_env('signatures', $a_signatures);
}
// no identities, display text input field
else {
$field_attrib['class'] = 'from_address';
$input_from = new html_inputfield($field_attrib);
$out = $input_from->show($MESSAGE->compose['from']);
}
return $out;
}
function rcmail_compose_editor_mode()
{
global $RCMAIL, $MESSAGE, $compose_mode;
static $useHtml;
if ($useHtml !== null)
return $useHtml;
$html_editor = intval($RCMAIL->config->get('htmleditor'));
if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
$useHtml = $MESSAGE->has_html_part();
}
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
$useHtml = ($html_editor == 1 || ($html_editor == 2 && $MESSAGE->has_html_part()));
}
else { // RCUBE_COMPOSE_FORWARD or NEW
$useHtml = ($html_editor == 1);
}
return $useHtml;
}
function rcmail_prepare_message_body()
{
global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
// use posted message body
if (!empty($_POST['_message'])) {
$body = get_input_value('_message', RCUBE_INPUT_POST, true);
$isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
}
else if ($COMPOSE['param']['body']) {
$body = $COMPOSE['param']['body'];
$isHtml = false;
}
// forward as attachment
else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) {
$isHtml = rcmail_compose_editor_mode();
$body = '';
if (empty($COMPOSE['attachments']))
rcmail_write_forward_attachment($MESSAGE);
}
// reply/edit/draft/forward
else if ($compose_mode) {
$has_html_part = $MESSAGE->has_html_part();
$isHtml = rcmail_compose_editor_mode();
if ($isHtml) {
if ($has_html_part) {
$body = $MESSAGE->first_html_part();
}
else {
$body = $MESSAGE->first_text_part();
// try to remove the signature
if ($RCMAIL->config->get('strip_existing_sig', true))
$body = rcmail_remove_signature($body);
// add HTML formatting
$body = rcmail_plain_body($body);
if ($body)
$body = '<pre>' . $body . '</pre>';
}
}
else {
if ($has_html_part) {
// use html part if it has been used for message (pre)viewing
// decrease line length for quoting
$len = $compose_mode == RCUBE_COMPOSE_REPLY ? $LINE_LENGTH-2 : $LINE_LENGTH;
$txt = new html2text($MESSAGE->first_html_part(), false, true, $len);
$body = $txt->get_text();
}
else {
$body = $MESSAGE->first_text_part($part);
if ($body && $part && $part->ctype_secondary == 'plain'
&& $part->ctype_parameters['format'] == 'flowed'
) {
$body = rcube_message::unfold_flowed($body);
}
}
}
// compose reply-body
if ($compose_mode == RCUBE_COMPOSE_REPLY)
$body = rcmail_create_reply_body($body, $isHtml);
// forward message body inline
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
$body = rcmail_create_forward_body($body, $isHtml);
// load draft message body
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT)
$body = rcmail_create_draft_body($body, $isHtml);
}
else { // new message
$isHtml = rcmail_compose_editor_mode();
}
$plugin = $RCMAIL->plugins->exec_hook('message_compose_body',
array('body' => $body, 'html' => $isHtml, 'mode' => $compose_mode));
$body = $plugin['body'];
unset($plugin);
// add blocked.gif attachment (#1486516)
if ($isHtml && preg_match('#<img src="\./program/blocked\.gif"#', $body)) {
if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
$body = preg_replace('#\./program/blocked\.gif#',
$RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'],
$body);
}
}
$HTML_MODE = $isHtml;
return $body;
}
function rcmail_compose_body($attrib)
{
global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE, $MESSAGE_BODY;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (empty($attrib['id']))
$attrib['id'] = 'rcmComposeBody';
$attrib['name'] = '_message';
$isHtml = $HTML_MODE;
$out = $form_start ? "$form_start\n" : '';
$saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE->headers->messageID) : ''));
$out .= $saveid->show();
$drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes'));
$out .= $drafttoggle->show();
$msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0")));
$out .= $msgtype->show();
// If desired, set this textarea to be editable by TinyMCE
if ($isHtml) {
$attrib['class'] = 'mce_editor';
$textarea = new html_textarea($attrib);
$out .= $textarea->show($MESSAGE_BODY);
}
else {
$textarea = new html_textarea($attrib);
$out .= $textarea->show('');
// quote plain text, inject into textarea
$table = get_html_translation_table(HTML_SPECIALCHARS);
$MESSAGE_BODY = strtr($MESSAGE_BODY, $table);
$out = substr($out, 0, -11) . $MESSAGE_BODY . '</textarea>';
}
$out .= $form_end ? "\n$form_end" : '';
$OUTPUT->set_env('composebody', $attrib['id']);
// include HTML editor
rcube_html_editor();
// include GoogieSpell
if (!empty($CONFIG['enable_spellcheck'])) {
$engine = $RCMAIL->config->get('spellcheck_engine','googie');
$dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary');
$spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages',
array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español',
'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski',
'pt'=>'Português', 'fi'=>'Suomi', 'sv'=>'Svenska'));
// googie works only with two-letter codes
if ($engine == 'googie') {
$lang = strtolower(substr($_SESSION['language'], 0, 2));
$spellcheck_langs_googie = array();
foreach ($spellcheck_langs as $key => $name)
$spellcheck_langs_googie[strtolower(substr($key,0,2))] = $name;
$spellcheck_langs = $spellcheck_langs_googie;
}
else {
$lang = $_SESSION['language'];
// if not found in the list, try with two-letter code
if (!$spellcheck_langs[$lang])
$lang = strtolower(substr($lang, 0, 2));
}
if (!$spellcheck_langs[$lang])
$lang = 'en';
$editor_lang_set = array();
foreach ($spellcheck_langs as $key => $name) {
$editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key);
}
$OUTPUT->include_script('googiespell.js');
$OUTPUT->add_script(sprintf(
"var googie = new GoogieSpell('\$__skin_path/images/googiespell/','?_task=utils&_action=spell&lang=', %s);\n".
"googie.lang_chck_spell = \"%s\";\n".
"googie.lang_rsm_edt = \"%s\";\n".
"googie.lang_close = \"%s\";\n".
"googie.lang_revert = \"%s\";\n".
"googie.lang_no_error_found = \"%s\";\n".
"googie.lang_learn_word = \"%s\";\n".
"googie.setLanguages(%s);\n".
"googie.setCurrentLanguage('%s');\n".
"googie.setSpellContainer('spellcheck-control');\n".
"googie.decorateTextarea('%s');\n".
"%s.set_env('spellcheck', googie);",
!empty($dictionary) ? 'true' : 'false',
JQ(Q(rcube_label('checkspelling'))),
JQ(Q(rcube_label('resumeediting'))),
JQ(Q(rcube_label('close'))),
JQ(Q(rcube_label('revertto'))),
JQ(Q(rcube_label('nospellerrors'))),
JQ(Q(rcube_label('addtodict'))),
json_serialize($spellcheck_langs),
$lang,
$attrib['id'],
JS_OBJECT_NAME), 'foot');
$OUTPUT->add_label('checking');
$OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
}
$out .= "\n".'<iframe name="savetarget" src="program/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>';
return $out;
}
function rcmail_create_reply_body($body, $bodyIsHtml)
{
global $RCMAIL, $MESSAGE, $LINE_LENGTH;
// build reply prefix
$from = array_pop($RCMAIL->imap->decode_address_list($MESSAGE->get_header('from'), 1, false));
$prefix = rcube_label(array(
'name' => 'mailreplyintro',
'vars' => array(
'date' => format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')),
'sender' => $from['name'] ? $from['name'] : rcube_idn_to_utf8($from['mailto']),
)
));
if (!$bodyIsHtml) {
$body = preg_replace('/\r?\n/', "\n", $body);
// try to remove the signature
if ($RCMAIL->config->get('strip_existing_sig', true))
$body = rcmail_remove_signature($body);
// soft-wrap and quote message text
$body = rcmail_wrap_and_quote(rtrim($body, "\n"), $LINE_LENGTH);
$prefix .= "\n";
$suffix = '';
if ($RCMAIL->config->get('top_posting'))
$prefix = "\n\n\n" . $prefix;
}
else {
// save inline images to files
$cid_map = rcmail_write_inline_attachments($MESSAGE);
// set is_safe flag (we need this for html body washing)
rcmail_check_safe($MESSAGE);
// clean up html tags
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
// build reply (quote content)
$prefix = '<p>' . Q($prefix) . "</p>\n";
$prefix .= '<blockquote>';
if ($RCMAIL->config->get('top_posting')) {
$prefix = '<br>' . $prefix;
$suffix = '</blockquote>';
}
else {
$suffix = '</blockquote><p></p>';
}
}
return $prefix.$body.$suffix;
}
function rcmail_create_forward_body($body, $bodyIsHtml)
{
global $RCMAIL, $MESSAGE, $COMPOSE;
// add attachments
if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts))
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
$date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
$charset = $RCMAIL->output->get_charset();
if (!$bodyIsHtml)
{
$prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n";
$prefix .= rcube_label('subject') . ': ' . $MESSAGE->subject . "\n";
$prefix .= rcube_label('date') . ': ' . $date . "\n";
$prefix .= rcube_label('from') . ': ' . $MESSAGE->get_header('from') . "\n";
$prefix .= rcube_label('to') . ': ' . $MESSAGE->get_header('to') . "\n";
if ($MESSAGE->headers->cc)
$prefix .= rcube_label('cc') . ': ' . $MESSAGE->get_header('cc') . "\n";
if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
$prefix .= rcube_label('replyto') . ': ' . $MESSAGE->get_header('replyto') . "\n";
$prefix .= "\n";
}
else
{
// set is_safe flag (we need this for html body washing)
rcmail_check_safe($MESSAGE);
// clean up html tags
$body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
$prefix = sprintf(
"<br /><p>-------- " . rcube_label('originalmessage') . " --------</p>" .
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" .
"<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
rcube_label('subject'), Q($MESSAGE->subject),
rcube_label('date'), Q($date),
rcube_label('from'), htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $charset),
rcube_label('to'), htmlspecialchars(Q($MESSAGE->get_header('to'), 'replace'), ENT_COMPAT, $charset));
if ($MESSAGE->headers->cc)
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
rcube_label('cc'),
htmlspecialchars(Q($MESSAGE->get_header('cc'), 'replace'), ENT_COMPAT, $charset));
if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
$prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>",
rcube_label('replyto'),
htmlspecialchars(Q($MESSAGE->get_header('replyto'), 'replace'), ENT_COMPAT, $charset));
$prefix .= "</tbody></table><br>";
}
return $prefix.$body;
}
function rcmail_create_draft_body($body, $bodyIsHtml)
{
global $MESSAGE, $OUTPUT, $COMPOSE;
/**
* add attachments
* sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
*/
if (empty($COMPOSE['forward_attachments'])
&& is_array($MESSAGE->mime_parts)
&& count($MESSAGE->mime_parts) > 0)
{
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
// replace cid with href in inline images links
if ($cid_map)
$body = str_replace(array_keys($cid_map), array_values($cid_map), $body);
}
return $body;
}
function rcmail_remove_signature($body)
{
global $RCMAIL;
$len = strlen($body);
$sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
if ($sp == 0 || $body[$sp-1] == "\n") {
// do not touch blocks with more that X lines
if (substr_count($body, "\n", $sp) < $sig_max_lines) {
$body = substr($body, 0, max(0, $sp-1));
}
break;
}
}
return $body;
}
function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
{
global $RCMAIL, $COMPOSE;
$cid_map = $messages = array();
foreach ((array)$message->mime_parts as $pid => $part)
{
if (($part->ctype_primary != 'message' || !$bodyIsHtml) && $part->ctype_primary != 'multipart' &&
($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename)
&& $part->mimetype != 'application/ms-tnef'
) {
$skip = false;
if ($part->mimetype == 'message/rfc822') {
$messages[] = $part->mime_id;
} else if ($messages) {
// skip attachments included in message/rfc822 attachment (#1486487)
foreach ($messages as $mimeid)
if (strpos($part->mime_id, $mimeid.'.') === 0) {
$skip = true;
break;
}
}
if (!$skip && ($attachment = rcmail_save_attachment($message, $pid))) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
$url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
$cid_map[$part->content_location] = $url;
}
}
}
}
$COMPOSE['forward_attachments'] = true;
return $cid_map;
}
function rcmail_write_inline_attachments(&$message)
{
global $RCMAIL, $COMPOSE;
$cid_map = array();
foreach ((array)$message->mime_parts as $pid => $part) {
if (($part->content_id || $part->content_location) && $part->filename) {
if ($attachment = rcmail_save_attachment($message, $pid)) {
$COMPOSE['attachments'][$attachment['id']] = $attachment;
$url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
$cid_map[$part->content_location] = $url;
}
}
}
return $cid_map;
}
// Creates an attachment from the forwarded message
function rcmail_write_forward_attachment(&$message)
{
global $RCMAIL, $COMPOSE;
if (strlen($message->subject)) {
$name = mb_substr($message->subject, 0, 64) . '.eml';
}
else {
$name = 'message_rfc822.eml';
}
$mem_limit = parse_bytes(ini_get('memory_limit'));
$curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
$data = $path = null;
// don't load too big attachments into memory
if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) {
$temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
$path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($path, 'w')) {
$RCMAIL->imap->get_raw_body($message->uid, $fp);
fclose($fp);
} else
return false;
} else {
$data = $RCMAIL->imap->get_raw_body($message->uid);
}
$attachment = array(
'group' => $COMPOSE['id'],
'name' => $name,
'mimetype' => 'message/rfc822',
'data' => $data,
'path' => $path,
'size' => $path ? filesize($path) : strlen($data),
);
$attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
$COMPOSE['attachments'][$attachment['id']] = $attachment;
return true;
} else if ($path) {
@unlink($path);
}
return false;
}
function rcmail_save_attachment(&$message, $pid)
{
global $COMPOSE;
$rcmail = rcmail::get_instance();
$part = $message->mime_parts[$pid];
$mem_limit = parse_bytes(ini_get('memory_limit'));
$curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
$data = $path = null;
// don't load too big attachments into memory
if ($mem_limit > 0 && $part->size > $mem_limit - $curr_mem) {
$temp_dir = unslashify($rcmail->config->get('temp_dir'));
$path = tempnam($temp_dir, 'rcmAttmnt');
if ($fp = fopen($path, 'w')) {
$message->get_part_content($pid, $fp);
fclose($fp);
} else
return false;
} else {
$data = $message->get_part_content($pid);
}
$attachment = array(
'group' => $COMPOSE['id'],
'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary,
'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
'content_id' => $part->content_id,
'data' => $data,
'path' => $path,
'size' => $path ? filesize($path) : strlen($data),
);
$attachment = $rcmail->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
return $attachment;
} else if ($path) {
@unlink($path);
}
return false;
}
function rcmail_save_image($path, $mimetype='')
{
global $COMPOSE;
// handle attachments in memory
$data = file_get_contents($path);
$attachment = array(
'group' => $COMPOSE['id'],
'name' => rcmail_basename($path),
'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
'data' => $data,
'size' => strlen($data),
);
$attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment);
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
return $attachment;
}
return false;
}
function rcmail_basename($filename)
{
// basename() is not unicode safe and locale dependent
if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
return preg_replace('/^.*[\\\\\\/]/', '', $filename);
} else {
return preg_replace('/^.*[\/]/', '', $filename);
}
}
function rcmail_compose_subject($attrib)
{
global $MESSAGE, $COMPOSE, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_subject';
$attrib['spellcheck'] = 'true';
$textfield = new html_inputfield($attrib);
$subject = '';
// use subject from post
if (isset($_POST['_subject'])) {
$subject = get_input_value('_subject', RCUBE_INPUT_POST, TRUE);
}
// create a reply-subject
else if ($compose_mode == RCUBE_COMPOSE_REPLY) {
if (preg_match('/^re:/i', $MESSAGE->subject))
$subject = $MESSAGE->subject;
else
$subject = 'Re: '.$MESSAGE->subject;
}
// create a forward-subject
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
if (preg_match('/^fwd:/i', $MESSAGE->subject))
$subject = $MESSAGE->subject;
else
$subject = 'Fwd: '.$MESSAGE->subject;
}
// creeate a draft-subject
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
$subject = $MESSAGE->subject;
}
else if (!empty($COMPOSE['param']['subject'])) {
$subject = $COMPOSE['param']['subject'];
}
$out = $form_start ? "$form_start\n" : '';
$out .= $textfield->show($subject);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_compose_attachment_list($attrib)
{
global $OUTPUT, $CONFIG, $COMPOSE;
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmAttachmentList';
$out = "\n";
$jslist = array();
if (is_array($COMPOSE['attachments'])) {
if ($attrib['deleteicon']) {
$button = html::img(array(
'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
'alt' => rcube_label('delete')
));
}
else
$button = Q(rcube_label('delete'));
foreach ($COMPOSE['attachments'] as $id => $a_prop)
{
if (empty($a_prop))
continue;
$out .= html::tag('li', array('id' => 'rcmfile'.$id),
html::a(array(
'href' => "#delete",
'title' => rcube_label('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id)),
$button) . Q($a_prop['name']));
$jslist['rcmfile'.$id] = array('name' => $a_prop['name'], 'complete' => true, 'mimetype' => $a_prop['mimetype']);
}
}
if ($attrib['deleteicon'])
$COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
if ($attrib['cancelicon'])
$OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
if ($attrib['loadingicon'])
$OUTPUT->set_env('loadingicon', $CONFIG['skin_path'] . $attrib['loadingicon']);
$OUTPUT->set_env('attachments', $jslist);
$OUTPUT->add_gui_object('attachmentlist', $attrib['id']);
return html::tag('ul', $attrib, $out, html::$common_attrib);
}
function rcmail_compose_attachment_form($attrib)
{
global $RCMAIL, $OUTPUT;
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmUploadbox';
// Get filesize, enable upload progress bar
$max_filesize = rcube_upload_init();
$button = new html_inputfield(array('type' => 'button'));
$out = html::div($attrib,
$OUTPUT->form_tag(array('name' => 'uploadform', 'method' => 'post', 'enctype' => 'multipart/form-data'),
html::div(null, rcmail_compose_attachment_field(array('size' => $attrib['attachmentfieldsize']))) .
html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
html::div('buttons',
$button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
$button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('send-attachment', this.form)"))
)
)
);
$OUTPUT->add_gui_object('uploadbox', $attrib['id']);
return $out;
}
function rcmail_compose_attachment_field($attrib)
{
$attrib['type'] = 'file';
$attrib['name'] = '_attachments[]';
$attrib['multiple'] = 'multiple';
$field = new html_inputfield($attrib);
return $field->show();
}
function rcmail_priority_selector($attrib)
{
global $MESSAGE;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
$attrib['name'] = '_priority';
$selector = new html_select($attrib);
$selector->add(array(rcube_label('lowest'),
rcube_label('low'),
rcube_label('normal'),
rcube_label('high'),
rcube_label('highest')),
array(5, 4, 0, 2, 1));
if (isset($_POST['_priority']))
$sel = $_POST['_priority'];
else if (intval($MESSAGE->headers->priority) != 3)
$sel = intval($MESSAGE->headers->priority);
else
$sel = 0;
$out = $form_start ? "$form_start\n" : '';
$out .= $selector->show($sel);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_receipt_checkbox($attrib)
{
global $RCMAIL, $MESSAGE, $compose_mode;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'receipt';
$attrib['name'] = '_receipt';
$attrib['value'] = '1';
$checkbox = new html_checkbox($attrib);
if ($MESSAGE && in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT)))
$mdn_default = (bool) $MESSAGE->headers->mdn_to;
else
$mdn_default = $RCMAIL->config->get('mdn_default');
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show($mdn_default);
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_dsn_checkbox($attrib)
{
global $RCMAIL;
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
if (!isset($attrib['id']))
$attrib['id'] = 'dsn';
$attrib['name'] = '_dsn';
$attrib['value'] = '1';
$checkbox = new html_checkbox($attrib);
$out = $form_start ? "$form_start\n" : '';
$out .= $checkbox->show($RCMAIL->config->get('dsn_default'));
$out .= $form_end ? "\n$form_end" : '';
return $out;
}
function rcmail_editor_selector($attrib)
{
global $CONFIG, $MESSAGE, $compose_mode;
// determine whether HTML or plain text should be checked
$useHtml = rcmail_compose_editor_mode();
if (empty($attrib['editorid']))
$attrib['editorid'] = 'rcmComposeBody';
if (empty($attrib['name']))
$attrib['name'] = 'editorSelect';
$attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')";
$select = new html_select($attrib);
$select->add(Q(rcube_label('htmltoggle')), 'html');
$select->add(Q(rcube_label('plaintoggle')), 'plain');
return $select->show($useHtml ? 'html' : 'plain');
foreach ($choices as $value => $text) {
$attrib['id'] = '_' . $value;
$attrib['value'] = $value;
$selector .= $radio->show($chosenvalue, $attrib) . html::label($attrib['id'], Q(rcube_label($text)));
}
return $selector;
}
function rcmail_store_target_selection($attrib)
{
global $COMPOSE;
$attrib['name'] = '_store_target';
$select = rcmail_mailbox_select(array_merge($attrib, array(
'noselection' => '- '.rcube_label('dontsave').' -',
'folder_filter' => 'mail',
'folder_rights' => 'w',
)));
return $select->show($COMPOSE['param']['sent_mbox'], $attrib);
}
function rcmail_check_sent_folder($folder, $create=false)
{
- global $IMAP;
+ global $RCMAIL;
- if ($IMAP->mailbox_exists($folder, true)) {
+ if ($RCMAIL->imap->mailbox_exists($folder, true)) {
return true;
}
// folder may exist but isn't subscribed (#1485241)
if ($create) {
- if (!$IMAP->mailbox_exists($folder))
- return $IMAP->create_mailbox($folder, true);
+ if (!$RCMAIL->imap->mailbox_exists($folder))
+ return $RCMAIL->imap->create_mailbox($folder, true);
else
- return $IMAP->subscribe($folder);
+ return $RCMAIL->imap->subscribe($folder);
}
return false;
}
function get_form_tags($attrib)
{
global $RCMAIL, $MESSAGE_FORM, $COMPOSE;
$form_start = '';
if (!$MESSAGE_FORM)
{
$hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task));
$hiddenfields->add(array('name' => '_action', 'value' => 'send'));
$hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id']));
$form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
$form_start .= $hiddenfields->show();
}
$form_end = ($MESSAGE_FORM && !strlen($attrib['form'])) ? '</form>' : '';
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
if (!$MESSAGE_FORM)
$RCMAIL->output->add_gui_object('messageform', $form_name);
$MESSAGE_FORM = $form_name;
return array($form_start, $form_end);
}
// register UI objects
$OUTPUT->add_handlers(array(
'composeheaders' => 'rcmail_compose_headers',
'composesubject' => 'rcmail_compose_subject',
'composebody' => 'rcmail_compose_body',
'composeattachmentlist' => 'rcmail_compose_attachment_list',
'composeattachmentform' => 'rcmail_compose_attachment_form',
'composeattachment' => 'rcmail_compose_attachment_field',
'priorityselector' => 'rcmail_priority_selector',
'editorselector' => 'rcmail_editor_selector',
'receiptcheckbox' => 'rcmail_receipt_checkbox',
'dsncheckbox' => 'rcmail_dsn_checkbox',
'storetarget' => 'rcmail_store_target_selection',
));
$OUTPUT->send('compose');
diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc
index a4d6a4778..edb6af3d5 100644
--- a/program/steps/mail/copy.inc
+++ b/program/steps/mail/copy.inc
@@ -1,54 +1,54 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/copy.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2010, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Copy the submitted messages to a specific mailbox |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
$Id$
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
return;
// move messages
if (!empty($_POST['_uid']) && !empty($_POST['_target_mbox'])) {
$uids = get_input_value('_uid', RCUBE_INPUT_POST);
$target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true);
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
- $copied = $IMAP->copy_message($uids, $target, $mbox);
+ $copied = $RCMAIL->imap->copy_message($uids, $target, $mbox);
if (!$copied) {
// send error message
rcmail_display_server_error('errorcopying');
$OUTPUT->send();
exit;
}
else {
$OUTPUT->show_message('messagecopied', 'confirmation');
}
rcmail_send_unread_count($target, true);
$OUTPUT->command('set_quota', rcmail_quota_content());
}
// unknown action or missing query param
else {
exit;
}
// send response
$OUTPUT->send();
diff --git a/program/steps/mail/folders.inc b/program/steps/mail/folders.inc
index fad2bf3e3..6e687b06a 100644
--- a/program/steps/mail/folders.inc
+++ b/program/steps/mail/folders.inc
@@ -1,80 +1,80 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/folders.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Implement folder operations line EXPUNGE and Clear |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
return;
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
// send EXPUNGE command
if ($RCMAIL->action == 'expunge') {
- $success = $IMAP->expunge($mbox);
+ $success = $RCMAIL->imap->expunge($mbox);
// reload message list if current mailbox
if ($success) {
$OUTPUT->show_message('folderexpunged', 'confirmation');
if (!empty($_REQUEST['_reload'])) {
$OUTPUT->command('set_quota', rcmail_quota_content());
$OUTPUT->command('message_list.clear');
$RCMAIL->action = 'list';
return;
}
}
else {
rcmail_display_server_error();
}
}
// clear mailbox
else if ($RCMAIL->action == 'purge')
{
- $delimiter = $IMAP->get_hierarchy_delimiter();
+ $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
$trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/';
$junk_regexp = '/^' . preg_quote($CONFIG['junk_mbox'] . $delimiter, '/') . '/';
// we should only be purging trash and junk (or their subfolders)
if ($mbox == $CONFIG['trash_mbox'] || $mbox == $CONFIG['junk_mbox']
|| preg_match($trash_regexp, $mbox) || preg_match($junk_regexp, $mbox)
) {
- $success = $IMAP->clear_mailbox($mbox);
+ $success = $RCMAIL->imap->clear_mailbox($mbox);
if ($success) {
$OUTPUT->show_message('folderpurged', 'confirmation');
if (!empty($_REQUEST['_reload'])) {
$OUTPUT->set_env('messagecount', 0);
$OUTPUT->set_env('pagecount', 0);
$OUTPUT->command('message_list.clear');
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox);
$OUTPUT->command('set_unread_count', $mbox, 0);
$OUTPUT->command('set_quota', rcmail_quota_content());
rcmail_set_unseen_count($mbox, 0);
}
}
else {
rcmail_display_server_error();
}
}
}
$OUTPUT->send();
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 7e3a86cb5..1063c8ddf 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1,1618 +1,1618 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/func.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2010, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide webmail functionality and GUI objects |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// setup some global vars used by mail steps
$SENT_MBOX = $RCMAIL->config->get('sent_mbox');
$DRAFTS_MBOX = $RCMAIL->config->get('drafts_mbox');
$SEARCH_MODS_DEFAULT = array(
'*' => array('subject'=>1, 'from'=>1),
$SENT_MBOX => array('subject'=>1, 'to'=>1),
$DRAFTS_MBOX => array('subject'=>1, 'to'=>1)
);
// actions that do not require imap connection here
$NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get');
// always instantiate imap object (but not yet connect to server)
$RCMAIL->imap_init();
// log in to imap server
if (!in_array($RCMAIL->action, $NOIMAP_ACTIONS) && !$RCMAIL->imap_connect()) {
$RCMAIL->kill_session();
if ($OUTPUT->ajax_call)
$OUTPUT->redirect(array(), 2000);
$OUTPUT->set_env('task', 'login');
$OUTPUT->send('login');
}
// set imap properties and session vars
if (strlen(trim($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC, true))))
- $IMAP->set_mailbox(($_SESSION['mbox'] = $mbox));
-else if ($IMAP)
- $_SESSION['mbox'] = $IMAP->get_mailbox_name();
+ $RCMAIL->imap->set_mailbox(($_SESSION['mbox'] = $mbox));
+else if ($RCMAIL->imap)
+ $_SESSION['mbox'] = $RCMAIL->imap->get_mailbox_name();
if (!empty($_GET['_page']))
- $IMAP->set_page(($_SESSION['page'] = intval($_GET['_page'])));
+ $RCMAIL->imap->set_page(($_SESSION['page'] = intval($_GET['_page'])));
// set default sort col/order to session
if (!isset($_SESSION['sort_col']))
$_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : '';
if (!isset($_SESSION['sort_order']))
$_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC';
// set threads mode
$a_threading = $RCMAIL->config->get('message_threading', array());
if (isset($_GET['_threads'])) {
if ($_GET['_threads'])
$a_threading[$_SESSION['mbox']] = true;
else
unset($a_threading[$_SESSION['mbox']]);
$RCMAIL->user->save_prefs(array('message_threading' => $a_threading));
}
-$IMAP->set_threading($a_threading[$_SESSION['mbox']]);
+$RCMAIL->imap->set_threading($a_threading[$_SESSION['mbox']]);
// set message set for search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
&& $_SESSION['search_request'] == $_REQUEST['_search']
) {
- $IMAP->set_search_set($_SESSION['search']);
+ $RCMAIL->imap->set_search_set($_SESSION['search']);
$OUTPUT->set_env('search_request', $_REQUEST['_search']);
$OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
}
// set main env variables, labels and page title
if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
- $mbox_name = $IMAP->get_mailbox_name();
+ $mbox_name = $RCMAIL->imap->get_mailbox_name();
if (empty($RCMAIL->action)) {
// initialize searching result if search_filter is used
if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
$search_request = md5($mbox_name.$_SESSION['search_filter']);
- $IMAP->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']);
- $_SESSION['search'] = $IMAP->get_search_set();
+ $RCMAIL->imap->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $_SESSION['sort_col']);
+ $_SESSION['search'] = $RCMAIL->imap->get_search_set();
$_SESSION['search_request'] = $search_request;
$OUTPUT->set_env('search_request', $search_request);
}
$search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
$OUTPUT->set_env('search_mods', $search_mods);
}
// set current mailbox and some other vars in client environment
$OUTPUT->set_env('mailbox', $mbox_name);
- $OUTPUT->set_env('pagesize', $IMAP->page_size);
- $OUTPUT->set_env('quota', $IMAP->get_capability('QUOTA'));
- $OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter());
- $OUTPUT->set_env('threading', (bool) $IMAP->threading);
- $OUTPUT->set_env('threads', $IMAP->threading || $IMAP->get_capability('THREAD'));
+ $OUTPUT->set_env('pagesize', $RCMAIL->imap->page_size);
+ $OUTPUT->set_env('quota', $RCMAIL->imap->get_capability('QUOTA'));
+ $OUTPUT->set_env('delimiter', $RCMAIL->imap->get_hierarchy_delimiter());
+ $OUTPUT->set_env('threading', (bool) $RCMAIL->imap->threading);
+ $OUTPUT->set_env('threads', $RCMAIL->imap->threading || $RCMAIL->imap->get_capability('THREAD'));
$OUTPUT->set_env('preview_pane_mark_read', $RCMAIL->config->get('preview_pane_mark_read', 0));
if ($CONFIG['flag_for_deletion'])
$OUTPUT->set_env('flag_for_deletion', true);
if ($CONFIG['read_when_deleted'])
$OUTPUT->set_env('read_when_deleted', true);
if ($CONFIG['skip_deleted'])
$OUTPUT->set_env('skip_deleted', true);
if ($CONFIG['display_next'])
$OUTPUT->set_env('display_next', true);
if ($CONFIG['forward_attachment'])
$OUTPUT->set_env('forward_attachment', true);
if ($CONFIG['trash_mbox'])
$OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
if ($CONFIG['drafts_mbox'])
$OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']);
if ($CONFIG['junk_mbox'])
$OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']);
if (!$OUTPUT->ajax_call)
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
'copy', 'move', 'quota');
- $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->mod_mailbox($mbox_name)));
+ $OUTPUT->set_pagetitle(rcmail_localize_foldername($RCMAIL->imap->mod_mailbox($mbox_name)));
}
/**
* return the message list as HTML table
*/
function rcmail_message_list($attrib)
{
- global $IMAP, $CONFIG, $OUTPUT;
+ global $RCMAIL, $CONFIG, $OUTPUT;
// add some labels to client
$OUTPUT->add_label('from', 'to');
// add id to message list table if not specified
if (!strlen($attrib['id']))
$attrib['id'] = 'rcubemessagelist';
// define list of cols to be displayed based on parameter or config
if (empty($attrib['columns'])) {
$a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
$OUTPUT->set_env('col_movable', !in_array('list_cols', (array)$CONFIG['dont_override']));
}
else {
$a_show_cols = preg_split('/[\s,;]+/', strip_quotes($attrib['columns']));
$attrib['columns'] = $a_show_cols;
}
// save some variables for use in ajax list
$_SESSION['list_attrib'] = $attrib;
- $mbox = $IMAP->get_mailbox_name();
- $delim = $IMAP->get_hierarchy_delimiter();
+ $mbox = $RCMAIL->imap->get_mailbox_name();
+ $delim = $RCMAIL->imap->get_hierarchy_delimiter();
// show 'to' instead of 'from' in sent/draft messages
if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0)
&& (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
$a_show_cols[$f] = 'to';
// make sure 'threads' and 'subject' columns are present
if (!in_array('subject', $a_show_cols))
array_unshift($a_show_cols, 'subject');
if (!in_array('threads', $a_show_cols))
array_unshift($a_show_cols, 'threads');
$skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path'];
// set client env
$OUTPUT->add_gui_object('messagelist', $attrib['id']);
$OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads']));
$OUTPUT->set_env('sort_col', $_SESSION['sort_col']);
$OUTPUT->set_env('sort_order', $_SESSION['sort_order']);
$OUTPUT->set_env('messages', array());
$OUTPUT->set_env('coltypes', $a_show_cols);
$OUTPUT->include_script('list.js');
$thead = '';
foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell)
$thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']);
return html::tag('table',
$attrib,
html::tag('thead', null, html::tag('tr', null, $thead)) .
html::tag('tbody', null, ''),
array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
}
/**
* return javascript commands to add rows to the message list
*/
function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null)
{
- global $CONFIG, $IMAP, $RCMAIL, $OUTPUT;
+ global $CONFIG, $RCMAIL, $OUTPUT;
if (empty($a_show_cols)) {
if (!empty($_SESSION['list_attrib']['columns']))
$a_show_cols = $_SESSION['list_attrib']['columns'];
else
$a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
}
else {
if (!is_array($a_show_cols))
$a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols));
$head_replace = true;
}
- $mbox = $IMAP->get_mailbox_name();
- $delim = $IMAP->get_hierarchy_delimiter();
+ $mbox = $RCMAIL->imap->get_mailbox_name();
+ $delim = $RCMAIL->imap->get_hierarchy_delimiter();
// make sure 'threads' and 'subject' columns are present
if (!in_array('subject', $a_show_cols))
array_unshift($a_show_cols, 'subject');
if (!in_array('threads', $a_show_cols))
array_unshift($a_show_cols, 'threads');
$_SESSION['list_attrib']['columns'] = $a_show_cols;
// show 'to' instead of 'from' in sent/draft messages
if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0)
&& (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
$a_show_cols[$f] = 'to';
// Make sure there are no duplicated columns (#1486999)
$a_show_cols = array_unique($a_show_cols);
// Plugins may set header's list_cols/list_flags and other rcube_mail_header variables
// and list columns
$plugin = $RCMAIL->plugins->exec_hook('messages_list',
array('messages' => $a_headers, 'cols' => $a_show_cols));
$a_show_cols = $plugin['cols'];
$a_headers = $plugin['messages'];
$thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL;
$OUTPUT->command('set_message_coltypes', $a_show_cols, $thead);
if (empty($a_headers))
return;
// remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here
foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) {
if (($key = array_search($col, $a_show_cols)) !== FALSE)
unset($a_show_cols[$key]);
}
// loop through message headers
foreach ($a_headers as $n => $header) {
if (empty($header))
continue;
$a_msg_cols = array();
$a_msg_flags = array();
- $IMAP->set_charset(!empty($header->charset) ? $header->charset : $CONFIG['default_charset']);
+ $RCMAIL->imap->set_charset(!empty($header->charset) ? $header->charset : $CONFIG['default_charset']);
// format each col; similar as in rcmail_message_list()
foreach ($a_show_cols as $col) {
if (in_array($col, array('from', 'to', 'cc', 'replyto')))
$cont = Q(rcmail_address_string($header->$col, 3), 'show');
else if ($col=='subject') {
- $cont = trim($IMAP->decode_header($header->$col));
+ $cont = trim($RCMAIL->imap->decode_header($header->$col));
if (!$cont) $cont = rcube_label('nosubject');
$cont = Q($cont);
}
else if ($col=='size')
$cont = show_bytes($header->$col);
else if ($col=='date')
$cont = format_date($header->date);
else
$cont = Q($header->$col);
$a_msg_cols[$col] = $cont;
}
$a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags));
if ($header->depth)
$a_msg_flags['depth'] = $header->depth;
else if ($header->has_children)
$roots[] = $header->uid;
if ($header->parent_uid)
$a_msg_flags['parent_uid'] = $header->parent_uid;
if ($header->has_children)
$a_msg_flags['has_children'] = $header->has_children;
if ($header->unread_children)
$a_msg_flags['unread_children'] = $header->unread_children;
if ($header->others['list-post'])
$a_msg_flags['ml'] = 1;
if ($header->priority)
$a_msg_flags['prio'] = (int) $header->priority;
$a_msg_flags['ctype'] = Q($header->ctype);
$a_msg_flags['mbox'] = $mbox;
// merge with plugin result (Deprecated, use $header->flags)
if (!empty($header->list_flags) && is_array($header->list_flags))
$a_msg_flags = array_merge($a_msg_flags, $header->list_flags);
if (!empty($header->list_cols) && is_array($header->list_cols))
$a_msg_cols = array_merge($a_msg_cols, $header->list_cols);
$OUTPUT->command('add_message_row',
$header->uid,
$a_msg_cols,
$a_msg_flags,
$insert_top);
}
- if ($IMAP->threading) {
+ if ($RCMAIL->imap->threading) {
$OUTPUT->command('init_threads', (array) $roots, $mbox);
}
}
/*
* Creates <THEAD> for message list table
*/
function rcmail_message_list_head($attrib, $a_show_cols)
{
global $CONFIG;
$skin_path = $_SESSION['skin_path'];
$image_tag = html::img(array('src' => "%s%s", 'alt' => "%s"));
// check to see if we have some settings for sorting
$sort_col = $_SESSION['sort_col'];
$sort_order = $_SESSION['sort_order'];
// define sortable columns
$a_sort_cols = array('subject', 'date', 'from', 'to', 'size', 'cc');
if (!empty($attrib['optionsmenuicon'])) {
$onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')";
if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true')
$list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu',
'id' => 'listmenulink', 'title' => rcube_label('listoptions')));
else
$list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
'id' => 'listmenulink', 'title' => rcube_label('listoptions')))
);
}
else
$list_menu = '';
$cells = array();
foreach ($a_show_cols as $col) {
// get column name
switch ($col) {
case 'flag':
$col_name = '<span class="flagged">&nbsp;</span>';
break;
case 'attachment':
case 'priority':
case 'status':
$col_name = '<span class="' . $col .'">&nbsp;</span>';
break;
case 'threads':
$col_name = $list_menu;
break;
default:
$col_name = Q(rcube_label($col));
}
// make sort links
if (in_array($col, $a_sort_cols))
$col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => rcube_label('sortby')), $col_name);
$sort_class = $col == $sort_col ? " sorted$sort_order" : '';
$class_name = $col.$sort_class;
// put it all together
$cells[] = array('className' => $class_name, 'id' => "rcm$col", 'html' => $col_name);
}
return $cells;
}
/**
* return an HTML iframe for loading mail content
*/
function rcmail_messagecontent_frame($attrib)
- {
+{
global $OUTPUT, $RCMAIL;
if (empty($attrib['id']))
$attrib['id'] = 'rcmailcontentwindow';
$attrib['name'] = $attrib['id'];
if ($RCMAIL->config->get('preview_pane'))
$OUTPUT->set_env('contentframe', $attrib['id']);
$OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
return html::iframe($attrib);
- }
+}
function rcmail_messagecount_display($attrib)
- {
+{
global $RCMAIL;
if (!$attrib['id'])
$attrib['id'] = 'rcmcountdisplay';
$RCMAIL->output->add_gui_object('countdisplay', $attrib['id']);
$content = $RCMAIL->action != 'show' ? rcmail_get_messagecount_text() : rcube_label('loading');
return html::span($attrib, $content);
- }
+}
function rcmail_get_messagecount_text($count=NULL, $page=NULL)
- {
- global $RCMAIL, $IMAP;
+{
+ global $RCMAIL;
if ($page===NULL)
- $page = $IMAP->list_page;
+ $page = $RCMAIL->imap->list_page;
- $start_msg = ($page-1) * $IMAP->page_size + 1;
+ $start_msg = ($page-1) * $RCMAIL->imap->page_size + 1;
if ($count!==NULL)
$max = $count;
else if ($RCMAIL->action)
- $max = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
+ $max = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
if ($max==0)
$out = rcube_label('mailboxempty');
else
- $out = rcube_label(array('name' => $IMAP->threading ? 'threadsfromto' : 'messagesfromto',
+ $out = rcube_label(array('name' => $RCMAIL->imap->threading ? 'threadsfromto' : 'messagesfromto',
'vars' => array('from' => $start_msg,
- 'to' => min($max, $start_msg + $IMAP->page_size - 1),
+ 'to' => min($max, $start_msg + $RCMAIL->imap->page_size - 1),
'count' => $max)));
return Q($out);
- }
+}
function rcmail_mailbox_name_display($attrib)
{
global $RCMAIL;
if (!$attrib['id'])
$attrib['id'] = 'rcmmailboxname';
$RCMAIL->output->add_gui_object('mailboxname', $attrib['id']);
return html::span($attrib, rcmail_get_mailbox_name_text());
}
function rcmail_get_mailbox_name_text()
{
global $RCMAIL;
return rcmail_localize_foldername($RCMAIL->imap->get_mailbox_name());
}
function rcmail_send_unread_count($mbox_name, $force=false, $count=null, $mark='')
{
global $RCMAIL;
$old_unseen = rcmail_get_unseen_count($mbox_name);
if ($count === null)
$unseen = $RCMAIL->imap->messagecount($mbox_name, 'UNSEEN', $force);
else
$unseen = $count;
if ($unseen != $old_unseen || ($mbox_name == 'INBOX'))
$RCMAIL->output->command('set_unread_count', $mbox_name, $unseen,
($mbox_name == 'INBOX'), $unseen && $mark ? $mark : '');
rcmail_set_unseen_count($mbox_name, $unseen);
return $unseen;
}
function rcmail_set_unseen_count($mbox_name, $count)
{
// @TODO: this data is doubled (session and cache tables) if caching is enabled
// Make sure we have an array here (#1487066)
if (!is_array($_SESSION['unseen_count']))
$_SESSION['unseen_count'] = array();
$_SESSION['unseen_count'][$mbox_name] = $count;
}
function rcmail_get_unseen_count($mbox_name)
{
if (is_array($_SESSION['unseen_count']) && array_key_exists($mbox_name, $_SESSION['unseen_count']))
return $_SESSION['unseen_count'][$mbox_name];
else
return null;
}
/**
* Sets message is_safe flag according to 'show_images' option value
*
* @param object rcube_message Message
*/
function rcmail_check_safe(&$message)
{
global $RCMAIL;
$show_images = $RCMAIL->config->get('show_images');
if (!$message->is_safe
&& !empty($show_images)
&& $message->has_html_part())
{
switch($show_images) {
case '1': // known senders only
$CONTACTS = new rcube_contacts($RCMAIL->db, $_SESSION['user_id']);
if ($CONTACTS->search('email', $message->sender['mailto'], true, false)->count) {
$message->set_safe(true);
}
break;
case '2': // always
$message->set_safe(true);
break;
}
}
}
/**
* Cleans up the given message HTML Body (for displaying)
*
* @param string HTML
* @param array Display parameters
* @param array CID map replaces (inline images)
* @return string Clean HTML
*/
function rcmail_wash_html($html, $p, $cid_replaces)
{
global $REMOTE_OBJECTS;
$p += array('safe' => false, 'inline_html' => true);
// special replacements (not properly handled by washtml class)
$html_search = array(
'/(<\/nobr>)(\s+)(<nobr>)/i', // space(s) between <NOBR>
'/<title[^>]*>[^<]*<\/title>/i', // PHP bug #32547 workaround: remove title tag
'/^(\0\0\xFE\xFF|\xFF\xFE\0\0|\xFE\xFF|\xFF\xFE|\xEF\xBB\xBF)/', // byte-order mark (only outlook?)
'/<html\s[^>]+>/i', // washtml/DOMDocument cannot handle xml namespaces
);
$html_replace = array(
'\\1'.' &nbsp; '.'\\3',
'',
'',
'<html>',
);
$html = preg_replace($html_search, $html_replace, trim($html));
// PCRE errors handling (#1486856), should we use something like for every preg_* use?
if ($html === null && ($preg_error = preg_last_error()) != PREG_NO_ERROR) {
$errstr = "Could not clean up HTML message! PCRE Error: $preg_error.";
if ($preg_error == PREG_BACKTRACK_LIMIT_ERROR)
$errstr .= " Consider raising pcre.backtrack_limit!";
if ($preg_error == PREG_RECURSION_LIMIT_ERROR)
$errstr .= " Consider raising pcre.recursion_limit!";
raise_error(array('code' => 620, 'type' => 'php',
'line' => __LINE__, 'file' => __FILE__,
'message' => $errstr), true, false);
return '';
}
// fix (unknown/malformed) HTML tags before "wash"
$html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html);
// charset was converted to UTF-8 in rcube_imap::get_message_part(),
// change/add charset specification in HTML accordingly,
// washtml cannot work without that
$meta = '<meta http-equiv="Content-Type" content="text/html; charset='.RCMAIL_CHARSET.'" />';
// remove old meta tag and add the new one, making sure
// that it is placed in the head (#1488093)
$html = preg_replace('/<meta[^>]+charset=[a-z0-9-_]+[^>]*>/Ui', '', $html);
$html = preg_replace('/(<head[^>]*>)/Ui', '\\1'.$meta, $html, -1, $rcount);
if (!$rcount) {
$html = '<head>' . $meta . '</head>' . $html;
}
// turn relative into absolute urls
$html = rcmail_resolve_base($html);
// clean HTML with washhtml by Frederic Motte
$wash_opts = array(
'show_washed' => false,
'allow_remote' => $p['safe'],
'blocked_src' => "./program/blocked.gif",
'charset' => RCMAIL_CHARSET,
'cid_map' => $cid_replaces,
'html_elements' => array('body'),
);
if (!$p['inline_html']) {
$wash_opts['html_elements'] = array('html','head','title','body');
}
if ($p['safe']) {
$wash_opts['html_elements'][] = 'link';
$wash_opts['html_attribs'] = array('rel','type');
}
// overwrite washer options with options from plugins
if (isset($p['html_elements']))
$wash_opts['html_elements'] = $p['html_elements'];
if (isset($p['html_attribs']))
$wash_opts['html_attribs'] = $p['html_attribs'];
// initialize HTML washer
$washer = new washtml($wash_opts);
if (!$p['skip_washer_form_callback'])
$washer->add_callback('form', 'rcmail_washtml_callback');
// allow CSS styles, will be sanitized by rcmail_washtml_callback()
if (!$p['skip_washer_style_callback'])
$washer->add_callback('style', 'rcmail_washtml_callback');
// Remove non-UTF8 characters (#1487813)
$html = rc_utf8_clean($html);
$html = $washer->wash($html);
$REMOTE_OBJECTS = $washer->extlinks;
return $html;
}
/**
* Convert the given message part to proper HTML
* which can be displayed the message view
*
* @param object rcube_message_part Message part
* @param array Display parameters array
* @return string Formatted HTML string
*/
function rcmail_print_body($part, $p = array())
{
global $RCMAIL;
// trigger plugin hook
$data = $RCMAIL->plugins->exec_hook('message_part_before',
array('type' => $part->ctype_secondary, 'body' => $part->body, 'id' => $part->mime_id)
+ $p + array('safe' => false, 'plain' => false, 'inline_html' => true));
// convert html to text/plain
if ($data['type'] == 'html' && $data['plain']) {
$txt = new html2text($data['body'], false, true);
$body = $txt->get_text();
$part->ctype_secondary = 'plain';
}
// text/html
else if ($data['type'] == 'html') {
$body = rcmail_wash_html($data['body'], $data, $part->replaces);
$part->ctype_secondary = $data['type'];
}
// text/enriched
else if ($data['type'] == 'enriched') {
$part->ctype_secondary = 'html';
require_once(INSTALL_PATH . 'program/lib/enriched.inc');
$body = Q(enriched_to_html($data['body']), 'show');
}
else {
// assert plaintext
$body = $part->body;
$part->ctype_secondary = $data['type'] = 'plain';
}
// free some memory (hopefully)
unset($data['body']);
// plaintext postprocessing
if ($part->ctype_secondary == 'plain')
$body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
// allow post-processing of the message body
$data = $RCMAIL->plugins->exec_hook('message_part_after',
array('type' => $part->ctype_secondary, 'body' => $body, 'id' => $part->mime_id) + $data);
return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']);
}
/**
* Handle links and citation marks in plain text message
*
* @param string Plain text string
* @param boolean Text uses format=flowed
*
* @return string Formatted HTML string
*/
function rcmail_plain_body($body, $flowed=false)
{
global $RCMAIL;
// make links and email-addresses clickable
$replacer = new rcube_string_replacer;
// search for patterns like links and e-mail addresses
$body = preg_replace_callback($replacer->link_pattern, array($replacer, 'link_callback'), $body);
$body = preg_replace_callback($replacer->mailto_pattern, array($replacer, 'mailto_callback'), $body);
// split body into single lines
$body = preg_split('/\r?\n/', $body);
$quote_level = 0;
$last = -1;
// find/mark quoted lines...
for ($n=0, $cnt=count($body); $n < $cnt; $n++) {
if ($body[$n][0] == '>' && preg_match('/^(>+\s*)+/', $body[$n], $regs)) {
$q = strlen(preg_replace('/\s/', '', $regs[0]));
$body[$n] = substr($body[$n], strlen($regs[0]));
if ($q > $quote_level) {
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('<blockquote>', $q - $quote_level))) . $body[$n];
}
else if ($q < $quote_level) {
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('</blockquote>', $quote_level - $q))) . $body[$n];
}
else if ($flowed) {
// previous line is flowed
if (isset($body[$last]) && $body[$n]
&& $body[$last][strlen($body[$last])-1] == ' ') {
// merge lines
$body[$last] .= $body[$n];
unset($body[$n]);
}
else {
$last = $n;
}
}
}
else {
$q = 0;
if ($flowed) {
// sig separator - line is fixed
if ($body[$n] == '-- ') {
$last = $last_sig = $n;
}
else {
// remove space-stuffing
if ($body[$n][0] == ' ')
$body[$n] = substr($body[$n], 1);
// previous line is flowed?
if (isset($body[$last]) && $body[$n]
&& $last !== $last_sig
&& $body[$last][strlen($body[$last])-1] == ' '
) {
$body[$last] .= $body[$n];
unset($body[$n]);
}
else {
$last = $n;
}
}
if ($quote_level > 0)
$body[$last] = $replacer->get_replacement($replacer->add(
str_repeat('</blockquote>', $quote_level))) . $body[$last];
}
else if ($quote_level > 0)
$body[$n] = $replacer->get_replacement($replacer->add(
str_repeat('</blockquote>', $quote_level))) . $body[$n];
}
$quote_level = $q;
}
$body = join("\n", $body);
// quote plain text (don't use Q() here, to display entities "as is")
$table = get_html_translation_table(HTML_SPECIALCHARS);
unset($table['?']);
$body = strtr($body, $table);
// colorize signature (up to <sig_max_lines> lines)
$len = strlen($body);
$sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15);
while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
if ($sp == 0 || $body[$sp-1] == "\n") {
// do not touch blocks with more that X lines
if (substr_count($body, "\n", $sp) < $sig_max_lines)
$body = substr($body, 0, max(0, $sp))
.'<span class="sig">'.substr($body, $sp).'</span>';
break;
}
}
// insert url/mailto links and citation tags
$body = $replacer->resolve($body);
return $body;
}
/**
* Callback function for washtml cleaning class
*/
function rcmail_washtml_callback($tagname, $attrib, $content)
{
switch ($tagname) {
case 'form':
$out = html::div('form', $content);
break;
case 'style':
// decode all escaped entities and reduce to ascii strings
$stripped = preg_replace('/[^a-zA-Z\(:;]/', '', rcmail_xss_entity_decode($content));
// now check for evil strings like expression, behavior or url()
if (!preg_match('/expression|behavior|url\(|import[^a]/', $stripped)) {
$out = html::tag('style', array('type' => 'text/css'), $content);
break;
}
default:
$out = '';
}
return $out;
}
/**
* Callback function for HTML tags fixing
*/
function rcmail_html_tag_callback($matches)
{
$tagname = $matches[2];
$tagname = preg_replace(array(
'/:.*$/', // Microsoft's Smart Tags <st1:xxxx>
'/[^a-z0-9_\[\]\!-]/i', // forbidden characters
), '', $tagname);
return $matches[1].$tagname;
}
/**
* return table with message headers
*/
function rcmail_message_headers($attrib, $headers=NULL)
{
- global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL;
+ global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL;
static $sa_attrib;
// keep header table attrib
if (is_array($attrib) && !$sa_attrib)
$sa_attrib = $attrib;
else if (!is_array($attrib) && is_array($sa_attrib))
$attrib = $sa_attrib;
if (!isset($MESSAGE))
return FALSE;
// get associative array of headers object
if (!$headers)
$headers = is_object($MESSAGE->headers) ? get_object_vars($MESSAGE->headers) : $MESSAGE->headers;
// show these headers
$standard_headers = array('subject', 'from', 'to', 'cc', 'bcc', 'replyto',
'mail-reply-to', 'mail-followup-to', 'date');
$output_headers = array();
foreach ($standard_headers as $hkey) {
if ($headers[$hkey])
$value = $headers[$hkey];
else if ($headers['others'][$hkey])
$value = $headers['others'][$hkey];
else
continue;
if ($hkey == 'date') {
if ($PRINT_MODE)
$header_value = format_date($value, $RCMAIL->config->get('date_long', 'x'));
else
$header_value = format_date($value);
}
else if ($hkey == 'replyto') {
if ($headers['replyto'] != $headers['from'])
$header_value = rcmail_address_string($value, null, true, $attrib['addicon']);
else
continue;
}
else if ($hkey == 'mail-reply-to') {
if ($headers['mail-replyto'] != $headers['reply-to']
&& $headers['reply-to'] != $headers['from']
)
$header_value = rcmail_address_string($value, null, true, $attrib['addicon']);
else
continue;
}
else if ($hkey == 'mail-followup-to') {
$header_value = rcmail_address_string($value, null, true, $attrib['addicon']);
}
else if (in_array($hkey, array('from', 'to', 'cc', 'bcc')))
$header_value = rcmail_address_string($value, null, true, $attrib['addicon']);
else if ($hkey == 'subject' && empty($value))
$header_value = rcube_label('nosubject');
else
- $header_value = trim($IMAP->decode_header($value));
+ $header_value = trim($RCMAIL->imap->decode_header($value));
$output_headers[$hkey] = array(
'title' => rcube_label(preg_replace('/(^mail-|-)/', '', $hkey)),
'value' => $header_value, 'raw' => $value
);
}
$plugin = $RCMAIL->plugins->exec_hook('message_headers_output',
array('output' => $output_headers, 'headers' => $MESSAGE->headers));
// compose html table
$table = new html_table(array('cols' => 2));
foreach ($plugin['output'] as $hkey => $row) {
$table->add(array('class' => 'header-title'), Q($row['title']));
$table->add(array('class' => 'header '.$hkey), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
}
return $table->show($attrib);
}
/**
* return block to show full message headers
*/
function rcmail_message_full_headers($attrib, $headers=NULL)
{
global $OUTPUT;
$html = html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('load-headers','',this)"), '');
$html .= html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), ''));
$OUTPUT->add_gui_object('all_headers_row', 'all-headers');
$OUTPUT->add_gui_object('all_headers_box', 'headers-source');
return html::div($attrib, $html);
}
/**
* Handler for the 'messagebody' GUI object
*
* @param array Named parameters
* @return string HTML content showing the message body
*/
function rcmail_message_body($attrib)
{
- global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $RCMAIL, $REMOTE_OBJECTS;
+ global $CONFIG, $OUTPUT, $MESSAGE, $RCMAIL, $REMOTE_OBJECTS;
if (!is_array($MESSAGE->parts) && empty($MESSAGE->body))
return '';
if (!$attrib['id'])
$attrib['id'] = 'rcmailMsgBody';
$safe_mode = $MESSAGE->is_safe || intval($_GET['_safe']);
$out = '';
$header_attrib = array();
foreach ($attrib as $attr => $value)
if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
$header_attrib[$regs[1]] = $value;
if (!empty($MESSAGE->parts)) {
foreach ($MESSAGE->parts as $i => $part) {
if ($part->type == 'headers')
$out .= rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : NULL, $part->headers);
else if ($part->type == 'content' && $part->size) {
// Check if we have enough memory to handle the message in it
// #1487424: we need up to 10x more memory than the body
if (!rcmail_mem_check($part->size * 10)) {
$out .= html::span('part-notice', rcube_label('messagetoobig'). ' '
. html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id
- .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')));
+ .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download')));
continue;
}
if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
$part->ctype_parameters['charset'] = $MESSAGE->headers->charset;
// fetch part if not available
if (!isset($part->body))
$part->body = $MESSAGE->get_part_content($part->mime_id);
// message is cached but not exists (#1485443), or other error
if ($part->body === false) {
rcmail_message_error($MESSAGE->uid);
}
$plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
'part' => $part, 'prefix' => ''));
$body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
if ($part->ctype_secondary == 'html') {
$body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs);
$div_attr = array('class' => 'message-htmlpart');
$style = array();
if (!empty($attrs)) {
foreach ($attrs as $a_idx => $a_val)
$style[] = $a_idx . ': ' . $a_val;
if (!empty($style))
$div_attr['style'] = implode('; ', $style);
}
$out .= html::div($div_attr, $plugin['prefix'] . $body);
}
else
$out .= html::div('message-part', $plugin['prefix'] . $body);
}
}
}
else {
// Check if we have enough memory to handle the message in it
// #1487424: we need up to 10x more memory than the body
if (!rcmail_mem_check(strlen($MESSAGE->body) * 10)) {
$out .= html::span('part-notice', rcube_label('messagetoobig'). ' '
. html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part=0'
- .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')));
+ .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download')));
}
else {
$plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
'part' => $MESSAGE, 'prefix' => ''));
$out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
rcmail_plain_body(Q($MESSAGE->body, 'strict', false))));
}
}
// list images after mail body
if ($CONFIG['inline_images'] && !empty($MESSAGE->attachments)) {
foreach ($MESSAGE->attachments as $attach_prop) {
// Content-Type: image/*...
if (preg_match('/^image\//i', $attach_prop->mimetype) ||
// ...or known file extension: many clients are using application/octet-stream
($attach_prop->filename &&
preg_match('/^application\/octet-stream$/i', $attach_prop->mimetype) &&
preg_match('/\.(jpg|jpeg|png|gif|bmp)$/i', $attach_prop->filename))
) {
$out .= html::tag('hr') . html::p(array('align' => "center"),
html::img(array(
'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true),
'title' => $attach_prop->filename,
'alt' => $attach_prop->filename,
)));
}
}
}
// tell client that there are blocked remote objects
if ($REMOTE_OBJECTS && !$safe_mode)
$OUTPUT->set_env('blockedobjects', true);
return html::div($attrib, $out);
}
/**
* Convert all relative URLs according to a <base> in HTML
*/
function rcmail_resolve_base($body)
{
// check for <base href=...>
if (preg_match('!(<base.*href=["\']?)([hftps]{3,5}://[a-z0-9/.%-]+)!i', $body, $regs)) {
$replacer = new rcube_base_replacer($regs[2]);
// replace all relative paths
$body = preg_replace_callback('/(src|background|href)=(["\']?)([^"\'\s]+)(\2|\s|>)/Ui', array($replacer, 'callback'), $body);
$body = preg_replace_callback('/(url\s*\()(["\']?)([^"\'\)\s]+)(\2)\)/Ui', array($replacer, 'callback'), $body);
}
return $body;
}
/**
* modify a HTML message that it can be displayed inside a HTML page
*/
function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null)
{
$last_style_pos = 0;
$cont_id = $container_id.($body_id ? ' div.'.$body_id : '');
// find STYLE tags
while (($pos = stripos($body, '<style', $last_style_pos)) && ($pos2 = stripos($body, '</style>', $pos)))
{
$pos = strpos($body, '>', $pos)+1;
// replace all css definitions with #container [def]
$styles = rcmail_mod_css_styles(
substr($body, $pos, $pos2-$pos), $cont_id);
$body = substr_replace($body, $styles, $pos, $pos2-$pos);
$last_style_pos = $pos2;
}
// modify HTML links to open a new window if clicked
$GLOBALS['rcmail_html_container_id'] = $container_id;
$body = preg_replace_callback('/<(a|link)\s+([^>]+)>/Ui', 'rcmail_alter_html_link', $body);
unset($GLOBALS['rcmail_html_container_id']);
$body = preg_replace(array(
// add comments arround html and other tags
'/(<!DOCTYPE[^>]*>)/i',
'/(<\?xml[^>]*>)/i',
'/(<\/?html[^>]*>)/i',
'/(<\/?head[^>]*>)/i',
'/(<title[^>]*>.*<\/title>)/Ui',
'/(<\/?meta[^>]*>)/i',
// quote <? of php and xml files that are specified as text/html
'/<\?/',
'/\?>/',
// replace <body> with <div>
'/<body([^>]*)>/i',
'/<\/body>/i',
),
array(
'<!--\\1-->',
'<!--\\1-->',
'<!--\\1-->',
'<!--\\1-->',
'<!--\\1-->',
'<!--\\1-->',
'&lt;?',
'?&gt;',
'<div class="'.$body_id.'"\\1>',
'</div>',
),
$body);
$attributes = array();
// Handle body attributes that doesn't play nicely with div elements
$regexp = '/<div class="' . preg_quote($body_id, '/') . '"([^>]*)/';
if (preg_match($regexp, $body, $m)) {
$attrs = $m[0];
// Get bgcolor, we'll set it as background-color of the message container
if ($m[1] && preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/', $attrs, $mb)) {
$attributes['background-color'] = $mb[1];
$attrs = preg_replace('/bgcolor=["\']*([a-z0-9#]+)["\']*/', '', $attrs);
}
// Get background, we'll set it as background-image of the message container
if ($m[1] && preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) {
$attributes['background-image'] = 'url('.$mb[1].')';
$attrs = preg_replace('/background=["\']*([^"\'>\s]+)["\']*/', '', $attrs);
}
if (!empty($attributes)) {
$body = preg_replace($regexp, rtrim($attrs), $body, 1);
}
// handle body styles related to background image
if ($attributes['background-image']) {
// get body style
if (preg_match('/#'.preg_quote($cont_id, '/').'\s+\{([^}]+)}/i', $body, $m)) {
// get background related style
if (preg_match_all('/(background-position|background-repeat)\s*:\s*([^;]+);/i', $m[1], $ma, PREG_SET_ORDER)) {
foreach ($ma as $style)
$attributes[$style[1]] = $style[2];
}
}
}
}
// make sure there's 'rcmBody' div, we need it for proper css modification
// its name is hardcoded in rcmail_message_body() also
else {
$body = '<div class="' . $body_id . '">' . $body . '</div>';
}
return $body;
}
/**
* parse link attributes and set correct target
*/
function rcmail_alter_html_link($matches)
{
global $RCMAIL;
// Support unicode/punycode in top-level domain part
$EMAIL_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[^&@"\'.][^@&"\']*\\.([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,}))';
$tag = $matches[1];
$attrib = parse_attrib_string($matches[2]);
$end = '>';
// Remove non-printable characters in URL (#1487805)
$attrib['href'] = preg_replace('/[\x00-\x1F]/', '', $attrib['href']);
if ($tag == 'link' && preg_match('/^https?:\/\//i', $attrib['href'])) {
$tempurl = 'tmp-' . md5($attrib['href']) . '.css';
$_SESSION['modcssurls'][$tempurl] = $attrib['href'];
$attrib['href'] = $RCMAIL->url(array('task' => 'utils', 'action' => 'modcss', 'u' => $tempurl, 'c' => $GLOBALS['rcmail_html_container_id']));
$end = ' />';
}
else if (preg_match('/^mailto:'.$EMAIL_PATTERN.'(\?[^"\'>]+)?/i', $attrib['href'], $mailto)) {
$attrib['href'] = $mailto[0];
$attrib['onclick'] = sprintf(
"return %s.command('compose','%s',this)",
JS_OBJECT_NAME,
JQ($mailto[1].$mailto[3]));
}
else if (!empty($attrib['href']) && $attrib['href'][0] != '#') {
$attrib['target'] = '_blank';
}
return "<$tag" . html::attrib_string($attrib, array('href','name','target','onclick','id','class','style','title','rel','type','media')) . $end;
}
/**
* decode address string and re-format it as HTML links
*/
function rcmail_address_string($input, $max=null, $linked=false, $addicon=null)
{
- global $IMAP, $RCMAIL, $PRINT_MODE, $CONFIG;
+ global $RCMAIL, $PRINT_MODE, $CONFIG;
- $a_parts = $IMAP->decode_address_list($input);
+ $a_parts = $RCMAIL->imap->decode_address_list($input);
if (!sizeof($a_parts))
return $input;
$c = count($a_parts);
$j = 0;
$out = '';
if ($addicon && !isset($_SESSION['writeable_abook'])) {
$_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false;
}
foreach ($a_parts as $part) {
$j++;
$name = $part['name'];
$mailto = $part['mailto'];
$string = $part['string'];
// IDNA ASCII to Unicode
if ($name == $mailto)
$name = rcube_idn_to_utf8($name);
if ($string == $mailto)
$string = rcube_idn_to_utf8($string);
$mailto = rcube_idn_to_utf8($mailto);
if ($PRINT_MODE) {
$out .= sprintf('%s &lt;%s&gt;', Q($name), $mailto);
}
else if (check_email($part['mailto'], false)) {
if ($linked) {
$address = html::a(array(
'href' => 'mailto:'.$mailto,
'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($mailto)),
'title' => $mailto,
'class' => "rcmContactAddress",
),
Q($name ? $name : $mailto));
}
else {
$address = html::span(array('title' => $mailto, 'class' => "rcmContactAddress"),
Q($name ? $name : $mailto));
}
if ($addicon && $_SESSION['writeable_abook']) {
$address = html::span(null, $address . html::a(array(
'href' => "#add",
'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, urlencode($string)),
'title' => rcube_label('addtoaddressbook'),
),
html::img(array(
'src' => $CONFIG['skin_path'] . $addicon,
'alt' => "Add contact",
))));
}
$out .= $address;
}
else {
if ($name)
$out .= Q($name);
if ($mailto)
$out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
}
if ($c>$j)
$out .= ','.($max ? '&nbsp;' : ' ');
if ($max && $j==$max && $c>$j) {
$out .= '...';
break;
}
}
return $out;
}
/**
* Wrap text to a given number of characters per line
* but respect the mail quotation of replies messages (>).
* Finally add another quotation level by prpending the lines
* with >
*
* @param string Text to wrap
* @param int The line width
* @return string The wrapped text
*/
function rcmail_wrap_and_quote($text, $length = 72)
{
// Rebuild the message body with a maximum of $max chars, while keeping quoted message.
$max = min(77, $length + 8);
$lines = preg_split('/\r?\n/', trim($text));
$out = '';
foreach ($lines as $line) {
// don't wrap already quoted lines
if ($line[0] == '>')
$line = '>' . rtrim($line);
else if (mb_strlen($line) > $max) {
$newline = '';
foreach(explode("\n", rc_wordwrap($line, $length - 2)) as $l) {
if (strlen($l))
$newline .= '> ' . $l . "\n";
else
$newline .= ">\n";
}
$line = rtrim($newline);
}
else
$line = '> ' . $line;
// Append the line
$out .= $line . "\n";
}
return $out;
}
function rcmail_draftinfo_encode($p)
{
$parts = array();
foreach ($p as $key => $val)
$parts[] = $key . '=' . ($key == 'folder' ? base64_encode($val) : $val);
return join('; ', $parts);
}
function rcmail_draftinfo_decode($str)
{
$info = array();
foreach (preg_split('/;\s+/', $str) as $part) {
list($key, $val) = explode('=', $part, 2);
if ($key == 'folder')
$val = base64_decode($val);
$info[$key] = $val;
}
return $info;
}
function rcmail_message_part_controls()
{
global $MESSAGE;
$part = asciiwords(get_input_value('_part', RCUBE_INPUT_GPC));
if (!is_object($MESSAGE) || !is_array($MESSAGE->parts) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE->mime_parts[$part])
return '';
$part = $MESSAGE->mime_parts[$part];
$table = new html_table(array('cols' => 3));
if (!empty($part->filename)) {
$table->add('title', Q(rcube_label('filename')));
$table->add(null, Q($part->filename));
$table->add(null, '[' . html::a('?'.str_replace('_frame=', '_download=', $_SERVER['QUERY_STRING']), Q(rcube_label('download'))) . ']');
}
if (!empty($part->size)) {
$table->add('title', Q(rcube_label('filesize')));
$table->add(null, Q(show_bytes($part->size)));
}
return $table->show($attrib);
}
function rcmail_message_part_frame($attrib)
{
global $MESSAGE;
$part = $MESSAGE->mime_parts[asciiwords(get_input_value('_part', RCUBE_INPUT_GPC))];
$ctype_primary = strtolower($part->ctype_primary);
$attrib['src'] = './?' . str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']);
return html::iframe($attrib);
}
/**
* clear message composing settings
*/
function rcmail_compose_cleanup($id)
{
if (!isset($_SESSION['compose_data_'.$id]))
return;
$rcmail = rcmail::get_instance();
$rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id));
$rcmail->session->remove('compose_data_'.$id);
}
/**
* Send the MDN response
*
* @param mixed $message Original message object (rcube_message) or UID
* @param array $smtp_error SMTP error array (reference)
*
* @return boolean Send status
*/
function rcmail_send_mdn($message, &$smtp_error)
{
- global $RCMAIL, $IMAP;
+ global $RCMAIL;
if (!is_object($message) || !is_a($message, 'rcube_message'))
$message = new rcube_message($message);
if ($message->headers->mdn_to && empty($message->headers->flags['MDNSENT']) &&
- ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*')))
+ ($RCMAIL->imap->check_permflag('MDNSENT') || $RCMAIL->imap->check_permflag('*')))
{
$identity = $RCMAIL->user->get_identity();
$sender = format_email_recipient($identity['email'], $identity['name']);
- $recipient = array_shift($IMAP->decode_address_list($message->headers->mdn_to));
+ $recipient = array_shift($RCMAIL->imap->decode_address_list($message->headers->mdn_to));
$mailto = $recipient['mailto'];
$compose = new Mail_mime("\r\n");
$compose->setParam('text_encoding', 'quoted-printable');
$compose->setParam('html_encoding', 'quoted-printable');
$compose->setParam('head_encoding', 'quoted-printable');
$compose->setParam('head_charset', RCMAIL_CHARSET);
$compose->setParam('html_charset', RCMAIL_CHARSET);
$compose->setParam('text_charset', RCMAIL_CHARSET);
// compose headers array
$headers = array(
'Date' => rcmail_user_date(),
'From' => $sender,
'To' => $message->headers->mdn_to,
'Subject' => rcube_label('receiptread') . ': ' . $message->subject,
'Message-ID' => rcmail_gen_message_id(),
'X-Sender' => $identity['email'],
'References' => trim($message->headers->references . ' ' . $message->headers->messageID),
);
if ($agent = $RCMAIL->config->get('useragent'))
$headers['User-Agent'] = $agent;
$body = rcube_label("yourmessage") . "\r\n\r\n" .
"\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($message->headers->to, $message->headers->charset) . "\r\n" .
"\t" . rcube_label("subject") . ': ' . $message->subject . "\r\n" .
"\t" . rcube_label("sent") . ': ' . format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" .
"\r\n" . rcube_label("receiptnote") . "\r\n";
$ua = $RCMAIL->config->get('useragent', "Roundcube Webmail (Version ".RCMAIL_VERSION.")");
$report = "Reporting-UA: $ua\r\n";
if ($message->headers->to)
$report .= "Original-Recipient: {$message->headers->to}\r\n";
$report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" .
"Original-Message-ID: {$message->headers->messageID}\r\n" .
"Disposition: manual-action/MDN-sent-manually; displayed\r\n";
$compose->headers($headers);
$compose->setContentType('multipart/report', array('report-type'=> 'disposition-notification'));
$compose->setTXTBody(rc_wordwrap($body, 75, "\r\n"));
$compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
$sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file);
if ($sent)
{
- $IMAP->set_flag($message->uid, 'MDNSENT');
+ $RCMAIL->imap->set_flag($message->uid, 'MDNSENT');
return true;
}
}
return false;
}
// Fixes some content-type names
function rcmail_fix_mimetype($name)
{
// Some versions of Outlook create garbage Content-Type:
// application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608
if (preg_match('/^application\/pdf.+/', $name))
$name = 'application/pdf';
return $name;
}
function rcmail_search_filter($attrib)
{
global $OUTPUT, $CONFIG;
if (!strlen($attrib['id']))
$attrib['id'] = 'rcmlistfilter';
$attrib['onchange'] = JS_OBJECT_NAME.'.filter_mailbox(this.value)';
/*
RFC3501 (6.4.4): 'ALL', 'RECENT',
'ANSWERED', 'DELETED', 'FLAGGED', 'SEEN',
'UNANSWERED', 'UNDELETED', 'UNFLAGGED', 'UNSEEN',
'NEW', // = (RECENT UNSEEN)
'OLD' // = NOT RECENT
*/
$select_filter = new html_select($attrib);
$select_filter->add(rcube_label('all'), 'ALL');
$select_filter->add(rcube_label('unread'), 'UNSEEN');
$select_filter->add(rcube_label('flagged'), 'FLAGGED');
$select_filter->add(rcube_label('unanswered'), 'UNANSWERED');
if (!$CONFIG['skip_deleted'])
$select_filter->add(rcube_label('deleted'), 'DELETED');
$select_filter->add(rcube_label('priority').': '.rcube_label('highest'), 'HEADER X-PRIORITY 1');
$select_filter->add(rcube_label('priority').': '.rcube_label('high'), 'HEADER X-PRIORITY 2');
$select_filter->add(rcube_label('priority').': '.rcube_label('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5');
$select_filter->add(rcube_label('priority').': '.rcube_label('low'), 'HEADER X-PRIORITY 4');
$select_filter->add(rcube_label('priority').': '.rcube_label('lowest'), 'HEADER X-PRIORITY 5');
$out = $select_filter->show($_SESSION['search_filter']);
$OUTPUT->add_gui_object('search_filter', $attrib['id']);
return $out;
}
function rcmail_message_error($uid=null)
{
global $RCMAIL;
// Set env variables for messageerror.html template
if ($RCMAIL->action == 'show') {
$mbox_name = $RCMAIL->imap->get_mailbox_name();
$RCMAIL->output->set_env('mailbox', $mbox_name);
$RCMAIL->output->set_env('uid', null);
}
// display error message
$RCMAIL->output->show_message('messageopenerror', 'error');
// ... display message error page
$RCMAIL->output->send('messageerror');
}
// register UI objects
$OUTPUT->add_handlers(array(
'mailboxlist' => 'rcmail_mailbox_list',
'messages' => 'rcmail_message_list',
'messagecountdisplay' => 'rcmail_messagecount_display',
'quotadisplay' => 'rcmail_quota_display',
'mailboxname' => 'rcmail_mailbox_name_display',
'messageheaders' => 'rcmail_message_headers',
'messagefullheaders' => 'rcmail_message_full_headers',
'messagebody' => 'rcmail_message_body',
'messagecontentframe' => 'rcmail_messagecontent_frame',
'messagepartframe' => 'rcmail_message_part_frame',
'messagepartcontrols' => 'rcmail_message_part_controls',
'searchfilter' => 'rcmail_search_filter',
'searchform' => array($OUTPUT, 'search_form'),
));
// register action aliases
$RCMAIL->register_action_map(array(
'preview' => 'show.inc',
'print' => 'show.inc',
'moveto' => 'move_del.inc',
'delete' => 'move_del.inc',
'send' => 'sendmail.inc',
'expunge' => 'folders.inc',
'purge' => 'folders.inc',
'remove-attachment' => 'attachments.inc',
'display-attachment' => 'attachments.inc',
'upload' => 'attachments.inc',
'group-expand' => 'autocomplete.inc',
));
diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc
index 1e0583cf8..cbe59346f 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -1,232 +1,232 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/get.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Delivering a specific part of a mail message |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// show loading page
if (!empty($_GET['_preload'])) {
$url = preg_replace('/[&?]+_preload=1/', '', $_SERVER['REQUEST_URI']);
$message = rcube_label('loadingdata');
header('Content-Type: text/html; charset=' . RCMAIL_CHARSET);
print "<html>\n<head>\n"
. '<meta http-equiv="refresh" content="0; url='.Q($url).'">' . "\n"
. '<meta http-equiv="content-type" content="text/html; charset='.RCMAIL_CHARSET.'">' . "\n"
. "</head>\n<body>\n$message\n</body>\n</html>";
exit;
}
ob_end_clean();
// Now we need IMAP connection
if (!$RCMAIL->imap_connect()) {
// Get action is often executed simultanously.
// Some servers have MAXPERIP or other limits.
// To workaround this we'll wait for some time
// and try again (once).
// Note: Random sleep interval is used to minimize concurency
// in getting message parts
if (!isset($_GET['_redirected'])) {
usleep(rand(10,30)*100000); // 1-3 sec.
header('Location: ' . $_SERVER['REQUEST_URI'] . '&_redirected=1');
}
else {
raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => 'Unable to get/display message part. IMAP connection error'),
true, true);
}
// Don't kill session, just quit (#1486995)
exit;
}
// similar code as in program/steps/mail/show.inc
if (!empty($_GET['_uid'])) {
$RCMAIL->config->set('prefer_html', true);
$MESSAGE = new rcube_message(get_input_value('_uid', RCUBE_INPUT_GET));
}
// show part page
if (!empty($_GET['_frame'])) {
if (($part_id = get_input_value('_part', RCUBE_INPUT_GPC)) && ($part = $MESSAGE->mime_parts[$part_id]) && $part->filename)
$OUTPUT->set_pagetitle($part->filename);
-
+
$OUTPUT->send('messagepart');
exit;
}
else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
if ($part = $MESSAGE->mime_parts[$pid]) {
$ctype_primary = strtolower($part->ctype_primary);
$ctype_secondary = strtolower($part->ctype_secondary);
$mimetype = sprintf('%s/%s', $ctype_primary, $ctype_secondary);
// allow post-processing of the message body
$plugin = $RCMAIL->plugins->exec_hook('message_part_get',
array('id' => $part->mime_id, 'mimetype' => $mimetype, 'part' => $part, 'download' => !empty($_GET['_download'])));
if ($plugin['abort'])
exit;
// overwrite modified vars from plugin
$mimetype = $plugin['mimetype'];
list($ctype_primary, $ctype_secondary) = explode('/', $mimetype);
if ($plugin['body'])
$part->body = $plugin['body'];
$browser = $RCMAIL->output->browser;
// send download headers
if ($plugin['download']) {
header("Content-Type: application/octet-stream");
if ($browser->ie)
header("Content-Type: application/force-download");
}
else if ($ctype_primary == 'text') {
header("Content-Type: text/$ctype_secondary; charset=" . ($part->charset ? $part->charset : RCMAIL_CHARSET));
}
else {
$mimetype = rcmail_fix_mimetype($mimetype);
header("Content-Type: $mimetype");
header("Content-Transfer-Encoding: binary");
}
// deliver part content
if ($ctype_primary == 'text' && $ctype_secondary == 'html' && empty($plugin['download'])) {
// Check if we have enough memory to handle the message in it
// #1487424: we need up to 10x more memory than the body
if (!rcmail_mem_check($part->size * 10)) {
$out = '<body>' . rcube_label('messagetoobig'). ' '
. html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id
- .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')) . '</body></html>';
+ .'&_mbox='. urlencode($RCMAIL->imap->get_mailbox_name()), rcube_label('download')) . '</body></html>';
}
else {
// get part body if not available
if (!$part->body)
$part->body = $MESSAGE->get_part_content($part->mime_id);
$out = rcmail_print_body($part, array('safe' => $MESSAGE->is_safe, 'inline_html' => false));
}
$OUTPUT = new rcube_html_page();
$OUTPUT->write($out);
}
else {
// don't kill the connection if download takes more than 30 sec.
@set_time_limit(0);
$ext = '.' . ($mimetype == 'text/plain' ? 'txt' : $ctype_secondary);
$filename = $part->filename ? $part->filename : ($MESSAGE->subject ? $MESSAGE->subject : 'roundcube') . $ext;
$filename = preg_replace('[\r\n]', '', $filename);
if ($browser->ie && $browser->ver < 7)
$filename = rawurlencode(abbreviate_string($filename, 55));
else if ($browser->ie)
$filename = rawurlencode($filename);
else
$filename = addcslashes($filename, '"');
$disposition = !empty($plugin['download']) ? 'attachment' : 'inline';
header("Content-Disposition: $disposition; filename=\"$filename\"");
// do content filtering to avoid XSS through fake images
if (!empty($_REQUEST['_embed']) && $browser->ie && $browser->ver <= 8) {
if ($part->body)
echo preg_match('/<(script|iframe|object)/i', $part->body) ? '' : $part->body;
else if ($part->size) {
$stdout = fopen('php://output', 'w');
stream_filter_register('rcube_content', 'rcube_content_filter') or die('Failed to register content filter');
stream_filter_append($stdout, 'rcube_content');
- $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout);
+ $RCMAIL->imap->get_message_part($MESSAGE->uid, $part->mime_id, $part, false, $stdout);
}
}
else {
// turn off output buffering and print part content
if ($part->body)
echo $part->body;
else if ($part->size)
- $IMAP->get_message_part($MESSAGE->uid, $part->mime_id, $part, true);
+ $RCMAIL->imap->get_message_part($MESSAGE->uid, $part->mime_id, $part, true);
}
}
exit;
}
}
// print message
else {
// send correct headers for content type
header("Content-Type: text/html");
$cont = "<html>\n<head><title></title>\n</head>\n<body>";
$cont .= rcmail_message_body(array());
$cont .= "\n</body>\n</html>";
$OUTPUT = new rcube_html_page();
$OUTPUT->write($cont);
exit;
}
// if we arrive here, the requested part was not found
header('HTTP/1.1 404 Not Found');
exit;
/**
* PHP stream filter to detect html/javascript code in attachments
*/
class rcube_content_filter extends php_user_filter
{
private $buffer = '';
private $cutoff = 2048;
function onCreate()
{
$this->cutoff = rand(2048, 3027);
return true;
}
function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
$this->buffer .= $bucket->data;
// check for evil content and abort
if (preg_match('/<(script|iframe|object)/i', $this->buffer))
return PSFS_ERR_FATAL;
// keep buffer small enough
if (strlen($this->buffer) > 4096)
$this->buffer = substr($this->buffer, $this->cutoff);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
diff --git a/program/steps/mail/getunread.inc b/program/steps/mail/getunread.inc
index 27ae5f747..39880b99b 100644
--- a/program/steps/mail/getunread.inc
+++ b/program/steps/mail/getunread.inc
@@ -1,48 +1,48 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/getunread.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Check all mailboxes for unread messages and update GUI |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
-$a_folders = $IMAP->list_mailboxes('', '*', 'mail');
+$a_folders = $RCMAIL->imap->list_mailboxes('', '*', 'mail');
if (!empty($a_folders))
{
- $current = $IMAP->get_mailbox_name();
+ $current = $RCMAIL->imap->get_mailbox_name();
$inbox = ($current == 'INBOX');
$check_all = (bool)$RCMAIL->config->get('check_all_folders');
foreach ($a_folders as $mbox_row) {
$unseen_old = rcmail_get_unseen_count($mbox_row);
if (!$check_all && $unseen_old !== null && $mbox_row != $current)
$unseen = $unseen_old;
else
- $unseen = $IMAP->messagecount($mbox_row, 'UNSEEN', $unseen_old === null);
+ $unseen = $RCMAIL->imap->messagecount($mbox_row, 'UNSEEN', $unseen_old === null);
if ($unseen || $unseen_old === null) {
$OUTPUT->command('set_unread_count', $mbox_row, $unseen, $inbox && $mbox_row == 'INBOX');
}
rcmail_set_unseen_count($mbox_row, $unseen);
}
}
$OUTPUT->send();
diff --git a/program/steps/mail/headers.inc b/program/steps/mail/headers.inc
index 7d166f915..5eee4bdef 100644
--- a/program/steps/mail/headers.inc
+++ b/program/steps/mail/headers.inc
@@ -1,50 +1,50 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/headers.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2007, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Fetch message headers in raw format for display |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
$Id$
*/
if ($uid = get_input_value('_uid', RCUBE_INPUT_POST))
{
- $source = $IMAP->get_raw_headers($uid);
+ $source = $RCMAIL->imap->get_raw_headers($uid);
if ($source !== false) {
$source = htmlspecialchars(trim($source));
$source = preg_replace(
array(
'/\n[\t\s]+/',
'/^([a-z0-9_:-]+)/im',
'/\r?\n/'
),
array(
"\n&nbsp;&nbsp;&nbsp;&nbsp;",
'<font class="bold">\1</font>',
'<br />'
), $source);
$OUTPUT->command('set_headers', $source);
}
else {
$RCMAIL->output->show_message('messageopenerror', 'error');
}
$OUTPUT->send();
}
exit;
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index 9988a00b4..c2a47488f 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -1,121 +1,121 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/list.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2007, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Send message list to client (as remote response) |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
if (!$OUTPUT->ajax_call) {
return;
}
// is there a sort type for this request?
if ($sort = get_input_value('_sort', RCUBE_INPUT_GET))
{
// yes, so set the sort vars
list($sort_col, $sort_order) = explode('_', $sort);
// set session vars for sort (so next page and task switch know how to sort)
$save_arr = array();
$_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
$_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
}
else
{
// use session settings if set, defaults if not
$sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
}
// is there a set of columns for this request?
if ($cols = get_input_value('_cols', RCUBE_INPUT_GET))
{
$save_arr = array();
$save_arr['list_cols'] = explode(',', $cols);
}
if ($save_arr)
$RCMAIL->user->save_prefs($save_arr);
-$mbox_name = $IMAP->get_mailbox_name();
+$mbox_name = $RCMAIL->imap->get_mailbox_name();
// Synchronize mailbox cache, handle flag changes
-$IMAP->mailbox_sync($mbox_name);
+$RCMAIL->imap->mailbox_sync($mbox_name);
// initialize searching result if search_filter is used
if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
{
$search_request = md5($mbox_name.$_SESSION['search_filter']);
- $IMAP->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $sort_col);
- $_SESSION['search'] = $IMAP->get_search_set();
+ $RCMAIL->imap->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, $sort_col);
+ $_SESSION['search'] = $RCMAIL->imap->get_search_set();
$_SESSION['search_request'] = $search_request;
$OUTPUT->set_env('search_request', $search_request);
}
// fetch message headers
-if ($count = $IMAP->messagecount($mbox_name, $IMAP->threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh'])))
- $a_headers = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order);
+if ($count = $RCMAIL->imap->messagecount($mbox_name, $RCMAIL->imap->threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh'])))
+ $a_headers = $RCMAIL->imap->list_headers($mbox_name, NULL, $sort_col, $sort_order);
// update search set (possible change of threading mode)
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
&& $_SESSION['search_request'] == $_REQUEST['_search']
) {
- $_SESSION['search'] = $IMAP->get_search_set();
+ $_SESSION['search'] = $RCMAIL->imap->get_search_set();
}
// remove old search data
else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) {
$RCMAIL->session->remove('search');
}
// empty result? we'll skip UNSEEN counting in rcmail_send_unread_count()
if (empty($search_request) && empty($a_headers)) {
$unseen = 0;
}
// update mailboxlist
rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']), $unseen);
// update message count display
-$pages = ceil($count/$IMAP->page_size);
+$pages = ceil($count/$RCMAIL->imap->page_size);
$OUTPUT->set_env('messagecount', $count);
$OUTPUT->set_env('pagecount', $pages);
-$OUTPUT->set_env('threading', (bool) $IMAP->threading);
-$OUTPUT->set_env('current_page', $count ? $IMAP->list_page : 1);
+$OUTPUT->set_env('threading', (bool) $RCMAIL->imap->threading);
+$OUTPUT->set_env('current_page', $count ? $RCMAIL->imap->list_page : 1);
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name);
$OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
// add message rows
rcmail_js_message_list($a_headers, FALSE, $cols);
if (isset($a_headers) && count($a_headers))
{
if ($search_request)
$OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
}
else {
// handle IMAP errors (e.g. #1486905)
- if ($err_code = $IMAP->get_error_code()) {
+ if ($err_code = $RCMAIL->imap->get_error_code()) {
rcmail_display_server_error();
}
else if ($search_request)
$OUTPUT->show_message('searchnomatch', 'notice');
else
$OUTPUT->show_message('nomessagesfound', 'notice');
}
// send response
$OUTPUT->send();
diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc
index c232d8c48..3b52dfe4f 100644
--- a/program/steps/mail/mark.inc
+++ b/program/steps/mail/mark.inc
@@ -1,129 +1,129 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/mark.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Mark the submitted messages with the specified flag |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
return;
$a_flags_map = array(
'undelete' => 'UNDELETED',
'delete' => 'DELETED',
'read' => 'SEEN',
'unread' => 'UNSEEN',
'flagged' => 'FLAGGED',
'unflagged' => 'UNFLAGGED');
if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_value('_flag', RCUBE_INPUT_POST)))
{
$flag = $a_flags_map[$flag] ? $a_flags_map[$flag] : strtoupper($flag);
if ($flag == 'DELETED' && $CONFIG['skip_deleted'] && $_POST['_from'] != 'show') {
// count messages before changing anything
- $old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
- $old_pages = ceil($old_count / $IMAP->page_size);
+ $old_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
+ $old_pages = ceil($old_count / $RCMAIL->imap->page_size);
$count = sizeof(explode(',', $uids));
}
- $marked = $IMAP->set_flag($uids, $flag);
+ $marked = $RCMAIL->imap->set_flag($uids, $flag);
if (!$marked) {
// send error message
if ($_POST['_from'] != 'show')
$OUTPUT->command('list_mailbox');
rcmail_display_server_error('errormarking');
$OUTPUT->send();
exit;
}
else if (empty($_POST['_quiet'])) {
$OUTPUT->show_message('messagemarked', 'confirmation');
}
if ($flag == 'DELETED' && $CONFIG['read_when_deleted'] && !empty($_POST['_ruid'])) {
$ruids = get_input_value('_ruid', RCUBE_INPUT_POST);
- $read = $IMAP->set_flag($ruids, 'SEEN');
+ $read = $RCMAIL->imap->set_flag($ruids, 'SEEN');
if ($read && !$CONFIG['skip_deleted'])
$OUTPUT->command('flag_deleted_as_read', $ruids);
}
if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$CONFIG['skip_deleted'])) {
- rcmail_send_unread_count($IMAP->get_mailbox_name());
+ rcmail_send_unread_count($RCMAIL->imap->get_mailbox_name());
}
else if ($flag == 'DELETED' && $CONFIG['skip_deleted']) {
if ($_POST['_from'] == 'show') {
if ($next = get_input_value('_next_uid', RCUBE_INPUT_GPC))
$OUTPUT->command('show_message', $next);
else
$OUTPUT->command('command', 'list');
} else {
// refresh saved search set after moving some messages
- if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $IMAP->search_set) {
- $_SESSION['search'] = $IMAP->refresh_search();
+ if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $RCMAIL->imap->search_set) {
+ $_SESSION['search'] = $RCMAIL->imap->refresh_search();
}
- $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
- $pages = ceil($msg_count / $IMAP->page_size);
- $nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page;
- $remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1);
+ $msg_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
+ $pages = ceil($msg_count / $RCMAIL->imap->page_size);
+ $nextpage_count = $old_count - $RCMAIL->imap->page_size * $RCMAIL->imap->list_page;
+ $remaining = $msg_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1);
// jump back one page (user removed the whole last page)
- if ($IMAP->list_page > 1 && $remaining == 0) {
- $IMAP->set_page($IMAP->list_page-1);
- $_SESSION['page'] = $IMAP->list_page;
+ if ($RCMAIL->imap->list_page > 1 && $remaining == 0) {
+ $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1);
+ $_SESSION['page'] = $RCMAIL->imap->list_page;
$jump_back = true;
}
// update message count display
$OUTPUT->set_env('messagecount', $msg_count);
- $OUTPUT->set_env('current_page', $IMAP->list_page);
+ $OUTPUT->set_env('current_page', $RCMAIL->imap->list_page);
$OUTPUT->set_env('pagecount', $pages);
// update mailboxlist
- $mbox = $IMAP->get_mailbox_name();
- $unseen_count = $msg_count ? $IMAP->messagecount($mbox, 'UNSEEN') : 0;
+ $mbox = $RCMAIL->imap->get_mailbox_name();
+ $unseen_count = $msg_count ? $RCMAIL->imap->messagecount($mbox, 'UNSEEN') : 0;
$old_unseen = rcmail_get_unseen_count($mbox);
if ($old_unseen != $unseen_count) {
$OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
rcmail_set_unseen_count($mbox, $unseen_count);
}
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
- if ($IMAP->threading)
+ if ($RCMAIL->imap->threading)
$count = get_input_value('_count', RCUBE_INPUT_POST);
// add new rows from next page (if any)
if ($count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
$sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
- $a_headers = $IMAP->list_headers($mbox, NULL, $sort_col, $sort_order,
+ $a_headers = $RCMAIL->imap->list_headers($mbox, NULL, $sort_col, $sort_order,
$jump_back ? NULL : $count);
rcmail_js_message_list($a_headers, false);
}
}
}
$OUTPUT->send();
}
exit;
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index a42bc90cd..95a456ed5 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -1,144 +1,144 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/move_del.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Move the submitted messages to a specific mailbox or delete them |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// only process ajax requests
if (!$OUTPUT->ajax_call)
return;
// count messages before changing anything
-$old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
-$old_pages = ceil($old_count / $IMAP->page_size);
+$old_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
+$old_pages = ceil($old_count / $RCMAIL->imap->page_size);
// move messages
if ($RCMAIL->action=='moveto' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
$count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST))));
$target = get_input_value('_target_mbox', RCUBE_INPUT_POST, true);
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
- $moved = $IMAP->move_message($uids, $target, $mbox);
+ $moved = $RCMAIL->imap->move_message($uids, $target, $mbox);
if (!$moved) {
// send error message
if ($_POST['_from'] != 'show')
$OUTPUT->command('list_mailbox');
rcmail_display_server_error('errormoving');
$OUTPUT->send();
exit;
}
else {
$OUTPUT->show_message('messagemoved', 'confirmation');
}
$addrows = true;
}
// delete messages
else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {
$count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST))));
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
- $del = $IMAP->delete_message($uids, $mbox);
+ $del = $RCMAIL->imap->delete_message($uids, $mbox);
if (!$del) {
// send error message
if ($_POST['_from'] != 'show')
$OUTPUT->command('list_mailbox');
rcmail_display_server_error('errordeleting');
$OUTPUT->send();
exit;
}
else {
$OUTPUT->show_message('messagedeleted', 'confirmation');
}
$addrows = true;
}
// unknown action or missing query param
else {
exit;
}
// refresh saved search set after moving some messages
-if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $IMAP->search_set) {
- $_SESSION['search'] = $IMAP->refresh_search();
+if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $RCMAIL->imap->search_set) {
+ $_SESSION['search'] = $RCMAIL->imap->refresh_search();
}
if ($_POST['_from'] == 'show')
{
if ($next = get_input_value('_next_uid', RCUBE_INPUT_GPC))
$OUTPUT->command('show_message', $next);
else
$OUTPUT->command('command', 'list');
}
else
{
- $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL');
- $pages = ceil($msg_count / $IMAP->page_size);
- $nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page;
- $remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1);
+ $msg_count = $RCMAIL->imap->messagecount(NULL, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
+ $pages = ceil($msg_count / $RCMAIL->imap->page_size);
+ $nextpage_count = $old_count - $RCMAIL->imap->page_size * $RCMAIL->imap->list_page;
+ $remaining = $msg_count - $RCMAIL->imap->page_size * ($RCMAIL->imap->list_page - 1);
// jump back one page (user removed the whole last page)
- if ($IMAP->list_page > 1 && $remaining == 0) {
- $IMAP->set_page($IMAP->list_page-1);
- $_SESSION['page'] = $IMAP->list_page;
+ if ($RCMAIL->imap->list_page > 1 && $remaining == 0) {
+ $RCMAIL->imap->set_page($RCMAIL->imap->list_page-1);
+ $_SESSION['page'] = $RCMAIL->imap->list_page;
$jump_back = true;
}
// update message count display
$OUTPUT->set_env('messagecount', $msg_count);
- $OUTPUT->set_env('current_page', $IMAP->list_page);
+ $OUTPUT->set_env('current_page', $RCMAIL->imap->list_page);
$OUTPUT->set_env('pagecount', $pages);
// update mailboxlist
- $mbox = $IMAP->get_mailbox_name();
- $unseen_count = $msg_count ? $IMAP->messagecount($mbox, 'UNSEEN') : 0;
+ $mbox = $RCMAIL->imap->get_mailbox_name();
+ $unseen_count = $msg_count ? $RCMAIL->imap->messagecount($mbox, 'UNSEEN') : 0;
$old_unseen = rcmail_get_unseen_count($mbox);
if ($old_unseen != $unseen_count) {
$OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
rcmail_set_unseen_count($mbox, $unseen_count);
}
if ($RCMAIL->action == 'moveto' && strlen($target)) {
rcmail_send_unread_count($target, true);
}
$OUTPUT->command('set_quota', rcmail_quota_content());
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox);
- if ($IMAP->threading)
+ if ($RCMAIL->imap->threading)
$count = get_input_value('_count', RCUBE_INPUT_POST);
// add new rows from next page (if any)
if ($addrows && $count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
$sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col'];
$sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
- $a_headers = $IMAP->list_headers($mbox, NULL, $sort_col, $sort_order,
+ $a_headers = $RCMAIL->imap->list_headers($mbox, NULL, $sort_col, $sort_order,
$jump_back ? NULL : $count);
rcmail_js_message_list($a_headers, false);
}
}
// send response
$OUTPUT->send();
diff --git a/program/steps/mail/pagenav.inc b/program/steps/mail/pagenav.inc
index 16844f4e1..f15ac38de 100644
--- a/program/steps/mail/pagenav.inc
+++ b/program/steps/mail/pagenav.inc
@@ -1,57 +1,57 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/pagenav.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Updates message page navigation controls |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
$Id: show.inc 4176 2010-11-04 09:59:55Z alec $
*/
$uid = get_input_value('_uid', RCUBE_INPUT_GET);
-$index = $IMAP->message_index(null, $_SESSION['sort_col'], $_SESSION['sort_order']);
+$index = $RCMAIL->imap->message_index(null, $_SESSION['sort_col'], $_SESSION['sort_order']);
$cnt = $index->countMessages();
if ($cnt && ($pos = $index->exists($uid, true)) !== false) {
$prev = $pos ? $index->getElement($pos-1) : 0;
$first = $pos ? $index->getElement('FIRST') : 0;
$next = $pos < $cnt-1 ? $index->getElement($pos+1) : 0;
$last = $pos < $cnt-1 ? $index->getElement('LAST') : 0;
}
// Set UIDs and activate navigation buttons
if ($prev) {
$OUTPUT->set_env('prev_uid', $prev);
$OUTPUT->command('enable_command', 'previousmessage', 'firstmessage', true);
}
if ($next) {
$OUTPUT->set_env('next_uid', $next);
$OUTPUT->command('enable_command', 'nextmessage', 'lastmessage', true);
}
if ($first)
$OUTPUT->set_env('first_uid', $first);
if ($last)
$OUTPUT->set_env('last_uid', $last);
// Don't need a real messages count value
$OUTPUT->set_env('messagecount', 1);
// Set rowcount text
$OUTPUT->command('set_rowcount', rcube_label(array(
'name' => 'messagenrof',
'vars' => array('nr' => $pos+1, 'count' => $cnt)
)));
$OUTPUT->send();
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index 05ba9d23e..42bdf9776 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -1,149 +1,149 @@
<?php
/*
+-----------------------------------------------------------------------+
| steps/mail/search.inc |
| |
| Search functions for rc webmail |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
| Author: Benjamin Smith <defitro@gmail.com> |
| Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$REMOTE_REQUEST = TRUE;
// reset list_page and old search results
-$IMAP->set_page(1);
-$IMAP->set_search_set(NULL);
+$RCMAIL->imap->set_page(1);
+$RCMAIL->imap->set_search_set(NULL);
$_SESSION['page'] = 1;
// using encodeURI with javascript "should" give us
// a correctly encoded query string
$imap_charset = RCMAIL_CHARSET;
// get search string
$str = get_input_value('_q', RCUBE_INPUT_GET, true);
$mbox = get_input_value('_mbox', RCUBE_INPUT_GET, true);
$filter = get_input_value('_filter', RCUBE_INPUT_GET);
$headers = get_input_value('_headers', RCUBE_INPUT_GET);
$subject = array();
$search_request = md5($mbox.$filter.$str);
// add list filter string
$search_str = $filter && $filter != 'ALL' ? $filter : '';
$_SESSION['search_filter'] = $filter;
// Check the search string for type of search
if (preg_match("/^from:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['from'] = "HEADER FROM";
}
else if (preg_match("/^to:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['to'] = "HEADER TO";
}
else if (preg_match("/^cc:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['cc'] = "HEADER CC";
}
else if (preg_match("/^bcc:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['bcc'] = "HEADER BCC";
}
else if (preg_match("/^subject:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['subject'] = "HEADER SUBJECT";
}
else if (preg_match("/^body:.*/i", $str))
{
list(,$srch) = explode(":", $str);
$subject['text'] = "TEXT";
}
else if (strlen(trim($str)))
{
if ($headers) {
foreach (explode(',', $headers) as $header) {
if ($header == 'text') {
// #1488208: get rid of other headers when searching by "TEXT"
$subject = array('text' => 'TEXT');
break;
}
else {
$subject[$header] = 'HEADER '.strtoupper($header);
}
}
// save search modifiers for the current folder to user prefs
$search_mods = $RCMAIL->config->get('search_mods', $SEARCH_MODS_DEFAULT);
$search_mods[$mbox] = array_fill_keys(array_keys($subject), 1);
$RCMAIL->user->save_prefs(array('search_mods' => $search_mods));
} else {
// search in subject by default
$subject['subject'] = 'HEADER SUBJECT';
}
}
$search = isset($srch) ? trim($srch) : trim($str);
if (!empty($subject)) {
$search_str .= str_repeat(' OR', count($subject)-1);
foreach ($subject as $sub)
$search_str .= sprintf(" %s {%d}\r\n%s", $sub, strlen($search), $search);
}
$search_str = trim($search_str);
// execute IMAP search
if ($search_str)
- $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
+ $RCMAIL->imap->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
// save search results in session
if (!is_array($_SESSION['search']))
$_SESSION['search'] = array();
if ($search_str) {
- $_SESSION['search'] = $IMAP->get_search_set();
+ $_SESSION['search'] = $RCMAIL->imap->get_search_set();
$_SESSION['last_text_search'] = $str;
}
$_SESSION['search_request'] = $search_request;
// Get the headers
-$result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
-$count = $IMAP->messagecount($mbox, $IMAP->threading ? 'THREADS' : 'ALL');
+$result_h = $RCMAIL->imap->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
+$count = $RCMAIL->imap->messagecount($mbox, $RCMAIL->imap->threading ? 'THREADS' : 'ALL');
// Make sure we got the headers
if (!empty($result_h)) {
rcmail_js_message_list($result_h);
if ($search_str)
- $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $IMAP->messagecount(NULL, 'ALL')));
+ $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->imap->messagecount(NULL, 'ALL')));
}
// handle IMAP errors (e.g. #1486905)
-else if ($err_code = $IMAP->get_error_code()) {
+else if ($err_code = $RCMAIL->imap->get_error_code()) {
rcmail_display_server_error();
}
else {
$OUTPUT->show_message('searchnomatch', 'notice');
}
// update message count display
$OUTPUT->set_env('search_request', $search_str ? $search_request : '');
$OUTPUT->set_env('messagecount', $count);
-$OUTPUT->set_env('pagecount', ceil($count/$IMAP->page_size));
+$OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->imap->page_size));
$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox);
$OUTPUT->send();
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 6e124f98f..e4e5093b1 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -1,761 +1,761 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/sendmail.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Compose a new mail message with all headers and attachments |
| and send it using the PEAR::Net_SMTP class or with PHP mail() |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
// remove all scripts and act as called in frame
$OUTPUT->reset();
$OUTPUT->framed = TRUE;
$savedraft = !empty($_POST['_draft']) ? true : false;
$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
/****** checks ********/
if (!isset($COMPOSE['id'])) {
raise_error(array('code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, false);
$OUTPUT->show_message('internalerror', 'error');
$OUTPUT->send('iframe');
}
if (!$savedraft) {
if (empty($_POST['_to']) && empty($_POST['_cc']) && empty($_POST['_bcc'])
&& empty($_POST['_subject']) && $_POST['_message']) {
$OUTPUT->show_message('sendingfailed', 'error');
$OUTPUT->send('iframe');
}
if(!empty($CONFIG['sendmail_delay'])) {
$wait_sec = time() - intval($CONFIG['sendmail_delay']) - intval($CONFIG['last_message_time']);
if($wait_sec < 0) {
$OUTPUT->show_message('senttooquickly', 'error', array('sec' => $wait_sec * -1));
$OUTPUT->send('iframe');
}
}
}
/****** message sending functions ********/
// encrypt parts of the header
function rcmail_encrypt_header($what)
{
global $CONFIG, $RCMAIL;
if (!$CONFIG['http_received_header_encrypt']) {
return $what;
}
return $RCMAIL->encrypt($what);
}
// get identity record
function rcmail_get_identity($id)
{
global $USER, $OUTPUT;
if ($sql_arr = $USER->get_identity($id)) {
$out = $sql_arr;
$out['mailto'] = $sql_arr['email'];
$out['string'] = format_email_recipient($sql_arr['email'],
rcube_charset_convert($sql_arr['name'], RCMAIL_CHARSET, $OUTPUT->get_charset()));
return $out;
}
return FALSE;
}
/**
* go from this:
* <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*
* to this:
*
* <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
* ...
*/
function rcmail_fix_emoticon_paths(&$mime_message)
{
global $CONFIG;
$body = $mime_message->getHTMLBody();
// remove any null-byte characters before parsing
$body = preg_replace('/\x00/', '', $body);
$searchstr = 'program/js/tiny_mce/plugins/emotions/img/';
$offset = 0;
// keep track of added images, so they're only added once
$included_images = array();
if (preg_match_all('# src=[\'"]([^\'"]+)#', $body, $matches, PREG_OFFSET_CAPTURE)) {
foreach ($matches[1] as $m) {
// find emoticon image tags
if (preg_match('#'.$searchstr.'(.*)$#', $m[0], $imatches)) {
$image_name = $imatches[1];
// sanitize image name so resulting attachment doesn't leave images dir
$image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
$img_file = INSTALL_PATH . '/' . $searchstr . $image_name;
if (! in_array($image_name, $included_images)) {
// add the image to the MIME message
if (! $mime_message->addHTMLImage($img_file, 'image/gif', '', true, $image_name))
$OUTPUT->show_message("emoticonerror", 'error');
array_push($included_images, $image_name);
}
$body = substr_replace($body, $img_file, $m[1] + $offset, strlen($m[0]));
$offset += strlen($img_file) - strlen($m[0]);
}
}
}
$mime_message->setHTMLBody($body);
return $body;
}
/**
* Parse and cleanup email address input (and count addresses)
*
* @param string Address input
* @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
* @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
* @return string Canonical recipients string separated by comma
*/
function rcmail_email_input_format($mailto, $count=false, $check=true)
{
global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
// simplified email regexp, supporting quoted local part
$email_regexp = '(\S+|("[^"]+"))@\S+';
$delim = trim($RCMAIL->config->get('recipients_separator', ','));
$regexp = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
$replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
// replace new lines and strip ending ', ', make address input more valid
$mailto = trim(preg_replace($regexp, $replace, $mailto));
$result = array();
$items = rcube_explode_quoted_string($delim, $mailto);
foreach($items as $item) {
$item = trim($item);
// address in brackets without name (do nothing)
if (preg_match('/^<'.$email_regexp.'>$/', $item)) {
$item = rcube_idn_to_ascii(trim($item, '<>'));
$result[] = '<' . $item . '>';
// address without brackets and without name (add brackets)
} else if (preg_match('/^'.$email_regexp.'$/', $item)) {
$item = rcube_idn_to_ascii($item);
$result[] = '<' . $item . '>';
// address with name (handle name)
} else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
$address = $matches[0];
$name = trim(str_replace($address, '', $item), '" ');
$address = rcube_idn_to_ascii(trim($address, '<>'));
$result[] = format_email_recipient($address, $name);
$item = $address;
} else if (trim($item)) {
continue;
}
// check address format
$item = trim($item, '<>');
if ($item && $check && !check_email($item)) {
$EMAIL_FORMAT_ERROR = $item;
return;
}
}
if ($count) {
$RECIPIENT_COUNT += count($result);
}
return implode(', ', $result);
}
/****** compose message ********/
if (strlen($_POST['_draft_saveid']) > 3)
$olddraftmessageid = get_input_value('_draft_saveid', RCUBE_INPUT_POST);
$message_id = rcmail_gen_message_id();
// set default charset
$input_charset = $OUTPUT->get_charset();
$message_charset = isset($_POST['_charset']) ? $_POST['_charset'] : $input_charset;
$EMAIL_FORMAT_ERROR = NULL;
$RECIPIENT_COUNT = 0;
$mailto = rcmail_email_input_format(get_input_value('_to', RCUBE_INPUT_POST, TRUE, $message_charset), true);
$mailcc = rcmail_email_input_format(get_input_value('_cc', RCUBE_INPUT_POST, TRUE, $message_charset), true);
$mailbcc = rcmail_email_input_format(get_input_value('_bcc', RCUBE_INPUT_POST, TRUE, $message_charset), true);
if ($EMAIL_FORMAT_ERROR) {
$OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR));
$OUTPUT->send('iframe');
}
if (empty($mailto) && !empty($mailcc)) {
$mailto = $mailcc;
$mailcc = null;
}
else if (empty($mailto))
$mailto = 'undisclosed-recipients:;';
// Get sender name and address...
$from = get_input_value('_from', RCUBE_INPUT_POST, true, $message_charset);
// ... from identity...
if (is_numeric($from)) {
if (is_array($identity_arr = rcmail_get_identity($from))) {
if ($identity_arr['mailto'])
$from = $identity_arr['mailto'];
if ($identity_arr['string'])
$from_string = $identity_arr['string'];
}
else {
$from = null;
}
}
// ... if there is no identity record, this might be a custom from
else if ($from_string = rcmail_email_input_format($from)) {
if (preg_match('/(\S+@\S+)/', $from_string, $m))
$from = trim($m[1], '<>');
else
$from = null;
}
if (!$from_string && $from)
$from_string = $from;
// compose headers array
$headers = array();
// if configured, the Received headers goes to top, for good measure
if ($CONFIG['http_received_header'])
{
$nldlm = "\r\n\t";
// FROM/VIA
$http_header = 'from ';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$host = $_SERVER['HTTP_X_FORWARDED_FOR'];
$hostname = gethostbyaddr($host);
if ($CONFIG['http_received_header_encrypt']) {
$http_header .= rcmail_encrypt_header($hostname);
if ($host != $hostname)
$http_header .= ' ('. rcmail_encrypt_header($host) . ')';
} else {
$http_header .= (($host != $hostname) ? $hostname : '[' . $host . ']');
if ($host != $hostname)
$http_header .= ' (['. $host .'])';
}
$http_header .= $nldlm . ' via ';
}
$host = $_SERVER['REMOTE_ADDR'];
$hostname = gethostbyaddr($host);
if ($CONFIG['http_received_header_encrypt']) {
$http_header .= rcmail_encrypt_header($hostname);
if ($host != $hostname)
$http_header .= ' ('. rcmail_encrypt_header($host) . ')';
} else {
$http_header .= (($host != $hostname) ? $hostname : '[' . $host . ']');
if ($host != $hostname)
$http_header .= ' (['. $host .'])';
}
// BY
$http_header .= $nldlm . 'by ' . $_SERVER['HTTP_HOST'];
// WITH
$http_header .= $nldlm . 'with HTTP (' . $_SERVER['SERVER_PROTOCOL'] .
' '.$_SERVER['REQUEST_METHOD'] . '); ' . date('r');
$http_header = wordwrap($http_header, 69, $nldlm);
$headers['Received'] = $http_header;
}
$headers['Date'] = rcmail_user_date();
$headers['From'] = rcube_charset_convert($from_string, RCMAIL_CHARSET, $message_charset);
$headers['To'] = $mailto;
// additional recipients
if (!empty($mailcc)) {
$headers['Cc'] = $mailcc;
}
if (!empty($mailbcc)) {
$headers['Bcc'] = $mailbcc;
}
if (!empty($identity_arr['bcc'])) {
$headers['Bcc'] = ($headers['Bcc'] ? $headers['Bcc'].', ' : '') . $identity_arr['bcc'];
$RECIPIENT_COUNT ++;
}
if (($max_recipients = (int) $RCMAIL->config->get('max_recipients')) > 0) {
if ($RECIPIENT_COUNT > $max_recipients) {
$OUTPUT->show_message('toomanyrecipients', 'error', array('max' => $max_recipients));
$OUTPUT->send('iframe');
}
}
// add subject
$headers['Subject'] = trim(get_input_value('_subject', RCUBE_INPUT_POST, TRUE, $message_charset));
if (!empty($identity_arr['organization'])) {
$headers['Organization'] = $identity_arr['organization'];
}
if (!empty($_POST['_replyto'])) {
$headers['Reply-To'] = rcmail_email_input_format(get_input_value('_replyto', RCUBE_INPUT_POST, TRUE, $message_charset));
}
else if (!empty($identity_arr['reply-to'])) {
$headers['Reply-To'] = rcmail_email_input_format($identity_arr['reply-to'], false, true);
}
if (!empty($headers['Reply-To'])) {
$headers['Mail-Reply-To'] = $headers['Reply-To'];
}
if (!empty($_POST['_followupto'])) {
$headers['Mail-Followup-To'] = rcmail_email_input_format(get_input_value('_followupto', RCUBE_INPUT_POST, TRUE, $message_charset));
}
if (!empty($COMPOSE['reply_msgid'])) {
$headers['In-Reply-To'] = $COMPOSE['reply_msgid'];
}
// remember reply/forward UIDs in special headers
if (!empty($COMPOSE['reply_uid']) && $savedraft) {
$headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $COMPOSE['reply_uid']);
}
else if (!empty($COMPOSE['forward_uid']) && $savedraft) {
$headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $COMPOSE['forward_uid']);
}
if (!empty($COMPOSE['references'])) {
$headers['References'] = $COMPOSE['references'];
}
if (!empty($_POST['_priority'])) {
$priority = intval($_POST['_priority']);
$a_priorities = array(1=>'highest', 2=>'high', 4=>'low', 5=>'lowest');
if ($str_priority = $a_priorities[$priority]) {
$headers['X-Priority'] = sprintf("%d (%s)", $priority, ucfirst($str_priority));
}
}
if (!empty($_POST['_receipt'])) {
$headers['Return-Receipt-To'] = $from_string;
$headers['Disposition-Notification-To'] = $from_string;
}
// additional headers
$headers['Message-ID'] = $message_id;
$headers['X-Sender'] = $from;
if (is_array($headers['X-Draft-Info'])) {
$headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $COMPOSE['mailbox']));
}
if (!empty($CONFIG['useragent'])) {
$headers['User-Agent'] = $CONFIG['useragent'];
}
// exec hook for header checking and manipulation
$data = $RCMAIL->plugins->exec_hook('message_outgoing_headers', array('headers' => $headers));
// sending aborted by plugin
if ($data['abort'] && !$savedraft) {
$OUTPUT->show_message($data['message'] ? $data['message'] : 'sendingfailed');
$OUTPUT->send('iframe');
}
else
$headers = $data['headers'];
$isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
// fetch message body
$message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_charset);
if ($isHtml) {
$font = rcube_fontdefs($RCMAIL->config->get('default_font', 'Verdana'));
$bstyle = $font && is_string($font) ? " style='font-family: $font'" : '';
// append doctype and html/body wrappers
$message_body = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">' .
"\r\n<html><body$bstyle>\r\n" . $message_body;
}
if (!$savedraft) {
if ($isHtml) {
// remove signature's div ID
$message_body = preg_replace('/\s*id="_rc_sig"/', '', $message_body);
// add inline css for blockquotes
$bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px; width:100%';
$message_body = preg_replace('/<blockquote>/',
'<blockquote type="cite" style="'.$bstyle.'">', $message_body);
}
// Check spelling before send
if ($CONFIG['spellcheck_before_send'] && $CONFIG['enable_spellcheck']
&& empty($COMPOSE['spell_checked']) && !empty($message_body)
) {
$spellchecker = new rcube_spellchecker(get_input_value('_lang', RCUBE_INPUT_GPC));
$spell_result = $spellchecker->check($message_body, $isHtml);
$COMPOSE['spell_checked'] = true;
if (!$spell_result) {
$result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
$OUTPUT->show_message('mispellingsfound', 'error');
$OUTPUT->command('spellcheck_resume', $isHtml, $result);
$OUTPUT->send('iframe');
}
}
// generic footer for all messages
if ($isHtml && !empty($CONFIG['generic_message_footer_html'])) {
$footer = file_get_contents(realpath($CONFIG['generic_message_footer_html']));
$footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset);
}
else if (!empty($CONFIG['generic_message_footer'])) {
$footer = file_get_contents(realpath($CONFIG['generic_message_footer']));
$footer = rcube_charset_convert($footer, RCMAIL_CHARSET, $message_charset);
if ($isHtml)
$footer = '<pre>'.$footer.'</pre>';
}
if ($footer)
$message_body .= "\r\n" . $footer;
}
if ($isHtml) {
$message_body .= "\r\n</body></html>\r\n";
}
// set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 72);
// Since we can handle big messages with disk usage, we need more time to work
@set_time_limit(0);
// create PEAR::Mail_mime instance
$MAIL_MIME = new Mail_mime("\r\n");
// Check if we have enough memory to handle the message in it
// It's faster than using files, so we'll do this if we only can
if (is_array($COMPOSE['attachments']) && $CONFIG['smtp_server']
&& ($mem_limit = parse_bytes(ini_get('memory_limit'))))
{
$memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
foreach ($COMPOSE['attachments'] as $id => $attachment)
$memory += $attachment['size'];
// Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
if ($memory * 1.33 * 12 > $mem_limit)
$MAIL_MIME->setParam('delay_file_io', true);
}
// For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part
if ($isHtml) {
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $message_body, 'type' => 'html', 'message' => $MAIL_MIME));
$MAIL_MIME->setHTMLBody($plugin['body']);
// replace emoticons
$plugin['body'] = rcmail_replace_emoticons($plugin['body']);
// add a plain text version of the e-mail as an alternative part.
$h2t = new html2text($plugin['body'], false, true, 0);
$plainTextPart = rc_wordwrap($h2t->get_text(), $LINE_LENGTH, "\r\n");
$plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true);
if (!$plainTextPart) {
// empty message body breaks attachment handling in drafts
$plainTextPart = "\r\n";
}
else {
// make sure all line endings are CRLF (#1486712)
$plainTextPart = preg_replace('/\r?\n/', "\r\n", $plainTextPart);
}
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $plainTextPart, 'type' => 'alternative', 'message' => $MAIL_MIME));
$MAIL_MIME->setTXTBody($plugin['body']);
// look for "emoticon" images from TinyMCE and change their src paths to
// be file paths on the server instead of URL paths.
$message_body = rcmail_fix_emoticon_paths($MAIL_MIME);
}
else {
$plugin = $RCMAIL->plugins->exec_hook('message_outgoing_body',
array('body' => $message_body, 'type' => 'plain', 'message' => $MAIL_MIME));
$message_body = $plugin['body'];
// compose format=flowed content if enabled
if ($flowed = $RCMAIL->config->get('send_format_flowed', true))
$message_body = rcube_message::format_flowed($message_body, min($LINE_LENGTH+2, 79));
else
$message_body = rc_wordwrap($message_body, $LINE_LENGTH, "\r\n");
$message_body = wordwrap($message_body, 998, "\r\n", true);
if (!strlen($message_body)) {
// empty message body breaks attachment handling in drafts
$message_body = "\r\n";
}
$MAIL_MIME->setTXTBody($message_body, false, true);
}
// add stored attachments, if any
if (is_array($COMPOSE['attachments']))
{
foreach ($COMPOSE['attachments'] as $id => $attachment) {
// This hook retrieves the attachment contents from the file storage backend
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
$dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/';
$message_body = $MAIL_MIME->getHTMLBody();
if ($isHtml && (preg_match($dispurl, $message_body) > 0)) {
$message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body);
$MAIL_MIME->setHTMLBody($message_body);
if ($attachment['data'])
$MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false);
else
$MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true);
}
else {
$ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914
$file = $attachment['data'] ? $attachment['data'] : $attachment['path'];
// .eml attachments send inline
$MAIL_MIME->addAttachment($file,
$ctype,
$attachment['name'],
($attachment['data'] ? false : true),
($ctype == 'message/rfc822' ? '8bit' : 'base64'),
($ctype == 'message/rfc822' ? 'inline' : 'attachment'),
'', '', '',
$CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,
$CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL,
'', RCMAIL_CHARSET
);
}
}
}
// choose transfer encoding for plain/text body
if (preg_match('/[^\x00-\x7F]/', $MAIL_MIME->getTXTBody()))
$transfer_encoding = $RCMAIL->config->get('force_7bit') ? 'quoted-printable' : '8bit';
else
$transfer_encoding = '7bit';
// encoding settings for mail composing
$MAIL_MIME->setParam('text_encoding', $transfer_encoding);
$MAIL_MIME->setParam('html_encoding', 'quoted-printable');
$MAIL_MIME->setParam('head_encoding', 'quoted-printable');
$MAIL_MIME->setParam('head_charset', $message_charset);
$MAIL_MIME->setParam('html_charset', $message_charset);
$MAIL_MIME->setParam('text_charset', $message_charset . ($flowed ? ";\r\n format=flowed" : ''));
// encoding subject header with mb_encode provides better results with asian characters
if (function_exists('mb_encode_mimeheader')) {
mb_internal_encoding($message_charset);
$headers['Subject'] = mb_encode_mimeheader($headers['Subject'],
$message_charset, 'Q', "\r\n", 8);
mb_internal_encoding(RCMAIL_CHARSET);
}
// pass headers to message object
$MAIL_MIME->headers($headers);
// Begin SMTP Delivery Block
if (!$savedraft)
{
// check 'From' address (identity may be incomplete)
if (empty($from)) {
$OUTPUT->show_message('nofromaddress', 'error');
$OUTPUT->send('iframe');
}
// Handle Delivery Status Notification request
if (!empty($_POST['_dsn'])) {
$smtp_opts['dsn'] = true;
}
$sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto,
$smtp_error, $mailbody_file, $smtp_opts);
// return to compose page if sending failed
if (!$sent)
{
// remove temp file
if ($mailbody_file) {
unlink($mailbody_file);
}
if ($smtp_error)
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
else
$OUTPUT->show_message('sendingfailed', 'error');
$OUTPUT->send('iframe');
}
// save message sent time
if (!empty($CONFIG['sendmail_delay']))
$RCMAIL->user->save_prefs(array('last_message_time' => time()));
// set replied/forwarded flag
if ($COMPOSE['reply_uid'])
- $IMAP->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']);
+ $RCMAIL->imap->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']);
else if ($COMPOSE['forward_uid'])
- $IMAP->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']);
+ $RCMAIL->imap->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']);
} // End of SMTP Delivery Block
// Determine which folder to save message
if ($savedraft)
$store_target = $CONFIG['drafts_mbox'];
else
$store_target = isset($_POST['_store_target']) ? get_input_value('_store_target', RCUBE_INPUT_POST) : $CONFIG['sent_mbox'];
if ($store_target) {
// check if folder is subscribed
- if ($IMAP->mailbox_exists($store_target, true))
+ if ($RCMAIL->imap->mailbox_exists($store_target, true))
$store_folder = true;
// folder may be existing but not subscribed (#1485241)
- else if (!$IMAP->mailbox_exists($store_target))
- $store_folder = $IMAP->create_mailbox($store_target, true);
- else if ($IMAP->subscribe($store_target))
+ else if (!$RCMAIL->imap->mailbox_exists($store_target))
+ $store_folder = $RCMAIL->imap->create_mailbox($store_target, true);
+ else if ($RCMAIL->imap->subscribe($store_target))
$store_folder = true;
// append message to sent box
if ($store_folder) {
// message body in file
if ($mailbody_file || $MAIL_MIME->getParam('delay_file_io')) {
$headers = $MAIL_MIME->txtHeaders();
// file already created
if ($mailbody_file)
$msg = $mailbody_file;
else {
$temp_dir = $RCMAIL->config->get('temp_dir');
$mailbody_file = tempnam($temp_dir, 'rcmMsg');
if (!PEAR::isError($msg = $MAIL_MIME->saveMessageBody($mailbody_file)))
$msg = $mailbody_file;
}
}
else {
$msg = $MAIL_MIME->getMessage();
$headers = '';
}
if (PEAR::isError($msg))
raise_error(array('code' => 650, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not create message: ".$msg->getMessage()),
TRUE, FALSE);
else {
- $saved = $IMAP->save_message($store_target, $msg, $headers, $mailbody_file ? true : false);
+ $saved = $RCMAIL->imap->save_message($store_target, $msg, $headers, $mailbody_file ? true : false);
}
if ($mailbody_file) {
unlink($mailbody_file);
$mailbody_file = null;
}
// raise error if saving failed
if (!$saved) {
raise_error(array('code' => 800, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not save message in $store_target"), TRUE, FALSE);
if ($savedraft) {
$OUTPUT->show_message('errorsaving', 'error');
$OUTPUT->send('iframe');
}
}
}
if ($olddraftmessageid) {
// delete previous saved draft
// @TODO: use message UID (remember to check UIDVALIDITY) to skip this SEARCH
- $delete_idx = $IMAP->search_once($CONFIG['drafts_mbox'],
+ $delete_idx = $RCMAIL->imap->search_once($CONFIG['drafts_mbox'],
'HEADER Message-ID '.$olddraftmessageid);
if ($del_uid = $delete_idx->getElement('FIRST')) {
- $deleted = $IMAP->delete_message($del_uid, $CONFIG['drafts_mbox']);
+ $deleted = $RCMAIL->imap->delete_message($del_uid, $CONFIG['drafts_mbox']);
// raise error if deletion of old draft failed
if (!$deleted)
raise_error(array('code' => 800, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Could not delete message from ".$CONFIG['drafts_mbox']), TRUE, FALSE);
}
}
}
// remove temp file
else if ($mailbody_file) {
unlink($mailbody_file);
}
if ($savedraft) {
$msgid = strtr($message_id, array('>' => '', '<' => ''));
// remember new draft-uid ($saved could be an UID or TRUE here)
if (is_bool($saved)) {
- $draft_idx = $IMAP->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid);
+ $draft_idx = $RCMAIL->imap->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid);
$saved = $draft_idx->getElement('FIRST');
}
$COMPOSE['param']['draft_uid'] = $saved;
// display success
$OUTPUT->show_message('messagesaved', 'confirmation');
// update "_draft_saveid" and the "cmp_hash" to prevent "Unsaved changes" warning
$OUTPUT->command('set_draft_id', $msgid);
$OUTPUT->command('compose_field_hash', true);
// start the auto-save timer again
$OUTPUT->command('auto_save_start');
$OUTPUT->send('iframe');
}
else {
rcmail_compose_cleanup($COMPOSE_ID);
if ($store_folder && !$saved)
$OUTPUT->command('sent_successfully', 'error', rcube_label('errorsavingsent'));
else
$OUTPUT->command('sent_successfully', 'confirmation', rcube_label('messagesent'));
$OUTPUT->send('iframe');
}
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index d928cfd68..d7b9d4f9e 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -1,259 +1,259 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/show.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Display a mail message similar as a usual mail application does |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
$PRINT_MODE = $RCMAIL->action=='print' ? TRUE : FALSE;
// similar code as in program/steps/mail/get.inc
if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) {
$MESSAGE = new rcube_message($uid);
// if message not found (wrong UID)...
if (empty($MESSAGE->headers)) {
rcmail_message_error($uid);
}
- $mbox_name = $IMAP->get_mailbox_name();
+ $mbox_name = $RCMAIL->imap->get_mailbox_name();
// show images?
rcmail_check_safe($MESSAGE);
// set message charset as default
if (!empty($MESSAGE->headers->charset))
- $IMAP->set_charset($MESSAGE->headers->charset);
+ $RCMAIL->imap->set_charset($MESSAGE->headers->charset);
$OUTPUT->set_pagetitle(abbreviate_string($MESSAGE->subject, 128, '...', true));
// give message uid to the client
$OUTPUT->set_env('uid', $MESSAGE->uid);
// set environement
$OUTPUT->set_env('safemode', $MESSAGE->is_safe);
$OUTPUT->set_env('sender', $MESSAGE->sender['string']);
$OUTPUT->set_env('permaurl', rcmail_url('show', array('_uid' => $MESSAGE->uid, '_mbox' => $mbox_name)));
- $OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter());
+ $OUTPUT->set_env('delimiter', $RCMAIL->imap->get_hierarchy_delimiter());
$OUTPUT->set_env('mailbox', $mbox_name);
// mimetypes supported by the browser (default settings)
$mimetypes = $RCMAIL->config->get('client_mimetypes', 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/x-javascript,application/pdf,application/x-shockwave-flash');
$OUTPUT->set_env('mimetypes', is_string($mimetypes) ? explode(',', $mimetypes) : (array)$mimetypes);
if ($CONFIG['trash_mbox'])
$OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']);
if ($CONFIG['flag_for_deletion'])
$OUTPUT->set_env('flag_for_deletion', true);
if ($CONFIG['read_when_deleted'])
$OUTPUT->set_env('read_when_deleted', true);
if ($CONFIG['skip_deleted'])
$OUTPUT->set_env('skip_deleted', true);
if ($CONFIG['display_next'])
$OUTPUT->set_env('display_next', true);
if ($MESSAGE->headers->others['list-post'])
$OUTPUT->set_env('list_post', true);
if ($CONFIG['forward_attachment'])
$OUTPUT->set_env('forward_attachment', true);
if (!$OUTPUT->ajax_call)
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'deletingmessage');
// check for unset disposition notification
if ($MESSAGE->headers->mdn_to
&& empty($MESSAGE->headers->flags['MDNSENT'])
&& empty($MESSAGE->headers->flags['SEEN'])
- && ($IMAP->check_permflag('MDNSENT') || $IMAP->check_permflag('*'))
+ && ($RCMAIL->imap->check_permflag('MDNSENT') || $RCMAIL->imap->check_permflag('*'))
&& $mbox_name != $CONFIG['drafts_mbox']
&& $mbox_name != $CONFIG['sent_mbox']
) {
$mdn_cfg = intval($CONFIG['mdn_requests']);
if ($mdn_cfg == 1 || (($mdn_cfg == 3 || $mdn_cfg == 4) && rcmail_contact_exists($MESSAGE->sender['mailto']))) {
// Send MDN
if (rcmail_send_mdn($MESSAGE, $smtp_error))
$OUTPUT->show_message('receiptsent', 'confirmation');
else if ($smtp_error)
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
else
$OUTPUT->show_message('errorsendingreceipt', 'error');
}
else if ($mdn_cfg != 2 && $mdn_cfg != 4) {
// Ask user
$OUTPUT->add_label('mdnrequest');
$OUTPUT->set_env('mdn_request', true);
}
}
if (empty($MESSAGE->headers->flags['SEEN'])
&& ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0))
) {
$RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid,
'mailbox' => $mbox_name, 'message' => $MESSAGE));
}
}
function rcmail_message_attachments($attrib)
{
global $PRINT_MODE, $MESSAGE;
$out = $ol = '';
if (sizeof($MESSAGE->attachments)) {
foreach ($MESSAGE->attachments as $attach_prop) {
if ($PRINT_MODE) {
$ol .= html::tag('li', null, sprintf("%s (%s)", Q($attach_prop->filename), Q(show_bytes($attach_prop->size))));
}
else {
if (mb_strlen($attach_prop->filename) > 50) {
$filename = abbreviate_string($attach_prop->filename, 50);
$title = $attach_prop->filename;
}
else {
$filename = $attach_prop->filename;
$title = '';
}
$ol .= html::tag('li', null,
html::a(array(
'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false),
'onclick' => sprintf(
'return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)',
JS_OBJECT_NAME,
$attach_prop->mime_id,
rcmail_fix_mimetype($attach_prop->mimetype)),
'title' => Q($title),
),
Q($filename)));
}
}
$out = html::tag('ul', $attrib, $ol, html::$common_attrib);
}
return $out;
}
function rcmail_remote_objects_msg()
{
global $MESSAGE, $RCMAIL;
$attrib['id'] = 'remote-objects-message';
$attrib['class'] = 'notice';
$attrib['style'] = 'display: none';
$msg = Q(rcube_label('blockedimages')) . '&nbsp;';
$msg .= html::a(array('href' => "#loadimages", 'onclick' => JS_OBJECT_NAME.".command('load-images')"), Q(rcube_label('showimages')));
// add link to save sender in addressbook and reload message
if ($MESSAGE->sender['mailto'] && $RCMAIL->config->get('show_images') == 1) {
$msg .= ' ' . html::a(array('href' => "#alwaysload", 'onclick' => JS_OBJECT_NAME.".command('always-load')", 'style' => "white-space:nowrap"),
Q(rcube_label(array('name' => 'alwaysshow', 'vars' => array('sender' => $MESSAGE->sender['mailto'])))));
}
$RCMAIL->output->add_gui_object('remoteobjectsmsg', $attrib['id']);
return html::div($attrib, $msg);
}
function rcmail_message_buttons()
{
global $MESSAGE, $RCMAIL, $CONFIG;
$mbox = $RCMAIL->imap->get_mailbox_name();
$delim = $RCMAIL->imap->get_hierarchy_delimiter();
$dbox = $CONFIG['drafts_mbox'];
// the message is not a draft
if ($mbox != $dbox && strpos($mbox, $dbox.$delim) !== 0) {
return '';
}
$attrib['id'] = 'message-buttons';
$attrib['class'] = 'notice';
$msg = Q(rcube_label('isdraft')) . '&nbsp;';
$msg .= html::a(array('href' => "#edit", 'onclick' => JS_OBJECT_NAME.".command('edit')"), Q(rcube_label('edit')));
return html::div($attrib, $msg);
}
function rcmail_message_objects($attrib)
{
global $RCMAIL, $MESSAGE;
if (!$attrib['id'])
$attrib['id'] = 'message-objects';
$content = array(
rcmail_message_buttons(),
rcmail_remote_objects_msg(),
);
$plugin = $RCMAIL->plugins->exec_hook('message_objects',
array('content' => $content, 'message' => $MESSAGE));
$content = implode("\n", $plugin['content']);
return html::div($attrib, $content);
}
function rcmail_contact_exists($email)
{
global $RCMAIL;
if ($email) {
// @TODO: search in all address books?
$CONTACTS = $RCMAIL->get_address_book(null, true);
$existing = $CONTACTS->search('email', $email, true, false);
if ($existing->count)
return true;
}
return false;
}
$OUTPUT->add_handlers(array(
'messageattachments' => 'rcmail_message_attachments',
'mailboxname' => 'rcmail_mailbox_name_display',
'messageobjects' => 'rcmail_message_objects',
));
if ($RCMAIL->action=='print' && $OUTPUT->template_exists('messageprint'))
$OUTPUT->send('messageprint', false);
else if ($RCMAIL->action=='preview' && $OUTPUT->template_exists('messagepreview'))
$OUTPUT->send('messagepreview', false);
else
$OUTPUT->send('message', false);
// mark message as read
if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($CONFIG['preview_pane_mark_read']) == 0)))
{
- if ($IMAP->set_flag($MESSAGE->uid, 'SEEN')) {
+ if ($RCMAIL->imap->set_flag($MESSAGE->uid, 'SEEN')) {
if ($count = rcmail_get_unseen_count($mbox_name)) {
rcmail_set_unseen_count($mbox_name, $count - 1);
}
}
}
exit;
diff --git a/program/steps/mail/viewsource.inc b/program/steps/mail/viewsource.inc
index e25fad132..d951fbead 100644
--- a/program/steps/mail/viewsource.inc
+++ b/program/steps/mail/viewsource.inc
@@ -1,59 +1,59 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/mail/viewsource.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Display a mail message similar as a usual mail application does |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
ob_end_clean();
// similar code as in program/steps/mail/get.inc
if ($uid = get_input_value('_uid', RCUBE_INPUT_GET))
{
- $headers = $IMAP->get_headers($uid);
+ $headers = $RCMAIL->imap->get_headers($uid);
$charset = $headers->charset ? $headers->charset : $CONFIG['default_charset'];
header("Content-Type: text/plain; charset={$charset}");
if (!empty($_GET['_save'])) {
- $filename = ($headers->subject ? $IMAP->decode_header($headers->subject) : 'roundcube') . '.eml';
+ $filename = ($headers->subject ? $RCMAIL->imap->decode_header($headers->subject) : 'roundcube') . '.eml';
$browser = $RCMAIL->output->browser;
if ($browser->ie && $browser->ver < 7)
$filename = rawurlencode(abbreviate_string($filename, 55));
else if ($browser->ie)
$filename = rawurlencode($filename);
else
$filename = addcslashes($filename, '"');
header("Content-Length: {$headers->size}");
header("Content-Disposition: attachment; filename=\"$filename\"");
}
- $IMAP->print_raw_body($uid);
+ $RCMAIL->imap->print_raw_body($uid);
}
else
{
raise_error(array(
'code' => 500,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => 'Message UID '.$uid.' not found'),
true, true);
}
exit;
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 77cbb5571..31f31a32a 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -1,420 +1,420 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/settings/folders.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide functionality of folders management |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
$Id$
*/
// WARNING: folder names in UI are encoded with RCMAIL_CHARSET
// init IMAP connection
$RCMAIL->imap_connect();
// subscribe mailbox
if ($RCMAIL->action == 'subscribe')
{
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP');
if (strlen($mbox)) {
- $result = $IMAP->subscribe(array($mbox));
+ $result = $RCMAIL->imap->subscribe(array($mbox));
// Handle virtual (non-existing) folders
- if (!$result && $IMAP->get_error_code() == -1 &&
- $IMAP->get_response_code() == rcube_imap::TRYCREATE
+ if (!$result && $RCMAIL->imap->get_error_code() == -1 &&
+ $RCMAIL->imap->get_response_code() == rcube_imap::TRYCREATE
) {
- $result = $IMAP->create_mailbox($mbox, true);
+ $result = $RCMAIL->imap->create_mailbox($mbox, true);
if ($result) {
// @TODO: remove 'virtual' class of folder's row
}
}
if ($result) {
// Handle subscription of protected folder (#1487656)
if ($CONFIG['protect_default_folders'] == true
&& in_array($mbox, $CONFIG['default_imap_folders'])
) {
$OUTPUT->command('disable_subscription', $mbox);
}
$OUTPUT->show_message('foldersubscribed', 'confirmation');
}
else
rcmail_display_server_error('errorsaving');
}
}
// unsubscribe mailbox
else if ($RCMAIL->action == 'unsubscribe')
{
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true, 'UTF7-IMAP');
if (strlen($mbox)) {
- $result = $IMAP->unsubscribe(array($mbox));
+ $result = $RCMAIL->imap->unsubscribe(array($mbox));
if ($result)
$OUTPUT->show_message('folderunsubscribed', 'confirmation');
else
rcmail_display_server_error('errorsaving');
}
}
// delete an existing mailbox
else if ($RCMAIL->action == 'delete-folder')
{
$mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true);
$mbox = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP');
if (strlen($mbox)) {
$plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox));
if (!$plugin['abort']) {
- $deleted = $IMAP->delete_mailbox($plugin['name']);
+ $deleted = $RCMAIL->imap->delete_mailbox($plugin['name']);
}
else {
$deleted = $plugin['result'];
}
}
if ($OUTPUT->ajax_call && $deleted) {
// Remove folder and subfolders rows
$OUTPUT->command('remove_folder_row', $mbox_utf8, true);
$OUTPUT->show_message('folderdeleted', 'confirmation');
// Clear content frame
$OUTPUT->command('subscription_select');
$OUTPUT->command('set_quota', rcmail_quota_content());
}
else if (!$deleted) {
rcmail_display_server_error('errorsaving');
}
}
// rename an existing mailbox
else if ($RCMAIL->action == 'rename-folder')
{
$name_utf8 = trim(get_input_value('_folder_newname', RCUBE_INPUT_POST, true));
$oldname_utf8 = trim(get_input_value('_folder_oldname', RCUBE_INPUT_POST, true));
if (strlen($name_utf8) && strlen($oldname_utf8)) {
$name = rcube_charset_convert($name_utf8, RCMAIL_CHARSET, 'UTF7-IMAP');
$oldname = rcube_charset_convert($oldname_utf8, RCMAIL_CHARSET, 'UTF7-IMAP');
$rename = rcmail_rename_folder($oldname, $name);
}
if ($rename && $OUTPUT->ajax_call) {
rcmail_update_folder_row($name, $oldname);
}
else if (!$rename) {
rcmail_display_server_error('errorsaving');
}
}
// clear mailbox
else if ($RCMAIL->action == 'purge')
{
$mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true);
$mbox = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP');
- $delimiter = $IMAP->get_hierarchy_delimiter();
+ $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
$trash_regexp = '/^' . preg_quote($CONFIG['trash_mbox'] . $delimiter, '/') . '/';
// we should only be purging trash (or their subfolders)
if (!strlen($CONFIG['trash_mbox']) || $mbox == $CONFIG['trash_mbox']
|| preg_match($trash_regexp, $mbox)
) {
- $success = $IMAP->clear_mailbox($mbox);
+ $success = $RCMAIL->imap->clear_mailbox($mbox);
$delete = true;
}
// copy to Trash
else {
- $success = $IMAP->move_message('1:*', $CONFIG['trash_mbox'], $mbox);
+ $success = $RCMAIL->imap->move_message('1:*', $CONFIG['trash_mbox'], $mbox);
$delete = false;
}
if ($success) {
$OUTPUT->set_env('messagecount', 0);
if ($delete) {
$OUTPUT->show_message('folderpurged', 'confirmation');
$OUTPUT->command('set_quota', rcmail_quota_content());
}
else {
$OUTPUT->show_message('messagemoved', 'confirmation');
}
$_SESSION['unseen_count'][$mbox] = 0;
$OUTPUT->command('show_folder', $mbox_utf8, null, true);
}
else {
rcmail_display_server_error('errorsaving');
}
}
// get mailbox size
else if ($RCMAIL->action == 'folder-size')
{
$name = trim(get_input_value('_mbox', RCUBE_INPUT_POST, true));
- $size = $IMAP->get_mailbox_size($name);
+ $size = $RCMAIL->imap->get_mailbox_size($name);
// @TODO: check quota and show percentage usage of specified mailbox?
if ($size !== false) {
$OUTPUT->command('folder_size_update', show_bytes($size));
}
else {
rcmail_display_server_error();
}
}
if ($OUTPUT->ajax_call)
$OUTPUT->send();
// build table with all folders listed by server
function rcube_subscription_form($attrib)
{
- global $RCMAIL, $IMAP, $CONFIG, $OUTPUT;
+ global $RCMAIL, $CONFIG, $OUTPUT;
list($form_start, $form_end) = get_form_tags($attrib, 'folders');
unset($attrib['form']);
if (!$attrib['id'])
$attrib['id'] = 'rcmSubscriptionlist';
$table = new html_table();
if ($attrib['noheader'] !== true && $attrib['noheader'] != "true") {
// add table header
$table->add_header('name', rcube_label('foldername'));
$table->add_header('subscribed', '');
}
// get folders from server
- $IMAP->clear_cache('mailboxes', true);
+ $RCMAIL->imap->clear_cache('mailboxes', true);
- $a_unsubscribed = $IMAP->list_unsubscribed();
- $a_subscribed = $IMAP->list_mailboxes('', '*', null, null, true); // unsorted
- $delimiter = $IMAP->get_hierarchy_delimiter();
- $namespace = $IMAP->get_namespace();
+ $a_unsubscribed = $RCMAIL->imap->list_unsubscribed();
+ $a_subscribed = $RCMAIL->imap->list_mailboxes('', '*', null, null, true); // unsorted
+ $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
+ $namespace = $RCMAIL->imap->get_namespace();
$a_js_folders = array();
$seen = array();
$list_folders = array();
// pre-process folders list
foreach ($a_unsubscribed as $i => $folder) {
$folder_id = $folder;
- $folder = $IMAP->mod_mailbox($folder);
+ $folder = $RCMAIL->imap->mod_mailbox($folder);
$foldersplit = explode($delimiter, $folder);
$name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP');
$parent_folder = join($delimiter, $foldersplit);
$level = count($foldersplit);
// add any necessary "virtual" parent folders
if ($parent_folder && !isset($seen[$parent_folder])) {
for ($i=1; $i<=$level; $i++) {
$ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
if ($ancestor_folder && !$seen[$ancestor_folder]++) {
$ancestor_name = rcube_charset_convert($foldersplit[$i-1], 'UTF7-IMAP');
$list_folders[] = array(
'id' => $ancestor_folder,
'name' => $ancestor_name,
'level' => $i-1,
'virtual' => true,
);
}
}
}
// Handle properly INBOX.INBOX situation
if (isset($seen[$folder])) {
continue;
}
$seen[$folder]++;
$list_folders[] = array(
'id' => $folder_id,
'name' => $name,
'level' => $level,
);
}
unset($seen);
// add drop-target representing 'root'
$table->add_row(array('id' => 'mailboxroot', 'class' => 'virtual root'));
$table->add('name', '&nbsp;');
$table->add(null, '&nbsp;');
$a_js_folders['mailboxroot'] = array('', '', true);
$checkbox_subscribe = new html_checkbox(array(
'name' => '_subscribed[]',
'title' => rcube_label('changesubscription'),
'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)",
));
// create list of available folders
foreach ($list_folders as $i => $folder) {
$idx = $i + 1;
$sub_key = array_search($folder['id'], $a_subscribed);
$subscribed = $sub_key !== false;
$protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders']));
$noselect = false;
$classes = array($i%2 ? 'even' : 'odd');
$folder_js = Q($folder['id']);
$folder_utf8 = rcube_charset_convert($folder['id'], 'UTF7-IMAP');
$display_folder = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $folder['level'])
. Q($protected ? rcmail_localize_foldername($folder['id']) : $folder['name']);
if ($folder['virtual']) {
$classes[] = 'virtual';
}
if (!$protected) {
- $attrs = $IMAP->mailbox_attributes($folder['id']);
+ $attrs = $RCMAIL->imap->mailbox_attributes($folder['id']);
$noselect = in_array('\\Noselect', $attrs);
}
$disabled = (($protected && $subscribed) || $noselect);
// check if the folder is a namespace prefix, then disable subscription option on it
if (!$disabled && $folder['virtual'] && $folder['level'] == 0 && !empty($namespace)) {
$fname = $folder['id'] . $delimiter;
foreach ($namespace as $ns) {
foreach ($ns as $item) {
if ($item[0] === $fname) {
$disabled = true;
break 2;
}
}
}
}
// check if the folder is an other users virtual-root folder, then disable subscription option on it
if (!$disabled && $folder['virtual'] && $folder['level'] == 1
&& !empty($namespace) && !empty($namespace['other'])
) {
$parts = explode($delimiter, $folder['id']);
$fname = $parts[0] . $delimiter;
foreach ($namespace['other'] as $item) {
if ($item[0] === $fname) {
$disabled = true;
break;
}
}
}
// check if the folder is shared, then disable subscription option on it
if (!$disabled && $folder['virtual'] && !empty($namespace)) {
$tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']);
foreach ($tmp_ns as $item) {
if (strpos($folder['id'], $item[0]) === 0) {
$disabled = true;
break;
}
}
}
$table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes),
'foldername' => $folder['id']));
$table->add('name', $display_folder);
$table->add('subscribed', $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''),
array('value' => $folder_utf8, 'disabled' => $disabled ? 'disabled' : '')));
$a_js_folders['rcmrow'.$idx] = array($folder_utf8,
Q($display_folder), $protected || $folder['virtual']);
}
$RCMAIL->plugins->exec_hook('folders_list', array('table' => $table));
$OUTPUT->add_gui_object('subscriptionlist', $attrib['id']);
$OUTPUT->set_env('subscriptionrows', $a_js_folders);
$OUTPUT->set_env('defaultfolders', $CONFIG['default_imap_folders']);
$OUTPUT->set_env('delimiter', $delimiter);
return $form_start . $table->show($attrib) . $form_end;
}
function rcmail_folder_frame($attrib)
{
global $OUTPUT;
if (!$attrib['id'])
$attrib['id'] = 'rcmfolderframe';
$attrib['name'] = $attrib['id'];
$OUTPUT->set_env('contentframe', $attrib['name']);
$OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
return html::iframe($attrib);
}
function rcmail_rename_folder($oldname, $newname)
{
global $RCMAIL;
$delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
$plugin = $RCMAIL->plugins->exec_hook('folder_rename', array(
'oldname' => $oldname, 'newname' => $newname));
if (!$plugin['abort']) {
$renamed = $RCMAIL->imap->rename_mailbox($oldname, $newname);
}
else {
$renamed = $plugin['result'];
}
// update per-folder options for modified folder and its subfolders
if ($renamed) {
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
$oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/';
foreach ($a_threaded as $key => $val) {
if ($key == $oldname) {
unset($a_threaded[$key]);
$a_threaded[$newname] = true;
}
else if (preg_match($oldprefix, $key)) {
unset($a_threaded[$key]);
$a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = true;
}
}
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
return true;
}
return false;
}
$OUTPUT->set_pagetitle(rcube_label('folders'));
$OUTPUT->include_script('list.js');
-$OUTPUT->set_env('quota', $IMAP->get_capability('QUOTA'));
+$OUTPUT->set_env('quota', $RCMAIL->imap->get_capability('QUOTA'));
// add some labels to client
$OUTPUT->add_label('deletefolderconfirm', 'purgefolderconfirm', 'folderdeleting',
'foldermoving', 'foldersubscribing', 'folderunsubscribing', 'quota');
// register UI objects
$OUTPUT->add_handlers(array(
'foldersubscription' => 'rcube_subscription_form',
'folderframe' => 'rcmail_folder_frame',
'quotadisplay' => 'rcmail_quota_display',
));
$OUTPUT->send('folders');
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index b778afa13..65836a958 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -1,915 +1,915 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/settings/func.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2007, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide functionality for user's settings & preferences |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
if (!$OUTPUT->ajax_call)
$OUTPUT->set_pagetitle(rcube_label('preferences'));
// similar function as /steps/settings/identities.inc::rcmail_identity_frame()
function rcmail_preferences_frame($attrib)
{
global $OUTPUT;
if (!$attrib['id'])
$attrib['id'] = 'rcmprefsframe';
$attrib['name'] = $attrib['id'];
$OUTPUT->set_env('contentframe', $attrib['name']);
$OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
return html::iframe($attrib);
}
function rcmail_sections_list($attrib)
{
global $RCMAIL;
// add id to message list table if not specified
if (!strlen($attrib['id']))
$attrib['id'] = 'rcmsectionslist';
list($list, $cols) = rcmail_user_prefs();
// create XHTML table
$out = rcube_table_output($attrib, $list, $cols, 'id');
// set client env
$RCMAIL->output->add_gui_object('sectionslist', $attrib['id']);
$RCMAIL->output->include_script('list.js');
return $out;
}
function rcmail_identities_list($attrib)
{
global $OUTPUT, $USER, $RCMAIL;
// add id to message list table if not specified
if (!strlen($attrib['id']))
$attrib['id'] = 'rcmIdentitiesList';
// get identities list and define 'mail' column
$list = $USER->list_identities();
foreach ($list as $idx => $row)
$list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>');
// get all identites from DB and define list of cols to be displayed
$plugin = $RCMAIL->plugins->exec_hook('identities_list', array(
'list' => $list,
'cols' => array('mail')));
// @TODO: use <UL> instead of <TABLE> for identities list
// create XHTML table
$out = rcube_table_output($attrib, $plugin['list'], $plugin['cols'], 'identity_id');
// set client env
$OUTPUT->add_gui_object('identitieslist', $attrib['id']);
return $out;
}
// similar function as in /steps/addressbook/edit.inc
function get_form_tags($attrib, $action, $id = null, $hidden = null)
{
global $EDIT_FORM, $RCMAIL;
$form_start = $form_end = '';
if (empty($EDIT_FORM)) {
$request_key = $action . (isset($id) ? '.'.$id : '');
$form_start = $RCMAIL->output->request_form(array(
'name' => 'form',
'method' => 'post',
'task' => $RCMAIL->task,
'action' => $action,
'request' => $request_key,
'noclose' => true
) + $attrib);
if (is_array($hidden)) {
$hiddenfields = new html_hiddenfield($hidden);
$form_start .= $hiddenfields->show();
}
$form_end = !strlen($attrib['form']) ? '</form>' : '';
$EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form';
$RCMAIL->output->add_gui_object('editform', $EDIT_FORM);
}
return array($form_start, $form_end);
}
function rcmail_user_prefs($current=null)
{
global $RCMAIL;
$sections['general'] = array('id' => 'general', 'section' => rcube_label('uisettings'));
$sections['mailbox'] = array('id' => 'mailbox', 'section' => rcube_label('mailboxview'));
$sections['compose'] = array('id' => 'compose', 'section' => rcube_label('messagescomposition'));
$sections['mailview'] = array('id' => 'mailview','section' => rcube_label('messagesdisplaying'));
$sections['addressbook'] = array('id' => 'addressbook','section' => rcube_label('addressbook'));
$sections['folders'] = array('id' => 'folders', 'section' => rcube_label('specialfolders'));
$sections['server'] = array('id' => 'server', 'section' => rcube_label('serversettings'));
// hook + define list cols
$plugin = $RCMAIL->plugins->exec_hook('preferences_sections_list',
array('list' => $sections, 'cols' => array('section')));
$sections = $plugin['list'];
$config = $RCMAIL->config->all();
$no_override = array_flip($RCMAIL->config->get('dont_override', array()));
foreach ($sections as $idx => $sect) {
if ($current && $sect['id'] != $current)
continue;
$blocks = array();
switch ($sect['id']) {
// general
case 'general':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'list' => array('name' => Q(rcube_label('listoptions'))),
);
// language selection
if (!isset($no_override['language'])) {
$a_lang = $RCMAIL->list_languages();
asort($a_lang);
$field_id = 'rcmfd_lang';
$select_lang = new html_select(array('name' => '_language', 'id' => $field_id));
$select_lang->add(array_values($a_lang), array_keys($a_lang));
$blocks['main']['options']['language'] = array(
'title' => html::label($field_id, Q(rcube_label('language'))),
'content' => $select_lang->show($RCMAIL->user->language),
);
}
// show page size selection
if (!isset($no_override['timezone'])) {
$field_id = 'rcmfd_timezone';
$select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id, 'onchange' => "$('#rcmfd_dst').attr('disabled', this.selectedIndex==0)"));
$select_timezone->add(rcube_label('autodetect'), 'auto');
$select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
$select_timezone->add('(GMT -10:00) Hawaii', '-10');
$select_timezone->add('(GMT -9:30) Marquesas Islands', '-9.5');
$select_timezone->add('(GMT -9:00) Alaska', '-9');
$select_timezone->add('(GMT -8:00) Pacific Time (US/Canada)', '-8');
$select_timezone->add('(GMT -7:00) Mountain Time (US/Canada)', '-7');
$select_timezone->add('(GMT -6:00) Central Time (US/Canada), Mexico City', '-6');
$select_timezone->add('(GMT -5:00) Eastern Time (US/Canada), Bogota, Lima', '-5');
$select_timezone->add('(GMT -4:30) Caracas', '-4.5');
$select_timezone->add('(GMT -4:00) Atlantic Time (Canada), La Paz', '-4');
$select_timezone->add('(GMT -3:30) Nfld Time (Canada), Nfld, S. Labador', '-3.5');
$select_timezone->add('(GMT -3:00) Brazil, Buenos Aires, Georgetown', '-3');
$select_timezone->add('(GMT -2:00) Mid-Atlantic', '-2');
$select_timezone->add('(GMT -1:00) Azores, Cape Verde Islands', '-1');
$select_timezone->add('(GMT) Western Europe, London, Lisbon, Casablanca', '0');
$select_timezone->add('(GMT +1:00) Central European Time', '1');
$select_timezone->add('(GMT +2:00) EET: Tallinn, Helsinki, Kaliningrad, South Africa', '2');
$select_timezone->add('(GMT +3:00) Baghdad, Kuwait, Riyadh, Moscow, Nairobi', '3');
$select_timezone->add('(GMT +3:30) Tehran', '3.5');
$select_timezone->add('(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi', '4');
$select_timezone->add('(GMT +4:30) Kabul', '4.5');
$select_timezone->add('(GMT +5:00) Ekaterinburg, Islamabad, Karachi', '5');
$select_timezone->add('(GMT +5:30) Chennai, Kolkata, Mumbai, New Delhi', '5.5');
$select_timezone->add('(GMT +5:45) Kathmandu', '5.75');
$select_timezone->add('(GMT +6:00) Almaty, Dhaka, Colombo', '6');
$select_timezone->add('(GMT +6:30) Cocos Islands, Myanmar', '6.5');
$select_timezone->add('(GMT +7:00) Bangkok, Hanoi, Jakarta', '7');
$select_timezone->add('(GMT +8:00) Beijing, Perth, Singapore, Taipei', '8');
$select_timezone->add('(GMT +8:45) Caiguna, Eucla, Border Village', '8.75');
$select_timezone->add('(GMT +9:00) Tokyo, Seoul, Yakutsk', '9');
$select_timezone->add('(GMT +9:30) Adelaide, Darwin', '9.5');
$select_timezone->add('(GMT +10:00) EAST/AEST: Sydney, Guam, Vladivostok', '10');
$select_timezone->add('(GMT +10:30) New South Wales', '10.5');
$select_timezone->add('(GMT +11:00) Magadan, Solomon Islands', '11');
$select_timezone->add('(GMT +11:30) Norfolk Island', '11.5');
$select_timezone->add('(GMT +12:00) Auckland, Wellington, Kamchatka', '12');
$select_timezone->add('(GMT +12:45) Chatham Islands', '12.75');
$select_timezone->add('(GMT +13:00) Tonga, Pheonix Islands', '13');
$select_timezone->add('(GMT +14:00) Kiribati', '14');
$blocks['main']['options']['timezone'] = array(
'title' => html::label($field_id, Q(rcube_label('timezone'))),
'content' => $select_timezone->show((string)$config['timezone']),
);
}
// daylight savings
if (!isset($no_override['dst_active'])) {
$field_id = 'rcmfd_dst';
$input_dst = new html_checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1, 'disabled' => ($config['timezone'] === 'auto')));
$blocks['main']['options']['dstactive'] = array(
'title' => html::label($field_id, Q(rcube_label('dstactive'))),
'content' => $input_dst->show($config['dst_active']),
);
}
// date/time formatting
if (!isset($no_override['time_format'])) {
$reftime = mktime(7,30,0);
$field_id = 'rcmfd_time_format';
$select_time = new html_select(array('name' => '_time_format', 'id' => $field_id));
foreach ((array)$RCMAIL->config->get('time_formats', array('G:i', 'H:i', 'g:i a', 'h:i A')) as $choice)
$select_time->add(date($choice, $reftime), $choice);
$blocks['main']['options']['time_format'] = array(
'title' => html::label($field_id, Q(rcube_label('timeformat'))),
'content' => $select_time->show($RCMAIL->config->get('time_format')),
);
}
if (!isset($no_override['date_format'])) {
$refdate = mktime(12,30,0,7,24);
$field_id = 'rcmfd_date_format';
$select_date = new html_select(array('name' => '_date_format', 'id' => $field_id));
foreach ((array)$RCMAIL->config->get('date_formats', array('Y-m-d','d-m-Y','Y/m/d','m/d/Y','d/m/Y','d.m.Y','j.n.Y')) as $choice)
$select_date->add(date($choice, $refdate), $choice);
$blocks['main']['options']['date_format'] = array(
'title' => html::label($field_id, Q(rcube_label('dateformat'))),
'content' => $select_date->show($config['date_format']),
);
}
// MM: Show checkbox for toggling 'pretty dates'
if (!isset($no_override['prettydate'])) {
$field_id = 'rcmfd_prettydate';
$input_prettydate = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['prettydate'] = array(
'title' => html::label($field_id, Q(rcube_label('prettydate'))),
'content' => $input_prettydate->show($config['prettydate']?1:0),
);
}
// show page size selection
if (!isset($no_override['pagesize'])) {
$field_id = 'rcmfd_pgsize';
$input_pagesize = new html_inputfield(array('name' => '_pagesize', 'id' => $field_id, 'size' => 5));
$blocks['list']['options']['pagesize'] = array(
'title' => html::label($field_id, Q(rcube_label('pagesize'))),
'content' => $input_pagesize->show($config['pagesize']),
);
}
// show drop-down for available skins
if (!isset($no_override['skin'])) {
$skins = rcmail_get_skins();
if (count($skins) > 1) {
$field_id = 'rcmfd_skin';
$input_skin = new html_select(array('name'=>'_skin', 'id'=>$field_id));
foreach($skins as $skin)
$input_skin->add($skin, $skin);
$blocks['main']['options']['skin'] = array(
'title' => html::label($field_id, Q(rcube_label('skin'))),
'content' => $input_skin->show($config['skin']),
);
}
}
break;
// Mailbox view (mail screen)
case 'mailbox':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'new_message' => array('name' => Q(rcube_label('newmessage'))),
);
// show config parameter for preview pane
if (!isset($no_override['preview_pane'])) {
$field_id = 'rcmfd_preview';
$input_preview = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1,
'onchange' => JS_OBJECT_NAME.'.toggle_preview_pane(this)'));
$blocks['main']['options']['preview_pane'] = array(
'title' => html::label($field_id, Q(rcube_label('previewpane'))),
'content' => $input_preview->show($config['preview_pane']?1:0),
);
}
// show config parameter for preview pane auto mark as read delay
if (!isset($no_override['preview_pane_mark_read'])) {
// apply default if config option is not set at all
$config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0);
$field_id = 'rcmfd_preview_pane_mark_read';
$select_delay = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id,
'disabled' => $config['preview_pane']?0:1));
$select_delay->add(rcube_label('never'), '-1');
$select_delay->add(rcube_label('immediately'), 0);
foreach(array(5, 10, 20, 30) as $sec)
$select_delay->add(rcube_label(array('name' => 'afternseconds', 'vars' => array('n' => $sec))), $sec);
$blocks['main']['options']['preview_pane_mark_read'] = array(
'title' => html::label($field_id, Q(rcube_label('previewpanemarkread'))),
'content' => $select_delay->show(intval($config['preview_pane_mark_read'])),
);
}
if (!isset($no_override['mdn_requests'])) {
$field_id = 'rcmfd_mdn_requests';
$select_mdn_requests = new html_select(array('name' => '_mdn_requests', 'id' => $field_id));
$select_mdn_requests->add(rcube_label('askuser'), 0);
$select_mdn_requests->add(rcube_label('autosend'), 1);
$select_mdn_requests->add(rcube_label('autosendknown'), 3);
$select_mdn_requests->add(rcube_label('autosendknownignore'), 4);
$select_mdn_requests->add(rcube_label('ignore'), 2);
$blocks['main']['options']['mdn_requests'] = array(
'title' => html::label($field_id, Q(rcube_label('mdnrequests'))),
'content' => $select_mdn_requests->show($config['mdn_requests']),
);
}
$RCMAIL->imap_connect();
$threading_supported = $RCMAIL->imap->get_capability('THREAD');
if (!isset($no_override['autoexpand_threads']) && $threading_supported) {
$field_id = 'rcmfd_autoexpand_threads';
$select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id));
$select_autoexpand_threads->add(rcube_label('never'), 0);
$select_autoexpand_threads->add(rcube_label('do_expand'), 1);
$select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2);
$blocks['main']['options']['autoexpand_threads'] = array(
'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))),
'content' => $select_autoexpand_threads->show($config['autoexpand_threads']),
);
}
if (!isset($no_override['keep_alive'])) {
$field_id = 'rcmfd_keep_alive';
$select_keep_alive = new html_select(array('name' => '_keep_alive', 'id' => $field_id));
foreach(array(1, 3, 5, 10, 15, 30, 60) as $min)
if((!$config['min_keep_alive'] || $config['min_keep_alive'] <= $min * 60)
&& (!$config['session_lifetime'] || $config['session_lifetime'] > $min)) {
$select_keep_alive->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min);
}
$blocks['new_message']['options']['keep_alive'] = array(
'title' => html::label($field_id, Q(rcube_label('keepalive'))),
'content' => $select_keep_alive->show($config['keep_alive']/60),
);
}
if (!isset($no_override['check_all_folders'])) {
$field_id = 'rcmfd_check_all_folders';
$input_check_all = new html_checkbox(array('name' => '_check_all_folders', 'id' => $field_id, 'value' => 1));
$blocks['new_message']['options']['check_all_folders'] = array(
'title' => html::label($field_id, Q(rcube_label('checkallfolders'))),
'content' => $input_check_all->show($config['check_all_folders']?1:0),
);
}
break;
// Message viewing
case 'mailview':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
);
// show checkbox for HTML/plaintext messages
if (!isset($no_override['prefer_html'])) {
$field_id = 'rcmfd_htmlmsg';
$input_preferhtml = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1,
'onchange' => JS_OBJECT_NAME.'.toggle_prefer_html(this)'));
$blocks['main']['options']['prefer_html'] = array(
'title' => html::label($field_id, Q(rcube_label('preferhtml'))),
'content' => $input_preferhtml->show($config['prefer_html']?1:0),
);
}
if (!isset($no_override['default_charset'])) {
$field_id = 'rcmfd_default_charset';
$blocks['main']['options']['default_charset'] = array(
'title' => html::label($field_id, Q(rcube_label('defaultcharset'))),
'content' => $RCMAIL->output->charset_selector(array(
'name' => '_default_charset', 'selected' => $config['default_charset']
))
);
}
if (!isset($no_override['show_images'])) {
$field_id = 'rcmfd_show_images';
$input_show_images = new html_select(array('name' => '_show_images', 'id' => $field_id,
'disabled' => !$config['prefer_html']));
$input_show_images->add(rcube_label('never'), 0);
$input_show_images->add(rcube_label('fromknownsenders'), 1);
$input_show_images->add(rcube_label('always'), 2);
$blocks['main']['options']['show_images'] = array(
'title' => html::label($field_id, Q(rcube_label('showremoteimages'))),
'content' => $input_show_images->show($config['prefer_html'] ? $config['show_images'] : 0),
);
}
if (!isset($no_override['inline_images'])) {
$field_id = 'rcmfd_inline_images';
$input_inline_images = new html_checkbox(array('name' => '_inline_images', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['inline_images'] = array(
'title' => html::label($field_id, Q(rcube_label('showinlineimages'))),
'content' => $input_inline_images->show($config['inline_images']?1:0),
);
}
// "display after delete" checkbox
if (!isset($no_override['display_next'])) {
$field_id = 'rcmfd_displaynext';
$input_displaynext = new html_checkbox(array('name' => '_display_next', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['display_next'] = array(
'title' => html::label($field_id, Q(rcube_label('displaynext'))),
'content' => $input_displaynext->show($config['display_next']?1:0),
);
}
break;
// Mail composition
case 'compose':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'spellcheck' => array('name' => Q(rcube_label('spellcheckoptions'))),
'sig' => array('name' => Q(rcube_label('signatureoptions'))),
);
if (!isset($no_override['htmleditor'])) {
$field_id = 'rcmfd_htmleditor';
$select_htmleditor = new html_select(array('name' => '_htmleditor', 'id' => $field_id));
$select_htmleditor->add(rcube_label('never'), 0);
$select_htmleditor->add(rcube_label('always'), 1);
$select_htmleditor->add(rcube_label('htmlonreply'), 2);
$blocks['main']['options']['htmleditor'] = array(
'title' => html::label($field_id, Q(rcube_label('htmleditor'))),
'content' => $select_htmleditor->show(intval($config['htmleditor'])),
);
}
if (!isset($no_override['draft_autosave'])) {
$field_id = 'rcmfd_autosave';
$select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => $field_id, 'disabled' => empty($config['drafts_mbox'])));
$select_autosave->add(rcube_label('never'), 0);
foreach (array(1, 3, 5, 10) as $i => $min)
$select_autosave->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min*60);
$blocks['main']['options']['draft_autosave'] = array(
'title' => html::label($field_id, Q(rcube_label('autosavedraft'))),
'content' => $select_autosave->show($config['draft_autosave']),
);
}
if (!isset($no_override['mime_param_folding'])) {
$field_id = 'rcmfd_param_folding';
$select_param_folding = new html_select(array('name' => '_mime_param_folding', 'id' => $field_id));
$select_param_folding->add(rcube_label('2231folding'), 0);
$select_param_folding->add(rcube_label('miscfolding'), 1);
$select_param_folding->add(rcube_label('2047folding'), 2);
$blocks['main']['options']['mime_param_folding'] = array(
'advanced' => true,
'title' => html::label($field_id, Q(rcube_label('mimeparamfolding'))),
'content' => $select_param_folding->show($config['mime_param_folding']),
);
}
if (!isset($no_override['force_7bit'])) {
$field_id = 'rcmfd_force_7bit';
$input_7bit = new html_checkbox(array('name' => '_force_7bit', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['force_7bit'] = array(
'title' => html::label($field_id, Q(rcube_label('force7bit'))),
'content' => $input_7bit->show($config['force_7bit']?1:0),
);
}
if (!isset($no_override['mdn_default'])) {
$field_id = 'rcmfd_mdn_default';
$input_mdn = new html_checkbox(array('name' => '_mdn_default', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['mdn_default'] = array(
'title' => html::label($field_id, Q(rcube_label('reqmdn'))),
'content' => $input_mdn->show($config['mdn_default']?1:0),
);
}
if (!isset($no_override['dsn_default'])) {
$field_id = 'rcmfd_dsn_default';
$input_dsn = new html_checkbox(array('name' => '_dsn_default', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['dsn_default'] = array(
'title' => html::label($field_id, Q(rcube_label('reqdsn'))),
'content' => $input_dsn->show($config['dsn_default']?1:0),
);
}
if (!isset($no_override['reply_same_folder'])) {
$field_id = 'rcmfd_reply_same_folder';
$input_reply_same_folder = new html_checkbox(array('name' => '_reply_same_folder', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['reply_same_folder'] = array(
'title' => html::label($field_id, Q(rcube_label('replysamefolder'))),
'content' => $input_reply_same_folder->show($config['reply_same_folder']?1:0),
);
}
if (!isset($no_override['top_posting'])) {
$field_id = 'rcmfd_top_posting';
$select_replymode = new html_select(array('name' => '_top_posting', 'id' => $field_id, 'onchange' => "\$('#rcmfd_sig_above').attr('disabled',this.selectedIndex==0)"));
$select_replymode->add(rcube_label('replybottomposting'), 0);
$select_replymode->add(rcube_label('replytopposting'), 1);
$blocks['main']['options']['top_posting'] = array(
'title' => html::label($field_id, Q(rcube_label('whenreplying'))),
'content' => $select_replymode->show($config['top_posting']?1:0),
);
}
if (!isset($no_override['spellcheck_before_send']) && $config['enable_spellcheck']) {
$field_id = 'rcmfd_spellcheck_before_send';
$input_spellcheck = new html_checkbox(array('name' => '_spellcheck_before_send', 'id' => $field_id, 'value' => 1));
$blocks['spellcheck']['options']['spellcheck_before_send'] = array(
'title' => html::label($field_id, Q(rcube_label('spellcheckbeforesend'))),
'content' => $input_spellcheck->show($config['spellcheck_before_send']?1:0),
);
}
if ($config['enable_spellcheck']) {
foreach (array('syms', 'nums', 'caps') as $key) {
$key = 'spellcheck_ignore_'.$key;
if (!isset($no_override[$key])) {
$input_spellcheck = new html_checkbox(array('name' => '_'.$key, 'id' => 'rcmfd_'.$key, 'value' => 1));
$blocks['spellcheck']['options'][$key] = array(
'title' => html::label($field_id, Q(rcube_label(str_replace('_', '', $key)))),
'content' => $input_spellcheck->show($config[$key]?1:0),
);
}
}
}
if (!isset($no_override['show_sig'])) {
$field_id = 'rcmfd_show_sig';
$select_show_sig = new html_select(array('name' => '_show_sig', 'id' => $field_id));
$select_show_sig->add(rcube_label('never'), 0);
$select_show_sig->add(rcube_label('always'), 1);
$select_show_sig->add(rcube_label('newmessageonly'), 2);
$select_show_sig->add(rcube_label('replyandforwardonly'), 3);
$blocks['sig']['options']['show_sig'] = array(
'title' => html::label($field_id, Q(rcube_label('autoaddsignature'))),
'content' => $select_show_sig->show($RCMAIL->config->get('show_sig', 1)),
);
}
if (!isset($no_override['sig_above'])) {
$field_id = 'rcmfd_sig_above';
$select_sigabove = new html_select(array('name' => '_sig_above', 'id' => $field_id, 'disabled' => !$config['top_posting']));
$select_sigabove->add(rcube_label('belowquote'), 0);
$select_sigabove->add(rcube_label('abovequote'), 1);
$blocks['sig']['options']['sig_above'] = array(
'title' => html::label($field_id, Q(rcube_label('replysignaturepos'))),
'content' => $select_sigabove->show($config['sig_above']?1:0),
);
}
if (!isset($no_override['strip_existing_sig'])) {
$field_id = 'rcmfd_strip_existing_sig';
$input_stripexistingsig = new html_checkbox(array('name' => '_strip_existing_sig', 'id' => $field_id, 'value' => 1));
$blocks['sig']['options']['strip_existing_sig'] = array(
'title' => html::label($field_id, Q(rcube_label('replyremovesignature'))),
'content' => $input_stripexistingsig->show($config['strip_existing_sig']?1:0),
);
}
if (!isset($no_override['default_font'])) {
$field_id = 'rcmfd_default_font';
$fonts = rcube_fontdefs();
$default_font = $config['default_font'] ? $config['default_font'] : 'Verdana';
$select = '<select name="_default_font" id="'.$field_id.'">';
foreach ($fonts as $fname => $font)
$select .= '<option value="'.$fname.'"'
. ($fname == $default_font ? ' selected="selected"' : '')
. ' style=\'font-family: ' . $font . '\'>'
. Q($fname) . '</option>';
$select .= '</select>';
$blocks['main']['options']['default_font'] = array(
'title' => html::label($field_id, Q(rcube_label('defaultfont'))),
'content' => $select
);
}
break;
// Addressbook config
case 'addressbook':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
);
if (!isset($no_override['default_addressbook'])
&& ($books = $RCMAIL->get_address_sources(true))
) {
$field_id = 'rcmfd_default_addressbook';
$select_abook = new html_select(array('name' => '_default_addressbook', 'id' => $field_id));
foreach ($books as $book) {
$select_abook->add($book['name'], $book['id']);
}
$blocks['main']['options']['default_addressbook'] = array(
'title' => html::label($field_id, Q(rcube_label('defaultaddressbook'))),
'content' => $select_abook->show($config['default_addressbook']),
);
}
if (!isset($no_override['autocomplete_single'])) {
$field_id = 'rcmfd_autocomplete_single';
$checkbox = new html_checkbox(array('name' => '_autocomplete_single', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['autocomplete_single'] = array(
'title' => html::label($field_id, Q(rcube_label('autocompletesingle'))),
'content' => $checkbox->show($config['autocomplete_single']?1:0),
);
}
break;
// Special IMAP folders
case 'folders':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
);
// Configure special folders
if (!isset($no_override['default_imap_folders'])) {
$RCMAIL->imap_connect();
// load folders list only when needed
if ($current) {
$select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
'maxlength' => 30, 'exceptions' => array('INBOX'), 'folder_filter' => 'mail', 'folder_rights' => 'w'));
}
else // dummy select
$select = new html_select();
if (!isset($no_override['drafts_mbox']))
$blocks['main']['options']['drafts_mbox'] = array(
'title' => Q(rcube_label('drafts')),
'content' => $select->show($config['drafts_mbox'], array('name' => "_drafts_mbox")),
);
if (!isset($no_override['sent_mbox']))
$blocks['main']['options']['sent_mbox'] = array(
'title' => Q(rcube_label('sent')),
'content' => $select->show($config['sent_mbox'], array('name' => "_sent_mbox")),
);
if (!isset($no_override['junk_mbox']))
$blocks['main']['options']['junk_mbox'] = array(
'title' => Q(rcube_label('junk')),
'content' => $select->show($config['junk_mbox'], array('name' => "_junk_mbox")),
);
if (!isset($no_override['trash_mbox']))
$blocks['main']['options']['trash_mbox'] = array(
'title' => Q(rcube_label('trash')),
'content' => $select->show($config['trash_mbox'], array('name' => "_trash_mbox")),
);
}
break;
// Server settings
case 'server':
$blocks = array(
'main' => array('name' => Q(rcube_label('mainoptions'))),
'maintenance' => array('name' => Q(rcube_label('maintenance'))),
);
if (!isset($no_override['read_when_deleted'])) {
$field_id = 'rcmfd_read_deleted';
$input_readdeleted = new html_checkbox(array('name' => '_read_when_deleted', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['read_when_deleted'] = array(
'title' => html::label($field_id, Q(rcube_label('readwhendeleted'))),
'content' => $input_readdeleted->show($config['read_when_deleted']?1:0),
);
}
if (!isset($no_override['flag_for_deletion'])) {
$field_id = 'rcmfd_flag_for_deletion';
$input_flagfordeletion = new html_checkbox(array('name' => '_flag_for_deletion', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['flag_for_deletion'] = array(
'title' => html::label($field_id, Q(rcube_label('flagfordeletion'))),
'content' => $input_flagfordeletion->show($config['flag_for_deletion']?1:0),
);
}
// don't show deleted messages
if (!isset($no_override['skip_deleted'])) {
$field_id = 'rcmfd_skip_deleted';
$input_purge = new html_checkbox(array('name' => '_skip_deleted', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['skip_deleted'] = array(
'title' => html::label($field_id, Q(rcube_label('skipdeleted'))),
'content' => $input_purge->show($config['skip_deleted']?1:0),
);
}
if (!isset($no_override['delete_always'])) {
$field_id = 'rcmfd_delete_always';
$input_delete_always = new html_checkbox(array('name' => '_delete_always', 'id' => $field_id, 'value' => 1));
$blocks['main']['options']['delete_always'] = array(
'title' => html::label($field_id, Q(rcube_label('deletealways'))),
'content' => $input_delete_always->show($config['delete_always']?1:0),
);
}
// Trash purging on logout
if (!isset($no_override['logout_purge'])) {
$field_id = 'rcmfd_logout_purge';
$input_purge = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
$blocks['maintenance']['options']['logout_purge'] = array(
'title' => html::label($field_id, Q(rcube_label('logoutclear'))),
'content' => $input_purge->show($config['logout_purge']?1:0),
);
}
// INBOX compacting on logout
if (!isset($no_override['logout_expunge'])) {
$field_id = 'rcmfd_logout_expunge';
$input_expunge = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
$blocks['maintenance']['options']['logout_expunge'] = array(
'title' => html::label($field_id, Q(rcube_label('logoutcompact'))),
'content' => $input_expunge->show($config['logout_expunge']?1:0),
);
}
break;
}
$data = $RCMAIL->plugins->exec_hook('preferences_list', array('section' => $sect['id'], 'blocks' => $blocks));
$found = false;
// create output
foreach ($data['blocks'] as $block) {
if (!empty($block['content']) || !empty($block['options'])) {
$found = true;
break;
}
}
if (!$found)
unset($sections[$idx]);
else
$sections[$idx]['blocks'] = $data['blocks'];
}
return array($sections, $plugin['cols']);
}
function rcmail_get_skins()
{
$path = 'skins';
$skins = array();
$dir = opendir($path);
if (!$dir)
return false;
while (($file = readdir($dir)) !== false)
{
$filename = $path.'/'.$file;
if (!preg_match('/^\./', $file) && is_dir($filename) && is_readable($filename))
$skins[] = $file;
}
closedir($dir);
return $skins;
}
function rcmail_folder_options($mailbox)
{
global $RCMAIL;
$options = $RCMAIL->imap->mailbox_info($mailbox);
$options['protected'] = $options['is_root'] || ($options['special'] && $RCMAIL->config->get('protect_default_folders'));
return $options;
}
/**
* Updates (or creates) folder row in the subscriptions table
*
* @param string $name Folder name
* @param string $oldname Old folder name (for update)
* @param bool $subscribe Checks subscription checkbox
* @param string $class CSS class name for folder row
*/
function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class_name=null)
{
- global $IMAP, $CONFIG, $OUTPUT;
+ global $RCMAIL, $CONFIG, $OUTPUT;
- $delimiter = $IMAP->get_hierarchy_delimiter();
+ $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
$name_utf8 = rcube_charset_convert($name, 'UTF7-IMAP');
$protected = ($CONFIG['protect_default_folders'] == true && in_array($name, $CONFIG['default_imap_folders']));
- $foldersplit = explode($delimiter, $IMAP->mod_mailbox($name));
+ $foldersplit = explode($delimiter, $RCMAIL->imap->mod_mailbox($name));
$level = count($foldersplit) - 1;
$display_name = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level)
. Q($protected ? rcmail_localize_foldername($name) : rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP'));
if ($oldname === null)
$OUTPUT->command('add_folder_row', $name_utf8, $display_name, $protected, $subscribe,
false, $class_name);
else
$OUTPUT->command('replace_folder_row', rcube_charset_convert($oldname, 'UTF7-IMAP'),
$name_utf8, $display_name, $protected, $class_name);
}
// register UI objects
$OUTPUT->add_handlers(array(
'prefsframe' => 'rcmail_preferences_frame',
'sectionslist' => 'rcmail_sections_list',
'identitieslist' => 'rcmail_identities_list',
));
// register action aliases
$RCMAIL->register_action_map(array(
'folders' => 'folders.inc',
'rename-folder' => 'folders.inc',
'delete-folder' => 'folders.inc',
'subscribe' => 'folders.inc',
'unsubscribe' => 'folders.inc',
'purge' => 'folders.inc',
'folder-size' => 'folders.inc',
'add-identity' => 'edit_identity.inc',
));
diff --git a/program/steps/settings/save_folder.inc b/program/steps/settings/save_folder.inc
index 48c957239..0fc090e12 100644
--- a/program/steps/settings/save_folder.inc
+++ b/program/steps/settings/save_folder.inc
@@ -1,194 +1,194 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/steps/settings/save_folder.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide functionality to create/edit a folder |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
$Id$
*/
// WARNING: folder names in UI are encoded with RCMAIL_CHARSET
// init IMAP connection
$RCMAIL->imap_connect();
$name = trim(get_input_value('_name', RCUBE_INPUT_POST, true));
$old = trim(get_input_value('_mbox', RCUBE_INPUT_POST, true));
$path = trim(get_input_value('_parent', RCUBE_INPUT_POST, true));
$name_imap = rcube_charset_convert($name, RCMAIL_CHARSET, 'UTF7-IMAP');
$old_imap = rcube_charset_convert($old, RCMAIL_CHARSET, 'UTF7-IMAP');
// $path is in UTF7-IMAP already
-$delimiter = $IMAP->get_hierarchy_delimiter();
+$delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
$options = strlen($old_imap) ? rcmail_folder_options($old_imap) : array();
// Folder name checks
if ($options['protected'] || $options['norename']) {
}
else if (!strlen($name)) {
$error = rcube_label('cannotbeempty');
}
else if (mb_strlen($name) > 128) {
$error = rcube_label('nametoolong');
}
else {
// these characters are problematic e.g. when used in LIST/LSUB
foreach (array($delimiter, '%', '*') as $char) {
if (strpos($name, $delimiter) !== false) {
$error = rcube_label('forbiddencharacter') . " ($char)";
break;
}
}
}
if ($error) {
$OUTPUT->command('display_message', $error, 'error');
}
else {
if ($options['protected'] || $options['norename']) {
$name_imap = $old_imap;
}
else if (strlen($path)) {
$name_imap = $path . $delimiter . $name_imap;
}
else {
$name_imap = $RCMAIL->imap->mod_mailbox($name_imap, 'in');
}
}
// Check access rights to the parent folder
if (!$error && strlen($path) && (!strlen($old_imap) || $old_imap != $name_imap)) {
$parent_opts = $RCMAIL->imap->mailbox_info($path);
if ($parent_opts['namespace'] != 'personal'
&& (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts)))
) {
$error = rcube_label('parentnotwritable');
}
}
if (!$error) {
$folder['name'] = $name_imap;
$folder['oldname'] = $old_imap;
$folder['class'] = '';
$folder['options'] = $options;
$folder['settings'] = array(
// List view mode: 0-list, 1-threads
'view_mode' => (int) get_input_value('_viewmode', RCUBE_INPUT_POST),
'sort_column' => get_input_value('_sortcol', RCUBE_INPUT_POST),
'sort_order' => get_input_value('_sortord', RCUBE_INPUT_POST),
);
}
// create a new mailbox
if (!$error && !strlen($old)) {
$folder['subscribe'] = true;
$plugin = $RCMAIL->plugins->exec_hook('folder_create', array('record' => $folder));
$folder = $plugin['record'];
if (!$plugin['abort']) {
- $created = $IMAP->create_mailbox($folder['name'], $folder['subscribe']);
+ $created = $RCMAIL->imap->create_mailbox($folder['name'], $folder['subscribe']);
}
else {
$created = $plugin['result'];
}
if ($created) {
// Save folder settings
if (isset($_POST['_viewmode'])) {
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
if ($_POST['_viewmode'])
$a_threaded[$folder['name']] = true;
else
unset($a_threaded[$folder['name']]);
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
}
rcmail_update_folder_row($folder['name'], null, $folder['subscribe'], $folder['class']);
$OUTPUT->show_message('foldercreated', 'confirmation');
// reset folder preview frame
$OUTPUT->command('subscription_select');
$OUTPUT->send('iframe');
}
else {
// show error message
$OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error', null, false);
}
}
// update a mailbox
else if (!$error) {
$plugin = $RCMAIL->plugins->exec_hook('folder_update', array('record' => $folder));
$folder = $plugin['record'];
$rename = ($folder['oldname'] != $folder['name']);
if (!$plugin['abort']) {
if ($rename) {
$updated = $RCMAIL->imap->rename_mailbox($folder['oldname'], $folder['name']);
}
else {
$updated = true;
}
}
else {
$updated = $plugin['result'];
}
if ($updated) {
// Update folder settings,
if (isset($_POST['_viewmode'])) {
$a_threaded = (array) $RCMAIL->config->get('message_threading', array());
// In case of name change update names of childrens in settings
if ($rename) {
$oldprefix = '/^' . preg_quote($folder['oldname'] . $delimiter, '/') . '/';
foreach ($a_threaded as $key => $val) {
if ($key == $folder['oldname']) {
unset($a_threaded[$key]);
}
else if (preg_match($oldprefix, $key)) {
unset($a_threaded[$key]);
$a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = true;
}
}
}
if ($_POST['_viewmode'])
$a_threaded[$folder['name']] = true;
else
unset($a_threaded[$folder['name']]);
$RCMAIL->user->save_prefs(array('message_threading' => $a_threaded));
}
$OUTPUT->show_message('folderupdated', 'confirmation');
if ($rename) {
rcmail_update_folder_row($folder['name'], $folder['oldname'], $folder['subscribe'], $folder['class']);
$OUTPUT->send('iframe');
}
}
else {
// show error message
$OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error', null, false);
}
}
rcmail_overwrite_action('edit-folder');

File Metadata

Mime Type
text/x-diff
Expires
Fri, Aug 21, 3:10 AM (6 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1273243
Default Alt Text
(317 KB)

Event Timeline