Some IMAP ResponseParser improvements

This commit is contained in:
djmaze 2021-11-04 16:25:54 +01:00
parent d961d8e836
commit 40b8bf3d7e
2 changed files with 39 additions and 70 deletions

View file

@ -11,6 +11,8 @@
namespace MailSo\Imap; namespace MailSo\Imap;
use \MailSo\Imap\Enumerations\ResponseType;
/** /**
* @category MailSo * @category MailSo
* @package Imap * @package Imap
@ -20,12 +22,12 @@ class Response
/** /**
* @var array * @var array
*/ */
public $ResponseList; public $ResponseList = array();
/** /**
* @var array | null * @var array | null
*/ */
public $OptionalResponse; public $OptionalResponse = null;
/** /**
* @var string * @var string
@ -35,34 +37,23 @@ class Response
/** /**
* @var string * @var string
*/ */
public $HumanReadable; public $HumanReadable = '';
/** /**
* @var bool * @var bool
*/ */
public $IsStatusResponse; public $IsStatusResponse = false;
/** /**
* @var string * @var int
*/ */
public $ResponseType; public $ResponseType = 0;
/** /**
* @var string * @var string
*/ */
public $Tag; public $Tag;
function __construct()
{
$this->ResponseList = array();
$this->OptionalResponse = null;
$this->StatusOrIndex = '';
$this->HumanReadable = '';
$this->IsStatusResponse = false;
$this->ResponseType = \MailSo\Imap\Enumerations\ResponseType::UNKNOWN;
$this->Tag = '';
}
private function recToLine(array $aList) : string private function recToLine(array $aList) : string
{ {
$aResult = array(); $aResult = array();
@ -73,6 +64,25 @@ class Response
return \implode(' ', $aResult); return \implode(' ', $aResult);
} }
public function setStatus(string $value) : void
{
$value = \strtoupper($value);
$this->StatusOrIndex = $value;
$this->IsStatusResponse = \defined("\\MailSo\\Imap\\Enumerations\\ResponseStatus::{$value}");
}
public function setTag(string $value) : void
{
$this->Tag = $value;
if ('+' === $value) {
$this->ResponseType = ResponseType::CONTINUATION;
} else if ('*' === $value) {
$this->ResponseType = ResponseType::UNTAGGED;
} else {
$this->ResponseType = ResponseType::UNKNOWN;
}
}
public function ToLine() : string public function ToLine() : string
{ {
return $this->recToLine($this->ResponseList); return $this->recToLine($this->ResponseList);

View file

@ -12,7 +12,6 @@
namespace MailSo\Imap\Traits; namespace MailSo\Imap\Traits;
use \MailSo\Imap\Response; use \MailSo\Imap\Response;
use \MailSo\Imap\Enumerations\ResponseStatus;
use \MailSo\Imap\Enumerations\ResponseType; use \MailSo\Imap\Enumerations\ResponseType;
use \MailSo\Imap\Exceptions\ResponseNotFoundException; use \MailSo\Imap\Exceptions\ResponseNotFoundException;
@ -84,9 +83,6 @@ trait ResponseParser
$bIsGotoDefault = false; $bIsGotoDefault = false;
$bCountOneInited = false;
$bCountTwoInited = false;
$sAtomBuilder = $bTreatAsAtom ? '' : null; $sAtomBuilder = $bTreatAsAtom ? '' : null;
$aList = array(); $aList = array();
if ($bRoot) if ($bRoot)
@ -258,15 +254,12 @@ trait ResponseParser
if ($bRoot && $oImapResponse->IsStatusResponse) if ($bRoot && $oImapResponse->IsStatusResponse)
{ {
$iPos = $iBufferEndIndex; $iPos = $iBufferEndIndex;
if ($iPos > $iCharBlockStartPos) {
while ($iPos > $iCharBlockStartPos && $this->sResponseBuffer[$iCharBlockStartPos] === ' ') $iCharBlockStartPos += \strspn($this->sResponseBuffer, ' ', $iCharBlockStartPos, $iPos - $iCharBlockStartPos);
{
++$iCharBlockStartPos;
} }
} }
$bIsAtomDone = false; while ($iPos <= $iBufferEndIndex)
while (!$bIsAtomDone && ($iPos <= $iBufferEndIndex))
{ {
$sCharDef = $this->sResponseBuffer[$iPos]; $sCharDef = $this->sResponseBuffer[$iPos];
switch (true) switch (true)
@ -282,8 +275,7 @@ trait ResponseParser
$sAtomBuilder .= \substr($this->sResponseBuffer, $iCharBlockStartPos, $iPos - $iCharBlockStartPos + 1); $sAtomBuilder .= \substr($this->sResponseBuffer, $iCharBlockStartPos, $iPos - $iCharBlockStartPos + 1);
++$iPos; $this->iResponseBufParsedPos = ++$iPos;
$this->iResponseBufParsedPos = $iPos;
$sListBlock = $this->partialParseResponseBranch($oImapResponse, true, $sListBlock = $this->partialParseResponseBranch($oImapResponse, true,
null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase), null === $sPreviousAtomUpperCase ? '' : \strtoupper($sPreviousAtomUpperCase),
@ -300,8 +292,7 @@ trait ResponseParser
case ' ' === $sCharDef: case ' ' === $sCharDef:
case ')' === $sCharDef && '(' === $sOpenBracket: case ')' === $sCharDef && '(' === $sOpenBracket:
case ']' === $sCharDef && '[' === $sOpenBracket: case ']' === $sCharDef && '[' === $sOpenBracket:
$bIsAtomDone = true; break 2;
break;
default: default:
++$iPos; ++$iPos;
break; break;
@ -330,52 +321,20 @@ trait ResponseParser
if ($bRoot) if ($bRoot)
{ {
// if (1 === \count($aList)) if (!isset($oImapResponse->Tag) && 1 === \count($aList))
if (!$bCountOneInited && 1 === \count($aList))
// if (isset($aList[0]) && !isset($aList[1])) // fast 1 === \count($aList)
{ {
$bCountOneInited = true; $oImapResponse->setTag($aList[0]);
if ($this->getCurrentTag() === $oImapResponse->Tag)
$oImapResponse->Tag = $aList[0];
if ('+' === $oImapResponse->Tag)
{
$oImapResponse->ResponseType = ResponseType::CONTINUATION;
}
else if ('*' === $oImapResponse->Tag)
{
$oImapResponse->ResponseType = ResponseType::UNTAGGED;
}
else if ($this->getCurrentTag() === $oImapResponse->Tag)
{ {
$oImapResponse->ResponseType = ResponseType::TAGGED; $oImapResponse->ResponseType = ResponseType::TAGGED;
} }
else
{
$oImapResponse->ResponseType = ResponseType::UNKNOWN;
}
} }
// else if (2 === \count($aList)) else if (!isset($oImapResponse->StatusOrIndex) && 2 === \count($aList))
else if (!$bCountTwoInited && 2 === \count($aList))
// else if (isset($aList[1]) && !isset($aList[2])) // fast 2 === \count($aList)
{ {
$bCountTwoInited = true; $oImapResponse->setStatus($aList[1]);
$oImapResponse->StatusOrIndex = \strtoupper($aList[1]);
if ($oImapResponse->StatusOrIndex == ResponseStatus::OK ||
$oImapResponse->StatusOrIndex == ResponseStatus::NO ||
$oImapResponse->StatusOrIndex == ResponseStatus::BAD ||
$oImapResponse->StatusOrIndex == ResponseStatus::BYE ||
$oImapResponse->StatusOrIndex == ResponseStatus::PREAUTH)
{
$oImapResponse->IsStatusResponse = true;
}
} }
else if (ResponseType::CONTINUATION === $oImapResponse->ResponseType) else if (ResponseType::CONTINUATION === $oImapResponse->ResponseType
{ || $oImapResponse->IsStatusResponse)
$oImapResponse->HumanReadable = $sLastCharBlock;
}
else if ($oImapResponse->IsStatusResponse)
{ {
$oImapResponse->HumanReadable = $sLastCharBlock; $oImapResponse->HumanReadable = $sLastCharBlock;
} }