diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php index 70fd3793c..4c3699739 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php @@ -1254,6 +1254,40 @@ class Utils return \MailSo\Base\Utils::Base64Decode($sData); } + /** + * @param string $sSequence + * + * @return array + */ + public static function ExpandFetchSequence($sSequence) + { + $aResult = array(); + $sSequence = \trim($sSequence); + if (0 < \strlen($sSequence)) + { + $aSequence = \explode(',', $sSequence); + foreach ($aSequence as $sItem) + { + if (false === \strpos($sItem, ':')) + { + $aResult[] = (int) $sItem; + } + else + { + $aItems = \explode(':', $sItem); + $iMax = \max($aItems[0], $aItems[1]); + + for ($iIndex = $aItems[0]; $iIndex <= $iMax; $iIndex++) + { + $aResult[] = (int) $iIndex; + } + } + } + } + + return $aResult; + } + /** * * @param resource $fResource diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php index 5cee16823..31d1a6ff4 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php @@ -1039,9 +1039,102 @@ class ImapClient extends \MailSo\Net\NetClient return $aReturn; } + /** + * @param string $sSearchCriterias = 'ALL' + * @param array $aSearchReturn = null + * @param bool $bReturnUid = true + * @param string $sLimit = '' + * @param string $sCharset = '' + * + * @return array + * + * @throws \MailSo\Base\Exceptions\InvalidArgumentException + * @throws \MailSo\Net\Exceptions\Exception + * @throws \MailSo\Imap\Exceptions\Exception + */ + public function MessageSimpleESearch($sSearchCriterias = 'ALL', $aSearchReturn = null, $bReturnUid = true, $sLimit = '', $sCharset = '') + { + $sCommandPrefix = ($bReturnUid) ? 'UID ' : ''; + $sSearchCriterias = 0 === \strlen($sSearchCriterias) || '*' === $sSearchCriterias + ? 'ALL' : $sSearchCriterias; + + if (!$this->IsSupported('ESEARCH')) + { + $this->writeLogException( + new \MailSo\Base\Exceptions\InvalidArgumentException(), + \MailSo\Log\Enumerations\Type::ERROR, true); + } + + if (!\is_array($aSearchReturn) || 0 === \count($aSearchReturn)) + { + $aSearchReturn = array('ALL'); + } + + $aRequest = array(); + if (0 < \strlen($sCharset)) + { + $aRequest[] = 'CHARSET'; + $aRequest[] = \strtoupper($sCharset); + } + + $aRequest[] = 'RETURN'; + $aRequest[] = $aSearchReturn; + + $aRequest[] = $sSearchCriterias; + + if (0 < \strlen($sLimit)) + { + $aRequest[] = $sLimit; + } + + $this->SendRequest($sCommandPrefix.('SEARCH'), $aRequest); + $sRequestTag = $this->getCurrentTag(); + + $aResult = array(); + $aResponse = $this->parseResponseWithValidation(); + + if (\is_array($aResponse)) + { + $oImapResponse = null; + foreach ($aResponse as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse) + { + if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType + && 'ESEARCH' === $oImapResponse->StatusOrIndex + && \is_array($oImapResponse->ResponseList) + && isset($oImapResponse->ResponseList[2], $oImapResponse->ResponseList[2][0], $oImapResponse->ResponseList[2][1]) + && 'TAG' === $oImapResponse->ResponseList[2][0] && $sRequestTag === $oImapResponse->ResponseList[2][1] + && (!$bReturnUid || ($bReturnUid && !empty($oImapResponse->ResponseList[3]) && 'UID' === $oImapResponse->ResponseList[3])) + ) + { + $iStart = 3; + foreach ($oImapResponse->ResponseList as $iIndex => $mItem) + { + if ($iIndex >= $iStart) + { + switch ($mItem) + { + case 'ALL': + case 'MAX': + case 'MIN': + case 'COUNT': + if (isset($oImapResponse->ResponseList[$iIndex + 1])) + { + $aResult[$mItem] = $oImapResponse->ResponseList[$iIndex + 1]; + } + break; + } + } + } + } + } + } + + return $aResult; + } + /** * @param string $sSearchCriterias - * @param bool $bReturnUid + * @param bool $bReturnUid = true * @param string $sCharset = '' * * @return array 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 1bd221972..729e9233b 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 @@ -1520,6 +1520,7 @@ class MailClient * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() + * @param bool $bUseESearchOrESortRequest = true * * @return \MailSo\Mail\MessageCollection * @@ -1528,7 +1529,8 @@ class MailClient * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', - $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array()) + $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array(), + $bUseESearchOrESortRequest = true) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || @@ -1555,7 +1557,9 @@ class MailClient $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; @@ -1584,7 +1588,6 @@ class MailClient if ($bSearch || ($bUseSortIfSupported && !$bUseThreadSortIfSupported)) { $bIndexAsUid = true; - $aIndexOrUids = null; $sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete(); @@ -1618,7 +1621,15 @@ class MailClient { if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) { - $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); + if ($bESortSupported) + { + // TODO + $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); + } } else { @@ -1626,7 +1637,18 @@ class MailClient { try { - $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); + if ($bESearchSupported) + { + $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid, '', 'UTF-8'); + if (isset($aESearchData['ALL'])) + { + $aIndexOrUids = \MailSo\Base\Utils::ExpandFetchSequence($aESearchData['ALL']); + } + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); + } } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { @@ -1637,7 +1659,18 @@ class MailClient if (null === $aIndexOrUids) { - $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); + if ($bESearchSupported) + { + $aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), $bIndexAsUid); + if (isset($aESearchData['ALL'])) + { + $aIndexOrUids = \MailSo\Base\Utils::ExpandFetchSequence($aESearchData['ALL']); + } + } + else + { + $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); + } } } }