Merge branch 'master' into dev-elastic

pull/6040/head
Aleksander Machniak 7 years ago
commit 3c1b78af48

@ -0,0 +1,29 @@
language: php
sudo: false
matrix:
fast_finish: true
include:
- php: 5.4
- php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
env: CODE_COVERAGE=1
- php: 7.2
cache:
directories:
- $HOME/.composer
install:
- if [ "$CODE_COVERAGE" != 1 ]; then phpenv config-rm xdebug.ini || true; fi
- cp composer.json-dist composer.json
- composer install --prefer-dist
script:
- if [ "$CODE_COVERAGE" = 1 ]; then CODE_COVERAGE_ARGS="--coverage-text"; fi; vendor/bin/phpunit -c tests/phpunit.xml $CODE_COVERAGE_ARGS
notifications:
email: false

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Managesieve: Add ability to disable filter sets and other actions (#5496, #5898)
- Changed defaults for smtp_user (%u), smtp_pass (%p) and smtp_port (587)
- Composer: Fix certificate validation errors by using packagist only (#5148)
- Enigma: Add button to send mail unencrypted if no key was found (#5913)
@ -30,6 +31,7 @@ CHANGELOG Roundcube Webmail
- subscriptions_option: show \\Noselect folders greyed out (#5621)
- Add option to not indent quoted text on top-posting reply (#5105)
- Removed global $CONFIG variable
- Password: Support host variables in password_db_dsn option (#5955)
- Password: Automatic virtualmin domain setting, removed password_virtualmin_format option (#5759)
- Support AUTHENTICATE LOGIN for IMAP connections (#5563)
- Support LDAP GSSAPI authentication (#5703)
@ -44,6 +46,11 @@ CHANGELOG Roundcube Webmail
- Fix bug where pink image was used instead of a thumbnail when image resize fails (#5933)
- Fix so files size/count limit is verified (client-side) also on drag-n-drop uploads (#5940)
- Fix invalid template loading on a message error in preview frame (#5941)
- Fix bug where HTML messages could have been rendered empty on some systems (#5957)
- Fix wording of "Mark previewed messages as read" to "Mark messages as read" (#5952)
- Enigma: Fix decryption of messages encoded with non-ascii charset (#5962)
- Fix missing cursor in HTML editor on mail reply (#5969)
- Fix (again) bug where image data URIs in css style were treated as evil/remote in mail preview (#5580)
RELEASE 1.3.1
-------------

@ -1,7 +1,8 @@
Roundcube Webmail
=================
[roundcube.net](http://roundcube.net)
[roundcube.net](https://roundcube.net)
[![Build Status](https://api.travis-ci.org/roundcube/roundcubemail.svg?branch=master)](https://travis-ci.org/roundcube/roundcubemail)
ATTENTION
---------
@ -95,7 +96,7 @@ hello(at)roundcube(dot)net
[washtml]: http://www.ubixis.com/washtml/
[kmgerich]: http://kmgerich.com/
[gpl]: http://www.gnu.org/licenses/
[license]: http://roundcube.net/license
[contrib]: http://roundcube.net/contribute
[support]: http://roundcube.net/support
[githubissues]: https://github.com/roundcube/roundcubemail/issues
[license]: https://roundcube.net/license
[contrib]: https://roundcube.net/contribute
[support]: https://roundcube.net/support
[githubissues]: https://github.com/roundcube/roundcubemail/issues

@ -22,7 +22,7 @@
"endroid/qrcode": "~1.6.5"
},
"require-dev": {
"phpunit/phpunit": "~5.7.15"
"phpunit/phpunit": "^4.8.36 || ^5.7.21"
},
"suggest": {
"pear/net_ldap2": "~2.2.0 required for connecting to LDAP",

@ -1196,6 +1196,11 @@ class enigma_engine
}
else {
$body = $msg->get_part_body($part->mime_id, false);
// Convert charset to get rid of possible non-ascii characters (#5962)
if ($part->charset && stripos($part->charset, 'ASCII') === false) {
$body = rcube_charset::convert($body, $part->charset, 'US-ASCII');
}
}
return $body;

@ -1,6 +1,9 @@
* version 9.0 [2017-10-02]
-----------------------------------------------------------
- Fix parsing dot-staffed lines in multiline text (#5838)
- Fix AM/PM suffix in vacation time selectors
- Fix bug where 'exists' operator was reset to 'contains' (#5899)
- Add ability to disable filter sets and other actions (#5496, #5898)
* version 8.9 [2017-05-22]
-----------------------------------------------------------

@ -106,3 +106,9 @@ $config['managesieve_notify_methods'] = array('mailto');
// Enables scripts RAW editor feature
$config['managesieve_raw_editor'] = true;
// Disabled actions
// Prevent user from performing specific actions:
// list_sets, enable_disable_set, delete_set, new_set, download_set, new_rule, delete_rule
// Note: disabling list_sets removes the Filter sets widget from the UI and means the set defined in managesieve_script_name will always be used (and activated)
$config['managesieve_disabled_actions'] = array();

@ -62,8 +62,9 @@ class rcube_sieve_engine
2 => 'notifyimportancenormal',
1 => 'notifyimportancehigh'
);
private $disabled_actions;
const VERSION = '8.9';
const VERSION = '9.0';
const PROGNAME = 'Roundcube (Managesieve)';
const PORT = 4190;
@ -92,6 +93,8 @@ class rcube_sieve_engine
'filterseteditraw' => array($this, 'filterset_editraw'),
));
$this->disabled_actions = $this->rc->config->get('managesieve_disabled_actions', array());
// connect to managesieve server
$error = $this->connect($_SESSION['username'], $this->rc->decrypt($_SESSION['password']));
@ -147,6 +150,9 @@ class rcube_sieve_engine
}
$this->rc->output->set_env('raw_sieve_editor', $this->rc->config->get('managesieve_raw_editor', true));
$this->rc->output->set_env('managesieve_disabled_actions', $this->disabled_actions);
if (in_array('list_sets', $this->disabled_actions))
$this->rc->output->set_env('managesieve_no_set_list', true);
return $error;
}
@ -288,18 +294,23 @@ class rcube_sieve_engine
$fid = (int) rcube_utils::get_input_value('_fid', rcube_utils::INPUT_POST);
if ($action == 'delete' && !$error) {
if (isset($this->script[$fid])) {
if ($this->sieve->script->delete_rule($fid))
$result = $this->save_script();
if ($result === true) {
$this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'del', array('id' => $fid));
}
else {
$this->rc->output->show_message('managesieve.filterdeleteerror', 'error');
if (!in_array('delete_rule', $this->disabled_actions)) {
if (isset($this->script[$fid])) {
if ($this->sieve->script->delete_rule($fid))
$result = $this->save_script();
if ($result === true) {
$this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'del', array('id' => $fid));
}
else {
$this->rc->output->show_message('managesieve.filterdeleteerror', 'error');
}
}
}
else {
$this->rc->output->show_message('managesieve.disabledaction', 'error');
}
}
else if ($action == 'move' && !$error) {
if (isset($this->script[$fid])) {
@ -366,60 +377,77 @@ class rcube_sieve_engine
}
}
else if ($action == 'setact' && !$error) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->activate_script($script_name);
$kep14 = $this->rc->config->get('managesieve_kolab_master');
if ($result === true) {
$this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setactivated', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setact',
array('name' => $script_name, 'active' => true, 'all' => !$kep14));
if (!in_array('enable_disable_set', $this->disabled_actions)) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->activate_script($script_name);
$kep14 = $this->rc->config->get('managesieve_kolab_master');
if ($result === true) {
$this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setactivated', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setact',
array('name' => $script_name, 'active' => true, 'all' => !$kep14));
}
else {
$this->rc->output->show_message('managesieve.setactivateerror', 'error');
}
}
else {
$this->rc->output->show_message('managesieve.setactivateerror', 'error');
$this->rc->output->show_message('managesieve.disabledaction', 'error');
}
}
else if ($action == 'deact' && !$error) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->deactivate_script($script_name);
if ($result === true) {
$this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setact',
array('name' => $script_name, 'active' => false));
if (!in_array('enable_disable_set', $this->disabled_actions)) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->deactivate_script($script_name);
if ($result === true) {
$this->rc->output->set_env('active_sets', $this->active);
$this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setact',
array('name' => $script_name, 'active' => false));
}
else {
$this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
}
}
else {
$this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
$this->rc->output->show_message('managesieve.disabledaction', 'error');
}
}
else if ($action == 'setdel' && !$error) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->remove_script($script_name);
if ($result === true) {
$this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setdel',
array('name' => $script_name));
$this->rc->session->remove('managesieve_current');
if (!in_array('delete_set', $this->disabled_actions)) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_POST, true);
$result = $this->remove_script($script_name);
if ($result === true) {
$this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
$this->rc->output->command('managesieve_updatelist', 'setdel',
array('name' => $script_name));
$this->rc->session->remove('managesieve_current');
}
else {
$this->rc->output->show_message('managesieve.setdeleteerror', 'error');
}
}
else {
$this->rc->output->show_message('managesieve.setdeleteerror', 'error');
$this->rc->output->show_message('managesieve.disabledaction', 'error');
}
}
else if ($action == 'setget') {
$this->rc->request_security_check(rcube_utils::INPUT_GET);
if (!in_array('download_set', $this->disabled_actions)) {
$this->rc->request_security_check(rcube_utils::INPUT_GET);
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
$script = $this->sieve->get_script($script_name);
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
$script = $this->sieve->get_script($script_name);
if ($script !== false) {
$this->rc->output->download_headers($script_name . '.txt', array('length' => strlen($script)));
echo $script;
}
if ($script !== false) {
$this->rc->output->download_headers($script_name . '.txt', array('length' => strlen($script)));
echo $script;
}
exit;
exit;
}
}
else if ($action == 'list') {
$result = $this->list_rules();
@ -547,7 +575,10 @@ class rcube_sieve_engine
$name_uc = mb_strtolower($name);
$list = $this->list_scripts();
if (!$name) {
if (in_array('new_set', $this->disabled_actions)) {
$error = 'managesieve.disabledaction';
}
else if (!$name) {
$this->errors['name'] = $this->plugin->gettext('cannotbeempty');
}
else if (mb_strlen($name) > 128) {
@ -1407,6 +1438,12 @@ class rcube_sieve_engine
$fid = rcube_utils::get_input_value('_fid', rcube_utils::INPUT_GPC);
$scr = isset($this->form) ? $this->form : $this->script[$fid];
// do not allow creation of new rules
if ($fid == null && in_array('new_rule', $this->disabled_actions)) {
$this->rc->output->show_message('managesieve.disabledaction', 'error');
return;
}
$hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
$hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
$hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
@ -2472,6 +2509,17 @@ class rcube_sieve_engine
}
}
// When no script listing allowed limit the list to the defined script
if (in_array('list_sets', $this->disabled_actions)) {
$script_name = $this->rc->config->get('managesieve_script_name', 'roundcube');
$this->list = array_intersect($this->list, array($script_name));
$this->active = null;
if (in_array($script_name, $this->list)) {
// Because its the only allowed script make sure its active
$this->activate_script($script_name);
}
}
// reindex
if (!empty($this->list)) {
$this->list = array_values($this->list);
@ -2514,7 +2562,7 @@ class rcube_sieve_engine
$user_script = $_SESSION['managesieve_user_script'];
// if the script is not active...
if ($user_script && array_search($name, $this->active) === false) {
if ($user_script && array_search($name, (array) $this->active) === false) {
// ...rewrite USER file adding appropriate include command
if ($this->sieve->load($user_script)) {
$script = $this->sieve->script->as_array();

@ -237,4 +237,6 @@ $messages['saveerror'] = 'Unable to save data. Server error occurred.';
$messages['vacationsaved'] = 'Vacation data saved successfully.';
$messages['emptyvacationbody'] = 'Body of vacation message is required!';
$messages['duplicate.conflict.err'] = 'Both header and unique identifier are not allowed.';
$messages['disabledaction'] = 'Action not permitted.';
?>

@ -241,5 +241,6 @@ $messages['saveerror'] = 'Unable to save data. Server error occurred.';
$messages['vacationsaved'] = 'Vacation data saved successfully.';
$messages['emptyvacationbody'] = 'Body of vacation message is required!';
$messages['duplicate.conflict.err'] = 'Both header and unique identifier are not allowed.';
$messages['disabledaction'] = 'Action not permitted.';
?>

@ -56,7 +56,8 @@ if (window.rcmail) {
sieve_raw_editor_init();
}
else {
rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
rcmail.enable_command('plugin.managesieve-add', !rcmail.env.sieveconnerror && $.inArray('new_rule', rcmail.env.managesieve_disabled_actions) == -1);
rcmail.enable_command('plugin.managesieve-setadd', !rcmail.env.sieveconnerror && $.inArray('new_set', rcmail.env.managesieve_disabled_actions) == -1);
}
var setcnt, set = rcmail.env.currentset;
@ -92,8 +93,9 @@ if (window.rcmail) {
setcnt = rcmail.filtersets_list.rowcount;
rcmail.enable_command('plugin.managesieve-set', true);
rcmail.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', setcnt > 0);
rcmail.enable_command('plugin.managesieve-setdel', setcnt > 1);
rcmail.enable_command('plugin.managesieve-setact', setcnt > 0 && $.inArray('enable_disable_set', rcmail.env.managesieve_disabled_actions) == -1);
rcmail.enable_command('plugin.managesieve-setget', setcnt > 0 && $.inArray('download_set', rcmail.env.managesieve_disabled_actions) == -1);
rcmail.enable_command('plugin.managesieve-setdel', setcnt > 1 && $.inArray('delete_set', rcmail.env.managesieve_disabled_actions) == -1);
rcmail.enable_command('plugin.managesieve-seteditraw', setcnt > 0 && rcmail.env.raw_sieve_editor);
// Fix dragging filters over sets list
@ -145,7 +147,9 @@ rcube_webmail.prototype.managesieve_select = function(list)
}
var has_id = typeof(id) != 'undefined' && id != null;
this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', has_id);
this.enable_command('plugin.managesieve-act', has_id);
this.enable_command('plugin.managesieve-del', has_id && $.inArray('delete_rule', rcmail.env.managesieve_disabled_actions) == -1);
};
// Set selection
@ -153,8 +157,9 @@ rcube_webmail.prototype.managesieve_setselect = function(list)
{
this.show_contentframe(false);
this.filters_list.clear(true);
this.enable_command('plugin.managesieve-setdel', list.rowcount > 1);
this.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', list.rowcount > 0);
this.enable_command('plugin.managesieve-setdel', list.rowcount > 1 && $.inArray('delete_set', rcmail.env.managesieve_disabled_actions) == -1);
this.enable_command('plugin.managesieve-setact', list.rowcount > 0 && $.inArray('enable_disable_set', rcmail.env.managesieve_disabled_actions) == -1);
this.enable_command('plugin.managesieve-setget', list.rowcount > 0 && $.inArray('delete_set', rcmail.env.managesieve_disabled_actions) == -1);
this.enable_command('plugin.managesieve-seteditraw', list.rowcount > 0 && this.env.raw_sieve_editor);
var id = list.get_single_selection();
@ -299,7 +304,8 @@ rcube_webmail.prototype.managesieve_updatelist = function(action, o)
list.insert_row(row.get(0));
list.highlight_row(o.id);
this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', true);
this.enable_command('plugin.managesieve-del', $.inArray('delete_rule', rcmail.env.managesieve_disabled_actions) == -1);
this.enable_command('plugin.managesieve-act', true);
break;

@ -19,6 +19,11 @@
left: 205px;
}
#filtersscreen.nosetlist
{
left: 0;
}
#filterslistbox
{
position: absolute;

@ -7,7 +7,9 @@
<script type="text/javascript" src="/splitter.js"></script>
<style type="text/css">
<roundcube:if condition="!env:managesieve_no_set_list" />
#filterslistbox { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter-5 : 210" />px; }
<roundcube:endif />
#filter-box { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220" />px; }
#filtersetslistbox { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter2) ? cookie:sieveviewsplitter2-5 : 175" />px; }
#filtersscreen { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter2) ? cookie:sieveviewsplitter2+5 : 185" />px; }
@ -21,7 +23,7 @@
<roundcube:include file="/includes/settingstabs.html" />
<div id="mainscreen">
<roundcube:if condition="!env:managesieve_no_set_list" />
<div id="filtersetslistbox">
<div id="filtersetslist-title" class="boxtitle"><roundcube:label name="managesieve.filtersets" /></div>
<div class="boxlistcontent">
@ -34,6 +36,9 @@
</div>
<div id="filtersscreen">
<roundcube:else />
<div id="filtersscreen" class="nosetlist">
<roundcube:endif />
<div id="filterslistbox">
<div class="boxtitle"><roundcube:label name="managesieve.filters" /></div>
<div class="boxlistcontent">
@ -46,8 +51,10 @@
</div>
<script type="text/javascript">
<roundcube:if condition="!env:managesieve_no_set_list" />
var sieveviewsplit2 = new rcube_splitter({id:'sieveviewsplitter2', p1: 'filtersetslistbox', p2: 'filtersscreen', orientation: 'v', relative: true, start: 200});
rcmail.add_onload('sieveviewsplit2.init()');
<roundcube:endif />
var sieveviewsplit = new rcube_splitter({id:'sieveviewsplitter', p1: 'filterslistbox', p2: 'filter-box', orientation: 'v', relative: true, start: 215});
rcmail.add_onload('sieveviewsplit.init()');

@ -16,6 +16,11 @@
left: 162px;
}
#filtersscreen.nosetlist
{
left: 0;
}
#filterslistbox
{
position: absolute;

@ -15,6 +15,7 @@
<roundcube:include file="/includes/settingstabs.html" />
<div id="settings-right" role="main">
<roundcube:if condition="!env:managesieve_no_set_list" />
<div id="filtersetslistbox" class="uibox listbox" aria-labelledby="aria-label-filtersets">
<h2 class="boxtitle" id="aria-label-filtersets"><roundcube:label name="managesieve.filtersets" /></h2>
<div class="scroller withfooter">
@ -24,8 +25,10 @@
<roundcube:button command="plugin.managesieve-setadd" type="link" title="managesieve.filtersetadd" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="filtersetmenulink" id="filtersetmenulink" type="link" title="moreactions" class="listbutton groupactions" onclick="return UI.toggle_popup('filtersetmenu', event)" innerClass="inner" content="&#9881;" aria-haspopup="true" aria-expanded="false" aria-owns="filtersetmenu-menu" />
</div>
</div>
<div id="filtersscreen">
<roundcube:else />
<div id="filtersscreen" class="nosetlist">
<roundcube:endif />
<div id="filterslistbox" class="uibox listbox" aria-labelledby="aria-label-filters">
<h2 class="boxtitle" id="aria-label-filters"><roundcube:label name="managesieve.filters" /></h2>
<div class="scroller withfooter">
@ -72,8 +75,10 @@
<roundcube:include file="/includes/footer.html" />
<script type="text/javascript">
<roundcube:if condition="!env:managesieve_no_set_list" />
new rcube_splitter({ id:'managesievesplitter1', p1:'#filtersetslistbox', p2:'#filtersscreen',
orientation:'v', relative:true, start:156, min:120, size:12 }).init();
<roundcube:endif />
new rcube_splitter({ id:'managesievesplitter2', p1:'#filterslistbox', p2:'#filter-box',
orientation:'v', relative:true, start:186, min:120, size:12 }).init();
</script>

@ -3,7 +3,7 @@
"type": "roundcube-plugin",
"description": "Password Change for Roundcube. Plugin adds a possibility to change user password using many methods (drivers) via Settings/Password tab.",
"license": "GPLv3+",
"version": "4.2",
"version": "4.3",
"authors": [
{
"name": "Aleksander Machniak",

@ -83,6 +83,12 @@ $config['password_disabled'] = false;
// ------------------
// PEAR database DSN for performing the query. By default
// Roundcube DB settings are used.
// Supported replacement variables:
// %h - user's IMAP hostname
// %n - hostname ($_SERVER['SERVER_NAME'])
// %t - hostname without the first part
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
$config['password_db_dsn'] = '';
// The SQL query used to change the password.

@ -35,7 +35,7 @@ class rcube_sql_password
}
if ($dsn = $rcmail->config->get('password_db_dsn')) {
$db = rcube_db::factory($dsn, '', false);
$db = rcube_db::factory(self::parse_dsn($dsn), '', false);
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
}
else {
@ -169,4 +169,23 @@ class rcube_sql_password
return PASSWORD_ERROR;
}
/**
* Parse DSN string and replace host variables
*/
protected static function parse_dsn($dsn)
{
if (strpos($dsn, '%')) {
// parse DSN and replace variables in hostname
$parsed = rcube_db::parse_dsn($dsn);
$host = rcube_utils::parse_host($parsed['hostspec']);
// build back the DSN string
if ($host != $parsed['hostspec']) {
$dsn = str_replace('@' . $parsed['hostspec'], '@' . $host, $dsn);
}
}
return $dsn;
}
}

@ -4284,9 +4284,7 @@ function rcube_webmail()
else if (input_message)
elem = input_message;
this.init_messageform_inputs(elem);
this.env.compose_focus_elem = document.activeElement;
this.env.compose_focus_elem = this.init_messageform_inputs(elem);
// get summary of all field values
this.compose_field_hash(true);
@ -4316,8 +4314,11 @@ function rcube_webmail()
this.init_address_input_events($("[name='_"+ac_fields[i]+"']"), ac_props);
}
// focus first empty element
$(focused || input_to).focus();
if (!focused)
focused = input_to;
// focus first empty element (and return it)
return $(focused).focus().get(0);
};
this.compose_restore_dialog = function(j, html_mode)

@ -184,7 +184,7 @@ function rcube_text_editor(config, id)
rcmail.change_identity(elem);
// Focus previously focused element
if (fe && fe.id != this.id) {
if (fe && fe.id != this.id && fe.nodeName != 'BODY') {
window.focus(); // for WebKit (#1486674)
fe.focus();
rcmail.env.compose_focus_elem = null;

@ -189,8 +189,8 @@ class rcube_imap extends rcube_storage
// write error log
else if ($this->conn->error) {
if ($pass && $user) {
$message = sprintf("Login failed for %s from %s. %s",
$user, rcube_utils::remote_ip(), $this->conn->error);
$message = sprintf("Login failed for %s against %s from %s. %s",
$user, $host, rcube_utils::remote_ip(), $this->conn->error);
rcube::raise_error(array('code' => 403, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,

@ -251,7 +251,7 @@ class rcube_message
if (is_resource($mode)) {
if ($body !== false) {
fwrite($mode, $body);
rewind($mode);
@rewind($mode);
}
return $body !== false;
@ -276,7 +276,7 @@ class rcube_message
!($mode && $formatted), $max_bytes, $mode && $formatted);
if (is_resource($mode)) {
rewind($mode);
@rewind($mode);
return $body !== false;
}

@ -407,10 +407,17 @@ class rcube_utils
if ($allow_remote) {
$a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
foreach ($a_styles as $line) {
for ($i=0, $len=count($a_styles); $i < $len; $i++) {
$line = $a_styles[$i];
$stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
// ... and only allow strict url() values
if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
// allow data:image uri, join with continuation
if (stripos($stripped, 'url(data:image')) {
$a_styles[$i] .= ';' . $a_styles[$i+1];
unset($a_styles[$i+1]);
}
// allow strict url() values only
else if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
$a_styles = array('/* evil! */');
break;
}
@ -1160,7 +1167,7 @@ class rcube_utils
$random = openssl_random_pseudo_bytes($length);
if ($random === false) {
if ($random === false && $length > 0) {
throw new Exception("Failed to get random bytes");
}

@ -381,9 +381,9 @@ class rcube_vcard
}
if (($tag = self::$fieldmap[$field]) && (is_array($value) || strlen($value))) {
$index = count($this->raw[$tag]);
$this->raw[$tag][$index] = (array)$value;
$this->raw[$tag][] = (array) $value;
if ($type) {
$index = count($this->raw[$tag]) - 1;
$typemap = array_flip($this->typemap);
$this->raw[$tag][$index]['type'] = explode(',', $typemap[$type_uc] ?: $type);
}
@ -405,7 +405,7 @@ class rcube_vcard
*/
public function set_raw($tag, $value, $append = false)
{
$index = $append ? count($this->raw[$tag]) : 0;
$index = $append && isset($this->raw[$tag]) ? count($this->raw[$tag]) : 0;
$this->raw[$tag][$index] = (array)$value;
}

@ -311,17 +311,17 @@ class rcube_washtml
}
}
if ($this->is_image_attribute($node->tagName, $key)) {
if ($this->is_image_attribute($node->nodeName, $key)) {
$out = $this->wash_uri($value, true);
}
else if ($this->is_link_attribute($node->tagName, $key)) {
else if ($this->is_link_attribute($node->nodeName, $key)) {
if (!preg_match('!^(javascript|vbscript|data:text)!i', $value)
&& preg_match('!^([a-z][a-z0-9.+-]+:|//|#).+!i', $value)
) {
$out = $value;
}
}
else if ($this->is_funciri_attribute($node->tagName, $key)) {
else if ($this->is_funciri_attribute($node->nodeName, $key)) {
if (preg_match('/^[a-z:]*url\(/i', $val)) {
if (preg_match('/^([a-z:]*url)\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)/iu', $value, $match)) {
if ($url = $this->wash_uri($match[2])) {
@ -454,14 +454,14 @@ class rcube_washtml
do {
switch ($node->nodeType) {
case XML_ELEMENT_NODE: //Check element
$tagName = strtolower($node->tagName);
$tagName = strtolower($node->nodeName);
if ($callback = $this->handlers[$tagName]) {
$dump .= call_user_func($callback, $tagName,
$this->wash_attribs($node), $this->dumpHtml($node, $level), $this);
}
else if (isset($this->_html_elements[$tagName])) {
$content = $this->dumpHtml($node, $level);
$dump .= '<' . $node->tagName;
$dump .= '<' . $node->nodeName;
if ($tagName == 'svg') {
$xpath = new DOMXPath($node->ownerDocument);
@ -481,14 +481,14 @@ class rcube_washtml
$dump .= ' />';
}
else {
$dump .= '>' . $content . '</' . $node->tagName . '>';
$dump .= '>' . $content . '</' . $node->nodeName . '>';
}
}
else if (isset($this->_ignore_elements[$tagName])) {
$dump .= '<!-- ' . htmlspecialchars($node->tagName, ENT_QUOTES) . ' not allowed -->';
$dump .= '<!-- ' . htmlspecialchars($node->nodeName, ENT_QUOTES) . ' not allowed -->';
}
else {
$dump .= '<!-- ' . htmlspecialchars($node->tagName, ENT_QUOTES) . ' ignored -->';
$dump .= '<!-- ' . htmlspecialchars($node->nodeName, ENT_QUOTES) . ' ignored -->';
$dump .= $this->dumpHtml($node, $level); // ignore tags not its content
}
break;

@ -554,7 +554,7 @@ $labels['replyandforwardonly'] = 'replies and forwards only';
$labels['insertsignature'] = 'Insert signature';
$labels['sigbelow'] = 'Place signature below the quoted message';
$labels['sigseparator'] = 'Force standard separator in signatures';
$labels['previewpanemarkread'] = 'Mark previewed messages as read';
$labels['automarkread'] = 'Mark messages as read';
$labels['afternseconds'] = 'after $n seconds';
$labels['reqmdn'] = 'Always request a return receipt';
$labels['reqdsn'] = 'Always request a delivery status notification';

@ -449,7 +449,7 @@ function rcmail_user_prefs($current = null)
}
$blocks['main']['options']['mail_read_time'] = array(
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('previewpanemarkread'))),
'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('automarkread'))),
'content' => $select->show($config['mail_read_time']),
);
}

@ -218,7 +218,9 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
// allow data URIs with images (#5580)
$mod = rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody');
$this->assertEquals("#rcmbody { background-image: url(data:image/png;base64,123); }", $mod, "Data URIs in url() allowed");
$this->assertContains("#rcmbody { background-image: url(data:image/png;base64,123);", $mod, "Data URIs in url() allowed [1]");
$mod = rcube_utils::mod_css_styles("body { background-image: url(data:image/png;base64,123); }", 'rcmbody', true);
$this->assertContains("#rcmbody { background-image: url(data:image/png;base64,123);", $mod, "Data URIs in url() allowed [2]");
}
function test_xss_entity_decode()

@ -91,4 +91,9 @@
<file>./../plugins/zipdownload/tests/Zipdownload.php</file>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../program/lib</directory>
</whitelist>
</filter>
</phpunit>

Loading…
Cancel
Save