summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2011-04-11 12:24:00 +0000
committeralecpl <alec@alec.pl>2011-04-11 12:24:00 +0000
commitd3105370870a8c51aaeb6a18f561311202da3356 (patch)
tree9b0d50549f35a44d7eb438bd7ad3dfa9ca72d263
parent382b8b1351e1a4598f04ab184cec803b96d7e4b7 (diff)
- Apply fixes from trunk
-rw-r--r--CHANGELOG6
-rw-r--r--plugins/managesieve/localization/pl_PL.inc8
-rw-r--r--program/include/rcube_imap.php13
-rw-r--r--program/include/rcube_imap_generic.php122
-rw-r--r--program/include/rcube_mdb2.php10
-rw-r--r--program/include/rcube_message.php4
-rw-r--r--program/js/app.js17
-rw-r--r--program/lib/html2text.php28
-rw-r--r--program/steps/mail/func.inc63
-rw-r--r--program/steps/settings/save_prefs.inc15
10 files changed, 150 insertions, 136 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 53892d21f..e9437a17e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,12 @@
CHANGELOG Roundcube Webmail
===========================
+- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling
+- Fix bug where some content would cause hang on html2text conversion (#1487863)
+- Improve space-stuffing handling in format=flowed messages (#1487861)
+- Fix bug where some dates would produce SQL error in MySQL (#1487856)
+- Added workaround for some IMAP server with broken STATUS response (#1487859)
+- Fix bug where default_charset was not used for text messages (#1487836)
- Stateless request tokens. No keep-alive necessary on login page (#1487829)
- PEAR::Net_SMTP 1.5.1
- Force names of unique constraints in PostgreSQL DDL
diff --git a/plugins/managesieve/localization/pl_PL.inc b/plugins/managesieve/localization/pl_PL.inc
index e530619a4..1fbe65d5b 100644
--- a/plugins/managesieve/localization/pl_PL.inc
+++ b/plugins/managesieve/localization/pl_PL.inc
@@ -41,10 +41,10 @@ $labels['vacationaddresses'] = 'Lista dodatkowych adresów odbiorców (oddzielon
$labels['vacationreason'] = 'Treść (przyczyna nieobecności):';
$labels['filterset'] = 'Zbiór filtrów';
$labels['filtersetadd'] = 'Dodaj zbiór filtrów';
-$labels['filtersetdel'] = 'Usuń bierzący zbiór filtrów';
-$labels['filtersetact'] = 'Aktywuj bierzący zbiór filtrów';
-$labels['filtersetdeact'] = 'Deaktywuj bierzący zbiór filtrów';
-$labels['filtersetget'] = 'Pobierz bierzący zbiór filtrów w formacie tekstowym';
+$labels['filtersetdel'] = 'Usuń bieżący zbiór filtrów';
+$labels['filtersetact'] = 'Aktywuj bieżący zbiór filtrów';
+$labels['filtersetdeact'] = 'Deaktywuj bieżący zbiór filtrów';
+$labels['filtersetget'] = 'Pobierz bieżący zbiór filtrów w formacie tekstowym';
$labels['filterdef'] = 'Definicja filtra';
$labels['filtersetname'] = 'Nazwa zbioru';
$labels['newfilterset'] = 'Nowy zbiór filtrów';
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index adca4e3d4..e2ab550d5 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -2426,9 +2426,11 @@ class rcube_imap
* @param rcube_message_part $o_part Part object created by get_structure()
* @param mixed $print True to print part, ressource to write part contents in
* @param resource $fp File pointer to save the message part
+ * @param boolean $skip_charset_conv Disables charset conversion
+ *
* @return string Message/part body if not printed
*/
- function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL)
+ function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false)
{
// get part encoding if not provided
if (!is_object($o_part)) {
@@ -2458,10 +2460,13 @@ class rcube_imap
return true;
}
- // convert charset (if text or message part) and part's charset is specified
- if ($body && $o_part->charset
- && preg_match('/^(text|message)$/', $o_part->ctype_primary)
+ // convert charset (if text or message part)
+ if ($body && !$skip_charset_conv &&
+ preg_match('/^(text|message)$/', $o_part->ctype_primary)
) {
+ if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') {
+ $o_part->charset = $this->default_charset;
+ }
$body = rcube_charset_convert($body, $o_part->charset);
}
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 29159c734..43194c4fd 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -964,6 +964,16 @@ class rcube_imap_generic
list($mbox, $items) = $this->tokenizeResponse($response, 2);
+ // Fix for #1487859. Some buggy server returns not quoted
+ // folder name with spaces. Let's try to handle this situation
+ if (!is_array($items) && ($pos = strpos($response, '(')) !== false) {
+ $response = substr($response, $pos);
+ $items = $this->tokenizeResponse($response, 1);
+ if (!is_array($items)) {
+ return $result;
+ }
+ }
+
for ($i=0, $len=count($items); $i<$len; $i += 2) {
$result[$items[$i]] = (int) $items[$i+1];
}
@@ -1569,36 +1579,21 @@ class rcube_imap_generic
if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/sU', $line, $matches)) {
$str = $matches[1];
- // swap parents with quotes, then explode
- $str = preg_replace('/[()]/', '"', $str);
- $a = rcube_explode_quoted_string(' ', $str);
-
- // did we get the right number of replies?
- $parts_count = count($a);
- if ($parts_count>=6) {
- for ($i=0; $i<$parts_count; $i=$i+2) {
- if ($a[$i] == 'UID') {
- $result[$id]->uid = intval($a[$i+1]);
- }
- else if ($a[$i] == 'RFC822.SIZE') {
- $result[$id]->size = intval($a[$i+1]);
- }
- else if ($a[$i] == 'INTERNALDATE') {
- $time_str = $a[$i+1];
- }
- else if ($a[$i] == 'FLAGS') {
- $flags_str = $a[$i+1];
- }
+ while (list($name, $value) = $this->tokenizeResponse($str, 2)) {
+ if ($name == 'UID') {
+ $result[$id]->uid = intval($value);
+ }
+ else if ($name == 'RFC822.SIZE') {
+ $result[$id]->size = intval($value);
+ }
+ else if ($name == 'INTERNALDATE') {
+ $result[$id]->internaldate = $value;
+ $result[$id]->date = $value;
+ $result[$id]->timestamp = $this->StrToTime($value);
+ }
+ else if ($name == 'FLAGS') {
+ $flags_a = $value;
}
-
- $time_str = str_replace('"', '', $time_str);
-
- // if time is gmt...
- $time_str = str_replace('GMT','+0000',$time_str);
-
- $result[$id]->internaldate = $time_str;
- $result[$id]->timestamp = $this->StrToTime($time_str);
- $result[$id]->date = $time_str;
}
// BODYSTRUCTURE
@@ -1646,7 +1641,7 @@ class rcube_imap_generic
// handle FLAGS reply after headers (AOL, Zimbra?)
if (preg_match('/\s+FLAGS \((.*)\)\)$/', $line, $matches)) {
- $flags_str = $matches[1];
+ $flags_a = $this->tokenizeResponse($matches[1]);
break;
}
@@ -1670,10 +1665,10 @@ class rcube_imap_generic
// create array with header field:data
while (list($lines_key, $str) = each($lines)) {
- list($field, $string) = $this->splitHeaderLine($str);
+ list($field, $string) = explode(':', $str, 2);
$field = strtolower($field);
- $string = preg_replace('/\n\s*/', ' ', $string);
+ $string = preg_replace('/\n[\t\s]*/', ' ', trim($string));
switch ($field) {
case 'date';
@@ -1737,32 +1732,31 @@ class rcube_imap_generic
}
// process flags
- if (!empty($flags_str)) {
- $flags_str = preg_replace('/[\\\"]/', '', $flags_str);
- $flags_a = explode(' ', $flags_str);
-
- if (is_array($flags_a)) {
- foreach($flags_a as $flag) {
- $flag = strtoupper($flag);
- if ($flag == 'SEEN') {
- $result[$id]->seen = true;
- } else if ($flag == 'DELETED') {
- $result[$id]->deleted = true;
- } else if ($flag == 'RECENT') {
- $result[$id]->recent = true;
- } else if ($flag == 'ANSWERED') {
- $result[$id]->answered = true;
- } else if ($flag == '$FORWARDED') {
- $result[$id]->forwarded = true;
- } else if ($flag == 'DRAFT') {
- $result[$id]->is_draft = true;
- } else if ($flag == '$MDNSENT') {
- $result[$id]->mdn_sent = true;
- } else if ($flag == 'FLAGGED') {
- $result[$id]->flagged = true;
- }
+ if (!empty($flags_a)) {
+ foreach ($flags_a as $flag) {
+ $flag = str_replace('\\', '', $flag);
+ $result[$id]->flags[] = $flag;
+
+ switch (strtoupper($flag)) {
+ case 'SEEN':
+ $result[$id]->seen = true;
+ break;
+ case 'DELETED':
+ $result[$id]->deleted = true;
+ break;
+ case 'ANSWERED':
+ $result[$id]->answered = true;
+ break;
+ case '$FORWARDED':
+ $result[$id]->forwarded = true;
+ break;
+ case '$MDNSENT':
+ $result[$id]->mdn_sent = true;
+ break;
+ case 'FLAGGED':
+ $result[$id]->flagged = true;
+ break;
}
- $result[$id]->flags = $flags_a;
}
}
}
@@ -3297,9 +3291,10 @@ class rcube_imap_generic
{
// support non-standard "GMTXXXX" literal
$date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date);
+
// if date parsing fails, we have a date in non-rfc format.
// remove token from the end and try again
- while ((($ts = @strtotime($date))===false) || ($ts < 0)) {
+ while (($ts = intval(@strtotime($date))) <= 0) {
$d = explode(' ', $date);
array_pop($d);
if (!$d) {
@@ -3313,17 +3308,6 @@ class rcube_imap_generic
return $ts < 0 ? 0 : $ts;
}
- private function splitHeaderLine($string)
- {
- $pos = strpos($string, ':');
- if ($pos>0) {
- $res[0] = substr($string, 0, $pos);
- $res[1] = trim(substr($string, $pos+1));
- return $res;
- }
- return $string;
- }
-
private function parseCapability($str, $trusted=false)
{
$str = preg_replace('/^\* CAPABILITY /i', '', $str);
diff --git a/program/include/rcube_mdb2.php b/program/include/rcube_mdb2.php
index 3376a9e00..d7fd4e013 100644
--- a/program/include/rcube_mdb2.php
+++ b/program/include/rcube_mdb2.php
@@ -553,15 +553,7 @@ class rcube_mdb2
*/
function fromunixtime($timestamp)
{
- switch($this->db_provider) {
- case 'mysqli':
- case 'mysql':
- case 'sqlite':
- return sprintf("FROM_UNIXTIME(%d)", $timestamp);
-
- default:
- return date("'Y-m-d H:i:s'", $timestamp);
- }
+ return date("'Y-m-d H:i:s'", $timestamp);
}
diff --git a/program/include/rcube_message.php b/program/include/rcube_message.php
index 5c0773815..6ffe9194d 100644
--- a/program/include/rcube_message.php
+++ b/program/include/rcube_message.php
@@ -725,7 +725,9 @@ class rcube_message
$line = $prefix . rc_wordwrap($line, $length - $level - 2, " \r\n$prefix ");
}
else if ($line) {
- $line = ' ' . rc_wordwrap(rtrim($line), $length - 2, " \r\n ");
+ $line = rc_wordwrap(rtrim($line), $length - 2, " \r\n");
+ // space-stuffing
+ $line = preg_replace('/(^|\r\n)(From| |>)/', '\\1 \\2', $line);
}
$text[$idx] = $line;
diff --git a/program/js/app.js b/program/js/app.js
index 38141a92f..d752a768b 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -2994,11 +2994,11 @@ function rcube_webmail()
this.compose_field_hash = function(save)
{
// check input fields
- var value_to = $("[name='_to']").val();
- var value_cc = $("[name='_cc']").val();
- var value_bcc = $("[name='_bcc']").val();
- var value_subject = $("[name='_subject']").val();
- var str = '';
+ var ed, str = '',
+ value_to = $("[name='_to']").val(),
+ value_cc = $("[name='_cc']").val(),
+ value_bcc = $("[name='_bcc']").val(),
+ value_subject = $("[name='_subject']").val();
if (value_to)
str += value_to+':';
@@ -3009,9 +3009,8 @@ function rcube_webmail()
if (value_subject)
str += value_subject+':';
- var editor = tinyMCE.get(this.env.composebody);
- if (editor)
- str += editor.getContent();
+ if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody)))
+ str += ed.getContent();
else
str += $("[name='_message']").val();
@@ -4622,7 +4621,7 @@ function rcube_webmail()
var current_li, target_li;
if ((current_li = this.get_folder_li(old, prefix))) {
- $(current_li).removeClass('selected').removeClass('unfocused');
+ $(current_li).removeClass('selected').addClass('unfocused');
}
if ((target_li = this.get_folder_li(name, prefix))) {
$(target_li).removeClass('unfocused').addClass('selected');
diff --git a/program/lib/html2text.php b/program/lib/html2text.php
index 325a1c941..48df4592c 100644
--- a/program/lib/html2text.php
+++ b/program/lib/html2text.php
@@ -572,9 +572,16 @@ class html2text
*/
function _convert_pre(&$text)
{
+ // get the content of PRE element
while (preg_match('/<pre[^>]*>(.*)<\/pre>/ismU', $text, $matches)) {
- $result = preg_replace($this->pre_search, $this->pre_replace, $matches[1]);
- $text = preg_replace('/<pre[^>]*>.*<\/pre>/ismU', '<div><br>' . $result . '<br></div>', $text, 1);
+ // convert the content
+ $this->pre_content = sprintf('<div><br>%s<br></div>',
+ preg_replace($this->pre_search, $this->pre_replace, $matches[1]));
+ // replace the content (use callback because content can contain $0 variable)
+ $text = preg_replace_callback('/<pre[^>]*>.*<\/pre>/ismU',
+ array('html2text', '_preg_pre_callback'), $text, 1);
+ // free memory
+ $this->pre_content = '';
}
}
@@ -639,9 +646,8 @@ class html2text
*
* @param array PREG matches
* @return string
- * @access private
*/
- function _preg_callback($matches)
+ private function _preg_callback($matches)
{
switch($matches[1]) {
case 'b':
@@ -659,13 +665,23 @@ class html2text
}
/**
+ * Callback function for preg_replace_callback use in PRE content handler.
+ *
+ * @param array PREG matches
+ * @return string
+ */
+ private function _preg_pre_callback($matches)
+ {
+ return $this->pre_content;
+ }
+
+ /**
* Strtoupper multibyte wrapper function
*
* @param string
* @return string
- * @access private
*/
- function _strtoupper($str)
+ private function _strtoupper($str)
{
if (function_exists('mb_strtoupper'))
return mb_strtoupper($str);
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index f700a6cdb..b40ec099b 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -726,71 +726,74 @@ function rcmail_plain_body($body, $flowed=false)
$body = preg_replace_callback($replacer->mailto_pattern, array($replacer, 'mailto_callback'), $body);
// split body into single lines
- $a_lines = preg_split('/\r?\n/', $body);
+ $body = preg_split('/\r?\n/', $body);
$quote_level = 0;
$last = -1;
// find/mark quoted lines...
- for ($n=0, $cnt=count($a_lines); $n < $cnt; $n++) {
- if ($a_lines[$n][0] == '>' && preg_match('/^(>+\s*)+/', $a_lines[$n], $regs)) {
+ for ($n=0, $cnt=count($body); $n < $cnt; $n++) {
+ if ($body[$n][0] == '>' && preg_match('/^(>+\s*)+/', $body[$n], $regs)) {
$q = strlen(preg_replace('/\s/', '', $regs[0]));
- $a_lines[$n] = substr($a_lines[$n], strlen($regs[0]));
-
- if ($q > $quote_level)
- $a_lines[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('<blockquote>', $q - $quote_level))) . $a_lines[$n];
- else if ($q < $quote_level)
- $a_lines[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level - $q))) . $a_lines[$n];
+ $body[$n] = substr($body[$n], strlen($regs[0]));
+
+ if ($q > $quote_level) {
+ $body[$n] = $replacer->get_replacement($replacer->add(
+ str_repeat('<blockquote>', $q - $quote_level))) . $body[$n];
+ }
+ else if ($q < $quote_level) {
+ $body[$n] = $replacer->get_replacement($replacer->add(
+ str_repeat('</blockquote>', $quote_level - $q))) . $body[$n];
+ }
else if ($flowed) {
// previous line is flowed
- if (isset($a_lines[$last]) && $a_lines[$n]
- && $a_lines[$last][strlen($a_lines[$last])-1] == ' ') {
+ if (isset($body[$last]) && $body[$n]
+ && $body[$last][strlen($body[$last])-1] == ' ') {
// merge lines
- $a_lines[$last] .= $a_lines[$n];
- unset($a_lines[$n]);
+ $body[$last] .= $body[$n];
+ unset($body[$n]);
}
- else
+ else {
$last = $n;
+ }
}
}
else {
$q = 0;
if ($flowed) {
// sig separator - line is fixed
- if ($a_lines[$n] == '-- ') {
- $last = $n;
+ if ($body[$n] == '-- ') {
+ $last = $last_sig = $n;
}
else {
// remove space-stuffing
- if ($a_lines[$n][0] == ' ')
- $a_lines[$n] = substr($a_lines[$n], 1);
+ if ($body[$n][0] == ' ')
+ $body[$n] = substr($body[$n], 1);
// previous line is flowed?
- if (isset($a_lines[$last]) && $a_lines[$n]
- && $a_lines[$last] != '-- '
- && $a_lines[$last][strlen($a_lines[$last])-1] == ' '
+ if (isset($body[$last]) && $body[$n]
+ && $last != $last_sig
+ && $body[$last][strlen($body[$last])-1] == ' '
) {
- $a_lines[$last] .= $a_lines[$n];
- unset($a_lines[$n]);
+ $body[$last] .= $body[$n];
+ unset($body[$n]);
}
else {
$last = $n;
}
}
if ($quote_level > 0)
- $a_lines[$last] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level))) . $a_lines[$last];
+ $body[$last] = $replacer->get_replacement($replacer->add(
+ str_repeat('</blockquote>', $quote_level))) . $body[$last];
}
else if ($quote_level > 0)
- $a_lines[$n] = $replacer->get_replacement($replacer->add(
- str_repeat('</blockquote>', $quote_level))) . $a_lines[$n];
+ $body[$n] = $replacer->get_replacement($replacer->add(
+ str_repeat('</blockquote>', $quote_level))) . $body[$n];
}
$quote_level = $q;
}
- $body = join("\n", $a_lines);
+ $body = join("\n", $body);
// quote plain text (don't use Q() here, to display entities "as is")
$table = get_html_translation_table(HTML_SPECIALCHARS);
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index feeb18341..2bf814722 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -97,10 +97,10 @@ switch ($CURR_SECTION)
break;
}
-$data = rcmail::get_instance()->plugins->exec_hook('preferences_save',
+$plugin = rcmail::get_instance()->plugins->exec_hook('preferences_save',
array('prefs' => $a_user_prefs, 'section' => $CURR_SECTION));
-$a_user_prefs = $data['prefs'];
+$a_user_prefs = $plugin['prefs'];
// don't override these parameters
foreach ((array)$CONFIG['dont_override'] as $p)
@@ -159,10 +159,17 @@ switch ($CURR_SECTION)
break;
}
-if ($USER->save_prefs($a_user_prefs))
+// Save preferences
+if (!$plugin['abort'])
+ $saved = $USER->save_prefs($a_user_prefs);
+else
+ $saved = $plugin['result'];
+
+if ($saved)
$OUTPUT->show_message('successfullysaved', 'confirmation');
+else
+ $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'errorsaving', 'error');
// display the form again
rcmail_overwrite_action('edit-prefs');
-