MDL-48846 filter: Stop reffering to invalid moodle.org/download/mimetex
[moodle.git] / filter / tex / texdebug.php
CommitLineData
4317f92f 1<?php
f7f0909c
PS
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 function fetches math. images from the data directory
19 * If not, it obtains the corresponding TeX expression from the cache_tex db table
20 * and uses mimeTeX to create the image file
21 *
22 * @package filter
23 * @subpackage tex
24 * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu
25 * Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 */
9cc17305 28
9cc17305 29 require_once("../../config.php");
30
0662bd67 31 if (!filter_is_enabled('tex')) {
e25b7ded 32 print_error('filternotenabled');
33851b5c 33 }
34
220a90c5 35 require_once($CFG->libdir.'/filelib.php');
36 require_once($CFG->dirroot.'/filter/tex/lib.php');
37 require_once($CFG->dirroot.'/filter/tex/latex.php');
38
39 $action = optional_param('action', '', PARAM_ALPHA);
40 $texexp = optional_param('tex', '', PARAM_RAW);
9cc17305 41
e42398e4 42 require_login();
6ca657a7 43 require_capability('moodle/site:config', context_system::instance(), $USER->id); /// Required cap to run this. MDL-18552
ece1e519
DT
44 if ($action || $texexp) {
45 require_sesskey();
46 }
e42398e4 47
d93a90dc 48 $output = '';
9cc17305 49
d93a90dc 50 // look up in cache if required
220a90c5 51 if ($action=='ShowDB' or $action=='DeleteDB') {
52 $md5 = md5($texexp);
b402e134 53 $texcache = $DB->get_record("cache_filters", array("filter"=>"tex", "md5key"=>$md5));
d93a90dc 54 }
55
56 // Action: Show DB Entry
220a90c5 57 if ($action=='ShowDB') {
d93a90dc 58 if ($texcache) {
220a90c5 59 $output = "DB cache_filters entry for $texexp\n";
d93a90dc 60 $output .= "id = $texcache->id\n";
61 $output .= "filter = $texcache->filter\n";
62 $output .= "version = $texcache->version\n";
63 $output .= "md5key = $texcache->md5key\n";
64 $output .= "rawtext = $texcache->rawtext\n";
65 $output .= "timemodified = $texcache->timemodified\n";
66 } else {
220a90c5 67 $output = "DB cache_filters entry for $texexp not found\n";
623799eb 68 }
d93a90dc 69 }
70
71 // Action: Delete DB Entry
220a90c5 72 if ($action=='DeleteDB') {
d93a90dc 73 if ($texcache) {
220a90c5 74 $output = "Deleting DB cache_filters entry for $texexp\n";
8618fd2a 75 $result = $DB->delete_records("cache_filters", array("id"=>$texcache->id));
d93a90dc 76 if ($result) {
77 $result = 1;
623799eb 78 } else {
d93a90dc 79 $result = 0;
623799eb 80 }
d93a90dc 81 $output .= "Number of records deleted = $result\n";
82 } else {
220a90c5 83 $output = "Could not delete DB cache_filters entry for $texexp\nbecause it could not be found.\n";
9cc17305 84 }
d93a90dc 85 }
86
87 // Action: Show Image
220a90c5 88 if ($action=='ShowImageMimetex') {
89 tex2image($texexp);
d93a90dc 90 }
91
92 // Action: Check Slasharguments
220a90c5 93 if ($action=='SlashArguments') {
94 slasharguments($texexp);
ece1e519 95 exit;
d93a90dc 96 }
97
98 // Action: Show Tex command line output
220a90c5 99 if ($action=='ShowImageTex') {
100 TexOutput($texexp, true);
d93a90dc 101 exit;
102 }
103
104 // Action: Show Tex command line output
220a90c5 105 if ($action=='ShowOutputTex') {
54d08125 106 if (debugging()) {
107 TexOutput($texexp);
108 } else {
109 echo "Can not output detailed information due to security concerns, please turn on debug mode first.";
110 }
d93a90dc 111 exit;
112 }
113
220a90c5 114 if (!empty($action)) {
d93a90dc 115 outputText($output);
116 }
117
118 // nothing more to do if there was any action
220a90c5 119 if (!empty($action)) {
623799eb 120 exit;
9cc17305 121 }
122
123
623799eb 124 function outputText($texexp) {
8a7703ce 125 header("Content-type: text/html; charset=utf-8");
623799eb 126 echo "<html><body><pre>\n";
127 if ($texexp) {
f7f0909c 128 echo s($texexp)."\n\n";
623799eb 129 } else {
130 echo "No text output available\n\n";
131 }
132 echo "</pre></body></html>\n";
133 }
134
9dd9a426 135 function tex2image($texexp, $return=false) {
623799eb 136 global $CFG;
9cc17305 137
220a90c5 138 if (!$texexp) {
139 echo 'No tex expresion specified';
140 return;
623799eb 141 }
220a90c5 142
143 $image = md5($texexp) . ".gif";
144 $filetype = 'image/gif';
145 if (!file_exists("$CFG->dataroot/filter/tex")) {
146 make_upload_directory("filter/tex");
147 }
148 $pathname = "$CFG->dataroot/filter/tex/$image";
149 if (file_exists($pathname)) {
150 unlink($pathname);
151 }
152
153 $texexp = '\Large '.$texexp;
35716b86
PS
154 $commandpath = filter_tex_get_executable(true);
155 $cmd = filter_tex_get_cmd($pathname, $texexp);
220a90c5 156 system($cmd, $status);
157
894ff63f 158 if ($return) {
159 return $image;
9dd9a426 160 }
220a90c5 161
162 if (file_exists($pathname)) {
163 send_file($pathname, $image);
164
54d08125 165 } else if (debugging()) {
623799eb 166 $ecmd = "$cmd 2>&1";
9a58f7cb 167 echo `$ecmd` . "<br />\n";
168 echo "The shell command<br />$cmd<br />returned status = $status<br />\n";
623799eb 169 if ($status == 4) {
9a58f7cb 170 echo "Status corresponds to illegal instruction<br />\n";
623799eb 171 } else if ($status == 11) {
9a58f7cb 172 echo "Status corresponds to bus error<br />\n";
623799eb 173 } else if ($status == 22) {
9a58f7cb 174 echo "Status corresponds to abnormal termination<br />\n";
623799eb 175 }
176 if (file_exists($commandpath)) {
9a58f7cb 177 echo "File size of mimetex executable $commandpath is " . filesize($commandpath) . "<br />";
178 echo "The file permissions are: " . decoct(fileperms($commandpath)) . "<br />";
623799eb 179 if (function_exists("md5_file")) {
9a58f7cb 180 echo "The md5 checksum of the file is " . md5_file($commandpath) . "<br />";
623799eb 181 } else {
182 $handle = fopen($commandpath,"rb");
183 $contents = fread($handle,16384);
184 fclose($handle);
9a58f7cb 185 echo "The md5 checksum of the first 16384 bytes is " . md5($contents) . "<br />";
623799eb 186 }
187 } else {
9a58f7cb 188 echo "mimetex executable $commandpath not found!<br />";
623799eb 189 }
190 echo "Image not found!";
54d08125 191 } else {
192 echo "Can not output detailed information due to security concerns, please turn on debug mode first.";
623799eb 193 }
194 }
ddea4cf0 195
d93a90dc 196
197 // test Tex/Ghostscript output - command execution only
220a90c5 198 function TexOutput($expression, $graphic=false) {
d93a90dc 199 global $CFG;
200 $output = '';
201
202 $latex = new latex();
203
204 // first check if it is likely to work at all
205 $output .= "<h3>Checking executables</h3>\n";
a57a336f 206 $executablesexist = true;
a275c52f 207 $pathlatex = trim(get_config('filter_tex', 'pathlatex'), " '\"");
7a372321
TG
208 if (is_file($pathlatex)) {
209 $output .= "latex executable ($pathlatex) is readable<br />\n";
a57a336f
DT
210 } else {
211 $executablesexist = false;
7a372321 212 $output .= "<b>Error:</b> latex executable ($pathlatex) is not readable<br />\n";
d93a90dc 213 }
a275c52f 214 $pathdvips = trim(get_config('filter_tex', 'pathdvips'), " '\"");
7a372321
TG
215 if (is_file($pathdvips)) {
216 $output .= "dvips executable ($pathdvips) is readable<br />\n";
a57a336f
DT
217 } else {
218 $executablesexist = false;
7a372321 219 $output .= "<b>Error:</b> dvips executable ($pathdvips) is not readable<br />\n";
d93a90dc 220 }
a275c52f 221 $pathconvert = trim(get_config('filter_tex', 'pathconvert'), " '\"");
7a372321
TG
222 if (is_file($pathconvert)) {
223 $output .= "convert executable ($pathconvert) is readable<br />\n";
a57a336f
DT
224 } else {
225 $executablesexist = false;
7a372321 226 $output .= "<b>Error:</b> convert executable ($pathconvert) is not readable<br />\n";
d93a90dc 227 }
a275c52f 228 $pathdvisvgm = trim(get_config('filter_tex', 'pathdvisvgm'), " '\"");
a57a336f
DT
229 if (is_file($pathdvisvgm)) {
230 $output .= "dvisvgm executable ($pathdvisvgm) is readable<br />\n";
231 } else {
232 $executablesexist = false;
233 $output .= "<b>Error:</b> dvisvgm executable ($pathdvisvgm) is not readable<br />\n";
234 }
d93a90dc 235
220a90c5 236 // knowing that it might work..
237 $md5 = md5($expression);
d93a90dc 238 $output .= "<p>base filename for expression is '$md5'</p>\n";
220a90c5 239
d93a90dc 240 // temporary paths
241 $tex = "$latex->temp_dir/$md5.tex";
242 $dvi = "$latex->temp_dir/$md5.dvi";
243 $ps = "$latex->temp_dir/$md5.ps";
7a372321
TG
244 $convertformat = get_config('filter_tex', 'convertformat');
245 $img = "$latex->temp_dir/$md5.{$convertformat}";
d93a90dc 246
247 // put the expression as a file into the temp area
220a90c5 248 $expression = html_entity_decode($expression);
07caf142 249 $output .= "<p>Processing TeX expression:</p><pre>$expression</pre>\n";
220a90c5 250 $doc = $latex->construct_latex_document($expression);
251 $fh = fopen($tex, 'w');
252 fputs($fh, $doc);
253 fclose($fh);
d93a90dc 254
255 // cd to temp dir
220a90c5 256 chdir($latex->temp_dir);
d93a90dc 257
258 // step 1: latex command
a275c52f 259 $pathlatex = escapeshellarg($pathlatex);
7a372321 260 $cmd = "$pathlatex --interaction=nonstopmode --halt-on-error $tex";
220a90c5 261 $output .= execute($cmd);
d93a90dc 262
263 // step 2: dvips command
a275c52f 264 $pathdvips = escapeshellarg($pathdvips);
7a372321 265 $cmd = "$pathdvips -E $dvi -o $ps";
220a90c5 266 $output .= execute($cmd);
d93a90dc 267
a57a336f
DT
268 // Step 3: Set convert or dvisvgm command.
269 if ($convertformat == 'svg') {
a275c52f 270 $pathdvisvgm = escapeshellarg($pathdvisvgm);
a57a336f
DT
271 $cmd = "$pathdvisvgm -E $ps -o $img";
272 } else {
a275c52f 273 $pathconvert = escapeshellarg($pathconvert);
a57a336f
DT
274 $cmd = "$pathconvert -density 240 -trim $ps $img ";
275 }
220a90c5 276 $output .= execute($cmd);
d93a90dc 277
278 if (!$graphic) {
f7f0909c 279 echo $output;
a57a336f 280 } else if (file_exists($img)) {
7a372321 281 send_file($img, "$md5.{$convertformat}");
f7f0909c
PS
282 } else {
283 echo "Error creating image, see command execution output for more details.";
284 }
d93a90dc 285 }
286
220a90c5 287 function execute($cmd) {
288 exec($cmd, $result, $code);
d93a90dc 289 $output = "<pre>$ $cmd\n";
220a90c5 290 $lines = implode("\n", $result);
d93a90dc 291 $output .= "OUTPUT: $lines\n";
292 $output .= "RETURN CODE: $code\n</pre>\n";
293 return $output;
294 }
295
9dd9a426 296 function slasharguments($texexp) {
781cac72 297 global $CFG;
220a90c5 298 $admin = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=http';
9dd9a426 299 $image = tex2image($texexp,true);
781cac72 300 echo "<p>If the following image displays correctly, set your ";
220a90c5 301 echo "<a href=\"$admin\" target=\"_blank\">Administration->Server->HTTP</a> ";
6544f8d8 302 echo "setting for slasharguments to file.php/1/pic.jpg: ";
220a90c5 303 echo "<img src=\"$CFG->wwwroot/filter/tex/pix.php/$image\" align=\"absmiddle\"></p>\n";
6544f8d8 304 echo "<p>Otherwise set it to file.php?file=/1/pic.jpg ";
781cac72 305 echo "It should display correctly as ";
220a90c5 306 echo "<img src=\"$CFG->wwwroot/filter/tex/pix.php?file=$image\" align=\"absmiddle\"></p>\n";
781cac72 307 echo "<p>If neither equation image displays correctly, please seek ";
308 echo "further help at moodle.org at the ";
220a90c5 309 echo "<a href=\"http://moodle.org/mod/forum/view.php?id=752&loginguest=true\" target=\"_blank\">";
781cac72 310 echo "Mathematics Tools Forum</a></p>";
9dd9a426 311 }
312
9cc17305 313?>
314
315<html>
316<head><title>TeX Filter Debugger</title></head>
317<body>
9cc17305 318 <p>Please enter an algebraic expression <b>without</b> any surrounding $$ into
319 the text box below. (Click <a href="#help">here for help.</a>)
320 <form action="texdebug.php" method="get"
321 target="inlineframe">
322 <center>
9a58f7cb 323 <input type="text" name="tex" size="50"
cf4e7548 324 value="f(x)=\int_{-\infty}^x~e^{-t^2}dt" />
9cc17305 325 </center>
d93a90dc 326 <p>The following tests are available:</p>
9cc17305 327 <ol>
54d08125 328 <li><input type="radio" name="action" value="ShowDB" id="ShowDB" />
329 <label for="ShowDB">See the cache_filters database entry for this expression (if any).</label></li>
cf4e7548 330 <li><input type="radio" name="action" value="DeleteDB" id="DeleteDB" />
54d08125 331 <label for="DeleteDB">Delete the cache_filters database entry for this expression (if any).</label></li>
84585f1d 332 <li><input type="radio" name="action" value="ShowImageMimetex" id="ShowImageMimetex" checked="checked" />
54d08125 333 <label for="ShowImageMimetex">Show a graphic image of the algebraic expression rendered with mimetex.</label></li>
334 <li><input type="radio" name="action" value="ShowImageTex" id="ShowImageTex" />
335 <label for="ShowImageTex">Show a graphic image of the algebraic expression rendered with Tex/Ghostscript.</label></li>
336 <li><input type="radio" name="action" value="ShowOutputTex" id="ShowOutputTex" />
337 <label for="ShowOutputTex">Show command execution output from the algebraic expression rendered with Tex/Ghostscript.</label></li>
338 <li><input type="radio" name="action" value="SlashArguments" id="SlashArguments" />
339 <label for="SlashArguments">Check slasharguments setting.</label></li>
9cc17305 340 </ol>
d93a90dc 341 <input type="submit" value="Do it!" />
ece1e519 342 <input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />
9a58f7cb 343 </form> <br /> <br />
9cc17305 344 <center>
345 <iframe name="inlineframe" align="middle" width="80%" height="200">
4317f92f 346 &lt;p&gt;Something is wrong...&lt;/p&gt;
9cc17305 347 </iframe>
9a58f7cb 348 </center> <br />
349<hr />
9cc17305 350<a name="help">
351<h2>Debugging Help</h2>
352</a>
353<p>First a brief overview of how the TeX filter works. The TeX filter first
354searches the database cache_filters table to see if this TeX expression had been
355processed before. If not, it adds a DB entry for that expression. It then
356replaces the TeX expression by an &lt;img src=&quot;.../filter/tex/pix.php...&quot;&gt;
357tag. The filter/tex/pix.php script then searches the database to find an
a57a336f 358appropriate gif/png/svg image file for that expression and to create one if it doesn't exist.
d93a90dc 359It will then use either the LaTex/Ghostscript renderer (using external executables
360on your system) or the bundled Mimetex executable. The full Latex/Ghostscript
4317f92f 361renderer produces better results and is tried first.
9cc17305 362Here are a few common things that can go wrong and some suggestions on how
363you might try to fix them.</p>
364<ol>
365<li>Something had gone wrong on a previous occasion when the filter tried to
366process this expression. Then the database entry for that expression contains
367a bad TeX expression in the rawtext field (usually blank). You can fix this
368by clicking on &quot;Delete DB Entry&quot;</li>
a57a336f 369<li>The TeX to gif/png/svg image conversion process does not work.
d93a90dc 370If paths are specified in the filter configuation screen for the three
371executables these will be tried first. Note that they still must be correctly
4317f92f 372installed and have the correct permissions. In particular make sure that you
d93a90dc 373have all the packages installed (e.g., on Debian/Ubuntu you need to install
374the 'tetex-extra' package). Running the 'show command execution' test should
375give a big clue.
4317f92f 376If this fails or is not available, the Mimetex executable is tried. If this
d93a90dc 377fails a likely cause is that the mimetex binary you are using is
9cc17305 378incompatible with your operating system. You can try compiling it from the
379C sources downloaded from <a href="http://www.forkosh.com/mimetex.zip">
292df9f6 380http://www.forkosh.com/mimetex.zip</a>.
9cc17305 381Another possible problem which may affect
382both Unix and Windows servers is that the web server doesn't have execute permission
383on the mimetex binary. In that case change permissions accordingly</li>
384</ol>
385</body>
386</html>