Skip to content

Commit

Permalink
Merge branch 'master' of github.com:roundcube/roundcubemail
Browse files Browse the repository at this point in the history
  • Loading branch information
thomascube committed Sep 17, 2012
2 parents 99d9f50 + 6898b42 commit 8f098e8
Show file tree
Hide file tree
Showing 30 changed files with 414 additions and 74 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG Roundcube Webmail
===========================

- List related text/html part as attachment in plain text mode (#1488677)
- Use IMAP BINARY (RFC3516) extension to fetch message/part bodies
- Fix folder creation under public namespace root (#1488665)
- Fix so "Edit as new" on draft creates a new message (#1488687)
- Fix invalid error message on deleting mail from read only folder (#1488694)
- Fix error where session wasn't updated after folder rename/delete (#1488692)
- Replace data URIs of images (pasted in HTML editor) with inline attachments (#1488502)
- Fix PLAIN authentication for some IMAP servers (#1488674)
- Fix encoding vCard file when contains PHOTO;ENCODING=b (#1488683)
- Fix focus issue in IE when selecting message row (#1488620)
Expand Down
12 changes: 10 additions & 2 deletions installer/check.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@
'suhosin.session.encrypt' => 0,
'magic_quotes_runtime' => 0,
'magic_quotes_sybase' => 0,
'date.timezone' => '-NOTEMPTY-',
);

$optional_checks = array(
// required for utils/modcss.inc, should we require this?
'allow_url_fopen' => 1,
'date.timezone' => '-NOTEMPTY-',
);

$source_urls = array(
Expand Down Expand Up @@ -171,7 +171,15 @@
$status = ini_get($var);
if ($val === '-NOTEMPTY-') {
if (empty($status)) {
$RCI->fail($var, "cannot be empty and needs to be set");
$RCI->fail($var, "empty value detected");
} else if ($var == 'date.timezone') {
try {
$tz = new DateTimeZone($status);
$RCI->pass($var);
}
catch (Exception $e) {
$RCI->fail($var, "invalid value detected: $status");
}
} else {
$RCI->pass($var);
}
Expand Down
10 changes: 9 additions & 1 deletion plugins/password/config.inc.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ $rcmail_config['password_db_dsn'] = '';
// The query can contain the following macros that will be expanded as follows:
// %p is replaced with the plaintext new password
// %c is replaced with the crypt version of the new password, MD5 if available
// otherwise DES.
// otherwise DES. More hash function can be enabled using the password_crypt_hash
// configuration parameter.
// %D is replaced with the dovecotpw-crypted version of the new password
// %o is replaced with the password before the change
// %n is replaced with the hashed version of the new password
Expand All @@ -51,6 +52,13 @@ $rcmail_config['password_db_dsn'] = '';
// Default: "SELECT update_passwd(%c, %u)"
$rcmail_config['password_query'] = 'SELECT update_passwd(%c, %u)';

// By default the crypt() function which is used to create the '%c'
// parameter uses the md5 algorithm. To use different algorithms
// you can choose between: des, md5, blowfish, sha256, sha512.
// Before using other hash functions than des or md5 please make sure
// your operating system supports the other hash functions.
$rcmail_config['password_crypt_hash'] = 'md5';

// By default domains in variables are using unicode.
// Enable this option to use punycoded names
$rcmail_config['password_idn_ascii'] = false;
Expand Down
41 changes: 33 additions & 8 deletions plugins/password/drivers/sql.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,38 @@ function save($curpass, $passwd)
// crypted password
if (strpos($sql, '%c') !== FALSE) {
$salt = '';
if (CRYPT_MD5) {
// Always use eight salt characters for MD5 (#1488136)
$len = 8;
} else if (CRYPT_STD_DES) {
$len = 2;
} else {
return PASSWORD_CRYPT_ERROR;

if (!($crypt_hash = $rcmail->config->get('password_crypt_hash')))
{
if (CRYPT_MD5)
$crypt_hash = 'md5';
else if (CRYPT_STD_DES)
$crypt_hash = 'des';
}

switch ($crypt_hash)
{
case 'md5':
$len = 8;
$salt_hashindicator = '$1$';
break;
case 'des':
$len = 2;
break;
case 'blowfish':
$len = 22;
$salt_hashindicator = '$2a$';
break;
case 'sha256':
$len = 16;
$salt_hashindicator = '$5$';
break;
case 'sha512':
$len = 16;
$salt_hashindicator = '$6$';
break;
default:
return PASSWORD_CRYPT_ERROR;
}

//Restrict the character set used as salt (#1488136)
Expand All @@ -55,7 +80,7 @@ function save($curpass, $passwd)
$salt .= $seedchars[rand(0, 63)];
}

$sql = str_replace('%c', $db->quote(crypt($passwd, CRYPT_MD5 ? '$1$'.$salt.'$' : $salt)), $sql);
$sql = str_replace('%c', $db->quote(crypt($passwd, $salt_hashindicator ? $salt_hashindicator .$salt.'$' : $salt)), $sql);
}

// dovecotpw
Expand Down
8 changes: 4 additions & 4 deletions program/include/rcmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -1774,10 +1774,7 @@ public function display_server_error($fallback = null, $fallback_args = null)
$err_code = $this->storage->get_error_code();
$res_code = $this->storage->get_response_code();

if ($err_code < 0) {
$this->output->show_message('storageerror', 'error');
}
else if ($res_code == rcube_storage::NOPERM) {
if ($res_code == rcube_storage::NOPERM) {
$this->output->show_message('errornoperm', 'error');
}
else if ($res_code == rcube_storage::READONLY) {
Expand All @@ -1792,6 +1789,9 @@ public function display_server_error($fallback = null, $fallback_args = null)
$this->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
}
}
else if ($err_code < 0) {
$this->output->show_message('storageerror', 'error');
}
else if ($fallback) {
$this->output->show_message($fallback, 'error', $fallback_args);
}
Expand Down
2 changes: 1 addition & 1 deletion program/include/rcube_addressbook.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ public static function compose_display_name($contact, $full_email = false)
$fn = $contact['name'];

if (!$fn) // default display name composition according to vcard standard
$fn = join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])));
$fn = trim(join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix']))));

// use email address part for name
$email = is_array($contact['email']) ? $contact['email'][0] : $contact['email'];
Expand Down
25 changes: 19 additions & 6 deletions program/include/rcube_charset.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static function error_handler($errno, $errstr)
* Sometimes charset string is malformed, there are also charset aliases
* but we need strict names for charset conversion (specially utf8 class)
*
* @param string Input charset name
* @param string $input Input charset name
*
* @return string The validated charset name
*/
Expand Down Expand Up @@ -176,9 +176,10 @@ public static function convert($str, $from, $to = null)
{
static $iconv_options = null;
static $mbstring_list = null;
static $mbstring_sch = null;
static $conv = null;

$to = empty($to) ? strtoupper(RCMAIL_CHARSET) : self::parse_charset($to);
$to = empty($to) ? strtoupper(RCMAIL_CHARSET) : $to;
$from = self::parse_charset($from);

// It is a common case when UTF-16 charset is used with US-ASCII content (#1488654)
Expand Down Expand Up @@ -221,6 +222,7 @@ public static function convert($str, $from, $to = null)

if ($mbstring_list === null) {
if (extension_loaded('mbstring')) {
$mbstring_sch = mb_substitute_character();
$mbstring_list = mb_list_encodings();
$mbstring_list = array_map('strtoupper', $mbstring_list);
}
Expand All @@ -229,14 +231,25 @@ public static function convert($str, $from, $to = null)
// convert charset using mbstring module
if ($mbstring_list !== null) {
$aliases['WINDOWS-1257'] = 'ISO-8859-13';
// it happens that mbstring supports ASCII but not US-ASCII
if (($from == 'US-ASCII' || $to == 'US-ASCII') && !in_array('US-ASCII', $mbstring_list)) {
$aliases['US-ASCII'] = 'ASCII';
}

$mb_from = $aliases[$from] ? $aliases[$from] : $from;
$mb_to = $aliases[$to] ? $aliases[$to] : $to;

// return if encoding found, string matches encoding and convert succeeded
if (in_array($mb_from, $mbstring_list) && in_array($mb_to, $mbstring_list)) {
if (mb_check_encoding($str, $mb_from) && ($out = mb_convert_encoding($str, $mb_to, $mb_from))) {
return $out;
if (mb_check_encoding($str, $mb_from)) {
// Do the same as //IGNORE with iconv
mb_substitute_character('none');
$out = mb_convert_encoding($str, $mb_to, $mb_from);
mb_substitute_character($mbstring_sch);

if ($out !== false) {
return $out;
}
}
}
}
Expand Down Expand Up @@ -646,14 +659,14 @@ public static function detect($string, $failover='')
return $failover;
}

// FIXME: the order is important, because sometimes
// FIXME: the order is important, because sometimes
// iso string is detected as euc-jp and etc.
$enc = array(
'UTF-8', 'SJIS', 'BIG5', 'GB2312',
'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4',
'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9',
'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16',
'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R',
'WINDOWS-1252', 'WINDOWS-1251', 'EUC-JP', 'EUC-TW', 'KOI8-R',
'ISO-2022-KR', 'ISO-2022-JP'
);

Expand Down
18 changes: 12 additions & 6 deletions program/include/rcube_db.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,19 @@ protected function _query($query, $offset, $numrows, $params)
$idx = 0;

while ($pos = strpos($query, '?', $pos)) {
$val = $this->quote($params[$idx++]);
unset($params[$idx-1]);
$query = substr_replace($query, $val, $pos, 1);
$pos += strlen($val);
if ($query[$pos+1] == '?') { // skip escaped ?
$pos += 2;
}
else {
$val = $this->quote($params[$idx++]);
unset($params[$idx-1]);
$query = substr_replace($query, $val, $pos, 1);
$pos += strlen($val);
}
}

$query = rtrim($query, ';');
// replace escaped ? back to normal
$query = rtrim(strtr($query, array('??' => '?')), ';');

$this->debug($query);

Expand Down Expand Up @@ -591,7 +597,7 @@ public function quote($input, $type = null)
'integer' => PDO::PARAM_INT,
);
$type = isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
return $this->dbh->quote($input, $type);
return strtr($this->dbh->quote($input, $type), array('?' => '??')); // escape ?
}

return 'NULL';
Expand Down
15 changes: 9 additions & 6 deletions program/include/rcube_imap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,12 @@ protected function search_index($folder, $criteria='ALL', $charset=NULL, $sort_f
$criteria = 'UNDELETED '.$criteria;
}

// unset CHARSET if criteria string is ASCII, this way
// SEARCH won't be re-sent after "unsupported charset" response
if ($charset && $charset != 'US-ASCII' && is_ascii($criteria)) {
$charset = 'US-ASCII';
}

if ($this->threading) {
$threads = $this->conn->thread($folder, $this->threading, $criteria, true, $charset);

Expand Down Expand Up @@ -1465,7 +1471,7 @@ protected function search_index($folder, $criteria='ALL', $charset=NULL, $sort_f
}

$messages = $this->conn->search($folder,
($charset ? "CHARSET $charset " : '') . $criteria, true);
($charset && $charset != 'US-ASCII' ? "CHARSET $charset " : '') . $criteria, true);

// Error, try with US-ASCII (some servers may support only US-ASCII)
if ($messages->is_error() && $charset && $charset != 'US-ASCII') {
Expand Down Expand Up @@ -3291,11 +3297,8 @@ public function folder_info($folder)
}

// Get folder rights (MYRIGHTS)
if ($acl && !$options['noselect']) {
// skip shared roots
if (!$options['is_root'] || $options['namespace'] == 'personal') {
$options['rights'] = (array)$this->my_rights($folder);
}
if ($acl && ($rights = $this->my_rights($folder))) {
$options['rights'] = $rights;
}

// Set 'norename' flag
Expand Down
15 changes: 11 additions & 4 deletions program/include/rcube_imap_generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -2402,17 +2402,24 @@ function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL,
$mode = 0;
}

// Use BINARY extension when possible (and safe)
$binary = $mode && preg_match('/^[0-9.]+$/', $part) && $this->hasCapability('BINARY');
$fetch_mode = $binary ? 'BINARY' : 'BODY';

// format request
$reply_key = '* ' . $id;
$key = $this->nextTag();
$request = $key . ($is_uid ? ' UID' : '') . " FETCH $id (BODY.PEEK[$part])";
$request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part])";

// send request
if (!$this->putLine($request)) {
$this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
return false;
}

if ($binary) {
$mode = -1;
}

// receive reply line
do {
$line = rtrim($this->readLine(1024));
Expand Down Expand Up @@ -2457,13 +2464,13 @@ function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL,
$prev = '';

while ($bytes > 0) {
$line = $this->readLine(4096);
$line = $this->readLine(8192);

if ($line === NULL) {
break;
}

$len = strlen($line);
$len = strlen($line);

if ($len > $bytes) {
$line = substr($line, 0, $bytes);
Expand Down
7 changes: 6 additions & 1 deletion program/include/rcube_message.php
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,13 @@ private function parse_structure($structure, $recursive = false)
}

// list as attachment as well
if (!empty($mail_part->filename))
if (!empty($mail_part->filename)) {
$this->attachments[] = $mail_part;
}
// list html part as attachment (here the part is most likely inside a multipart/related part)
else if ($this->parse_alternative && ($secondary_type == 'html' && !$this->opt['prefer_html'])) {
$this->attachments[] = $mail_part;
}
}
// part message/*
else if ($primary_type == 'message') {
Expand Down
4 changes: 4 additions & 0 deletions program/include/rcube_result_index.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ public function init($data = null)
for ($i=0, $len=count($data); $i<$len; $i++) {
$data_item = &$data[$i];
if (preg_match('/^ SORT/i', $data_item)) {
// valid response, initialize raw_data for is_error()
$this->raw_data = '';
$data_item = substr($data_item, 5);
break;
}
else if (preg_match('/^ (E?SEARCH)/i', $data_item, $m)) {
// valid response, initialize raw_data for is_error()
$this->raw_data = '';
$data_item = substr($data_item, strlen($m[0]));

if (strtoupper($m[1]) == 'ESEARCH') {
Expand Down
2 changes: 2 additions & 0 deletions program/include/rcube_result_thread.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public function init($data = null)
// ...skip unilateral untagged server responses
for ($i=0, $len=count($data); $i<$len; $i++) {
if (preg_match('/^ THREAD/i', $data[$i])) {
// valid response, initialize raw_data for is_error()
$this->raw_data = '';
$data[$i] = substr($data[$i], 7);
break;
}
Expand Down
Loading

0 comments on commit 8f098e8

Please sign in to comment.