From 8bed5e0151eb375e2d2dc91e4e6c6d5aa62daa5c Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sun, 19 Jul 2015 05:06:48 -0400
Subject: [PATCH] Fix regression where compose editor mode was set incorrectly
---
program/lib/Roundcube/rcube_imap_generic.php | 169 +++++++++++++++++++++++++++++++-------------------------
1 files changed, 94 insertions(+), 75 deletions(-)
diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php
index a3a76ab..7686b56 100644
--- a/program/lib/Roundcube/rcube_imap_generic.php
+++ b/program/lib/Roundcube/rcube_imap_generic.php
@@ -48,8 +48,6 @@
'*' => '\\*',
);
- public static $mupdate;
-
protected $fp;
protected $host;
protected $logged = false;
@@ -1108,7 +1106,8 @@
// 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);
+ $items = $this->tokenizeResponse($response, 1);
+
if (!is_array($items)) {
return $result;
}
@@ -1146,7 +1145,7 @@
}
// Clear internal status cache
- unset($this->data['STATUS:'.$mailbox]);
+ $this->clear_status_cache($mailbox);
if (!empty($messages) && $messages != '*' && $this->hasCapability('UIDPLUS')) {
$messages = self::compressMessageSet($messages);
@@ -1461,13 +1460,9 @@
*
* @return int Number of messages, False on error
*/
- function countMessages($mailbox, $refresh = false)
+ function countMessages($mailbox)
{
- if ($refresh) {
- $this->selected = null;
- }
-
- if ($this->selected === $mailbox) {
+ if ($this->selected === $mailbox && isset($this->data['EXISTS'])) {
return $this->data['EXISTS'];
}
@@ -1495,14 +1490,20 @@
*/
function countRecent($mailbox)
{
- if (!strlen($mailbox)) {
- $mailbox = 'INBOX';
+ if ($this->selected === $mailbox && isset($this->data['RECENT'])) {
+ return $this->data['RECENT'];
}
- $this->select($mailbox);
+ // Check internal cache
+ $cache = $this->data['STATUS:'.$mailbox];
+ if (!empty($cache) && isset($cache['RECENT'])) {
+ return (int) $cache['RECENT'];
+ }
- if ($this->selected === $mailbox) {
- return $this->data['RECENT'];
+ // Try STATUS (should be faster than SELECT)
+ $counts = $this->status($mailbox, array('RECENT'));
+ if (is_array($counts)) {
+ return (int) $counts['RECENT'];
}
return false;
@@ -1704,7 +1705,6 @@
$encoding = $encoding ? trim($encoding) : 'US-ASCII';
$algorithm = $algorithm ? trim($algorithm) : 'REFERENCES';
$criteria = $criteria ? 'ALL '.trim($criteria) : 'ALL';
- $data = '';
list($code, $response) = $this->execute($return_uid ? 'UID THREAD' : 'THREAD',
array($algorithm, $encoding, $criteria));
@@ -2124,7 +2124,7 @@
// Clear internal status cache
unset($this->data['STATUS:'.$to]);
- unset($this->data['STATUS:'.$from]);
+ $this->clear_status_cache($from);
$result = $this->execute('UID MOVE', array(
$this->compressMessageSet($messages), $this->escape($to)),
@@ -2438,7 +2438,16 @@
return false;
}
- function sortHeaders($a, $field, $flag)
+ /**
+ * Sort messages by specified header field
+ *
+ * @param array $messages Array of rcube_message_header objects
+ * @param string $field Name of the property to sort by
+ * @param string $flag Sorting order (ASC|DESC)
+ *
+ * @return array Sorted input array
+ */
+ public static function sortHeaders($messages, $field, $flag)
{
if (empty($field)) {
$field = 'uid';
@@ -2447,57 +2456,65 @@
$field = strtolower($field);
}
- if ($field == 'date' || $field == 'internaldate') {
- $field = 'timestamp';
- }
-
if (empty($flag)) {
$flag = 'ASC';
- } else {
+ }
+ else {
$flag = strtoupper($flag);
}
- $c = count($a);
- if ($c > 0) {
- // Strategy:
- // First, we'll create an "index" array.
- // Then, we'll use sort() on that array,
- // and use that to sort the main array.
+ // Strategy: First, we'll create an "index" array.
+ // Then, we'll use sort() on that array, and use that to sort the main array.
- // create "index" array
- $index = array();
- reset($a);
- while (list($key, $val) = each($a)) {
- if ($field == 'timestamp') {
- $data = $this->strToTime($val->date);
- if (!$data) {
- $data = $val->timestamp;
- }
- } else {
- $data = $val->$field;
- if (is_string($data)) {
- $data = str_replace('"', '', $data);
- if ($field == 'subject') {
- $data = preg_replace('/^(Re: \s*|Fwd:\s*|Fw:\s*)+/i', '', $data);
- }
- $data = strtoupper($data);
- }
+ $index = array();
+ $result = array();
+
+ reset($messages);
+
+ while (list($key, $headers) = each($messages)) {
+ $value = null;
+
+ switch ($field) {
+ case 'arrival':
+ $field = 'internaldate';
+ case 'date':
+ case 'internaldate':
+ case 'timestamp':
+ $value = self::strToTime($headers->$field);
+ if (!$value && $field != 'timestamp') {
+ $value = $headers->timestamp;
}
- $index[$key] = $data;
+
+ break;
+
+ default:
+ // @TODO: decode header value, convert to UTF-8
+ $value = $headers->$field;
+ if (is_string($value)) {
+ $value = str_replace('"', '', $value);
+ if ($field == 'subject') {
+ $value = preg_replace('/^(Re:\s*|Fwd:\s*|Fw:\s*)+/i', '', $value);
+ }
+
+ $data = strtoupper($value);
+ }
}
+ $index[$key] = $value;
+ }
+
+ if (!empty($index)) {
// sort index
if ($flag == 'ASC') {
asort($index);
- } else {
+ }
+ else {
arsort($index);
}
// form new array based on index
- $result = array();
- reset($index);
while (list($key, $val) = each($index)) {
- $result[$key] = $a[$key];
+ $result[$key] = $messages[$key];
}
}
@@ -2569,7 +2586,7 @@
return false;
}
- $initiated = false;
+ $binary = true;
do {
if (!$initiated) {
@@ -2591,16 +2608,16 @@
}
// Use BINARY extension when possible (and safe)
- $binary = !$binary_err && $mode && preg_match('/^[0-9.]+$/', $part) && $this->hasCapability('BINARY');
+ $binary = $binary && $mode && preg_match('/^[0-9.]+$/', $part) && $this->hasCapability('BINARY');
$fetch_mode = $binary ? 'BINARY' : 'BODY';
$partial = $max_bytes ? sprintf('<0.%d>', $max_bytes) : '';
// format request
- $key = $this->nextTag();
- $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part]$partial)";
- $result = false;
- $found = false;
- $initiated = true;
+ $key = $this->nextTag();
+ $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part]$partial)";
+ $result = false;
+ $found = false;
+ $initiated = true;
// send request
if (!$this->putLine($request)) {
@@ -2616,14 +2633,14 @@
$line = trim($this->readLine(1024));
- // handle UNKNOWN-CTE response - RFC 3516, try standard BODY request instead of BINARY
- if ($binary && preg_match('/^' . $key . ' NO \[UNKNOWN-CTE\]/i', $line)) {
- $initiated = false;
- continue;
- }
-
if (!$line) {
break;
+ }
+
+ // handle UNKNOWN-CTE response - RFC 3516, try again with standard BODY request
+ if ($binary && !$found && preg_match('/^' . $key . ' NO \[UNKNOWN-CTE\]/i', $line)) {
+ $binary = $initiated = false;
+ continue;
}
// skip irrelevant untagged responses (we have a result already)
@@ -2731,7 +2748,7 @@
}
}
}
- } while (!$this->startsWith($line, $key, true));
+ } while (!$this->startsWith($line, $key, true) || !$initiated);
if ($result !== false) {
if ($file) {
@@ -3271,11 +3288,6 @@
}
foreach ($data as $entry) {
- // Workaround cyrus-murder bug, the entry[2] string needs to be escaped
- if (self::$mupdate) {
- $entry[2] = addcslashes($entry[2], '\\"');
- }
-
// ANNOTATEMORE drafts before version 08 require quoted parameters
$entries[] = sprintf('%s (%s %s)', $this->escape($entry[0], true),
$this->escape($entry[1], true), $this->escape($entry[2], true));
@@ -3768,6 +3780,17 @@
}
/**
+ * Clear internal status cache
+ */
+ protected function clear_status_cache($mailbox)
+ {
+ unset($this->data['STATUS:' . $mailbox]);
+ unset($this->data['EXISTS']);
+ unset($this->data['RECENT']);
+ unset($this->data['UNSEEN']);
+ }
+
+ /**
* Converts flags array into string for inclusion in IMAP command
*
* @param array $flags Flags (see self::flags)
@@ -3838,10 +3861,6 @@
if (!isset($this->prefs['literal+']) && in_array('LITERAL+', $this->capability)) {
$this->prefs['literal+'] = true;
- }
-
- if (preg_match('/(\[| )MUPDATE=.*/', $str)) {
- self::$mupdate = true;
}
if ($trusted) {
--
Gitblit v1.9.1