From d96a1acc0b1e84e3659e14f3cde65969e5985e4e Mon Sep 17 00:00:00 2001 From: mjollnir_ Date: Tue, 12 Aug 2008 13:17:34 +0000 Subject: [PATCH] MDL-15777 more fixes for portfolio to use file api this introduces portfolio/file.php to serve portfolio related files - access check is delegated to the plugin. and also two new classes in the portfolio plugin tree - push vs pull. --- lang/en_utf8/portfolio.php | 6 ++- lib/portfoliolib.php | 78 ++++++++++++++++++++++++--------- portfolio/add.php | 11 ----- portfolio/file.php | 27 ++++++++++++ portfolio/type/boxnet/lib.php | 2 +- portfolio/type/download/lib.php | 44 +++++++++---------- 6 files changed, 112 insertions(+), 56 deletions(-) create mode 100644 portfolio/file.php diff --git a/lang/en_utf8/portfolio.php b/lang/en_utf8/portfolio.php index 71fd96005b..23c808ef8f 100644 --- a/lang/en_utf8/portfolio.php +++ b/lang/en_utf8/portfolio.php @@ -2,7 +2,7 @@ $string['addnewportfolio'] = 'Add a new portfolio'; $string['addtoportfolio'] = 'Add to portfolio'; -$string['alreadyexporting'] = 'You already have an active portfolio export in this session. Please complete that first'; +$string['alreadyexporting'] = 'You already have an active portfolio export in this session. Please complete that first, or click here to cancel it.'; $string['availableformats'] = 'Available export formats'; $string['callercouldnotpackage'] = 'Failed to package up your data for export'; $string['cannotsetvisible'] = 'Cannot set this to visible - the plugin has been completely disabled because of a misconfiguration'; @@ -23,6 +23,8 @@ $string['exportcomplete'] = 'Portfolio export complete!'; $string['exportqueued'] = 'Portfolio export has been successfully queued for transfer'; $string['exportedpreviously'] = 'Previous exports'; $string['failedtosendpackage'] = 'Failed to send your data to the selected portfolio system!'; +$string['filedenied'] = 'Access denied to this file'; +$string['filenotfound'] = 'File not found'; $string['format_file'] = 'File'; $string['format_mbkp'] = 'Moodle Backup'; $string['hidden'] = 'Hidden'; @@ -31,7 +33,7 @@ $string['instanceismisconfigured'] = 'Portfolio instance is misconfigured, skipp $string['instancenotsaved'] = 'Failed to save portfolio'; $string['instancenotdelete'] = 'Failed to delete portfolio'; $string['instancesaved'] = 'Portfolio saved successfully'; -$string['invalidtempid'] = 'Invalid temporary id'; +$string['invalidtempid'] = 'Invalid export id. maybe it has expired'; $string['invalidformat'] = 'Something is exporting an invalid format, $a'; $string['invalidinstance'] = 'Could not find that portfolio instance'; $string['manageportfolios'] = 'Manage portfolios'; diff --git a/lib/portfoliolib.php b/lib/portfoliolib.php index 1c2f5b9955..f670a38c31 100644 --- a/lib/portfoliolib.php +++ b/lib/portfoliolib.php @@ -155,7 +155,7 @@ function portfolio_add_button($callbackclass, $callbackargs, $callbackfile=null, } if (isset($SESSION->portfolioexport)) { - print_error('alreadyexporting', 'portfolio'); + print_error('alreadyexporting', 'portfolio', null, $CFG->wwwroot . '/portfolio/add.php?cancel=1'); } if (empty($callbackfile)) { @@ -889,6 +889,15 @@ abstract class portfolio_plugin_base { */ public abstract function expected_time($callertime); + /** + * is this plugin push or pill. + * if push, cleanup will be called directly after send_package + * if not, cleanup will be called after portfolio/file.php is requested + * + * @return boolean + */ + public abstract function is_push(); + /** * check sanity of plugin * if this function returns something non empty, ALL instances of your plugin @@ -1427,6 +1436,38 @@ abstract class portfolio_plugin_base { } } +/** +* class to inherit from for 'push' type plugins +*/ +abstract class portfolio_plugin_push_base extends portfolio_plugin_base { + + public function is_push() { + return true; + } +} + +/** +* class to inherit from for 'pull' type plugins +*/ +abstract class portfolio_plugin_pull_base extends portfolio_plugin_base { + + private $file; + + public function is_push() { + return false; + } + + + /** + * before sending the file when the pull is requested, verify the request parameters + * these might include a token of some sort of whatever + * + * @param array request parameters (POST wins over GET) + */ + public abstract function verify_file_request_params($params); + +} + /** * this is the form that is actually used while exporting. * plugins and callers don't get to define their own class @@ -1698,7 +1739,6 @@ final class portfolio_exporter { if (!$alreadystolen && $url = $this->instance->steal_control($stage)) { $this->set('stage', $stage); $this->save(); - //$SESSION->portfolio->stagepresteal = $stage; redirect($url); break; } @@ -1754,8 +1794,6 @@ final class portfolio_exporter { */ public function process_stage_config() { - //global $SESSION; - $pluginobj = $callerobj = null; if ($this->instance->has_export_config()) { $pluginobj = $this->instance; @@ -1789,11 +1827,6 @@ final class portfolio_exporter { $mform = new portfolio_export_form('', $customdata); if ($mform->is_cancelled()){ $this->cancel_request(); - /* - unset($SESSION->portfolio); - redirect($this->caller->get_return_url()); - exit; - */ } else if ($fromform = $mform->get_data()){ if (!confirm_sesskey()) { return $this->raise_error('confirmsesskeybad', '', $caller->get_return_url()); @@ -1939,8 +1972,13 @@ final class portfolio_exporter { * * @return boolean whether or not to process the next stage. this is important as the control function is called recursively. */ - public function process_stage_cleanup() { + public function process_stage_cleanup($pullok=false) { global $CFG, $DB, $SESSION; + + if (!$pullok && !$this->get('instance')->is_push()) { + unset($SESSION->portfolioexport); + return true; + } // @todo maybe add a hook in the plugin(s) $DB->delete_records('portfolio_tempdata', array('id' => $this->id)); $fs = get_file_storage(); @@ -1979,7 +2017,6 @@ final class portfolio_exporter { * @return boolean whether or not to process the next stage. this is important as the control function is called recursively. */ public function process_stage_finished($queued=false) { - //global $SESSION; $returnurl = $this->caller->get_return_url(); $continueurl = $this->instance->get_continue_url(); $extras = $this->instance->get_extra_finish_options(); @@ -2002,7 +2039,6 @@ final class portfolio_exporter { } } print_footer(); - //unset($SESSION->portfolio); return false; } @@ -2024,24 +2060,22 @@ final class portfolio_exporter { * error handler - decides whether we're running interactively or not * and behaves accordingly */ - public function raise_error($string, $module='moodle', $continue=null) { + public function raise_error($string, $module='moodle', $continue=null, $a=null) { if (defined('FULLME') && FULLME == 'cron') { debugging(get_string($string, $module)); return false; } if (isset($this)) { - $this->process_stage_cleanup(); + $this->process_stage_cleanup(true); } - //global $SESSION; - //unset($SESSION->portfolio); - print_error($string, $module, $continue); + print_error($string, $module, $continue, $a); } public function cancel_request() { if (!isset($this)) { return; } - $this->process_stage_cleanup(); + $this->process_stage_cleanup(true); redirect($this->caller->get_return_url()); exit; } @@ -2066,7 +2100,7 @@ final class portfolio_exporter { public static function rewaken_object($id) { global $DB, $CFG; if (!$data = $DB->get_record('portfolio_tempdata', array('id' => $id))) { - portfolio_exporer::raise_error('invalidtempid', 'portfolio'); + portfolio_exporter::raise_error('invalidtempid', 'portfolio'); } $exporter = unserialize(base64_decode($data->data)); if ($exporter->instancefile) { @@ -2121,7 +2155,11 @@ final class portfolio_exporter { if (empty($files)) { return array(); } - return $files; + $returnfiles = array(); + foreach ($files as $f) { + $returnfiles[$f->get_filename()] = $f; + } + return $returnfiles; } /** diff --git a/portfolio/add.php b/portfolio/add.php index e467be1983..c2de922b7c 100644 --- a/portfolio/add.php +++ b/portfolio/add.php @@ -19,11 +19,6 @@ if ($dataid) { $exporter = portfolio_exporter::rewaken_object($dataid); if ($cancel = optional_param('cancel', 0, PARAM_RAW)) { $exporter->cancel_request(); - /* - $returnurl = $exporter->get('caller')->get_return_url(); - unset($SESSION->portfolio); - redirect($returnurl); - */ } if (!$exporter->get('instance')) { if ($instance = optional_param('instance', '', PARAM_INT)) { @@ -105,12 +100,6 @@ if (!$exporter->get('instance')) { $mform = new portfolio_instance_select('', array('caller' => $exporter->get('caller'))); if ($mform->is_cancelled()) { $exporter->cancel_request(); - /* - $returnurl = $caller->get_return_url(); - unset($SESSION->portfolio); - redirect($returnurl); - exit; - */ } else if ($fromform = $mform->get_data()){ redirect($CFG->wwwroot . '/portfolio/add.php?instance=' . $fromform->instance . '&id=' . $exporter->get('id')); exit; diff --git a/portfolio/file.php b/portfolio/file.php new file mode 100644 index 0000000000..b53c9f560a --- /dev/null +++ b/portfolio/file.php @@ -0,0 +1,27 @@ +libdir . '/portfoliolib.php'); +require_once($CFG->libdir . '/file/stored_file.php'); +require_once($CFG->libdir . '/filelib.php'); + +$id = required_param('id', PARAM_INT); + +$exporter = portfolio_exporter::rewaken_object($id); + +if ($exporter->get('instance')->is_push()) { + $exporter->raise_error('filedenied', 'portfolio'); +} + +if (!$exporter->get('instance')->verify_file_request_params(array_merge($_GET, $_POST))) { + $exporter->raise_error('filedenied', 'portfolio'); +} + +$file = $exporter->get('instance')->get('file'); +if (!($file instanceof stored_file)) { + $exporter->raise_error('filenotfound', 'portfolio'); +} + +send_stored_file($file, 0, 0, true, null, true); +$exporter->process_stage_cleanup(true); + +?> diff --git a/portfolio/type/boxnet/lib.php b/portfolio/type/boxnet/lib.php index bd4d67c26f..471ea50b26 100644 --- a/portfolio/type/boxnet/lib.php +++ b/portfolio/type/boxnet/lib.php @@ -2,7 +2,7 @@ require_once($CFG->libdir.'/filelib.php'); require_once($CFG->dirroot.'/repository/boxnet/boxlibphp5.php'); -class portfolio_plugin_boxnet extends portfolio_plugin_base { +class portfolio_plugin_boxnet extends portfolio_plugin_push_base { private $boxclient; private $ticket; diff --git a/portfolio/type/download/lib.php b/portfolio/type/download/lib.php index 1c8678f36e..524671f952 100644 --- a/portfolio/type/download/lib.php +++ b/portfolio/type/download/lib.php @@ -1,10 +1,11 @@ libdir . '/portfoliolib.php'); +require_once($CFG->libdir . '/packer/zip_packer.php'); -class portfolio_plugin_download extends portfolio_plugin_base { +class portfolio_plugin_download extends portfolio_plugin_pull_base { - protected $zipfile; + protected $file; protected $exportconfig; public static function allows_multiple() { @@ -16,20 +17,16 @@ class portfolio_plugin_download extends portfolio_plugin_base { } public function prepare_package() { - // just zip up whatever files the caller has created for us - // and move them to the user's temporary area. - $userdir = temp_portfolio_usertemp_directory($this->get('user')->id); - - $newfile = 'portfolio_export_' . time() . '.zip'; - $files = get_directory_list($tempdir); - foreach ($files as $key => $file) { - $files[$key] = $tempdir . '/' . $file; - } - zip_files($files, $userdir . '/' . $newfile); - $this->set('zipfile', $newfile); + $files = $this->exporter->get_tempfiles(); + $zipper = new zip_packer(); - return true; + $filename = 'portfolio-export.zip'; + if ($newfile = $zipper->archive_to_storage($files, SYSCONTEXTID, 'portfolio_exporter', $this->exporter->get('id'), '/final/', $filename, $this->user->id)) { + $this->set('file', $newfile); + return true; + } + return false; } public function send_package() { @@ -38,18 +35,21 @@ class portfolio_plugin_download extends portfolio_plugin_base { public function get_extra_finish_options() { global $CFG; - return array( - // @todo this will go through files api later, this is a (nonworking) hack for now. - $CFG->wwwroot . '/file.php?file=' . $this->zipfile => get_string('downloadfile', 'portfolio_download'), - ); + return array($CFG->wwwroot . '/portfolio/file.php?id=' . $this->exporter->get('id') => get_string('downloadfile', 'portfolio_download')); } - public function get_continue_url() { - return false; + public function verify_file_request_params($params) { + // for download plugin the only thing we need to verify is that + // the logged in user is the same as the exporting user + global $USER; + if ($USER->id != $this->user->id) { + return false; + } + return true; } - public static function plugin_sanity_check() { - return 'notupgradedtousefilesapi'; + public function get_continue_url() { + return false; } } -- 2.39.5