ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilVirusScannerClamAV.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22{
23 private const ADD_SCAN_PARAMS = '--no-summary -i';
24
25 public function __construct(string $scan_command, string $clean_command)
26 {
27 parent::__construct($scan_command, $clean_command);
28 $this->type = 'clamav';
29 $this->scanZipFiles = true;
30 }
31
32 public function scanBuffer(string $buffer): bool
33 {
34 if (!$this->isBufferScanPossible()) {
35 return $this->scanFileFromBuffer($buffer);
36 }
37
38 return $this->processBufferScan($buffer);
39 }
40
41 protected function isBufferScanPossible(): bool
42 {
43 $functions = ['proc_open', 'proc_close'];
44
45 foreach ($functions as $func) {
46 if (function_exists($func)) {
47 continue;
48 }
49
50 return false;
51 }
52
53 return true;
54 }
55
56 protected function processBufferScan(string $buffer): bool
57 {
58 $descriptor_spec = [
59 0 => ['pipe', 'r'], // stdin is a pipe that the child will read from
60 1 => ['pipe', 'w'], // stdout is a pipe that the child will write to
61 2 => ['pipe', 'w'] // stderr for the child
62 ];
63
64 $pipes = []; // will look like follows after passing
65 // 0 => writeable handle connected to child stdin
66 // 1 => readable handle connected to child stdout
67
68 $process = proc_open($this->buildScanCommand(), $descriptor_spec, $pipes);
69
70 if (!is_resource($process)) {
71 return false; // no scan, no virus detected
72 }
73
74 fwrite($pipes[0], $buffer);
75 fclose($pipes[0]);
76
77 $detectionReport = stream_get_contents($pipes[1]);
78 fclose($pipes[1]);
79
80 $errorReport = stream_get_contents($pipes[2]);
81 fclose($pipes[2]);
82
83 $return = proc_close($process);
84
85 return (bool) $this->hasDetections($detectionReport);
86 }
87
88 protected function buildScanCommand(string $file = '-'): string
89 {
90 return $this->scanCommand . ' ' . self::ADD_SCAN_PARAMS . ' ' . $file;
91 }
95 protected function buildScanCommandArguments($file = '-') // default means piping
96 {
97 return ' ' . self::ADD_SCAN_PARAMS . ' ' . $file;
98 }
99
100
101 protected function hasDetections(string $detectionReport): int
102 {
103 return preg_match('/FOUND/', $detectionReport);
104 }
105
106 public function scanFile(string $file_path, string $org_name = ''): string
107 {
108 $this->scanFilePath = $file_path;
109 $this->scanFileOrigName = $org_name;
110 // Make group readable for clamdscan
111 $currentPermission = fileperms($file_path);
112 $perm = $currentPermission | 0640;
113 chmod($file_path, $perm);
114
115 $a_filepath = realpath($file_path);
116 if (file_exists($file_path)) {
117 $args = ilShellUtil::escapeShellArg($file_path);
118 $arguments = $this->buildScanCommandArguments($args) . ' 2>&1';
119 $cmd = ilShellUtil::escapeShellCmd($this->scanCommand);
120 $out = ilShellUtil::execQuoted($cmd, $arguments);
121 $this->scanResult = implode("\n", $out);
122
123 if ($perm != $currentPermission) {
124 chmod($a_filepath, $currentPermission);
125 }
126
127 if ($this->hasDetections($this->scanResult)) {
128 $this->scanFileIsInfected = true;
129 $this->logScanResult();
130 return $this->scanResult;
131 } else {
132 $this->scanFileIsInfected = false;
133 return '';
134 }
135 }
136
137 $return_error = 'ERROR (Virus Scanner failed): '
138 . $this->scanResult
139 . '; Path=' . $a_filepath;
140 $this->log->write($return_error);
141 return $return_error;
142 }
143}
$out
Definition: buildRTE.php:24
static escapeShellArg(string $a_arg)
static escapeShellCmd(string $a_arg)
static execQuoted(string $cmd, ?string $args=null)
scanFile(string $file_path, string $org_name='')
__construct(string $scan_command, string $clean_command)
hasDetections(string $detectionReport)
scanFileFromBuffer(string $buffer)
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc