diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 4abf7f48d..10ae653b1 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -1081,10 +1081,11 @@ class MailClient /** * @param string $sSearch * @param int $iTimeZoneOffset = 0 + * @param bool $bAddNotDeleted = false * * @return string */ - private function getImapSearchCriterias($sSearch, $iTimeZoneOffset = 0) + private function getImapSearchCriterias($sSearch, $iTimeZoneOffset = 0, $bAddNotDeleted = false) { $aCriteriasResult = array(); if (0 < \strlen(\trim($sSearch))) @@ -1309,7 +1310,11 @@ class MailClient $sCriteriasResult = \trim(\implode(' ', $aCriteriasResult)); if ('' === $sCriteriasResult) { - $sCriteriasResult = 'ALL'; + $sCriteriasResult = $bAddNotDeleted ? 'UNDELETED' : 'ALL'; + } + else if ($bAddNotDeleted) + { + $sCriteriasResult .= ' UNDELETED'; } return $sCriteriasResult; @@ -1470,7 +1475,7 @@ class MailClient if ($oCacher && $oCacher->IsInited()) { $sSerializedHash = - 'ThreadsMap/'. + 'ThreadsMap/UNDELETED/'. $this->oImapClient->GetLogginedUser().'@'. $this->oImapClient->GetConnectedHost().':'. $this->oImapClient->GetConnectedPort().'/'. @@ -1492,7 +1497,7 @@ class MailClient $aThreadUids = array(); try { - $aThreadUids = $this->oImapClient->MessageSimpleThread(); + $aThreadUids = $this->oImapClient->MessageSimpleThread('UNDELETED'); } catch (\MailSo\Imap\Exceptions\RuntimeException $oException) { @@ -1638,6 +1643,283 @@ class MailClient $bCacher = false; $bSearch = false; + if (0 < $iMessageRealCount) + { + $bIndexAsUid = false; + $aIndexOrUids = array(); + + $bSearch = 0 < \strlen($sSearch); + + if ($bSearch || !$bUseThreadSortIfSupported) + { + $bIndexAsUid = true; + $aIndexOrUids = null; + + $sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, true); + + if ($iMessageCacheCount < $iMessageRealCount && $oCacher && $oCacher->IsInited()) + { + $sSerializedHash = + ($bUseSortIfSupported ? 'S': 'N').'/'. + ($bUseThreadSortIfSupported ? 'T': 'N').'/'. + $this->oImapClient->GetLogginedUser().'@'. + $this->oImapClient->GetConnectedHost().':'. + $this->oImapClient->GetConnectedPort().'/'. + $oMessageCollection->FolderName.'/'. + $sSearchCriterias; + + $sSerializedLog = '"'.$oMessageCollection->FolderName.'" / '.$sSearchCriterias.''; + + $sSerialized = $oCacher->Get($sSerializedHash); + if (!empty($sSerialized)) + { + $aSerialized = @\unserialize($sSerialized); + if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) && + \is_array($aSerialized['Uids']) && + $oMessageCollection->FolderHash === $aSerialized['FolderHash']) + { + if ($this->oLogger) + { + $this->oLogger->Write('Get Serialized UIDS from cache ('.$sSerializedLog.') [count:'.\count($aSerialized['Uids']).']'); + } + + $aIndexOrUids = $aSerialized['Uids']; + $bCacher = true; + } + } + } + + if (!\is_array($aIndexOrUids)) + { + if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) + { + if ($bESortSupported) + { + $aESorthData = $this->oImapClient->MessageSimpleESort(array('ARRIVAL'), $sSearchCriterias, array('ALL'), $bIndexAsUid, ''); + if (isset($aESorthData['ALL'])) + { + $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESorthData['ALL']); + $aIndexOrUids = \array_reverse($aIndexOrUids); + } + + unset($aESorthData); + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, $bIndexAsUid); + } + } + else + { + if (!\MailSo\Base\Utils::IsAscii($sSearch)) + { + try + { + if ($bESearchSupported) + { + $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid, '', 'UTF-8'); + if (isset($aESearchData['ALL'])) + { + $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); + $aIndexOrUids = \array_reverse($aIndexOrUids); + } + unset($aESearchData); + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); + } + } + catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) + { + $oException = null; + $aIndexOrUids = null; + } + } + + if (null === $aIndexOrUids) + { + if ($bESearchSupported) + { + $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid); + if (isset($aESearchData['ALL'])) + { + $aIndexOrUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']); + $aIndexOrUids = \array_reverse($aIndexOrUids); + } + + unset($aESearchData); + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); + } + } + } + } + } + else + { + if ($bUseThreadSortIfSupported && 1 < $iMessageCount) + { + $bIndexAsUid = true; + $aThreads = $this->MessageListThreadsMap( + $oMessageCollection->FolderName, + $oMessageCollection->FolderHash, + $oCacher); + + $aIndexOrUids = $this->compileLineThreadUids($aThreads, $aLastCollapsedThreadUids, $aExpandedThreadsUids, 0); + $iMessageCount = \count($aIndexOrUids); + } + else + { + $bIndexAsUid = false; + $aIndexOrUids = array(1); + if (1 < $iMessageCount) + { + $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); + } + } + } + + if ($bIndexAsUid && !$bCacher && \is_array($aIndexOrUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) + { + $oCacher->Set($sSerializedHash, \serialize(array( + 'FolderHash' => $oMessageCollection->FolderHash, + 'Uids' => $aIndexOrUids + ))); + + if ($this->oLogger) + { + $this->oLogger->Write('Save Serialized UIDS to cache ('.$sSerializedLog.') [count:'.\count($aIndexOrUids).']'); + } + } + + if (\is_array($aIndexOrUids)) + { + $oMessageCollection->MessageCount = $iMessageRealCount; + $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; + $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) + ? $iMessageCount : \count($aIndexOrUids); + + if (0 < count($aIndexOrUids)) + { + $iOffset = (0 > $iOffset) ? 0 : $iOffset; + $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); + + $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); + } + } + } + + $aLastCollapsedThreadUidsForPage = array(); + + if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) + { + $oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ( + $aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) + { + $iUid = $oMessage->Uid(); + if (in_array($iUid, $aLastCollapsedThreadUids)) + { + $aLastCollapsedThreadUidsForPage[] = $iUid; + } + + if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) + { + $oMessage->SetThreads($aThreads[$iUid]); + $oMessage->SetThreadsLen(\count($aThreads[$iUid])); + } + else if (!isset($aThreads[$iUid])) + { + foreach ($aThreads as $iKeyUid => $mSubItem) + { + if (is_array($mSubItem) && in_array($iUid, $mSubItem)) + { + $oMessage->SetParentThread($iKeyUid); + $oMessage->SetThreadsLen(\count($mSubItem)); + } + } + } + }); + + $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; + } + + return $oMessageCollection; + } + + /** + * @deprecated + * + * @param string $sFolderName + * @param int $iOffset = 0 + * @param int $iLimit = 10 + * @param string $sSearch = '' + * @param string $sPrevUidNext = '' + * @param mixed $oCacher = null + * @param string $sCachePrefix = '' + * @param bool $bUseSortIfSupported = false + * @param bool $bUseThreadSortIfSupported = false + * @param array $aExpandedThreadsUids = array() + * @param bool $bUseESearchOrESortRequest = false + * + * @return \MailSo\Mail\MessageCollection + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageListDepr($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', + $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array(), + $bUseESearchOrESortRequest = false) + { + $sSearch = \trim($sSearch); + if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || + !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999) || + !is_string($sSearch)) + { + throw new \MailSo\Base\Exceptions\InvalidArgumentException(); + } + + $this->oImapClient->FolderExamine($sFolderName); + + $oMessageCollection = MessageCollection::NewInstance(); + $oMessageCollection->FolderName = $sFolderName; + $oMessageCollection->Offset = $iOffset; + $oMessageCollection->Limit = $iLimit; + $oMessageCollection->Search = $sSearch; + + $aLastCollapsedThreadUids = array(); + + $aThreads = array(); + $iMessageCount = 0; + $iMessageRealCount = 0; + $iMessageUnseenCount = 0; + $iMessageCacheCount = 100; + $sUidNext = '0'; + $sSerializedHash = ''; + $bESearchSupported = $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESEARCH') : false; + $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; + $bESortSupported = $bUseSortIfSupported && $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESORT') : false; + $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? + ($this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT')) : false; + + if (!$oCacher || !($oCacher instanceof \MailSo\Cache\CacheClient)) + { + $oCacher = null; + } + + $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); + $iMessageCount = $iMessageRealCount; + + $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); + $oMessageCollection->UidNext = $sUidNext; + $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); + + $bCacher = false; + $bSearch = false; + if (0 < $iMessageRealCount) { $bIndexAsUid = false; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index df99ba996..4cb9a68c4 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -797,7 +797,7 @@ class Actions '][GUID:'.\MailSo\Log\Logger::Guid().']'); $this->oLogger->Write( - ' ['.$oHttp->GetMethod().'] '.$oHttp->GetScheme().'://'.$oHttp->GetHost(false, false).$oHttp->GetServer('REQUEST_URI', ''), + '['.$oHttp->GetMethod().'] '.$oHttp->GetScheme().'://'.$oHttp->GetHost(false, false).$oHttp->GetServer('REQUEST_URI', ''), \MailSo\Log\Enumerations\Type::NOTE, 'REQUEST'); } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php index fdc3bcfd1..ac6fc9f56 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php @@ -146,8 +146,10 @@ class Service return $this; } + $bIndex = true; if (0 < \count($aPaths) && !empty($aPaths[0]) && !$bAdmin && 'index' !== $aPaths[0]) { + $bIndex = false; $sMethodName = 'Service'.$aPaths[0]; if (\method_exists($this->oServiceActions, $sMethodName) && \is_callable(array($this->oServiceActions, $sMethodName))) @@ -157,10 +159,11 @@ class Service } else if (!$this->oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths)) { - $this->oActions->Logger()->Write('Unknown request', \MailSo\Log\Enumerations\Type::WARNING, 'RESPONSE'); + $bIndex = true; } } - else + + if ($bIndex) { @header('Content-Type: text/html; charset=utf-8'); $this->oHttp->ServerNoCache(); @@ -206,9 +209,9 @@ class Service $sResult .= ''; }