| | |
| | | $all_ids = array(); |
| | | foreach($msg_index as $root) { |
| | | $all_ids[] = $root; |
| | | if (!empty($thread_tree[$root])) |
| | | $all_ids = array_merge($all_ids, array_keys_recursive($thread_tree[$root])); |
| | | if (!empty($thread_tree[$root])) { |
| | | foreach (array_keys_recursive($thread_tree[$root]) as $val) |
| | | $all_ids[] = $val; |
| | | } |
| | | } |
| | | |
| | | return $all_ids; |
| | |
| | | else |
| | | $this->struct_charset = $this->_structure_charset($structure); |
| | | |
| | | $headers->ctype = strtolower($headers->ctype); |
| | | |
| | | // Here we can recognize malformed BODYSTRUCTURE and |
| | | // 1. [@TODO] parse the message in other way to create our own message structure |
| | | // 2. or just show the raw message body. |
| | | // Example of structure for malformed MIME message: |
| | | // ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 2154 70 NIL NIL NIL) |
| | | if ($headers->ctype && $headers->ctype != 'text/plain' |
| | | && $structure[0] == 'text' && $structure[1] == 'plain') { |
| | | return false; |
| | | // ("text" "plain" NIL NIL NIL "7bit" 2154 70 NIL NIL NIL) |
| | | if ($headers->ctype && !is_array($structure[0]) && $headers->ctype != 'text/plain' |
| | | && strtolower($structure[0].'/'.$structure[1]) == 'text/plain') { |
| | | // we can handle single-part messages, by simple fix in structure (#1486898) |
| | | if (preg_match('/^(text|application)\/(.*)/', $headers->ctype, $m)) { |
| | | $structure[0] = $m[1]; |
| | | $structure[1] = $m[2]; |
| | | } |
| | | else |
| | | return false; |
| | | } |
| | | |
| | | $struct = &$this->_structure_part($structure); |
| | |
| | | * |
| | | * @access private |
| | | */ |
| | | function &_structure_part($part, $count=0, $parent='', $mime_headers=null, $raw_headers=null) |
| | | function &_structure_part($part, $count=0, $parent='', $mime_headers=null) |
| | | { |
| | | $struct = new rcube_message_part; |
| | | $struct->mime_id = empty($parent) ? (string)$count : "$parent.$count"; |
| | |
| | | // multipart |
| | | 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; $i<count($part); $i++) { |
| | |
| | | $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 (!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; $i<count($part); $i++) { |
| | | if (!is_array($part[$i])) |
| | | break; |
| | | // 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') { |
| | | $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; |
| | | } |
| | | } |
| | | } |
| | |
| | | $mime_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox, |
| | | $this->_msg_id, $mime_part_headers); |
| | | } |
| | | // we'll need a real content-type of message/rfc822 part |
| | | if ($raw_part_headers) { |
| | | $raw_part_headers = $this->conn->fetchMIMEHeaders($this->mailbox, |
| | | $this->_msg_id, $raw_part_headers, false); |
| | | } |
| | | |
| | | $struct->parts = array(); |
| | | for ($i=0, $count=0; $i<count($part); $i++) { |
| | | if (is_array($part[$i]) && count($part[$i]) > 3) { |
| | | $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]); |
| | | } |
| | | 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]); |
| | | } |
| | | |
| | | 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->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])) |
| | |
| | | $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<count($part[8]); $i++) |
| | | if (is_array($part[8][$i]) && count($part[8][$i]) > 5) |
| | | $struct->parts[] = $this->_structure_part($part[8][$i], ++$count, $struct->mime_id); |
| | | for ($i=0, $count=0; $i<count($part[8]); $i++) { |
| | | if (!is_array($part[8][$i])) |
| | | break; |
| | | $struct->parts[] = $this->_structure_part($part[8][$i], ++$count, $struct->mime_id); |
| | | } |
| | | } |
| | | |
| | | // get part ID |
| | |
| | | } |
| | | $struct->headers = $this->_parse_headers($mime_headers) + $struct->headers; |
| | | |
| | | // get real headers for message of type 'message/rfc822' |
| | | // get real content-type of message/rfc822 |
| | | if ($struct->mimetype == 'message/rfc822') { |
| | | if (empty($raw_headers)) { |
| | | $raw_headers = $this->conn->fetchMIMEHeaders( |
| | | $this->mailbox, $this->_msg_id, (array)$struct->mime_id, false); |
| | | } |
| | | $struct->real_headers = $this->_parse_headers($raw_headers); |
| | | |
| | | // get real content-type of message/rfc822 |
| | | if (preg_match('/^([a-z0-9_\/-]+)/i', $struct->real_headers['content-type'], $matches)) { |
| | | $struct->real_mimetype = strtolower($matches[1]); |
| | | // single-part |
| | | if (!is_array($part[8][0])) |
| | | $struct->real_mimetype = strtolower($part[8][0] . '/' . $part[8][1]); |
| | | // multi-part |
| | | else { |
| | | for ($n=0; $n<count($part[8]); $n++) |
| | | if (!is_array($part[8][$n])) |
| | | break; |
| | | $struct->real_mimetype = 'multipart/' . strtolower($part[8][$n]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | if ($struct->ctype_primary == 'message' && empty($struct->parts)) { |
| | | if (is_array($part[8]) && $di != 8) |
| | | $struct->parts[] = $this->_structure_part($part[8], ++$count, $struct->mime_id); |
| | | } |
| | | } |
| | | |
| | | // normalize filename property |
| | |
| | | return true; |
| | | |
| | | // convert charset (if text or message part) |
| | | if ($o_part->ctype_primary == 'text' || $o_part->ctype_primary == 'message') { |
| | | if ($body && ($o_part->ctype_primary == 'text' || $o_part->ctype_primary == 'message')) { |
| | | // assume default if no charset specified |
| | | if (empty($o_part->charset) || strtolower($o_part->charset) == 'us-ascii') |
| | | $o_part->charset = $this->default_charset; |
| | |
| | | $a_defaults = $a_out = array(); |
| | | |
| | | // Give plugins a chance to provide a list of mailboxes |
| | | $data = rcmail::get_instance()->plugins->exec_hook('list_mailboxes', |
| | | $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list', |
| | | array('root' => $root, 'filter' => $filter, 'mode' => 'LSUB')); |
| | | |
| | | if (isset($data['folders'])) { |
| | |
| | | function list_unsubscribed($root='', $filter='*') |
| | | { |
| | | // Give plugins a chance to provide a list of mailboxes |
| | | $data = rcmail::get_instance()->plugins->exec_hook('list_mailboxes', |
| | | $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list', |
| | | array('root' => $root, 'filter' => $filter, 'mode' => 'LIST')); |
| | | |
| | | if (isset($data['folders'])) { |
| | |
| | | // retrieve list of folders from IMAP server |
| | | $a_mboxes = $this->conn->listMailboxes($this->mod_mailbox($root), $filter); |
| | | } |
| | | |
| | | |
| | | $a_folders = array(); |
| | | if (!is_array($a_mboxes)) |
| | | $a_mboxes = array(); |