20 Commits
0.5 ... 0.7

Author SHA1 Message Date
Boris Gulay
1b424b4348 Fixed check for port number (cannot be 0). 2016-05-21 01:22:41 +03:00
Boris Gulay
6705312240 Removed NOT NULL constraints in initial file. 2016-05-21 01:22:41 +03:00
Boris Gulay
05ea494fa6 README.md edited online with Bitbucket 2016-05-20 20:42:22 +00:00
Boris Gulay
5a704f2717 Fixed double encryption of pwd when changing record (cannot connect
after change).
2016-05-20 23:40:48 +03:00
Boris Gulay
01edffa66b Removed unused skin-related styles. 2016-05-20 23:21:15 +03:00
Boris Gulay
9367409f36 Russian translation added. 2016-05-20 23:21:15 +03:00
Boris Gulay
bbf28eed57 Label and host are not required from now. 2016-05-20 23:21:15 +03:00
Boris Gulay
ec71910156 Done better checks and saving NULL instead of empty string. 2016-05-20 23:21:15 +03:00
Boris Gulay
f700593730 Added data validation for identity form. 2016-05-20 23:21:15 +03:00
Boris Gulay
9db4f48593 Do now show connection options for default identity. 2016-05-20 23:21:15 +03:00
Boris Gulay
2b9c43858e Fixed bug when account selected is shown twice on settings pages. 2016-05-20 23:21:15 +03:00
Boris Gulay
95716183d7 Make fields on form disabled if Enabled not checked. 2016-05-20 23:21:15 +03:00
Boris Gulay
40e7f5664e Missing string added. 2016-05-20 23:21:15 +03:00
Boris Gulay
ea62869891 README.md edited online with Bitbucket 2016-05-20 16:06:32 +00:00
Boris Gulay
057c88ebc5 Added conflist option for SMTP switcher. 2016-05-16 22:43:53 +03:00
Boris Gulay
41186b613e Added logging in Roundcube way. Removed some unneccesery logging. 2016-05-16 22:36:01 +03:00
Boris Gulay
3e41e57888 Now correct identity is selected when creating new message in remote
account.
2016-05-16 22:18:20 +03:00
Boris Gulay
0925fca08a Removed old config files. 2016-05-16 21:35:31 +03:00
Boris Gulay
67dc78a48c Implemented basic SMTP functionality. 2016-05-16 21:16:17 +03:00
Boris Gulay
1b7d90a92b README.md edited online with Bitbucket 2016-05-16 17:44:03 +00:00
13 changed files with 236 additions and 157 deletions

View File

@@ -1,2 +1,11 @@
# ident_switch
ident_switch plugin for Roundcube
This plugin allows users to switch between different accounts (including remote) in single Roundcube session.
*Inspired by identities_imap plugin that is no longer supported.*
### Where to start ###
* In settigs interface create new identity.
* For all identities except default you will see new section of settings - IMAP. Enter data required to connect to remote server. Don't forget to check Enabled check box.
* After you have created at least one identity with active IMAP settings you will see combobox in the top right corner instead of plain text field with account name. It will allows you to switch to another account.

View File

@@ -18,16 +18,14 @@ CREATE TABLE ident_switch
password
varchar(64),
host
varchar(64)
NOT NULL,
varchar(64),
port
integer
CHECK(port > 0 AND port <= 65535),
delimiter
char(1),
label
varchar(32)
NOT NULL,
varchar(32),
flags
integer
NOT NULL

View File

@@ -0,0 +1,11 @@
ALTER TABLE
ident_switch
ALTER COLUMN
host
DROP NOT NULL;
ALTER TABLE
ident_switch
ALTER COLUMN
label
DROP NOT NULL;

View File

@@ -22,6 +22,9 @@
"php": ">=5.3.0",
"roundcube/plugin-installer": ">=0.1.3"
},
"conflict": {
"elm/identity_smtp": "*"
},
"support": {
"issues": "https://bitbucket.org/BoresExpress/ident_switch/issues"
},

View File

@@ -1,26 +0,0 @@
<?php
/* Password encryption:
'rcmail': encrypt passwords by default Roundcube methods.
'secure': encrypt passwords by using the IMAP password as encryption key.
NOTE: When using 'secure' encryption, If IMAP passwords are changed
using methods other than Roundcube Webmail interface
(hmail_password or password plugin) then IMAP server identities
passwords must be re-entered by users.
*/
$rcmail_config['identities_imap_crypt'] = 'rcmail';
/* password encryption salt (only used for secure encryption) */
$rcmail_config['identities_imap_salt'] = '!kQm*fF3pXe1Kbm%9';
/* predefined imap hosts (associated with the domain part of the identity email property) */
$rcmail_config['identities_imap_external'] = array(
);
$rcmail_config['identities_imap_internal'] = array(
'BoresSoft Webmail' => array(
'host' =>'localhost',
'delimiter' => '/',
'readonly' => false, // on match prevent field editing
),
);
?>

View File

@@ -1,44 +1,2 @@
<?php
/* Password encryption:
'rcmail': encrypt passwords by default Roundcube methods.
'secure': encrypt passwords by using the IMAP password as encryption key.
NOTE: When using 'secure' encryption, If IMAP passwords are changed
using methods other than Roundcube Webmail interface
(hmail_password or password plugin) then IMAP server identities
passwords must be re-entered by users.
*/
$rcmail_config['identities_imap_crypt'] = 'rcmail';
/* password encryption salt (only used for secure encryption) */
$rcmail_config['identities_imap_salt'] = '!kQm*fF3pXe1Kbm%9';
/* predefined imap hosts (associated with the domain part of the identity email property) */
$rcmail_config['identities_imap_external'] = array(
'gmail.com' => array(
'host' =>'ssl://imap.gmail.com:993',
'delimiter' => '/',
'readonly' => true, // on match prevent field editing
),
'googlemail.com' => array(
'host' =>'ssl://imap.gmail.com:993',
'delimiter' => '/',
'readonly' => true, // on match prevent field editing
),
'freenet.de' => array(
'host' =>'mx.freenet.de',
'delimiter' => '.',
'readonly' => false, // on match prevent field editing
),
);
$rcmail_config['identities_imap_internal'] = array(
'mydomain.tld' => array(
'host' =>'ssl://imap.mydomain.tld:993',
'delimiter' => '/',
'readonly' => true, // on match prevent field editing
),
);
/* auto-detect IMAP server */
$rcmail_config['identities_imap_autodetect'] = false;
?>

View File

@@ -1,15 +1,35 @@
/*
* This is part of identity_imap plugin
*/
$(function() {
if ($('#plugin-ident_switch-account').size() > 0) {
$('#plugin-ident_switch-account').prependTo('.topright');
$('.topright .username').hide();
$('#plugin-ident_switch-account').show();
var $truName = $('.topright .username');
if ($truName.size() > 0) {
$sw = $('#plugin-ident_switch-account');
if ($sw.size() > 0) {
$sw.prependTo('.topright');
$truName.hide();
$('#plugin-ident_switch-account').show();
console.log("Doing replace.");
}
}
var $enFld = $("INPUT[name='_ident_switch.form.enabled']");
if ($enFld.size() == 1)
$enFld.change();
});
function plugin_switchIdent_enabled_onChange(e) {
var $enFld = $("INPUT[name='_ident_switch.form.enabled']");
$("INPUT[name!='_ident_switch.form.enabled']", $enFld.parents("FIELDSET")).prop("disabled", !$enFld.is(":checked"));
}
function plugin_switchIdent_switch(val) {
console.log("qwe1");
rcmail.http_post('plugin.ident_switch.switch', { '_ident-id': val });
}
function plugin_switchIdent_fixIdent(iid) {
if (parseInt(iid) > 0)
$("#_from").val(iid);
}

View File

@@ -13,6 +13,7 @@ class ident_switch extends rcube_plugin
public $task='?(?!login|logout).*';
private $table = 'ident_switch';
private $my_postfix = '_iswitch';
// Flags user in database
private $db_enabled = 1;
@@ -22,10 +23,11 @@ class ident_switch extends rcube_plugin
{
$this->add_hook('startup', array($this, 'on_startup'));
$this->add_hook('render_page', array($this, 'on_render_page'));
# $this->add_hook('smtp_connect', array($this, 'on_smtp_connect'));
$this->add_hook('smtp_connect', array($this, 'on_smtp_connect'));
$this->add_hook('identity_form', array($this, 'on_identity_form'));
$this->add_hook('identity_update', array($this, 'on_identity_update'));
$this->add_hook('identity_delete', array($this, 'on_identity_delete'));
$this->add_hook('template_object_composeheaders', array($this, 'on_template_object_composeheaders'));
$this->register_action('plugin.ident_switch.switch', array($this, 'on_switch'));
}
@@ -33,8 +35,9 @@ class ident_switch extends rcube_plugin
function on_startup($args)
{
$rc = rcmail::get_instance();
error_log('Task: ' . $args['task'] . ', action: ' . $args['action']);
if (strtolower($rc->user->data['username']) != strtolower($_SESSION['username']))
if (strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 1)
{ // We are impersonating
$rc->config->set('imap_cache', null);
$rc->config->set('messages_cache', false);
@@ -52,6 +55,7 @@ class ident_switch extends rcube_plugin
function on_render_page($args)
{
$rc = rcmail::get_instance();
error_log('Template: ' . $args['template']);
// Get list of alternative accounts
$sOpt = '';
@@ -63,17 +67,26 @@ class ident_switch extends rcube_plugin
if (strcasecmp($_SESSION['username'], $r['username']) === 0)
$opts['selected'] = 'selected';
// Make label
$lbl = $r['label'];
if (!$lbl)
{
if (strpos($r['username'], '@') === false)
$lbl = $r['username'] . '@' . ($r['host'] ? $r['host'] : 'localhost');
else
$lbl = $r['username'];
}
$sOpt .= html::tag(
'option',
$opts,
$r['label']
rcube::Q($lbl)
);
}
// Render UI if user has extra accounts
if (!empty($sOpt))
{
// Add main account
$opts = array('value' => -1);
if (strcasecmp($_SESSION['username'], $rc->user->data['username']) === 0)
@@ -103,19 +116,36 @@ class ident_switch extends rcube_plugin
function on_smtp_connect($args)
{
error_log('on_smtp_connect');
$rc = rcmail::get_instance();
// TODO: Rewrite with full settings!
if (strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 1)
{
if ($args['smtp_user'] == '%u')
$args['smtp_user'] = $rc->user->data['username'];
if ($args['smtp_pass'] == '%p')
$args['smtp_pass'] = $rc->decrypt($_SESSION['password' . $this->my_postfix]);
}
return $args;
}
function on_identity_form($args)
{
$rc = rcmail::get_instance();
// Do now show options for default identity
if (strcasecmp($args['record']['email'], $rc->user->data['username']) === 0)
return $args;
$this->add_texts('localization');
// Create our field set
$args['form']['ident_switch'] = array(
'name' => $this->gettext('form.caption'),
'content' => array(
'ident_switch.form.enabled' => array('type' => 'checkbox'),
'ident_switch.form.enabled' => array('type' => 'checkbox', 'onchange' => 'plugin_switchIdent_enabled_onChange();'),
'ident_switch.form.label' => array('type' => 'text', 'size' => 32),
'ident_switch.form.host' => array('type' => 'text', 'size' => 64),
'ident_switch.form.secure' => array('type' => 'checkbox'),
@@ -152,9 +182,57 @@ class ident_switch extends rcube_plugin
{
$rc = rcmail::get_instance();
// TODO: check field values
// Check field values
$noErrors = false;
$sql = 'SELECT NULL FROM ' . $rc->db->table_name($this->table) . ' WHERE iid = ? AND user_id = ?';
$fLabel = self::ntrim(get_input_value('_ident_switch_form_label', RCUBE_INPUT_POST));
if (strlen($fLabel) > 32)
$rc->output->show_message('err.label.long', 'error');
else
{
$fHost = self::ntrim(get_input_value('_ident_switch_form_host', RCUBE_INPUT_POST));
if (strlen($fHost) > 64)
$rc->output->show_message('err.host.long', 'error');
else
{
$fPort = self::ntrim(get_input_value('_ident_switch_form_port', RCUBE_INPUT_POST));
if ($fPort && !ctype_digit($fPort))
$rc->output->show_message('err.port.num', 'error');
else
{
if ($fPort && ($fPort <= 0 || $fPort > 65535))
$rc->output->show_message('err.port.num', 'error');
else
{
$fUser = self::ntrim(get_input_value('_ident_switch_form_username', RCUBE_INPUT_POST));
if (strlen($fUser) > 64)
$rc->output->show_message('err.user.long', 'error');
else
{
if (!$fUser)
$rc->output->show_message('err.user.empty', 'error');
else
{
$fDelim = self::ntrim(get_input_value('_ident_switch_form_delimiter', RCUBE_INPUT_POST));
if (strlen($fDelim) > 1)
$rc->output->show_message('err.delim.long', 'error');
else
$noErrors = true;
}
}
}
}
}
}
if (!$noErrors)
{
//$rc->output->send();
$args['abort'] = true;
return $args;
}
$sql = 'SELECT password FROM ' . $rc->db->table_name($this->table) . ' WHERE iid = ? AND user_id = ?';
$q = $rc->db->query($sql, $args['id'], $rc->user->ID);
$r = $rc->db->fetch_assoc($q);
if ($r)
@@ -177,15 +255,20 @@ class ident_switch extends rcube_plugin
if (get_input_value('_ident_switch_form_secure', RCUBE_INPUT_POST))
$flags |= $this->db_secure;
// Do we need to update pwd?
$fPass = get_input_value('_ident_switch_form_password', RCUBE_INPUT_POST);
if ($fPass != $r['password'])
$fPass = $rc->encrypt($fPass);
$rc->db->query(
$sql,
$flags,
get_input_value('_ident_switch_form_label', RCUBE_INPUT_POST),
get_input_value('_ident_switch_form_host', RCUBE_INPUT_POST),
get_input_value('_ident_switch_form_port', RCUBE_INPUT_POST),
get_input_value('_ident_switch_form_username', RCUBE_INPUT_POST),
$rc->encrypt(get_input_value('_ident_switch_form_password', RCUBE_INPUT_POST)),
get_input_value('_ident_switch_form_delimiter', RCUBE_INPUT_POST),
$fLabel,
$fHost,
$fPort,
$fUser,
$fPass,
$fDelim,
$rc->user->ID,
$args['id']
);
@@ -198,46 +281,64 @@ class ident_switch extends rcube_plugin
$rc = rcmail::get_instance();
$sql = 'DELETE FROM ' . $rc->db->table_name($this->table) . ' WHERE iid = ? AND user_id = ?';
$rc->db->query($sql, $args['id'], $rc->user->ID);
$q = $rc->db->query($sql, $args['id'], $rc->user->ID);
// TODO: Affected rows count for log
if ($rc->db->affected_rows($q))
$rc->write_log($this->my_log, 'Deleted associated information for identity with ID = ' . $args['id'] . '.');
return $args;
}
function on_template_object_composeheaders($args)
{
if ($args['id'] == '_from')
{
$rc = rcmail::get_instance();
if (strcasecmp($_SESSION['username'], $rc->user->data['username']) !== 0)
{
if (isset($_SESSION['iid' . $this->my_postfix]))
$rc->output->add_script('plugin_switchIdent_fixIdent(' . $_SESSION['iid' . $this->my_postfix] . ');', 'docready');
else
$rc->write_log($this->my_log, 'Special session variable with active identity ID not found.');
}
}
}
function on_switch()
{
$rc = rcmail::get_instance();
$my_postfix = '_iswitch';
$my_postfix_len = strlen($my_postfix);
error_log('Switcing account!'); // TODO: Add nornal logging here!
$my_postfix_len = strlen($this->my_postfix);
$identId = rcube_utils::get_input_value('_ident-id', RCUBE_INPUT_POST);
error_log($identId);
if (-1 == $identId)
{ // Switch to main account
$rc->write_log($this->my_log, 'Switching mailbox back to default.');
foreach ($_SESSION as $k => $v)
{
if (strncasecmp($k, 'storage', 7) === 0 && substr_compare($k, $my_postfix, -$my_postfix_len, $my_postfix_len) === 0)
if (strncasecmp($k, 'storage', 7) === 0 && substr_compare($k, $this->my_postfix, -$my_postfix_len, $my_postfix_len) === 0)
{
error_log($k . '=>' . $v);
$_SESSION[$k] = $_SESSION[$k . $my_postfix];
$rc->session->remove($k . $my_postfix);
$_SESSION[$k] = $_SESSION[$k . $this->my_postfix];
$rc->session->remove($k . $this->my_postfix);
}
}
$_SESSION['username'] = $rc->user->data['username'];
$_SESSION['password'] = $_SESSION['password' . $my_postfix];
$_SESSION['password'] = $_SESSION['password' . $this->my_postfix];
$_SESSION['iid' . $this->my_postfix] = -1;
}
else
{
$sql = 'SELECT host, flags, port, username, password FROM ' . $rc->db->table_name($this->table) . ' WHERE id = ? AND user_id = ?';
$sql = 'SELECT host, flags, port, username, password, iid FROM ' . $rc->db->table_name($this->table) . ' WHERE id = ? AND user_id = ?';
$q = $rc->db->query($sql, $identId ,$rc->user->ID);
$r = $rc->db->fetch_assoc($q);
if (is_array($r))
{
$rc->write_log(
$this->my_log,
'Switching mailbox to one for identity with ID = ' . $r['iid'] . ' (username = \'' . $r['username'] . '\').'
);
$port = $r['port'];
$ssl = false;
if ($r['flags'] & $this->db_secure)
@@ -255,28 +356,28 @@ class ident_switch extends rcube_plugin
{
foreach ($_SESSION as $k => $v)
{
if (strncasecmp($k, 'storage', 7) === 0 && substr_compare($k, $my_postfix, -$my_postfix_len, $my_postfix_len) !== 0)
if (strncasecmp($k, 'storage', 7) === 0 && substr_compare($k, $this->my_postfix, -$my_postfix_len, $my_postfix_len) !== 0)
{
error_log($k . '=>' . $v);
$_SESSION[$k . $my_postfix] = $_SESSION[$k];
$_SESSION[$k . $this->my_postfix] = $_SESSION[$k];
$rc->session->remove($k);
}
}
}
$_SESSION['password' . $my_postfix] = $_SESSION['password'];
$_SESSION['password' . $this->my_postfix] = $_SESSION['password'];
$_SESSION['storage_host'] = $r['host'];
$_SESSION['storage_host'] = $r['host'] ? $r['host'] : 'localhost'; // Default host here!
$_SESSION['storage_ssl'] = $ssl;
$_SESSION['storage_port'] = $port;
$_SESSION['username'] = $r['username'];
$_SESSION['password'] = $r['password'];
$_SESSION['iid' . $this->my_postfix] = $r['iid'];
$rc->session->remove('folders');
}
else
{
// TODO: Show message in browser
error_log('Requested account not found!');
$rc->write_log($this->my_log, 'Requested remote mailbox with ID = ' . $identId . ' not found.');
return;
}
}
@@ -288,4 +389,16 @@ class ident_switch extends rcube_plugin
)
);
}
protected static function ntrim($str)
{
if (is_null($str))
return $str;
$s = trim($str);
if (!$s)
return null;
return $s;
}
}

View File

@@ -13,8 +13,14 @@ $labels['form.enabled'] = 'Enabled';
// Label
$labels['form.label'] = 'Label';
// Server URI
$labels['form.server']='Server URI';
// Server host name
$labels['form.host']='Server host name';
// Secure connection (SSL/TLS)
$labels['form.secure']='Secure connection (SSL/TLS)';
// Port
$labels['form.port']='Port';
// Username
$labels['form.username'] = 'Username';

32
localization/ru_RU.inc Normal file
View File

@@ -0,0 +1,32 @@
<?php
/*
* Localization file for ident_switch plugin
*/
$labels = array();
// IMAP
$labels['form.caption'] = 'IMAP';
// Enabled
$labels['form.enabled'] = 'Включено';
// Label
$labels['form.label'] = 'Название';
// Server host name
$labels['form.host'] = 'Адрес сервера';
// Secure connection (SSL/TLS)
$labels['form.secure'] = 'Безопасное соединение (SSL/TLS)';
// Port
$labels['form.port'] = 'Порт';
// Username
$labels['form.username'] = 'Имя пользователя';
// Passwotrd
$labels['form.password'] = 'Пароль';
// Folder hierarchy delimiter
$labels['form.delimiter'] = 'Разделитель в иерархии папок';

View File

@@ -1,15 +0,0 @@
/***************************************************************************
* This file is part of Roundcube "identities_imap" plugin.
*
* Your are not allowed to distribute this file or parts of it.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Copyright (c) 2012 - 2014 Roland 'Rosali' Liebl - all rights reserved
* dev-team [at] myroundcube [dot] com
* http://myroundcube.com
***************************************************************************/
#accounts{position:absolute; top:63px; left:18px;}.remotehint{z-index:-1; position:absolute; top:7px; margin-left:auto; left:210px; width:400px; border-radius:5px; padding:4px; -moz-border-radius:5px; border:1px solid #DEEEFC; background:#F2F9FF; text-align:center; color:#3F70BA; display:inline;}.classic{top:2px;}

View File

@@ -1,15 +0,0 @@
/***************************************************************************
* This file is part of Roundcube "identities_imap" plugin.
*
* Your are not allowed to distribute this file or parts of it.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Copyright (c) 2012 - 2014 Roland 'Rosali' Liebl - all rights reserved
* dev-team [at] myroundcube [dot] com
* http://myroundcube.com
***************************************************************************/
select.deco{height:18px; font-size:12px; border-radius:3px; -moz-border-radius:3px; -webkit-border-radius:3px; color:#fff; background:#444; border:1px solid #ababab;}.remotehint{z-index:1; position:absolute; top:1px; margin-left:auto; left:50%; margin-left:-200px; width:400px; border-radius:5px; padding:4px; -moz-border-radius:5px; border:1px solid #DEEEFC; background:#F2F9FF; text-align:center; color:#3F70BA; display:inline;}

View File

@@ -1,15 +0,0 @@
/***************************************************************************
* This file is part of Roundcube "##PLUGIN##" plugin.
*
* Your are not allowed to distribute this file or parts of it.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Copyright (c) 2012 - ##YEAR## Roland 'Rosali' Liebl - all rights reserved
* dev-team [at] myroundcube [dot] com
* http://myroundcube.com
***************************************************************************/
select.deco{}#taskbar .remotehint{position:absolute; top:52px; left:50%; margin-left:-200px; width:400px; padding:0px; border:1px solid #DEEEFC; background-color:#F2F9FF; text-align:center; font-size:10px; color:#3F70BA;}