} */ public function parse(string $payload): array { $payload = trim($payload); $offset = 0; $nameToken = $this->readToken($payload, $offset); $statusToken = $this->readToken($payload, $offset); if ($nameToken === null || $statusToken === null) { throw new ImapException('Unable to parse STATUS response payload: ' . $payload); } $mailbox = $this->decodeAtom($nameToken); if ($mailbox === null || $mailbox === '') { throw new ImapException('STATUS response is missing a mailbox name: ' . $payload); } return [$mailbox, $this->parseItems($statusToken, $payload)]; } /** * @return array */ private function parseItems(string $statusToken, string $payload): array { $statusToken = trim($statusToken); if (!str_starts_with($statusToken, '(') || !str_ends_with($statusToken, ')')) { throw new ImapException('Invalid STATUS data payload: ' . $payload); } $items = trim(substr($statusToken, 1, -1)); if ($items === '') { return []; } $tokens = preg_split('/\s+/', $items) ?: []; if (count($tokens) % 2 !== 0) { throw new ImapException('Malformed STATUS item list: ' . $payload); } $status = []; for ($index = 0; $index < count($tokens); $index += 2) { $item = strtoupper($tokens[$index]); $value = $tokens[$index + 1]; if (!preg_match('/^\d+$/', $value)) { throw new ImapException('STATUS item value must be numeric: ' . $payload); } $status[$item] = (int) $value; } return $status; } private function readToken(string $payload, int &$offset): ?string { $length = strlen($payload); while ($offset < $length && ctype_space($payload[$offset])) { $offset++; } if ($offset >= $length) { return null; } if ($payload[$offset] === '(') { $end = strpos($payload, ')', $offset); if ($end === false) { throw new ImapException('Unterminated STATUS item block: ' . $payload); } $token = substr($payload, $offset, $end - $offset + 1); $offset = $end + 1; return $token; } if ($payload[$offset] === '"') { $start = $offset; $offset++; while ($offset < $length) { if ($payload[$offset] === '\\') { $offset += 2; continue; } if ($payload[$offset] === '"') { $offset++; return substr($payload, $start, $offset - $start); } $offset++; } throw new ImapException('Unterminated quoted STATUS token: ' . $payload); } $start = $offset; while ($offset < $length && !ctype_space($payload[$offset])) { $offset++; } return substr($payload, $start, $offset - $start); } private function decodeAtom(string $value): ?string { $value = trim($value); if (strtoupper($value) === 'NIL') { return null; } if (str_starts_with($value, '"') && str_ends_with($value, '"')) { return stripcslashes(substr($value, 1, -1)); } return $value; } }