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