See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 * Base 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 25 namespace core\antivirus; 26 27 defined('MOODLE_INTERNAL') || die(); 28 require_once($CFG->dirroot . '/iplookup/lib.php'); 29 30 /** 31 * Base abstract antivirus scanner class. 32 * 33 * @package core 34 * @subpackage antivirus 35 * @copyright 2015 Ruslan Kabalin, Lancaster University. 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 abstract class scanner { 39 /** Scanning result indicating no virus found. */ 40 const SCAN_RESULT_OK = 0; 41 /** Scanning result indicating that virus is found. */ 42 const SCAN_RESULT_FOUND = 1; 43 /** Scanning result indicating the error. */ 44 const SCAN_RESULT_ERROR = 2; 45 46 /** @var stdClass the config for antivirus */ 47 protected $config; 48 /** @var string scanning notice */ 49 protected $scanningnotice = ''; 50 /** @var array any admin messages generated by a plugin. */ 51 protected $messages = []; 52 53 /** 54 * Class constructor. 55 * 56 * @return void. 57 */ 58 public function __construct() { 59 // Populate config variable, inheriting class namespace is matching 60 // full plugin name, so we can use it directly to retrieve plugin 61 // configuration. 62 $ref = new \ReflectionClass(get_class($this)); 63 $this->config = get_config($ref->getNamespaceName()); 64 } 65 66 /** 67 * Config get method. 68 * 69 * @param string $property config property to get. 70 * @return mixed 71 * @throws \coding_exception 72 */ 73 public function get_config($property) { 74 if (property_exists($this->config, $property)) { 75 return $this->config->$property; 76 } 77 throw new \coding_exception('Config property "' . $property . '" doesn\'t exist'); 78 } 79 80 /** 81 * Get scanning notice. 82 * 83 * @return string 84 */ 85 public function get_scanning_notice() { 86 return $this->scanningnotice; 87 } 88 89 /** 90 * Set scanning notice. 91 * 92 * @param string $notice notice to set. 93 * @return void 94 */ 95 protected function set_scanning_notice($notice) { 96 $this->scanningnotice = $notice; 97 } 98 99 /** 100 * Are the antivirus settings configured? 101 * 102 * @return bool True if plugin has been configured. 103 */ 104 public abstract function is_configured(); 105 106 /** 107 * Scan file. 108 * 109 * @param string $file Full path to the file. 110 * @param string $filename Name of the file (could be different from physical file if temp file is used). 111 * @return int Scanning result constants. 112 */ 113 public abstract function scan_file($file, $filename); 114 115 /** 116 * Scan data. 117 * 118 * By default it saves data variable content to file and then scans it using 119 * scan_file method, however if antivirus plugin permits scanning data directly, 120 * the method can be overridden. 121 * 122 * @param string $data The variable containing the data to scan. 123 * @return int Scanning result constants. 124 */ 125 public function scan_data($data) { 126 // Prepare temp file. 127 $tempdir = make_request_directory(); 128 $tempfile = $tempdir . DIRECTORY_SEPARATOR . rand(); 129 file_put_contents($tempfile, $data); 130 131 // Perform a virus scan now. 132 return $this->scan_file($tempfile, get_string('datastream', 'antivirus')); 133 } 134 135 /** 136 * This function pushes given messages into the message queue, which will be sent by the antivirus manager. 137 * 138 * @param string $notice The body of the email to be sent. 139 * @param string $format The body format. 140 * @param string $eventname event name 141 * @return void 142 * @throws \coding_exception 143 * @throws \moodle_exception 144 */ 145 public function message_admins($notice, $format = FORMAT_PLAIN, $eventname = 'errors') { 146 $noticehtml = $format !== FORMAT_PLAIN ? format_text($notice, $format) : ''; 147 $site = get_site(); 148 149 $subject = get_string('emailsubject', 'antivirus', format_string($site->fullname)); 150 $notifyemail = get_config('antivirus', 'notifyemail'); 151 // If one email address is specified, construct a message to fake account. 152 if (!empty($notifyemail)) { 153 $user = new \stdClass(); 154 $user->id = -1; 155 $user->email = $notifyemail; 156 $user->mailformat = 1; 157 $admins = [$user]; 158 } else { 159 // Otherwise, we message all admins. 160 $admins = get_admins(); 161 } 162 163 foreach ($admins as $admin) { 164 $eventdata = new \core\message\message(); 165 $eventdata->courseid = SITEID; 166 $eventdata->component = 'moodle'; 167 $eventdata->name = $eventname; 168 $eventdata->userfrom = get_admin(); 169 $eventdata->userto = $admin; 170 $eventdata->subject = $subject; 171 $eventdata->fullmessage = $notice; 172 $eventdata->fullmessageformat = $format; 173 $eventdata->fullmessagehtml = $noticehtml; 174 $eventdata->smallmessage = ''; 175 176 // Now add the message to an array to be sent by the antivirus manager. 177 $this->messages[] = $eventdata; 178 } 179 } 180 181 /** 182 * Return incident details 183 * 184 * @param string $file full path to the file 185 * @param string $filename original name of the file 186 * @param string $notice notice from antivirus 187 * @param string $virus if this template is due to a virus found. 188 * @return string the incident details 189 * @throws \coding_exception 190 */ 191 public function get_incident_details($file = '', $filename = '', $notice = '', $virus = true) { 192 global $OUTPUT, $USER; 193 if (empty($notice)) { 194 $notice = $this->get_scanning_notice(); 195 } 196 $classname = get_class($this); 197 $component = explode('\\', $classname)[0]; 198 199 $content = new \stdClass(); 200 $unknown = get_string('unknown', 'antivirus'); 201 $content->header = get_string('emailinfectedfiledetected', 'antivirus'); 202 $content->filename = !empty($filename) ? $filename : $unknown; 203 $content->scanner = $component; 204 // Check for empty file, or file not uploaded. 205 if (!empty($file) && filesize($file) !== false) { 206 $content->filesize = display_size(filesize($file)); 207 $content->contenthash = \file_storage::hash_from_path($file); 208 $content->contenttype = mime_content_type($file); 209 } else { 210 $content->filesize = $unknown; 211 $content->contenthash = $unknown; 212 $content->contenttype = $unknown; 213 } 214 215 $content->author = \core_user::is_real_user($USER->id) ? fullname($USER) . " ($USER->username)" : $unknown; 216 $content->ipaddress = getremoteaddr(); 217 $geoinfo = iplookup_find_location(getremoteaddr()); 218 $content->geoinfo = $geoinfo['city'] . ', ' . $geoinfo['country']; 219 $content->date = userdate(time(), get_string('strftimedatetimeshort')); 220 $content->referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $unknown; 221 $content->notice = $notice; 222 $report = new \moodle_url('/report/infectedfiles/index.php'); 223 $content->report = $report->out(); 224 225 // If this is not due to a virus, we need to change the header line. 226 if (!$virus) { 227 $content->header = get_string('emailscannererrordetected', 'antivirus'); 228 } 229 230 return $OUTPUT->render_from_template('core/infected_file_email', $content); 231 } 232 233 /** 234 * Getter method for messages queued by the antivirus scanner. 235 * 236 * @return array 237 */ 238 public function get_messages() : array { 239 return $this->messages; 240 } 241 242 /** 243 * Getter method for the antivirus message displayed in the exception. 244 * 245 * @return array array of string and component to pass to exception constructor. 246 */ 247 public function get_virus_found_message() { 248 // Base antivirus found string. 249 return ['string' => 'virusfound', 'component' => 'antivirus', 'placeholders' => []]; 250 } 251 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body