/** * 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); }
} break; case 'upload': // handle exception here instead moodle default exception handler // see MDL-23407 try { // TODO: add file scanning MDL-19380 into each plugin $result = $repo->upload($saveas_filename, $maxbytes); echo json_encode($result); } catch (Exception $e) { $err->error = $e->getMessage(); echo json_encode($err); die; } break; case 'overwrite': // existing file $filepath = required_param('existingfilepath', PARAM_PATH); $filename = required_param('existingfilename', PARAM_FILE); // user added file which needs to replace the existing file $newfilepath = required_param('newfilepath', PARAM_PATH); $newfilename = required_param('newfilename', PARAM_FILE); echo json_encode(repository::overwrite_existing_draftfile($itemid, $filepath, $filename, $newfilepath, $newfilename)); break; case 'deletetmpfile': // delete tmp file $newfilepath = required_param('newfilepath', PARAM_PATH); $newfilename = required_param('newfilename', PARAM_FILE); echo json_encode(repository::delete_tempfile_from_draft($itemid, $newfilepath, $newfilename)); break; }
$info = repository::move_to_filepool($downloadedfile['path'], $record); if (empty($info)) { $info['e'] = get_string('error', 'moodle'); } } } echo json_encode($info); die; } break; case 'upload': $result = $repo->upload($saveas_filename, $maxbytes); echo json_encode($result); break; case 'overwrite': // existing file $filepath = required_param('existingfilepath', PARAM_PATH); $filename = required_param('existingfilename', PARAM_FILE); // user added file which needs to replace the existing file $newfilepath = required_param('newfilepath', PARAM_PATH); $newfilename = required_param('newfilename', PARAM_FILE); $info = repository::overwrite_existing_draftfile($itemid, $filepath, $filename, $newfilepath, $newfilename); echo json_encode($info); break; case 'deletetmpfile': // delete tmp file $newfilepath = required_param('newfilepath', PARAM_PATH); $newfilename = required_param('newfilename', PARAM_FILE); echo json_encode(repository::delete_tempfile_from_draft($itemid, $newfilepath, $newfilename)); break; }
// Extract archive and move all files from $temppath to $filepath if ($file->extract_to_storage($zipper, $user_context->id, 'user', 'draft', $draftid, $temppath, $USER->id) !== false) { $extractedfiles = $fs->get_directory_files($user_context->id, 'user', 'draft', $draftid, $temppath, true); $xtemppath = preg_quote($temppath, '|'); foreach ($extractedfiles as $file) { $realpath = preg_replace('|^'.$xtemppath.'|', $filepath, $file->get_filepath()); if (!$file->is_directory()) { // Set the source to the extracted file to indicate that it came from archive. $file->set_source(serialize((object)array('source' => $filepath))); } if (!$fs->file_exists($user_context->id, 'user', 'draft', $draftid, $realpath, $file->get_filename())) { // File or directory did not exist, just move it. $file->rename($realpath, $file->get_filename()); } else if (!$file->is_directory()) { // File already existed, overwrite it repository::overwrite_existing_draftfile($draftid, $realpath, $file->get_filename(), $file->get_filepath(), $file->get_filename()); } else { // Directory already existed, remove temporary dir but make sure we don't remove the existing dir $doremovedirs[] = $file->get_filepath(); $donotremovedirs[] = $realpath; } } $return = new stdClass(); $return->filepath = $filepath; } else { $return = false; } // Remove remaining temporary directories. foreach (array_diff($doremovedirs, $donotremovedirs) as $filepath) { if ($file = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $filepath, '.')) { $file->delete();