AutorÃa | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Base class for antivirus integration.** @package core_antivirus* @copyright 2015 Ruslan Kabalin, Lancaster University.* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/namespace core\antivirus;defined('MOODLE_INTERNAL') || die();require_once($CFG->dirroot . '/iplookup/lib.php');/*** Base abstract antivirus scanner class.** @package core* @subpackage antivirus* @copyright 2015 Ruslan Kabalin, Lancaster University.* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/abstract class scanner {/** Scanning result indicating no virus found. */const SCAN_RESULT_OK = 0;/** Scanning result indicating that virus is found. */const SCAN_RESULT_FOUND = 1;/** Scanning result indicating the error. */const SCAN_RESULT_ERROR = 2;/** @var \stdClass the config for antivirus */protected $config;/** @var string scanning notice */protected $scanningnotice = '';/** @var array any admin messages generated by a plugin. */protected $messages = [];/*** Class constructor.** @return void.*/public function __construct() {// Populate config variable, inheriting class namespace is matching// full plugin name, so we can use it directly to retrieve plugin// configuration.$ref = new \ReflectionClass(get_class($this));$this->config = get_config($ref->getNamespaceName());}/*** Config get method.** @param string $property config property to get.* @return mixed* @throws \coding_exception*/public function get_config($property) {if (property_exists($this->config, $property)) {return $this->config->$property;}throw new \coding_exception('Config property "' . $property . '" doesn\'t exist');}/*** Get scanning notice.** @return string*/public function get_scanning_notice() {return $this->scanningnotice;}/*** Set scanning notice.** @param string $notice notice to set.* @return void*/protected function set_scanning_notice($notice) {$this->scanningnotice = $notice;}/*** Are the antivirus settings configured?** @return bool True if plugin has been configured.*/abstract public function is_configured();/*** Scan file.** @param string $file Full path to the file.* @param string $filename Name of the file (could be different from physical file if temp file is used).* @return int Scanning result constants.*/abstract public function scan_file($file, $filename);/*** Scan data.** By default it saves data variable content to file and then scans it using* scan_file method, however if antivirus plugin permits scanning data directly,* the method can be overridden.** @param string $data The variable containing the data to scan.* @return int Scanning result constants.*/public function scan_data($data) {// Prepare temp file.$tempdir = make_request_directory();$tempfile = $tempdir . DIRECTORY_SEPARATOR . rand();file_put_contents($tempfile, $data);// Perform a virus scan now.return $this->scan_file($tempfile, get_string('datastream', 'antivirus'));}/*** This function pushes given messages into the message queue, which will be sent by the antivirus manager.** @param string $notice The body of the email to be sent.* @param string $format The body format.* @param string $eventname event name* @return void* @throws \coding_exception* @throws \moodle_exception*/public function message_admins($notice, $format = FORMAT_PLAIN, $eventname = 'errors') {$noticehtml = $format !== FORMAT_PLAIN ? format_text($notice, $format) : '';$site = get_site();$subject = get_string('emailsubject', 'antivirus', format_string($site->fullname));$notifyemail = get_config('antivirus', 'notifyemail');// If one email address is specified, construct a message to fake account.if (!empty($notifyemail)) {$user = new \stdClass();$user->id = -1;$user->email = $notifyemail;$user->mailformat = 1;$admins = [$user];} else {// Otherwise, we message all admins.$admins = get_admins();}foreach ($admins as $admin) {$eventdata = new \core\message\message();$eventdata->courseid = SITEID;$eventdata->component = 'moodle';$eventdata->name = $eventname;$eventdata->userfrom = get_admin();$eventdata->userto = $admin;$eventdata->subject = $subject;$eventdata->fullmessage = $notice;$eventdata->fullmessageformat = $format;$eventdata->fullmessagehtml = $noticehtml;$eventdata->smallmessage = '';// Now add the message to an array to be sent by the antivirus manager.$this->messages[] = $eventdata;}}/*** Return incident details** @param string $file full path to the file* @param string $filename original name of the file* @param string $notice notice from antivirus* @param string $virus if this template is due to a virus found.* @return string the incident details* @throws \coding_exception*/public function get_incident_details($file = '', $filename = '', $notice = '', $virus = true) {global $OUTPUT, $USER;if (empty($notice)) {$notice = $this->get_scanning_notice();}$classname = get_class($this);$component = explode('\\', $classname)[0];$content = new \stdClass();$unknown = get_string('unknown', 'antivirus');$content->header = get_string('emailinfectedfiledetected', 'antivirus');$content->filename = !empty($filename) ? $filename : $unknown;$content->scanner = $component;// Check for empty file, or file not uploaded.if (!empty($file) && filesize($file) !== false) {$content->filesize = display_size(filesize($file));$content->contenthash = \file_storage::hash_from_path($file);$content->contenttype = mime_content_type($file);} else {$content->filesize = $unknown;$content->contenthash = $unknown;$content->contenttype = $unknown;}$content->author = \core_user::is_real_user($USER->id) ? fullname($USER) . " ($USER->username)" : $unknown;$content->ipaddress = getremoteaddr();$geoinfo = iplookup_find_location(getremoteaddr());$content->geoinfo = $geoinfo['city'] . ', ' . $geoinfo['country'];$content->date = userdate(time(), get_string('strftimedatetimeshort'));$content->referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $unknown;$content->notice = $notice;$report = new \moodle_url('/report/infectedfiles/index.php');$content->report = $report->out();// If this is not due to a virus, we need to change the header line.if (!$virus) {$content->header = get_string('emailscannererrordetected', 'antivirus');}return $OUTPUT->render_from_template('core/infected_file_email', $content);}/*** Getter method for messages queued by the antivirus scanner.** @return array*/public function get_messages(): array {return $this->messages;}/*** Getter method for the antivirus message displayed in the exception.** @return array array of string and component to pass to exception constructor.*/public function get_virus_found_message() {// Base antivirus found string.return ['string' => 'virusfound', 'component' => 'antivirus', 'placeholders' => []];}}