public function testRemoveWithDuplicateSequenceNumbers() { $map = new Horde_Imap_Client_Ids_Map(array(1 => 1, 2 => 2, 3 => 3)); // Inefficient sequence number remove with duplicate sequence numbers. $ids = new Horde_Imap_Client_Ids(array(), true); $ids->duplicates = true; $ids->add(array('2', '2')); $map->remove($ids); $this->assertEquals(array(1 => 1), $map->map); }
/** * @dataProvider clientSortProvider */ public function testClientSortProvider($sort, $expected, $locale) { $ids = new Horde_Imap_Client_Ids(); $pipeline = $this->socket_ob->pipeline(); foreach ($this->fetch_data as $val) { $token = new Horde_Imap_Client_Tokenize($val); $token->rewind(); $token->next(); $ids->add($token->next()); $this->socket_ob->doServerResponse($pipeline, $val); } $this->socket_ob->fetch_results = $pipeline->fetch; $sorted = $this->sort_ob->clientSort($ids, array('sort' => $sort)); $this->assertEquals(count($expected), count($sorted)); if (!$locale || class_exists('Collator')) { $this->assertEquals($expected, array_values($sorted)); } }
/** */ public function resolveIds(Horde_Imap_Client_Mailbox $mailbox, Horde_Imap_Client_Ids $ids, $convert = 0) { if (!$ids->special && (!$convert || !$ids->sequence && $convert == 1 || $ids->isEmpty())) { return clone $ids; } $uids = $this->_pop3Cache('uidl'); return $this->getIdsOb($ids->all ? array_values($uids) : array_intersect_keys($uids, $ids->ids)); }
/** * Resolves an IDs object into a list of IDs. * * @param Horde_Imap_Client_Mailbox $mailbox The mailbox. * @param Horde_Imap_Client_Ids $ids The Ids object. * @param integer $convert Convert to UIDs? * - 0: No * - 1: Only if $ids is not already a UIDs object * - 2: Always * * @return Horde_Imap_Client_Ids The list of IDs. */ public function resolveIds(Horde_Imap_Client_Mailbox $mailbox, Horde_Imap_Client_Ids $ids, $convert = 0) { $map = $this->_mailboxOb($mailbox)->map; if ($ids->special) { /* Optimization for ALL sequence searches. */ if (!$convert && $ids->all && $ids->sequence) { $res = $this->status($mailbox, Horde_Imap_Client::STATUS_MESSAGES); return $this->getIdsOb($res['messages'] ? '1:' . $res['messages'] : array(), true); } $convert = 2; } elseif (!$convert || !$ids->sequence && $convert == 1 || $ids->isEmpty()) { return clone $ids; } else { /* Do an all or nothing: either we have all the numbers/UIDs in * memory and can return, or just send the whole ID query to the * server. Any advantage we would get by a partial search are * outweighed by the complexities needed to make the search and * then merge back into the original results. */ $lookup = $map->lookup($ids); if (count($lookup) === count($ids)) { return $this->getIdsOb(array_values($lookup)); } } $query = new Horde_Imap_Client_Search_Query(); $query->ids($ids); $res = $this->search($mailbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH, Horde_Imap_Client::SEARCH_RESULTS_SAVE), 'sequence' => !$convert && $ids->sequence, 'sort' => array(Horde_Imap_Client::SORT_SEQUENCE))); /* Update mapping. */ if ($convert) { if ($ids->all) { $ids = $this->getIdsOb('1:' . count($res['match'])); } elseif ($ids->special) { return $res['match']; } /* Sanity checking (Bug #12911). */ $list1 = array_slice($ids->ids, 0, count($res['match'])); $list2 = $res['match']->ids; if (!empty($list1) && !empty($list2) && count($list1) === count($list2)) { $map->update(array_combine($list1, $list2)); } } return $res['match']; }
public function testReverse() { $ids = new Horde_Imap_Client_Ids(array(1, 3, 5)); $ids->reverse(); $this->assertEquals(array(5, 3, 1), $ids->ids); }
/** * Removes messages from the ID mapping. * * @param Horde_Imap_Client_Ids $ids IDs to remove. */ public function remove(Horde_Imap_Client_Ids $ids) { /* For sequence numbers, we need to reindex anytime we have an index * that appears equal to or after a previously seen index. If an IMAP * server is smart, it will expunge in reverse order instead. */ if ($ids->sequence) { $remove = $ids->ids; } else { $ids->sort(); $remove = array_reverse(array_keys($this->lookup($ids))); } if (empty($remove)) { return; } $this->sort(); /* Find the minimum sequence number to remove. We know entries before * this are untouched so no need to process them multiple times. */ $first = min($remove); $edit = $newids = array(); foreach (array_keys($this->_ids) as $i => $seq) { if ($seq >= $first) { $i += $seq == $first ? 0 : 1; $newids = array_slice($this->_ids, 0, $i, true); $edit = array_slice($this->_ids, $i + ($seq == $first ? 0 : 1), null, true); break; } } if (!empty($edit)) { foreach ($remove as $val) { $found = false; $tmp = array(); foreach (array_keys($edit) as $i => $seq) { if ($found) { $tmp[$seq - 1] = $edit[$seq]; } elseif ($seq >= $val) { $tmp = array_slice($edit, 0, $seq == $val ? $i : $i + 1, true); $found = true; } } $edit = $tmp; } } $this->_ids = $newids + $edit; }
/** * Search for messages within a given UID range. Only one message range * can be specified per query. * * @param Horde_Imap_Client_Ids $ids The list of UIDs to search. * @param boolean $not If true, do a 'NOT' search of the * UIDs. * @param array $opts Additional options: * - fuzzy: (boolean) If true, perform a fuzzy search. The IMAP server * MUST support RFC 6203. */ public function ids(Horde_Imap_Client_Ids $ids, $not = false, array $opts = array()) { if (!$ids->isEmpty()) { $this->_search['ids'] = array_filter(array('fuzzy' => !empty($opts['fuzzy']), 'ids' => $ids, 'not' => $not)); } }
function Execute($aparams) { require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "ClassPathMapper.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "ClassPathMapper" . DS . "Default.php"; require_once JPATH_SITE . DS . "Horde" . DS . "Autoloader" . DS . "Default.php"; $this->Log("Checking email account - {$aparams['name']}"); /*if (JRequest::getVar('email') != 1) return;*/ if (!$aparams['server']) { return $this->Log("No server specified"); } if (!$aparams['port']) { return $this->Log("No port specified"); } if (!$aparams['username']) { return $this->Log("No username specified"); } if (!$aparams['password']) { return $this->Log("No password specified"); } $this->params = $aparams; $this->connect(); if (!$this->conn) { return $this->Log("Unable to connect to server"); } // check if we have any messages at all $messages = $this->conn->search("INBOX"); $ids = $messages['match']; $ids->reverse(); $msgcount = $ids->count(); if ($msgcount == 0) { $this->Log("No messages"); $this->disconnect(); return; } else { $this->Log("{$msgcount} messaeges"); } // only get the first 20 messages to make sure web page response is quicker $maxmsgcount = 50; if ($msgcount < $maxmsgcount) { $maxmsgcount = $msgcount; } $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $query->structure(); $query->headerText(array('peek' => 1)); $uid = new Horde_Imap_Client_Ids(); for ($i = 0; $i < $maxmsgcount; $i++) { $uid->add($ids->ids[$i]); } $messages = $this->conn->fetch('INBOX', $query, array('ids' => $uid)); // for the most recent xx messages for ($i = 0; $i < $maxmsgcount; $i++) { $mapped = $ids->ids[$i]; $message = $messages->get($mapped); $this->Log("---------------------"); $this->Log("Processing message {$i} / {$mapped}"); // get headres of message if (!$this->GetHeaders($message)) { $this->Log("Error getting headers"); continue; } $subject = $this->headers->getValue("subject"); $this->Log("Subject : " . $subject); $this->from = $this->parse_addys($this->headers->getValue("from")); $this->to = $this->parse_addys($this->headers->getValue("to")); $this->Log("From : {$this->from[0]->mailbox}@{$this->from[0]->host} ({$this->from[0]->personal})"); if ($this->from[0]->mailbox == "no-reply") { // no-reply from form builder, attempt to find address in name $text = $this->from[0]->personal; //$text = str_replace("\"","",$text); $matches = array(); $pattern = "/(?:[a-z0-9!#\$%&'*+=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+=?^_`{|}~-]+)*|\"(?:[-\v\f-!#-[]-]|\\[-\t\v\f-])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[-\v\f-!-ZS-]|\\[-\t\v\f-])+)\\])/"; preg_match_all($pattern, $text, $matches); //print_p($matches); if (count($matches[0]) > 0) { // new email found $newemail = $matches[0][0]; list($name, $host) = explode("@", $newemail); $this->Log("No Reply message, New From address : {$name}@{$host}"); $this->from[0]->mailbox = $name; $this->from[0]->host = $host; $this->from[0]->personal = trim(str_replace("{$name}@{$host}", "", $this->from[0]->personal)); } } // skip if already read if ($aparams['type'] == "imap" && $this->IsMessageRead($message)) { $this->Log("Skipping read message"); continue; } // validate to address is required if (!$this->ValidateToAddress()) { $this->Log("Skipping invalid to address"); continue; } if (!$this->ValidateFromAddress()) { $this->Log("Skipping due to from address"); continue; } //check subject and to email to see if we have found a user and or ticket $subject = $this->headers->getValue("subject"); list($ticketid, $userid, $subject) = $this->ParseSubject($subject, $this->from[0]->mailbox . '@' . $this->from[0]->host); $this->subject = $subject; //echo "Ticket : $ticketid, $userid, $subject<br>"; // ok, need to get the message as we have decided its ok to use this ticket if ($ticketid < 1 && $userid < 1 && $this->params['newticketsfrom'] == "registered") { $this->Log("Skipping as registered only and not a registered email"); continue; } if ($this->params['allowrepliesonly'] && $ticketid < 1) { $this->Log("Skipping as not a reply"); continue; } // validate that the ticket is being replied to by user or handler if ($ticketid > 0) { $ticket = $this->getTicket($ticketid); if ($this->params['allowunknown'] < 1) { if ($ticket['user_id'] == 0 && $ticket['email'] != "{$this->from[0]->mailbox}@{$this->from[0]->host}") { $this->Log("Unknown email replying to the message, ignore the email ({$this->from[0]->mailbox}@{$this->from[0]->host})"); continue; } if ($userid != $ticket['handler_id'] && $userid != $ticket['user_id']) { $this->Log("Unknown user replying to the message, ignore the email ({$this->from[0]->mailbox}@{$this->from[0]->host})"); continue; } } } $this->GetMessage($message); $this->TrimMessage(); $messageid = 0; $filesok = true; // add to existing ticket if ($ticketid > 0) { // unreg ticket, just check email if ($ticket['user_id'] == 0) { //echo "Adding message to ticket - {$ticket['email']}<br>"; $this->DoTicketReply($ticketid, $userid, 0, $messageid); } else { if ($userid == $ticket['handler_id']) { //echo "Adding admin message to ticket - {$ticket['user_id']} -> {$userid}<br>"; $this->DoTicketReply($ticketid, $userid, 1, $messageid); } else { if ($userid == $ticket['user_id']) { //echo "Adding message to ticket - {$ticket['user_id']} -> {$userid}<br>"; $this->DoTicketReply($ticketid, $userid, 0, $messageid); if (!FSS_Settings::get('support_user_attach')) { $filesok = false; } } else { if ($this->params['allowunknown']) { // unreg ticket, add users reply $this->DoTicketReply($ticketid, 0, 0, $messageid); } } } } } else { if ($userid > 0) { //echo "Opening new ticket<br>"; $ticketid = $this->OpenNewTicket($userid, $messageid); } else { // open ticket for unregistered user //echo "Opening new ticket for unreg user<br>"; $ticketid = $this->OpenNewTicketUnreg($messageid); } } $ticket = $this->getTicket($ticketid); if ($userid > 0) { $user = JFactory::getUser($userid); $this->Log("Ticket ID : {$ticketid} - {$ticket['reference']}, UserID : {$userid} - {$user->name} ({$user->username})"); } else { $this->Log("Ticket ID : {$ticketid} - {$ticket['reference']}, Unregistered User"); } /* if ($filesok) $this->AttachFiles($ticketid, $userid, $messageid);*/ } //imap_expunge($this->conn); $this->disconnect(); //echo "</div>"; }