Completed
Push — master ( d2158a...3056cf )
by Krishnaprasad
04:47
created

ClamavValidator::validateClamav()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0582

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 11
cts 13
cp 0.8462
rs 9.424
c 0
b 0
f 0
cc 4
nc 4
nop 3
crap 4.0582
1
<?php namespace Sunspikes\ClamavValidator;
2
3
use Illuminate\Contracts\Translation\Translator;
4
use Illuminate\Support\Arr;
5
use Illuminate\Support\Facades\Config;
6
use Illuminate\Validation\Validator;
7
use Xenolope\Quahog\Client;
8
use Socket\Raw\Factory;
9
use Symfony\Component\HttpFoundation\File\UploadedFile;
10
11
class ClamavValidator extends Validator
12
{
13
    /**
14
     * Creates a new instance of ClamavValidator
15
     *
16
     * ClamavValidator constructor.
17
     * @param Translator $translator
18
     * @param array      $data
19
     * @param array      $rules
20
     * @param array      $messages
21
     * @param array      $customAttributes
22
     */
23 4
    public function __construct(
24
        Translator $translator,
25
        array $data,
26
        array $rules,
27
        array $messages = [],
28
        array $customAttributes = []
29
    ) {
30 4
        parent::__construct($translator, $data, $rules, $messages, $customAttributes);
31 4
    }
32
33
    /**
34
     * Validate the uploaded file for virus/malware with ClamAV
35
     *
36
     * @param  $attribute   string
37
     * @param  $value       mixed
38
     * @param  $parameters  array
39
     *
40
     * @return boolean
41
     * @throws ClamavValidatorException
42
     */
43 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...
44
    {
45
        // Skip validation, if configured
46 3
        if (true === Config::get('clamav.skip_validation')) {
47
            return true;
48
        }
49
50 3
        $file = $this->getFilePath($value);
51 3
        $clamavSocket = $this->getClamavSocket();
52
53
        // Create a new socket instance
54 3
        $socket = (new Factory())->createClient($clamavSocket);
55
56
        // Create a new instance of the Client
57 3
        $quahog = new Client($socket, Config::get('clamav.socket_read_timeout'), PHP_NORMAL_READ);
58
59
        // Check if the file is readable
60 3
        if (! is_readable($file)) {
61 1
            throw new ClamavValidatorException(sprintf('The file "%s" is not readable', $file));
62
        }
63
64
        // Scan the file
65 2
        $result = $quahog->scanResourceStream(fopen($file, 'rb'));
66
67 2
        if (Client::RESULT_ERROR === $result['status']) {
68
            throw new ClamavValidatorException($result['reason']);
69
        }
70
71
        // Check if scan result is not clean
72 2
        return Client::RESULT_OK === $result['status'];
73
    }
74
75
    /**
76
     * Guess the ClamAV socket
77
     *
78
     * @return string
79
     */
80 3
    protected function getClamavSocket()
81
    {
82 3
        $preferredSocket = Config::get('clamav.preferred_socket');
83
84 3
        if ($preferredSocket === 'unix_socket') {
85 3
            $unixSocket = Config::get('clamav.unix_socket');
86 3
            if (file_exists($unixSocket)) {
87 3
                return 'unix://' . $unixSocket;
88
            }
89
        }
90
        // We use the tcp_socket as fallback as well
91
        return Config::get('clamav.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 !== Arr::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