diff --git a/Listener/VirusScannerListener.php b/Listener/VirusScannerListener.php index 7c784c82e1c76948c35f079b08633872d3f29548..c79d637ba718ee6984a04610c50b71348590581f 100644 --- a/Listener/VirusScannerListener.php +++ b/Listener/VirusScannerListener.php @@ -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; + } } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 9b92167d908869c1bc0ca81de2fc62f96f2b65c4..4cc0d7fbcad73fa0aed1959ff215776e2109248c 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -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: diff --git a/Tests/Listener/VirusScannerListenerTest.php b/Tests/Listener/VirusScannerListenerTest.php index 582da7f5ccf45c61513949d4cfd68297b60484fe..ef71021d02c9d064b83ec68303ba92a86207f7da 100644 --- a/Tests/Listener/VirusScannerListenerTest.php +++ b/Tests/Listener/VirusScannerListenerTest.php @@ -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); } } diff --git a/composer.json b/composer.json index 6fa2391ee28252b4a1e44826062bc487845f38d2..141f5fb835e52a64a1f59a2f0a51048f4606ee17 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ "ramsey/uuid": "~2.8", "blueimp/jquery-file-upload": "~9.9", "white-october/pagerfanta-bundle": "~1.0", - "willdurand/js-translation-bundle": "~2.2" + "willdurand/js-translation-bundle": "~2.2", + "xenolope/quahog": "^2.1" }, "require-dev": { "phpunit/phpunit": "^4.8"