From f3e5dd959245d3e7a6c486fa5984e14af42175d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 19 Aug 2020 12:46:05 +0300 Subject: [PATCH 01/10] Add default 0 for empty count in ContentDisposition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- src/Header/ContentDisposition.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Header/ContentDisposition.php b/src/Header/ContentDisposition.php index 5594afb8..5066ddeb 100644 --- a/src/Header/ContentDisposition.php +++ b/src/Header/ContentDisposition.php @@ -68,6 +68,22 @@ public static function fromString($headerLine) if (strpos($name, '*')) { list($name, $count) = explode('*', $name); + // allow optional count: + // Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67 + if ($count === "") { + $count = 0; + } + + if (! is_numeric($count)) { + $type = gettype($count); + $value = var_export($count, 1); + throw new Exception\InvalidArgumentException(sprintf( + "Invalid header line for Content-Disposition string". + " - count expected to be numeric, got %s with value %s", + $type, + $value + )); + } if (! isset($continuedValues[$name])) { $continuedValues[$name] = []; } @@ -82,7 +98,8 @@ public static function fromString($headerLine) for ($i = 0; $i < count($values); $i++) { if (! isset($values[$i])) { throw new Exception\InvalidArgumentException( - 'Invalid header line for Content-Disposition string - incomplete continuation' + 'Invalid header line for Content-Disposition string - incomplete continuation'. + '; HeaderLine: '.$headerLine ); } $value .= $values[$i]; From d4042fef879a6107e52a4a28b9a099f99a4f5401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 19 Aug 2020 12:48:22 +0300 Subject: [PATCH 02/10] Add test for Header Parameter Value Continuation parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index e62f2774..aa7b9607 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -129,6 +129,20 @@ public function testFromStringHandlesContinuations() $this->assertEquals(['level' => '1'], $header->getParameters()); } + /** + * Should not throw if the optional count is missing + * + * @see https://tools.ietf.org/html/rfc2231 + */ + public function testParameterValueOptionalContinuationsRFC2231(): void + { + $input = "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"; + $header = ContentDisposition::fromString($input); + + $this->assertEquals('attachment', $header->getDisposition()); + $this->assertEquals(['filename' => "UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"], $header->getParameters()); + } + /** * @dataProvider invalidParametersProvider */ From bec78644ac6a9690b2d79e41e43cf92ecc14c4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 19 Aug 2020 12:49:40 +0300 Subject: [PATCH 03/10] Add test for ContentType parameter wrapping from rfc2231 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index aa7b9607..1bc477c2 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -136,11 +136,16 @@ public function testFromStringHandlesContinuations() */ public function testParameterValueOptionalContinuationsRFC2231(): void { - $input = "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"; - $header = ContentDisposition::fromString($input); + $input1 = "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"; + $header = ContentDisposition::fromString($input1); $this->assertEquals('attachment', $header->getDisposition()); $this->assertEquals(['filename' => "UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"], $header->getParameters()); + + $input2 = "Content-Type: application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"; + $header = ContentType::fromString($input2); + + $this->assertEquals(['title*' => "us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"], $header->getParameters()); } /** From fb265437e95adb3b5a6070e007d966c89277b327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 19 Aug 2020 13:02:50 +0300 Subject: [PATCH 04/10] Split tests to appropriate test classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 24 ++++++++++++++---------- test/Header/ContentTypeTest.php | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index 1bc477c2..6d648c5e 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -133,19 +133,14 @@ public function testFromStringHandlesContinuations() * Should not throw if the optional count is missing * * @see https://tools.ietf.org/html/rfc2231 + * @dataProvider parameterWrappingProvider */ - public function testParameterValueOptionalContinuationsRFC2231(): void + public function testParameterWrapping(string $input, string $disposition, array $parameters): void { - $input1 = "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"; - $header = ContentDisposition::fromString($input1); + $header = ContentDisposition::fromString($input); - $this->assertEquals('attachment', $header->getDisposition()); - $this->assertEquals(['filename' => "UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"], $header->getParameters()); - - $input2 = "Content-Type: application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"; - $header = ContentType::fromString($input2); - - $this->assertEquals(['title*' => "us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"], $header->getParameters()); + $this->assertEquals($disposition, $header->getDisposition()); + $this->assertEquals($parameters, $header->getParameters()); } /** @@ -265,4 +260,13 @@ public function getParameterProvider() ]; // @codingStandardsIgnoreEnd } + + public function parameterWrappingProvider(): iterable + { + yield 'Without sequence number' => [ + "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67", + 'attachment', + ['filename' => "UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"] + ]; + } } diff --git a/test/Header/ContentTypeTest.php b/test/Header/ContentTypeTest.php index 4d3f9b3a..32698040 100644 --- a/test/Header/ContentTypeTest.php +++ b/test/Header/ContentTypeTest.php @@ -123,6 +123,19 @@ public function testFromStringHandlesContinuations() $this->assertEquals(['level' => '1'], $header->getParameters()); } + /** + * Should not throw if the optional count is missing + * + * @see https://tools.ietf.org/html/rfc2231 + * @dataProvider parameterWrappingProvider + */ + public function testParameterWrapping(string $input, array $parameters): void + { + $header = ContentType::fromString($input); + + $this->assertEquals($parameters, $header->getParameters()); + } + /** * @dataProvider invalidParametersProvider */ @@ -245,4 +258,12 @@ public function testRemoveParameterNotExists() $header = ContentType::fromString('content-type: text/plain'); $this->assertFalse($header->removeParameter('level')); } + + public function parameterWrappingProvider(): iterable + { + yield 'Example from RFC2231' => [ + "Content-Type: application/x-stuff; title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A", + ['title*' => "us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A"] + ]; + } } From ccad5c2f77d99c3f3432d03fb276f039bedbf9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 19 Aug 2020 13:06:37 +0300 Subject: [PATCH 05/10] Add test for two segments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index 6d648c5e..7db39694 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -268,5 +268,12 @@ public function parameterWrappingProvider(): iterable 'attachment', ['filename' => "UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67"] ]; + yield 'With two ordered items' => [ + "Content-Disposition: attachment;" . + "filename*0*=UTF-8''%76%C3%A4%6C%6A%61%70%C3%A4%C3%A4%73%75%2D%65%69%2D%6F;" . + "filename*1*=%6C%65%2E%6A%70%67", + 'attachment', + ['filename' => "UTF-8''%76%C3%A4%6C%6A%61%70%C3%A4%C3%A4%73%75%2D%65%69%2D%6F%6C%65%2E%6A%70%67"] + ]; } } From ee6b68758768fd805a7f3d217ffede4558bb7109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 20 Aug 2020 10:48:04 +0300 Subject: [PATCH 06/10] Add testParameterWrappingExceptions test to increase coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index 7db39694..a561d894 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -143,6 +143,16 @@ public function testParameterWrapping(string $input, string $disposition, array $this->assertEquals($parameters, $header->getParameters()); } + /** + * @dataProvider parameterWrappingProviderExceptions + */ + public function testParameterWrappingExceptions(string $input, string $exception, string $message): void + { + $this->expectException($exception); + $this->expectExceptionMessage($message); + ContentDisposition::fromString($input); + } + /** * @dataProvider invalidParametersProvider */ @@ -276,4 +286,17 @@ public function parameterWrappingProvider(): iterable ['filename' => "UTF-8''%76%C3%A4%6C%6A%61%70%C3%A4%C3%A4%73%75%2D%65%69%2D%6F%6C%65%2E%6A%70%67"] ]; } + + public function parameterWrappingProviderExceptions(): iterable + { + // @codingStandardsIgnoreStart + yield 'With non-numeric-sequence' => [ + "Content-Disposition: attachment;" . + "filename*0*=UTF-8''%76%C3%A4%6C%6A%61%70%C3%A4%C3%A4%73%75%2D%65%69%2D%6F;" . + "filename*a*=%6C%65%2E%6A%70%67", + InvalidArgumentException::class, + "Invalid header line for Content-Disposition string - count expected to be numeric, got string with value 'a'" + ]; + // @codingStandardsIgnoreEnd + } } From 44988d041c65876d68c56dc62294a096f19b98a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Fri, 18 Sep 2020 10:17:11 +0300 Subject: [PATCH 07/10] Add another unit test from different PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chunk from PR#111 by Cédric Anne Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index a561d894..5a0b9417 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -285,6 +285,11 @@ public function parameterWrappingProvider(): iterable 'attachment', ['filename' => "UTF-8''%76%C3%A4%6C%6A%61%70%C3%A4%C3%A4%73%75%2D%65%69%2D%6F%6C%65%2E%6A%70%67"] ]; + yield 'With two ordered items' => [ + "Content-Disposition: attachment; filename*=utf-8''Capture%20d%E2%80%99e%CC%81cran%202020%2D05%2D13%20a%CC%80%2017.13.47.png", + 'attachment', + ['filename' => "utf-8''Capture%20d%E2%80%99e%CC%81cran%202020%2D05%2D13%20a%CC%80%2017.13.47.png"] + ]; } public function parameterWrappingProviderExceptions(): iterable From cafc1ac22f6576c42efce459d4fbcf1f3f37d636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 5 Oct 2020 00:11:36 +0300 Subject: [PATCH 08/10] Add @codingStandardsIgnoreStart to long tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Elan Ruusamäe --- test/Header/ContentDispositionTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Header/ContentDispositionTest.php b/test/Header/ContentDispositionTest.php index 5a0b9417..e87756ca 100644 --- a/test/Header/ContentDispositionTest.php +++ b/test/Header/ContentDispositionTest.php @@ -273,6 +273,7 @@ public function getParameterProvider() public function parameterWrappingProvider(): iterable { + // @codingStandardsIgnoreStart yield 'Without sequence number' => [ "Content-Disposition: attachment; filename*=UTF-8''%64%61%61%6D%69%2D%6D%C3%B5%72%76%2E%6A%70%67", 'attachment', @@ -290,6 +291,7 @@ public function parameterWrappingProvider(): iterable 'attachment', ['filename' => "utf-8''Capture%20d%E2%80%99e%CC%81cran%202020%2D05%2D13%20a%CC%80%2017.13.47.png"] ]; + // @codingStandardsIgnoreEnd } public function parameterWrappingProviderExceptions(): iterable From 1e2b5c00d5f34fc98e4c4b82916c6b0564548a5f Mon Sep 17 00:00:00 2001 From: Laminas Bot Date: Thu, 31 Dec 2020 11:20:27 +0000 Subject: [PATCH 09/10] Bumps changelog version to 2.12.5 Updates the CHANGELOG.md file to add a changelog entry for a new 2.12.5 version. --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0107e4d5..d9a0bd22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. +## 2.12.5 - TBD + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + ## 2.12.3 - TBD ### Added From ed5b36a0deef4ffafe6138c2ae9cafcffafab856 Mon Sep 17 00:00:00 2001 From: Laminas Bot Date: Thu, 31 Dec 2020 11:41:57 +0000 Subject: [PATCH 10/10] 2.12.5 readiness Updates the CHANGELOG.md to set the release date. --- CHANGELOG.md | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a0bd22..78f6911e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,27 +2,24 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 2.12.5 - TBD +## 2.12.5 - 2020-12-31 -### Added - -- Nothing. -### Changed - -- Nothing. +----- -### Deprecated +### Release Notes for [2.12.5](https://github.com/laminas/laminas-mail/milestone/9) -- Nothing. +2.12.x bugfix release (patch) -### Removed +### 2.12.5 -- Nothing. +- Total issues resolved: **0** +- Total pull requests resolved: **1** +- Total contributors: **1** -### Fixed +#### Bug -- Nothing. + - [108: Fix Invalid header line for Content-Disposition string - incomplete continuation](https://github.com/laminas/laminas-mail/pull/108) thanks to @glensc ## 2.12.3 - TBD