From 95fd49e4f267d788ba87fea7149c846a74ad44c0 Mon Sep 17 00:00:00 2001 From: alecpl Date: Fri, 30 Jul 2010 12:16:56 +0000 Subject: - Fix message structure parsing when it lacks optional fields (#1486881) --- CHANGELOG | 1 + program/include/rcube_imap.php | 88 ++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c454b6d4b..7d7cc2687 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG RoundCube Webmail =========================== +- Fix message structure parsing when it lacks optional fields (#1486881) - Include all recipients in sendmail log - Support HTTP_X_FORWARDED_PROTO header for HTTPS detecting (#1486866) - Fix default IMAP port configuration (#1486864) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 9c3653120..cdc52a49f 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -1747,6 +1747,18 @@ class rcube_imap if (is_array($part[0])) { $struct->ctype_primary = 'multipart'; + /* RFC3501: BODYSTRUCTURE fields of multipart part + part1 array + part2 array + part3 array + .... + 1. subtype + 2. parameters (optional) + 3. description (optional) + 4. language (optional) + 5. location (optional) + */ + // find first non-array entry for ($i=1; $imimetype = 'multipart/'.$struct->ctype_secondary; // build parts list for headers pre-fetching - for ($i=0, $count=0; $i 4) { - // fetch message headers if message/rfc822 - // or named part (could contain Content-Location header) - if (!is_array($part[$i][0])) { - $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; - if (strtolower($part[$i][0]) == 'message' && strtolower($part[$i][1]) == 'rfc822') { - $raw_part_headers[] = $tmp_part_id; - $mime_part_headers[] = $tmp_part_id; - } - else if (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL')) { - $mime_part_headers[] = $tmp_part_id; - } + for ($i=0; $imime_id ? $struct->mime_id.'.'.($i+1) : $i+1; + if (strtolower($part[$i][0]) == 'message' && strtolower($part[$i][1]) == 'rfc822') { + $raw_part_headers[] = $tmp_part_id; + $mime_part_headers[] = $tmp_part_id; + } + else if (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL')) { + $mime_part_headers[] = $tmp_part_id; } } } @@ -1787,18 +1799,40 @@ class rcube_imap $raw_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox, $this->_msg_id, $raw_part_headers, false); } + $struct->parts = array(); for ($i=0, $count=0; $i 4) { - $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; - $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id, + if (!is_array($part[$i])) + break; + $tmp_part_id = $struct->mime_id ? $struct->mime_id.'.'.($i+1) : $i+1; + $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id, $mime_part_headers[$tmp_part_id], $raw_part_headers[$tmp_part_id]); - } } return $struct; } + /* RFC3501: BODYSTRUCTURE fields of non-multipart part + 0. type + 1. subtype + 2. parameters + 3. id + 4. description + 5. encoding + 6. size + -- text + 7. lines + -- message/rfc822 + 7. envelope structure + 8. body structure + 9. lines + -- + x. md5 (optional) + x. disposition (optional) + x. language (optional) + x. location (optional) + */ + // regular part $struct->ctype_primary = strtolower($part[0]); $struct->ctype_secondary = strtolower($part[1]); @@ -1825,9 +1859,11 @@ class rcube_imap $struct->size = intval($part[6]); // read part disposition - $di = count($part) - 2; - if ((is_array($part[$di]) && count($part[$di]) == 2 && is_array($part[$di][1])) || - (is_array($part[--$di]) && count($part[$di]) == 2)) { + $di = 8; + if ($struct->ctype_primary == 'text') $di += 1; + else if ($struct->mimetype == 'message/rfc822') $di += 3; + + if (is_array($part[$di]) && count($part[$di]) == 2) { $struct->disposition = strtolower($part[$di][0]); if (is_array($part[$di][1])) @@ -1835,12 +1871,14 @@ class rcube_imap $struct->d_parameters[strtolower($part[$di][1][$n])] = $part[$di][1][$n+1]; } - // get child parts + // get message/rfc822's child-parts if (is_array($part[8]) && $di != 8) { $struct->parts = array(); - for ($i=0, $count=0; $i 5) - $struct->parts[] = $this->_structure_part($part[8][$i], ++$count, $struct->mime_id); + for ($i=0, $count=0; $iparts[] = $this->_structure_part($part[8][$i], ++$count, $struct->mime_id); + } } // get part ID @@ -1875,7 +1913,7 @@ class rcube_imap } } - if ($struct->ctype_primary=='message') { + if ($struct->ctype_primary == 'message') { if (is_array($part[8]) && $di != 8 && empty($struct->parts)) $struct->parts[] = $this->_structure_part($part[8], ++$count, $struct->mime_id); } -- cgit v1.2.3