Completed
Pull Request — master (#14)
by Krishnaprasad
11:20
created

ClamavValidator::validateClamav()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0067

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 26
ccs 10
cts 11
cp 0.9091
rs 9.504
cc 3
nc 3
nop 3
crap 3.0067
1
<?php namespace Sunspikes\ClamavValidator;
2
3
use Illuminate\Validation\Validator;
4
use Xenolope\Quahog\Client;
5
use Socket\Raw\Factory;
6
use Symfony\Component\HttpFoundation\File\UploadedFile;
7
8
class ClamavValidator extends Validator
9
{
10
    /**
11
     * @const string CLAMAV_STATUS_OK
12
     */
13
    const CLAMAV_STATUS_OK = 'OK';
14
15
    /**
16
     * @const string CLAMAV_STATUS_ERROR
17
     */
18
    const CLAMAV_STATUS_ERROR = 'ERROR';
19
20
    /**
21
     * @const string CLAMAV_UNIX_SOCKET
22
     */
23
    const CLAMAV_UNIX_SOCKET = '/var/run/clamav/clamd.ctl';
24
25
    /**
26
     * @const string CLAMAV_LOCAL_TCP_SOCKET
27
     */
28
    const CLAMAV_LOCAL_TCP_SOCKET = 'tcp://127.0.0.1:3310';
29
30
    /**
31
     * @const string CLAMAV_SOCKET_READ_TIMEOUT
32
     */
33
    const CLAMAV_SOCKET_READ_TIMEOUT = 30;
34
35
    /**
36
     * Creates a new instance of ClamavValidator
37
     */
38 4
    public function __construct($translator, $data, $rules, $messages)
39
    {
40 4
        parent::__construct($translator, $data, $rules, $messages);
41 4
    }
42
43
    /**
44
     * Validate the uploaded file for virus/malware with ClamAV
45
     *
46
     * @param  $attribute   string
47
     * @param  $value       mixed
48
     * @param  $parameters  array
49
     *
50
     * @return boolean
51
     * @throws ClamavValidatorException
52
     */
53 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...
54
    {
55 3
        $file = $this->getFilePath($value);
56 3
        $clamavSocket = $this->getClamavSocket();
57
58
        // Create a new socket instance
59 3
        $socket = (new Factory())->createClient($clamavSocket);
60
61
        // Create a new instance of the Client
62 3
        $quahog = new Client($socket, self::CLAMAV_SOCKET_READ_TIMEOUT, PHP_NORMAL_READ);
63
64
        // Check if the file is readable
65 3
        if (! is_readable($file)) {
66 1
            throw new ClamavValidatorException(sprintf('The file "%s" is not readable', $file));
67
        }
68
69
        // Scan the file
70 2
        $result = $quahog->scanResourceStream(fopen($file, 'rb'));
71
72 2
        if (self::CLAMAV_STATUS_ERROR === $result['status']) {
73
            throw new ClamavValidatorException($result['reason']);
74
        }
75
76
        // Check if scan result is not clean
77 2
        return !(self::CLAMAV_STATUS_OK !== $result['status']);
78
    }
79
80
    /**
81
     * Guess the ClamAV socket
82
     *
83
     * @return string
84
     */
85 3
    protected function getClamavSocket()
86
    {
87 3
        if (file_exists(env('CLAMAV_UNIX_SOCKET', self::CLAMAV_UNIX_SOCKET))) {
88 3
            return 'unix://' . env('CLAMAV_UNIX_SOCKET', self::CLAMAV_UNIX_SOCKET);
89
        }
90
91
        return env('CLAMAV_TCP_SOCKET', self::CLAMAV_LOCAL_TCP_SOCKET);
92
    }
93
94
    /**
95
     * Return the file path from the passed object
96
     *
97
     * @param $file mixed
98
     * @return string
99
     */
100 3
    protected function getFilePath($file)
101
    {
102
        // if were passed an instance of UploadedFile, return the path
103 3
        if ($file instanceof UploadedFile) {
104
            return $file->getPathname();
105
        }
106
107
        // if we're passed a PHP file upload array, return the "tmp_name"
108 3
        if (is_array($file) && null !== array_get($file, 'tmp_name')) {
109
            return $file['tmp_name'];
110
        }
111
112
        // fallback: we were likely passed a path already
113 3
        return $file;
114
    }
115
}
116