From d5bb9f1ffca8eb4110881f989421f0a09e9d88b0 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Tue, 21 Mar 2017 13:16:29 +0800 Subject: [PATCH] MDL-58334 repositories: Offline downloads Support an optional param for offline downloads for repositories supporting external links (googledrive and skydrive). Part of MDL-58220 --- lib/filelib.php | 70 ++++++++++++++++++----------------- pluginfile.php | 5 ++- repository/googledocs/lib.php | 12 +++++- repository/skydrive/lib.php | 9 +++-- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index d9e0b0bb414c4..0c314f547bae4 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3856,9 +3856,11 @@ public function refresh() { * @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(); diff --git a/pluginfile.php b/pluginfile.php index 8cc087786ddad..9148b624447b1 100644 --- a/pluginfile.php +++ b/pluginfile.php @@ -33,5 +33,8 @@ $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); diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index 5137d519e3272..0cafa7b0f567b 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -580,7 +580,7 @@ public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownloa $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 @@ public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownloa $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'; diff --git a/repository/skydrive/lib.php b/repository/skydrive/lib.php index 89c3b174559de..569526c58ec35 100644 --- a/repository/skydrive/lib.php +++ b/repository/skydrive/lib.php @@ -530,7 +530,7 @@ public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownloa $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 @@ public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownloa $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 @@ public function reference_file_selected($reference, $context, $component, $filea // 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) {