MDL-58334 repositories: Offline downloads

Support an optional param for offline downloads for repositories supporting external links (googledrive and skydrive).

Part of MDL-58220
This commit is contained in:
Damyon Wiese 2017-03-21 13:16:29 +08:00
parent fa78244d17
commit d5bb9f1ffc
4 changed files with 57 additions and 39 deletions

View File

@ -3856,9 +3856,11 @@ class curl_cache {
* @param string $relativepath
* @param bool $forcedownload
* @param null|string $preview the preview mode, defaults to serving the original file
* @param boolean $offline If offline is requested - don't serve a redirect to an external file, return a file suitable for viewing
* offline (e.g. mobile app).
* @todo MDL-31088 file serving improments
*/
function file_pluginfile($relativepath, $forcedownload, $preview = null) {
function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false) {
global $DB, $CFG, $USER;
// relative path must start with '/'
if (!$relativepath) {
@ -3882,6 +3884,8 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
$fs = get_file_storage();
$sendfileoptions = ['preview' => $preview, 'offline' => $offline];
// ========================================================================================================================
if ($component === 'blog') {
// Blog file serving
@ -3934,7 +3938,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
send_file_not_found();
}
send_stored_file($file, 10*60, 0, true, array('preview' => $preview)); // download MUST be forced - security!
send_stored_file($file, 10*60, 0, true, $sendfileoptions); // download MUST be forced - security!
// ========================================================================================================================
} else if ($component === 'grade') {
@ -3951,7 +3955,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
//TODO: nobody implemented this yet in grade edit form!!
@ -3968,7 +3972,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
}
@ -3989,7 +3993,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, true, array('preview' => $preview));
send_stored_file($file, 60*60, 0, true, $sendfileoptions);
} else {
send_file_not_found();
@ -4011,14 +4015,14 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close();
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'userbadge' and $context->contextlevel == CONTEXT_USER) {
if (!$file = $fs->get_file($context->id, 'badges', 'userbadge', $badge->id, '/', $filename.'.png')) {
send_file_not_found();
}
\core\session\manager::write_close();
send_stored_file($file, 60*60, 0, true, array('preview' => $preview));
send_stored_file($file, 60*60, 0, true, $sendfileoptions);
}
// ========================================================================================================================
} else if ($component === 'calendar') {
@ -4045,7 +4049,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
@ -4073,7 +4077,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, true, array('preview' => $preview));
send_stored_file($file, 0, 0, true, $sendfileoptions);
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
@ -4120,7 +4124,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
@ -4174,7 +4178,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
send_file($imagefile, basename($imagefile), 60*60*24*14);
}
$options = array('preview' => $preview);
$options = $sendfileoptions;
if (empty($CFG->forcelogin) && empty($CFG->forceloginforprofileimage)) {
// Profile images should be cache-able by both browsers and proxies according
// to $CFG->forcelogin and $CFG->forceloginforprofileimage.
@ -4200,7 +4204,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
@ -4247,7 +4251,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
$userid = (int)array_shift($args);
@ -4285,7 +4289,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
} else if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
require_login();
@ -4306,7 +4310,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
} else {
send_file_not_found();
@ -4339,7 +4343,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
}
@ -4362,7 +4366,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'section') {
if ($CFG->forcelogin) {
@ -4384,7 +4388,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
@ -4413,7 +4417,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
if (($file = $fs->get_file($cohortcontext->id, 'cohort', 'description', $cohort->id, $filepath, $filename))
&& !$file->is_directory()) {
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60 * 60, 0, $forcedownload, $sendfileoptions);
}
}
@ -4445,7 +4449,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'icon') {
$filename = array_pop($args);
@ -4460,7 +4464,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, false, array('preview' => $preview));
send_stored_file($file, 60*60, 0, false, $sendfileoptions);
} else {
send_file_not_found();
@ -4485,7 +4489,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
@ -4504,7 +4508,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 0, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
require_login($course);
@ -4519,7 +4523,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close();
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
require_login($course, false, $cm);
@ -4532,7 +4536,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close();
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
} else if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
// Backup files that were generated by the automated backup systems.
@ -4547,7 +4551,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 0, 0, $forcedownload, $sendfileoptions);
} else {
send_file_not_found();
@ -4556,7 +4560,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
// ========================================================================================================================
} else if ($component === 'question') {
require_once($CFG->libdir . '/questionlib.php');
question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload);
question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload, $sendfileoptions);
send_file_not_found();
// ========================================================================================================================
@ -4593,7 +4597,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
\core\session\manager::write_close(); // Unlock session during file serving.
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
}
// ========================================================================================================================
@ -4625,17 +4629,17 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
}
// finally send the file
send_stored_file($file, null, 0, false, array('preview' => $preview));
send_stored_file($file, null, 0, false, $sendfileoptions);
}
$filefunction = $component.'_pluginfile';
$filefunctionold = $modname.'_pluginfile';
if (function_exists($filefunction)) {
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
} else if (function_exists($filefunctionold)) {
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
}
send_file_not_found();
@ -4676,7 +4680,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
$filefunction = $component.'_pluginfile';
if (function_exists($filefunction)) {
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, $sendfileoptions);
}
send_file_not_found();
@ -4697,7 +4701,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
$filefunction = $component.'_pluginfile';
if (function_exists($filefunction)) {
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
}
send_file_not_found();

View File

@ -33,5 +33,8 @@ require_once('lib/filelib.php');
$relativepath = get_file_argument();
$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
$preview = optional_param('preview', null, PARAM_ALPHANUM);
// Offline means download the file from the repository and serve it, even if it was an external link.
// The repository may have to export the file to an offline format.
$offline = optional_param('offline', 0, PARAM_BOOL);
file_pluginfile($relativepath, $forcedownload, $preview);
file_pluginfile($relativepath, $forcedownload, $preview, $offline);

View File

@ -580,7 +580,7 @@ class repository_googledocs extends repository {
$storedfile->get_filepath(),
$storedfile->get_filename());
if ($info->is_writable()) {
if (empty($options['offline']) && $info->is_writable()) {
// Add the current user as an OAuth writer.
$systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer);
@ -613,7 +613,15 @@ class repository_googledocs extends repository {
$this->add_temp_writer_to_file($systemservice, $source->id, $useremail);
}
if ($source->link) {
if (!empty($options['offline'])) {
$downloaded = $this->get_file($storedfile->get_reference(), $storedfile->get_filename());
$filename = $storedfile->get_filename();
if (isset($downloaded['newfilename'])) {
$filename = $downloaded['newfilename'];
}
send_file($downloaded['path'], $filename, $lifetime, $filter, false, $forcedownload, '', false, $options);
} else if ($source->link) {
redirect($source->link);
} else {
$details = 'File is missing source link';

View File

@ -530,7 +530,7 @@ class repository_skydrive extends repository {
$storedfile->get_filepath(),
$storedfile->get_filename());
if ($info->is_writable()) {
if (empty($options['offline']) && $info->is_writable()) {
// Add the current user as an OAuth writer.
$systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer);
@ -563,7 +563,11 @@ class repository_skydrive extends repository {
$this->add_temp_writer_to_file($systemservice, $source->id, $useremail);
}
if ($source->link) {
if (!empty($options['offline'])) {
$downloaded = $this->get_file($storedfile->get_reference(), $storedfile->get_filename());
$filename = $storedfile->get_filename();
send_file($downloaded['path'], $filename, $lifetime, $filter, false, $forcedownload, '', false, $options);
} else if ($source->link) {
redirect($source->link);
} else {
$details = 'File is missing source link';
@ -820,7 +824,6 @@ class repository_skydrive extends repository {
// then set the permissions so anyone with the share link can view,
// finally update the reference to contain the share link if it was not
// already there (and point to new file id if we copied).
var_dump($reference);
$systemauth = \core\oauth2\api::get_system_oauth_client($this->issuer);
if ($systemauth === false) {