Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

   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   * Tests for antivirus manager.
  19   *
  20   * @package    core_antivirus
  21   * @category   phpunit
  22   * @copyright  2016 Ruslan Kabalin, Lancaster University.
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  require_once (__DIR__ . '/fixtures/testable_antivirus.php');
  28  
  29  class core_antivirus_testcase extends advanced_testcase {
  30      protected $tempfile;
  31  
  32      protected function setUp(): void {
  33          global $CFG;
  34          // Use our special testable fixture plugin.
  35          $CFG->antiviruses = 'testable';
  36  
  37          $this->resetAfterTest();
  38  
  39          // Create tempfile.
  40          $tempfolder = make_request_directory(false);
  41          $this->tempfile = $tempfolder . '/' . rand();
  42          touch($this->tempfile);
  43      }
  44  
  45      protected function tearDown(): void {
  46          @unlink($this->tempfile);
  47      }
  48  
  49      public function test_manager_get_antivirus() {
  50          // We are using clamav plugin in the test,
  51          // as the only plugin we know exists for sure.
  52          $antivirusviaget = \core\antivirus\manager::get_antivirus('clamav');
  53          $antivirusdirect = new \antivirus_clamav\scanner();
  54          $this->assertEquals($antivirusdirect, $antivirusviaget);
  55      }
  56  
  57      public function test_manager_scan_file_no_virus() {
  58          // Run mock scanning.
  59          $this->assertFileExists($this->tempfile);
  60          $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'OK', true));
  61          // File expected to remain in place.
  62          $this->assertFileExists($this->tempfile);
  63      }
  64  
  65      public function test_manager_scan_file_error() {
  66          // Run mock scanning.
  67          $this->assertFileExists($this->tempfile);
  68          $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'ERROR', true));
  69          // File expected to remain in place.
  70          $this->assertFileExists($this->tempfile);
  71      }
  72  
  73      public function test_manager_scan_file_virus() {
  74          // Run mock scanning without deleting infected file.
  75          $this->assertFileExists($this->tempfile);
  76          $this->expectException(\core\antivirus\scanner_exception::class);
  77          $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'FOUND', false));
  78          // File expected to remain in place.
  79          $this->assertFileExists($this->tempfile);
  80  
  81          // Run mock scanning with deleting infected file.
  82          $this->expectException(\core\antivirus\scanner_exception::class);
  83          $this->assertEmpty(\core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true));
  84          // File expected to be deleted.
  85          $this->assertFileDoesNotExist($this->tempfile);
  86      }
  87  
  88      public function test_manager_send_message_to_user_email_scan_file_virus() {
  89          $sink = $this->redirectEmails();
  90          $exception = null;
  91          try {
  92              set_config('notifyemail', 'fake@example.com', 'antivirus');
  93              \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
  94          } catch (\core\antivirus\scanner_exception $ex) {
  95              $exception = $ex;
  96          }
  97          $this->assertNotEmpty($exception);
  98          $result = $sink->get_messages();
  99          $this->assertCount(1, $result);
 100          $this->assertStringContainsString('fake@example.com', $result[0]->to);
 101          $sink->close();
 102      }
 103  
 104      public function test_manager_send_message_to_admin_email_scan_file_virus() {
 105          $sink = $this->redirectMessages();
 106          $exception = null;
 107          try {
 108              \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
 109          } catch (\core\antivirus\scanner_exception $ex) {
 110              $exception = $ex;
 111          }
 112          $this->assertNotEmpty($exception);
 113          $result = $sink->get_messages();
 114          $admins = array_keys(get_admins());
 115          $this->assertCount(1, $admins);
 116          $this->assertCount(1, $result);
 117          $this->assertEquals($result[0]->useridto, reset($admins));
 118          $sink->close();
 119      }
 120  
 121      public function test_manager_quarantine_file_virus() {
 122          try {
 123              set_config('enablequarantine', true, 'antivirus');
 124              \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
 125          } catch (\core\antivirus\scanner_exception $ex) {
 126              $exception = $ex;
 127          }
 128          $this->assertNotEmpty($exception);
 129          // Quarantined files.
 130          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 131          $this->assertEquals(1, count($quarantinedfiles));
 132          // Clean up.
 133          \core\antivirus\quarantine::clean_up_quarantine_folder(time());
 134          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 135          $this->assertEquals(0, count($quarantinedfiles));
 136      }
 137  
 138      public function test_manager_none_quarantine_file_virus() {
 139          try {
 140              \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true);
 141          } catch (\core\antivirus\scanner_exception $ex) {
 142              $exception = $ex;
 143          }
 144          $this->assertNotEmpty($exception);
 145          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 146          $this->assertEquals(0, count($quarantinedfiles));
 147      }
 148  
 149      public function test_manager_scan_data_no_virus() {
 150          // Run mock scanning.
 151          $this->assertEmpty(\core\antivirus\manager::scan_data('OK'));
 152      }
 153  
 154      public function test_manager_scan_data_error() {
 155          // Run mock scanning.
 156          $this->assertEmpty(\core\antivirus\manager::scan_data('ERROR'));
 157      }
 158  
 159      public function test_manager_scan_data_virus() {
 160          // Run mock scanning.
 161          $this->expectException(\core\antivirus\scanner_exception::class);
 162          $this->assertEmpty(\core\antivirus\manager::scan_data('FOUND'));
 163      }
 164  
 165      public function test_manager_send_message_to_user_email_scan_data_virus() {
 166          $sink = $this->redirectEmails();
 167          set_config('notifyemail', 'fake@example.com', 'antivirus');
 168          $exception = null;
 169          try {
 170              \core\antivirus\manager::scan_data('FOUND');
 171          } catch (\core\antivirus\scanner_exception $ex) {
 172              $exception = $ex;
 173          }
 174          $this->assertNotEmpty($exception);
 175          $result = $sink->get_messages();
 176          $this->assertCount(1, $result);
 177          $this->assertStringContainsString('fake@example.com', $result[0]->to);
 178          $sink->close();
 179      }
 180  
 181      public function test_manager_send_message_to_admin_email_scan_data_virus() {
 182          $sink = $this->redirectMessages();
 183          $exception = null;
 184          try {
 185              \core\antivirus\manager::scan_data('FOUND');
 186          } catch (\core\antivirus\scanner_exception $ex) {
 187              $exception = $ex;
 188          }
 189          $this->assertNotEmpty($exception);
 190          $result = $sink->get_messages();
 191          $admins = array_keys(get_admins());
 192          $this->assertCount(1, $admins);
 193          $this->assertCount(1, $result);
 194          $this->assertEquals($result[0]->useridto, reset($admins));
 195          $sink->close();
 196      }
 197  
 198      public function test_manager_quarantine_data_virus() {
 199          set_config('enablequarantine', true, 'antivirus');
 200          $exception = null;
 201          try {
 202              \core\antivirus\manager::scan_data('FOUND');
 203          } catch (\core\antivirus\scanner_exception $ex) {
 204              $exception = $ex;
 205          }
 206          $this->assertNotEmpty($exception);
 207          // Quarantined files.
 208          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 209          $this->assertEquals(1, count($quarantinedfiles));
 210          // Clean up.
 211          \core\antivirus\quarantine::clean_up_quarantine_folder(time());
 212          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 213          $this->assertEquals(0, count($quarantinedfiles));
 214      }
 215  
 216  
 217      public function test_manager_none_quarantine_data_virus() {
 218          $exception = null;
 219          try {
 220              \core\antivirus\manager::scan_data('FOUND');
 221          } catch (\core\antivirus\scanner_exception $ex) {
 222              $exception = $ex;
 223          }
 224          $this->assertNotEmpty($exception);
 225          // No Quarantined files.
 226          $quarantinedfiles = \core\antivirus\quarantine::get_quarantined_files();
 227          $this->assertEquals(0, count($quarantinedfiles));
 228      }
 229  }