From 0a971efc85f6dd4437e27599983e157f267d4937 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 11:54:17 +0200 Subject: [PATCH 01/12] Catch faulty stream wrapper implementations in StreamReader constructor.. --- src/PdfParser/StreamReader.php | 6 +++ .../PdfParser/DummyFaultyStreamWrapper.php | 52 +++++++++++++++++++ tests/unit/PdfParser/StreamReaderTest.php | 17 ++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/unit/PdfParser/DummyFaultyStreamWrapper.php diff --git a/src/PdfParser/StreamReader.php b/src/PdfParser/StreamReader.php index 0c484fa..a493a85 100644 --- a/src/PdfParser/StreamReader.php +++ b/src/PdfParser/StreamReader.php @@ -113,6 +113,12 @@ public function __construct($stream, $closeStream = false) ); } + if (fseek($stream, 0) === -1) { + throw new \InvalidArgumentException( + 'Given stream is not seekable!' + ); + } + $this->stream = $stream; $this->closeStream = $closeStream; $this->reset(); diff --git a/tests/unit/PdfParser/DummyFaultyStreamWrapper.php b/tests/unit/PdfParser/DummyFaultyStreamWrapper.php new file mode 100644 index 0000000..35d148a --- /dev/null +++ b/tests/unit/PdfParser/DummyFaultyStreamWrapper.php @@ -0,0 +1,52 @@ +assertTrue($caught); + } + public function testConstructor() { $resource = fopen('php://temp', 'r+b'); From e338d4ceb38b6360c77b6d399a815964a2e4d0a2 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 15:40:07 +0200 Subject: [PATCH 02/12] Optimized parameter naming --- src/PdfParser/Type/PdfIndirectObject.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PdfParser/Type/PdfIndirectObject.php b/src/PdfParser/Type/PdfIndirectObject.php index 8b7898f..c3c40cb 100644 --- a/src/PdfParser/Type/PdfIndirectObject.php +++ b/src/PdfParser/Type/PdfIndirectObject.php @@ -22,8 +22,8 @@ class PdfIndirectObject extends PdfType /** * Parses an indirect object from a tokenizer, parser and stream-reader. * - * @param int $objectNumberToken - * @param int $objectGenerationNumberToken + * @param int $objectNumber + * @param int $objectGenerationNumber * @param PdfParser $parser * @param Tokenizer $tokenizer * @param StreamReader $reader @@ -31,8 +31,8 @@ class PdfIndirectObject extends PdfType * @throws PdfTypeException */ public static function parse( - $objectNumberToken, - $objectGenerationNumberToken, + $objectNumber, + $objectGenerationNumber, PdfParser $parser, Tokenizer $tokenizer, StreamReader $reader @@ -50,8 +50,8 @@ public static function parse( } $v = new self(); - $v->objectNumber = (int) $objectNumberToken; - $v->generationNumber = (int) $objectGenerationNumberToken; + $v->objectNumber = (int) $objectNumber; + $v->generationNumber = (int) $objectGenerationNumber; $v->value = $value; return $v; From 5accf14b32b2223e2ef00e0966300a17d8ae54d8 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 15:42:12 +0200 Subject: [PATCH 03/12] Moved value parsing into explicit methods --- src/PdfParser/PdfParser.php | 82 ++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/src/PdfParser/PdfParser.php b/src/PdfParser/PdfParser.php index a127cfc..a95461b 100644 --- a/src/PdfParser/PdfParser.php +++ b/src/PdfParser/PdfParser.php @@ -25,6 +25,7 @@ use setasign\Fpdi\PdfParser\Type\PdfString; use setasign\Fpdi\PdfParser\Type\PdfToken; use setasign\Fpdi\PdfParser\Type\PdfType; +use setasign\Fpdi\PdfParser\Type\PdfTypeException; /** * A PDF parser class @@ -258,25 +259,25 @@ public function readValue($token = null, $expectedType = null) switch ($token) { case '(': $this->ensureExpectedType($token, $expectedType); - return PdfString::parse($this->streamReader); + return $this->parsePdfString(); case '<': if ($this->streamReader->getByte() === '<') { $this->ensureExpectedType('<<', $expectedType); $this->streamReader->addOffset(1); - return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this); + return $this->parsePdfDictionary(); } $this->ensureExpectedType($token, $expectedType); - return PdfHexString::parse($this->streamReader); + return $this->parsePdfHexString(); case '/': $this->ensureExpectedType($token, $expectedType); - return PdfName::parse($this->tokenizer, $this->streamReader); + return $this->parsePdfName(); case '[': $this->ensureExpectedType($token, $expectedType); - return PdfArray::parse($this->tokenizer, $this); + return $this->parsePdfArray(); default: if (\is_numeric($token)) { @@ -291,13 +292,7 @@ public function readValue($token = null, $expectedType = null) ); } - return PdfIndirectObject::parse( - (int) $token, - (int) $token2, - $this, - $this->tokenizer, - $this->streamReader - ); + return $this->parsePdfIndirectObject((int)$token, (int)$token2); case 'R': if ( $expectedType !== null && @@ -309,7 +304,7 @@ public function readValue($token = null, $expectedType = null) ); } - return PdfIndirectObjectReference::create((int) $token, (int) $token2); + return PdfIndirectObjectReference::create((int)$token, (int)$token2); } $this->tokenizer->pushStack($token3); @@ -351,6 +346,65 @@ public function readValue($token = null, $expectedType = null) } } + /** + * @return PdfString + */ + protected function parsePdfString() + { + return PdfString::parse($this->streamReader); + } + + /** + * @return bool|PdfHexString + */ + protected function parsePdfHexString() + { + return PdfHexString::parse($this->streamReader); + } + + /** + * @return bool|PdfDictionary + * @throws PdfTypeException + */ + protected function parsePdfDictionary() + { + return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this); + } + + /** + * @return PdfName + */ + protected function parsePdfName() + { + return PdfName::parse($this->tokenizer, $this->streamReader); + } + + /** + * @return bool|PdfArray + * @throws PdfTypeException + */ + protected function parsePdfArray() + { + return PdfArray::parse($this->tokenizer, $this); + } + + /** + * @param int $objectNumber + * @param int $generationNumber + * @return bool|PdfIndirectObject + * @throws Type\PdfTypeException + */ + protected function parsePdfIndirectObject($objectNumber, $generationNumber) + { + return PdfIndirectObject::parse( + $objectNumber, + $generationNumber, + $this, + $this->tokenizer, + $this->streamReader + ); + } + /** * Ensures that the token will evaluate to an expected object type (or not). * @@ -359,7 +413,7 @@ public function readValue($token = null, $expectedType = null) * @return bool * @throws Type\PdfTypeException */ - private function ensureExpectedType($token, $expectedType) + protected function ensureExpectedType($token, $expectedType) { static $mapping = [ '(' => PdfString::class, From 984dace82826b4fc8936bf1bfbb9c3112b745237 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 16:05:23 +0200 Subject: [PATCH 04/12] Added PdfString::escape() method --- src/PdfParser/Type/PdfString.php | 30 ++++++++++++++++++++++++++++++ src/Tcpdf/Fpdi.php | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/PdfParser/Type/PdfString.php b/src/PdfParser/Type/PdfString.php index 41b66ed..f1598d1 100644 --- a/src/PdfParser/Type/PdfString.php +++ b/src/PdfParser/Type/PdfString.php @@ -78,6 +78,36 @@ public static function ensure($string) return PdfType::ensureType(self::class, $string, 'String value expected.'); } + /** + * Escapes sequences in a string according to the PDF specification. + * + * @param string $s + * @return string + */ + public static function escape($s) + { + // Still a bit faster, than direct replacing + if (strpos($s, '\\') !== false || + strpos($s, ')') !== false || + strpos($s, '(') !== false || + strpos($s, "\x0D") !== false || + strpos($s, "\x0A") !== false || + strpos($s, "\x09") !== false || + strpos($s, "\x08") !== false || + strpos($s, "\x0C") !== false + ) + { + // is faster than strtr(...) + return str_replace( + ['\\', ')', '(', "\x0D", "\x0A", "\x09", "\x08", "\x0C"], + ['\\\\', '\\)', '\\(', '\r', '\n', '\t', '\b', '\f'], + $s + ); + } + + return $s; + } + /** * Unescapes escaped sequences in a PDF string according to the PDF specification. * diff --git a/src/Tcpdf/Fpdi.php b/src/Tcpdf/Fpdi.php index fc3b362..1f5b1e8 100644 --- a/src/Tcpdf/Fpdi.php +++ b/src/Tcpdf/Fpdi.php @@ -251,7 +251,7 @@ protected function writePdfType(PdfType $value) if ($value instanceof PdfString) { $string = PdfString::unescape($value->value); $string = $this->_encrypt_data($this->currentObjectNumber, $string); - $value->value = \TCPDF_STATIC::_escape($string); + $value->value = PdfString::escape($string); } elseif ($value instanceof PdfHexString) { $filter = new AsciiHex(); $string = $filter->decode($value->value); From 268ea0ac75ac6a86b0875f85473d45101638d6f4 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 16:05:48 +0200 Subject: [PATCH 05/12] Added tests for PdfString::escape() and PdfString::unescape() --- tests/unit/PdfParser/Type/PdfStringTest.php | 121 +++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/tests/unit/PdfParser/Type/PdfStringTest.php b/tests/unit/PdfParser/Type/PdfStringTest.php index d63d5bd..bc9a3c1 100644 --- a/tests/unit/PdfParser/Type/PdfStringTest.php +++ b/tests/unit/PdfParser/Type/PdfStringTest.php @@ -36,4 +36,123 @@ public function testEnsure() $b = PdfString::ensure($a); $this->assertSame($a, $b); } -} \ No newline at end of file + + public function escapeProvider() + { + return [ + // in => out + ['do not escape', 'do not escape'], + ['abcd\\', 'abcd\\\\'], + ['\\abcd', '\\\\abcd'], + ['ab\\cd', 'ab\\\\cd'], + + ['abcd)', 'abcd\)'], + [')abcd', '\)abcd'], + ['ab)cd', 'ab\)cd'], + + ['abcd(', 'abcd\('], + ['(abcd', '\(abcd'], + ['ab(cd', 'ab\(cd'], + + ["abcd\x0D", 'abcd\r'], + ["\x0Dabcd", '\rabcd'], + ["ab\x0Dcd", 'ab\rcd'], + + ["abcd\x0A", 'abcd\n'], + ["\x0Aabcd", '\nabcd'], + ["ab\x0Acd", 'ab\ncd'], + + ["abcd\x09", 'abcd\t'], + ["\x09abcd", '\tabcd'], + ["ab\x09cd", 'ab\tcd'], + + ["abcd\x08", 'abcd\b'], + ["\x08abcd", '\babcd'], + ["ab\x08cd", 'ab\bcd'], + + ["abcd\x0C", 'abcd\f'], + ["\x0Cabcd", '\fabcd'], + ["ab\x0Ccd", 'ab\fcd'], + ]; + } + + /** + * @dataProvider escapeProvider + */ + public function testEscape($in, $out) + { + $this->assertEquals($out, PdfString::escape($in)); + } + + public function unescapeProvider() + { + return [ + // out , in + ['do not unescape', 'do not unescape'], + + ['abcd\\', 'abcd\\\\'], + ['\\abcd', '\\\\abcd'], + ['ab\\cd', 'ab\\\\cd'], + + ['abcd)', 'abcd\)'], + [')abcd', '\)abcd'], + ['ab)cd', 'ab\)cd'], + + ['abcd(', 'abcd\('], + ['(abcd', '\(abcd'], + ['ab(cd', 'ab\(cd'], + + ["abcd\x0D", 'abcd\r'], + ["\x0Dabcd", '\rabcd'], + ["ab\x0Dcd", 'ab\rcd'], + + ["abcd\x0A", 'abcd\n'], + ["\x0Aabcd", '\nabcd'], + ["ab\x0Acd", 'ab\ncd'], + + ["abcd\x09", 'abcd\t'], + ["\x09abcd", '\tabcd'], + ["ab\x09cd", 'ab\tcd'], + + ["abcd\x08", 'abcd\b'], + ["\x08abcd", '\babcd'], + ["ab\x08cd", 'ab\bcd'], + + ["abcd\x0C", 'abcd\f'], + ["\x0Cabcd", '\fabcd'], + ["ab\x0Ccd", 'ab\fcd'], + + ["A simple\nline break", "A simple\nline break"], + ["A simple\nline break", "A simple\\nline break"], + ["Another simple\rline break", "Another simple\rline break"], + ["Another simple\rline break", "Another simple\\rline break"], + ["And again another simple\r\nline break", "And again another simple\r\nline break"], + ["And again another simple\r\nline break", "And again another simple\\r\\nline break"], + + ["A long text without a line break", "A long text \\\rwithout a line break"], + ["A long text without a line break", "A long text \\\nwithout a line break"], + ["A long text without a line break", "A long text \\\r\nwithout a line break"], + + [chr(octdec('245')), '\245'], + [chr(octdec('307')), '\307'], + + [chr(octdec('053')), '\053'], + [chr(octdec('053')), '\53'], + [chr(octdec('005')).'3', '\0053'], + [chr(octdec('005')), '\5'], + + ['just ignored', '\just ignored'], + ['just ignored', 'just\ ignored'], + ['just ignored', 'just i\gnored'], + ['just ignored', 'just ignored\\'], + ]; + } + + /** + * @dataProvider unescapeProvider + */ + public function testUnescape($out, $in) + { + $this->assertEquals($out, PdfString::unescape($in)); + } +} From a40897cff8410e5cb0f94891385e0ada1845a38e Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Mon, 18 Sep 2023 17:36:42 +0200 Subject: [PATCH 06/12] Added handling for Crypt filter in PdfStream class --- src/PdfParser/Type/PdfStream.php | 15 +++++++++++++ .../PdfParser/Type/PdfStreamTest.php | 22 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/PdfParser/Type/PdfStream.php b/src/PdfParser/Type/PdfStream.php index f72114e..492d625 100644 --- a/src/PdfParser/Type/PdfStream.php +++ b/src/PdfParser/Type/PdfStream.php @@ -308,6 +308,21 @@ public function getUnfilteredStream() $stream = $filterObject->decode($stream); break; + case 'Crypt': + if (!$decodeParam instanceof PdfDictionary) { + break; + } + // Filter is "Identity" + $name = PdfDictionary::get($decodeParam, 'Name'); + if (!$name instanceof PdfName || $name->value !== 'Identity') { + break; + } + + throw new FilterException( + 'Support for Crypt filters other than "Identity" is not implemented.', + FilterException::UNSUPPORTED_FILTER + ); + default: throw new FilterException( \sprintf('Unsupported filter "%s".', $filter->value), diff --git a/tests/functional/PdfParser/Type/PdfStreamTest.php b/tests/functional/PdfParser/Type/PdfStreamTest.php index 457e491..c3e6bd7 100644 --- a/tests/functional/PdfParser/Type/PdfStreamTest.php +++ b/tests/functional/PdfParser/Type/PdfStreamTest.php @@ -423,4 +423,26 @@ public function testGetUnfilteredStream($file, $objectNumber, $expectedResult) $this->assertEquals($expectedResult, $stream->getUnfilteredStream()); } + + + public function testParseWithCryptFilter() + { + $in = "123 0 obj\n<>\nstream\nHello\nendstream\nendobj"; + + $stream = StreamReader::createByString($in); + + // set position and prepare dictionary (equals to result) + $stream->setOffset(45); + $this->assertSame("\n", $stream->getByte()); // this is the \n after the stream keyword + + $dict = PdfDictionary::create([ + 'Filter' => PdfName::create('Crypt'), + 'Length' => PdfNumeric::create(5) + ]); + + $result = PdfStream::parse($dict, $stream); + + $this->assertSame($dict, $result->value); + $this->assertSame('Hello', $result->getUnfilteredStream()); + } } From a42d5e06796dffdf22be676bcf44a941b6d6d399 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Tue, 19 Sep 2023 15:31:04 +0200 Subject: [PATCH 07/12] Update PdfStreamTest.php --- tests/functional/PdfParser/Type/PdfStreamTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/PdfParser/Type/PdfStreamTest.php b/tests/functional/PdfParser/Type/PdfStreamTest.php index c3e6bd7..42b1f62 100644 --- a/tests/functional/PdfParser/Type/PdfStreamTest.php +++ b/tests/functional/PdfParser/Type/PdfStreamTest.php @@ -424,7 +424,6 @@ public function testGetUnfilteredStream($file, $objectNumber, $expectedResult) $this->assertEquals($expectedResult, $stream->getUnfilteredStream()); } - public function testParseWithCryptFilter() { $in = "123 0 obj\n<>\nstream\nHello\nendstream\nendobj"; From 79b632e854149a076d39185f0286321437f28af3 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Tue, 19 Sep 2023 15:31:18 +0200 Subject: [PATCH 08/12] Added PdfStream::getFilters() method --- src/PdfParser/Type/PdfStream.php | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/PdfParser/Type/PdfStream.php b/src/PdfParser/Type/PdfStream.php index 492d625..42f2be4 100644 --- a/src/PdfParser/Type/PdfStream.php +++ b/src/PdfParser/Type/PdfStream.php @@ -213,18 +213,16 @@ protected function extractStream() } /** - * Get the unfiltered stream data. - * - * @return string - * @throws FilterException - * @throws PdfParserException + * Get all filters defined for that stream. + * + * @return PdfType[] + * @throws PdfTypeException */ - public function getUnfilteredStream() + public function getFilters() { - $stream = $this->getStream(); $filters = PdfDictionary::get($this->value, 'Filter'); if ($filters instanceof PdfNull) { - return $stream; + return []; } if ($filters instanceof PdfArray) { @@ -233,6 +231,24 @@ public function getUnfilteredStream() $filters = [$filters]; } + return $filters; + } + + /** + * Get the unfiltered stream data. + * + * @return string + * @throws FilterException + * @throws PdfParserException + */ + public function getUnfilteredStream() + { + $stream = $this->getStream(); + $filters = $this->getFilters(); + if ($filters === []) { + return $stream; + } + $decodeParams = PdfDictionary::get($this->value, 'DecodeParms'); if ($decodeParams instanceof PdfArray) { $decodeParams = $decodeParams->value; From d000ff62f86c61fe87454849d21875a0ffaeb1e1 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Tue, 26 Sep 2023 15:30:18 +0200 Subject: [PATCH 09/12] Optimized doc-blocks --- src/PdfParser/PdfParser.php | 2 +- src/PdfParser/Type/PdfIndirectObject.php | 2 +- src/PdfParser/Type/PdfStream.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PdfParser/PdfParser.php b/src/PdfParser/PdfParser.php index a95461b..035919a 100644 --- a/src/PdfParser/PdfParser.php +++ b/src/PdfParser/PdfParser.php @@ -391,7 +391,7 @@ protected function parsePdfArray() /** * @param int $objectNumber * @param int $generationNumber - * @return bool|PdfIndirectObject + * @return false|PdfIndirectObject * @throws Type\PdfTypeException */ protected function parsePdfIndirectObject($objectNumber, $generationNumber) diff --git a/src/PdfParser/Type/PdfIndirectObject.php b/src/PdfParser/Type/PdfIndirectObject.php index c3c40cb..72a80e1 100644 --- a/src/PdfParser/Type/PdfIndirectObject.php +++ b/src/PdfParser/Type/PdfIndirectObject.php @@ -27,7 +27,7 @@ class PdfIndirectObject extends PdfType * @param PdfParser $parser * @param Tokenizer $tokenizer * @param StreamReader $reader - * @return bool|self + * @return self|false * @throws PdfTypeException */ public static function parse( diff --git a/src/PdfParser/Type/PdfStream.php b/src/PdfParser/Type/PdfStream.php index 42f2be4..68d901f 100644 --- a/src/PdfParser/Type/PdfStream.php +++ b/src/PdfParser/Type/PdfStream.php @@ -214,7 +214,7 @@ protected function extractStream() /** * Get all filters defined for that stream. - * + * * @return PdfType[] * @throws PdfTypeException */ From bdbca9797f6112fe14c19a05d435f33788a7c7b9 Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Tue, 26 Sep 2023 15:33:10 +0200 Subject: [PATCH 10/12] Optimized doc-blocks --- src/PdfParser/PdfParser.php | 4 ++-- src/PdfParser/Type/PdfArray.php | 2 +- src/PdfParser/Type/PdfHexString.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PdfParser/PdfParser.php b/src/PdfParser/PdfParser.php index 035919a..22a72e6 100644 --- a/src/PdfParser/PdfParser.php +++ b/src/PdfParser/PdfParser.php @@ -355,7 +355,7 @@ protected function parsePdfString() } /** - * @return bool|PdfHexString + * @return false|PdfHexString */ protected function parsePdfHexString() { @@ -380,7 +380,7 @@ protected function parsePdfName() } /** - * @return bool|PdfArray + * @return false|PdfArray * @throws PdfTypeException */ protected function parsePdfArray() diff --git a/src/PdfParser/Type/PdfArray.php b/src/PdfParser/Type/PdfArray.php index 33c6bc4..c7981b6 100644 --- a/src/PdfParser/Type/PdfArray.php +++ b/src/PdfParser/Type/PdfArray.php @@ -25,7 +25,7 @@ class PdfArray extends PdfType * * @param Tokenizer $tokenizer * @param PdfParser $parser - * @return bool|self + * @return false|self * @throws PdfTypeException */ public static function parse(Tokenizer $tokenizer, PdfParser $parser) diff --git a/src/PdfParser/Type/PdfHexString.php b/src/PdfParser/Type/PdfHexString.php index 86694b0..cd9d2b6 100644 --- a/src/PdfParser/Type/PdfHexString.php +++ b/src/PdfParser/Type/PdfHexString.php @@ -21,7 +21,7 @@ class PdfHexString extends PdfType * Parses a hexadecimal string object from the stream reader. * * @param StreamReader $streamReader - * @return bool|self + * @return false|self */ public static function parse(StreamReader $streamReader) { From 41e62d5b9a43d8c34565040a0c5a65b9758b77ba Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Wed, 27 Sep 2023 11:01:35 +0200 Subject: [PATCH 11/12] Code style --- src/PdfParser/Type/PdfString.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/PdfParser/Type/PdfString.php b/src/PdfParser/Type/PdfString.php index f1598d1..dc4ce33 100644 --- a/src/PdfParser/Type/PdfString.php +++ b/src/PdfParser/Type/PdfString.php @@ -87,18 +87,18 @@ public static function ensure($string) public static function escape($s) { // Still a bit faster, than direct replacing - if (strpos($s, '\\') !== false || - strpos($s, ')') !== false || - strpos($s, '(') !== false || - strpos($s, "\x0D") !== false || - strpos($s, "\x0A") !== false || - strpos($s, "\x09") !== false || - strpos($s, "\x08") !== false || - strpos($s, "\x0C") !== false - ) - { + if ( + \strpos($s, '\\') !== false || + \strpos($s, ')') !== false || + \strpos($s, '(') !== false || + \strpos($s, "\x0D") !== false || + \strpos($s, "\x0A") !== false || + \strpos($s, "\x09") !== false || + \strpos($s, "\x08") !== false || + \strpos($s, "\x0C") !== false + ) { // is faster than strtr(...) - return str_replace( + return \str_replace( ['\\', ')', '(', "\x0D", "\x0A", "\x09", "\x08", "\x0C"], ['\\\\', '\\)', '\\(', '\r', '\n', '\t', '\b', '\f'], $s From 4a4ca8d2899c4b7fa3092ad9999642cebc5b653e Mon Sep 17 00:00:00 2001 From: Jan Slabon Date: Wed, 27 Sep 2023 14:32:48 +0200 Subject: [PATCH 12/12] Typo --- src/PdfParser/Type/PdfStream.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PdfParser/Type/PdfStream.php b/src/PdfParser/Type/PdfStream.php index 68d901f..cfa2cdb 100644 --- a/src/PdfParser/Type/PdfStream.php +++ b/src/PdfParser/Type/PdfStream.php @@ -213,7 +213,7 @@ protected function extractStream() } /** - * Get all filters defined for that stream. + * Get all filters defined for this stream. * * @return PdfType[] * @throws PdfTypeException