Example #1
0
 /**
  * Create the backend driver.
  *
  * @return mixed The backend driver.
  */
 public function createBackend()
 {
     $config = $this->getParams();
     $client = new rcube_imap_generic();
     if (isset($config['debug'])) {
         if ($config['debug'] == 'STDOUT') {
             $client->setDebug(true);
         } else {
             $this->_debug_log = fopen($config['debug'], 'a');
             $client->setDebug(true, array($this, 'debugLog'));
         }
     }
     $client->connect($config['host'], $config['username'], $config['password'], array('ssl_mode' => $config['secure'], 'port' => $config['port'], 'timeout' => 0, 'force_caps' => false));
     return $client;
 }
Example #2
0
    /**
     * Subscribe/unsubscribe a list of folders and update local cache
     */
    protected function change_subscription($folders, $mode)
    {
        $updated = false;

        if (!empty($folders)) {
            if (!$this->check_connection()) {
                return false;
            }

            foreach ((array)$folders as $i => $folder) {
                $folders[$i] = $folder;

                if ($mode == 'subscribe') {
                    $updated = $this->conn->subscribe($folder);
                }
                else if ($mode == 'unsubscribe') {
                    $updated = $this->conn->unsubscribe($folder);
                }
            }
        }

        // clear cached folders list(s)
        if ($updated) {
            $this->clear_cache('mailboxes', true);
        }

        return $updated;
    }
Example #3
0
 /**
  * Subscribe/unsubscribe a list of mailboxes and update local cache
  * @access private
  */
 private function _change_subscription($a_mboxes, $mode)
 {
     $updated = false;
     if (is_array($a_mboxes)) {
         foreach ($a_mboxes as $i => $mbox_name) {
             $mailbox = $this->mod_mailbox($mbox_name);
             $a_mboxes[$i] = $mailbox;
             if ($mode == 'subscribe') {
                 $updated = $this->conn->subscribe($mailbox);
             } else {
                 if ($mode == 'unsubscribe') {
                     $updated = $this->conn->unsubscribe($mailbox);
                 }
             }
         }
     }
     // get cached mailbox list
     if ($updated) {
         $a_mailbox_cache = $this->get_cache('mailboxes');
         if (!is_array($a_mailbox_cache)) {
             return $updated;
         }
         // modify cached list
         if ($mode == 'subscribe') {
             $a_mailbox_cache = array_merge($a_mailbox_cache, $a_mboxes);
         } else {
             if ($mode == 'unsubscribe') {
                 $a_mailbox_cache = array_diff($a_mailbox_cache, $a_mboxes);
             }
         }
         // write mailboxlist to cache
         $this->update_cache('mailboxes', $this->_sort_mailbox_list($a_mailbox_cache));
     }
     return $updated;
 }
Example #4
0
 /**
  * Find UID of the specified message sequence ID
  *
  * @param int    $id     Message (sequence) ID
  * @param string $folder Folder name
  *
  * @return int Message UID
  */
 public function id2uid($id, $folder = null)
 {
     if (!strlen($folder)) {
         $folder = $this->folder;
     }
     if (!$this->check_connection()) {
         return null;
     }
     return $this->conn->ID2UID($folder, $id);
 }
 /**
  * Test for uncompressMessageSet
  */
 function test_uncompressMessageSet()
 {
     $result = rcube_imap_generic::uncompressMessageSet(null);
     $this->assertSame(array(), $result);
     $this->assertCount(0, $result);
     $result = rcube_imap_generic::uncompressMessageSet('1');
     $this->assertSame(array(1), $result);
     $this->assertCount(1, $result);
     $result = rcube_imap_generic::uncompressMessageSet('1:3');
     $this->assertSame(array(1, 2, 3), $result);
     $this->assertCount(3, $result);
 }
 /**
  * Test for tokenizeResponse
  */
 function test_tokenizeResponse()
 {
     $response = "test brack[et] {1}\r\na {0}\r\n (item1 item2)";
     $result = rcube_imap_generic::tokenizeResponse($response, 1);
     $this->assertSame("test", $result);
     $result = rcube_imap_generic::tokenizeResponse($response, 1);
     $this->assertSame("brack[et]", $result);
     $result = rcube_imap_generic::tokenizeResponse($response, 1);
     $this->assertSame("a", $result);
     $result = rcube_imap_generic::tokenizeResponse($response, 1);
     $this->assertSame("", $result);
     $result = rcube_imap_generic::tokenizeResponse($response, 1);
     $this->assertSame(array('item1', 'item2'), $result);
 }
Example #7
0
 /**
  * Subscribe/unsubscribe a list of mailboxes and update local cache
  * @access private
  */
 private function _change_subscription($a_mboxes, $mode)
 {
     $updated = false;
     if (is_array($a_mboxes)) {
         foreach ($a_mboxes as $i => $mailbox) {
             $a_mboxes[$i] = $mailbox;
             if ($mode == 'subscribe') {
                 $updated = $this->conn->subscribe($mailbox);
             } else {
                 if ($mode == 'unsubscribe') {
                     $updated = $this->conn->unsubscribe($mailbox);
                 }
             }
         }
     }
     // clear cached mailbox list(s)
     if ($updated) {
         $this->clear_cache('mailboxes', true);
     }
     return $updated;
 }
 /**
  * Parse message UIDs input
  *
  * @param mixed $uids UIDs array or comma-separated list or '*' or '1:*'
  *
  * @return array Two elements array with UIDs converted to list and ALL flag
  */
 protected function parse_uids($uids)
 {
     if ($uids === '*' || $uids === '1:*') {
         if (empty($this->search_set)) {
             $uids = '1:*';
             $all = true;
         } else {
             $uids = join(',', $this->search_set->get());
         }
     } else {
         if (is_array($uids)) {
             $uids = join(',', $uids);
         } else {
             if (strpos($uids, ':')) {
                 $uids = join(',', rcube_imap_generic::uncompressMessageSet($uids));
             }
         }
         if (preg_match('/[^0-9,]/', $uids)) {
             $uids = '';
         }
     }
     return array($uids, (bool) $all);
 }
 /**
  * Synchronizes the mailbox.
  *
  * @param string $mailbox Folder name
  */
 function synchronize($mailbox)
 {
     // RFC4549: Synchronization Operations for Disconnected IMAP4 Clients
     // RFC4551: IMAP Extension for Conditional STORE Operation
     //          or Quick Flag Changes Resynchronization
     // RFC5162: IMAP Extensions for Quick Mailbox Resynchronization
     // @TODO: synchronize with other methods?
     $qresync = $this->imap->get_capability('QRESYNC');
     $condstore = $qresync ? true : $this->imap->get_capability('CONDSTORE');
     if (!$qresync && !$condstore) {
         return;
     }
     // Get stored index
     $index = $this->get_index_row($mailbox);
     // database is empty
     if (empty($index)) {
         // set the flag that DB was already queried for index
         // this way we'll be able to skip one SELECT in get_index()
         $this->icache[$mailbox]['index_queried'] = true;
         return;
     }
     $this->icache[$mailbox]['index'] = $index;
     // no last HIGHESTMODSEQ value
     if (empty($index['modseq'])) {
         return;
     }
     if (!$this->imap->check_connection()) {
         return;
     }
     // Enable QRESYNC
     $res = $this->imap->conn->enable($qresync ? 'QRESYNC' : 'CONDSTORE');
     if ($res === false) {
         return;
     }
     // Close mailbox if already selected to get most recent data
     if ($this->imap->conn->selected == $mailbox) {
         $this->imap->conn->close();
     }
     // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.)
     $mbox_data = $this->imap->folder_data($mailbox);
     if (empty($mbox_data)) {
         return;
     }
     // Check UIDVALIDITY
     if ($index['validity'] != $mbox_data['UIDVALIDITY']) {
         $this->clear($mailbox);
         return;
     }
     // QRESYNC not supported on specified mailbox
     if (!empty($mbox_data['NOMODSEQ']) || empty($mbox_data['HIGHESTMODSEQ'])) {
         return;
     }
     // Nothing new
     if ($mbox_data['HIGHESTMODSEQ'] == $index['modseq']) {
         return;
     }
     $uids = array();
     $removed = array();
     // Get known UIDs
     if ($this->mode & self::MODE_MESSAGE) {
         $sql_result = $this->db->query("SELECT `uid`" . " FROM {$this->messages_table}" . " WHERE `user_id` = ?" . " AND `mailbox` = ?", $this->userid, $mailbox);
         while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
             $uids[] = $sql_arr['uid'];
         }
     }
     // Synchronize messages data
     if (!empty($uids)) {
         // Get modified flags and vanished messages
         // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED)
         $result = $this->imap->conn->fetch($mailbox, $uids, true, array('FLAGS'), $index['modseq'], $qresync);
         if (!empty($result)) {
             foreach ($result as $msg) {
                 $uid = $msg->uid;
                 // Remove deleted message
                 if ($this->skip_deleted && !empty($msg->flags['DELETED'])) {
                     $removed[] = $uid;
                     // Invalidate index
                     $index['valid'] = false;
                     continue;
                 }
                 $flags = 0;
                 if (!empty($msg->flags)) {
                     foreach ($this->flags as $idx => $flag) {
                         if (!empty($msg->flags[$flag])) {
                             $flags += $idx;
                         }
                     }
                 }
                 $this->db->query("UPDATE {$this->messages_table}" . " SET `flags` = ?, `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . " WHERE `user_id` = ?" . " AND `mailbox` = ?" . " AND `uid` = ?" . " AND `flags` <> ?", $flags, $this->userid, $mailbox, $uid, $flags);
             }
         }
         // VANISHED found?
         if ($qresync) {
             $mbox_data = $this->imap->folder_data($mailbox);
             // Removed messages found
             $uids = rcube_imap_generic::uncompressMessageSet($mbox_data['VANISHED']);
             if (!empty($uids)) {
                 $removed = array_merge($removed, $uids);
                 // Invalidate index
                 $index['valid'] = false;
             }
         }
         // remove messages from database
         if (!empty($removed)) {
             $this->remove_message($mailbox, $removed);
         }
     }
     $sort_field = $index['sort_field'];
     $sort_order = $index['object']->get_parameters('ORDER');
     $exists = true;
     // Validate index
     if (!$this->validate($mailbox, $index, $exists)) {
         // Invalidate (remove) thread index
         // if $exists=false it was already removed in validate()
         if ($exists) {
             $this->remove_thread($mailbox);
         }
         // Update index
         $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
     } else {
         $data = $index['object'];
     }
     // update index and/or HIGHESTMODSEQ value
     $this->add_index_row($mailbox, $sort_field, $data, $mbox_data, $exists);
     // update internal cache for get_index()
     $this->icache[$mailbox]['index']['object'] = $data;
 }
 /**
  * CAPABILITY response parser
  */
 protected function parseCapability($str, $trusted = false)
 {
     $str = preg_replace('/^\\* CAPABILITY /i', '', $str);
     $this->capability = explode(' ', strtoupper($str));
     if (!empty($this->prefs['disabled_caps'])) {
         $this->capability = array_diff($this->capability, $this->prefs['disabled_caps']);
     }
     if (!isset($this->prefs['literal+']) && in_array('LITERAL+', $this->capability)) {
         $this->prefs['literal+'] = true;
     }
     if (preg_match('/(\\[| )MUPDATE=.*/', $str)) {
         self::$mupdate = true;
     }
     if ($trusted) {
         $this->capability_readed = true;
     }
 }
 /**
  * Return all messages in the result.
  *
  * @return array List of message identifiers
  */
 public function get_compressed()
 {
     if (empty($this->raw_data)) {
         return '';
     }
     return rcube_imap_generic::compressMessageSet($this->get());
 }
Example #12
0
 private function archive($uids, $verbose = true)
 {
     global $E_SESSION;
     $rcmail = rcmail::get_instance();
     $path = getcwd();
     chdir(str_replace(array('/modules/CRM/Roundcube/RC', '\\modules\\CRM\\Roundcube\\RC'), '', $path));
     $msgs = array();
     if (!is_array($uids)) {
         $uids = $uids->get();
     }
     foreach ($uids as $uid) {
         $msg = new rcube_message($uid);
         if ($msg === null || empty($msg->headers)) {
             if ($verbose) {
                 $rcmail->output->command('display_message', 'messageopenerror', 'error');
             }
             return false;
         } else {
             $msgs[$uid] = $msg;
         }
     }
     $map = array();
     foreach ($msgs as $k => $msg) {
         $sends = $rcmail->storage->decode_address_list($msg->headers->to);
         $map[$k] = array();
         foreach ($sends as $send) {
             $addr = $send['mailto'];
             $ret = $this->look_contact($addr);
             $map[$k] = array_merge($map[$k], $ret);
         }
         $addr = $rcmail->storage->decode_address_list($msg->headers->from);
         if ($addr) {
             $addr = array_shift($addr);
         }
         if (!isset($addr['mailto']) || !$addr['mailto']) {
             $map[$k] = false;
             continue;
         }
         $ret = $this->look_contact($addr['mailto']);
         $map[$k] = array_merge($map[$k], $ret);
     }
     if (!isset($_SESSION['force_archive'])) {
         $_SESSION['force_archive'] = array();
     }
     foreach ($map as $k => $ret) {
         if (!$ret && !isset($_SESSION['force_archive'][$k]) && $verbose) {
             $_SESSION['force_archive'][$k] = 1;
             $rcmail->output->command('display_message', $this->gettext('contactnotfound'), 'error');
             return false;
         }
     }
     $attachments_dir = DATA_DIR . '/CRM_Roundcube/attachments/';
     $epesi_mails = array();
     if (!file_exists($attachments_dir)) {
         mkdir($attachments_dir);
     }
     foreach ($msgs as $k => $msg) {
         $contacts = $map[$k];
         $mime_map = array();
         foreach ($msg->mime_parts as $mid => $m) {
             $mime_map[$m->mime_id] = md5($k . microtime(true) . $mid);
         }
         if ($msg->has_html_part()) {
             //            $body = $msg->first_html_part();
             foreach ($msg->mime_parts as $mime_id => $part) {
                 $mimetype = strtolower($part->ctype_primary . '/' . $part->ctype_secondary);
                 if ($mimetype == 'text/html') {
                     $body = $rcmail->storage->get_message_part($msg->uid, $mime_id, $part);
                     if (isset($part->replaces)) {
                         $cid_map = $part->replaces;
                     } else {
                         $cid_map = array();
                     }
                     break;
                 }
             }
             foreach ($cid_map as $k => &$v) {
                 if (preg_match('/_part=(.*?)&/', $v, $matches)) {
                     $mid = $matches[1];
                     if (isset($mime_map[$mid])) {
                         $v = 'get.php?' . http_build_query(array('mail_id' => '__MAIL_ID__', 'mime_id' => $mime_map[$mid]));
                     }
                 } else {
                     unset($cid_map[$k]);
                 }
             }
             $body = rcmail_wash_html($body, array('safe' => true, 'inline_html' => true), $cid_map);
         } else {
             $body = '<pre>' . $msg->first_text_part() . '</pre>';
         }
         $date = rcube_imap_generic::strToTime($msg->get_header('DATE'));
         $headers = array();
         foreach ($msg->headers as $k => $v) {
             if (is_string($v) && $k != 'from' && $k != 'to' && $k != 'body_structure') {
                 $headers[] = $k . ': ' . rcube_mime::decode_mime_string((string) $v);
             }
         }
         $message_id = str_replace(array('<', '>'), '', $msg->get_header('MESSAGE-ID'));
         if (Utils_RecordBrowserCommon::get_records_count('rc_mails', array('message_id' => $message_id)) > 0) {
             $rcmail->output->command('display_message', $this->gettext('archived_duplicate'), 'warning');
             return false;
         }
         $employee = DB::GetOne('SELECT id FROM contact_data_1 WHERE active=1 AND f_login=%d', array($E_SESSION['user']));
         $data = array('message_id' => $message_id, 'references' => $msg->get_header('REFERENCES'), 'contacts' => $contacts, 'date' => $date, 'subject' => substr($msg->subject, 0, 256), 'body' => $body, 'headers_data' => implode("\n", $headers), 'from' => $rcmail->storage->decode_header($msg->headers->from), 'to' => $rcmail->storage->decode_header($msg->headers->to), 'employee' => $employee);
         $id = Utils_RecordBrowserCommon::new_record('rc_mails', $data);
         $epesi_mails[] = $id;
         foreach ($contacts as $c) {
             list($rs, $con_id) = explode(':', $c);
             if ($rs == 'P') {
                 Utils_WatchdogCommon::new_event('contact', $con_id, 'N_New mail');
             } else {
                 Utils_WatchdogCommon::new_event('company', $con_id, 'N_New mail');
             }
         }
         Utils_WatchdogCommon::new_event('contact', $employee, 'N_New mail');
         /*DB::Execute('INSERT INTO rc_mails_data_1(created_on,created_by,f_contacts,f_date,f_employee,f_subject,f_body,f_headers_data,f_direction) VALUES(%T,%d,%s,%T,%d,%s,%s,%s,%b)',array(
                       time(),$E_SESSION['user'],$contacts,$date,$employee,substr($msg->subject,0,256),$body,implode("\n",$headers),$sent_mbox));
           $id = DB::Insert_ID('rc_mails_data_1','id');*/
         foreach ($msg->mime_parts as $mid => $m) {
             if (!$m->disposition) {
                 continue;
             }
             if (isset($cid_map['cid:' . $m->content_id])) {
                 $attachment = 0;
             } else {
                 $attachment = 1;
             }
             DB::Execute('INSERT INTO rc_mails_attachments(mail_id,type,name,mime_id,attachment) VALUES(%d,%s,%s,%s,%b)', array($id, $m->mimetype, $m->filename, $mime_map[$m->mime_id], $attachment));
             if (!file_exists($attachments_dir . $id)) {
                 mkdir($attachments_dir . $id);
             }
             $fp = fopen($attachments_dir . $id . '/' . $mime_map[$m->mime_id], 'w');
             $msg->get_part_content($m->mime_id, $fp);
             fclose($fp);
         }
     }
     //$rcmail->output->command('delete_messages');
     $E_SESSION['rc_mails_cp'] = $epesi_mails;
     chdir($path);
     return true;
 }
Example #13
0
 /**
  * Synchronizes the mailbox.
  *
  * @param string $mailbox Folder name
  */
 function synchronize($mailbox)
 {
     // RFC4549: Synchronization Operations for Disconnected IMAP4 Clients
     // RFC4551: IMAP Extension for Conditional STORE Operation
     //          or Quick Flag Changes Resynchronization
     // RFC5162: IMAP Extensions for Quick Mailbox Resynchronization
     // @TODO: synchronize with other methods?
     $qresync = $this->imap->get_capability('QRESYNC');
     $condstore = $qresync ? true : $this->imap->get_capability('CONDSTORE');
     if (!$qresync && !$condstore) {
         return;
     }
     // Get stored index
     $index = $this->get_index_row($mailbox);
     // database is empty
     if (empty($index)) {
         // set the flag that DB was already queried for index
         // this way we'll be able to skip one SELECT in get_index()
         $this->icache[$mailbox]['index_queried'] = true;
         return;
     }
     $this->icache[$mailbox]['index'] = $index;
     // no last HIGHESTMODSEQ value
     if (empty($index['modseq'])) {
         return;
     }
     // NOTE: make sure the mailbox isn't selected, before
     // enabling QRESYNC and invoking SELECT
     if ($this->imap->conn->selected !== null) {
         $this->imap->conn->close();
     }
     // Enable QRESYNC
     $res = $this->imap->conn->enable($qresync ? 'QRESYNC' : 'CONDSTORE');
     if (!is_array($res)) {
         return;
     }
     // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.)
     $mbox_data = $this->imap->mailbox_data($mailbox);
     if (empty($mbox_data)) {
         return;
     }
     // Check UIDVALIDITY
     if ($index['validity'] != $mbox_data['UIDVALIDITY']) {
         $this->clear($mailbox);
         return;
     }
     // QRESYNC not supported on specified mailbox
     if (!empty($mbox_data['NOMODSEQ']) || empty($mbox_data['HIGHESTMODSEQ'])) {
         return;
     }
     // Nothing new
     if ($mbox_data['HIGHESTMODSEQ'] == $index['modseq']) {
         return;
     }
     // Get known uids
     $uids = array();
     $sql_result = $this->db->query("SELECT uid" . " FROM " . get_table_name('cache_messages') . " WHERE user_id = ?" . " AND mailbox = ?", $this->userid, $mailbox);
     while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
         $uids[] = $sql_arr['uid'];
     }
     // No messages in database, nothing to sync
     if (empty($uids)) {
         return;
     }
     // Get modified flags and vanished messages
     // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED)
     $result = $this->imap->conn->fetch($mailbox, !empty($uids) ? $uids : '1:*', true, array('FLAGS'), $index['modseq'], $qresync);
     $invalidated = false;
     if (!empty($result)) {
         foreach ($result as $id => $msg) {
             $uid = $msg->uid;
             // Remove deleted message
             if ($this->skip_deleted && !empty($msg->flags['DELETED'])) {
                 $this->remove_message($mailbox, $uid);
                 if (!$invalidated) {
                     $invalidated = true;
                     // Invalidate thread indexes (?)
                     $this->remove_thread($mailbox);
                     // Invalidate index
                     $index['valid'] = false;
                 }
                 continue;
             }
             $flags = 0;
             if (!empty($msg->flags)) {
                 foreach ($this->flags as $idx => $flag) {
                     if (!empty($msg->flags[$flag])) {
                         $flags += $idx;
                     }
                 }
             }
             $this->db->query("UPDATE " . get_table_name('cache_messages') . " SET flags = ?, changed = " . $this->db->now() . " WHERE user_id = ?" . " AND mailbox = ?" . " AND uid = ?" . " AND flags <> ?", $flags, $this->userid, $mailbox, $uid, $flags);
         }
     }
     // Get VANISHED
     if ($qresync) {
         $mbox_data = $this->imap->mailbox_data($mailbox);
         // Removed messages
         if (!empty($mbox_data['VANISHED'])) {
             $uids = rcube_imap_generic::uncompressMessageSet($mbox_data['VANISHED']);
             if (!empty($uids)) {
                 // remove messages from database
                 $this->remove_message($mailbox, $uids);
                 // Invalidate thread indexes (?)
                 $this->remove_thread($mailbox);
                 // Invalidate index
                 $index['valid'] = false;
             }
         }
     }
     $sort_field = $index['sort_field'];
     $sort_order = $index['sort_order'];
     $exists = true;
     // Validate index
     if (!$this->validate($mailbox, $index, $exists)) {
         // Update index
         $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data);
     } else {
         $data = array_combine($index['seq'], $index['uid']);
     }
     // update index and/or HIGHESTMODSEQ value
     $this->add_index_row($mailbox, $sort_field, $sort_order, $data, $mbox_data, $exists);
     // update internal cache for get_index()
     $this->icache[$mailbox]['index']['result'] = $data;
 }