Merge branch 'master' into dev-elastic

pull/5838/head
Aleksander Machniak 8 years ago
commit adbab9d3e2

@ -30,8 +30,10 @@ RewriteRule ^favicon\.ico$ skins/larry/images/favicon.ico
RewriteRule ^(?!installer|\.well-known\/|[a-zA-Z0-9]{16})(\.?[^\.]+)$ - [F]
# - deny access to some locations
RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|program\/(include|lib|localization|steps)) - [F]
# - deny access to composer binaries
RewriteRule ^/vendor\/bin\/.* - [F]
# - deny access to some documentation files
RewriteRule /?(README\.md|composer\.json-dist|composer\.json|package\.xml|Dockerfile)$ - [F]
RewriteRule /?(README\.md|composer\.json-dist|composer\.json|package\.xml|jsdeps.json|Dockerfile)$ - [F]
</IfModule>
<IfModule mod_deflate.c>

@ -1,9 +1,24 @@
CHANGELOG Roundcube Webmail
===========================
- Enigma: Always use detached signatures (#5624)
- Enigma: Fix handling of messages with nested PGP encrypted parts (#5634)
- Minimize unwanted message loading in preview frame on drag (#5616)
- Fix autocomplete popup closing with click outside the input, don't handle Tab key as Enter (#5606)
- Fix jsdeps.json synchronization on update, warn about missing requirements of install-jsdeps.sh (#5598)
- Fix missing thread expand icon on search result in widescreen mode (#5613)
- Fix bug where image data URIs in css style were treated as evil/remote in mail preview (#5580)
- Fix bug where external content in src attribute of input/video tags was not secured (#5583)
- Fix PHP error on update of a contact with multiple email addresses when using PHP 7.1 (#5587)
- Fix bug where mail content frame couldn't be reset in some corner cases (#5608)
- Fix bug where some classic skin images were not displayed in IE/Edge (#5614)
- Fix bug where signature couldn't be added above the quote in Firefox 51 (#5628)
- Fix regression where groups with email address were resolved to its members' addresses
- Fix update of group name in the contacts list header on group rename (#5648)
- Add rewrite rule to disable access to /vendor/bin folder in .htaccess (#5630)
- Fix bug where it was too easy accidentally move a folder when using the subscription checkbox (#5655)
- Managesieve: Fix parser issue with empty lines between comments (#5657)
- Fix/rephrase "unsaved changes" warning when cancelling a draft (#5610)
RELEASE 1.3-beta
----------------

@ -41,15 +41,18 @@ it on a unix system, you need to do the following operations by hand:
./skins/
./plugins/
./vendor/
4. Update dependencies:
4a. If you previously installed plugins through composer, update dependencies
by running `php composer.phar update --no-dev`
by running `php composer.phar update --no-dev`.
4b. Install/update dependencies using composer:
- get composer from https://getcomposer.org/download/
- rename the composer.json-dist file into composer.json
- if you want to use LDAP address books, enable the LDAP libraries in your
composer.json file by moving the items from "suggest" to the "require"
section (remove the explanation texts after the version!).
- run `php composer.phar install --no-dev`
- run `php composer.phar install --no-dev`.
4c. If you use git sources or the release package without dependencies
update javascript dependencies by executing `bin/install-jsdeps.sh` script.
5. Run `./bin/update.sh` from the commandline OR
open http://url-to-roundcube/installer/ in a browser and choose "3 Test config".
To enable the latter one, you have to temporary set 'enable_installer'

@ -34,6 +34,16 @@ $WGET = trim(`which wget`);
$UNZIP = trim(`which unzip`);
$FILEINFO = trim(`which file`);
if (empty($UNZIP)) {
die("ERROR: Required program 'unzip' not found\n");
}
if (empty($FILEINFO)) {
die("ERROR: Required program 'file' not found\n");
}
if (empty($CURL) && empty($WGET)) {
die("ERROR: Required program 'wget' or 'curl' not found\n");
}
$CACHEDIR = sys_get_temp_dir();
if (is_writeable(INSTALL_PATH . 'temp/js_cache') || mkdir(INSTALL_PATH . 'temp/js_cache', 0774, true)) {

@ -61,7 +61,7 @@ if (strtolower($input) == 'y') {
rcube::raise_error("Failed to execute command: $command", false, true);
}
}
foreach (array('index.php','.htaccess','config/defaults.inc.php','composer.json-dist','CHANGELOG','README.md','UPGRADING','LICENSE','INSTALL') as $file) {
foreach (array('index.php','.htaccess','config/defaults.inc.php','composer.json-dist','jsdeps.json','CHANGELOG','README.md','UPGRADING','LICENSE','INSTALL') as $file) {
$command = "rsync -a --out-format \"%n\" " . INSTALL_PATH . "$file $target_dir/$file";
if (file_exists(INSTALL_PATH . $file) && (!system($command, $ret) || $ret > 0)) {
rcube::raise_error("Failed to execute command: $command", false, true);

@ -29,7 +29,7 @@
"pear-pear.php.net/net_idna2": "~0.1.1",
"pear-pear.php.net/mail_mime": "~1.10.0",
"pear-pear.php.net/net_smtp": "~1.7.1",
"pear-pear.php.net/crypt_gpg": "~1.6.0@beta",
"pear-pear.php.net/crypt_gpg": "~1.6.0",
"roundcube/net_sieve": "~1.5.0",
"endroid/qrcode": "~1.6.5"
},

@ -673,8 +673,7 @@ echo $select_param_folding->show(strval($RCI->getprop('mime_param_folding')));
<?php
$plugins = $RCI->list_plugins();
foreach($plugins as $p)
{
foreach ($plugins as $p) {
$p_check = new html_checkbox(array('name' => '_plugins_'.$p['name'], 'id' => 'cfgplugin_'.$p['name'], 'value' => $p['name']));
echo '<dt class="propname"><label>';
echo $p_check->show($p['enabled'] ? $p['name'] : 0);

@ -74,7 +74,7 @@ class debug_logger extends rcube_plugin
$log_config = rcmail::get_instance()->config->get('debug_logger',array());
foreach($log_config as $type=>$file){
foreach ($log_config as $type => $file){
$this->runlog->set_file(rcmail::get_instance()->config->get('log_dir').'/'.$file, $type);
}

@ -68,7 +68,7 @@ class runlog {
$this->indent--;
if ($this->run_log[$lastk]['duration'] >= $this->threshold) {
$tag_report = "";
foreach($this->tag_count as $tag => $count){
foreach ($this->tag_count as $tag => $count){
$tag_report .= "$tag: $count, ";
}
if (!empty($tag_report)) {

@ -59,6 +59,7 @@ Possible reasons:
- non-working loader in shebang (#! /usr/bin/env php)
Make sure it works for the user the php scripts are executed upon
(i.e. apache, www-date, etc.)
- SELinux setting, try command: setsebool -P httpd_unified 0
Note: pinentry is used with gpg >= 2.0 and <= 2.1.12.
Note: for server use GnuPG developers still recommend version 1.4.

@ -292,10 +292,10 @@ rcube_webmail.prototype.enigma_keylist_keypress = function(list)
// load key frame
rcube_webmail.prototype.enigma_loadframe = function(url)
{
var frm, win;
var win;
if (this.env.contentframe && window.frames && (frm = window.frames[this.env.contentframe])) {
if (!url && (win = window.frames[this.env.contentframe])) {
if (win = this.get_frame_window(this.env.contentframe)) {
if (!url) {
if (win.location && win.location.href.indexOf(this.env.blankpage) < 0)
win.location.href = this.env.blankpage;
if (this.env.frame_lock)
@ -304,7 +304,7 @@ rcube_webmail.prototype.enigma_loadframe = function(url)
}
this.env.frame_lock = this.set_busy(true, 'loading');
frm.location.href = this.env.comm_path + '&_framed=1&' + url;
win.location.href = this.env.comm_path + '&_framed=1' + url;
}
};

@ -164,11 +164,7 @@ class enigma_engine
case self::SIGN_MODE_MIME:
$pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
break;
/*
case self::SIGN_MODE_SEPARATE:
$pgp_mode = Crypt_GPG::SIGN_MODE_NORMAL;
break;
*/
default:
if ($mime->isMultipart()) {
$pgp_mode = Crypt_GPG::SIGN_MODE_DETACHED;
@ -430,11 +426,6 @@ class enigma_engine
{
$part = $p['structure'];
// exit, if we're already inside a decrypted message
if (in_array($part->mime_id, $this->encrypted_parts)) {
return;
}
// Get message body from IMAP server
if ($body === null) {
$body = $this->get_part_body($p['object'], $part);

@ -157,8 +157,8 @@ class enigma_mime_message extends Mail_mime
*/
public function get($params = null, $filename = null, $skip_head = false)
{
if (isset($params)) {
while (list($key, $value) = each($params)) {
if (!empty($params)) {
foreach ($params as $key => $value) {
$this->build_params[$key] = $value;
}
}

@ -1079,7 +1079,7 @@ class enigma_ui
}
else if (!$savedraft && $sign_enable) {
$engine = $this->enigma->load_engine();
$status = $engine->sign_message($p['message']);
$status = $engine->sign_message($p['message'], enigma_engine::SIGN_MODE_MIME);
$mode = 'sign';
}

@ -7,9 +7,7 @@
<script type="text/javascript" src="/splitter.js"></script>
<style type="text/css">
#enigmakeyslist { width: <roundcube:exp expression="!empty(cookie:enigmaviewsplitter) ? cookie:enigmaviewsplitter-5 : 210" />px; }
#enigmacontent-box { left: <roundcube:exp expression="!empty(cookie:enigmaviewsplitter) ? cookie:enigmaviewsplitter+5 : 220" />px;
<roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:enigmaeviewsplitter) ? cookie:enigmaviewsplitter+5 : 220).')+\\'px\\');') : ''" />
}
#enigmacontent-box { left: <roundcube:exp expression="!empty(cookie:enigmaviewsplitter) ? cookie:enigmaviewsplitter+5 : 220" />px; }
</style>
</head>
<body>

@ -165,7 +165,7 @@ class rcube_sieve
$rawErrorMessage = $result->getMessage();
$errMessages = preg_split("/$name:/", $rawErrorMessage);
if (sizeof($errMessages) > 0) {
if (count($errMessages) > 0) {
foreach ($errMessages as $singleError) {
$matches = array();
$res = preg_match('/line (\d+):(.*)/i', $singleError, $matches);

@ -506,7 +506,7 @@ class rcube_sieve_engine
if ($result === false) {
$this->rc->output->show_message('managesieve.filtersaveerror', 'error');
$errorLines = $this->sieve->get_error_lines();
if (sizeof($errorLines) > 0) {
if (count($errorLines) > 0) {
$this->rc->output->set_env("sieve_errors", $errorLines);
}
}
@ -689,7 +689,7 @@ class rcube_sieve_engine
if ($name == '')
$this->errors['name'] = $this->plugin->gettext('cannotbeempty');
else {
foreach($this->script as $idx => $rule)
foreach ($this->script as $idx => $rule)
if($rule['name'] == $name && $idx != $fid) {
$this->errors['name'] = $this->plugin->gettext('ruleexist');
break;
@ -1432,7 +1432,7 @@ class rcube_sieve_engine
// 'any' flag
if ((!isset($this->form) && empty($scr['tests']) && !empty($scr))
|| (sizeof($scr['tests']) == 1 && $scr['tests'][0]['test'] == 'true' && !$scr['tests'][0]['not'])
|| (count($scr['tests']) == 1 && $scr['tests'][0]['test'] == 'true' && !$scr['tests'][0]['not'])
) {
$any = true;
}
@ -1493,7 +1493,7 @@ class rcube_sieve_engine
$out .= $input_join . html::label($field_id, rcube::Q($this->plugin->gettext('filterany')));
$rows_num = !empty($scr['tests']) ? sizeof($scr['tests']) : 1;
$rows_num = !empty($scr['tests']) ? count($scr['tests']) : 1;
$out .= '<div id="rules"'.($any ? ' style="display: none"' : '').'>';
for ($x=0; $x<$rows_num; $x++)
@ -1505,7 +1505,7 @@ class rcube_sieve_engine
// actions
$out .= '<fieldset><legend>' . rcube::Q($this->plugin->gettext('messagesactions')) . "</legend>\n";
$rows_num = isset($scr) ? sizeof($scr['actions']) : 1;
$rows_num = isset($scr) ? count($scr['actions']) : 1;
$out .= '<div id="actions">';
for ($x=0; $x<$rows_num; $x++)
@ -1531,7 +1531,7 @@ class rcube_sieve_engine
function rule_div($fid, $id, $div=true)
{
$rule = isset($this->form) ? $this->form['tests'][$id] : $this->script[$fid]['tests'][$id];
$rows_num = isset($this->form) ? sizeof($this->form['tests']) : sizeof($this->script[$fid]['tests']);
$rows_num = isset($this->form) ? count($this->form['tests']) : count($this->script[$fid]['tests']);
// headers select
$select_header = new html_select(array('name' => "_header[]", 'id' => 'header'.$id,
@ -1935,7 +1935,7 @@ class rcube_sieve_engine
function action_div($fid, $id, $div=true)
{
$action = isset($this->form) ? $this->form['actions'][$id] : $this->script[$fid]['actions'][$id];
$rows_num = isset($this->form) ? sizeof($this->form['actions']) : sizeof($this->script[$fid]['actions']);
$rows_num = isset($this->form) ? count($this->form['actions']) : count($this->script[$fid]['actions']);
$out = $div ? '<div class="actionrow" id="actionrow' .$id .'">'."\n" : '';

@ -85,21 +85,22 @@ class rcube_sieve_script
{
// TODO: check this->supported
array_push($this->content, $content);
return sizeof($this->content)-1;
return count($this->content) - 1;
}
public function delete_rule($index)
{
if(isset($this->content[$index])) {
if (isset($this->content[$index])) {
unset($this->content[$index]);
return true;
}
return false;
}
public function size()
{
return sizeof($this->content);
return count($this->content);
}
public function update_rule($index, $content)
@ -109,6 +110,7 @@ class rcube_sieve_script
$this->content[$index] = $content;
return $index;
}
return false;
}
@ -590,7 +592,8 @@ class rcube_sieve_script
$prefix .= $line . "\n";
}
$position = $endl + 1;
// skip empty lines after the comment (#5657)
$position = self::ltrim_position($script, $endl + 1);
}
// handle script header
@ -1087,7 +1090,7 @@ class rcube_sieve_script
static function escape_string($str)
{
if (is_array($str) && count($str) > 1) {
foreach($str as $idx => $val)
foreach ($str as $idx => $val)
$str[$idx] = self::escape_string($val);
return '[' . implode(',', $str) . ']';

@ -1,5 +1,6 @@
# Sieve Filter
# Erzeugt von Ingo (http://www.horde.org/ingo/) (30.09.2016, 16:02)
# Nested rules aren't supported and will be ignored (#5540)
# rule:[Ausgeschlossene Adressen]
if address :is ["From","Sender","Resent-From"] "noreply@example.org"

@ -64,7 +64,7 @@ class rcube_ximss_password
fclose($sock);
foreach( explode( "\0",$responseblob) as $response ) {
foreach (explode( "\0",$responseblob) as $response) {
$resp = simplexml_load_string("<xml>".$response."</xml>");
if( $resp->response[0]['id'] == 'A001' ) {

@ -194,7 +194,7 @@ class squirrelmail_usercopy extends rcube_plugin
// parse addres book file
if (filesize($abookfile)) {
foreach(file($abookfile) as $line) {
foreach (file($abookfile) as $line) {
$line = $this->convert_charset(rtrim($line), $file_charset);
list($rec['name'], $rec['firstname'], $rec['surname'], $rec['email']) = explode('|', $line);
if ($rec['name'] && $rec['email']) {

@ -185,7 +185,7 @@ class zipdownload extends rcube_plugin
if ($rcmail->config->get('zipdownload_selection') && !empty($_POST['_uid'])) {
$messageset = rcmail::get_uids();
if (sizeof($messageset)) {
if (count($messageset)) {
$this->_download_messages($messageset);
}
}

@ -537,8 +537,8 @@ class rcmail extends rcube
// we'll only handle unset host (if possible)
if (!$host && !empty($default_host)) {
if (is_array($default_host)) {
list($key, $val) = each($default_host);
$host = is_numeric($key) ? $val : $key;
$key = key($default_host);
$host = is_numeric($key) ? $default_host[$key] : $key;
}
else {
$host = $default_host;
@ -749,8 +749,8 @@ class rcmail extends rcube
// take the first entry if $host is still not set
if (empty($host)) {
list($key, $val) = each($default_host);
$host = is_numeric($key) ? $val : $key;
$key = key($default_host);
$host = is_numeric($key) ? $default_host[$key] : $key;
}
}
else if (empty($default_host)) {

@ -988,27 +988,19 @@ EOF;
),
array(
"\$_SESSION['\\1']",
"\$app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
"\$env['\\1']",
"\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
"\$this->env['\\1']",
"rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)",
"\$_COOKIE['\\1']",
"\$browser->{'\\1'}",
"'" . $this->template_name . "'",
"\$this->browser->{'\\1'}",
"'{$this->template_name}'",
),
$expression
);
$fn = create_function('$app,$browser,$env', "return ($expression);");
if (!$fn) {
rcube::raise_error(array(
'code' => 505, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Expression parse error on: ($expression)"
), true, false);
return;
}
return $fn($this->app, $this->browser, $this->env);
// Note: We used create_function() before but it's deprecated in PHP 7.2
// and really it was just a wrapper on eval().
return eval("return ($expression);");
}
/**

@ -230,7 +230,6 @@ function rcube_webmail()
this.message_list
.addEventListener('initrow', function(o) { ref.init_message_row(o); })
.addEventListener('dblclick', function(o) { ref.msglist_dbl_click(o); })
.addEventListener('click', function(o) { ref.msglist_click(o); })
.addEventListener('keypress', function(o) { ref.msglist_keypress(o); })
.addEventListener('select', function(o) { ref.msglist_select(o); })
.addEventListener('dragstart', function(o) { ref.drag_start(o); })
@ -1060,12 +1059,10 @@ function rcube_webmail()
case 'select-all':
this.select_all_mode = props ? false : true;
this.dummy_select = true; // prevent msg opening if there's only one msg on the list
if (props == 'invert')
this.message_list.invert_selection();
else
this.message_list.select_all(props == 'page' ? '' : props);
this.dummy_select = null;
break;
case 'select-none':
@ -1850,31 +1847,12 @@ function rcube_webmail()
this.select_all_mode = false;
// start timer for message preview (wait for double click)
if (selected && this.env.contentframe && !list.multi_selecting && !this.dummy_select)
if (selected && this.env.contentframe && !list.multi_selecting)
this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, list.dblclick_time);
else if (this.env.contentframe)
this.show_contentframe(false);
};
// This allow as to re-select selected message and display it in preview frame
this.msglist_click = function(list)
{
if (list.multi_selecting || !this.env.contentframe)
return;
if (list.get_single_selection())
return;
var win = this.get_frame_window(this.env.contentframe);
if (win && win.location.href.indexOf(this.env.blankpage) >= 0) {
if (this.preview_timer)
clearTimeout(this.preview_timer);
this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, list.dblclick_time);
}
};
this.msglist_dbl_click = function(list)
{
if (this.preview_timer)
@ -2622,10 +2600,12 @@ function rcube_webmail()
url._mbox = mbox;
url._page = page;
// disable double-click on the list when preview pane is on
// this eliminates delay when opening a message in preview pane (#5199)
// Disable double-click on the list when preview pane is on
// to make the delay when opening a message in preview pane minimal (#5199)
// Standard double-click time is 500ms, we use 100ms, the smaller the value is
// unwanted message opening (on drag) can happen more often (#5616)
if (this.message_list)
this.message_list.dblclick_time = this.env.layout != 'list' ? 10 : this.dblclick_time;
this.message_list.dblclick_time = this.env.layout != 'list' ? 100 : this.dblclick_time;
this.http_request('list', url, lock);
this.update_state({ _mbox: mbox, _page: (page && page > 1 ? page : null) });
@ -3356,7 +3336,8 @@ function rcube_webmail()
var r_uids = [],
post_data = this.selection_post_data({_uid: this.uids_to_list(a_uids), _flag: 'delete'}),
lock = this.display_message(this.get_label('markingmessage'), 'loading'),
rows = this.message_list ? this.message_list.rows : {},
list = this.message_list,
rows = list ? list.rows : {},
count = 0;
for (var i=0, len=a_uids.length; i<len; i++) {
@ -3367,7 +3348,7 @@ function rcube_webmail()
if (this.env.skip_deleted) {
count += this.update_thread(uid);
this.message_list.remove_row(uid, (this.env.display_next && i == this.message_list.selection.length-1));
list.remove_row(uid, (this.env.display_next && i == list.selection.length-1));
}
else
this.set_message(uid, 'deleted', true);
@ -3375,9 +3356,9 @@ function rcube_webmail()
}
// make sure there are no selected rows
if (this.env.skip_deleted && this.message_list) {
if (!this.env.display_next)
this.message_list.clear_selection();
if (this.env.skip_deleted && list) {
if (!this.env.display_next || !list.rowcount)
list.clear_selection();
if (count < 0)
post_data._count = (count*-1);
else if (count > 0)
@ -4214,6 +4195,8 @@ function rcube_webmail()
// add signature according to selected identity
// if we have HTML editor, signature is added in a callback
if (input_from.prop('type') == 'select-one') {
// for some reason the caret initially is not at pos=0 in Firefox 51 (#5628)
this.set_caret_pos(input_message, 0);
this.change_identity(input_from[0]);
}
@ -4323,6 +4306,9 @@ function rcube_webmail()
obj.keydown(function(e) { return ref.ksearch_keydown(e, this, props); })
.attr({ 'autocomplete': 'off', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'role': 'combobox' });
// hide the popup on any click
$(document).on('click', function() { ref.ksearch_hide(); });
};
this.submit_messageform = function(draft, saveonly)
@ -5404,8 +5390,7 @@ function rcube_webmail()
if (this.ksearch_timer)
clearTimeout(this.ksearch_timer);
var key = rcube_event.get_keycode(e),
mod = rcube_event.get_modifier(e);
var key = rcube_event.get_keycode(e);
switch (key) {
case 38: // arrow up
@ -5424,12 +5409,6 @@ function rcube_webmail()
return rcube_event.cancel(e);
case 9: // tab
if (mod == SHIFT_KEY || !this.ksearch_visible()) {
this.ksearch_hide();
return;
}
case 13: // enter
if (!this.ksearch_visible())
return false;
@ -5440,6 +5419,7 @@ function rcube_webmail()
return rcube_event.cancel(e);
case 9: // tab
case 27: // escape
this.ksearch_hide();
return;
@ -5930,9 +5910,6 @@ function rcube_webmail()
boxtitle.append($('<span>').text(prop ? prop.name : this.get_label('contacts')));
}
if (prop)
this.triggerEvent('groupupdate', prop);
};
// load contact record
@ -6220,13 +6197,14 @@ function rcube_webmail()
this.group_create = function()
{
var input = $('<input>').attr('type', 'text'),
content = $('<label>').text(this.get_label('namex')).append(input);
content = $('<label>').text(this.get_label('namex')).append(input),
source = this.env.source;
this.simple_dialog(content, 'newgroup',
function() {
var name;
if (name = input.val()) {
ref.http_post('group-create', {_source: ref.env.source, _name: name},
ref.http_post('group-create', {_source: source, _name: name},
ref.set_busy(true, 'loading'));
return true;
}
@ -6241,13 +6219,15 @@ function rcube_webmail()
var group_name = this.env.contactgroups['G' + this.env.source + this.env.group].name,
input = $('<input>').attr('type', 'text').val(group_name),
content = $('<label>').text(this.get_label('namex')).append(input);
content = $('<label>').text(this.get_label('namex')).append(input),
source = this.env.source,
group = this.env.group;
this.simple_dialog(content, 'grouprename',
function() {
var name;
if ((name = input.val()) && name != group_name) {
ref.http_post('group-rename', {_source: ref.env.source, _gid: ref.env.group, _name: name},
ref.http_post('group-rename', {_source: source, _gid: group, _name: name},
ref.set_busy(true, 'loading'));
return true;
}
@ -6275,7 +6255,8 @@ function rcube_webmail()
delete this.env.contactgroups[key];
}
this.list_contacts(prop.source, 0);
if (prop.source == this.env.source && prop.id == this.env.group)
this.list_contacts(prop.source, 0);
};
//remove selected contacts from current active group
@ -6345,6 +6326,9 @@ function rcube_webmail()
else {
$(this.treelist.get_item(key)).children().first().html(prop.name);
this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name;
if (prop.source == this.env.source && prop.id == this.env.group)
this.set_group_prop(prop);
}
// update list node and re-sort it
@ -6851,7 +6835,7 @@ function rcube_webmail()
.addEventListener('collapse', function(node) { ref.folder_collapsed(node) })
.addEventListener('expand', function(node) { ref.folder_collapsed(node) })
.addEventListener('search', function(p) { if (p.query) ref.subscription_select(); })
.draggable({cancel: 'li.mailbox.root'})
.draggable({cancel: 'li.mailbox.root,input,div.treetoggle'})
.droppable({
// @todo: find better way, accept callback is executed for every folder
// on the list when dragging starts (and stops), this is slow, but

@ -88,7 +88,7 @@ function rcube_text_editor(config, id)
// full-featured editor
else {
$.extend(conf, {
plugins: 'autolink charmap code colorpicker directionality link image media nonbreaking'
plugins: 'autolink charmap code colorpicker directionality link lists image media nonbreaking'
+ ' paste table tabfocus textcolor searchreplace spellchecker',
toolbar: 'bold italic underline | alignleft aligncenter alignright alignjustify'
+ ' | bullist numlist outdent indent ltr rtl blockquote | forecolor backcolor | fontselect fontsizeselect'

@ -806,7 +806,7 @@ class rcube
{
static $sa_languages = array();
if (!sizeof($sa_languages)) {
if (!count($sa_languages)) {
@include(RCUBE_LOCALIZATION_DIR . 'index.inc');
if ($dh = @opendir(RCUBE_LOCALIZATION_DIR)) {
@ -1661,7 +1661,7 @@ class rcube
$this->plugins->exec_hook('message_send_error', $plugin + array('error' => $error));
}
else {
$this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body));
$this->plugins->exec_hook('message_sent', array('headers' => $headers, 'body' => $msg_body, 'message' => $message));
// remove MDN headers after sending
unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);

@ -4241,7 +4241,7 @@ class rcube_imap extends rcube_storage
*/
protected function sort_folder_specials($folder, &$list, &$specials, &$out)
{
while (list($key, $name) = each($list)) {
foreach ($list as $key => $name) {
if ($folder === null || strpos($name, $folder.$this->delimiter) === 0) {
$out[] = $name;
unset($list[$key]);

@ -2643,7 +2643,7 @@ class rcube_imap_generic
reset($messages);
while (list($key, $headers) = each($messages)) {
foreach ($messages as $key => $headers) {
$value = null;
switch ($field) {
@ -2685,7 +2685,7 @@ class rcube_imap_generic
}
// form new array based on index
while (list($key, $val) = each($index)) {
foreach ($index as $key => $val) {
$result[$key] = $messages[$key];
}
}
@ -3630,14 +3630,12 @@ class rcube_imap_generic
$data['type'] = 'multipart';
}
else {
$data['type'] = strtolower($part_a[0]);
// encoding
$data['type'] = strtolower($part_a[0]);
$data['encoding'] = strtolower($part_a[5]);
// charset
if (is_array($part_a[2])) {
while (list($key, $val) = each($part_a[2])) {
foreach ($part_a[2] as $key => $val) {
if (strcasecmp($val, 'charset') == 0) {
$data['charset'] = $part_a[2][$key+1];
break;

@ -125,7 +125,8 @@ class rcube_message
$this->mime = new rcube_mime($this->headers->charset);
$this->subject = $this->headers->get('subject');
list(, $this->sender) = each($this->mime->decode_address_list($this->headers->from, 1));
$from = $this->mime->decode_address_list($this->headers->from, 1);
$this->sender = current($from);
// notify plugins and let them analyze this structured message object
$this->app->plugins->exec_hook('message_load', array('object' => $this));
@ -865,7 +866,7 @@ class rcube_message
}
// if this was a related part try to resolve references
if (preg_match('/^multipart\/(related|relative)/', $mimetype) && sizeof($this->inline_parts)) {
if (preg_match('/^multipart\/(related|relative)/', $mimetype) && count($this->inline_parts)) {
$a_replaces = array();
$img_regexp = '/^image\/(gif|jpe?g|png|tiff|bmp|svg)/';

@ -791,7 +791,7 @@ class rcube_mime
$mime_types = $mime_extensions = array();
$regex = "/([\w\+\-\.\/]+)\s+([\w\s]+)/i";
foreach((array)$lines as $line) {
foreach ((array)$lines as $line) {
// skip comments or mime types w/o any extensions
if ($line[0] == '#' || !preg_match($regex, $line, $matches))
continue;

@ -101,7 +101,7 @@ class rcube_mime_decode
$return = new stdClass;
$headers = $this->parseHeaders($headers);
while (list($key, $value) = each($headers)) {
foreach ($headers as $value) {
$header_name = strtolower($value['name']);
if (isset($return->headers[$header_name]) && !is_array($return->headers[$header_name])) {
@ -124,10 +124,8 @@ class rcube_mime_decode
$return->ctype_secondary = $regs[2];
}
if (isset($content_type['other'])) {
while (list($p_name, $p_value) = each($content_type['other'])) {
$return->ctype_parameters[$p_name] = $p_value;
}
if (!empty($content_type['other'])) {
$return->ctype_parameters = array_merge((array) $return->ctype_parameters, (array) $content_type['other']);
}
break;
@ -136,10 +134,8 @@ class rcube_mime_decode
$content_disposition = $this->parseHeaderValue($value['value']);
$return->disposition = $content_disposition['value'];
if (isset($content_disposition['other'])) {
while (list($p_name, $p_value) = each($content_disposition['other'])) {
$return->d_parameters[$p_name] = $p_value;
}
if (!empty($content_disposition['other'])) {
$return->d_parameters = array_merge((array) $return->d_parameters, (array) $content_disposition['other']);
}
break;

@ -101,7 +101,7 @@ class rcube_spellcheck_enchant extends rcube_spellcheck_engine
else if (!enchant_dict_check($this->enchant_dictionary, $word)) {
$suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
if (sizeof($suggestions) > self::MAX_SUGGESTIONS) {
if (count($suggestions) > self::MAX_SUGGESTIONS) {
$suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
}
@ -130,7 +130,7 @@ class rcube_spellcheck_enchant extends rcube_spellcheck_engine
$suggestions = enchant_dict_suggest($this->enchant_dictionary, $word);
if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
if (count($suggestions) > self::MAX_SUGGESTIONS)
$suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
return is_array($suggestions) ? $suggestions : array();

@ -141,7 +141,7 @@ class rcube_spellcheck_googie extends rcube_spellcheck_engine
if ($matches[0][4]) {
$suggestions = explode("\t", $matches[0][4]);
if (sizeof($suggestions) > self::MAX_SUGGESTIONS) {
if (count($suggestions) > self::MAX_SUGGESTIONS) {
$suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
}

@ -107,7 +107,7 @@ class rcube_spellcheck_pspell extends rcube_spellcheck_engine
else if (!pspell_check($this->plink, $word)) {
$suggestions = pspell_suggest($this->plink, $word);
if (sizeof($suggestions) > self::MAX_SUGGESTIONS) {
if (count($suggestions) > self::MAX_SUGGESTIONS) {
$suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
}
@ -136,7 +136,7 @@ class rcube_spellcheck_pspell extends rcube_spellcheck_engine
$suggestions = pspell_suggest($this->plink, $word);
if (sizeof($suggestions) > self::MAX_SUGGESTIONS)
if (count($suggestions) > self::MAX_SUGGESTIONS)
$suggestions = array_slice($suggestions, 0, self::MAX_SUGGESTIONS);
return is_array($suggestions) ? $suggestions : array();

@ -399,7 +399,7 @@ class rcube_user
$sql = "INSERT INTO ".$this->db->table_name('identities', true).
" (`changed`, ".join(', ', $insert_cols).")".
" VALUES (".$this->db->now().", ".join(', ', array_pad(array(), sizeof($insert_values), '?')).")";
" VALUES (".$this->db->now().", ".join(', ', array_pad(array(), count($insert_values), '?')).")";
call_user_func_array(array($this->db, 'query'),
array_merge(array($sql), $insert_values));
@ -832,7 +832,7 @@ class rcube_user
$sql = "INSERT INTO ".$this->db->table_name('searches', true)
." (".join(', ', $insert_cols).")"
." VALUES (".join(', ', array_pad(array(), sizeof($insert_values), '?')).")";
." VALUES (".join(', ', array_pad(array(), count($insert_values), '?')).")";
call_user_func_array(array($this->db, 'query'),
array_merge(array($sql), $insert_values));

@ -98,7 +98,7 @@ class rcube_utils
// If not an IP address
$domain_array = explode('.', $domain_part);
// Not enough parts to be a valid domain
if (sizeof($domain_array) < 2) {
if (count($domain_array) < 2) {
return false;
}
@ -633,7 +633,7 @@ class rcube_utils
$proxy_whitelist = rcube::get_instance()->config->get('proxy_whitelist', array());
if (in_array($_SERVER['REMOTE_ADDR'], $proxy_whitelist)) {
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
foreach(array_reverse(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])) as $forwarded_ip) {
foreach (array_reverse(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])) as $forwarded_ip) {
if (!in_array($forwarded_ip, $proxy_whitelist)) {
return $forwarded_ip;
}

@ -626,7 +626,7 @@ class rcube_vcard
$field = strtoupper($regs2[1][0]);
$enc = null;
foreach($regs2[1] as $attrid => $attr) {
foreach ($regs2[1] as $attrid => $attr) {
$attr = preg_replace('/[\s\t\n\r\0\x0B]/', '', $attr);
if ((list($key, $value) = explode('=', $attr)) && $value) {
if ($key == 'ENCODING') {
@ -752,7 +752,7 @@ class rcube_vcard
}
}
else {
foreach((array)$attrvalues as $attrvalue) {
foreach ((array)$attrvalues as $attrvalue) {
$attr .= strtoupper(";$attrname=") . self::vcard_quote($attrvalue, ',');
}
}
@ -785,7 +785,7 @@ class rcube_vcard
public static function vcard_quote($s, $sep = ';')
{
if (is_array($s)) {
foreach($s as $part) {
foreach ($s as $part) {
$r[] = self::vcard_quote($part, $sep);
}
return(implode($sep, (array)$r));

@ -99,7 +99,7 @@ $messages['disclosedreciptitle'] = 'Too many public recipients';
$messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like to enter one now?';
$messages['nosubjecttitle'] = 'No subject';
$messages['nobodywarning'] = 'Send this message without text?';
$messages['notsentwarning'] = 'Message has not been sent. Do you want to discard your message?';
$messages['notsentwarning'] = 'The message has not been sent and has unsaved changes. Do you want to discard your changes?';
$messages['restoresavedcomposedata'] = 'A previously composed but unsent message was found.\n\nSubject: $subject\nSaved: $date\n\nDo you want to restore this message?';
$messages['noldapserver'] = 'Please select an ldap server to search.';
$messages['nosearchname'] = 'Please enter a contact name or email address.';

@ -657,7 +657,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
if (is_array($colprop['subtypes'])) {
$values = $subtypes = array();
foreach (rcube_addressbook::get_col_values($field, $record) as $st => $vals) {
foreach((array)$vals as $value) {
foreach ((array)$vals as $value) {
$i = count($values);
$subtypes[$i] = $st;
$values[$i] = $value;

@ -24,16 +24,16 @@ if ($RCMAIL->action == 'group-expand') {
$abook = $RCMAIL->get_address_book(rcube_utils::get_input_value('_source', rcube_utils::INPUT_GPC));
if ($gid = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC)) {
$abook->set_group($gid);
$abook->set_pagesize(1000); // TODO: limit number of group members by config
$abook->set_pagesize(9999); // TODO: limit number of group members by config?
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
$result = $abook->list_records($RCMAIL->config->get('contactlist_fields'));
$members = array();
while ($result && ($sql_arr = $result->iterate())) {
$emails = (array) $abook->get_col_values('email', $sql_arr, true);
while ($result && ($record = $result->iterate())) {
$emails = (array) $abook->get_col_values('email', $record, true);
if (!empty($emails) && ($email = array_shift($emails))) {
$members[] = format_email_recipient($email, rcube_addressbook::compose_list_name($sql_arr));
$members[] = format_email_recipient($email, rcube_addressbook::compose_list_name($record));
}
}
@ -70,9 +70,9 @@ if (!empty($book_types) && strlen($search)) {
$abook->set_pagesize($MAXNUM);
if ($result = $abook->search($RCMAIL->config->get('contactlist_fields'), $search, $mode, true, true, 'email')) {
while ($sql_arr = $result->iterate()) {
while ($record = $result->iterate()) {
// Contact can have more than one e-mail address
$email_arr = (array)$abook->get_col_values('email', $sql_arr, true);
$email_arr = (array)$abook->get_col_values('email', $record, true);
$email_cnt = count($email_arr);
$idx = 0;
@ -81,7 +81,7 @@ if (!empty($book_types) && strlen($search)) {
continue;
}
$name = rcube_addressbook::compose_list_name($sql_arr);
$name = rcube_addressbook::compose_list_name($record);
$contact = format_email_recipient($email, $name);
// skip entries that don't match
@ -95,15 +95,20 @@ if (!empty($book_types) && strlen($search)) {
if (empty($contacts[$index])) {
$contact = array(
'name' => $contact,
'type' => $sql_arr['_type'],
'id' => $sql_arr['ID'],
'type' => $record['_type'],
'id' => $record['ID'],
'source' => $abook_id,
);
if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) {
if (($display = rcube_addressbook::compose_search_name($record, $email, $name)) && $display != $contact['name']) {
$contact['display'] = $display;
}
// groups with defined email address will not be expanded to its members' addresses
if ($record['_type'] == 'group') {
$contact['email'] = $email;
}
$contacts[$index] = $contact;
$sort_keys[$index] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++);

@ -1161,7 +1161,7 @@ function rcmail_create_draft_body($body, $bodyIsHtml)
global $MESSAGE, $COMPOSE;
// add attachments
// sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
// count($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

@ -450,7 +450,7 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null
$a_headers = $plugin['messages'];
if ($RCMAIL->config->get('layout', 'widescreen') == 'widescreen') {
if (!$OUTPUT->get_env('threading')) {
if (!$RCMAIL->storage->get_threading()) {
if (($idx = array_search('threads', $a_show_cols)) !== false) {
unset($a_show_cols[$idx]);
}
@ -1251,7 +1251,7 @@ function rcmail_message_body($attrib)
if (!empty($MESSAGE->parts)) {
foreach ($MESSAGE->parts as $part) {
if ($part->type == 'headers') {
$out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers));
$out .= html::div('message-partheaders', rcmail_message_headers(count($header_attrib) ? $header_attrib : null, $part->headers));
}
else if ($part->type == 'content') {
// unsupported (e.g. encrypted)
@ -1639,7 +1639,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
$a_parts = rcube_mime::decode_address_list($input, null, true, $default_charset);
if (!sizeof($a_parts)) {
if (!count($a_parts)) {
return $input;
}

@ -203,7 +203,6 @@ else {
// update message count display
$OUTPUT->set_env('search_request', $search_str ? $search_request : '');
$OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
$OUTPUT->set_env('threading', $RCMAIL->storage->get_threading());
$OUTPUT->set_env('messagecount', $count);
$OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize()));
$OUTPUT->set_env('exists', $mbox === null ? 0 : $RCMAIL->storage->count($mbox, 'EXISTS'));

@ -183,7 +183,7 @@ function rcmail_message_attachments($attrib)
$out = $ol = '';
$attachments = array();
if (sizeof($MESSAGE->attachments)) {
if (count($MESSAGE->attachments)) {
foreach ($MESSAGE->attachments as $attach_prop) {
$filename = rcmail_attachment_name($attach_prop, true);
$filesize = $RCMAIL->message_part_size($attach_prop);

@ -121,7 +121,7 @@ function rcube_identity_form($attrib)
}
if (IDENTITIES_LEVEL == 4) {
foreach($form['addressing']['content'] as $formfield => $value){
foreach ($form['addressing']['content'] as $formfield => $value){
$form['addressing']['content'][$formfield]['disabled'] = true;
$form['addressing']['content'][$formfield]['class'] = 'disabled';
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Loading…
Cancel
Save