| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 1 |
+<?php |
|
| 2 |
+ |
|
| 3 |
+declare(strict_types=1); |
|
| 4 |
+ |
|
| 5 |
+namespace GuzzleHttp\Psr7; |
|
| 6 |
+ |
|
| 7 |
+use Psr\Http\Message\StreamInterface; |
|
| 8 |
+ |
|
| 9 |
+/** |
|
| 10 |
+ * Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content. |
|
| 11 |
+ * |
|
| 12 |
+ * This stream decorator converts the provided stream to a PHP stream resource, |
|
| 13 |
+ * then appends the zlib.inflate filter. The stream is then converted back |
|
| 14 |
+ * to a Guzzle stream resource to be used as a Guzzle stream. |
|
| 15 |
+ * |
|
| 16 |
+ * @see https://datatracker.ietf.org/doc/html/rfc1950 |
|
| 17 |
+ * @see https://datatracker.ietf.org/doc/html/rfc1952 |
|
| 18 |
+ * @see https://www.php.net/manual/en/filters.compression.php |
|
| 19 |
+ */ |
|
| 20 |
+final class InflateStream implements StreamInterface |
|
| 21 |
+{
|
|
| 22 |
+ use StreamDecoratorTrait; |
|
| 23 |
+ |
|
| 24 |
+ /** @var StreamInterface */ |
|
| 25 |
+ private $stream; |
|
| 26 |
+ |
|
| 27 |
+ public function __construct(StreamInterface $stream) |
|
| 28 |
+ {
|
|
| 29 |
+ $resource = StreamWrapper::getResource($stream); |
|
| 30 |
+ // Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data |
|
| 31 |
+ // See https://www.zlib.net/manual.html#Advanced definition of inflateInit2 |
|
| 32 |
+ // "Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" |
|
| 33 |
+ // Default window size is 15. |
|
| 34 |
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15 + 32]); |
|
| 35 |
+ $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); |
|
| 36 |
+ } |
|
| 37 |
+} |
| 1 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,53 +0,0 @@ |
| 1 |
-<?php |
|
| 2 |
- |
|
| 3 |
-namespace GuzzleHttp\Psr7; |
|
| 4 |
- |
|
| 5 |
-use Psr\Http\Message\StreamInterface; |
|
| 6 |
- |
|
| 7 |
-/** |
|
| 8 |
- * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content. |
|
| 9 |
- * |
|
| 10 |
- * This stream decorator skips the first 10 bytes of the given stream to remove |
|
| 11 |
- * the gzip header, converts the provided stream to a PHP stream resource, |
|
| 12 |
- * then appends the zlib.inflate filter. The stream is then converted back |
|
| 13 |
- * to a Guzzle stream resource to be used as a Guzzle stream. |
|
| 14 |
- * |
|
| 15 |
- * @link http://tools.ietf.org/html/rfc1952 |
|
| 16 |
- * @link http://php.net/manual/en/filters.compression.php |
|
| 17 |
- */ |
|
| 18 |
-class InflateStream implements StreamInterface |
|
| 19 |
-{
|
|
| 20 |
- use StreamDecoratorTrait; |
|
| 21 |
- |
|
| 22 |
- public function __construct(StreamInterface $stream) |
|
| 23 |
- {
|
|
| 24 |
- // read the first 10 bytes, ie. gzip header |
|
| 25 |
- $header = $stream->read(10); |
|
| 26 |
- $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); |
|
| 27 |
- // Skip the header, that is 10 + length of filename + 1 (nil) bytes |
|
| 28 |
- $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); |
|
| 29 |
- $resource = StreamWrapper::getResource($stream); |
|
| 30 |
- stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); |
|
| 31 |
- $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- /** |
|
| 35 |
- * @param StreamInterface $stream |
|
| 36 |
- * @param $header |
|
| 37 |
- * @return int |
|
| 38 |
- */ |
|
| 39 |
- private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header) |
|
| 40 |
- {
|
|
| 41 |
- $filename_header_length = 0; |
|
| 42 |
- |
|
| 43 |
- if (substr(bin2hex($header), 6, 2) === '08') {
|
|
| 44 |
- // we have a filename, read until nil |
|
| 45 |
- $filename_header_length = 1; |
|
| 46 |
- while ($stream->read(1) !== chr(0)) {
|
|
| 47 |
- $filename_header_length++; |
|
| 48 |
- } |
|
| 49 |
- } |
|
| 50 |
- |
|
| 51 |
- return $filename_header_length; |
|
| 52 |
- } |
|
| 53 |
-} |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,53 @@ |
| 1 |
+<?php |
|
| 2 |
+ |
|
| 3 |
+namespace GuzzleHttp\Psr7; |
|
| 4 |
+ |
|
| 5 |
+use Psr\Http\Message\StreamInterface; |
|
| 6 |
+ |
|
| 7 |
+/** |
|
| 8 |
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content. |
|
| 9 |
+ * |
|
| 10 |
+ * This stream decorator skips the first 10 bytes of the given stream to remove |
|
| 11 |
+ * the gzip header, converts the provided stream to a PHP stream resource, |
|
| 12 |
+ * then appends the zlib.inflate filter. The stream is then converted back |
|
| 13 |
+ * to a Guzzle stream resource to be used as a Guzzle stream. |
|
| 14 |
+ * |
|
| 15 |
+ * @link http://tools.ietf.org/html/rfc1952 |
|
| 16 |
+ * @link http://php.net/manual/en/filters.compression.php |
|
| 17 |
+ */ |
|
| 18 |
+class InflateStream implements StreamInterface |
|
| 19 |
+{
|
|
| 20 |
+ use StreamDecoratorTrait; |
|
| 21 |
+ |
|
| 22 |
+ public function __construct(StreamInterface $stream) |
|
| 23 |
+ {
|
|
| 24 |
+ // read the first 10 bytes, ie. gzip header |
|
| 25 |
+ $header = $stream->read(10); |
|
| 26 |
+ $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); |
|
| 27 |
+ // Skip the header, that is 10 + length of filename + 1 (nil) bytes |
|
| 28 |
+ $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); |
|
| 29 |
+ $resource = StreamWrapper::getResource($stream); |
|
| 30 |
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); |
|
| 31 |
+ $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ /** |
|
| 35 |
+ * @param StreamInterface $stream |
|
| 36 |
+ * @param $header |
|
| 37 |
+ * @return int |
|
| 38 |
+ */ |
|
| 39 |
+ private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header) |
|
| 40 |
+ {
|
|
| 41 |
+ $filename_header_length = 0; |
|
| 42 |
+ |
|
| 43 |
+ if (substr(bin2hex($header), 6, 2) === '08') {
|
|
| 44 |
+ // we have a filename, read until nil |
|
| 45 |
+ $filename_header_length = 1; |
|
| 46 |
+ while ($stream->read(1) !== chr(0)) {
|
|
| 47 |
+ $filename_header_length++; |
|
| 48 |
+ } |
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ return $filename_header_length; |
|
| 52 |
+ } |
|
| 53 |
+} |