Completed
Push — master ( e3a6ad...a80db0 )
by Krishnaprasad
04:55
created

src/ClamavValidator/ClamavValidator.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Sunspikes\ClamavValidator;
4
5
use Illuminate\Contracts\Translation\Translator;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Facades\Config;
8
use Illuminate\Validation\Validator;
9
use Xenolope\Quahog\Client as QuahogClient;
10
use Socket\Raw\Factory as SocketFactory;
11
use Symfony\Component\HttpFoundation\File\UploadedFile;
12
13
class ClamavValidator extends Validator
14
{
15
    /**
16
     * Creates a new instance of ClamavValidator.
17
     *
18
     * ClamavValidator constructor.
19
     * @param Translator $translator
20
     * @param array      $data
21
     * @param array      $rules
22
     * @param array      $messages
23
     * @param array      $customAttributes
24
     */
25 4
    public function __construct(
26
        Translator $translator,
27
        array $data,
28
        array $rules,
29
        array $messages = [],
30
        array $customAttributes = []
31
    ) {
32 4
        parent::__construct($translator, $data, $rules, $messages, $customAttributes);
33 4
    }
34
35
    /**
36
     * Validate the uploaded file for virus/malware with ClamAV.
37
     *
38
     * @param  $attribute   string
39
     * @param  $value       mixed
40
     * @param  $parameters  array
41
     *
42
     * @return boolean
43
     * @throws ClamavValidatorException
44
     */
45 3
    public function validateClamav($attribute, $value, $parameters)
0 ignored issues
show
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...
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...
46
    {
47 3
        if (true === Config::get('clamav.skip_validation')) {
48
            return true;
49
        }
50
51 3
        $file = $this->getFilePath($value);
52 3
        if (! is_readable($file)) {
53 1
            throw ClamavValidatorException::forNonReadableFile($file);
54
        }
55
56
        try {
57 2
            $socket  = $this->getClamavSocket();
58 2
            $scanner = $this->createQuahogScannerClient($socket);
59 2
            $result  = $scanner->scanResourceStream(fopen($file, 'rb'));
60 2
        } catch (\Exception $exception) {
61
            throw ClamavValidatorException::forClientException($exception);
62
        }
63
64 2
        if (QuahogClient::RESULT_ERROR === $result['status']) {
65
            throw ClamavValidatorException::forScanResult($result);
66
        }
67
68
        // Check if scan result is clean
69 2
        return QuahogClient::RESULT_OK === $result['status'];
70
    }
71
72
    /**
73
     * Guess the ClamAV socket.
74
     *
75
     * @return string
76
     */
77 2
    protected function getClamavSocket()
78
    {
79 2
        $preferredSocket = Config::get('clamav.preferred_socket');
80
81 2
        if ($preferredSocket === 'unix_socket') {
82 2
            $unixSocket = Config::get('clamav.unix_socket');
83 2
            if (file_exists($unixSocket)) {
84 2
                return 'unix://' . $unixSocket;
85
            }
86
        }
87
88
        // We use the tcp_socket as fallback as well
89
        return Config::get('clamav.tcp_socket');
90
    }
91
92
    /**
93
     * Return the file path from the passed object.
94
     *
95
     * @param mixed $file
96
     * @return string
97
     */
98 3
    protected function getFilePath($file)
99
    {
100
        // if were passed an instance of UploadedFile, return the path
101 3
        if ($file instanceof UploadedFile) {
102
            return $file->getPathname();
103
        }
104
105
        // if we're passed a PHP file upload array, return the "tmp_name"
106 3
        if (is_array($file) && null !== Arr::get($file, 'tmp_name')) {
107
            return $file['tmp_name'];
108
        }
109
110
        // fallback: we were likely passed a path already
111 3
        return $file;
112
    }
113
114
    /**
115
     * Create a new quahog ClamAV scanner client.
116
     *
117
     * @param string $socket
118
     * @return QuahogClient
119
     */
120 2
    protected function createQuahogScannerClient($socket)
121
    {
122
        // Create a new client socket instance
123 2
        $client = (new SocketFactory())->createClient($socket);
124
125 2
        return new QuahogClient($client, Config::get('clamav.socket_read_timeout'), PHP_NORMAL_READ);
126
    }
127
}
128