1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * This file is serving optimised JS and WASM for ogv.js. 19 * 20 * @package media_videojs 21 * @copyright 2021 Huong Nguyen <huongnv13@gmail.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 // Disable moodle specific debug messages and any errors in output, 26 // comment out when debugging or better look into error log! 27 define('NO_DEBUG_DISPLAY', true); 28 29 // We need just the values from config.php and minlib.php. 30 define('ABORT_AFTER_CONFIG', true); 31 require_once('../../../config.php'); // This stops immediately at the beginning of lib/setup.php. 32 require_once($CFG->dirroot . '/lib/jslib.php'); 33 require_once($CFG->dirroot . '/lib/wasmlib.php'); 34 35 $slashargument = min_get_slash_argument(); 36 if (!$slashargument) { 37 // The above call to min_get_slash_argument should always work. 38 die('Invalid request'); 39 } 40 41 $slashargument = ltrim($slashargument, '/'); 42 if (substr_count($slashargument, '/') < 1) { 43 header('HTTP/1.0 404 not found'); 44 die('Slash argument must contain both a revision and a file path'); 45 } 46 47 // Get all the library files (js and wasm) of the OGV. 48 $basepath = $CFG->dirroot . '/media/player/videojs/ogvjs/'; 49 $jsfiles = []; 50 $files = glob("{$basepath}*.{js,wasm}", GLOB_BRACE); 51 foreach ($files as $file) { 52 $jsfiles[] = basename($file); 53 } 54 55 // Split into revision and module name. 56 list($rev, $file) = explode('/', $slashargument, 2); 57 $rev = min_clean_param($rev, 'INT'); 58 $file = min_clean_param($file, 'SAFEPATH'); 59 60 if (empty($jsfiles) || !in_array($file, $jsfiles)) { 61 // We can't find the requested file. 62 header('HTTP/1.0 404 not found'); 63 exit(0); 64 } 65 66 // Check if the requesting file is Javascript or Web Assembly. 67 $iswasm = media_videojs_ogvloader_is_wasm_file($file); 68 69 // Use the caching only for meaningful revision numbers which prevents future cache poisoning. 70 if ($rev > 0 and $rev < (time() + 60 * 60)) { 71 // We are lazy loading a single file - so include the filename in the etag. 72 $etag = sha1($rev . '/' . $file); 73 $candidate = $CFG->localcachedir . '/ogvloader/' . $etag; 74 75 if (file_exists($candidate)) { 76 // Cache exist. 77 if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 78 // We do not actually need to verify the etag value because our files 79 // never change in cache because we increment the rev parameter. 80 media_videojs_ogvloader_send_unmodified($iswasm, $candidate, $etag); 81 } 82 media_videojs_ogvloader_send_cached($iswasm, $candidate, $etag); 83 exit(0); 84 } else { 85 // Cache does not exist. Create one. 86 $filecontent = file_get_contents($basepath . $file); 87 if ($filecontent === false) { 88 error_log('Failed to load the library ' . $file); 89 $filecontent = "/* Failed to load library file {$file}. */\n"; 90 } 91 92 $filecontent = media_videojs_ogvloader_add_module_module_name_if_necessary($iswasm, $filecontent); 93 media_videojs_ogvloader_write_cache_file_content($iswasm, $candidate, $filecontent); 94 // Verify nothing failed in cache file creation. 95 clearstatcache(); 96 if (file_exists($candidate)) { 97 media_videojs_ogvloader_send_cached($iswasm, $candidate, $etag); 98 exit(0); 99 } 100 } 101 } 102 103 // If we've made it here then we're in "dev mode" where everything is lazy loaded. 104 // So all files will be served one at a time. 105 $filecontent = file_get_contents($basepath . $file); 106 $filecontent = rtrim($filecontent); 107 $filecontent = media_videojs_ogvloader_add_module_module_name_if_necessary($iswasm, $filecontent); 108 media_videojs_ogvloader_send_uncached($iswasm, $filecontent); 109 110 /** 111 * Check the given file is a Web Assembly file or not 112 * 113 * @param string $filename File name to check 114 * @return bool Whether the file is Web Assembly or not 115 */ 116 function media_videojs_ogvloader_is_wasm_file(string $filename): bool { 117 $ext = pathinfo($filename, PATHINFO_EXTENSION); 118 return $ext == 'wasm'; 119 } 120 121 /** 122 * Add Moodle module name to the Javascript module if necessary 123 * 124 * @param bool $iswasm Whether the file is Web Assembly or not 125 * @param string $content File content 126 * @return string 127 */ 128 function media_videojs_ogvloader_add_module_module_name_if_necessary(bool $iswasm, string $content): string { 129 if (!$iswasm && preg_match('/define\(\s*(\[|function)/', $content)) { 130 // If the JavaScript module has been defined without specifying a name then we'll 131 // add the Moodle module name now. 132 $replace = 'define(\'media_videojs/video-lazy\', '; 133 $search = 'define('; 134 // Replace only the first occurrence. 135 $content = implode($replace, explode($search, $content, 2)); 136 } 137 138 return $content; 139 } 140 141 /** 142 * Create cache file content 143 * 144 * @param bool $iswasm Whether the file is Web Assembly or not 145 * @param string $candidate Full file path to cache file 146 * @param string $filecontent File content 147 */ 148 function media_videojs_ogvloader_write_cache_file_content(bool $iswasm, string $candidate, string $filecontent): void { 149 $iswasm ? wasm_write_cache_file_content($candidate, $filecontent) : js_write_cache_file_content($candidate, $filecontent); 150 } 151 152 /** 153 * Send file content with as much caching as possible 154 * 155 * @param bool $iswasm Whether the file is Web Assembly or not 156 * @param string $candidate Full file path to cache file 157 * @param string $etag Etag 158 */ 159 function media_videojs_ogvloader_send_cached(bool $iswasm, string $candidate, string $etag): void { 160 $iswasm ? wasm_send_cached($candidate, $etag, 'ogvloader.php') : js_send_cached($candidate, $etag, 'ogvloader.php'); 161 } 162 163 /** 164 * Send file without any caching 165 * 166 * @param bool $iswasm Whether the file is Web Assembly or not 167 * @param string $ilecontent File content 168 */ 169 function media_videojs_ogvloader_send_uncached(bool $iswasm, string $ilecontent): void { 170 $iswasm ? wasm_send_uncached($ilecontent, 'ogvloader.php') : js_send_uncached($ilecontent, 'ogvloader.php'); 171 } 172 173 /** 174 * Send the file not modified headers 175 * 176 * @param bool $iswasm Whether the file is Web Assembly or not 177 * @param int $candidate Full file path to cache file 178 * @param string $etag Etag 179 */ 180 function media_videojs_ogvloader_send_unmodified(bool $iswasm, int $candidate, string $etag): void { 181 $iswasm ? wasm_send_unmodified(filemtime($candidate), $etag) : js_send_unmodified(filemtime($candidate), $etag); 182 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body