Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge pull request #190 from michalbundyra/hotfix/content-security-po…
Browse files Browse the repository at this point in the history
…licy-multiple

Content-Security-Policy implements MultipleHeaderInterface
  • Loading branch information
michalbundyra committed Nov 29, 2019
2 parents 72faa33 + 67ddca8 commit 78d212d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/Header/ContentSecurityPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* @link http://www.w3.org/TR/CSP/
*/
class ContentSecurityPolicy implements HeaderInterface
class ContentSecurityPolicy implements MultipleHeaderInterface
{
/**
* Valid directive names
Expand Down Expand Up @@ -154,4 +154,20 @@ public function toString()
{
return sprintf('%s: %s', $this->getFieldName(), $this->getFieldValue());
}

public function toStringMultipleHeaders(array $headers)
{
$strings = [$this->toString()];
foreach ($headers as $header) {
if (! $header instanceof ContentSecurityPolicy) {
throw new Exception\RuntimeException(
'The ContentSecurityPolicy multiple header implementation can only'
. ' accept an array of ContentSecurityPolicy headers'
);
}
$strings[] = $header->toString();
}

return implode("\r\n", $strings) . "\r\n";
}
}
1 change: 1 addition & 0 deletions src/HeaderLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class HeaderLoader extends PluginClassLoader
'contentlocation' => Header\ContentLocation::class,
'contentmd5' => Header\ContentMD5::class,
'contentrange' => Header\ContentRange::class,
'contentsecuritypolicy' => Header\ContentSecurityPolicy::class,
'contenttransferencoding' => Header\ContentTransferEncoding::class,
'contenttype' => Header\ContentType::class,
'cookie' => Header\Cookie::class,
Expand Down
48 changes: 48 additions & 0 deletions test/Header/ContentSecurityPolicyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
namespace ZendTest\Http\Header;

use PHPUnit\Framework\TestCase;
use Zend\Http\Exception\RuntimeException;
use Zend\Http\Header\ContentSecurityPolicy;
use Zend\Http\Header\Exception\InvalidArgumentException;
use Zend\Http\Header\GenericHeader;
use Zend\Http\Header\HeaderInterface;
use Zend\Http\Header\MultipleHeaderInterface;
use Zend\Http\Headers;

class ContentSecurityPolicyTest extends TestCase
{
Expand All @@ -25,6 +29,7 @@ public function testContentSecurityPolicyFromStringParsesDirectivesCorrectly()
$csp = ContentSecurityPolicy::fromString(
"Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self';"
);
$this->assertInstanceOf(MultipleHeaderInterface::class, $csp);
$this->assertInstanceOf(HeaderInterface::class, $csp);
$this->assertInstanceOf(ContentSecurityPolicy::class, $csp);
$directives = [
Expand Down Expand Up @@ -139,4 +144,47 @@ public function testContentSecurityPolicySetDirectiveWithEmptyReportUriRemovesEx
$csp->toString()
);
}

public function testToStringMultipleHeaders()
{
$csp = new ContentSecurityPolicy();
$csp->setDirective('default-src', ["'self'"]);

$additional = new ContentSecurityPolicy();
$additional->setDirective('img-src', ['https://*.github.com']);

self::assertSame(
"Content-Security-Policy: default-src 'self';\r\n"
. "Content-Security-Policy: img-src https://*.github.com;\r\n",
$csp->toStringMultipleHeaders([$additional])
);
}

public function testToStringMultipleHeadersExceptionIfDifferent()
{
$csp = new ContentSecurityPolicy();
$csp->setDirective('default-src', ["'self'"]);

$additional = new GenericHeader();

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage(
'The ContentSecurityPolicy multiple header implementation'
. ' can only accept an array of ContentSecurityPolicy headers'
);
$csp->toStringMultipleHeaders([$additional]);
}

public function testMultiple()
{
$headers = new Headers();
$headers->addHeader((new ContentSecurityPolicy())->setDirective('default-src', ["'self'"]));
$headers->addHeader((new ContentSecurityPolicy())->setDirective('img-src', ['https://*.github.com']));

self::assertSame(
"Content-Security-Policy: default-src 'self';\r\n"
. "Content-Security-Policy: img-src https://*.github.com;\r\n",
$headers->toString()
);
}
}

0 comments on commit 78d212d

Please sign in to comment.