- Applied fixes from trunk up to r5150

release-0.6
alecpl 13 years ago
parent fd6146b678
commit b08caf5813

@ -1,6 +1,10 @@
CHANGELOG Roundcube Webmail
===========================
- Fix imap_cache setting to values other than 'db' (#1488060)
- Fix handling of attachments inside message/rfc822 parts (#1488026)
- Make list of mimetypes that open in preview window configurable (#1487625)
- Added plugin hook 'message_part_get' for attachment downloads
- Fixed selecting identity on reply/forward (#1487981)
- Fix image type check for contact photo uploads

@ -326,6 +326,11 @@ $rcmail_config['dont_override'] = array();
// 3 - one identity with possibility to edit all params but not email address
$rcmail_config['identities_level'] = 0;
// Mimetypes supported by the browser.
// attachments of these types will open in a preview window
// either a comma-separated list or an array: 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/pdf'
$rcmail_config['client_mimetypes'] = null; # null == default
// mime magic database
$rcmail_config['mime_magic'] = '/usr/share/misc/magic';

@ -1,7 +1,7 @@
/**
* ACL plugin script
*
* @version 0.6
* @version 0.6.1
* @author Aleksander Machniak <alec@alec.pl>
*/
@ -11,7 +11,7 @@ if (window.rcmail) {
rcmail.acl_list_init();
// enable autocomplete on user input
if (rcmail.env.acl_users_source) {
rcmail.init_address_input_events($('#acluser'), {action:'plugin.acl-autocomplete'});
rcmail.init_address_input_events($('#acluser'), {action:'settings/plugin.acl-autocomplete'});
// fix inserted value
rcmail.addEventListener('autocomplete_insert', function(e) {
if (e.field.id != 'acluser')
@ -52,7 +52,7 @@ rcube_webmail.prototype.acl_delete = function()
var users = this.acl_get_usernames();
if (users && users.length && confirm(this.get_label('acl.deleteconfirm'))) {
this.http_request('plugin.acl', '_act=delete&_user='+urlencode(users.join(','))
this.http_request('settings/plugin.acl', '_act=delete&_user='+urlencode(users.join(','))
+ '&_mbox='+urlencode(this.env.mailbox),
this.set_busy(true, 'acl.deleting'));
}
@ -82,7 +82,7 @@ rcube_webmail.prototype.acl_save = function()
return;
}
this.http_request('plugin.acl', '_act=save'
this.http_request('settings/plugin.acl', '_act=save'
+ '&_user='+urlencode(user)
+ '&_acl=' +rights
+ '&_mbox='+urlencode(this.env.mailbox)
@ -120,7 +120,7 @@ rcube_webmail.prototype.acl_mode_switch = function(elem)
{
this.env.acl_advanced = !this.env.acl_advanced;
this.enable_command('acl-delete', 'acl-edit', false);
this.http_request('plugin.acl', '_act=list'
this.http_request('settings/plugin.acl', '_act=list'
+ '&_mode='+(this.env.acl_advanced ? 'advanced' : 'simple')
+ '&_mbox='+urlencode(this.env.mailbox),
this.set_busy(true, 'loading'));

@ -3,7 +3,7 @@
/**
* Folders Access Control Lists Management (RFC4314, RFC2086)
*
* @version 0.6
* @version 0.6.1
* @author Aleksander Machniak <alec@alec.pl>
*
*
@ -25,7 +25,7 @@
class acl extends rcube_plugin
{
public $task = 'settings|addressbook';
public $task = 'settings|addressbook|calendar';
private $rc;
private $supported = null;
@ -44,6 +44,7 @@ class acl extends rcube_plugin
$this->add_hook('folder_form', array($this, 'folder_form'));
// kolab_addressbook plugin
$this->add_hook('addressbook_form', array($this, 'folder_form'));
$this->add_hook('calendar_form_kolab', array($this, 'folder_form'));
// Plugin actions
$this->register_action('plugin.acl', array($this, 'acl_actions'));
$this->register_action('plugin.acl-autocomplete', array($this, 'acl_autocomplete'));
@ -526,7 +527,7 @@ class acl extends rcube_plugin
$list = array();
$attrib = array(
'name' => 'rcmyrights',
'style' => 'padding: 0 15px;',
'style' => 'margin:0; padding:0 15px;',
);
foreach ($supported as $right) {

@ -81,7 +81,7 @@
#aclform
{
top: 100px;
top: 80px;
width: 480px;
padding: 10px;
}

@ -66,6 +66,20 @@ class new_user_dialog extends rcube_plugin
'disabled' => ($identities_level == 1 || $identities_level == 3)
)));
$table->add('title', $this->gettext('organization'));
$table->add(null, html::tag('input', array(
'type' => 'text',
'name' => '_organization',
'value' => $identity['organization']
)));
$table->add('title', $this->gettext('signature'));
$table->add(null, html::tag('textarea', array(
'name' => '_signature',
'rows' => '3',
),$identity['signature']
));
// add overlay input box to html page
$rcmail->output->add_footer(html::div(array('id' => 'newuseroverlay'),
html::tag('form', array(
@ -106,6 +120,8 @@ class new_user_dialog extends rcube_plugin
$save_data = array(
'name' => get_input_value('_name', RCUBE_INPUT_POST),
'email' => get_input_value('_email', RCUBE_INPUT_POST),
'organization' => get_input_value('_organization', RCUBE_INPUT_POST),
'signature' => get_input_value('_signature', RCUBE_INPUT_POST),
);
// don't let the user alter the e-mail address if disabled by config
@ -125,4 +141,4 @@ class new_user_dialog extends rcube_plugin
}
?>
?>

@ -48,7 +48,8 @@
white-space: nowrap;
}
#newuseroverlay table td input
#newuseroverlay table td input,
#newuseroverlay table td textarea
{
width: 20em;
}

@ -1021,7 +1021,7 @@ function rcube_strtotime($date)
*/
function format_date($date, $format=NULL)
{
global $CONFIG;
global $RCMAIL, $CONFIG;
$ts = NULL;
@ -1032,13 +1032,7 @@ function format_date($date, $format=NULL)
return '';
// get user's timezone
if ($CONFIG['timezone'] === 'auto')
$tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600;
else {
$tz = $CONFIG['timezone'];
if ($CONFIG['dst_active'])
$tz++;
}
$tz = $RCMAIL->config->get_timezone();
// convert time to user's timezone
$timestamp = $ts - date('Z', $ts) + ($tz * 3600);
@ -1659,12 +1653,13 @@ function rcmail_replace_emoticons($html)
* @param string $from Sender address string
* @param array $mailto Array of recipient address strings
* @param array $smtp_error SMTP error array (reference)
* @param string $body_file Location of file with saved message body (reference)
* @param string $body_file Location of file with saved message body (reference),
* used when delay_file_io is enabled
* @param array $smtp_opts SMTP options (e.g. DSN request)
*
* @return boolean Send status.
*/
function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file, $smtp_opts=null)
function rcmail_deliver_message(&$message, $from, $mailto, &$smtp_error, &$body_file=null, $smtp_opts=null)
{
global $CONFIG, $RCMAIL;
@ -1823,17 +1818,10 @@ function rcmail_gen_message_id()
// Returns RFC2822 formatted current date in user's timezone
function rcmail_user_date()
{
global $CONFIG;
global $RCMAIL, $CONFIG;
// get user's timezone
if ($CONFIG['timezone'] === 'auto') {
$tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600;
}
else {
$tz = $CONFIG['timezone'];
if ($CONFIG['dst_active'])
$tz++;
}
$tz = $RCMAIL->config->get_timezone();
$date = time() + $tz * 60 * 60;
$date = gmdate('r', $date);

@ -413,7 +413,10 @@ class rcmail
$id = '0';
// use existing instance
if (isset($this->address_books[$id]) && is_a($this->address_books[$id], 'rcube_addressbook') && (!$writeable || !$this->address_books[$id]->readonly)) {
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]) {
@ -1183,7 +1186,7 @@ class rcmail
$this->smtp->disconnect();
foreach ($this->address_books as $book) {
if (is_a($book, 'rcube_addressbook'))
if (is_object($book) && is_a($book, 'rcube_addressbook'))
$book->close();
}

@ -220,6 +220,19 @@ class rcube_config
return $this->prop;
}
/**
* Special getter for user's timezone
*/
public function get_timezone()
{
$tz = $this->get('timezone');
if ($tz == 'auto')
$tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z') / 3600;
else
$tz = intval($tz) + intval($this->get('dst_active'));
return $tz;
}
/**
* Return requested DES crypto key.

@ -212,7 +212,7 @@ class rcube_html_page
if (!empty($this->scripts['docready'])) {
$this->add_script('$(document).ready(function(){ ' . $this->scripts['docready'] . "\n});", 'foot');
}
if (is_array($this->script_files['foot'])) {
foreach ($this->script_files['foot'] as $file) {
$page_footer .= sprintf($this->script_tag_file, $file);
@ -246,7 +246,7 @@ class rcube_html_page
// add page hader
if ($hpos) {
$output = substr($output,0,$hpos) . $page_header . substr($output,$hpos,strlen($output));
$output = substr_replace($output, $page_header, $hpos, 0);
}
else {
$output = $page_header . $output;
@ -254,7 +254,7 @@ class rcube_html_page
// add page footer
if (($fpos = strripos($output, '</body>')) || ($fpos = strripos($output, '</html>'))) {
$output = substr($output, 0, $fpos) . "$page_footer\n" . substr($output, $fpos);
$output = substr_replace($output, $page_footer."\n", $fpos, 0);
}
else {
$output .= "\n".$page_footer;
@ -268,7 +268,7 @@ class rcube_html_page
foreach ($this->css_files as $file) {
$css .= sprintf($this->link_css_file, $file);
}
$output = substr($output, 0, $pos) . $css . substr($output, $pos);
$output = substr_replace($output, $css, $pos, 0);
}
$this->base_path = $base_path;
@ -289,7 +289,7 @@ class rcube_html_page
echo $hook['content'];
}
}
/**
* Callback function for preg_replace_callback in write()
*

@ -3074,6 +3074,9 @@ class rcube_imap
if (isset($data['folders'])) {
$a_folders = $data['folders'];
}
else if (!$this->conn->connected()) {
return array();
}
else {
// Server supports LIST-EXTENDED, we can use selection options
$config = rcmail::get_instance()->config;
@ -3834,13 +3837,13 @@ class rcube_imap
/**
* Enable or disable indexes caching
*
* @param boolean $type Cache type (@see rcmail::get_cache)
* @param string $type Cache type (@see rcmail::get_cache)
* @access public
*/
function set_caching($type)
{
if ($type) {
$this->caching = true;
$this->caching = $type;
}
else {
if ($this->cache)
@ -3857,7 +3860,7 @@ class rcube_imap
{
if ($this->caching && !$this->cache) {
$rcmail = rcmail::get_instance();
$this->cache = $rcmail->get_cache('IMAP', $type);
$this->cache = $rcmail->get_cache('IMAP', $this->caching);
}
return $this->cache;

@ -286,7 +286,7 @@ class rcube_message
if ($message_ctype_primary == 'text' && !$recursive) {
$structure->type = 'content';
$this->parts[] = &$structure;
// Parse simple (plain text) message body
if ($message_ctype_secondary == 'plain')
foreach ((array)$this->uu_decode($structure) as $uupart) {
@ -306,7 +306,7 @@ class rcube_message
foreach ($structure->parts as $p => $sub_part) {
$sub_mimetype = $sub_part->mimetype;
// check if sub part is
if ($sub_mimetype == 'text/plain')
$plain_part = $p;
@ -323,7 +323,7 @@ class rcube_message
$this->parse_alternative = true;
$this->parse_structure($structure->parts[$related_part], true);
$this->parse_alternative = false;
// if plain part was found, we should unset it if html is preferred
if ($this->opt['prefer_html'] && count($this->parts))
$plain_part = null;
@ -432,7 +432,7 @@ class rcube_message
$this->attachments[] = $mail_part;
}
// part message/*
else if ($primary_type=='message') {
else if ($primary_type == 'message') {
$this->parse_structure($mail_part, true);
// list as attachment as well (mostly .eml)
@ -496,6 +496,10 @@ class rcube_message
$this->attachments[] = $mail_part;
}
}
// attachment part as message/rfc822 (#1488026)
else if ($mail_part->mimetype == 'message/rfc822') {
$this->parse_structure($mail_part);
}
}
// if this was a related part try to resolve references

@ -176,7 +176,7 @@ class rcube_plugin_api
if (is_subclass_of($plugin, 'rcube_plugin')) {
// ... task, request type and framed mode
if ((!$plugin->task || preg_match('/^('.$plugin->task.')$/i', $rcmail->task))
&& (!$plugin->noajax || is_a($rcmail->output, 'rcube_template'))
&& (!$plugin->noajax || (is_object($rcmail->output) && is_a($rcmail->output, 'rcube_template')))
&& (!$plugin->noframe || empty($_REQUEST['_framed']))
) {
$plugin->init();

@ -40,11 +40,6 @@ function rcube_webmail()
this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
// mimetypes supported by the browser (default settings)
this.mimetypes = new Array('text/plain', 'text/html', 'text/xml',
'image/jpeg', 'image/gif', 'image/png',
'application/x-javascript', 'application/pdf', 'application/x-shockwave-flash');
// default environment vars
this.env.keep_alive = 60; // seconds
this.env.request_timeout = 180; // seconds
@ -90,12 +85,15 @@ function rcube_webmail()
if (over) button_prop.over = over;
this.buttons[command].push(button_prop);
if (this.loaded)
init_button(command, button_prop);
};
// register a specific gui object
this.gui_object = function(name, id)
{
this.gui_objects[name] = id;
this.gui_objects[name] = this.loaded ? rcube_find_object(id) : id;
};
// register a container object
@ -748,7 +746,7 @@ function rcube_webmail()
var qstring = '_mbox='+urlencode(this.env.mailbox)+'&_uid='+this.env.uid+'&_part='+props.part;
// open attachment in frame if it's of a supported mimetype
if (this.env.uid && props.mimetype && $.inArray(props.mimetype, this.mimetypes)>=0) {
if (this.env.uid && props.mimetype && this.env.mimetypes && $.inArray(props.mimetype, this.env.mimetypes)>=0) {
if (props.mimetype == 'text/html')
qstring += '&_safe=1';
this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
@ -3505,7 +3503,7 @@ function rcube_webmail()
case 27: // escape
this.ksearch_hide();
break;
return;
case 37: // left
case 39: // right
@ -4914,6 +4912,34 @@ function rcube_webmail()
/********* GUI functionality *********/
/*********************************************************/
var init_button = function(cmd, prop)
{
var elm = document.getElementById(prop.id);
if (!elm)
return;
var preload = false;
if (prop.type == 'image') {
elm = elm.parentNode;
preload = true;
}
elm._command = cmd;
elm._id = prop.id;
if (prop.sel) {
elm.onmousedown = function(e){ return rcmail.button_sel(this._command, this._id); };
elm.onmouseup = function(e){ return rcmail.button_out(this._command, this._id); };
if (preload)
new Image().src = prop.sel;
}
if (prop.over) {
elm.onmouseover = function(e){ return rcmail.button_over(this._command, this._id); };
elm.onmouseout = function(e){ return rcmail.button_out(this._command, this._id); };
if (preload)
new Image().src = prop.over;
}
};
// enable/disable buttons for page shifting
this.set_page_buttons = function()
{
@ -4929,31 +4955,7 @@ function rcube_webmail()
continue;
for (var i=0; i< this.buttons[cmd].length; i++) {
var prop = this.buttons[cmd][i];
var elm = document.getElementById(prop.id);
if (!elm)
continue;
var preload = false;
if (prop.type == 'image') {
elm = elm.parentNode;
preload = true;
}
elm._command = cmd;
elm._id = prop.id;
if (prop.sel) {
elm.onmousedown = function(e){ return rcmail.button_sel(this._command, this._id); };
elm.onmouseup = function(e){ return rcmail.button_out(this._command, this._id); };
if (preload)
new Image().src = prop.sel;
}
if (prop.over) {
elm.onmouseover = function(e){ return rcmail.button_over(this._command, this._id); };
elm.onmouseout = function(e){ return rcmail.button_out(this._command, this._id); };
if (preload)
new Image().src = prop.over;
}
init_button(cmd, this.buttons[cmd][i]);
}
}
};
@ -5566,7 +5568,7 @@ function rcube_webmail()
var base = this.env.comm_path;
// overwrite task name
if (query._action.match(/([a-z]+)\/([a-z-_]+)/)) {
if (query._action.match(/([a-z]+)\/([a-z-_.]+)/)) {
query._action = RegExp.$2;
base = base.replace(/\_task=[a-z]+/, '_task='+RegExp.$1);
}

@ -1448,7 +1448,7 @@ function rcmail_send_mdn($message, &$smtp_error)
{
global $RCMAIL, $IMAP;
if (!is_a($message, rcube_message))
if (!is_object($message) || !is_a($message, rcube_message))
$message = new rcube_message($message);
if ($message->headers->mdn_to && !$message->headers->mdn_sent &&

@ -79,10 +79,23 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
$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 ($_GET['_download']) {
if ($plugin['download']) {
header("Content-Type: application/octet-stream");
if ($browser->ie)
header("Content-Type: application/force-download");
@ -97,7 +110,7 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
}
// deliver part content
if ($ctype_primary == 'text' && $ctype_secondary == 'html' && empty($_GET['_download'])) {
if ($ctype_primary == 'text' && $ctype_secondary == 'html' && empty($plugin['download'])) {
// get part body if not available
if (!$part->body)
$part->body = $MESSAGE->get_part_content($part->mime_id);
@ -119,7 +132,7 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
else
$filename = addcslashes($filename, '"');
$disposition = !empty($_GET['_download']) ? 'attachment' : 'inline';
$disposition = !empty($plugin['download']) ? 'attachment' : 'inline';
header("Content-Disposition: $disposition; filename=\"$filename\"");

@ -52,6 +52,10 @@ if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) {
$OUTPUT->set_env('delimiter', $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'])

@ -141,7 +141,7 @@ switch ($CURR_SECTION)
if (isset($CONFIG['max_pagesize']) && ($a_user_prefs['pagesize'] > $CONFIG['max_pagesize']))
$a_user_prefs['pagesize'] = (int) $CONFIG['max_pagesize'];
$a_user_prefs['timezone'] = $_SESSION['timezone'] = (string) $a_user_prefs['timezone'];
$a_user_prefs['timezone'] = (string) $a_user_prefs['timezone'];
break;
case 'mailbox':

@ -98,6 +98,13 @@ input.button:hover
color: black;
}
input.button[disabled],
input.button[disabled]:hover
{
color: #aaa;
border-color: #ccc;
}
input.mainaction
{
font-weight: bold;

Loading…
Cancel
Save