summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2009-03-06 09:12:41 +0000
committeralecpl <alec@alec.pl>2009-03-06 09:12:41 +0000
commit55c2a4e23e2a2382720043a1753e5601adfbb56d (patch)
tree35dc86a98e0d66bd633cb8db73470e92ebde3be2
parent25f779d2e90627f989da32dbd3cf7a0e3e3d2a3b (diff)
- Fix FETCH result parsing for servers returning flags at the end of result (#1485763)
-rw-r--r--CHANGELOG1
-rw-r--r--program/lib/imap.inc97
2 files changed, 53 insertions, 45 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 431ae0649..722b6268b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,7 @@ CHANGELOG RoundCube Webmail
2009/03/06 (alec)
----------
- Fix errors handling in IMAP command continuations (#1485762)
+- Fix FETCH result parsing for servers returning flags at the end of result (#1485763)
2009/03/04 (alec)
----------
diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index f50abeacd..67a2b7b3c 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -1690,7 +1690,7 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
do {
$line = iil_ReadLine($fp, 1024);
$line = iil_MultLine($fp, $line);
-
+
$a = explode(' ', $line);
if (($line[0] == '*') && ($a[2] == 'FETCH')) {
$id = $a[1];
@@ -1718,7 +1718,7 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
// did we get the right number of replies?
$parts_count = count($a);
- if ($parts_count>=8) {
+ if ($parts_count>=6) {
for ($i=0; $i<$parts_count; $i=$i+2) {
if (strcasecmp($a[$i],'UID') == 0)
$result[$id]->uid = $a[$i+1];
@@ -1730,34 +1730,6 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
$flags_str = $a[$i+1];
}
- // process flags
- $flags_str = eregi_replace('[\\\"]', '', $flags_str);
- $flags_a = explode(' ', $flags_str);
-
- if (is_array($flags_a)) {
- reset($flags_a);
- while (list(,$val)=each($flags_a)) {
- if (strcasecmp($val,'Seen') == 0) {
- $result[$id]->seen = true;
- } else if (strcasecmp($val, 'Deleted') == 0) {
- $result[$id]->deleted=true;
- } else if (strcasecmp($val, 'Recent') == 0) {
- $result[$id]->recent = true;
- } else if (strcasecmp($val, 'Answered') == 0) {
- $result[$id]->answered = true;
- } else if (strcasecmp($val, '$Forwarded') == 0) {
- $result[$id]->forwarded = true;
- } else if (strcasecmp($val, 'Draft') == 0) {
- $result[$id]->is_draft = true;
- } else if (strcasecmp($val, '$MDNSent') == 0) {
- $result[$id]->mdn_sent = true;
- } else if (strcasecmp($val, 'Flagged') == 0) {
- $result[$id]->flagged = true;
- }
- }
- $result[$id]->flags = $flags_a;
- }
-
$time_str = str_replace('"', '', $time_str);
// if time is gmt...
@@ -1800,7 +1772,7 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
// re-parse (see below)
foreach ($reslines as $line) {
if (ord($line[0])<=32) {
- $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
+ $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
} else {
$lines[++$ln] = trim($line);
}
@@ -1817,24 +1789,29 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
do {
$line = chop(iil_ReadLine($fp, 300), "\r\n");
+ // The preg_match below works around communigate imap, which outputs " UID <number>)".
+ // Without this, the while statement continues on and gets the "FH0 OK completed" message.
+ // If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.
+ // This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
+ // If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
+ // An alternative might be:
+ // if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
+ // however, unsure how well this would work with all imap clients.
+ if (preg_match("/^\s*UID [0-9]+\)$/", $line)) {
+ break;
+ }
+
+ // handle FLAGS reply after headers (AOL, Zimbra?)
+ if (preg_match('/\s+FLAGS \((.*)\)\)$/', $line, $matches)) {
+ $flags_str = $matches[1];
+ break;
+ }
+
if (ord($line[0])<=32) {
- $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
+ $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
} else {
$lines[++$ln] = trim($line);
}
- /*
- The preg_match below works around communigate imap, which outputs " UID <number>)".
- Without this, the while statement continues on and gets the "FH0 OK completed" message.
- If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.
- This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
- If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
- An alternative might be:
- if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
- however, unsure how well this would work with all imap clients.
- */
- if (preg_match("/^\s*UID [0-9]+\)$/", $line)) {
- break;
- }
// patch from "Maksim Rubis" <siburny@hotmail.com>
} while (trim($line[0]) != ')' && strncmp($line, $key, strlen($key)));
@@ -1922,6 +1899,36 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bo
} else {
$a = explode(' ', $line);
}
+
+ // process flags
+ if (!empty($flags_str)) {
+ $flags_str = eregi_replace('[\\\"]', '', $flags_str);
+ $flags_a = explode(' ', $flags_str);
+
+ if (is_array($flags_a)) {
+ reset($flags_a);
+ while (list(,$val)=each($flags_a)) {
+ if (strcasecmp($val,'Seen') == 0) {
+ $result[$id]->seen = true;
+ } else if (strcasecmp($val, 'Deleted') == 0) {
+ $result[$id]->deleted=true;
+ } else if (strcasecmp($val, 'Recent') == 0) {
+ $result[$id]->recent = true;
+ } else if (strcasecmp($val, 'Answered') == 0) {
+ $result[$id]->answered = true;
+ } else if (strcasecmp($val, '$Forwarded') == 0) {
+ $result[$id]->forwarded = true;
+ } else if (strcasecmp($val, 'Draft') == 0) {
+ $result[$id]->is_draft = true;
+ } else if (strcasecmp($val, '$MDNSent') == 0) {
+ $result[$id]->mdn_sent = true;
+ } else if (strcasecmp($val, 'Flagged') == 0) {
+ $result[$id]->flagged = true;
+ }
+ }
+ $result[$id]->flags = $flags_a;
+ }
+ }
}
} while (strcmp($a[0], $key) != 0);