Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@
"require": {
"php": ">=5.6",
"ext-json": "*",
"php-http/discovery": "^1.6.1",
"psr/http-client-implementation": "*",
"symfony/console": "^3.4|^4|^5|^6",
"symfony/finder": "^3|^4|^5|^6",
"symfony/process": "^3.4|^4|^5|^6",
"symfony/yaml": "^3.4|^4|^5|^6",
"guzzlehttp/guzzle": "^6.3|^7.0"
"symfony/yaml": "^3.4|^4|^5|^6"
},
"require-dev": {
"ext-zip" : "*",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^2.18|^3.0",
"php-http/client-common": "^2.5",
"php-http/socket-client": "^2.1",
"phpunit/phpunit": "^5.5|^6|^7|^8|^9"
},
"bin": ["security-checker"],
Expand Down
42 changes: 25 additions & 17 deletions src/AdvisoryFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@

namespace Enlightn\SecurityChecker;

use GuzzleHttp\Client;
use Http\Client\HttpClient;
use Http\Discovery\Psr17FactoryDiscovery;
use Psr\Http\Message\ResponseInterface;
use Http\Discovery\HttpClientDiscovery;

class AdvisoryFetcher
{
/**
* @var \GuzzleHttp\Client
* @var \Http\Client\HttpClient
*/
private $client;

/**
* @var \Psr\Http\Message\RequestFactoryInterface
*/
private $requestFactory;

/**
* @var string
*/
Expand All @@ -25,15 +32,14 @@ class AdvisoryFetcher

const EXTRACT_PATH = 'php_security_advisories';


public function __construct($tempDir = null)
{
$this->client = new Client();
$this->client = HttpClientDiscovery::find();
$this->requestFactory = Psr17FactoryDiscovery::findRequestFactory();
$this->tempDir = is_null($tempDir) ? sys_get_temp_dir() : $tempDir;
}

/**
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function fetchAdvisories()
{
$archivePath = $this->fetchAdvisoriesArchive();
Expand All @@ -48,28 +54,22 @@ public function fetchAdvisories()

/**
* @return string
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function fetchAdvisoriesArchive()
{
$headers = [];
$request = $this->requestFactory->createRequest('GET', self::ADVISORIES_URL);
$cacheResult = [];

if (! empty($cache = $this->getCacheFile())) {
$cacheResult = json_decode($cache, true);

if (is_file($cacheResult['ArchivePath'])) {
// Set cache headers only if both the cache file and archive file exist.
$headers = [
'If-None-Match' => $cacheResult['Key'],
'If-Modified-Since' => $cacheResult['Date'],
];
$request = $request->withHeader('If-None-Match', $cacheResult['Key']);
$request = $request->withHeader('If-Modified-Since', $cacheResult['Date']);
}
}

$response = $this->client->get(self::ADVISORIES_URL, [
'headers' => $headers,
]);
$response = $this->client->sendRequest($request);

if ($response->getStatusCode() !== 304) {
$this->writeCacheFile($response);
Expand Down Expand Up @@ -119,7 +119,7 @@ public function getExtractDirectoryPath()
return $this->tempDir.DIRECTORY_SEPARATOR.self::EXTRACT_PATH;
}

public function setClient(Client $client)
public function setClient(HttpClient $client)
{
$this->client = $client;
}
Expand All @@ -134,4 +134,12 @@ protected function writeCacheFile(ResponseInterface $response)

file_put_contents($this->getCacheFilePath(), json_encode($cache), LOCK_EX);
}

/**
* @return HttpClient
*/
public function getClient()
{
return $this->client;
}
}
1 change: 0 additions & 1 deletion src/SecurityChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public function __construct($tempDir = null)
* @param false $excludeDev
* @param array $allowList
* @return array
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function check($composerLockPath, $excludeDev = false, $allowList = [])
{
Expand Down
34 changes: 15 additions & 19 deletions tests/AdvisoryFetcherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

use Enlightn\SecurityChecker\AdvisoryFetcher;
use Enlightn\SecurityChecker\Filesystem;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Enlightn\SecurityChecker\Tests\Journal\SimpleArray;
use Http\Client\Common\Plugin\HistoryPlugin;
use Http\Client\Common\PluginClient;
use PHPUnit\Framework\TestCase;

class AdvisoryFetcherTest extends TestCase
Expand All @@ -17,10 +17,14 @@ class AdvisoryFetcherTest extends TestCase
public function fetches_archives_with_and_without_cache()
{
$fetcher = new AdvisoryFetcher;
$container = [];
$fetcher->setClient(new Client([
'handler' => $this->setupHistoryMiddleware($container),
]));
$journal = new SimpleArray;

$pluginClient = new PluginClient(
$fetcher->getClient(),
[new HistoryPlugin($journal)]
);

$fetcher->setClient($pluginClient);

// Test for non-cached version.
$this->cleanCacheFiles($fetcher);
Expand All @@ -30,8 +34,8 @@ public function fetches_archives_with_and_without_cache()
$this->assertTrue(is_dir($fetcher->getExtractDirectoryPath()));
$this->assertTrue(is_file($fetcher->getCacheFilePath()));
$this->assertTrue(is_file($fetcher->getExtractDirectoryPath().DIRECTORY_SEPARATOR.$this->getSampleFileToValidate()));
$this->assertCount(1, $container);
$this->assertSame(200, $container[0]['response']->getStatusCode());
$this->assertCount(1, $journal->successes);
$this->assertSame(200, $journal->successes[0][1]->getStatusCode());

// Test for cached version.
$this->cleanExtractDirectory($fetcher);
Expand All @@ -40,8 +44,8 @@ public function fetches_archives_with_and_without_cache()
$this->assertTrue(is_dir($fetcher->getExtractDirectoryPath()));
$this->assertTrue(is_file($fetcher->getCacheFilePath()));
$this->assertTrue(is_file($fetcher->getExtractDirectoryPath().DIRECTORY_SEPARATOR.$this->getSampleFileToValidate()));
$this->assertCount(2, $container);
$this->assertSame(304, $container[1]['response']->getStatusCode());
$this->assertCount(2, $journal->successes);
$this->assertSame(304, $journal->successes[1][1]->getStatusCode());;

$this->cleanCacheFiles($fetcher);
}
Expand All @@ -58,14 +62,6 @@ protected function cleanCacheFiles(AdvisoryFetcher $fetcher)
@unlink($fetcher->getArchiveFilePath());
}

protected function setupHistoryMiddleware(&$container)
{
$handlerStack = HandlerStack::create();
$handlerStack->push(Middleware::history($container));

return $handlerStack;
}

protected function getSampleFileToValidate()
{
return 'security-advisories-master'.DIRECTORY_SEPARATOR.'laravel'.DIRECTORY_SEPARATOR.'framework'
Expand Down
24 changes: 24 additions & 0 deletions tests/Journal/SimpleArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Enlightn\SecurityChecker\Tests\Journal;

use Http\Client\Common\Plugin\Journal;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class SimpleArray implements Journal
{
public $successes = [];
public $failures = [];

public function addSuccess(RequestInterface $request, ResponseInterface $response)
{
$this->successes[] = [$request, $response];
}

public function addFailure(RequestInterface $request, ClientExceptionInterface $exception)
{
$this->failures[] = [$request, $exception];
}
}