Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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 * TeX filter library functions. 19 * 20 * @package filter 21 * @subpackage tex 22 * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu 23 * Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 function filter_tex_get_executable($debug=false) { 30 global $CFG; 31 32 if ((PHP_OS == "WINNT") || (PHP_OS == "WIN32") || (PHP_OS == "Windows")) { 33 return "$CFG->dirroot/filter/tex/mimetex.exe"; 34 } 35 36 if ($pathmimetex = get_config('filter_tex', 'pathmimetex')) { 37 if (is_executable($pathmimetex)) { 38 return $pathmimetex; 39 } else { 40 print_error('mimetexnotexecutable', 'error'); 41 } 42 } 43 44 $custom_commandpath = "$CFG->dirroot/filter/tex/mimetex"; 45 if (file_exists($custom_commandpath)) { 46 if (is_executable($custom_commandpath)) { 47 return $custom_commandpath; 48 } else { 49 print_error('mimetexnotexecutable', 'error'); 50 } 51 } 52 53 switch (PHP_OS) { 54 case "Linux": return "$CFG->dirroot/filter/tex/mimetex.linux"; 55 case "Darwin": return "$CFG->dirroot/filter/tex/mimetex.darwin"; 56 case "FreeBSD": return "$CFG->dirroot/filter/tex/mimetex.freebsd"; 57 } 58 59 print_error('mimetexisnotexist', 'error'); 60 } 61 62 /** 63 * Check the formula expression against the list of denied keywords. 64 * 65 * List of allowed could be more complete but also harder to maintain. 66 * 67 * @param string $texexp Formula expression to check. 68 * @return string Formula expression with denied keywords replaced with 'forbiddenkeyword'. 69 */ 70 function filter_tex_sanitize_formula(string $texexp): string { 71 72 $denylist = [ 73 'include', 'command', 'loop', 'repeat', 'open', 'toks', 'output', 74 'input', 'catcode', 'name', '^^', 75 '\def', '\edef', '\gdef', '\xdef', 76 '\every', '\errhelp', '\errorstopmode', '\scrollmode', '\nonstopmode', 77 '\batchmode', '\read', '\write', 'csname', '\newhelp', '\uppercase', 78 '\lowercase', '\relax', '\aftergroup', 79 '\afterassignment', '\expandafter', '\noexpand', '\special', 80 '\let', '\futurelet', '\else', '\fi', '\chardef', '\makeatletter', '\afterground', 81 '\noexpand', '\line', '\mathcode', '\item', '\section', '\mbox', '\declarerobustcommand', 82 ]; 83 84 $allowlist = ['inputenc']; 85 86 // Prepare the denylist for regular expression. 87 $denylist = array_map(function($value){ 88 return '/' . preg_quote($value, '/') . '/i'; 89 }, $denylist); 90 91 // Prepare the allowlist for regular expression. 92 $allowlist = array_map(function($value){ 93 return '/\bforbiddenkeyword_(' . preg_quote($value, '/') . ')\b/i'; 94 }, $allowlist); 95 96 // First, mangle all denied words. 97 $texexp = preg_replace_callback($denylist, 98 function($matches) { 99 return 'forbiddenkeyword_' . $matches[0]; 100 }, 101 $texexp 102 ); 103 104 // Then, change back the allowed words. 105 $texexp = preg_replace_callback($allowlist, 106 function($matches) { 107 return $matches[1]; 108 }, 109 $texexp 110 ); 111 112 return $texexp; 113 } 114 115 function filter_tex_get_cmd($pathname, $texexp) { 116 $texexp = filter_tex_sanitize_formula($texexp); 117 $texexp = escapeshellarg($texexp); 118 $executable = filter_tex_get_executable(false); 119 120 if ((PHP_OS == "WINNT") || (PHP_OS == "WIN32") || (PHP_OS == "Windows")) { 121 $executable = str_replace(' ', '^ ', $executable); 122 return "$executable ++ -e \"$pathname\" -- $texexp"; 123 124 } else { 125 return "\"$executable\" -e \"$pathname\" -- $texexp"; 126 } 127 } 128 129 /** 130 * Purge all caches when settings changed. 131 */ 132 function filter_tex_updatedcallback($name) { 133 global $CFG, $DB; 134 reset_text_filters_cache(); 135 136 if (file_exists("$CFG->dataroot/filter/tex")) { 137 remove_dir("$CFG->dataroot/filter/tex"); 138 } 139 if (file_exists("$CFG->dataroot/filter/algebra")) { 140 remove_dir("$CFG->dataroot/filter/algebra"); 141 } 142 if (file_exists("$CFG->tempdir/latex")) { 143 remove_dir("$CFG->tempdir/latex"); 144 } 145 146 $DB->delete_records('cache_filters', array('filter'=>'tex')); 147 $DB->delete_records('cache_filters', array('filter'=>'algebra')); 148 149 $pathlatex = get_config('filter_tex', 'pathlatex'); 150 if ($pathlatex === false) { 151 // detailed settings not present yet 152 return; 153 } 154 155 $pathlatex = trim($pathlatex, " '\""); 156 $pathdvips = trim(get_config('filter_tex', 'pathdvips'), " '\""); 157 $pathconvert = trim(get_config('filter_tex', 'pathconvert'), " '\""); 158 $pathdvisvgm = trim(get_config('filter_tex', 'pathdvisvgm'), " '\""); 159 160 $supportedformats = array('gif'); 161 if ((is_file($pathlatex) && is_executable($pathlatex)) && 162 (is_file($pathdvips) && is_executable($pathdvips))) { 163 if (is_file($pathconvert) && is_executable($pathconvert)) { 164 $supportedformats[] = 'png'; 165 } 166 if (is_file($pathdvisvgm) && is_executable($pathdvisvgm)) { 167 $supportedformats[] = 'svg'; 168 } 169 } 170 if (!in_array(get_config('filter_tex', 'convertformat'), $supportedformats)) { 171 set_config('convertformat', array_pop($supportedformats), 'filter_tex'); 172 } 173 174 } 175
title
Description
Body
title
Description
Body
title
Description
Body
title
Body