From 7de05b413c8950cd6044deac8061b16b40699f87 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 23 May 2024 16:17:00 +0200 Subject: [PATCH] fix: improve parsing of encapsulated icap headers Signed-off-by: Robin Appelman --- lib/ICAP/ResponseParser.php | 45 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/lib/ICAP/ResponseParser.php b/lib/ICAP/ResponseParser.php index d24ebbce..a4d6ce09 100644 --- a/lib/ICAP/ResponseParser.php +++ b/lib/ICAP/ResponseParser.php @@ -66,58 +66,37 @@ private function readIcapStatusLine($stream): IcapResponseStatus { } private function parseResHdr($stream, string $headerValue): array { - $encapsulatedHeaders = []; $encapsulatedParts = \explode(",", $headerValue); foreach ($encapsulatedParts as $encapsulatedPart) { $pieces = \explode("=", \trim($encapsulatedPart)); - if ($pieces[1] === "0") { - continue; + if ($pieces[0] === "res-hdr") { + $offset = (int)$pieces[1]; + if ($offset > 0) { + fseek($stream, $offset); + } + break; } - $rawEncapsulatedHeaders = \fread($stream, (int)$pieces[1]); - $encapsulatedHeaders = $this->parseEncapsulatedHeaders($rawEncapsulatedHeaders); - // According to the spec we have a single res-hdr part and are not interested in res-body content - break; } + + $status = trim(\fgets($stream)); + $encapsulatedHeaders = $this->readHeaders($stream); + $encapsulatedHeaders['HTTP_STATUS'] = $status; + return $encapsulatedHeaders; } private function readHeaders($stream): array { $headers = []; - $prevString = ""; while (($headerString = \fgets($stream)) !== false) { $trimmedHeaderString = \trim($headerString); - if ($prevString === "" && $trimmedHeaderString === "") { + if ($trimmedHeaderString === "") { break; } [$headerName, $headerValue] = $this->parseHeader($trimmedHeaderString); if ($headerName !== '') { $headers[$headerName] = $headerValue; - if ($headerName == "Encapsulated") { - break; - } - } - $prevString = $trimmedHeaderString; - } - return $headers; - } - - private function parseEncapsulatedHeaders(string $headerString): array { - $headers = []; - $split = \preg_split('/\r?\n/', \trim($headerString)); - $statusLine = \array_shift($split); - if ($statusLine !== null) { - $headers['HTTP_STATUS'] = $statusLine; - } - foreach (\preg_split('/\r?\n/', $headerString) as $line) { - if ($line === '') { - continue; - } - [$name, $value] = $this->parseHeader($line); - if ($name !== '') { - $headers[$name] = $value; } } - return $headers; }