/**
  * 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());
 }
 /**
  * Checks index/thread validity
  */
 private function validate($mailbox, $index, &$exists = true)
 {
     $object = $index['object'];
     $is_thread = is_a($object, 'rcube_result_thread');
     // sanity check
     if (empty($object)) {
         return false;
     }
     $index['validated'] = true;
     // Get mailbox data (UIDVALIDITY, counters, etc.) for status check
     $mbox_data = $this->imap->folder_data($mailbox);
     // @TODO: Think about skipping validation checks.
     // If we could check only every 10 minutes, we would be able to skip
     // expensive checks, mailbox selection or even IMAP connection, this would require
     // additional logic to force cache invalidation in some cases
     // and many rcube_imap changes to connect when needed
     // Check UIDVALIDITY
     if ($index['validity'] != $mbox_data['UIDVALIDITY']) {
         $this->clear($mailbox);
         $exists = false;
         return false;
     }
     // Folder is empty but cache isn't
     if (empty($mbox_data['EXISTS'])) {
         if (!$object->is_empty()) {
             $this->clear($mailbox);
             $exists = false;
             return false;
         }
     } else {
         if ($object->is_empty()) {
             unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']);
             return false;
         }
     }
     // Validation flag
     if (!$is_thread && empty($index['valid'])) {
         unset($this->icache[$mailbox]['index']);
         return false;
     }
     // Index was created with different skip_deleted setting
     if ($this->skip_deleted != $index['deleted']) {
         return false;
     }
     // Check HIGHESTMODSEQ
     if (!empty($index['modseq']) && !empty($mbox_data['HIGHESTMODSEQ']) && $index['modseq'] == $mbox_data['HIGHESTMODSEQ']) {
         return true;
     }
     // Check UIDNEXT
     if ($index['uidnext'] != $mbox_data['UIDNEXT']) {
         unset($this->icache[$mailbox][$is_thread ? 'thread' : 'index']);
         return false;
     }
     // @TODO: find better validity check for threaded index
     if ($is_thread) {
         // check messages number...
         if (!$this->skip_deleted && $mbox_data['EXISTS'] != $object->count_messages()) {
             return false;
         }
         return true;
     }
     // The rest of checks, more expensive
     if (!empty($this->skip_deleted)) {
         // compare counts if available
         if (!empty($mbox_data['UNDELETED']) && $mbox_data['UNDELETED']->count() != $object->count()) {
             return false;
         }
         // compare UID sets
         if (!empty($mbox_data['UNDELETED'])) {
             $uids_new = $mbox_data['UNDELETED']->get();
             $uids_old = $object->get();
             if (count($uids_new) != count($uids_old)) {
                 return false;
             }
             sort($uids_new, SORT_NUMERIC);
             sort($uids_old, SORT_NUMERIC);
             if ($uids_old != $uids_new) {
                 return false;
             }
         } else {
             // get all undeleted messages excluding cached UIDs
             $ids = $this->imap->search_once($mailbox, 'ALL UNDELETED NOT UID ' . rcube_imap_generic::compressMessageSet($object->get()));
             if (!$ids->is_empty()) {
                 return false;
             }
         }
     } else {
         // check messages number...
         if ($mbox_data['EXISTS'] != $object->count()) {
             return false;
         }
         // ... and max UID
         if ($object->max() != $this->imap->id2uid($mbox_data['EXISTS'], $mailbox)) {
             return false;
         }
     }
     return true;
 }
Example #3
0
 /**
  * Checks if the cache is up-to-date
  *
  * @param string $mailbox   Mailbox name
  * @param string $cache_key Internal cache key
  * @return int   Cache status: -3 = off, -2 = incomplete, -1 = dirty, 1 = OK
  */
 private function check_cache_status($mailbox, $cache_key)
 {
     if (!$this->caching_enabled) {
         return -3;
     }
     $cache_index = $this->get_message_cache_index($cache_key);
     $msg_count = $this->_messagecount($mailbox);
     $cache_count = count($cache_index);
     // empty mailbox
     if (!$msg_count) {
         return $cache_count ? -2 : 1;
     }
     if ($cache_count == $msg_count) {
         if ($this->skip_deleted) {
             if (!empty($this->icache['all_undeleted_idx'])) {
                 $uids = rcube_imap_generic::uncompressMessageSet($this->icache['all_undeleted_idx']);
                 $uids = array_flip($uids);
                 foreach ($cache_index as $uid) {
                     unset($uids[$uid]);
                 }
             } else {
                 // get all undeleted messages excluding cached UIDs
                 $uids = $this->search_once($mailbox, 'ALL UNDELETED NOT UID ' . rcube_imap_generic::compressMessageSet($cache_index));
             }
             if (empty($uids)) {
                 return 1;
             }
         } else {
             // get UID of the message with highest index
             $uid = $this->_id2uid($msg_count, $mailbox);
             $cache_uid = array_pop($cache_index);
             // uids of highest message matches -> cache seems OK
             if ($cache_uid == $uid) {
                 return 1;
             }
         }
         // cache is dirty
         return -1;
     }
     // if cache count differs less than 10% report as dirty
     return abs($msg_count - $cache_count) < $msg_count / 10 ? -1 : -2;
 }