diff --git a/.travis.yml b/.travis.yml
index ed91078..7081cc5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,9 @@ php:
- "7.0"
- "7.1"
- "7.2"
+ - "7.3"
+ - "7.4"
+ - "nightly"
matrix:
fast_finish: true
diff --git a/composer.json b/composer.json
index 04503ec..2a6c43f 100644
--- a/composer.json
+++ b/composer.json
@@ -30,15 +30,18 @@
}
},
"require": {
- "php": "^7",
+ "php": "^7|^8",
"paragonie/constant_time_encoding": "^2"
},
"require-dev": {
"psr/http-message": "^1",
- "phpunit/phpunit": "4.*|5.*",
+ "phpunit/phpunit": "^7|^8|^9",
"squizlabs/php_codesniffer": "^3",
"vimeo/psalm": "^3"
},
+ "scripts": {
+ "test": "phpunit && psalm"
+ },
"suggest": {
"psr/http-message": "For CSPBuilder::injectCSPHeader()"
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 6060fcd..fc96fdf 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -10,16 +10,10 @@
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
- syntaxCheck="true"
>
./test
-
-
- ./src
-
-
\ No newline at end of file
diff --git a/src/CSPBuilder.php b/src/CSPBuilder.php
index db9f5fb..5647121 100644
--- a/src/CSPBuilder.php
+++ b/src/CSPBuilder.php
@@ -15,7 +15,7 @@ class CSPBuilder
const FORMAT_NGINX = 'nginx';
/**
- * @var array
+ * @var array
*/
private $policies = [];
@@ -142,6 +142,7 @@ public function compile(): string
*/
public function addSource(string $directive, string $path): self
{
+ $this->needsCompile = true;
switch ($directive) {
case 'child':
case 'frame':
@@ -212,6 +213,7 @@ public function addSource(string $directive, string $path): self
*/
public function addDirective(string $key, $value = null): self
{
+ $this->needsCompile = true;
if ($value === null) {
if (!isset($this->policies[$key])) {
$this->policies[$key] = true;
@@ -777,6 +779,8 @@ protected function compileSubgroup(string $directive, $policies = []): string
}
return $directive." 'none'; ";
}
+ /** @var array $policies */
+
$ret = $directive.' ';
if ($directive === 'plugin-types') {
// Expects MIME types, not URLs
@@ -787,9 +791,12 @@ protected function compileSubgroup(string $directive, $policies = []): string
}
if (!empty($policies['allow'])) {
- foreach ($policies['allow'] as $url) {
+ /** @var array $allowedPolicies */
+ $allowedPolicies = $policies['allow'];
+ foreach ($allowedPolicies as $url) {
+ /** @var string|bool $url */
$url = \filter_var($url, FILTER_SANITIZE_URL);
- if ($url !== false) {
+ if (\is_string($url)) {
if ($this->supportOldBrowsers && $directive !== 'sandbox') {
if (\strpos($url, '://') === false) {
if (($this->isHTTPSConnection() && $this->httpsTransformOnHttpsConnections)
@@ -812,7 +819,14 @@ protected function compileSubgroup(string $directive, $policies = []): string
}
if (!empty($policies['hashes'])) {
- foreach ($policies['hashes'] as $hash) {
+ /** @var array> $hashes */
+ $hashes = $policies['hashes'];
+ /** @var array $hash */
+ foreach ($hashes as $hash) {
+ /**
+ * @var string $algo
+ * @var string $hashval
+ */
foreach ($hash as $algo => $hashval) {
$ret .= \implode('', [
"'",
@@ -826,7 +840,10 @@ protected function compileSubgroup(string $directive, $policies = []): string
}
if (!empty($policies['nonces'])) {
- foreach ($policies['nonces'] as $nonce) {
+ /** @var array $nonces */
+ $nonces = $policies['nonces'];
+ /** @var string $nonce */
+ foreach ($nonces as $nonce) {
$ret .= \implode('', [
"'nonce-",
\preg_replace('/[^A-Za-z0-9\+\/=]/', '', $nonce),
@@ -836,8 +853,11 @@ protected function compileSubgroup(string $directive, $policies = []): string
}
if (!empty($policies['types'])) {
- foreach ($policies['types'] as $type) {
- $ret .= $type.' ';
+ /** @var array $types */
+ $types = $policies['types'];
+ /** @var string $type */
+ foreach ($types as $type) {
+ $ret .= $type . ' ';
}
}
diff --git a/test/BasicTest.php b/test/BasicTest.php
index 4f0a101..9e1e0fe 100644
--- a/test/BasicTest.php
+++ b/test/BasicTest.php
@@ -4,6 +4,7 @@
use ParagonIE\CSPBuilder\CSPBuilder;
use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* Class BasicTest
@@ -103,7 +104,7 @@ public function testPreHash()
*/
public function testSourceHttpsConversion()
{
- /** @var CSPBuilder|\PHPUnit_Framework_MockObject_MockObject $cspHttp */
+ /** @var CSPBuilder|MockObject $cspHttp */
$cspHttp = $this->getMockBuilder(CSPBuilder::class)->setMethods(['isHTTPSConnection'])
->disableOriginalConstructor()->getMock();
$cspHttp->method('isHTTPSConnection')->willReturn(false);
@@ -111,11 +112,12 @@ public function testSourceHttpsConversion()
$cspHttp->addSource('form', 'http://example.com');
$cspHttp->addSource('form', 'another.com');
$cspHttp->enableHttpsTransformOnHttpsConnections(); // enabled by default
+ /** @var string $compiledCspHttp */
$compiledCspHttp = $cspHttp->compile();
- $this->assertContains('http://example.com', $compiledCspHttp);
- $this->assertContains('http://another.com', $compiledCspHttp);
+ $this->assertStringContainsString('http://example.com', $compiledCspHttp);
+ $this->assertStringContainsString('http://another.com', $compiledCspHttp);
- /** @var CSPBuilder|\PHPUnit_Framework_MockObject_MockObject $cspHttps */
+ /** @var CSPBuilder|MockObject $cspHttps */
$cspHttps = $this->getMockBuilder(CSPBuilder::class)->setMethods(['isHTTPSConnection'])
->disableOriginalConstructor()->getMock();
$cspHttps->method('isHTTPSConnection')->willReturn(true);
@@ -123,16 +125,17 @@ public function testSourceHttpsConversion()
$cspHttps->addSource('form', 'http://example.com');
$cspHttps->addSource('form', 'another.com');
+ /** @var string $compiledCspHttpsWithConvertEnabled */
$compiledCspHttpsWithConvertEnabled = $cspHttps->compile();
- $this->assertContains('https://example.com', $compiledCspHttpsWithConvertEnabled);
- $this->assertContains('https://another.com', $compiledCspHttpsWithConvertEnabled);
- $this->assertNotContains('http://example.com', $compiledCspHttpsWithConvertEnabled);
- $this->assertNotContains('http://another.com', $compiledCspHttpsWithConvertEnabled);
+ $this->assertStringContainsString('https://example.com', $compiledCspHttpsWithConvertEnabled);
+ $this->assertStringContainsString('https://another.com', $compiledCspHttpsWithConvertEnabled);
+ $this->assertStringNotContainsString('http://example.com', $compiledCspHttpsWithConvertEnabled);
+ $this->assertStringNotContainsString('http://another.com', $compiledCspHttpsWithConvertEnabled);
$cspHttps->disableHttpsTransformOnHttpsConnections();
$compiledCspHttpsWithConvertDisabled = $cspHttps->compile();
- $this->assertContains('http://example.com', $compiledCspHttpsWithConvertDisabled);
- $this->assertContains('http://another.com', $compiledCspHttpsWithConvertDisabled);
+ $this->assertStringContainsString('http://example.com', $compiledCspHttpsWithConvertDisabled);
+ $this->assertStringContainsString('http://another.com', $compiledCspHttpsWithConvertDisabled);
}
/**
@@ -145,8 +148,8 @@ public function testUpgradeInsecureBeatsDisableHttpsConversionFlag()
$csp->disableHttpsTransformOnHttpsConnections();
$csp->addDirective('upgrade-insecure-requests');
$compiled = $csp->compile();
- $this->assertContains('https://example.com', $compiled);
- $this->assertNotContains('http://example.com', $compiled);
+ $this->assertStringContainsString('https://example.com', $compiled);
+ $this->assertStringNotContainsString('http://example.com', $compiled);
}
/**
@@ -159,7 +162,7 @@ public function testAllowDataUris()
$csp->setDataAllowed('img-src', true);
$compiled = $csp->compile();
- $this->assertContains("data:", $compiled);
+ $this->assertStringContainsString("data:", $compiled);
}
/**
* @covers CSPBuilder::setSelfAllowed()
@@ -188,7 +191,7 @@ public function testAllowSelfUris()
$csp->setSelfAllowed('img-src', true);
$compiled = $csp->compile();
- $this->assertContains("'self'", $compiled);
+ $this->assertStringContainsString("'self'", $compiled);
}
/**
@@ -201,7 +204,7 @@ public function testAllowUnsafeEval()
$csp->setAllowUnsafeEval('script-src', true);
$compiled = $csp->compile();
- $this->assertContains("'unsafe-eval'", $compiled);
+ $this->assertStringContainsString("'unsafe-eval'", $compiled);
}
/**
@@ -214,7 +217,7 @@ public function testAllowUnsafeInline()
$csp->setAllowUnsafeInline('script-src', true);
$compiled = $csp->compile();
- $this->assertContains("'unsafe-inline'", $compiled);
+ $this->assertStringContainsString("'unsafe-inline'", $compiled);
}
/**
@@ -251,13 +254,13 @@ public function testRemovingDirectives()
$csp->addSource('style-src', 'https://example.com');
$compiled = $csp->compile();
- $this->assertContains('frame-ancestors https://example.com', $compiled);
- $this->assertContains('style-src https://example.com', $compiled);
+ $this->assertStringContainsString('frame-ancestors https://example.com', $compiled);
+ $this->assertStringContainsString('style-src https://example.com', $compiled);
$csp->removeDirective('style-src');
$compiled = $csp->compile();
- $this->assertContains('frame-ancestors https://example.com', $compiled);
- $this->assertNotContains('style-src https://example.com', $compiled);
+ $this->assertStringContainsString('frame-ancestors https://example.com', $compiled);
+ $this->assertStringNotContainsString('style-src https://example.com', $compiled);
}
}