Replaced the new callable $cbUntaggedResponse for yieldUntaggedResponses

This commit is contained in:
djmaze 2021-12-08 22:10:55 +01:00
parent da0d8f66d5
commit 2ef0a7e382
5 changed files with 80 additions and 47 deletions

View file

@ -33,14 +33,13 @@ trait Messages
$oSort->sCriterias = $sSearchCriterias; $oSort->sCriterias = $sSearchCriterias;
$oSort->bUid = $bReturnUid; $oSort->bUid = $bReturnUid;
$oSort->aSortTypes = $aSortTypes; $oSort->aSortTypes = $aSortTypes;
$oResponseCollection = $oSort->SendRequestGetResponse(); $oSort->SendRequest();
$aReturn = array(); $aReturn = array();
foreach ($oResponseCollection as $oResponse) { foreach ($this->yieldUntaggedResponses() as $oResponse) {
$iOffset = ($bReturnUid && 'UID' === $oResponse->StatusOrIndex && !empty($oResponse->ResponseList[2]) && 'SORT' === $oResponse->ResponseList[2]) ? 1 : 0; $iOffset = ($bReturnUid && 'UID' === $oResponse->StatusOrIndex && !empty($oResponse->ResponseList[2]) && 'SORT' === $oResponse->ResponseList[2]) ? 1 : 0;
if (ResponseType::UNTAGGED === $oResponse->ResponseType if (\is_array($oResponse->ResponseList)
&& ('SORT' === $oResponse->StatusOrIndex || $iOffset) && 2 < \count($oResponse->ResponseList)
&& \is_array($oResponse->ResponseList) && ('SORT' === $oResponse->StatusOrIndex || $iOffset))
&& 2 < \count($oResponse->ResponseList))
{ {
$iLen = \count($oResponse->ResponseList); $iLen = \count($oResponse->ResponseList);
for ($iIndex = 2 + $iOffset; $iIndex < $iLen; ++$iIndex) { for ($iIndex = 2 + $iOffset; $iIndex < $iLen; ++$iIndex) {
@ -64,7 +63,8 @@ trait Messages
$oESearch->bUid = $bReturnUid; $oESearch->bUid = $bReturnUid;
$oESearch->sLimit = $sLimit; $oESearch->sLimit = $sLimit;
$oESearch->sCharset = $sCharset; $oESearch->sCharset = $sCharset;
return $this->getSimpleESearchOrESortResult($oESearch->SendRequestGetResponse(), $bReturnUid); $oESearch->SendRequest();
return $this->getSimpleESearchOrESortResult($bReturnUid);
} }
/** /**
@ -80,7 +80,8 @@ trait Messages
$oSort->aSortTypes = $aSortTypes; $oSort->aSortTypes = $aSortTypes;
$oSort->aReturn = $aSearchReturn ?: ['ALL']; $oSort->aReturn = $aSearchReturn ?: ['ALL'];
$oSort->sLimit = $sLimit; $oSort->sLimit = $sLimit;
return $this->getSimpleESearchOrESortResult($oSort->SendRequestGetResponse(), $bReturnUid); $oSort->SendRequest();
return $this->getSimpleESearchOrESortResult($bReturnUid);
} }
/** /**
@ -146,15 +147,14 @@ trait Messages
return $oThread->SendRequestGetResponse(); return $oThread->SendRequestGetResponse();
} }
private function getSimpleESearchOrESortResult(ResponseCollection $oResponseCollection, bool $bReturnUid) : array private function getSimpleESearchOrESortResult(bool $bReturnUid) : array
{ {
$sRequestTag = $this->getCurrentTag(); $sRequestTag = $this->getCurrentTag();
$aResult = array(); $aResult = array();
foreach ($oResponseCollection as $oResponse) { foreach ($this->yieldUntaggedResponses() as $oResponse) {
if (ResponseType::UNTAGGED === $oResponse->ResponseType if (\is_array($oResponse->ResponseList)
&& ('ESEARCH' === $oResponse->StatusOrIndex || 'SORT' === $oResponse->StatusOrIndex)
&& \is_array($oResponse->ResponseList)
&& isset($oResponse->ResponseList[2][1]) && isset($oResponse->ResponseList[2][1])
&& ('ESEARCH' === $oResponse->StatusOrIndex || 'SORT' === $oResponse->StatusOrIndex)
&& 'TAG' === $oResponse->ResponseList[2][0] && $sRequestTag === $oResponse->ResponseList[2][1] && 'TAG' === $oResponse->ResponseList[2][0] && $sRequestTag === $oResponse->ResponseList[2][1]
&& (!$bReturnUid || (!empty($oResponse->ResponseList[3]) && 'UID' === $oResponse->ResponseList[3])) && (!$bReturnUid || (!empty($oResponse->ResponseList[3]) && 'UID' === $oResponse->ResponseList[3]))
) )

View file

@ -484,10 +484,9 @@ class ImapClient extends \MailSo\Net\NetClient
$oInfo = new FolderInformation($sFolderName, false); $oInfo = new FolderInformation($sFolderName, false);
$this->SendRequest('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems)); $this->SendRequest('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems));
$this->getResponse(null, function(Response $oResponse) use ($oInfo) { foreach ($this->yieldUntaggedResponses() as $oResponse) {
$oInfo->setStatusFromResponse($oResponse); $oInfo->setStatusFromResponse($oResponse);
return true; }
});
if ($bReselect) { if ($bReselect) {
$this->selectOrExamineFolder($sFolderName, $bWritable, false); $this->selectOrExamineFolder($sFolderName, $bWritable, false);
@ -579,20 +578,18 @@ class ImapClient extends \MailSo\Net\NetClient
} else { } else {
$sDelimiter = ''; $sDelimiter = '';
$bInbox = false; $bInbox = false;
$oImapClient = $this; foreach ($this->yieldUntaggedResponses() as $oResponse) {
$this->getResponse(null, function(Response $oResponse) use ($oImapClient, &$aReturn, $sCmd, &$sDelimiter, &$bInbox, $aMetadata) {
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) { if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
$sFullName = $oImapClient->toUTF8($oResponse->ResponseList[2]); $sFullName = $this->toUTF8($oResponse->ResponseList[2]);
if (!isset($aReturn[$sFullName])) { if (!isset($aReturn[$sFullName])) {
$aReturn[$sFullName] = new Folder($sFullName); $aReturn[$sFullName] = new Folder($sFullName);
} }
$aReturn[$sFullName]->setStatusFromResponse($oResponse); $aReturn[$sFullName]->setStatusFromResponse($oResponse);
return true;
} }
else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) { else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) {
try try
{ {
$sFullName = $oImapClient->toUTF8($oResponse->ResponseList[4]); $sFullName = $this->toUTF8($oResponse->ResponseList[4]);
/** /**
* $oResponse->ResponseList[0] = * * $oResponse->ResponseList[0] = *
@ -624,19 +621,17 @@ class ImapClient extends \MailSo\Net\NetClient
} }
$aReturn[$sFullName] = $oFolder; $aReturn[$sFullName] = $oFolder;
return true;
} }
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException) catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
{ {
$oImapClient->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false); $this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {
$oImapClient->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false); $this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
} }
} }
return false; }
});
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) { if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter); $aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
@ -743,7 +738,7 @@ class ImapClient extends \MailSo\Net\NetClient
$oResult = new FolderInformation($sFolderName, $bIsWritable); $oResult = new FolderInformation($sFolderName, $bIsWritable);
$this->SendRequest($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams); $this->SendRequest($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
$this->getResponse(null, function(Response $oResponse) use ($oResult) { foreach ($this->yieldUntaggedResponses() as $oResponse) {
if (!$oResult->setStatusFromResponse($oResponse)) { if (!$oResult->setStatusFromResponse($oResponse)) {
// OK untagged responses // OK untagged responses
if (\is_array($oResponse->OptionalResponse)) { if (\is_array($oResponse->OptionalResponse)) {
@ -768,8 +763,7 @@ class ImapClient extends \MailSo\Net\NetClient
$oResult->Flags = $oResponse->ResponseList[2]; $oResult->Flags = $oResponse->ResponseList[2];
} }
} }
return true; }
});
$this->oCurrentFolderInfo = $oResult; $this->oCurrentFolderInfo = $oResult;
@ -889,17 +883,15 @@ class ImapClient extends \MailSo\Net\NetClient
*/ */
$this->SendRequest($bIndexIsUid ? 'UID FETCH' : 'FETCH', $aParams); $this->SendRequest($bIndexIsUid ? 'UID FETCH' : 'FETCH', $aParams);
$oImapClient = $this; foreach ($this->yieldUntaggedResponses() as $oResponse) {
$this->getResponse(null, function(Response $oResponse) use ($oImapClient, &$aReturn) {
if (FetchResponse::IsValidFetchImapResponse($oResponse)) { if (FetchResponse::IsValidFetchImapResponse($oResponse)) {
if (FetchResponse::IsNotEmptyFetchImapResponse($oResponse)) { if (FetchResponse::IsNotEmptyFetchImapResponse($oResponse)) {
$aReturn[] = new FetchResponse($oResponse); $aReturn[] = new FetchResponse($oResponse);
return true; } else if ($this->oLogger) {
} else if ($oImapClient->oLogger) { $this->oLogger->Write('Skipped Imap Response! ['.$oResponse->ToLine().']', \MailSo\Log\Enumerations\Type::NOTICE);
$oImapClient->oLogger->Write('Skipped Imap Response! ['.$oResponse->ToLine().']', \MailSo\Log\Enumerations\Type::NOTICE);
} }
} }
}); }
} finally { } finally {
$this->aFetchCallbacks = array(); $this->aFetchCallbacks = array();
} }
@ -1166,7 +1158,7 @@ class ImapClient extends \MailSo\Net\NetClient
} }
} }
protected function getResponse(string $sEndTag = null, callable $cbUntaggedResponse = null) : ResponseCollection protected function getResponse(string $sEndTag = null) : ResponseCollection
{ {
try { try {
$oResult = new ResponseCollection; $oResult = new ResponseCollection;
@ -1176,9 +1168,7 @@ class ImapClient extends \MailSo\Net\NetClient
while (true) { while (true) {
$oResponse = $this->partialParseResponse(); $oResponse = $this->partialParseResponse();
if (!$cbUntaggedResponse || Enumerations\ResponseType::UNTAGGED !== $oResponse->ResponseType || !$cbUntaggedResponse($oResponse)) { $oResult->append($oResponse);
$oResult->append($oResponse);
}
// RFC 5530 // RFC 5530
if ($sEndTag === $oResponse->Tag && \is_array($oResponse->OptionalResponse) && 'CLIENTBUG' === $oResponse->OptionalResponse[0]) { if ($sEndTag === $oResponse->Tag && \is_array($oResponse->OptionalResponse) && 'CLIENTBUG' === $oResponse->OptionalResponse[0]) {
@ -1209,6 +1199,50 @@ class ImapClient extends \MailSo\Net\NetClient
return $oResult; return $oResult;
} }
// public function yieldUntaggedResponses(string $sEndTag = null) : \Generator
public function yieldUntaggedResponses(string $sEndTag = null) : iterable
{
try {
$oResult = new ResponseCollection;
if (\is_resource($this->ConnectionResource())) {
$sEndTag = $sEndTag ?: $this->getCurrentTag();
while (true) {
$oResponse = $this->partialParseResponse();
if (Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType) {
yield $oResponse;
} else {
$oResult->append($oResponse);
}
// RFC 5530
if ($sEndTag === $oResponse->Tag && \is_array($oResponse->OptionalResponse) && 'CLIENTBUG' === $oResponse->OptionalResponse[0]) {
// The server has detected a client bug.
// \error_log("IMAP {$oResponse->OptionalResponse[0]}: {$this->lastCommand}");
}
if ($sEndTag === $oResponse->Tag || Enumerations\ResponseType::CONTINUATION === $oResponse->ResponseType) {
if (isset($this->aTagTimeouts[$sEndTag])) {
$this->writeLog((\microtime(true) - $this->aTagTimeouts[$sEndTag]).' ('.$sEndTag.')',
\MailSo\Log\Enumerations\Type::TIME);
unset($this->aTagTimeouts[$sEndTag]);
}
break;
}
}
}
$oResult->validate();
} catch (\Throwable $e) {
$this->writeLogException($e, \MailSo\Log\Enumerations\Type::WARNING);
throw $e;
}
}
protected function prepareParamLine(array $aParams = array()) : string protected function prepareParamLine(array $aParams = array()) : string
{ {
$sReturn = ''; $sReturn = '';

View file

@ -63,7 +63,7 @@ class ESEARCH extends Request
parent::__construct($oImapClient); parent::__construct($oImapClient);
} }
public function SendRequestGetResponse() : \MailSo\Imap\ResponseCollection public function SendRequest() : string
{ {
$sCmd = 'SEARCH'; $sCmd = 'SEARCH';
$aRequest = array(); $aRequest = array();
@ -120,7 +120,7 @@ class ESEARCH extends Request
$aRequest[] = $this->sLimit; $aRequest[] = $this->sLimit;
} }
return $this->oImapClient->SendRequestGetResponse( return $this->oImapClient->SendRequest(
($this->bUid ? 'UID ' : '') . $sCmd, ($this->bUid ? 'UID ' : '') . $sCmd,
$aRequest $aRequest
); );

View file

@ -64,7 +64,7 @@ class SORT extends Request
parent::__construct($oImapClient); parent::__construct($oImapClient);
} }
public function SendRequestGetResponse() : \MailSo\Imap\ResponseCollection public function SendRequest() : string
{ {
if (!$this->aSortTypes) { if (!$this->aSortTypes) {
$this->oImapClient->writeLogException( $this->oImapClient->writeLogException(
@ -109,7 +109,7 @@ class SORT extends Request
$aRequest[] = $this->sLimit; $aRequest[] = $this->sLimit;
} }
return $this->oImapClient->SendRequestGetResponse( return $this->oImapClient->SendRequest(
($this->bUid ? 'UID SORT' : 'SORT'), ($this->bUid ? 'UID SORT' : 'SORT'),
$aRequest $aRequest
); );

View file

@ -63,16 +63,15 @@ class THREAD extends Request
$aRequest[] = \strtoupper($this->sCharset); $aRequest[] = \strtoupper($this->sCharset);
$aRequest[] = $sSearchCriterias; $aRequest[] = $sSearchCriterias;
$oResponseCollection = $this->oImapClient->SendRequestGetResponse( $this->oImapClient->SendRequest(
($this->bUid ? 'UID THREAD' : 'THREAD'), ($this->bUid ? 'UID THREAD' : 'THREAD'),
$aRequest $aRequest
); );
$aReturn = array(); $aReturn = array();
foreach ($oResponseCollection as $oResponse) { foreach ($this->oImapClient->yieldUntaggedResponses() as $oResponse) {
$iOffset = ($bReturnUid && 'UID' === $oResponse->StatusOrIndex && !empty($oResponse->ResponseList[2]) && 'THREAD' === $oResponse->ResponseList[2]) ? 1 : 0; $iOffset = ($bReturnUid && 'UID' === $oResponse->StatusOrIndex && !empty($oResponse->ResponseList[2]) && 'THREAD' === $oResponse->ResponseList[2]) ? 1 : 0;
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType if (('THREAD' === $oResponse->StatusOrIndex || $iOffset)
&& ('THREAD' === $oResponse->StatusOrIndex || $iOffset)
&& \is_array($oResponse->ResponseList) && \is_array($oResponse->ResponseList)
&& 2 < \count($oResponse->ResponseList)) && 2 < \count($oResponse->ResponseList))
{ {