1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Manager class for antivirus integration.
19 *
20 * @package    core_antivirus
21 * @copyright  2015 Ruslan Kabalin, Lancaster University.
22 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace core\antivirus;
26
27defined('MOODLE_INTERNAL') || die();
28
29/**
30 * Class used for various antivirus related stuff.
31 *
32 * @package    core_antivirus
33 * @copyright  2015 Ruslan Kabalin, Lancaster University.
34 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
36class manager {
37    /**
38     * Returns list of enabled antiviruses.
39     *
40     * @return array Array ('antivirusname'=>stdClass antivirus object).
41     */
42    private static function get_enabled() {
43        global $CFG;
44
45        $active = array();
46        if (empty($CFG->antiviruses)) {
47            return $active;
48        }
49
50        foreach (explode(',', $CFG->antiviruses) as $e) {
51            if ($antivirus = self::get_antivirus($e)) {
52                if ($antivirus->is_configured()) {
53                    $active[$e] = $antivirus;
54                }
55            }
56        }
57        return $active;
58    }
59
60    /**
61     * Scan file using all enabled antiviruses, throws exception in case of infected file.
62     *
63     * @param string $file Full path to the file.
64     * @param string $filename Name of the file (could be different from physical file if temp file is used).
65     * @param bool $deleteinfected whether infected file needs to be deleted.
66     * @throws \core\antivirus\scanner_exception If file is infected.
67     * @return void
68     */
69    public static function scan_file($file, $filename, $deleteinfected) {
70        $antiviruses = self::get_enabled();
71        foreach ($antiviruses as $antivirus) {
72            $result = $antivirus->scan_file($file, $filename);
73            if ($result === $antivirus::SCAN_RESULT_FOUND) {
74                // Infection found.
75                if ($deleteinfected) {
76                    unlink($file);
77                }
78                throw new \core\antivirus\scanner_exception('virusfound', '', array('item' => $filename));
79            }
80        }
81    }
82
83    /**
84     * Scan data steam using all enabled antiviruses, throws exception in case of infected data.
85     *
86     * @param string $data The varaible containing the data to scan.
87     * @throws \core\antivirus\scanner_exception If data is infected.
88     * @return void
89     */
90    public static function scan_data($data) {
91        $antiviruses = self::get_enabled();
92        foreach ($antiviruses as $antivirus) {
93            $result = $antivirus->scan_data($data);
94            if ($result === $antivirus::SCAN_RESULT_FOUND) {
95                throw new \core\antivirus\scanner_exception('virusfound', '', array('item' => get_string('datastream', 'antivirus')));
96            }
97        }
98    }
99
100    /**
101     * Returns instance of antivirus.
102     *
103     * @param string $antivirusname name of antivirus.
104     * @return object|bool antivirus instance or false if does not exist.
105     */
106    public static function get_antivirus($antivirusname) {
107        global $CFG;
108
109        $classname = '\\antivirus_' . $antivirusname . '\\scanner';
110        if (!class_exists($classname)) {
111            return false;
112        }
113        return new $classname();
114    }
115
116    /**
117     * Get the list of available antiviruses.
118     *
119     * @return array Array ('antivirusname'=>'localised antivirus name').
120     */
121    public static function get_available() {
122        $antiviruses = array();
123        foreach (\core_component::get_plugin_list('antivirus') as $antivirusname => $dir) {
124            $antiviruses[$antivirusname] = get_string('pluginname', 'antivirus_'.$antivirusname);
125        }
126        return $antiviruses;
127    }
128}
129