Test version of TeX filter designed for moodle.org
[moodle.git] / filter / tex / tex_filter.php
CommitLineData
c49dede8 1<?PHP
2/////////////////////////////////////////////////////////////////////////////
3// //
4// NOTICE OF COPYRIGHT //
5// //
6// Moodle - Filter for converting TeX expressions to cached gif images //
7// //
8// Copyright (C) 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu //
9// Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca//
10// This program is free software; you can redistribute it and/or modify //
11// it under the terms of the GNU General Public License as published by //
12// the Free Software Foundation; either version 2 of the License, or //
13// (at your option) any later version. //
14// //
15// This program is distributed in the hope that it will be useful, //
16// but WITHOUT ANY WARRANTY; without even the implied warranty of //
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
18// GNU General Public License for more details: //
19// //
20// http://www.gnu.org/copyleft/gpl.html //
21// //
22/////////////////////////////////////////////////////////////////////////////
23//-------------------------------------------------------------------------
24// NOTE: This Moodle text filter converts TeX expressions delimited
25// by either $$...$$ or by <tex...>...</tex> tags to gif images using
26// mimetex.cgi obtained from http://www.forkosh.com/mimetex.html authored by
27// John Forkosh john@forkosh.com. The mimetex.cgi ELF binary compiled for Linux i386
28// is included with this distribution.
29// Note that there may be patent restrictions on the production of gif images
30// in Canada and some parts of Western Europe and Japan until July 2004.
31//-------------------------------------------------------------------------
32// You will then need to edit your moodle/config.php to invoke tex_filter.php
33//-------------------------------------------------------------------------
34
35
36/// Edit these lines to correspond to your installation
37// File path to the directory where mathml_filter.php resides
38 $CFG->filterDirectory = "/var/www/html/moodle1_2d/filter/tex";
39// File paths to the echo binary executable
40 $CFG->echo = "/bin/echo";
41// Frequency with which cache cleanup code is called: 119 means once in 119 times
42// that the filter is invoked
43 $CFG->cacheCleanFreq = 119;
44// Time in seconds after which image gifs which haven't been viewed are considered stale
45// and are scheduled for deletion
46 $CFG->cacheCleanTime = 14*24*3600;
47// Command used to list the oldest cached gif files to be scheduled for deletion, in
48// conjunction with the value of cacheCleanTime
49 $CFG->cleanFiles = "cd ". $CFG->dataroot . "/1/tex_files;/bin/ls -tr | /usr/bin/head -20";
50
51
52/// These lines are important - the variable must match the name
53/// of the actual function below
54 $textfilter_function='tex_filter';
55
56 if (function_exists($textfilter_function)) {
57 return;
58 }
59
60
61function string_file_picture($path, $courseid=0, $height="", $width="", $link="") {
62 // Given the path to a picture file in a course, or a URL,
63 // this function includes the picture in the page.
64 global $CFG;
65 $output = "";
66 if ($height) {
67 $height = "height=\"$height\"";
68 }
69 if ($width) {
70 $width = "width=\"$width\"";
71 }
72 if ($link) {
73 $output .= "<a href=\"$link\">";
74 }
75 if (substr(strtolower($path), 0, 7) == "http://") {
76 $output .= "<img border=\"0\" $height $width src=\"$path\" />";
77
78 } else if ($courseid) {
79 $output .= "<img border=\"0\" $height $width src=\"";
80 if ($CFG->slasharguments) { // Use this method if possible for better caching
81 $output .= "$CFG->wwwroot/file.php/$courseid/$path";
82 } else {
83 $output .= "$CFG->wwwroot/file.php?file=/$courseid/$path";
84 }
85 $output .= "\" />";
86 } else {
87 $output .= "Error: must pass URL or course";
88 }
89 if ($link) {
90 $output .= "</a>";
91 }
92 return $output;
93}
94
95function tex_filter ($courseid, $text) {
96
97 global $CFG;
98 $filterDirectory = $CFG->filterDirectory;
99
100 $scriptname = $_SERVER['SCRIPT_NAME'];
101 if (!strstr($scriptname,'/forum/')) {
102 return $text;
103 }
104 /// Do a quick check using stripos to avoid unnecessary wor
105 if (!preg_match('/<tex/i',$text) && !strstr($text,'$$')) {
106 return $text;
107 }
108
109 if (strstr($scriptname,'post.php')) {
110 $parent = forum_get_post_full($_GET['reply']);
111 $discussion = get_record("forum_discussions","id",$parent->discussion);
112 } else if (strstr($scriptname,'discuss.php')) {
113 $discussion = get_record("forum_discussions","id",$_GET['d'] );
114 } else {
115 return $text;
116 }
117 if ($discussion->forum != 130) {
118 return $text;
119 }
120
121 $old_umask = umask();
122
123 if (!file_exists($CFG->dataroot . "/1/")) {
124 mkdir($CFG->dataroot . "/1/",0775);
125 }
126
127 if (!file_exists($CFG->dataroot . "/1/tex_files/")) {
128 mkdir($CFG->dataroot . "/1/tex_files/",0775);
129 }
130 umask($old_umask);
131 echo "\n<!--$CFG->cleanFiles-->\n";
132 if (isadmin()) { error_reporting (E_ALL); }; //for debugging
133 $timenow = time();
134 if (!($timenow % $CFG->cacheCleanFreq)) {
135 $cleanFiles = explode("\n",`$CFG->cleanFiles`);
136 foreach ($cleanFiles as $cleanFile) {
137 $pathname = $CFG->dataroot . "/1/tex_files/" . $cleanFile;
138 if ($timenow - filemtime($pathname)>$CFG->cacheCleanTime) {
139 unlink($pathname);
140 } else {
141 break;
142 }
143 }
144 }
145
146
147 $text .= ' ';
148 preg_match_all('/\$(\$\$+?)([^\$])/s',$text,$matches);
149 for ($i=0;$i<count($matches[0]);$i++) {
150 $replacement = str_replace('$','&#x00024;',$matches[1][$i]).$matches[2][$i];
151 $text = str_replace($matches[0][$i],$replacement,$text);
152 }
153
154 if (isadmin()) { error_reporting (E_ALL); }; //for debugging
155
156 // <tex> TeX expression </tex>
157 // or $$ TeX expression $$
158
159 preg_match_all('/<tex>(.+?)<\/tex>|\$\$(.+?)\$\$/is', $text, $matches);
160 for ($i=0; $i<count($matches[0]); $i++) {
161 $texexp = $matches[1][$i] . $matches[2][$i];
162 $filename = "tex_files/". md5($texexp) . ".gif";
163 $pathname = $CFG->dataroot . "/1/" . $filename;
164
165 if (file_exists($pathname)) {
166 touch($pathname);
167 $text = str_replace( $matches[0][$i], string_file_picture($filename, 1), $text);
168 } else {
169 $texexp = str_replace('&lt;','<',$texexp);
170 $texexp = str_replace('&gt;','>',$texexp);
171 $texexp = preg_replace('!\r\n?!',' ',$texexp);
172
173 system("QUERY_STRING=;export QUERY_STRING;$filterDirectory/mimetex.cgi -d ". escapeshellarg($texexp) . " >$pathname");
174 $text = str_replace( $matches[0][$i], string_file_picture($filename, 1), $text);
175 }
176
177 }
178 return $text;
179};
180
181
182?>