- Apply fixes from trunk up to r5401

release-0.7
alecpl 13 years ago
parent 69cb80b059
commit 51f7a5b2a0

@ -1,6 +1,12 @@
CHANGELOG Roundcube Webmail
===========================
- Make email recipients separator configurable
- Fix so folders with \Noinferiors attribute aren't listed in parent selector
- Fix handling of curly brackets in URLs (#1488168)
- Fix handling of dates (birthday/anniversary) in contact data (#1488147)
- Fix error on opening searched LDAP contact (#1488144)
- Fix redundant line break in flowed format (#1488146)
- Fix IDN address validation issue (#1488137)
- Fix JS error when dst_active checkbox doesn't exist (#1488133)
- Autocomplete LDAP records when adding contacts from mail (#1488073)

@ -5,7 +5,7 @@
| Main configuration file |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2010, The Roundcube Dev Team |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
+-----------------------------------------------------------------------+
@ -460,6 +460,9 @@ $rcmail_config['spellcheck_ignore_nums'] = false;
// Makes that words with symbols will be ignored (e.g. g@@gle)
$rcmail_config['spellcheck_ignore_syms'] = false;
// Use this char/string to separate recipients when composing a new message
$rcmail_config['recipients_separator'] = ',';
// don't let users set pagesize to more than this value if set
$rcmail_config['max_pagesize'] = 200;

@ -1018,15 +1018,15 @@ function rcube_strtotime($date)
* Convert the given date to a human readable form
* This uses the date formatting properties from config
*
* @param mixed Date representation (string or timestamp)
* @param mixed Date representation (string or timestamp)
* @param string Date format to use
* @param bool Enables date convertion according to user timezone
*
* @return string Formatted date string
*/
function format_date($date, $format=NULL)
function format_date($date, $format=NULL, $convert=true)
{
global $RCMAIL, $CONFIG;
$ts = NULL;
if (!empty($date))
$ts = rcube_strtotime($date);
@ -1034,23 +1034,29 @@ function format_date($date, $format=NULL)
if (empty($ts))
return '';
// get user's timezone offset
$tz = $RCMAIL->config->get_timezone();
// convert time to user's timezone
$timestamp = $ts - date('Z', $ts) + ($tz * 3600);
if ($convert) {
// get user's timezone offset
$tz = $RCMAIL->config->get_timezone();
// get current timestamp in user's timezone
$now = time(); // local time
$now -= (int)date('Z'); // make GMT time
$now += ($tz * 3600); // user's time
$now_date = getdate($now);
// convert time to user's timezone
$timestamp = $ts - date('Z', $ts) + ($tz * 3600);
$today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
$week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
// get current timestamp in user's timezone
$now = time(); // local time
$now -= (int)date('Z'); // make GMT time
$now += ($tz * 3600); // user's time
}
else {
$now = time();
$timestamp = $ts;
}
// define date format depending on current time
if (!$format) {
$now_date = getdate($now);
$today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
$week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) {
$format = $RCMAIL->config->get('date_today', $RCMAIL->config->get('time_format', 'H:i'));
$today = true;
@ -1226,7 +1232,7 @@ function rcmail_mailbox_select($p = array())
if ($p['noselection'])
$select->add($p['noselection'], '');
rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p['exceptions']);
rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
return $select;
}
@ -1275,9 +1281,9 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
$path .= $prefix.$currentFolder;
if (!isset($arrFolders[$currentFolder])) {
// Check \Noselect option (if options are in cache)
if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
$virtual = in_array('\\Noselect', $opts);
// Check \Noselect attribute (if attributes are in cache)
if (!$virtual && ($attrs = $RCMAIL->imap->mailbox_attributes($path))) {
$virtual = in_array('\\Noselect', $attrs);
}
$arrFolders[$currentFolder] = array(
@ -1396,30 +1402,40 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
* @access private
* @return string
*/
function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $exceptions=array())
function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $opts=array())
{
global $RCMAIL;
$out = '';
foreach ($arrFolders as $key => $folder) {
if (empty($exceptions) || !in_array($folder['id'], $exceptions)) {
if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
$foldername = rcube_label($folder_class);
else {
$foldername = $folder['name'];
// shorten the folder name to a given length
if ($maxlength && $maxlength>1)
$foldername = abbreviate_string($foldername, $maxlength);
}
$select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
// skip exceptions (and its subfolders)
if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
continue;
}
else if ($nestLevel)
// skip folders in which it isn't possible to create subfolders
if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id']))
&& in_array('\\Noinferiors', $attrs)
) {
continue;
}
if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
$foldername = rcube_label($folder_class);
else {
$foldername = $folder['name'];
// shorten the folder name to a given length
if ($maxlength && $maxlength>1)
$foldername = abbreviate_string($foldername, $maxlength);
}
$select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
if (!empty($folder['folders']))
$out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
$select, $realnames, $nestLevel+1, $exceptions);
$select, $realnames, $nestLevel+1, $opts);
}
return $out;

@ -594,7 +594,6 @@ class rcmail
return;
$this->imap = new rcube_imap();
$this->imap->debug_level = $this->config->get('debug_level');
$this->imap->skip_deleted = $this->config->get('skip_deleted');
// enable caching of imap data

@ -41,7 +41,6 @@ class rcube_contacts extends rcube_addressbook
private $user_id = 0;
private $filter = null;
private $result = null;
private $name;
private $cache;
private $table_cols = array('name', 'email', 'firstname', 'surname');
private $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'nickname',
@ -50,6 +49,7 @@ class rcube_contacts extends rcube_addressbook
// public properties
public $primary_key = 'contact_id';
public $name;
public $readonly = false;
public $groups = true;
public $undelete = true;

@ -32,7 +32,6 @@
*/
class rcube_imap
{
public $debug_level = 1;
public $skip_deleted = false;
public $page_size = 10;
public $list_page = 1;
@ -317,6 +316,19 @@ class rcube_imap
}
/**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if IMAP conversation should be logged
* @access public
*/
function set_debug($dbg = true)
{
$this->options['debug'] = $dbg;
$this->conn->setDebug($dbg, array($this, 'debug_handler'));
}
/**
* Set default message charset
*
@ -3075,7 +3087,19 @@ class rcube_imap
*/
function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
{
// @TODO: caching
$cache_key = $root.':'.$name;
if (!empty($filter)) {
$cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter));
}
$cache_key .= ':'.$rights;
$cache_key = 'mailboxes.list.'.md5($cache_key);
// get cached folder list
$a_mboxes = $this->get_cache($cache_key);
if (is_array($a_mboxes)) {
return $a_mboxes;
}
// Give plugins a chance to provide a list of mailboxes
$data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
@ -3097,6 +3121,11 @@ class rcube_imap
array_unshift($a_mboxes, 'INBOX');
}
// cache folder attributes
if ($root == '' && $name == '*' && empty($filter)) {
$this->update_cache('mailboxes.attributes', $this->conn->data['LIST']);
}
// filter folders list according to rights requirements
if ($rights && $this->get_capability('ACL')) {
$a_folders = $this->filter_rights($a_folders, $rights);
@ -3107,6 +3136,9 @@ class rcube_imap
$a_mboxes = $this->_sort_mailbox_list($a_mboxes);
}
// write mailboxlist to cache
$this->update_cache($cache_key, $a_mboxes);
return $a_mboxes;
}
@ -3438,30 +3470,29 @@ class rcube_imap
/**
* Gets folder options from LIST response, e.g. \Noselect, \Noinferiors
* Gets folder attributes from LIST response, e.g. \Noselect, \Noinferiors
*
* @param string $mailbox Folder name
* @param bool $force Set to True if options should be refreshed
* Options are available after LIST command only
* @param bool $force Set to True if attributes should be refreshed
*
* @return array Options list
*/
function mailbox_options($mailbox, $force=false)
function mailbox_attributes($mailbox, $force=false)
{
if ($mailbox == 'INBOX') {
return array();
// get attributes directly from LIST command
if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$mailbox])) {
$opts = $this->conn->data['LIST'][$mailbox];
}
if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mailbox])) {
if ($force) {
$this->conn->listMailboxes('', $mailbox);
}
else {
return array();
}
// get cached folder attributes
else if (!$force) {
$opts = $this->get_cache('mailboxes.attributes');
$opts = $opts[$mailbox];
}
$opts = $this->conn->data['LIST'][$mailbox];
if (!is_array($opts)) {
$this->conn->listMailboxes('', $mailbox);
$opts = $this->conn->data['LIST'][$mailbox];
}
return is_array($opts) ? $opts : array();
}
@ -3544,17 +3575,17 @@ class rcube_imap
}
}
$options['name'] = $mailbox;
$options['options'] = $this->mailbox_options($mailbox, true);
$options['namespace'] = $this->mailbox_namespace($mailbox);
$options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
$options['special'] = in_array($mailbox, $this->default_folders);
$options['name'] = $mailbox;
$options['attributes'] = $this->mailbox_attributes($mailbox, true);
$options['namespace'] = $this->mailbox_namespace($mailbox);
$options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
$options['special'] = in_array($mailbox, $this->default_folders);
// Set 'noselect' and 'norename' flags
if (is_array($options['options'])) {
foreach ($options['options'] as $opt) {
$opt = strtolower($opt);
if ($opt == '\noselect' || $opt == '\nonexistent') {
if (is_array($options['attributes'])) {
foreach ($options['attributes'] as $attrib) {
$attrib = strtolower($attrib);
if ($attrib == '\noselect' || $attrib == '\nonexistent') {
$options['noselect'] = true;
}
}

@ -2242,12 +2242,29 @@ class rcube_imap_generic
list($code, $response) = $this->execute($subscribed ? 'LSUB' : 'LIST', $args);
if ($code == self::ERROR_OK) {
$folders = array();
while ($this->tokenizeResponse($response, 1) == '*') {
$cmd = strtoupper($this->tokenizeResponse($response, 1));
$folders = array();
$last = 0;
$pos = 0;
$response .= "\r\n";
while ($pos = strpos($response, "\r\n", $pos+1)) {
// literal string, not real end-of-command-line
if ($response[$pos-1] == '}') {
continue;
}
$line = substr($response, $last, $pos - $last);
$last = $pos + 2;
if (!preg_match('/^\* (LIST|LSUB|STATUS) /i', $line, $m)) {
continue;
}
$cmd = strtoupper($m[1]);
$line = substr($line, strlen($m[0]));
// * LIST (<options>) <delimiter> <mailbox>
if ($cmd == 'LIST' || $cmd == 'LSUB') {
list($opts, $delim, $mailbox) = $this->tokenizeResponse($response, 3);
list($opts, $delim, $mailbox) = $this->tokenizeResponse($line, 3);
// Add to result array
if (!$lstatus) {
@ -2258,31 +2275,21 @@ class rcube_imap_generic
}
// Add to options array
if (!empty($opts)) {
if (empty($this->data['LIST'][$mailbox]))
$this->data['LIST'][$mailbox] = $opts;
else
$this->data['LIST'][$mailbox] = array_unique(array_merge(
$this->data['LIST'][$mailbox], $opts));
}
if (empty($this->data['LIST'][$mailbox]))
$this->data['LIST'][$mailbox] = $opts;
else if (!empty($opts))
$this->data['LIST'][$mailbox] = array_unique(array_merge(
$this->data['LIST'][$mailbox], $opts));
}
// * STATUS <mailbox> (<result>)
else if ($cmd == 'STATUS') {
list($mailbox, $status) = $this->tokenizeResponse($response, 2);
list($mailbox, $status) = $this->tokenizeResponse($line, 2);
for ($i=0, $len=count($status); $i<$len; $i += 2) {
list($name, $value) = $this->tokenizeResponse($status, 2);
$folders[$mailbox][$name] = $value;
}
}
// other untagged response line, skip it
else {
$response = ltrim($response);
if (($position = strpos($response, "\n")) !== false)
$response = substr($response, $position+1);
else
$response = '';
}
}
return $folders;
@ -3392,15 +3399,10 @@ class rcube_imap_generic
// String atom, number, NIL, *, %
default:
// empty or one character
if ($str === '') {
// empty string
if ($str === '' || $str === null) {
break 2;
}
if (strlen($str) < 2) {
$result[] = $str;
$str = '';
break;
}
// excluded chars: SP, CTL, ), [, ]
if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) {

@ -1341,6 +1341,18 @@ class rcube_ldap extends rcube_addressbook
}
/**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if LDAP commands should be logged
* @access public
*/
function set_debug($dbg = true)
{
$this->debug = $dbg;
}
/**
* Quotes attribute value string
*

@ -35,16 +35,16 @@
*/
class rcube_mdb2
{
var $db_dsnw; // DSN for write operations
var $db_dsnr; // DSN for read operations
var $db_connected = false; // Already connected ?
var $db_mode = ''; // Connection mode
var $db_handle = 0; // Connection handle
var $db_error = false;
var $db_error_msg = '';
public $db_dsnw; // DSN for write operations
public $db_dsnr; // DSN for read operations
public $db_connected = false; // Already connected ?
public $db_mode = ''; // Connection mode
public $db_handle = 0; // Connection handle
public $db_error = false;
public $db_error_msg = '';
private $debug_mode = false;
private $write_failure = false;
private $conn_failure = false;
private $a_query_results = array('dummy');
private $last_res_id = 0;
private $tables;
@ -58,7 +58,7 @@ class rcube_mdb2
*/
function __construct($db_dsnw, $db_dsnr='', $pconn=false)
{
if ($db_dsnr == '')
if (empty($db_dsnr))
$db_dsnr = $db_dsnw;
$this->db_dsnw = $db_dsnw;
@ -122,30 +122,33 @@ class rcube_mdb2
*/
function db_connect($mode)
{
// previous connection failed, don't attempt to connect again
if ($this->conn_failure) {
return;
}
// no replication
if ($this->db_dsnw == $this->db_dsnr) {
$mode = 'w';
}
// Already connected
if ($this->db_connected) {
// connected to read-write db, current connection is ok
if ($this->db_mode == 'w' && !$this->write_failure)
return;
// no replication, current connection is ok for read and write
if (empty($this->db_dsnr) || $this->db_dsnw == $this->db_dsnr) {
$this->db_mode = 'w';
// connected to db with the same or "higher" mode
if ($this->db_mode == 'w' || $this->db_mode == $mode) {
return;
}
// Same mode, current connection is ok
if ($this->db_mode == $mode)
return;
}
$dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw;
$this->db_handle = $this->dsn_connect($dsn);
$this->db_handle = $this->dsn_connect($dsn);
$this->db_connected = !PEAR::isError($this->db_handle);
if ($this->db_connected)
$this->db_mode = $mode;
$this->db_mode = $mode;
else
$this->conn_failure = true;
}
@ -256,10 +259,6 @@ class rcube_mdb2
// Read or write ?
$mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w';
// don't event attempt to connect if previous write-operation failed
if ($this->write_failure && $mode == 'w')
return false;
$this->db_connect($mode);
// check connection before proceeding
@ -284,7 +283,7 @@ class rcube_mdb2
raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
$result = false;
}
else {
@ -293,10 +292,6 @@ class rcube_mdb2
}
}
// remember that write-operation failed
if ($mode == 'w' && ($result === false || PEAR::isError($result)))
$this->write_failure = true;
// add result, even if it's an error
return $this->_add_result($result);
}
@ -447,7 +442,7 @@ class rcube_mdb2
if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
return $result;
}
return null;
}
@ -530,7 +525,7 @@ class rcube_mdb2
*/
function now()
{
switch($this->db_provider) {
switch ($this->db_provider) {
case 'mssql':
case 'sqlsrv':
return "getdate()";

@ -39,7 +39,7 @@ class rcube_string_replacer
// Support unicode/punycode in top-level domain part
$utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})';
$url1 = '.:;,';
$url2 = 'a-z0-9%=#@+?&\\/_~\\[\\]-';
$url2 = 'a-z0-9%=#@+?&\\/_~\\[\\]{}-';
$this->link_pattern = "/([\w]+:\/\/|\Wwww\.)($utf_domain([$url1]?[$url2]+)*)/i";
$this->mailto_pattern = "/("

@ -20,7 +20,7 @@
function rcube_webmail()
{
this.env = {};
this.env = { recipients_separator:',', recipients_delimiter:', ' };
this.labels = {};
this.buttons = {};
this.buttons_sel = {};
@ -2926,6 +2926,8 @@ function rcube_webmail()
this.init_address_input_events = function(obj, props)
{
this.env.recipients_delimiter = this.env.recipients_separator + ' ';
obj[bw.ie || bw.safari || bw.chrome ? 'keydown' : 'keypress'](function(e) { return ref.ksearch_keydown(e, this, props); })
.attr('autocomplete', 'off');
};
@ -3590,13 +3592,13 @@ function rcube_webmail()
// insert all members of a group
if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].id) {
insert += this.env.contacts[id].name + ', ';
insert += this.env.contacts[id].name + this.env.recipients_delimiter;
this.group2expand = $.extend({}, this.env.contacts[id]);
this.group2expand.input = this.ksearch_input;
this.http_request('mail/group-expand', '_source='+urlencode(this.env.contacts[id].source)+'&_gid='+urlencode(this.env.contacts[id].id), false);
}
else if (typeof this.env.contacts[id] === 'string') {
insert = this.env.contacts[id] + ', ';
insert = this.env.contacts[id] + this.env.recipients_delimiter;
trigger = true;
}
@ -3633,7 +3635,7 @@ function rcube_webmail()
// get string from current cursor pos to last comma
var cpos = this.get_caret_pos(this.ksearch_input),
p = inp_value.lastIndexOf(',', cpos-1),
p = inp_value.lastIndexOf(this.env.recipients_separator, cpos-1),
q = inp_value.substring(p+1, cpos),
min = this.env.autocomplete_min_length,
ac = this.ksearch_data;

@ -619,7 +619,7 @@ function rcmail_contact_form($form, $record, $attrib = null)
$RCMAIL->output->set_env('month_names', $month_names);
}
$colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
$val = format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'));
$val = format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
}
$val = rcmail_get_edit_field($col, $val, $colprop, $colprop['type']);
@ -728,7 +728,7 @@ function rcmail_contact_photo($attrib)
function rcmail_format_date_col($val)
{
global $RCMAIL;
return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'));
return format_date($val, $RCMAIL->config->get('date_format', 'Y-m-d'), false);
}
@ -758,9 +758,12 @@ function rcmail_get_cids()
foreach ($cid as $id) {
// if _source is not specified we'll find it from decoded ID
if (!$got_source) {
list ($c, $s) = explode('-', $id, 2);
if (strlen($s)) {
$result[(string)$s][] = $c;
if ($sep = strrpos($id, '-')) {
$contact_id = substr($id, 0, $sep);
$source_id = substr($id, $sep+1);
if (strlen($source_id)) {
$result[(string)$source_id][] = $contact_id;
}
}
}
else {

@ -32,7 +32,8 @@ if ($RCMAIL->action == 'group-expand') {
$members[] = format_email_recipient($email, $sql_arr['name']);
}
$OUTPUT->command('replace_group_recipients', $gid, join(', ', $members));
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
$OUTPUT->command('replace_group_recipients', $gid, join($separator, array_unique($members)));
}
$OUTPUT->send();
@ -70,8 +71,8 @@ if (!empty($book_types) && strlen($search)) {
if ($email_cnt > 1 && stripos($contact, $search) === false) {
continue;
}
// when we've got more than one book, we need to skip duplicates
if ($books_num == 1 || !in_array($contact, $contacts)) {
// skip duplicates
if (!in_array($contact, $contacts)) {
$contacts[] = $contact;
if (count($contacts) >= $MAXNUM)
break 2;

@ -5,7 +5,7 @@
| program/steps/mail/compose.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@ -122,8 +122,9 @@ if (!empty($CONFIG['drafts_mbox'])) {
}
// set current mailbox in client environment
$OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name());
$OUTPUT->set_env('sig_above', $CONFIG['sig_above']);
$OUTPUT->set_env('top_posting', $CONFIG['top_posting']);
$OUTPUT->set_env('sig_above', $RCMAIL->config->get('sig_above', false));
$OUTPUT->set_env('top_posting', $RCMAIL->config->get('top_posting', false));
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
// get reference message and set compose mode
if ($msg_uid = $_SESSION['compose']['param']['draft_uid']) {
@ -324,6 +325,7 @@ else if (count($MESSAGE->identities)) {
// Set other headers
$a_recipients = array();
$parts = array('to', 'cc', 'bcc', 'replyto', 'followupto');
$separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' ';
foreach ($parts as $header) {
$fvalue = '';
@ -367,7 +369,7 @@ foreach ($parts as $header) {
if ($v = $MESSAGE->headers->to)
$fvalue .= $v;
if ($v = $MESSAGE->headers->cc)
$fvalue .= (!empty($fvalue) ? ', ' : '') . $v;
$fvalue .= (!empty($fvalue) ? $separator : '') . $v;
}
}
else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) {
@ -410,7 +412,7 @@ foreach ($parts as $header) {
}
}
$fvalue = implode(', ', $fvalue);
$fvalue = implode($separator, $fvalue);
}
$MESSAGE->compose[$header] = $fvalue;

@ -766,7 +766,7 @@ function rcmail_plain_body($body, $flowed=false)
// previous line is flowed?
if (isset($body[$last]) && $body[$n]
&& $last != $last_sig
&& $last !== $last_sig
&& $body[$last][strlen($body[$last])-1] == ' '
) {
$body[$last] .= $body[$n];

@ -5,7 +5,7 @@
| program/steps/mail/sendmail.inc |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2010, The Roundcube Dev Team |
| Copyright (C) 2005-2011, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@ -138,22 +138,30 @@ function rcmail_fix_emoticon_paths(&$mime_message)
return $body;
}
// parse email address input (and count addresses)
/**
* Parse and cleanup email address input (and count addresses)
*
* @param string Address input
* @param boolean Do count recipients (saved in global $RECIPIENT_COUNT)
* @param boolean Validate addresses (errors saved in global $EMAIL_FORMAT_ERROR)
* @return string Canonical recipients string separated by comma
*/
function rcmail_email_input_format($mailto, $count=false, $check=true)
{
global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT;
// simplified email regexp, supporting quoted local part
$email_regexp = '(\S+|("[^"]+"))@\S+';
$regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
$replace = array(', ', ', ', '', ',', '\\1 \\2');
$delim = trim($RCMAIL->config->get('recipients_separator', ','));
$regexp = array("/[,;$delim]\s*[\r\n]+/", '/[\r\n]+/', "/[,;$delim]\s*\$/m", '/;/', '/(\S{1})(<'.$email_regexp.'>)/U');
$replace = array($delim.' ', ', ', '', $delim, '\\1 \\2');
// replace new lines and strip ending ', ', make address input more valid
$mailto = trim(preg_replace($regexp, $replace, $mailto));
$result = array();
$items = rcube_explode_quoted_string(',', $mailto);
$items = rcube_explode_quoted_string($delim, $mailto);
foreach($items as $item) {
$item = trim($item);
@ -168,16 +176,9 @@ function rcmail_email_input_format($mailto, $count=false, $check=true)
// address with name (handle name)
} else if (preg_match('/<*'.$email_regexp.'>*$/', $item, $matches)) {
$address = $matches[0];
$name = str_replace($address, '', $item);
$name = trim($name);
if ($name && ($name[0] != '"' || $name[strlen($name)-1] != '"')
&& preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
$name = '"'.addcslashes($name, '"').'"';
}
$name = trim(str_replace($address, '', $item), '" ');
$address = rcube_idn_to_ascii(trim($address, '<>'));
$address = '<' . $address . '>';
$result[] = $name.' '.$address;
$result[] = format_email_recipient($address, $name);
$item = $address;
} else if (trim($item)) {
continue;

@ -119,7 +119,8 @@ function rcmail_folder_form($attrib)
'realnames' => false,
'maxlength' => 150,
'unsubscribed' => true,
'exceptions' => array($mbox_imap),
'skip_noinferiors' => true,
'exceptions' => array($mbox_imap),
));
$form['props']['fieldsets']['location']['content']['path'] = array(

@ -283,8 +283,8 @@ function rcube_subscription_form($attrib)
}
if (!$protected) {
$opts = $IMAP->mailbox_options($folder['id']);
$noselect = in_array('\\Noselect', $opts);
$attrs = $IMAP->mailbox_attributes($folder['id']);
$noselect = in_array('\\Noselect', $attrs);
}
$disabled = (($protected && $subscribed) || $noselect);

Loading…
Cancel
Save