| | |
| | | $attempt = 0; |
| | | do { |
| | | $data = rcmail::get_instance()->plugins->exec_hook('imap_connect', |
| | | array('host' => $host, 'user' => $user, 'attempt' => ++$attempt)); |
| | | array_merge($this->options, array('host' => $host, 'user' => $user, |
| | | 'attempt' => ++$attempt))); |
| | | |
| | | if (!empty($data['pass'])) |
| | | $pass = $data['pass']; |
| | | |
| | | $this->conn->connect($data['host'], $data['user'], $pass, $this->options); |
| | | $this->conn->connect($data['host'], $data['user'], $pass, $data); |
| | | } while(!$this->conn->connected() && $data['retry']); |
| | | |
| | | $this->host = $data['host']; |
| | |
| | | function set_search_set($str=null, $msgs=null, $charset=null, $sort_field=null, $threads=false, $sorted=false) |
| | | { |
| | | if (is_array($str) && $msgs == null) |
| | | list($str, $msgs, $charset, $sort_field, $threads) = $str; |
| | | list($str, $msgs, $charset, $sort_field, $threads, $sorted) = $str; |
| | | if ($msgs === false) |
| | | $msgs = array(); |
| | | else if ($msgs != null && !is_array($msgs)) |
| | |
| | | $mailbox = $this->mailbox; |
| | | } |
| | | |
| | | return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, false, $slice); |
| | | return $this->_list_headers($mailbox, $page, $sort_field, $sort_order, $slice); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | // fetch specified header for all messages and sort |
| | | else if ($msg_index = $this->conn->fetchHeaderIndex($mailbox, "1:*", |
| | | $this->sort_field, $this->skip_deleted, true) |
| | | $this->sort_field, $this->skip_deleted) |
| | | ) { |
| | | asort($msg_index); // ASC |
| | | $msg_index = array_keys($msg_index); |
| | | list($begin, $end) = $this->_get_message_range(count($msg_index), $page); |
| | | $msg_index = array_slice($msg_index, $begin, $end-$begin); |
| | | $is_uid = true; |
| | | |
| | | if ($slice) |
| | | $msg_index = array_slice($msg_index, ($this->sort_order == 'DESC' ? 0 : -$slice), $slice); |
| | | |
| | | // fetch reqested headers from server |
| | | $a_msg_headers = $this->fetch_headers($mailbox, $msg_index, true); |
| | | $a_msg_headers = $this->fetch_headers($mailbox, $msg_index); |
| | | } |
| | | |
| | | // return empty array if no messages found |
| | |
| | | |
| | | if (!empty($parents)) { |
| | | $headers[$idx]->parent_uid = end($parents); |
| | | if (!$header->seen) |
| | | if (empty($header->flags['SEEN'])) |
| | | $headers[$parents[0]]->unread_children++; |
| | | } |
| | | array_push($parents, $header->uid); |
| | |
| | | // use message index sort as default sorting |
| | | if (!$sort_field) { |
| | | if ($this->skip_deleted) { |
| | | $a_index = $this->_search_index($mailbox, 'ALL'); |
| | | $a_index = $this->conn->search($mailbox, 'ALL UNDELETED'); |
| | | // I didn't found that SEARCH should return sorted IDs |
| | | if (is_array($a_index)) |
| | | sort($a_index); |
| | | } else if ($max = $this->_messagecount($mailbox)) { |
| | | $a_index = range(1, $max); |
| | | } |
| | |
| | | } |
| | | |
| | | $struct = &$this->_structure_part($structure, 0, '', $headers); |
| | | $struct->headers = get_object_vars($headers); |
| | | |
| | | // don't trust given content-type |
| | | if (empty($struct->parts) && !empty($struct->headers['ctype'])) { |
| | | if (empty($struct->parts) && !empty($headers->ctype)) { |
| | | $struct->mime_id = '1'; |
| | | $struct->mimetype = strtolower($struct->headers['ctype']); |
| | | $struct->mimetype = strtolower($headers->ctype); |
| | | list($struct->ctype_primary, $struct->ctype_secondary) = explode('/', $struct->mimetype); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // convert charset (if text or message part) |
| | | if ($body && !$skip_charset_conv && |
| | | preg_match('/^(text|message)$/', $o_part->ctype_primary) |
| | | ) { |
| | | if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { |
| | | $o_part->charset = $this->default_charset; |
| | | if ($body && preg_match('/^(text|message)$/', $o_part->ctype_primary)) { |
| | | // Remove NULL characters (#1486189) |
| | | $body = str_replace("\x00", '', $body); |
| | | |
| | | if (!$skip_charset_conv) { |
| | | if (!$o_part->charset || strtoupper($o_part->charset) == 'US-ASCII') { |
| | | // try to extract charset information from HTML meta tag (#1488125) |
| | | if ($o_part->ctype_secondary == 'html' && preg_match('/<meta[^>]+charset=([a-z0-9-]+)/i', $body, $m)) |
| | | $o_part->charset = strtoupper($m[1]); |
| | | else |
| | | $o_part->charset = $this->default_charset; |
| | | } |
| | | $body = rcube_charset_convert($body, $o_part->charset); |
| | | } |
| | | $body = rcube_charset_convert($body, $o_part->charset); |
| | | } |
| | | |
| | | return $body; |
| | |
| | | * @param string $headers Headers string if $message contains only the body |
| | | * @param boolean $is_file True if $message is a filename |
| | | * |
| | | * @return boolean True on success, False on error |
| | | * @return int|bool Appended message UID or True on success, False on error |
| | | */ |
| | | function save_message($mailbox, &$message, $headers='', $is_file=false) |
| | | { |
| | |
| | | |
| | | // make sure mailbox exists |
| | | if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) { |
| | | if (in_array($to_mbox, $this->default_folders)) |
| | | $this->create_mailbox($to_mbox, true); |
| | | else |
| | | if (in_array($to_mbox, $this->default_folders)) { |
| | | if (!$this->create_mailbox($to_mbox, true)) { |
| | | return false; |
| | | } |
| | | } |
| | | else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | $config = rcmail::get_instance()->config; |
| | |
| | | |
| | | // make sure mailbox exists |
| | | if ($to_mbox != 'INBOX' && !$this->mailbox_exists($to_mbox)) { |
| | | if (in_array($to_mbox, $this->default_folders)) |
| | | $this->create_mailbox($to_mbox, true); |
| | | else |
| | | if (in_array($to_mbox, $this->default_folders)) { |
| | | if (!$this->create_mailbox($to_mbox, true)) { |
| | | return false; |
| | | } |
| | | } |
| | | else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // copy messages |
| | |
| | | /** |
| | | * Public method for listing subscribed folders |
| | | * |
| | | * @param string $root Optional root folder |
| | | * @param string $name Optional name pattern |
| | | * @param string $filter Optional filter |
| | | * @param string $root Optional root folder |
| | | * @param string $name Optional name pattern |
| | | * @param string $filter Optional filter |
| | | * @param string $rights Optional ACL requirements |
| | | * @param bool $skip_sort Enable to return unsorted list (for better performance) |
| | | * |
| | | * @return array List of mailboxes/folders |
| | | * @return array List of folders |
| | | * @access public |
| | | */ |
| | | function list_mailboxes($root='', $name='*', $filter=null) |
| | | function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) |
| | | { |
| | | $a_mboxes = $this->_list_mailboxes($root, $name, $filter); |
| | | $cache_key = $root.':'.$name; |
| | | if (!empty($filter)) { |
| | | $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter)); |
| | | } |
| | | $cache_key .= ':'.$rights; |
| | | $cache_key = 'mailboxes.'.md5($cache_key); |
| | | |
| | | // get cached folder list |
| | | $a_mboxes = $this->get_cache($cache_key); |
| | | if (is_array($a_mboxes)) { |
| | | return $a_mboxes; |
| | | } |
| | | |
| | | $a_mboxes = $this->_list_mailboxes($root, $name, $filter, $rights); |
| | | |
| | | if (!is_array($a_mboxes)) { |
| | | return array(); |
| | | } |
| | | |
| | | // filter folders list according to rights requirements |
| | | if ($rights && $this->get_capability('ACL')) { |
| | | $a_mboxes = $this->filter_rights($a_mboxes, $rights); |
| | | } |
| | | |
| | | // INBOX should always be available |
| | | if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) { |
| | | array_unshift($a_mboxes, 'INBOX'); |
| | | } |
| | | |
| | | // sort mailboxes |
| | | $a_mboxes = $this->_sort_mailbox_list($a_mboxes); |
| | | // sort mailboxes (always sort for cache) |
| | | if (!$skip_sort || $this->cache) { |
| | | $a_mboxes = $this->_sort_mailbox_list($a_mboxes); |
| | | } |
| | | |
| | | // write mailboxlist to cache |
| | | $this->update_cache($cache_key, $a_mboxes); |
| | | |
| | | return $a_mboxes; |
| | | } |
| | |
| | | * @param string $root Optional root folder |
| | | * @param string $name Optional name pattern |
| | | * @param mixed $filter Optional filter |
| | | * @param string $rights Optional ACL requirements |
| | | * |
| | | * @return array List of mailboxes/folders |
| | | * @see rcube_imap::list_mailboxes() |
| | | * @access private |
| | | */ |
| | | private function _list_mailboxes($root='', $name='*', $filter=null) |
| | | private function _list_mailboxes($root='', $name='*', $filter=null, $rights=null) |
| | | { |
| | | $cache_key = $root.':'.$name; |
| | | if (!empty($filter)) { |
| | | $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter)); |
| | | } |
| | | |
| | | $cache_key = 'mailboxes.'.md5($cache_key); |
| | | |
| | | // get cached folder list |
| | | $a_mboxes = $this->get_cache($cache_key); |
| | | if (is_array($a_mboxes)) { |
| | | return $a_mboxes; |
| | | } |
| | | |
| | | $a_defaults = $a_out = array(); |
| | | |
| | | // Give plugins a chance to provide a list of mailboxes |
| | |
| | | $a_folders = $data['folders']; |
| | | } |
| | | else if (!$this->conn->connected()) { |
| | | return array(); |
| | | return null; |
| | | } |
| | | else { |
| | | // Server supports LIST-EXTENDED, we can use selection options |
| | |
| | | $a_folders = array(); |
| | | } |
| | | |
| | | // write mailboxlist to cache |
| | | $this->update_cache($cache_key, $a_folders); |
| | | |
| | | return $a_folders; |
| | | } |
| | | |
| | |
| | | /** |
| | | * Get a list of all folders available on the IMAP server |
| | | * |
| | | * @param string $root IMAP root dir |
| | | * @param string $name Optional name pattern |
| | | * @param mixed $filter Optional filter |
| | | * @param string $root IMAP root dir |
| | | * @param string $name Optional name pattern |
| | | * @param mixed $filter Optional filter |
| | | * @param string $rights Optional ACL requirements |
| | | * @param bool $skip_sort Enable to return unsorted list (for better performance) |
| | | * |
| | | * @return array Indexed array with folder names |
| | | */ |
| | | function list_unsubscribed($root='', $name='*', $filter=null) |
| | | function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) |
| | | { |
| | | // @TODO: caching |
| | | // Give plugins a chance to provide a list of mailboxes |
| | |
| | | array_unshift($a_mboxes, 'INBOX'); |
| | | } |
| | | |
| | | // filter folders list according to rights requirements |
| | | if ($rights && $this->get_capability('ACL')) { |
| | | $a_folders = $this->filter_rights($a_folders, $rights); |
| | | } |
| | | |
| | | // filter folders and sort them |
| | | $a_mboxes = $this->_sort_mailbox_list($a_mboxes); |
| | | if (!$skip_sort) { |
| | | $a_mboxes = $this->_sort_mailbox_list($a_mboxes); |
| | | } |
| | | |
| | | return $a_mboxes; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Filter the given list of folders according to access rights |
| | | */ |
| | | private function filter_rights($a_folders, $rights) |
| | | { |
| | | $regex = '/('.$rights.')/'; |
| | | foreach ($a_folders as $idx => $folder) { |
| | | $myrights = join('', (array)$this->my_rights($folder)); |
| | | if ($myrights !== null && !preg_match($regex, $myrights)) |
| | | unset($a_folders[$idx]); |
| | | } |
| | | |
| | | return $a_folders; |
| | | } |
| | | |
| | | |
| | |
| | | if ($this->conn->selected != $mailbox) { |
| | | if ($this->conn->select($mailbox)) |
| | | $this->mailbox = $mailbox; |
| | | else |
| | | return null; |
| | | } |
| | | |
| | | $data = $this->conn->data; |
| | |
| | | } |
| | | |
| | | if (!empty($options['rights'])) { |
| | | $options['norename'] = !in_array('x', $options['rights']); |
| | | $options['norename'] = !in_array('x', $options['rights']) && !in_array('d', $options['rights']); |
| | | |
| | | if (!$options['noselect']) { |
| | | $options['noselect'] = !in_array('r', $options['rights']); |
| | | } |
| | |
| | | $this->icache['options'] = $options; |
| | | |
| | | return $options; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Synchronizes messages cache. |
| | | * |
| | | * @param string $mailbox Folder name |
| | | */ |
| | | public function mailbox_sync($mailbox) |
| | | { |
| | | if ($mcache = $this->get_mcache_engine()) { |
| | | $mcache->synchronize($mailbox); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | // @TODO: Honor MAXSIZE and DEPTH options |
| | | foreach ($queries as $attrib => $entry) |
| | | if ($result = $this->conn->getAnnotation($mailbox, $entry, $attrib)) |
| | | $res = array_merge($res, $result); |
| | | $res = array_merge_recursive($res, $result); |
| | | |
| | | return $res; |
| | | } |