/** * 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 * - refreshfilter: (boolean) If true, force refresh the query to reflect * changes in FILTERTYPE (using the sincedate) * @since 2.28.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()); $flags = array(); $search_uids = array(); // 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))); $current_modseq = $status[Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ]; if ($current_modseq && $folder->modseq() > 0 && ($folder->modseq() < $current_modseq || !empty($options['softdelete']) || !empty($options['refreshfilter']))) { $this->_logger->info(sprintf('[%s] CONDSTORE and CHANGES', $this->_procid)); $folder->checkValidity($status); // Catch all *changes* since the provided MODSEQ value. $query = new Horde_Imap_Client_Search_Query(); // $imap->search uses a >= comparison for MODSEQ, so we must // increment by one so we don't continuously receive the same change // set. $query->modseq($folder->modseq() + 1); 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))); $search_uids = $search_ret['count'] ? $search_ret['match']->ids : array(); // Catch changes to FILTERTYPE. if (!empty($options['refreshfilter'])) { $this->_logger->info(sprintf('[%s] Checking for additional messages within the new FilterType parameters.', $this->_procid)); $search_ret = $this->_buildSearchQuery($folder, $options, $mbox, false); if ($search_ret['count']) { $this->_logger->info(sprintf('[%s] Found %d messages that are now outside FilterType.', $this->_procid, $search_ret['count'])); $search_uids = array_merge($search_uids, $search_ret['match']->ids); } else { $this->_logger->info(sprintf('[%s] Found NO additional messages.', $this->_procid)); } } // Protect against very large change sets like might occur if // the FILTERTYPE is changed from some short interval like one week // to no filter at all. $cnt = count($search_uids) / self::MAX_FETCH + 1; $query = new Horde_Imap_Client_Fetch_Query(); $query->modseq(); $query->flags(); $changes = array(); $categories = array(); for ($i = 0; $i <= $cnt; $i++) { $ids = new Horde_Imap_Client_Ids(array_slice($search_uids, $i * self::MAX_FETCH, self::MAX_FETCH)); try { $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $ids)); } 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, $current_modseq); } // Set the changes in the folder object. $folder->setChanges($changes, $flags, $categories, !empty($options['softdelete']) || !empty($options['refreshfilter'])); // Check for deleted messages. 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); $this->_logger->info(sprintf('[%s] Found %d deleted messages.', $this->_procid, $deleted->count())); // Check for SOFTDELETE messages. if ((!empty($options['softdelete']) || !empty($options['refreshfilter'])) && !empty($options['sincedate'])) { $this->_logger->info(sprintf('[%s] Polling for SOFTDELETE in %s before %d', $this->_procid, $folder->serverid(), $options['sincedate'])); $search_ret = $this->_buildSearchQuery($folder, $options, $mbox, true); 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 ($current_modseq && !$folder->haveInitialSync) { $this->_logger->info(sprintf('[%s] Priming IMAP folder object.', $this->_procid)); $folder->primeFolder($search_ret['match']->ids); } elseif (count($search_ret['match']->ids)) { // No modseq. $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $cnt = $search_ret['count'] / self::MAX_FETCH + 1; for ($i = 0; $i <= $cnt; $i++) { $ids = new Horde_Imap_Client_Ids(array_slice($search_ret['match']->ids, $i * self::MAX_FETCH, self::MAX_FETCH)); $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $ids)); 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 ($current_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); } $cnt = $search_ret['count'] / self::MAX_FETCH + 1; $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); for ($i = 0; $i <= $cnt; $i++) { $ids = new Horde_Imap_Client_Ids(array_slice($search_ret['match']->ids, $i * self::MAX_FETCH, self::MAX_FETCH)); try { $fetch_ret = $imap->fetch($mbox, $query, array('ids' => $ids)); } 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; } } } if (!empty($flags)) { $folder->setChanges($search_ret['match']->ids, $flags); } $folder->setRemoved($imap->vanished($mbox, null, array('ids' => new Horde_Imap_Client_Ids($folder->messages())))->ids); } elseif ($current_modseq > 0 && $folder->modseq() == 0) { throw new Horde_ActiveSync_Exception_StaleState('Transition to MODSEQ enabled server'); } $folder->setStatus($status); return $folder; }
/** * Return a folder object containing all IMAP server change information. * * @param array $options An array of options. * @see Horde_ActiveSync_Imap_Adapter::getMessageChanges * * @return Horde_ActiveSync_Folder_Base The populated folder object. */ public function getChanges(array $options) { $this->_logger->info(sprintf('[%s] CONDSTORE and CHANGES', $this->_procid)); $flags = array(); $current_modseq = $this->_status[Horde_ActiveSync_Folder_Imap::HIGHESTMODSEQ]; $query = new Horde_Imap_Client_Search_Query(); // Increment since $imap->search uses >= operator. if ($this->_modseq_valid) { $query->modseq($this->_folder->modseq() + 1); } if (!empty($options['sincedate'])) { $query->dateSearch(new Horde_Date($options['sincedate']), Horde_Imap_Client_Search_Query::DATE_SINCE); } $search_ret = $this->_imap_ob->search($this->_mbox, $query, array('results' => array(Horde_Imap_Client::SEARCH_RESULTS_MATCH))); $search_uids = $search_ret['count'] ? $search_ret['match']->ids : array(); // Catch changes to FILTERTYPE. if (!empty($options['refreshfilter'])) { $this->_logger->info(sprintf('[%s] Checking for additional messages within the new FilterType parameters.', $this->_procid)); $search_ret = $this->_searchQuery($options, false); if ($search_ret['count']) { $this->_logger->info(sprintf('[%s] Found %d messages that are now outside FilterType.', $this->_procid, $search_ret['count'])); $search_uids = array_merge($search_uids, $search_ret['match']->ids); } } // Protect against very large change sets. $cnt = count($search_uids) / Horde_ActiveSync_Imap_Adapter::MAX_FETCH + 1; $query = new Horde_Imap_Client_Fetch_Query(); if ($this->_modseq_valid) { $query->modseq(); } $query->flags(); $changes = array(); $categories = array(); for ($i = 0; $i <= $cnt; $i++) { $ids = new Horde_Imap_Client_Ids(array_slice($search_uids, $i * Horde_ActiveSync_Imap_Adapter::MAX_FETCH, Horde_ActiveSync_Imap_Adapter::MAX_FETCH)); try { $fetch_ret = $this->_imap_ob->fetch($this->_mbox, $query, array('ids' => $ids)); } 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, $current_modseq); } // Set the changes in the folder object. $this->_folder->setChanges($changes, $flags, $categories, !empty($options['softdelete']) || !empty($options['refreshfilter'])); // Check for deleted messages. try { $deleted = $this->_imap_ob->vanished($this->_mbox, $this->_folder->modseq(), array('ids' => new Horde_Imap_Client_Ids($this->_folder->messages()))); } catch (Horde_Imap_Client_Excetion $e) { $this->_logger->err($e->getMessage()); throw new Horde_ActiveSync_Exception($e); } $this->_folder->setRemoved($deleted->ids); $this->_logger->info(sprintf('[%s] Found %d deleted messages.', $this->_procid, $deleted->count())); // Check for SOFTDELETE messages. if (!empty($options['sincedate']) && (!empty($options['softdelete']) || !empty($options['refreshfilter']))) { $this->_logger->info(sprintf('[%s] Polling for SOFTDELETE in %s before %d', $this->_procid, $this->_folder->serverid(), $options['sincedate'])); $search_ret = $this->_searchQuery($options, true); if ($search_ret['count']) { $this->_logger->info(sprintf('[%s] Found %d messages to SOFTDELETE.', $this->_procid, count($search_ret['match']->ids))); $this->_folder->setSoftDeleted($search_ret['match']->ids); } $this->_folder->setSoftDeleteTimes($options['sincedate'], time()); } return $this->_folder; }
/** * @depends testOptimizedSearches */ public function testComplexFetch() { // Fetching message information from complex MIME message. $complex_fetch = new Horde_Imap_Client_Fetch_Query(); $complex_fetch->fullText(array('length' => 100, 'peek' => true)); // Header of entire message $complex_fetch->headerText(array('length' => 100, 'peek' => true)); // Header of message/rfc822 part $complex_fetch->headerText(array('id' => 2, 'length' => 100, 'peek' => true)); // Body text of entire message $complex_fetch->bodyText(array('length' => 100, 'peek' => true)); // Body text of message/rfc822 part $complex_fetch->bodyText(array('id' => 2, 'length' => 100, 'peek' => true)); // MIME Header of multipart/alternative part $complex_fetch->mimeHeader('1', array('length' => 100, 'peek' => true)); // MIME Header of text/plain part embedded in message/rfc822 part $complex_fetch->mimeHeader('2.1', array('length' => 100, 'peek' => true)); // Body text of multipart/alternative part $complex_fetch->bodyPart('1', array('length' => 100, 'peek' => true)); // Body text of image/png part embedded in message/rfc822 part // Try to do server-side decoding, if available $complex_fetch->mimeHeader('2.2', array('decode' => true, 'length' => 100, 'peek' => true)); // If supported, return decoded body part size $complex_fetch->bodyPartSize('2.2'); // Select message-id header from base message header $complex_fetch->headers('headersearch1', array('message-id'), array('length' => 100, 'peek' => true)); // Select everything but message-id header from message/rfc822 header $complex_fetch->headers('headersearch2', array('message-id'), array('id' => '2', 'length' => 100, 'notsearch' => true, 'peek' => true)); $complex_fetch->structure(); $complex_fetch->flags(); $complex_fetch->imapDate(); $complex_fetch->size(); $complex_fetch->uid(); if (self::$live->capability->query('CONDSTORE')) { $complex_fetch->modseq(); } try { $res = self::$live->fetch(self::$test_mbox, $complex_fetch, array('ids' => new Horde_Imap_Client_Ids(3, true))); } catch (Horde_Imap_Client_Exception $e) { if ($e->getCode() === $e::MBOXNOMODSEQ) { $this->markTestSkipped('Mailbox does not support MODSEQ.'); } throw $e; } $this->assertInstanceOf('Horde_Imap_Client_Fetch_Results', $res); $this->assertEquals(1, count($res)); $this->assertEquals('Message-ID: <*****@*****.**>', trim($res[3]->getHeaders('headersearch1'))); /* Return stream instead. */ $this->assertInternalType('resource', $res[3]->getHeaders('headersearch1', Horde_Imap_Client_Data_Fetch::HEADER_STREAM)); /* Parse headers instead. */ $this->assertInstanceOf('Horde_Mime_Headers', $res[3]->getHeaders('headersearch1', Horde_Imap_Client_Data_Fetch::HEADER_PARSE)); }
/** * 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; }