From 373412c0855692f677036d3d17ef50dfddf2d6ba Mon Sep 17 00:00:00 2001 From: Serhii Matrunchyk Date: Mon, 8 Apr 2019 01:18:15 +0300 Subject: [PATCH] Update form upstream --- .travis.yml | 6 +-- README.md | 28 +++++----- composer.json | 25 +++++---- src/ClamavValidator/ClamavValidator.php | 54 +++++++------------ .../ClamavValidatorException.php | 34 +----------- .../ClamavValidatorServiceProvider.php | 15 +++--- src/lang/en/validation.php | 0 tests/ValidatorClamavTest.php | 48 +++++++++++------ ...t.php => ValidatorServiceProviderTest.php} | 25 ++++----- 9 files changed, 104 insertions(+), 131 deletions(-) mode change 100644 => 100755 src/ClamavValidator/ClamavValidator.php mode change 100644 => 100755 src/ClamavValidator/ClamavValidatorException.php mode change 100644 => 100755 src/ClamavValidator/ClamavValidatorServiceProvider.php mode change 100644 => 100755 src/lang/en/validation.php mode change 100644 => 100755 tests/ValidatorClamavTest.php rename tests/{ValidateServiceProviderTest.php => ValidatorServiceProviderTest.php} (54%) mode change 100644 => 100755 diff --git a/.travis.yml b/.travis.yml index 35abd5f..4fe57d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: php php: - - 5.4 - - 5.5 - 5.6 + - 7.0 + - 7.1 before_install: - sudo apt-get update -qq @@ -16,6 +16,6 @@ before_script: - composer install --prefer-source --no-interaction --dev script: - - phpunit --colors --verbose --coverage-clover build/logs/clover.xml + - php vendor/bin/phpunit --colors --verbose --coverage-clover build/logs/clover.xml after_script: if [ $(phpenv version-name) = "5.6" ]; then php vendor/bin/ocular code-coverage:upload --format=php-clover build/logs/clover.xml; fi diff --git a/README.md b/README.md index dfe0d18..796cfd7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Custom Laravel 5 anti-virus validator for file uploads. * [Requirements](#requirements) * [Installation](#installation) * [Usage](#usage) -* [Change Log](#changelog) +* [Configuration](#configuration) * [Author](#author) @@ -41,11 +41,17 @@ This package is not tested on windows, but if you have ClamAV running (usually o ## Installation -Install the package through [Composer](http://getcomposer.org). +#### 1. Install the package through [Composer](http://getcomposer.org). + + ```bash + $ composer require sunspikes/clamav-validator + ``` -Run `composer require digitalideastudio/clamav-validator` +#### 2. Add the service provider (for Laravel 5.4 or below) -Add the following to your `providers` array in `config/app.php`: +This package supports Laravel new [Package Discovery](https://laravel.com/docs/5.5/packages#package-discovery). + +If you are using Laravel < 5.5, you need to add `Sunspikes\ClamavValidator\ClamavValidatorServiceProvider::class` to your `providers` array in `config/app.php`: ```php 'providers' => array( @@ -66,18 +72,12 @@ $rules = array( ); ``` - -## Change Log + +## Configuration -2014.12.05 - Initial version, using extension php-clamav +By default the package will try to connect the clamav daemon via the default socket file (/var/run/clamav/clamd.ctl) and if it fails it will try the tcp port (127.0.0.1:3310) -2014.12.05 - Removed the dependency php-clamav, Now using [Quahog](https://github.com/jonjomckay/quahog) - -2015.10.20 - Updated for Laravel 5 - -2015.11.20 - Updated to use PSR-4 - -2015.12.03 - Added limited windows support +But you can set the `CLAMAV_UNIX_SOCKET` (socket file path) or `CLAMAV_TCP_SOCKET` (host:port) environment variables to override this. ## Author diff --git a/composer.json b/composer.json index 54bcff8..6d1e2d8 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "digitalideastudio/clamav-validator", + "name": "sunspikes/clamav-validator", "description": "Custom Laravel 5 anti-virus validator for file uploads.", "keywords": [ "laravel", @@ -7,7 +7,7 @@ "clamav", "virus" ], - "homepage": "https://github.com/digitalideastudio/clamav-validator", + "homepage": "https://github.com/sunspikes/clamav-validator", "license": "MIT", "authors": [ { @@ -16,15 +16,14 @@ } ], "require": { - "php": ">=5.4.0", + "php": ">=5.5.0", "xenolope/quahog": "2.*", "illuminate/support": ">=4.2", - "laravel/framework": ">=4.2", "illuminate/validation": ">=4.1.21" }, "require-dev": { "phpunit/phpunit": "4.*", - "mockery/mockery": "dev-master", + "mockery/mockery": "0.9.*", "scrutinizer/ocular": "dev-master" }, "autoload": { @@ -32,18 +31,18 @@ "Sunspikes\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "Sunspikes\\Tests\\ClamavValidator\\": "src/" - } - }, - "minimum-stability": "dev", - "prefer-stable": true, "extra": { "laravel": { "providers": [ "Sunspikes\\ClamavValidator\\ClamavValidatorServiceProvider" ] } - } + }, + "autoload-dev": { + "psr-4": { + "Sunspikes\\Tests\\ClamavValidator\\": "src/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/src/ClamavValidator/ClamavValidator.php b/src/ClamavValidator/ClamavValidator.php old mode 100644 new mode 100755 index 140d567..3061351 --- a/src/ClamavValidator/ClamavValidator.php +++ b/src/ClamavValidator/ClamavValidator.php @@ -1,11 +1,11 @@ getFilePath($value); - $clamavSocket = $this->getClamavSocket(); - try { - $socket = (new Factory())->createClient($clamavSocket); - } catch (\Exception $e) { - throw new ClamavValidatorException($e, $attribute, $this); - } + // Create a new socket instance + $socket = (new Factory())->createClient($clamavSocket); // Create a new instance of the Client - $quahog = new Client($socket, 30, PHP_NORMAL_READ); + $quahog = new Client($socket, self::CLAMAV_SOCKET_READ_TIMEOUT, PHP_NORMAL_READ); - // Ensure that clamav user is able to read the file - $oldPerms = fileperms($file); - chmod($file, 0666); - clearstatcache(true, $file); + // Check if the file is readable + if (! is_readable($file)) { + throw new ClamavValidatorException(sprintf('The file "%s" is not readable', $file)); + } // Scan the file - $result = $quahog->scanFile($file); - - // Restore permissions - chmod($file, $oldPerms); - clearstatcache(true, $file); - + $result = $quahog->scanResourceStream(fopen($file, 'rb')); if (self::CLAMAV_STATUS_ERROR === $result['status']) { throw new ClamavValidatorException($result['reason']); } // Check if scan result is not clean - if (self::CLAMAV_STATUS_OK != $result['status']) { - return false; - } - - return true; + return !(self::CLAMAV_STATUS_OK !== $result['status']); } /** @@ -90,11 +76,11 @@ public function validateClamav($attribute, $value, $parameters) */ protected function getClamavSocket() { - if (file_exists(self::CLAMAV_UNIX_SOCKET)) { - return 'unix://' . self::CLAMAV_UNIX_SOCKET; + if (file_exists(env('CLAMAV_UNIX_SOCKET', self::CLAMAV_UNIX_SOCKET))) { + return 'unix://' . env('CLAMAV_UNIX_SOCKET', self::CLAMAV_UNIX_SOCKET); } - return self::CLAMAV_LOCAL_TCP_SOCKET; + return env('CLAMAV_TCP_SOCKET', self::CLAMAV_LOCAL_TCP_SOCKET); } /** diff --git a/src/ClamavValidator/ClamavValidatorException.php b/src/ClamavValidator/ClamavValidatorException.php old mode 100644 new mode 100755 index 027f74c..7a86835 --- a/src/ClamavValidator/ClamavValidatorException.php +++ b/src/ClamavValidator/ClamavValidatorException.php @@ -1,37 +1,7 @@ exception = $exception; - $this->attribute = $attribute; - - parent::__construct($validator, $this->makeResponse()); - } - - public function makeResponse() - { - $message = $this->exception->getMessage(); - - if (substr_count($message, 'SOCKET_ECONNREFUSED')) { - $message = 'Unable to initiate antivirus check. Please try later.'; - } - - if (request()->expectsJson()) { - return response()->json([ - $this->attribute => $message - ], 422); - } - - return redirect()->back()->withInput( - request()->input() - ); - } } diff --git a/src/ClamavValidator/ClamavValidatorServiceProvider.php b/src/ClamavValidator/ClamavValidatorServiceProvider.php old mode 100644 new mode 100755 index ae2a30e..601c999 --- a/src/ClamavValidator/ClamavValidatorServiceProvider.php +++ b/src/ClamavValidator/ClamavValidatorServiceProvider.php @@ -17,9 +17,9 @@ class ClamavValidatorServiceProvider extends ServiceProvider * * @var bool */ - protected $rules = array( + protected $rules = [ 'clamav', - ); + ]; /** * Bootstrap the application events. @@ -31,12 +31,13 @@ public function boot() $this->loadTranslationsFrom(__DIR__ . '/../lang', 'clamav-validator'); $this->app['validator'] - ->resolver(function ($translator, $data, $rules, $messages) { + ->resolver(function ($translator, $data, $rules, $messages, $customAttributes = []) { return new ClamavValidator( $translator, $data, $rules, - $messages + $messages, + $customAttributes ); }); @@ -75,8 +76,8 @@ protected function extendValidator($rule) { $method = studly_case($rule); $translation = $this->app['translator']->get('clamav-validator::validation'); - $this->app['validator']->extend($rule, 'Sunspikes\ClamavValidator\ClamavValidator@validate' . $method, - isset($translation[$rule]) ? $translation[$rule] : array()); + $this->app['validator']->extend($rule, ClamavValidator::class .'@validate' . $method, + isset($translation[$rule]) ? $translation[$rule] : []); } @@ -97,6 +98,6 @@ public function register() */ public function provides() { - return array(); + return []; } } diff --git a/src/lang/en/validation.php b/src/lang/en/validation.php old mode 100644 new mode 100755 diff --git a/tests/ValidatorClamavTest.php b/tests/ValidatorClamavTest.php old mode 100644 new mode 100755 index fc6f6e8..2eb680c --- a/tests/ValidatorClamavTest.php +++ b/tests/ValidatorClamavTest.php @@ -3,6 +3,7 @@ namespace Sunspikes\Tests\ClamavValidator; use Mockery; +use Illuminate\Contracts\Translation\Translator; use Sunspikes\ClamavValidator\ClamavValidator; use Sunspikes\ClamavValidator\ClamavValidatorException; @@ -17,18 +18,18 @@ class ValidatorClamavTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->translator = Mockery::mock('\Symfony\Component\Translation\TranslatorInterface'); + $this->translator = Mockery::mock(Translator::class); $this->translator->shouldReceive('trans'); - $this->clean_data = array( - 'file' => dirname(__FILE__) . '/files/test1.txt' - ); - $this->virus_data = array( - 'file' => dirname(__FILE__) . '/files/test2.txt' - ); - $this->error_data = array( - 'file' => dirname(__FILE__) . '/files/test3.txt' - ); - $this->messages = array(); + $this->clean_data = [ + 'file' => $this->getTempPath(__DIR__ . '/files/test1.txt') + ]; + $this->virus_data = [ + 'file' => $this->getTempPath(__DIR__ . '/files/test2.txt') + ]; + $this->error_data = [ + 'file' => $this->getTempPath(__DIR__ . '/files/test3.txt') + ]; + $this->messages = []; } public function tearDown() @@ -42,7 +43,7 @@ public function testValidatesClean() $validator = new ClamavValidator( $this->translator, $this->clean_data, - array('file' => 'clamav'), + ['file' => 'clamav'], $this->messages ); @@ -54,7 +55,7 @@ public function testValidatesVirus() $validator = new ClamavValidator( $this->translator, $this->virus_data, - array('file' => 'clamav'), + ['file' => 'clamav'], $this->messages ); @@ -63,17 +64,32 @@ public function testValidatesVirus() public function testValidatesError() { + $this->setExpectedException(ClamavValidatorException::class, 'is not readable'); + $validator = new ClamavValidator( $this->translator, $this->error_data, - array('file' => 'clamav'), + ['file' => 'clamav'], $this->messages ); chmod($this->error_data['file'], 0000); - $this->setExpectedException('\Sunspikes\ClamavValidator\ClamavValidatorException', 'Access denied.'); - $validator->passes(); } + + /** + * Move to temp dir, so that clamav can access the file + * + * @param $file + * @return string + */ + private function getTempPath($file) + { + $tempPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . basename($file); + copy($file, $tempPath); + chmod($tempPath, 0644); + + return $tempPath; + } } \ No newline at end of file diff --git a/tests/ValidateServiceProviderTest.php b/tests/ValidatorServiceProviderTest.php old mode 100644 new mode 100755 similarity index 54% rename from tests/ValidateServiceProviderTest.php rename to tests/ValidatorServiceProviderTest.php index 58a462d..5ae8a15 --- a/tests/ValidateServiceProviderTest.php +++ b/tests/ValidatorServiceProviderTest.php @@ -2,41 +2,43 @@ namespace Sunspikes\Tests\ClamavValidator; +use Illuminate\Container\Container; +use Illuminate\Contracts\Translation\Translator; +use Illuminate\Validation\PresenceVerifierInterface; use Mockery; use Illuminate\Validation\Factory; use Illuminate\Support\Str; +use Sunspikes\ClamavValidator\ClamavValidator; +use Sunspikes\ClamavValidator\ClamavValidatorServiceProvider; -class ValidateServiceProviderTest extends \PHPUnit_Framework_TestCase +class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase { - public function testBoot() { - $translator = Mockery::mock('\Symfony\Component\Translation\TranslatorInterface'); + $translator = Mockery::mock(Translator::class); $translator->shouldReceive('get'); $translator->shouldReceive('addNamespace'); - $presence = Mockery::mock('\Illuminate\Validation\PresenceVerifierInterface'); + $presence = Mockery::mock(PresenceVerifierInterface::class); $factory = new Factory($translator); $factory->setPresenceVerifier($presence); - $container = Mockery::mock('\Illuminate\Container\Container'); + $container = Mockery::mock(Container::class); $container->shouldReceive('bind'); $container->shouldReceive('loadTranslationsFrom'); $container->shouldReceive('offsetGet')->with('translator')->andReturn($translator); $container->shouldReceive('offsetGet')->with('validator')->andReturn($factory); - $sp = Mockery::mock('\Sunspikes\ClamavValidator\ClamavValidatorServiceProvider[package]', array($container)); + $sp = Mockery::mock(ClamavValidatorServiceProvider::class .'[package]', [$container]); $sp->boot(); - $validator = $factory->make(array(), array()); - - foreach ($validator->getExtensions() as $rule => $class_and_method) { + $validator = $factory->make([], []); - $class_and_method = "\\" . $class_and_method; + foreach ($validator->extensions as $rule => $class_and_method) { $this->assertTrue(in_array($rule, $sp->getRules())); - $this->assertEquals('\Sunspikes\ClamavValidator\ClamavValidator@validate' . studly_case($rule), $class_and_method); + $this->assertEquals(ClamavValidator::class .'@validate' . studly_case($rule), $class_and_method); list($class, $method) = Str::parseCallback($class_and_method, null); @@ -48,5 +50,4 @@ public function tearDown() { Mockery::close(); } - }