public function test_manager_get_antivirus() { // We are using clamav plugin in the test, // as the only plugin we know exists for sure. $antivirusviaget = \core\antivirus\manager::get_antivirus('clamav'); $antivirusdirect = new \antivirus_clamav\scanner(); $this->assertEquals($antivirusdirect, $antivirusviaget); }
/** * Do the actual processing of the uploaded file * @param string $saveas_filename name to give to the file * @param int $maxbytes maximum file size * @param mixed $types optional array of file extensions that are allowed or '*' for all * @param string $savepath optional path to save the file to * @param int $itemid optional the ID for this item within the file area * @param string $license optional the license to use for this file * @param string $author optional the name of the author of this file * @param bool $overwriteexisting optional user has asked to overwrite the existing file * @param int $areamaxbytes maximum size of the file area. * @return object containing details of the file uploaded */ public function process_upload($saveas_filename, $maxbytes, $types = '*', $savepath = '/', $itemid = 0, $license = null, $author = '', $overwriteexisting = false, $areamaxbytes = FILE_AREA_MAX_BYTES_UNLIMITED) { global $USER, $CFG; if (is_array($types) and in_array('*', $types) or $types == '*') { $this->mimetypes = '*'; } else { foreach ($types as $type) { $this->mimetypes[] = mimeinfo('type', $type); } } if ($license == null) { $license = $CFG->sitedefaultlicense; } $record = new stdClass(); $record->filearea = 'draft'; $record->component = 'user'; $record->filepath = $savepath; $record->itemid = $itemid; $record->license = $license; $record->author = $author; $context = context_user::instance($USER->id); $elname = 'repo_upload_file'; $fs = get_file_storage(); $sm = get_string_manager(); if ($record->filepath !== '/') { $record->filepath = file_correct_filepath($record->filepath); } if (!isset($_FILES[$elname])) { throw new moodle_exception('nofile'); } if (!empty($_FILES[$elname]['error'])) { switch ($_FILES[$elname]['error']) { case UPLOAD_ERR_INI_SIZE: throw new moodle_exception('upload_error_ini_size', 'repository_upload'); break; case UPLOAD_ERR_FORM_SIZE: throw new moodle_exception('upload_error_form_size', 'repository_upload'); break; case UPLOAD_ERR_PARTIAL: throw new moodle_exception('upload_error_partial', 'repository_upload'); break; case UPLOAD_ERR_NO_FILE: throw new moodle_exception('upload_error_no_file', 'repository_upload'); break; case UPLOAD_ERR_NO_TMP_DIR: throw new moodle_exception('upload_error_no_tmp_dir', 'repository_upload'); break; case UPLOAD_ERR_CANT_WRITE: throw new moodle_exception('upload_error_cant_write', 'repository_upload'); break; case UPLOAD_ERR_EXTENSION: throw new moodle_exception('upload_error_extension', 'repository_upload'); break; default: throw new moodle_exception('nofile'); } } \core\antivirus\manager::scan_file($_FILES[$elname]['tmp_name'], $_FILES[$elname]['name'], true); // {@link repository::build_source_field()} $sourcefield = $this->get_file_source_info($_FILES[$elname]['name']); $record->source = self::build_source_field($sourcefield); if (empty($saveas_filename)) { $record->filename = clean_param($_FILES[$elname]['name'], PARAM_FILE); } else { $ext = ''; $match = array(); $filename = clean_param($_FILES[$elname]['name'], PARAM_FILE); if (strpos($filename, '.') === false) { // File has no extension at all - do not add a dot. $record->filename = $saveas_filename; } else { if (preg_match('/\\.([a-z0-9]+)$/i', $filename, $match)) { if (isset($match[1])) { $ext = $match[1]; } } $ext = !empty($ext) ? $ext : ''; if (preg_match('#\\.(' . $ext . ')$#i', $saveas_filename)) { // saveas filename contains file extension already $record->filename = $saveas_filename; } else { $record->filename = $saveas_filename . '.' . $ext; } } } // Check the file has some non-null contents - usually an indication that a user has // tried to upload a folder by mistake if (!$this->check_valid_contents($_FILES[$elname]['tmp_name'])) { throw new moodle_exception('upload_error_invalid_file', 'repository_upload', '', $record->filename); } if ($this->mimetypes != '*') { // check filetype $filemimetype = file_storage::mimetype($_FILES[$elname]['tmp_name'], $record->filename); if (!in_array($filemimetype, $this->mimetypes)) { throw new moodle_exception('invalidfiletype', 'repository', '', get_mimetype_description(array('filename' => $_FILES[$elname]['name']))); } } if (empty($record->itemid)) { $record->itemid = 0; } if ($maxbytes !== -1 && filesize($_FILES[$elname]['tmp_name']) > $maxbytes) { $maxbytesdisplay = display_size($maxbytes); throw new file_exception('maxbytesfile', (object) array('file' => $record->filename, 'size' => $maxbytesdisplay)); } if (file_is_draft_area_limit_reached($record->itemid, $areamaxbytes, filesize($_FILES[$elname]['tmp_name']))) { throw new file_exception('maxareabytes'); } $record->contextid = $context->id; $record->userid = $USER->id; if (repository::draftfile_exists($record->itemid, $record->filepath, $record->filename)) { $existingfilename = $record->filename; $unused_filename = repository::get_unused_filename($record->itemid, $record->filepath, $record->filename); $record->filename = $unused_filename; $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']); if ($overwriteexisting) { repository::overwrite_existing_draftfile($record->itemid, $record->filepath, $existingfilename, $record->filepath, $record->filename); $record->filename = $existingfilename; } else { $event = array(); $event['event'] = 'fileexists'; $event['newfile'] = new stdClass(); $event['newfile']->filepath = $record->filepath; $event['newfile']->filename = $unused_filename; $event['newfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $unused_filename)->out(false); $event['existingfile'] = new stdClass(); $event['existingfile']->filepath = $record->filepath; $event['existingfile']->filename = $existingfilename; $event['existingfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $existingfilename)->out(false); return $event; } } else { $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']); } return array('url' => moodle_url::make_draftfile_url($record->itemid, $record->filepath, $record->filename)->out(false), 'id' => $record->itemid, 'file' => $record->filename); }
/** * Returns the string equivalent of a numeric clam error code * * @deprecated since Moodle 3.0 - this is a part of clamav plugin now. * @param int $returncode The numeric error code in question. * @return string The definition of the error code */ function get_clam_error_code($returncode) { debugging('get_clam_error_code() is deprecated, please use get_clam_error_code() method of \\antivirus_clamav\\scanner class.', DEBUG_DEVELOPER); $antivirus = \core\antivirus\manager::get_antivirus('clamav'); return $antivirus->get_clam_error_code($returncode); }
/** * Process a message again to add body and attachment data. * * @param \Horde_Imap_Client_Data_Fetch $messagedata The structure and part of the message body * @param \Horde_Mime_Part $partdata The part data * @param string $part The part ID. * @param string $filename The filename of the attachment * @return \stdClass * @throws \core\message\inbound\processing_failed_exception If the attachment can't be saved to disk. */ private function process_message_part_attachment($messagedata, $partdata, $part, $filename) { global $CFG; // If a filename is present, assume that this part is an attachment. $attachment = new \stdClass(); $attachment->filename = $filename; $attachment->type = $partdata->getType(); $attachment->content = $partdata->getContents(); $attachment->charset = $partdata->getCharset(); $attachment->description = $partdata->getDescription(); $attachment->contentid = $partdata->getContentId(); $attachment->filesize = $messagedata->getBodyPartSize($part); if (!empty($CFG->antiviruses)) { mtrace("--> Attempting virus scan of '{$attachment->filename}'"); // Store the file on disk - it will need to be virus scanned first. $itemid = rand(1, 999999999); $directory = make_temp_directory("/messageinbound/{$itemid}", false); $filepath = $directory . "/" . $attachment->filename; if (!($fp = fopen($filepath, "w"))) { // Unable to open the temporary file to write this to disk. mtrace("--> Unable to save the file to disk for virus scanning. Check file permissions."); throw new \core\message\inbound\processing_failed_exception('attachmentfilepermissionsfailed', 'tool_messageinbound'); } fwrite($fp, $attachment->content); fclose($fp); // Perform a virus scan now. try { \core\antivirus\manager::scan_file($filepath, $attachment->filename, true); } catch (\core\antivirus\scanner_exception $e) { mtrace("--> A virus was found in the attachment '{$attachment->filename}'."); $this->inform_attachment_virus(); return; } } return $attachment; }
* @copyright 2015 Ruslan Kabalin, Lancaster University. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../config.php'; require_once $CFG->libdir . '/adminlib.php'; require_once $CFG->libdir . '/tablelib.php'; $action = required_param('action', PARAM_ALPHANUMEXT); $antivirus = required_param('antivirus', PARAM_PLUGIN); $confirm = optional_param('confirm', 0, PARAM_BOOL); $PAGE->set_url('/admin/antiviruses.php', array('action' => $action, 'antivirus' => $antivirus)); $PAGE->set_context(context_system::instance()); require_login(); require_capability('moodle/site:config', context_system::instance()); $returnurl = "{$CFG->wwwroot}/{$CFG->admin}/settings.php?section=manageantiviruses"; // Get currently installed and enabled antivirus plugins. $availableantiviruses = \core\antivirus\manager::get_available(); if (!empty($antivirus) and empty($availableantiviruses[$antivirus])) { redirect($returnurl); } $activeantiviruses = explode(',', $CFG->antiviruses); foreach ($activeantiviruses as $key => $active) { if (empty($availableantiviruses[$active])) { unset($activeantiviruses[$key]); } } if (!confirm_sesskey()) { redirect($returnurl); } switch ($action) { case 'disable': // Remove from enabled list.
/** * Builds the XHTML to display the control * * @param string $data Unused * @param string $query * @return string */ public function output_html($data, $query = '') { global $CFG, $OUTPUT; // Display strings. $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable', 'up', 'down', 'none')); $struninstall = get_string('uninstallplugin', 'core_admin'); $txt->updown = "{$txt->up}/{$txt->down}"; $antivirusesavailable = \core\antivirus\manager::get_available(); $activeantiviruses = explode(',', $CFG->antiviruses); $activeantiviruses = array_reverse($activeantiviruses); foreach ($activeantiviruses as $key => $antivirus) { if (empty($antivirusesavailable[$antivirus])) { unset($activeantiviruses[$key]); } else { $name = $antivirusesavailable[$antivirus]; unset($antivirusesavailable[$antivirus]); $antivirusesavailable[$antivirus] = $name; } } $antivirusesavailable = array_reverse($antivirusesavailable, true); $return = $OUTPUT->heading(get_string('actantivirushdr', 'antivirus'), 3, 'main', true); $return .= $OUTPUT->box_start('generalbox antivirusesui'); $table = new html_table(); $table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings, $struninstall); $table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign'); $table->id = 'antivirusmanagement'; $table->attributes['class'] = 'admintable generaltable'; $table->data = array(); // Iterate through auth plugins and add to the display table. $updowncount = 1; $antiviruscount = count($activeantiviruses); $baseurl = new moodle_url('/admin/antiviruses.php', array('sesskey' => sesskey())); foreach ($antivirusesavailable as $antivirus => $name) { // Hide/show link. $class = ''; if (in_array($antivirus, $activeantiviruses)) { $hideshowurl = $baseurl; $hideshowurl->params(array('action' => 'disable', 'antivirus' => $antivirus)); $hideshowimg = html_writer::img($OUTPUT->pix_url('t/hide'), 'disable', array('class' => 'iconsmall')); $hideshow = html_writer::link($hideshowurl, $hideshowimg); $enabled = true; $displayname = $name; } else { $hideshowurl = $baseurl; $hideshowurl->params(array('action' => 'enable', 'antivirus' => $antivirus)); $hideshowimg = html_writer::img($OUTPUT->pix_url('t/show'), 'enable', array('class' => 'iconsmall')); $hideshow = html_writer::link($hideshowurl, $hideshowimg); $enabled = false; $displayname = $name; $class = 'dimmed_text'; } // Up/down link. $updown = ''; if ($enabled) { if ($updowncount > 1) { $updownurl = $baseurl; $updownurl->params(array('action' => 'up', 'antivirus' => $antivirus)); $updownimg = html_writer::img($OUTPUT->pix_url('t/up'), 'up', array('class' => 'iconsmall')); $updown = html_writer::link($updownurl, $updownimg); } else { $updown .= html_writer::img($OUTPUT->pix_url('spacer'), '', array('class' => 'iconsmall')); } if ($updowncount < $antiviruscount) { $updownurl = $baseurl; $updownurl->params(array('action' => 'down', 'antivirus' => $antivirus)); $updownimg = html_writer::img($OUTPUT->pix_url('t/down'), 'down', array('class' => 'iconsmall')); $updown = html_writer::link($updownurl, $updownimg); } else { $updown .= html_writer::img($OUTPUT->pix_url('spacer'), '', array('class' => 'iconsmall')); } ++$updowncount; } // Settings link. if (file_exists($CFG->dirroot . '/lib/antivirus/' . $antivirus . '/settings.php')) { $eurl = new moodle_url('/admin/settings.php', array('section' => 'antivirussettings' . $antivirus)); $settings = html_writer::link($eurl, $txt->settings); } else { $settings = ''; } $uninstall = ''; if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('antivirus_' . $antivirus, 'manage')) { $uninstall = html_writer::link($uninstallurl, $struninstall); } // Add a row to the table. $row = new html_table_row(array($displayname, $hideshow, $updown, $settings, $uninstall)); if ($class) { $row->attributes['class'] = $class; } $table->data[] = $row; } $return .= html_writer::table($table); $return .= get_string('configantivirusplugins', 'antivirus') . html_writer::empty_tag('br') . get_string('tablenosave', 'admin'); $return .= $OUTPUT->box_end(); return highlight($query, $return); }
/** * Move file from download folder to file pool using FILE API * * @todo MDL-28637 * @static * @param string $thefile file path in download folder * @param stdClass $record * @return array containing the following keys: * icon * file * id * url */ public static function move_to_filepool($thefile, $record) { global $DB, $CFG, $USER, $OUTPUT; // scan for viruses if possible, throws exception if problem found // TODO: MDL-28637 this repository_no_delete is a bloody hack! \core\antivirus\manager::scan_file($thefile, $record->filename, empty($CFG->repository_no_delete)); $fs = get_file_storage(); // If file name being used. if (repository::draftfile_exists($record->itemid, $record->filepath, $record->filename)) { $draftitemid = $record->itemid; $new_filename = repository::get_unused_filename($draftitemid, $record->filepath, $record->filename); $old_filename = $record->filename; // Create a tmp file. $record->filename = $new_filename; $newfile = $fs->create_file_from_pathname($record, $thefile); $event = array(); $event['event'] = 'fileexists'; $event['newfile'] = new stdClass(); $event['newfile']->filepath = $record->filepath; $event['newfile']->filename = $new_filename; $event['newfile']->url = moodle_url::make_draftfile_url($draftitemid, $record->filepath, $new_filename)->out(); $event['existingfile'] = new stdClass(); $event['existingfile']->filepath = $record->filepath; $event['existingfile']->filename = $old_filename; $event['existingfile']->url = moodle_url::make_draftfile_url($draftitemid, $record->filepath, $old_filename)->out(); return $event; } if ($file = $fs->create_file_from_pathname($record, $thefile)) { if (empty($CFG->repository_no_delete)) { $delete = unlink($thefile); unset($CFG->repository_no_delete); } return array('url' => moodle_url::make_draftfile_url($file->get_itemid(), $file->get_filepath(), $file->get_filename())->out(), 'id' => $file->get_itemid(), 'file' => $file->get_filename(), 'icon' => $OUTPUT->pix_url(file_extension_icon($thefile, 32))->out()); } else { return null; } }
break; case UPLOAD_ERR_NO_TMP_DIR: throw new moodle_exception('upload_error_no_tmp_dir', 'repository_upload'); break; case UPLOAD_ERR_CANT_WRITE: throw new moodle_exception('upload_error_cant_write', 'repository_upload'); break; case UPLOAD_ERR_EXTENSION: throw new moodle_exception('upload_error_extension', 'repository_upload'); break; default: throw new moodle_exception('nofile'); } } // Scan for viruses. \core\antivirus\manager::scan_file($_FILES[$fieldname]['tmp_name'], $_FILES[$fieldname]['name'], true); $file = new stdClass(); $file->filename = clean_param($_FILES[$fieldname]['name'], PARAM_FILE); // check system maxbytes setting if ($_FILES[$fieldname]['size'] > get_max_upload_file_size($CFG->maxbytes)) { // oversize file will be ignored, error added to array to notify // web service client $file->errortype = 'fileoversized'; $file->error = get_string('maxbytes', 'error'); } else { $file->filepath = $_FILES[$fieldname]['tmp_name']; // calculate total size of upload $totalsize += $_FILES[$fieldname]['size']; } $files[] = $file; }
public function test_manager_scan_file_virus() { // Run mock scanning without deleting infected file. $this->assertFileExists($this->tempfile); try { \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', false); } catch (\moodle_exception $e) { $this->assertInstanceOf('\\core\\antivirus\\scanner_exception', $e); } // File expected to remain in place. $this->assertFileExists($this->tempfile); // Run mock scanning with deleting infected file. try { \core\antivirus\manager::scan_file($this->tempfile, 'FOUND', true); } catch (\moodle_exception $e) { $this->assertInstanceOf('\\core\\antivirus\\scanner_exception', $e); } // File expected to be deleted. $this->assertFileNotExists($this->tempfile); }