- Improve messages display performance
| | |
| | | CHANGELOG RoundCube Webmail |
| | | --------------------------- |
| | | |
| | | 2009/01/08 (alec) |
| | | ---------- |
| | | - Improve messages display performance |
| | | - Fix messages searching with 'to:' modifier |
| | | |
| | | 2008/12/30 (thomasb) |
| | | ---------- |
| | | - Fix mark popup in IE 7 (#1485369) |
| | |
| | | * @param int Message ID |
| | | * @param string Mailbox to read from |
| | | * @param boolean True if $id is the message UID |
| | | * @param boolean True if we need also BODYSTRUCTURE in headers |
| | | * @return object Message headers representation |
| | | */ |
| | | function get_headers($id, $mbox_name=NULL, $is_uid=TRUE) |
| | | function get_headers($id, $mbox_name=NULL, $is_uid=TRUE, $bodystr=FALSE) |
| | | { |
| | | $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox; |
| | | $uid = $is_uid ? $id : $this->_id2uid($id); |
| | |
| | | if ($uid && ($headers = &$this->get_cached_message($mailbox.'.msg', $uid))) |
| | | return $headers; |
| | | |
| | | $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid); |
| | | $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid, $bodystr); |
| | | |
| | | // write headers cache |
| | | if ($headers) |
| | |
| | | * an object structure similar to the one generated by PEAR::Mail_mimeDecode |
| | | * |
| | | * @param int Message UID to fetch |
| | | * @param string Message BODYSTRUCTURE string (optional) |
| | | * @return object rcube_message_part Message part tree or False on failure |
| | | */ |
| | | function &get_structure($uid) |
| | | function &get_structure($uid, $structure_str='') |
| | | { |
| | | $cache_key = $this->mailbox.'.msg'; |
| | | $headers = &$this->get_cached_message($cache_key, $uid, true); |
| | |
| | | return FALSE; |
| | | } |
| | | |
| | | if (!$structure_str) |
| | | $structure_str = iil_C_FetchStructureString($this->conn, $this->mailbox, $msg_id); |
| | | $structure = iml_GetRawStructureArray($structure_str); |
| | | $struct = false; |
| | |
| | | * |
| | | * @access private |
| | | */ |
| | | function &_structure_part($part, $count=0, $parent='') |
| | | function &_structure_part($part, $count=0, $parent='', $raw_headers=null) |
| | | { |
| | | $struct = new rcube_message_part; |
| | | $struct->mime_id = empty($parent) ? (string)$count : "$parent.$count"; |
| | |
| | | |
| | | $struct->mimetype = 'multipart/'.$struct->ctype_secondary; |
| | | |
| | | // build parts list for headers pre-fetching |
| | | for ($i=0, $count=0; $i<count($part); $i++) |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) |
| | | // fetch message headers if message/rfc822 or named part (could contain Content-Location header) |
| | | if (strtolower($part[$i][0]) == 'message' || |
| | | (in_array('name', (array)$part[$i][2]) && (empty($part[$i][3]) || $part[$i][3]=='NIL'))) { |
| | | $part_headers[] = $struct->mime_id ? $struct->mime_id.'.'.$i+1 : $i+1; |
| | | } |
| | | |
| | | // pre-fetch headers of all parts (in one command for better performance) |
| | | if ($part_headers) |
| | | $part_headers = iil_C_FetchMIMEHeaders($this->conn, $this->mailbox, $this->_msg_id, $part_headers); |
| | | |
| | | $struct->parts = array(); |
| | | for ($i=0, $count=0; $i<count($part); $i++) |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) |
| | | $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id); |
| | | $struct->parts[] = $this->_structure_part($part[$i], ++$count, $struct->mime_id, |
| | | $part_headers[$struct->mime_id ? $struck->mime_id.'.'.$i+1 : $i+1]); |
| | | |
| | | return $struct; |
| | | } |
| | |
| | | |
| | | // fetch message headers if message/rfc822 or named part (could contain Content-Location header) |
| | | if ($struct->ctype_primary == 'message' || ($struct->ctype_parameters['name'] && !$struct->content_id)) { |
| | | $part_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, $struct->mime_id); |
| | | $struct->headers = $this->_parse_headers($part_headers) + $struct->headers; |
| | | if (empty($raw_headers)) |
| | | $raw_headers = iil_C_FetchPartHeader($this->conn, $this->mailbox, $this->_msg_id, $struct->mime_id); |
| | | $struct->headers = $this->_parse_headers($raw_headers) + $struct->headers; |
| | | } |
| | | |
| | | if ($struct->ctype_primary=='message') { |
| | |
| | | $this->imap = $this->app->imap; |
| | | |
| | | $this->uid = $uid; |
| | | $this->headers = $this->imap->get_headers($uid); |
| | | $this->headers = $this->imap->get_headers($uid, NULL, true, true); |
| | | |
| | | $this->subject = rcube_imap::decode_mime_string($this->headers->subject, $this->headers->charset); |
| | | list(, $this->sender) = each($this->imap->decode_address_list($this->headers->from)); |
| | | |
| | | $this->set_safe((intval($_GET['_safe']) || $_SESSION['safe_messages'][$uid])); |
| | | |
| | | $this->opt = array( |
| | | 'safe' => $this->is_safe, |
| | | 'prefer_html' => $this->app->config->get('prefer_html'), |
| | | 'get_url' => rcmail_url('get', array('_mbox' => $this->imap->get_mailbox_name(), '_uid' => $uid)) |
| | | ); |
| | | |
| | | if ($this->structure = $this->imap->get_structure($uid)) { |
| | | if ($this->structure = $this->imap->get_structure($uid, $this->headers->body_structure)) { |
| | | $this->get_mime_numbers($this->structure); |
| | | $this->parse_structure($this->structure); |
| | | } |
| | |
| | | - added 4th argument to iil_Connect() |
| | | - allow setting rootdir and delimiter before connect |
| | | - support multiquota result |
| | | - include BODYSTRUCTURE in iil_C_FetchHeaders() |
| | | - added iil_C_FetchMIMEHeaders() function |
| | | |
| | | ********************************************************/ |
| | | |
| | |
| | | var $flags; |
| | | var $timestamp; |
| | | var $f; |
| | | var $body_structure; |
| | | var $internaldate; |
| | | var $references; |
| | | var $priority; |
| | |
| | | return $t_index; |
| | | } |
| | | |
| | | function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false) |
| | | function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false) |
| | | { |
| | | global $IMAP_USE_INTERNAL_DATE; |
| | | |
| | |
| | | /* FETCH uid, size, flags and headers */ |
| | | $key = 'FH12'; |
| | | $request = $key . ($uidfetch ? ' UID' : '') . " FETCH $message_set "; |
| | | $request .= "(UID RFC822.SIZE FLAGS INTERNALDATE BODY.PEEK[HEADER.FIELDS "; |
| | | $request .= "(UID RFC822.SIZE FLAGS INTERNALDATE "; |
| | | if ($bodystr) |
| | | $request .= "BODYSTRUCTURE "; |
| | | $request .= "BODY.PEEK[HEADER.FIELDS "; |
| | | $request .= "(DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC "; |
| | | $request .= "CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID "; |
| | | $request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY)])"; |
| | |
| | | return false; |
| | | } |
| | | do { |
| | | $line = chop(iil_ReadLine($fp, 1024)); |
| | | $line = iil_ReadLine($fp, 1024); |
| | | $line = iil_MultLine($fp, $line); |
| | | |
| | | $a = explode(' ', $line); |
| | | if (($line[0] == '*') && ($a[2] == 'FETCH')) { |
| | | $id = $a[1]; |
| | |
| | | $result[$id]->subject = ''; |
| | | $result[$id]->messageID = 'mid:' . $id; |
| | | |
| | | $lines = array(); |
| | | $ln = 0; |
| | | /* |
| | | Sample reply line: |
| | | * 321 FETCH (UID 2417 RFC822.SIZE 2730 FLAGS (\Seen) |
| | | INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODY[HEADER.FIELDS ... |
| | | INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODYSTRUCTURE (...) |
| | | BODY[HEADER.FIELDS ... |
| | | */ |
| | | |
| | | if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY\[HEADER/', $line, $matches)) { |
| | | if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/s', $line, $matches)) { |
| | | $str = $matches[1]; |
| | | |
| | | //swap parents with quotes, then explode |
| | |
| | | $result[$id]->timestamp = $timestamp; |
| | | $result[$id]->date = $time_str; |
| | | } |
| | | |
| | | // BODYSTRUCTURE |
| | | if($bodystr) { |
| | | while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) { |
| | | $line2 = iil_ReadLine($fp, 1024); |
| | | $line .= iil_MultLine($fp, $line2); |
| | | } |
| | | $result[$id]->body_structure = $m[1]; |
| | | } |
| | | |
| | | // the rest of the result |
| | | preg_match('/ BODY\[HEADER.FIELDS \(.*\)\]\s*(.*)/s', $line, $m); |
| | | $reslines = explode("\n", trim($m[1], '"')); |
| | | // re-parse (see below) |
| | | foreach ($reslines as $line) { |
| | | if (ord($line[0])<=32) { |
| | | $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line); |
| | | } else { |
| | | $lines[++$ln] = trim($line); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* |
| | |
| | | to the next valid header line. |
| | | */ |
| | | |
| | | $i = 0; |
| | | $lines = array(); |
| | | do { |
| | | $line = chop(iil_ReadLine($fp, 300), "\r\n"); |
| | | |
| | | if (ord($line[0])<=32) { |
| | | $lines[$i] .= (empty($lines[$i])?'':"\n").trim($line); |
| | | $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line); |
| | | } else { |
| | | $i++; |
| | | $lines[$i] = trim($line); |
| | | $lines[++$ln] = trim($line); |
| | | } |
| | | /* |
| | | The preg_match below works around communigate imap, which outputs " UID <number>)". |
| | |
| | | return $result; |
| | | } |
| | | |
| | | function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false) { |
| | | function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false) { |
| | | |
| | | $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch); |
| | | $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr); |
| | | if (is_array($a)) { |
| | | return array_shift($a); |
| | | } |
| | |
| | | return iil_ParseResult($line); |
| | | } |
| | | |
| | | function iil_C_FetchMIMEHeaders(&$conn, $mailbox, $id, $parts) { |
| | | |
| | | $fp = $conn->fp; |
| | | |
| | | if (!iil_C_Select($conn, $mailbox)) { |
| | | return false; |
| | | } |
| | | |
| | | $result = false; |
| | | $parts = (array) $parts; |
| | | $key = 'fmh0'; |
| | | $peeks = ''; |
| | | $idx = 0; |
| | | |
| | | // format request |
| | | foreach($parts as $part) |
| | | $peeks[] = "BODY[$part.MIME]"; |
| | | |
| | | $request = "$key FETCH $id (" . implode(' ', $peeks) . ')'; |
| | | |
| | | // send request |
| | | if (!iil_PutLine($fp, $request)) { |
| | | return false; |
| | | } |
| | | |
| | | do { |
| | | $line = iil_ReadLine($fp, 1000); |
| | | $line = iil_MultLine($fp, $line); |
| | | |
| | | if (preg_match('/BODY\[([0-9\.]+)\.MIME\]/', $line, $matches)) { |
| | | $idx = $matches[1]; |
| | | $result[$idx] = preg_replace('/^(\* '.$id.' FETCH \()?\s*BODY\['.$idx.'\.MIME\]\s+/', '', $line); |
| | | $result[$idx] = trim($result[$idx], '"'); |
| | | $result[$idx] = rtrim($result[$idx], "\t\r\n\0\x0B"); |
| | | } |
| | | } while (!iil_StartsWith($line, $key, true)); |
| | | |
| | | return $result; |
| | | } |
| | | |
| | | function iil_C_FetchPartHeader(&$conn, $mailbox, $id, $part) { |
| | | |
| | | $part = empty($part) ? 'HEADER' : $part.'.MIME'; |