diff --git a/h5p/classes/player.php b/h5p/classes/player.php index 6ef87ab4289..f9d32ab8dfb 100644 --- a/h5p/classes/player.php +++ b/h5p/classes/player.php @@ -348,12 +348,15 @@ class player { $url->remove_params(array_keys($url->params())); $path = $url->out_as_local_url(); + // We only need the slasharguments. + $path = substr($path, strpos($path, '.php/') + 5); $parts = explode('/', $path); $filename = array_pop($parts); - // First is an empty row and then the pluginfile.php part. Both can be ignored. - array_shift($parts); - array_shift($parts); + // If the request is made by tokenpluginfile.php we need to avoid userprivateaccesskey. + if (strpos($this->url, '/tokenpluginfile.php')) { + array_shift($parts); + } // Get the contextid, component and filearea. $contextid = array_shift($parts); $component = array_shift($parts); @@ -515,20 +518,40 @@ class player { */ private function get_export_settings(bool $downloadenabled): ?\moodle_url { - if ( ! $downloadenabled) { + if (!$downloadenabled) { return null; } $systemcontext = \context_system::instance(); $slug = $this->content['slug'] ? $this->content['slug'] . '-' : ''; - $url = \moodle_url::make_pluginfile_url( - $systemcontext->id, - \core_h5p\file_storage::COMPONENT, - \core_h5p\file_storage::EXPORT_FILEAREA, - '', - '', - "{$slug}{$this->content['id']}.h5p" - ); + // We have to build the right URL. + // Depending the request was made through webservice/pluginfile.php or pluginfile.php. + if (strpos($this->url, '/webservice/pluginfile.php')) { + $url = \moodle_url::make_webservice_pluginfile_url( + $systemcontext->id, + \core_h5p\file_storage::COMPONENT, + \core_h5p\file_storage::EXPORT_FILEAREA, + '', + '', + "{$slug}{$this->content['id']}.h5p" + ); + } else { + // If the request is made by tokenpluginfile.php we need to indicates to generate a token for current user. + $includetoken = false; + if (strpos($this->url, '/tokenpluginfile.php')) { + $includetoken = true; + } + $url = \moodle_url::make_pluginfile_url( + $systemcontext->id, + \core_h5p\file_storage::COMPONENT, + \core_h5p\file_storage::EXPORT_FILEAREA, + '', + '', + "{$slug}{$this->content['id']}.h5p", + false, + $includetoken + ); + } return $url; } diff --git a/h5p/tests/external_test.php b/h5p/tests/external_test.php index 9d02199a8d8..b9ae3ca7188 100644 --- a/h5p/tests/external_test.php +++ b/h5p/tests/external_test.php @@ -165,6 +165,124 @@ class core_h5p_external_testcase extends externallib_advanced_testcase { $this->assertEquals(get_string('h5pfilenotfound', 'core_h5p'), $result['warnings'][0]['message']); } + /** + * Test the request to get_trusted_h5p_file + * using webservice/pluginfile.php as url param. + */ + public function test_allow_webservice_pluginfile_in_url_param() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + // This is a valid .H5P file. + $filename = 'find-the-words.h5p'; + $path = __DIR__ . '/fixtures/'.$filename; + $syscontext = \context_system::instance(); + $filerecord = [ + 'contextid' => $syscontext->id, + 'component' => \core_h5p\file_storage::COMPONENT, + 'filearea' => 'unittest', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => $filename, + ]; + // Load the h5p file into DB. + $fs = get_file_storage(); + $file = $fs->create_file_from_pathname($filerecord, $path); + // Make the URL to pass to the WS. + $url = \moodle_url::make_webservice_pluginfile_url( + $syscontext->id, + \core_h5p\file_storage::COMPONENT, + 'unittest', + 0, + '/', + $filename + ); + // Call the WS. + $result = external::get_trusted_h5p_file($url->out(), 0, 0, 0, 0); + $result = external_api::clean_returnvalue(external::get_trusted_h5p_file_returns(), $result); + // Expected result: Just 1 record on files and none on warnings. + $this->assertCount(1, $result['files']); + $this->assertCount(0, $result['warnings']); + // Get the export file in the DB to compare with the ws's results. + $fileh5p = $this->get_export_file($filename, $file->get_pathnamehash()); + $fileh5purl = \moodle_url::make_webservice_pluginfile_url( + $syscontext->id, + \core_h5p\file_storage::COMPONENT, + \core_h5p\file_storage::EXPORT_FILEAREA, + '', + '', + $fileh5p->get_filename() + ); + $this->assertEquals($fileh5p->get_filepath(), $result['files'][0]['filepath']); + $this->assertEquals($fileh5p->get_mimetype(), $result['files'][0]['mimetype']); + $this->assertEquals($fileh5p->get_filesize(), $result['files'][0]['filesize']); + $this->assertEquals($fileh5p->get_timemodified(), $result['files'][0]['timemodified']); + $this->assertEquals($fileh5p->get_filename(), $result['files'][0]['filename']); + $this->assertEquals($fileh5purl->out(), $result['files'][0]['fileurl']); + } + + /** + * Test the request to get_trusted_h5p_file + * using tokenpluginfile.php as url param. + */ + public function test_allow_tokenluginfile_in_url_param() { + global $DB; + $this->resetAfterTest(true); + $this->setAdminUser(); + + // This is a valid .H5P file. + $filename = 'find-the-words.h5p'; + $path = __DIR__ . '/fixtures/'.$filename; + $syscontext = \context_system::instance(); + $filerecord = [ + 'contextid' => $syscontext->id, + 'component' => \core_h5p\file_storage::COMPONENT, + 'filearea' => 'unittest', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => $filename, + ]; + // Load the h5p file into DB. + $fs = get_file_storage(); + $file = $fs->create_file_from_pathname($filerecord, $path); + // Make the URL to pass to the WS. + $url = \moodle_url::make_pluginfile_url( + $syscontext->id, + \core_h5p\file_storage::COMPONENT, + 'unittest', + 0, + '/', + $filename, + false, + true + ); + // Call the WS. + $result = external::get_trusted_h5p_file($url->out(), 0, 0, 0, 0); + $result = external_api::clean_returnvalue(external::get_trusted_h5p_file_returns(), $result); + // Expected result: Just 1 record on files and none on warnings. + $this->assertCount(1, $result['files']); + $this->assertCount(0, $result['warnings']); + // Get the export file in the DB to compare with the ws's results. + $fileh5p = $this->get_export_file($filename, $file->get_pathnamehash()); + $fileh5purl = \moodle_url::make_pluginfile_url( + $syscontext->id, + \core_h5p\file_storage::COMPONENT, + \core_h5p\file_storage::EXPORT_FILEAREA, + '', + '', + $fileh5p->get_filename(), + false, + true + ); + $this->assertEquals($fileh5p->get_filepath(), $result['files'][0]['filepath']); + $this->assertEquals($fileh5p->get_mimetype(), $result['files'][0]['mimetype']); + $this->assertEquals($fileh5p->get_filesize(), $result['files'][0]['filesize']); + $this->assertEquals($fileh5p->get_timemodified(), $result['files'][0]['timemodified']); + $this->assertEquals($fileh5p->get_filename(), $result['files'][0]['filename']); + $this->assertEquals($fileh5purl->out(), $result['files'][0]['fileurl']); + } + /** * Get the H5P export file. *