Merge branch 'master' into dev/elastic

pull/6486/head
Aleksander Machniak 6 years ago
commit c8d133a6a0

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- SMTP GSSAPI support via krb_authentication plugin (#6417)
- Removed referer_check option (#6440)
- Update to TinyMCE 4.8.2
- Plugin API: Added 'raise_error' hook (#6199)
@ -8,9 +9,11 @@ CHANGELOG Roundcube Webmail
- Password: Added 'modoboa' driver (#6361)
- Password: Fix bug where password_dovecotpw_with_method setting could be ignored (#6436)
- Password: Fix bug where new users could skip forced password change (#6434)
- Elastic: Support new-line char as a separator for pasted recipients (#6460)
- Elastic: Improved UX of search dialogs (#6416)
- Elastic: Fix unwanted thread expanding when selecting a collapsed thread in non-mobile mode (#6445)
- Log errors caused by low pcre.backtrack_limit when sending a mail message (#6433)
- Fix bug where autocomplete list could be displayed out of screen (#6469)
- Fix style/navigation on error page depending on authentication state (#6362)
- Fix so invalid smtp_helo_host is never used, fallback to localhost (#6408)
- Fix custom logo size in Elastic (#6424)
@ -19,6 +22,9 @@ CHANGELOG Roundcube Webmail
- Managesieve: Fix bug where show_real_foldernames setting wasn't respected (#6422)
- New_user_identity: Fix %fu/%u vars substitution in user specific LDAP params (#6419)
- Fix support for "allow-from <uri>" in "x_frame_options" config option (#6449)
- Fix bug where valid content between HTML comments could have been skipped in some cases (#6464)
- Fix multiple VCard field search (#6466)
- Fix session issue on long running requests (#6470)
RELEASE 1.4-beta
----------------

@ -19,7 +19,7 @@ REQUIREMENTS
- GD, Imagick (optional thumbnails generation, QR-code)
* PEAR and PEAR packages distributed with Roundcube or external:
- Mail_Mime 1.10.0 or newer
- Net_SMTP 1.7.1 or newer
- Net_SMTP 1.8.1 or newer
- Net_Socket 1.0.12 or newer
- Net_IDNA2 0.1.1 or newer
- Auth_SASL 1.0.6 or newer

@ -11,11 +11,10 @@
"require": {
"php": ">=5.4.0",
"pear/pear-core-minimal": "~1.10.1",
"pear/net_socket": "~1.2.1",
"pear/auth_sasl": "~1.1.0",
"pear/net_idna2": "~0.2.0",
"pear/mail_mime": "~1.10.0",
"pear/net_smtp": "~1.8.0",
"pear/net_smtp": "~1.8.1",
"pear/crypt_gpg": "~1.6.3",
"pear/net_sieve": "~1.4.3",
"roundcube/plugin-installer": "~0.1.6",

@ -569,7 +569,7 @@ $config['max_group_members'] = 0;
$config['product_name'] = 'Roundcube Webmail';
// Add this user-agent to message headers when sending
$config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
$config['useragent'] = 'Roundcube Webmail/'.RCUBE_VERSION;
// try to load host-specific configuration
// see https://github.com/roundcube/roundcubemail/wiki/Configuration:-Multi-Domain-Setup

@ -3,7 +3,7 @@
"type": "roundcube-plugin",
"description": "Kerberos Authentication",
"license": "GPLv3+",
"version": "1.1",
"version": "1.2",
"authors": [
{
"name": "Jeroen van Meeuwen",

@ -9,5 +9,12 @@
// Unlike $config['default_host'] this must be a string!
$config['krb_authentication_host'] = '';
// GSS API security context
$config['krb_authentication_context'] = 'imap/kolab.example.org@EXAMPLE.ORG';
// GSSAPI security context.
// Single value or an array with per-protocol values. Example:
//
// $config['krb_authentication_context'] = array(
// 'imap' => 'imap/host.fqdn@REALM.NAME',
// 'smtp' => 'smtp/host.fqdn@REALM.NAME',
// 'sieve' => 'sieve/host.fqdn@REALM.NAME',
// );
$config['krb_authentication_context'] = 'principal@REALM.NAME';

@ -25,6 +25,7 @@ class krb_authentication extends rcube_plugin
$this->add_hook('login_after', array($this, 'login'));
$this->add_hook('storage_connect', array($this, 'storage_connect'));
$this->add_hook('managesieve_connect', array($this, 'managesieve_connect'));
$this->add_hook('smtp_connect', array($this, 'smtp_connect'));
}
/**
@ -74,19 +75,41 @@ class krb_authentication extends rcube_plugin
return $args;
}
/**
* login_after hook handler
*/
function login($args)
{
// Redirect to the previous QUERY_STRING
if ($this->redirect_query) {
header('Location: ./?' . $this->redirect_query);
exit;
}
return $args;
}
/**
* Storage_connect hook handler
*/
function storage_connect($args)
{
if (!empty($_SERVER['REMOTE_USER']) && !empty($_SERVER['KRB5CCNAME'])) {
// Load plugin's config file
$this->load_config();
$args['gssapi_context'] = $this->gssapi_context('imap');
$args['gssapi_cn'] = $_SERVER['KRB5CCNAME'];
$args['auth_type'] = 'GSSAPI';
}
$rcmail = rcmail::get_instance();
$context = $rcmail->config->get('krb_authentication_context');
return $args;
}
$args['gssapi_context'] = $context ?: 'imap/kolab.example.org@EXAMPLE.ORG';
/**
* managesieve_connect hook handler
*/
function managesieve_connect($args)
{
if ((!isset($args['auth_type']) || $args['auth_type'] == 'GSSAPI') && !empty($_SERVER['REMOTE_USER']) && !empty($_SERVER['KRB5CCNAME'])) {
$args['gssapi_context'] = $this->gssapi_context('sieve');
$args['gssapi_cn'] = $_SERVER['KRB5CCNAME'];
$args['auth_type'] = 'GSSAPI';
}
@ -95,36 +118,38 @@ class krb_authentication extends rcube_plugin
}
/**
* login_after hook handler
* smtp_connect hook handler
*/
function login($args)
function smtp_connect($args)
{
// Redirect to the previous QUERY_STRING
if ($this->redirect_query) {
header('Location: ./?' . $this->redirect_query);
exit;
if ((!isset($args['smtp_auth_type']) || $args['smtp_auth_type'] == 'GSSAPI') && !empty($_SERVER['REMOTE_USER']) && !empty($_SERVER['KRB5CCNAME'])) {
$args['gssapi_context'] = $this->gssapi_context('smtp');
$args['gssapi_cn'] = $_SERVER['KRB5CCNAME'];
$args['smtp_auth_type'] = 'GSSAPI';
}
return $args;
}
/**
* managesieve_connect hook handler
* Returns configured GSSAPI context string
*/
function managesieve_connect($args)
private function gssapi_context($protocol)
{
if ((!isset($args['auth_type']) || $args['auth_type'] == 'GSSAPI') && !empty($_SERVER['REMOTE_USER']) && !empty($_SERVER['KRB5CCNAME'])) {
// Load plugin's config file
$this->load_config();
// Load plugin's config file
$this->load_config();
$rcmail = rcmail::get_instance();
$context = $rcmail->config->get('krb_authentication_context');
$rcmail = rcmail::get_instance();
$context = $rcmail->config->get('krb_authentication_context');
$args['gssapi_context'] = $context ?: 'imap/kolab.example.org@EXAMPLE.ORG';
$args['gssapi_cn'] = $_SERVER['KRB5CCNAME'];
$args['auth_type'] = 'GSSAPI';
if (is_array($context)) {
$context = $context[$protocol];
}
return $args;
if (empty($context)) {
rcube::raise_error("Empty GSSAPI context ($protocol).", true);
}
return $context;
}
}

@ -5941,9 +5941,20 @@ function rcube_webmail()
// reset content
ul.innerHTML = '';
this.env.contacts = [];
// move the results pane right under the input box
var pos = $(this.ksearch_input).offset();
this.ksearch_pane.css({ left:pos.left+'px', top:(pos.top + this.ksearch_input.offsetHeight)+'px', display: 'none'});
var pos = $(this.ksearch_input).offset(),
w = $(window).width(),
left = w - pos.left > 200 ? pos.left : w - 200,
width = Math.min(400, w - left);
this.ksearch_pane.css({
left: left + 'px',
top: (pos.top + this.ksearch_input.offsetHeight + 1) + 'px',
maxWidth: width + 'px',
minWidth: '200px',
display: 'none'
});
}
// add each result line to list

@ -32,7 +32,7 @@ include_path directory of your webserver. Some classes of the framework require
one or multiple of the following [PEAR][pear] libraries:
- Mail_Mime 1.8.1 or newer
- Net_SMTP 1.7.1 or newer
- Net_SMTP 1.8.1 or newer
- Net_Socket 1.0.12 or newer
- Net_IDNA2 0.1.1 or newer
- Auth_SASL 1.0.6 or newer

@ -380,7 +380,7 @@ class rcube_contacts extends rcube_addressbook
foreach ((array)$row[$col] as $value) {
if ($this->compare_search_value($colname, $value, $search, $mode)) {
$found[$colname] = true;
break 2;
break;
}
}
}

@ -306,7 +306,7 @@ abstract class rcube_session
$cache = null;
}
// use internal data for fast requests (up to 0.5 sec.)
else if ($key == $this->key && (!$this->vars || $ts - $this->start < 0.5)) {
else if ($key == $this->key && (!$this->vars || microtime(true) - $this->start < 0.5)) {
$cache = $this->vars;
}
else { // else read data again

@ -108,7 +108,8 @@ class rcube_smtp
// IDNA Support
$smtp_host = rcube_utils::idn_to_ascii($smtp_host);
$this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host, false, 0, $CONFIG['smtp_conn_options']);
$this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host, false, 0, $CONFIG['smtp_conn_options'],
$CONFIG['gssapi_context'], $CONFIG['gssapi_cn']);
if ($rcube->config->get('smtp_debug')) {
$this->conn->setDebug(true, array($this, 'debug_handler'));
@ -154,7 +155,7 @@ class rcube_smtp
}
// attempt to authenticate to the SMTP server
if ($smtp_user && $smtp_pass) {
if (($smtp_user && $smtp_pass) || ($smtp_auth_type == 'GSSAPI')) {
// IDNA Support
if (strpos($smtp_user, '@')) {
$smtp_user = rcube_utils::idn_to_ascii($smtp_user);

@ -643,6 +643,9 @@ class rcube_washtml
$html = str_replace($badwordchars, $fixedwordchars, $html);
// FIXME: HTML comments handling could be better. The code below can break comments (#6464),
// we should probably do not modify content inside comments at all.
// fix (unknown/malformed) HTML tags before "wash"
$html = preg_replace_callback('/(<(?!\!)[\/]*)([^\s>]+)([^>]*)/', array($this, 'html_tag_callback'), $html);
@ -665,9 +668,15 @@ class rcube_washtml
*/
public static function html_tag_callback($matches)
{
// It might be an ending of a comment, ignore (#6464)
if (substr($matches[3], -2) == '--') {
$matches[0] = '';
return implode('', $matches);
}
$tagname = $matches[2];
$tagname = preg_replace(array(
'/:.*$/', // Microsoft's Smart Tags <st1:xxxx>
'/:.*$/', // Microsoft's Smart Tags <st1:xxxx>
'/[^a-z0-9_\[\]\!?-]/i', // forbidden characters
), '', $tagname);

@ -59,12 +59,20 @@
#rcmKSearchpane {
width: auto;
max-width: none;
overflow: hidden;
li {
padding-right: .5rem;
}
html.layout-small &,
html.layout-phone & {
bottom: auto;
border: 1px solid @color-input-border;
}
html.layout-phone & {
max-width: 100% !important;
}
}
html.layout-small,
@ -106,11 +114,6 @@ html.layout-phone {
width: 100%;
}
#rcmKSearchpane {
bottom: auto;
border: 1px solid @color-input-border;
}
.popover-header {
display: block;
border-radius: 0;

@ -2892,7 +2892,7 @@ function rcube_elastic_ui()
*/
function recipient_input(obj)
{
var list, input, ac_props,
var list, input, ac_props, update_lock,
input_len_update = function() {
input.css('width', input.val().length * 10 + 15);
},
@ -2932,29 +2932,41 @@ function rcube_elastic_ui()
else
recipient.insertBefore(input.parent());
},
update_func = function() {
var text = input.val().replace(/[,;\s]+$/, ''),
result = recipient_input_parser(text);
update_func = function(text) {
var result;
if (update_lock) {
return;
}
update_lock = true;
text = (text || input.val()).replace(/[,;\s]+$/, '');
result = recipient_input_parser(text);
$.each(result.recipients, function() {
insert_recipient(this.name, this.email);
});
input.val(result.text);
apply_func();
input_len_update();
// setTimeout() here is needed for proper input reset on paste event
// This is also the reason why we need parse_lock
setTimeout(function() {
input.val(result.text);
apply_func();
input_len_update();
update_lock = false;
}, 1);
if (result.recipients.length) {
return true;
}
return result.recipients.length > 0;
},
parse_func = function(e) {
// Note it can be also executed when autocomplete inserts a recipient
update_func();
if (e.type == 'blur') {
list.removeClass('focus');
}
// On paste the text is not yet in the input we have to use clipboard.
// Also because on paste new-line characters are replaced by spaces (#6460)
update_func(e.type == 'paste' ? (e.originalEvent.clipboardData || window.clipboardData).getData('text') : null);
},
keydown_func = function(e) {
// On Backspace remove the last recipient
@ -2963,8 +2975,8 @@ function rcube_elastic_ui()
apply_func();
return false;
}
// Here we add a recipient box when the separator character (,;) was pressed
else if (e.key == ',' || e.key == ';') {
// Here we add a recipient box when the separator (,;) or Enter was pressed
else if (e.key == ',' || e.key == ';' || e.key == 'Enter') {
if (update_func()) {
return false;
}
@ -2973,7 +2985,7 @@ function rcube_elastic_ui()
input_len_update();
};
// Create the input elemennt and "editable" area
// Create the input element and "editable" area
input = $('<input>').attr({type: 'text', tabindex: $(obj).attr('tabindex')})
.on('paste change blur', parse_func)
.on('keydown', keydown_func)
@ -3021,6 +3033,9 @@ function rcube_elastic_ui()
*/
function recipient_input_parser(text)
{
// support new-line as a separator, for paste action (#6460)
text = $.trim(text.replace(/[,;\s]*[\r\n]+/g, ','));
var recipients = [],
address_rx_part = '(\\S+|("[^"]+"))@\\S+',
recipient_rx1 = new RegExp('(<' + address_rx_part + '>)'),

@ -2426,6 +2426,8 @@ ul.toolbarmenu li span.copy {
border: 0;
cursor: default;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
}
#rcmKSearchpane ul li i.icon {

@ -98,6 +98,11 @@ class Framework_Washtml extends PHPUnit_Framework_TestCase
$washed = $this->cleanupResult($washer->wash($html));
$this->assertEquals('<p>para1</p><p>para2</p>', $washed, "HTML comments - bracket inside");
$html = "<p><!-- span>1</span -->\n<span>2</span>\n<!-- >3</span --><span>4</span></p>";
$washed = $this->cleanupResult($washer->wash($html));
$this->assertEquals("<p>\n<span>2</span>\n<span>4</span></p>", $washed, "HTML comments (#6464)");
}
/**

Loading…
Cancel
Save