Skip to content

Commit

Permalink
Poll for messages to add after a FilterType change as well.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrubinsk committed Jan 8, 2015
1 parent ba0c896 commit 92c59e6
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 42 deletions.
18 changes: 15 additions & 3 deletions framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,30 @@ class Horde_ActiveSync_Folder_Imap extends Horde_ActiveSync_Folder_Base implemen
* @param array $flags A hash of message read flags, keyed by UID.
* @param array $categories A hash of custom message flags, keyed by UID.
* @since 2.17.0
* @param boolean $resetMinUid If true, reset the minimum UID. Should be
* used when FilterType has widened and
* messages older than originally selected are
* being returned. @since 2.24.0
*/
public function setChanges(array $messages, array $flags = array(), array $categories = array())
public function setChanges(array $messages, array $flags = array(), array $categories = array(), $resetMinUid = false)
{
$uidnext = $this->uidnext();
$minuid = $this->minuid();
$modseq = $this->modseq();
foreach ($messages as $uid) {
if ($uid >= $uidnext) {
// new (to us) message.
$this->_added[] = $uid;
} elseif ($uid >= $minuid) {
} elseif ($uid >= $minuid || $resetMinUid) {
if ($modseq > 0) {
$this->_changed[] = $uid;
// MODSEQ capable server, either a changed message, or
// one that was previously outside of FilterType but is now
// within.
if (array_search($uid, $this->_messages)) {
$this->_changed[] = $uid;
} else {
$this->_added[] = $uid;
}
} else {
if (empty($this->_messages[$uid])) {
// Do not know about this message
Expand Down
130 changes: 91 additions & 39 deletions framework/ActiveSync/lib/Horde/ActiveSync/Imap/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,7 @@ public function getMessageChanges(
$this->_procid,
serialize($status))
);
$flags = array();
$categories = array();

$modseq = $status[Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ];
if ($modseq && $folder->modseq() > 0 && ($folder->modseq() < $modseq) || !empty($options['softdelete'])) {
$this->_logger->info(sprintf(
Expand All @@ -336,50 +335,58 @@ public function getMessageChanges(
throw new Horde_ActiveSync_Exception($e);
}

// Prepare the changes and flags array, ensuring no changes after
// $modseq sneak in yet (they will be caught on the next PING or
// SYNC).
// Build the changes array for the "normal" changes.
$changes = array();
$flags = array();
$categories = array();
$this->_buildModSeqChanges($changes, $flags, $categories, $fetch_ret, $options, $modseq);

// Get custom flags to use as categories.
$msgFlags = $this->_getMsgFlags();
// Check for mail outside of the time restriction since the
// filtertype changed
if ($options['softdelete']) {
$this->_logger->info(sprintf(
'[%s] Checking for additional messages within the new FilterType parameters.',
$this->_procid));

foreach ($fetch_ret as $uid => $data) {
if ($options['sincedate']) {
$since = new Horde_Date($options['sincedate']);
$headers = Horde_Mime_Headers::parseHeaders($data->getHeaderText());
try {
$date = new Horde_Date($headers->getValue('Date'));
if ($date->compareDate($since) <= -1) {
// Ignore, it's out of the FILTERTYPE range.
$this->_logger->info(sprintf(
'[%s] Ignoring UID %s since it is outside of the FILTERTYPE (%s)',
$this->_procid,
$uid,
$headers->getValue('Date')));
continue;
}
} catch (Horde_Date_Exception $e) {}
$query = new Horde_Imap_Client_Search_Query();
$query->dateSearch(
new Horde_Date($options['sincedate']),
Horde_Imap_Client_Search_Query::DATE_SINCE);
$query->ids(new Horde_Imap_Client_Ids($folder->messages()), true);
try {
$search_ret = $imap->search(
$mbox,
$query,
array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH)));
} catch (Horde_Imap_Client_Exception $e) {
$this->_logger->err($e->getMessage());
throw new Horde_ActiveSync_Exception($e);
}
if ($data->getModSeq() <= $modseq) {
$changes[] = $uid;
$flags[$uid] = array(
'read' => (array_search(Horde_Imap_Client::FLAG_SEEN, $data->getFlags()) !== false) ? 1 : 0
);
if (($options['protocolversion']) > Horde_ActiveSync::VERSION_TWOFIVE) {
$flags[$uid]['flagged'] = (array_search(Horde_Imap_Client::FLAG_FLAGGED, $data->getFlags()) !== false) ? 1 : 0;
}
if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) {
$categories[$uid] = array();
foreach ($data->getFlags() as $flag) {
if (!empty($msgFlags[strtolower($flag)])) {
$categories[$uid][] = $msgFlags[strtolower($flag)];
}
}
if ($search_ret['count']) {
$this->_logger->info(sprintf(
'[%s] Found %d additional messages that are now withing FilterType.',
$this->_procid, count($search_ret['match']->ids)));
$query = new Horde_Imap_Client_Fetch_Query();
$query->modseq();
$query->flags();
$query->headerText(array('peek' => true));
try {
$fetch_ret = $imap->fetch($mbox, $query, array(
'ids' => $search_ret['match']
));
} catch (Horde_Imap_Client_Exception $e) {
$this->_logger->err($e->getMessage());
throw new Horde_ActiveSync_Exception($e);
}
$this->_buildModSeqChanges($changes, $flags, $categories, $fetch_ret, $options, $modseq);
} else {
$this->_logger->info(sprintf(
'[%s] Found NO additional messages.',
$this->_procid));
}
}
$folder->setChanges($changes, $flags, $categories);
$folder->setChanges($changes, $flags, $categories, !empty($options['softdelete']));

try {
$deleted = $imap->vanished(
$mbox,
Expand Down Expand Up @@ -502,6 +509,51 @@ public function getMessageChanges(
return $folder;
}

protected function _buildModSeqChanges(
&$changes, &$flags, &$categories, $fetch_ret, $options, $modseq)
{
// Get custom flags to use as categories.
$msgFlags = $this->_getMsgFlags();

foreach ($fetch_ret as $uid => $data) {
if ($options['sincedate']) {
$since = new Horde_Date($options['sincedate']);
$headers = Horde_Mime_Headers::parseHeaders($data->getHeaderText());
try {
$date = new Horde_Date($headers->getValue('Date'));
if ($date->compareDate($since) <= -1) {
// Ignore, it's out of the FILTERTYPE range.
$this->_logger->info(sprintf(
'[%s] Ignoring UID %s since it is outside of the FILTERTYPE (%s)',
$this->_procid,
$uid,
$headers->getValue('Date')));
continue;
}
} catch (Horde_Date_Exception $e) {}
}
// Ensure no changes after $modseq sneak in
// (they will be caught on the next PING or SYNC).
if ($data->getModSeq() <= $modseq) {
$changes[] = $uid;
$flags[$uid] = array(
'read' => (array_search(Horde_Imap_Client::FLAG_SEEN, $data->getFlags()) !== false) ? 1 : 0
);
if (($options['protocolversion']) > Horde_ActiveSync::VERSION_TWOFIVE) {
$flags[$uid]['flagged'] = (array_search(Horde_Imap_Client::FLAG_FLAGGED, $data->getFlags()) !== false) ? 1 : 0;
}
if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) {
$categories[$uid] = array();
foreach ($data->getFlags() as $flag) {
if (!empty($msgFlags[strtolower($flag)])) {
$categories[$uid][] = $msgFlags[strtolower($flag)];
}
}
}
}
}
}

/**
* Return AS mail messages, from the given IMAP UIDs.
*
Expand Down

0 comments on commit 92c59e6

Please sign in to comment.