Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

269 lines (239 sloc) 10.623 kb
<?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/>.
/**
* This plugin is used to upload files
*
* @since 2.0
* @package repository_upload
* @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/repository/lib.php');
/**
* A repository plugin to allow user uploading files
*
* @since 2.0
* @package repository_upload
* @copyright 2009 Dongsheng Cai {@link http://dongsheng.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_upload extends repository {
private $mimetypes = array();
/**
* Print a upload form
* @return array
*/
public function print_login() {
return $this->get_listing();
}
/**
* Process uploaded file
* @return array|bool
*/
public function upload($saveas_filename, $maxbytes) {
global $CFG;
$types = optional_param_array('accepted_types', '*', PARAM_RAW);
$savepath = optional_param('savepath', '/', PARAM_PATH);
$itemid = optional_param('itemid', 0, PARAM_INT);
$license = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
$author = optional_param('author', '', PARAM_TEXT);
return $this->process_upload($saveas_filename, $maxbytes, $types, $savepath, $itemid, $license, $author);
}
/**
* 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
* @return object containing details of the file uploaded
*/
public function process_upload($saveas_filename, $maxbytes, $types = '*', $savepath = '/', $itemid = 0, $license = null, $author = '') {
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 = get_context_instance(CONTEXT_USER, $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');
}
}
// scan the files, throws exception and deletes if virus found
// this is tricky because clamdscan daemon might not be able to access the files
$permissions = fileperms($_FILES[$elname]['tmp_name']);
@chmod($_FILES[$elname]['tmp_name'], $CFG->filepermissions);
self::antivir_scan_file($_FILES[$elname]['tmp_name'], $_FILES[$elname]['name'], true);
@chmod($_FILES[$elname]['tmp_name'], $permissions);
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 (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']);
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)) {
throw new file_exception('maxbytes');
}
$record->contextid = $context->id;
$record->userid = $USER->id;
$record->source = '';
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']);
$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);
}
}
/**
* Checks the contents of the given file is not completely NULL - this can happen if a
* user drags & drops a folder onto a filemanager / filepicker element
* @param string $filepath full path (including filename) to file to check
* @return true if file has at least one non-null byte within it
*/
protected function check_valid_contents($filepath) {
$buffersize = 4096;
$fp = fopen($filepath, 'r');
if (!$fp) {
return false; // Cannot read the file - something has gone wrong
}
while (!feof($fp)) {
// Read the file 4k at a time
$data = fread($fp, $buffersize);
if (preg_match('/[^\0]+/', $data)) {
fclose($fp);
return true; // Return as soon as a non-null byte is found
}
}
// Entire file is NULL
fclose($fp);
return false;
}
/**
* Return a upload form
* @return array
*/
public function get_listing($path = '', $page = '') {
global $CFG;
$ret = array();
$ret['nologin'] = true;
$ret['nosearch'] = true;
$ret['norefresh'] = true;
$ret['list'] = array();
$ret['dynload'] = false;
$ret['upload'] = array('label'=>get_string('attachment', 'repository'), 'id'=>'repo-form');
$ret['allowcaching'] = true; // indicates that result of get_listing() can be cached in filepicker.js
return $ret;
}
/**
* supported return types
* @return int
*/
public function supported_returntypes() {
return FILE_INTERNAL;
}
}
Jump to Line
Something went wrong with that request. Please try again.