/** * 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; }
/** * 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; }
/** * 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; }
/** * 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); }
/** * 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()); }
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; }
/** * 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; }