Пример #1
0
 /**
  * Return message changes from the specified mailbox.
  *
  * @param Horde_ActiveSync_Folder_Imap $folder  The folder object.
  * @param array $options                        Additional options:
  *  - sincedate: (integer)  Timestamp of earliest message to retrieve.
  *               DEFAULT: 0 (Don't filter).
  *  - protocolversion: (float)  EAS protocol version to support.
  *                     DEFAULT: none REQUIRED
  *  - softdelete: (boolean)  If true, calculate SOFTDELETE data.
  *                           @since 2.8.0
  *
  * @return Horde_ActiveSync_Folder_Imap  The folder object, containing any
  *                                       change instructions for the device.
  *
  * @throws Horde_ActiveSync_Exception_FolderGone,
  *         Horde_ActiveSync_Exception, Horde_ActiveSync_Exception_StaleState
  */
 public function getMessageChanges(Horde_ActiveSync_Folder_Imap $folder, array $options = array())
 {
     $imap = $this->_getImapOb();
     $mbox = new Horde_Imap_Client_Mailbox($folder->serverid());
     // Note: non-CONDSTORE servers will return a highestmodseq of 0
     $status_flags = Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY | Horde_Imap_Client::STATUS_UIDNEXT_FORCE | Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_FORCE_REFRESH;
     try {
         $status = $imap->status($mbox, $status_flags);
     } catch (Horde_Imap_Client_Exception $e) {
         // If we can't status the mailbox, assume it's gone.
         throw new Horde_ActiveSync_Exception_FolderGone($e);
     }
     $this->_logger->info(sprintf('[%s] IMAP status: %s', $this->_procid, serialize($status)));
     $flags = array();
     $categories = array();
     $modseq = $status[Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ];
     if ($modseq && $folder->modseq() > 0 && $folder->modseq() < $modseq) {
         $this->_logger->info(sprintf('[%s] CONDSTORE and CHANGES', $this->_procid));
         $folder->checkValidity($status);
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->modseq();
         $query->flags();
         $query->headerText(array('peek' => true));
         try {
             $fetch_ret = $imap->fetch($mbox, $query, array('changedsince' => $folder->modseq()));
         } catch (Horde_Imap_Client_Exception $e) {
             $this->_logger->err($e->getMessage());
             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).
         $changes = array();
         // 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) {
                 }
             }
             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 (($key = array_search(strtolower($flag), array_map('strtolower', $msgFlags))) !== false) {
                             $categories[$uid][] = $msgFlags[$key];
                         }
                     }
                 }
             }
         }
         $folder->setChanges($changes, $flags, $categories);
         try {
             $deleted = $imap->vanished($mbox, $folder->modseq(), array('ids' => new Horde_Imap_Client_Ids($folder->messages())));
         } catch (Horde_Imap_Client_Excetion $e) {
             $this->_logger->err($e->getMessage());
             throw new Horde_ActiveSync_Exception($e);
         }
         $folder->setRemoved($deleted->ids);
         if (!empty($options['softdelete']) && !empty($options['sincedate'])) {
             $this->_logger->info(sprintf('[%s] Polling for SOFTDELETE in %s before %d', $this->_procid, $folder->serverid(), $options['sincedate']));
             $query = new Horde_Imap_Client_Search_Query();
             $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_BEFORE);
             $query->ids(new Horde_Imap_Client_Ids($folder->messages()));
             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 ($search_ret['count']) {
                 $this->_logger->info(sprintf('[%s] Found %d messages to SOFTDELETE.', $this->_procid, count($search_ret['match']->ids)));
                 $folder->setSoftDeleted($search_ret['match']->ids);
             } else {
                 $this->_logger->info(sprintf('[%s] Found NO messages to SOFTDELETE.', $this->_procid));
             }
             $folder->setSoftDeleteTimes($options['sincedate'], time());
         }
     } elseif ($folder->uidnext() == 0) {
         $this->_logger->info(sprintf('[%s] INITIAL SYNC', $this->_procid));
         $query = new Horde_Imap_Client_Search_Query();
         if (!empty($options['sincedate'])) {
             $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_SINCE);
         }
         $search_ret = $imap->search($mbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH)));
         if ($modseq && $folder->modseq() > 0 && $search_ret['count']) {
             $folder->setChanges($search_ret['match']->ids, array());
         } elseif (count($search_ret['match']->ids)) {
             $query = new Horde_Imap_Client_Fetch_Query();
             $query->flags();
             $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $search_ret['match']));
             foreach ($fetch_ret as $uid => $data) {
                 $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;
                 }
             }
             $folder->setChanges($search_ret['match']->ids, $flags);
         }
     } elseif ($modseq == 0) {
         $this->_logger->info(sprintf('[%s] NO CONDSTORE or per mailbox MODSEQ. minuid: %s, total_messages: %s', $this->_procid, $folder->minuid(), $status['messages']));
         $folder->checkValidity($status);
         $query = new Horde_Imap_Client_Search_Query();
         if (!empty($options['sincedate'])) {
             $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_SINCE);
         }
         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 (count($search_ret['match']->ids)) {
             // Update flags.
             $query = new Horde_Imap_Client_Fetch_Query();
             $query->flags();
             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);
             }
             foreach ($fetch_ret as $uid => $data) {
                 $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;
                 }
             }
             $folder->setChanges($search_ret['match']->ids, $flags);
         }
         $folder->setRemoved($imap->vanished($mbox, null, array('ids' => new Horde_Imap_Client_Ids($folder->messages())))->ids);
     } elseif ($modseq > 0 && $folder->modseq() == 0) {
         throw new Horde_ActiveSync_Exception_StaleState('Transition to MODSEQ enabled server');
     }
     $folder->setStatus($status);
     return $folder;
 }
Пример #2
0
 public function testSerializationWithoutImapCompression()
 {
     $folder = new Horde_ActiveSync_Folder_Imap('Trash', Horde_ActiveSync::CLASS_EMAIL);
     $status = array(Horde_ActiveSync_Folder_Imap::UIDVALIDITY => 100, Horde_ActiveSync_Folder_Imap::UIDNEXT => 47654, Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ => 200);
     $fixture = array(46653, 46654, 46655, 46656, 46657, 46658, 46659, 46660, 46661, 46662, 46663, 46664, 46665, 46666, 46667, 46668, 46669, 46670, 46671, 46672, 46673, 46674, 46675, 46676, 46677, 46678, 46679, 46680, 46681, 46682, 46691, 46692, 46693, 46694, 46695, 46696, 46697, 46698, 46699, 46700, 46701, 46702, 46703, 46704, 46705, 46706, 46707, 46708, 46709, 46710, 46711, 46712, 46713, 46714, 46715, 46716, 46717, 46718, 46719, 46720, 46721, 46723, 46724, 46725, 46726, 46727, 46728, 46729, 46730, 46731, 46732, 46733, 46734, 46735, 46736, 46737, 46738, 46739, 46740, 46741, 46742, 46743, 46744, 46745, 46746, 46747, 46748, 46749, 46750, 46751, 46752, 46753, 46754, 46755, 46756, 46757, 46758, 46759, 46760, 46761, 46762, 46763, 46764, 46765, 46766, 46767, 46768, 46769, 46770, 46771, 46772, 46773, 46774, 46775, 46776, 46777, 46778, 46779, 46780, 46781, 46782, 46783, 46784, 46785, 46786);
     $folder->setChanges($fixture);
     $folder->setStatus($status);
     $folder->updateState();
     $serialized = serialize($folder);
     $folder = unserialize($serialized);
     $this->assertEquals($fixture, $folder->messages());
 }