Commit e1c870c6 authored by Guillaume Perréal's avatar Guillaume Perréal
Browse files

Merge branch 'antivirus' into 'symfony3'

Add antivirus analyse (xenelop quahog)

See merge request !1
parents 79e1ffff c3ed8cbc
1 merge request!1Add antivirus analyse (xenelop quahog)
Showing with 96 additions and 53 deletions
+96 -53
......@@ -6,9 +6,10 @@
namespace Irstea\FileUploadBundle\Listener;
use CL\Tissue\Adapter\AdapterInterface;
use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent;
use Irstea\FileUploadBundle\Exception\RejectedFileException;
use Xenolope\Quahog\Client;
use Xenolope\Quahog\Exception\ConnectionException;
/**
* Description of AntivirusListener.
......@@ -16,42 +17,58 @@ use Irstea\FileUploadBundle\Exception\RejectedFileException;
class VirusScannerListener
{
/**
* @var AdapterInterface
* @var Client
*/
private $scanner;
private $client;
/**
* @param AdapterInterface $scanner
* @param Client $client
*/
public function __construct(AdapterInterface $scanner)
public function __construct(Client $client)
{
$this->scanner = $scanner;
$this->client = $client;
}
/**
* @param FileUploadCompleteEvent $event
*
* @throws ConnectionException
*/
public function onFileUploadCompleted(FileUploadCompleteEvent $event)
{
$client = $this->getClient();
$file = $event->getUploadedFile();
$path = $file->getLocalPath();
$result = $this->scanner->scan([$path]);
$result = $client->scanFile($path);
$hasVirus = $result['status'] === Client::RESULT_FOUND;
$meta = $file->getMetadata();
$meta['virus_scanner'] = ['has_virus' => $hasVirus];
$meta['virus_scanner'] = ['has_virus' => $result->hasVirus()];
if ($result->hasVirus()) {
if (null !== $desc = $result->getDetections()[0]->getDescription()) {
$meta['virus_scanner']['detected'] = $desc;
}
if ($hasVirus) {
$desc = $result['reason'];
$meta['virus_scanner']['detected'] = $result['reason'];
}
$file->setMetadata($meta);
if ($result->hasVirus()) {
if ($hasVirus) {
throw new RejectedFileException($file, $desc ? sprintf('Found the %s virus !', $desc) : 'Virus found !');
}
}
/**
* @throws ConnectionException
*
* @return Client
*/
private function getClient(): Client
{
// Check clamd server's state
$this->client->ping();
return $this->client;
}
}
......@@ -10,6 +10,10 @@ parameters:
irstea_file_upload.max_chunk_size: 0
irstea_file_upload.virus_scanner.clamav_socket_path: unix:///var/run/clamav/clamd.ctl
irstea_file_upload.virus_scanner.client_timeout: 30
irstea_file_upload.virus_scanner.client_mode: !php/const:PHP_NORMAL_READ
services:
# Le gestionnaire de fichiers
......@@ -70,12 +74,24 @@ services:
- "%irstea_file_upload.filesystem.name%"
# Scanner anti-virus
# irstea_file_upload.virus_scanner:
# class: Irstea\FileUploadBundle\Listener\VirusScannerListener
# arguments:
# - @cl_tissue.scanner
# tags:
# - { name: kernel.event_listener, event: file_upload.complete, method: onFileUploadCompleted }
irstea_file_upload.virus_scanner.socket:
class: Socket\Raw\Socket
arguments:
- "%irstea_file_upload.virus_scanner.clamav_socket_path"
irstea_file_upload.virus_scanner.client:
class: Xenolope\Quahog\Client
arguments:
- "@irstea_file_upload.virus_scanner.socket"
- "%irstea_file_upload.virus_scanner.client_timeout"
- "%irstea_file_upload.virus_scanner.client_mode"
irstea_file_upload.virus_scanner:
class: Irstea\FileUploadBundle\Listener\VirusScannerListener
arguments:
- "@irstea_file_upload.virus_scanner.client"
tags:
- { name: kernel.event_listener, event: file_upload.complete, method: onFileUploadCompleted }
# Extension Twig
irstea_file_upload.twig_extension:
......
......@@ -6,12 +6,13 @@
namespace Irstea\FileUploadBundle\Tests\Listener;
use CL\Tissue\Model\Detection;
use CL\Tissue\Model\ScanResult;
use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent;
use Irstea\FileUploadBundle\Listener\VirusScannerListener;
use Irstea\FileUploadBundle\Model\UploadedFileInterface;
use PHPUnit_Framework_MockObject_MockObject;
use PHPUnit_Framework_TestCase;
use Xenolope\Quahog\Client;
use Xenolope\Quahog\Exception\ConnectionException;
/**
* Generated by PHPUnit_SkeletonGenerator on 2015-01-29 at 14:43:16.
......@@ -26,7 +27,7 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
/**
* @var PHPUnit_Framework_MockObject_MockObject
*/
protected $scanner;
protected $client;
/**
* @var FileUploadCompleteEvent
......@@ -43,19 +44,27 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
*/
protected function setUp()
{
self::markTestSkipped('No CL\Tissue');
$this->client = $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock();
$this->file = $this->getMock(UploadedFileInterface::class);
$this->file->expects($this->any())->method('getLocalPath')->willReturn('foopath');
$this->file->expects($this->any())->method('getMetadata')->willReturn([]);
$this->event = new FileUploadCompleteEvent($this->file);
$this->listener = new VirusScannerListener($this->client);
}
public function testOnFileUploadCompletedResultOk()
{
$result = new ScanResult(
['foopath'],
['foopath'],
[]
);
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$result = [
'filename' => 'footpath',
'reason' => null,
'status' => Client::RESULT_OK,
];
$this->file->expects(static::once())->method('setMetadata')->with(['virus_scanner' => ['has_virus' => false]]);
$this->client->expects($this->once())->method('scanFile')->with('foopath')->willReturn($result);
$this->file->expects($this->once())->method('setMetadata')->with(['virus_scanner' => ['has_virus' => false]]);
$this->listener->onFileUploadCompleted($this->event);
}
......@@ -65,36 +74,36 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
*/
public function testOnFileUploadCompletedVirusFound()
{
$result = new ScanResult(
['foopath'],
['foopath'],
[new Detection('foopath', Detection::TYPE_VIRUS, 'BAR')]
);
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$result = [
'filename' => 'foopath',
'reason' => 'Terrible virus',
'status' => Client::RESULT_FOUND,
];
$this->file->expects(static::once())->method('setMetadata')->with(
['virus_scanner' => ['has_virus' => true, 'detected' => 'BAR']]
);
$this->client->expects($this->once())
->method('scanFile')
->with('foopath')
->willReturn($result);
$this->file->expects($this->once())
->method('setMetadata')
->with(['virus_scanner' => ['has_virus' => true, 'detected' => 'Terrible virus']]);
$this->listener->onFileUploadCompleted($this->event);
}
/**
* @expectedException \Irstea\FileUploadBundle\Exception\RejectedFileException
* @expectedException \Xenolope\Quahog\Exception\ConnectionException
*/
public function testOnFileUploadCompletedVirusFoundNoDescription()
public function testGetClientFailed()
{
$result = new ScanResult(
['foopath'],
['foopath'],
[new Detection('foopath', Detection::TYPE_VIRUS)]
);
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$this->file->expects(static::once())->method('setMetadata')->with(
['virus_scanner' => ['has_virus' => true]]
);
$this->client->expects($this->once())->method('ping')->willThrowException(new ConnectionException());
$this->listener->onFileUploadCompleted($this->event);
}
public function testGetClientSucceed()
{
$this->client->expects($this->once())->method('ping')->willReturn(true);
$this->listener->onFileUploadCompleted($this->event);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment