Completed
Push — master ( 6af6e1...6069eb )
by Krishnaprasad
04:34
created

ClamavValidator   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Test Coverage

Coverage 82.14%

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 6
dl 0
loc 110
ccs 23
cts 28
cp 0.8214
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getFilePath() 0 15 4
A validateClamav() 0 26 3
A getClamavSocket() 0 13 3
1
<?php namespace Sunspikes\ClamavValidator;
2
3
use Illuminate\Contracts\Translation\Translator;
4
use Illuminate\Support\Facades\Config;
5
use Illuminate\Validation\Validator;
6
use Xenolope\Quahog\Client;
7
use Socket\Raw\Factory;
8
use Symfony\Component\HttpFoundation\File\UploadedFile;
9
10
class ClamavValidator extends Validator
11
{
12
    /**
13
     * @const string CLAMAV_STATUS_OK
14
     */
15
    const CLAMAV_STATUS_OK = 'OK';
16
17
    /**
18
     * @const string CLAMAV_STATUS_ERROR
19
     */
20
    const CLAMAV_STATUS_ERROR = 'ERROR';
21
22
    /**
23
     * Creates a new instance of ClamavValidator]
24
     *
25
     * ClamavValidator constructor.
26
     * @param Translator $translator
27
     * @param array      $data
28
     * @param array      $rules
29
     * @param array      $messages
30
     * @param array      $customAttributes
31
     */
32 4
    public function __construct(
33
        Translator $translator,
34
        array $data,
35
        array $rules,
36
        array $messages = [],
37
        array $customAttributes = []
38
    ) {
39 4
        parent::__construct($translator, $data, $rules, $messages, $customAttributes);
40 4
    }
41
42
    /**
43
     * Validate the uploaded file for virus/malware with ClamAV
44
     *
45
     * @param  $attribute   string
46
     * @param  $value       mixed
47
     * @param  $parameters  array
48
     *
49
     * @return boolean
50
     * @throws ClamavValidatorException
51
     */
52 3
    public function validateClamav($attribute, $value, $parameters)
0 ignored issues
show
Unused Code introduced by
The parameter $attribute is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $parameters is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
53
    {
54 3
        $file = $this->getFilePath($value);
55 3
        $clamavSocket = $this->getClamavSocket();
56
57
        // Create a new socket instance
58 3
        $socket = (new Factory())->createClient($clamavSocket);
59
60
        // Create a new instance of the Client
61 3
        $quahog = new Client($socket, Config::get('clamav.socket_read_timeout'), PHP_NORMAL_READ);
62
63
        // Check if the file is readable
64 3
        if (! is_readable($file)) {
65 1
            throw new ClamavValidatorException(sprintf('The file "%s" is not readable', $file));
66
        }
67
68
        // Scan the file
69 2
        $result = $quahog->scanResourceStream(fopen($file, 'rb'));
70
71 2
        if (Client::RESULT_ERROR === $result['status']) {
72
            throw new ClamavValidatorException($result['reason']);
73
        }
74
75
        // Check if scan result is not clean
76 2
        return Client::RESULT_OK === $result['status'];
77
    }
78
79
    /**
80
     * Guess the ClamAV socket
81
     *
82
     * @return string
83
     */
84 3
    protected function getClamavSocket()
85
    {
86 3
        $preferredSocket = Config::get('clamav.preferred_socket');
87
88 3
        if ($preferredSocket === 'unix_socket') {
89 3
            $unixSocket = Config::get('clamav.unix_socket');
90 3
            if (file_exists($unixSocket)) {
91 3
                return 'unix://' . $unixSocket;
92
            }
93
        }
94
        // We use the tcp_socket as fallback as well
95
        return Config::get('clamav.tcp_socket');
96
    }
97
98
    /**
99
     * Return the file path from the passed object
100
     *
101
     * @param $file mixed
102
     * @return string
103
     */
104 3
    protected function getFilePath($file)
105
    {
106
        // if were passed an instance of UploadedFile, return the path
107 3
        if ($file instanceof UploadedFile) {
108
            return $file->getPathname();
109
        }
110
111
        // if we're passed a PHP file upload array, return the "tmp_name"
112 3
        if (is_array($file) && null !== array_get($file, 'tmp_name')) {
113
            return $file['tmp_name'];
114
        }
115
116
        // fallback: we were likely passed a path already
117 3
        return $file;
118
    }
119
}
120