| 1 | #!/usr/local/bin/webwork-perl |
1 | |
| 2 | |
2 | |
| 3 | |
3 | |
| 4 | #################################################################### |
4 | #################################################################### |
| 5 | # Copyright @ 1995-1999 University of Rochester |
5 | # Copyright @ 1995-1999 University of Rochester |
| 6 | # All Rights Reserved |
6 | # All Rights Reserved |
| 7 | #################################################################### |
7 | #################################################################### |
| 8 | |
8 | |
| 9 | #################################################################### |
9 | #################################################################### |
| 10 | # |
10 | # |
| 11 | # dangerousMacros.pl contains macros with potentially dangerous commands |
11 | # dangerousMacros.pl contains macros with potentially dangerous commands |
| 12 | # such as require and eval. They can reference disk files for reading and |
12 | # such as require and eval. They can reference disk files for reading and |
| 13 | # writing and can create links. It may be necessary to modify certain addresses |
13 | # writing and can create links. It may be necessary to modify certain addresses |
| 14 | # in this file to make the scripts run in different environments. |
14 | # in this file to make the scripts run in different environments. |
| 15 | # |
15 | # |
| 16 | # |
16 | # |
| 17 | |
17 | |
| … | |
… | |
| 20 | dangerousMacros.pl --- located in the courseScripts directory |
20 | dangerousMacros.pl --- located in the courseScripts directory |
| 21 | |
21 | |
| 22 | =head1 SYNPOSIS |
22 | =head1 SYNPOSIS |
| 23 | |
23 | |
| 24 | loadMacros(macrofile1,macrofile2,...) |
24 | loadMacros(macrofile1,macrofile2,...) |
| 25 | |
25 | |
| 26 | insertGraph(graphObject); |
26 | insertGraph(graphObject); |
| 27 | returns a path to the file containing the graph image. |
27 | returns a path to the file containing the graph image. |
| 28 | |
28 | |
| 29 | tth(texString) |
29 | tth(texString) |
| 30 | returns an HTML version of the tex code passed to it. |
30 | returns an HTML version of the tex code passed to it. |
| 31 | |
31 | |
| 32 | alias(pathToFile); |
32 | alias(pathToFile); |
| 33 | returns URL which links to that file |
33 | returns URL which links to that file |
| 34 | |
34 | |
| 35 | |
35 | |
| 36 | =head1 DESCRIPTION |
36 | =head1 DESCRIPTION |
| 37 | |
37 | |
| 38 | |
38 | |
| 39 | C<dangerousMacros.pl> contains macros with potentially dangerous commands |
39 | C<dangerousMacros.pl> contains macros with potentially dangerous commands |
| 40 | such as require and eval. They can reference disk files for reading and |
40 | such as require and eval. They can reference disk files for reading and |
| 41 | writing and can create links. It may be necessary to modify certain addresses |
41 | writing and can create links. It may be necessary to modify certain addresses |
| 42 | in this file to make the scripts run properly in different environments. |
42 | in this file to make the scripts run properly in different environments. |
| 43 | |
43 | |
| 44 | C<dangerousMacros.pl> is loaded and reinitialized |
44 | C<dangerousMacros.pl> is loaded and reinitialized |
| 45 | every time a new problem is rendered. |
45 | every time a new problem is rendered. |
| … | |
… | |
| 62 | |
62 | |
| 63 | |
63 | |
| 64 | The following considerations come into play. |
64 | The following considerations come into play. |
| 65 | |
65 | |
| 66 | * One needs to limit the access to modules for safety -- hence only |
66 | * One needs to limit the access to modules for safety -- hence only |
| 67 | modules in the F<courseScriptsDirectory> can be loaded. |
67 | modules in the F<courseScriptsDirectory> can be loaded. |
| 68 | |
68 | |
| 69 | * Loading them in dangerousMacros.pl is wasteful, since the modules |
69 | * Loading them in dangerousMacros.pl is wasteful, since the modules |
| 70 | would need to be reloaded everytime a new safe compartment is created. |
70 | would need to be reloaded everytime a new safe compartment is created. |
| 71 | (I believe that using require takes care of this.) |
71 | (I believe that using require takes care of this.) |
| 72 | |
72 | |
| 73 | * Loading GD within a safeCompartment creates infinite recurrsion in AUTOLOAD (probably a bug) |
73 | * Loading GD within a safeCompartment creates infinite recurrsion in AUTOLOAD (probably a bug) |
| 74 | hence this module is loaded by translate.pl and then shared with |
74 | hence this module is loaded by translate.pl and then shared with |
| 75 | the safe compartment. |
75 | the safe compartment. |
| 76 | |
76 | |
| 77 | * Other modules loaded by translate.pl are C<Exporter> and C<DynaLoader. |
77 | * Other modules loaded by translate.pl are C<Exporter> and C<DynaLoader. |
| 78 | |
78 | |
| 79 | * PGrandom is loaded by F<PG.pl> , since it is needed there. |
79 | * PGrandom is loaded by F<PG.pl> , since it is needed there. |
| 80 | |
80 | |
| 81 | |
81 | |
| 82 | |
82 | |
| 83 | The module name spaces loaded in dangerousMacros are: |
83 | The module name spaces loaded in dangerousMacros are: |
| 84 | |
84 | |
| 85 | PGrandom (if not previously loaded) |
85 | PGrandom (if not previously loaded) |
| 86 | WWPlot |
86 | WWPlot |
| 87 | Fun |
87 | Fun |
| 88 | Label |
88 | Label |
| 89 | Circle |
89 | Circle |
| 90 | |
90 | |
| 91 | in addition the subroutine &evaluate_units is shared from the module Units. |
91 | in addition the subroutine &evaluate_units is shared from the module Units. |
| 92 | |
92 | |
| 93 | =cut |
93 | =cut |
| 94 | |
94 | |
| 95 | BEGIN { |
95 | BEGIN { |
| 96 | be_strict(); # an alias for use strict. This means that all global variable must contain main:: as a prefix. |
96 | be_strict(); # an alias for use strict. This means that all global variable must contain main:: as a prefix. |
| 97 | |
97 | |
| 98 | } |
98 | } |
| 99 | |
99 | |
| 100 | |
100 | |
| 101 | sub _dangerousMacros_init { |
101 | sub _dangerousMacros_init { |
| 102 | } |
102 | } |
| … | |
… | |
| 125 | directory of the course C<($macroDirectory)> and then, if not found, in the WeBWorK courseScripts |
125 | directory of the course C<($macroDirectory)> and then, if not found, in the WeBWorK courseScripts |
| 126 | directory C<($courseScriptsDirectory)> where the default behavior of the PG language is defined. |
126 | directory C<($courseScriptsDirectory)> where the default behavior of the PG language is defined. |
| 127 | |
127 | |
| 128 | An individual course can modify the PG language, B<for that course only>, by |
128 | An individual course can modify the PG language, B<for that course only>, by |
| 129 | duplicating one of the macro files in the courseScripts directory and placing this |
129 | duplicating one of the macro files in the courseScripts directory and placing this |
| 130 | file in the macro directory for the course. The new file in the course |
130 | file in the macro directory for the course. The new file in the course |
| 131 | macro directory will now be used instead of the file in the courseScripts directory. |
131 | macro directory will now be used instead of the file in the courseScripts directory. |
| 132 | |
132 | |
| 133 | The new file in the course macro directory can by modified by adding macros or modifying existing macros. |
133 | The new file in the course macro directory can by modified by adding macros or modifying existing macros. |
| 134 | |
134 | |
| 135 | I< Modifying macros is for users with some experience.> |
135 | I< Modifying macros is for users with some experience.> |
| 136 | |
136 | |
| 137 | Modifying existing macros might break other standard macros or problems which depend on the |
137 | Modifying existing macros might break other standard macros or problems which depend on the |
| 138 | unmodified behavior of these macors so do this with great caution. |
138 | unmodified behavior of these macors so do this with great caution. |
| 139 | In addition problems which use new macros defined in these files or which depend on the |
139 | In addition problems which use new macros defined in these files or which depend on the |
| 140 | modified behavior of existing macros will not work in other courses unless the macros are also |
140 | modified behavior of existing macros will not work in other courses unless the macros are also |
| 141 | transferred to the new course. It helps to document the problems by indicating any special macros |
141 | transferred to the new course. It helps to document the problems by indicating any special macros |
| 142 | which the problems require. |
142 | which the problems require. |
| 143 | |
143 | |
| 144 | There is no facility for modifying or overloading a single macro. The entire file containing the macro |
144 | There is no facility for modifying or overloading a single macro. The entire file containing the macro |
| … | |
… | |
| 155 | # ${main::macroDirectory} |
155 | # ${main::macroDirectory} |
| 156 | # ${main::courseScriptsDirectory} |
156 | # ${main::courseScriptsDirectory} |
| 157 | # Global macros used |
157 | # Global macros used |
| 158 | # None |
158 | # None |
| 159 | |
159 | |
| 160 | # Because of the need to use the directory variables it is tricky to define this |
160 | # Because of the need to use the directory variables it is tricky to define this |
| 161 | # in translate.pl since, as currently written, the directories are not available |
161 | # in translate.pl since, as currently written, the directories are not available |
| 162 | # at that time. Perhaps if I rewrite translate as an object that method will work. |
162 | # at that time. Perhaps if I rewrite translate as an object that method will work. |
| 163 | |
163 | |
| 164 | # The only difficulty with defining loadMacros inside the Safe compartment is that |
164 | # The only difficulty with defining loadMacros inside the Safe compartment is that |
| 165 | # the error reporting does not work with syntax errors. |
165 | # the error reporting does not work with syntax errors. |
| 166 | # A kludge using require works around this problem |
166 | # A kludge using require works around this problem |
| … | |
… | |
| 169 | my ($macroDirectory, |
169 | my ($macroDirectory, |
| 170 | $courseScriptsDirectory, |
170 | $courseScriptsDirectory, |
| 171 | $templateDirectory, |
171 | $templateDirectory, |
| 172 | $scriptDirectory, |
172 | $scriptDirectory, |
| 173 | ); |
173 | ); |
| 174 | |
174 | |
| 175 | sub loadMacros { |
175 | sub loadMacros { |
| 176 | my @files = @_; |
176 | my @files = @_; |
| 177 | my $fileName; |
177 | my $fileName; |
| 178 | ############################################################################### |
178 | ############################################################################### |
| 179 | # At this point the directories have been defined from %envir and we can define |
179 | # At this point the directories have been defined from %envir and we can define |
| … | |
… | |
| 183 | $macroDirectory = eval('$main::macroDirectory') unless defined($macroDirectory); |
183 | $macroDirectory = eval('$main::macroDirectory') unless defined($macroDirectory); |
| 184 | $courseScriptsDirectory = eval('$main::courseScriptsDirectory') unless defined($courseScriptsDirectory); |
184 | $courseScriptsDirectory = eval('$main::courseScriptsDirectory') unless defined($courseScriptsDirectory); |
| 185 | $templateDirectory = eval('$main::courseScriptsDirectory') unless defined($templateDirectory); |
185 | $templateDirectory = eval('$main::courseScriptsDirectory') unless defined($templateDirectory); |
| 186 | $scriptDirectory = eval('$main::scriptDirectory') unless defined($scriptDirectory); |
186 | $scriptDirectory = eval('$main::scriptDirectory') unless defined($scriptDirectory); |
| 187 | |
187 | |
| 188 | unless (defined( $main::externalTTHPath) and $main::externalTTHPath) { |
188 | unless (defined( $main::externalTTHPath) and $main::externalTTHPath) { |
| 189 | warn "WARNING::Please make sure that the DOCUMENT() statement comes before<BR>\n" . |
189 | warn "WARNING::Please make sure that the DOCUMENT() statement comes before<BR>\n" . |
| 190 | " the loadMacros() statement in the problem template.<p>" . |
190 | " the loadMacros() statement in the problem template.<p>" . |
| 191 | " The externalTTHPath variable |$main::externalTTHPath| was\n". |
191 | " The externalTTHPath variable |$main::externalTTHPath| was\n". |
| 192 | " not defined which usually indicates the problem above.<br>\n"; |
192 | " not defined which usually indicates the problem above.<br>\n"; |
| 193 | |
193 | |
| 194 | } |
194 | } |
| 195 | #warn "running load macros"; |
195 | #warn "running load macros"; |
| 196 | while (@files) { |
196 | while (@files) { |
| 197 | $fileName = shift @files; |
197 | $fileName = shift @files; |
| 198 | next if ($fileName =~ /^PG.pl$/) ; # the PG.pl macro package is already loaded. |
198 | next if ($fileName =~ /^PG.pl$/) ; # the PG.pl macro package is already loaded. |
| 199 | |
199 | |
| 200 | my $macro_file_name = $fileName; |
200 | my $macro_file_name = $fileName; |
| 201 | $macro_file_name =~s/\.pl//; # trim off the extension |
201 | $macro_file_name =~s/\.pl//; # trim off the extension |
| 202 | $macro_file_name =~s/\.pg//; # sometimes the extension is .pg (e.g. CAPA files) |
202 | $macro_file_name =~s/\.pg//; # sometimes the extension is .pg (e.g. CAPA files) |
| 203 | my $init_subroutine_name = "_${macro_file_name}_init"; |
203 | my $init_subroutine_name = "_${macro_file_name}_init"; |
| 204 | my $macro_file_loaded; |
204 | my $macro_file_loaded; |
| … | |
… | |
| 215 | ############################################################################### |
215 | ############################################################################### |
| 216 | |
216 | |
| 217 | local($temp::rf_init_subroutine); |
217 | local($temp::rf_init_subroutine); |
| 218 | eval qq{ \$temp::rf_init_subroutine = \\&main::$init_subroutine_name;}; |
218 | eval qq{ \$temp::rf_init_subroutine = \\&main::$init_subroutine_name;}; |
| 219 | #warn "loadMacros: defining \$temp::rf_init_subroutine ",$temp::rf_init_subroutine; |
219 | #warn "loadMacros: defining \$temp::rf_init_subroutine ",$temp::rf_init_subroutine; |
| 220 | |
220 | |
| 221 | $macro_file_loaded = defined($temp::rf_init_subroutine) && defined( &{$temp::rf_init_subroutine} ); |
221 | $macro_file_loaded = defined($temp::rf_init_subroutine) && defined( &{$temp::rf_init_subroutine} ); |
| 222 | |
222 | |
| 223 | # macros are searched for first in the $macroDirectory of the course |
223 | # macros are searched for first in the $macroDirectory of the course |
| 224 | # and then in the webwork $courseScripts directory. |
224 | # and then in the webwork $courseScripts directory. |
| 225 | unless ($macro_file_loaded) { |
225 | unless ($macro_file_loaded) { |
| 226 | #print STDERR "loadMacros: loading macro file $fileName\n"; |
226 | #print STDERR "loadMacros: loading macro file $fileName\n"; |
| 227 | if (-r "${main::macroDirectory}$fileName") { |
227 | if (-r "${main::macroDirectory}$fileName") { |
| 228 | compile_file("${main::macroDirectory}$fileName"); |
228 | compile_file("${main::macroDirectory}$fileName"); |
| 229 | |
229 | |
| 230 | } elsif (-r "${main::courseScriptsDirectory}$fileName" ) { |
230 | } elsif (-r "${main::courseScriptsDirectory}$fileName" ) { |
| 231 | compile_file("${main::courseScriptsDirectory}$fileName"); |
231 | compile_file("${main::courseScriptsDirectory}$fileName"); |
| 232 | } else { |
232 | } else { |
| 233 | die "Can't locate macro file via path: |${main::macroDirectory}$fileName| or |${main::courseScriptsDirectory}$fileName|"; |
233 | die "Can't locate macro file via path: |${main::macroDirectory}$fileName| or |${main::courseScriptsDirectory}$fileName|"; |
| 234 | } |
234 | } |
| 235 | } |
235 | } |
| 236 | # Try again to define the initialization subroutine. |
236 | # Try again to define the initialization subroutine. |
| … | |
… | |
| 240 | if ( defined($temp::rf_init_subroutine) and defined( &{$temp::rf_init_subroutine} ) ) { |
240 | if ( defined($temp::rf_init_subroutine) and defined( &{$temp::rf_init_subroutine} ) ) { |
| 241 | #print " &$init_subroutine_name defined = ", $macro_file_loaded,"\n"; |
241 | #print " &$init_subroutine_name defined = ", $macro_file_loaded,"\n"; |
| 242 | &{$temp::rf_init_subroutine}(); #initialize file |
242 | &{$temp::rf_init_subroutine}(); #initialize file |
| 243 | #print "initializing $init_subroutine_name\n"; |
243 | #print "initializing $init_subroutine_name\n"; |
| 244 | } |
244 | } |
| 245 | |
245 | |
| 246 | } |
246 | } |
| 247 | } |
247 | } |
| 248 | |
248 | |
| 249 | # errors in compiling macros is not always being reported. |
249 | # errors in compiling macros is not always being reported. |
| 250 | sub compile_file { |
250 | sub compile_file { |
| … | |
… | |
| 256 | my $string = <MACROFILE>; |
256 | my $string = <MACROFILE>; |
| 257 | my ($result,$error,$fullerror) = PG_restricted_eval($string); |
257 | my ($result,$error,$fullerror) = PG_restricted_eval($string); |
| 258 | if ($error) { # the $fullerror report has formatting and is never empty |
258 | if ($error) { # the $fullerror report has formatting and is never empty |
| 259 | $fullerror =~ s/\(eval \d+\)/ $filePath\n/; # attempt to insert file name instead of eval number |
259 | $fullerror =~ s/\(eval \d+\)/ $filePath\n/; # attempt to insert file name instead of eval number |
| 260 | die "Error detected while loading $filePath:\n$fullerror"; |
260 | die "Error detected while loading $filePath:\n$fullerror"; |
| 261 | |
261 | |
| 262 | } |
262 | } |
| 263 | |
263 | |
| 264 | close(MACROFILE); |
264 | close(MACROFILE); |
| 265 | |
265 | |
| 266 | } |
266 | } |
| 267 | |
267 | |
| 268 | # This creates on the fly graphs |
268 | # This creates on the fly graphs |
| 269 | |
269 | |
| 270 | =head2 insertGraph |
270 | =head2 insertGraph |
| 271 | |
271 | |
| 272 | $filePath = insertGraph(graphObject); |
272 | $filePath = insertGraph(graphObject); |
| 273 | returns a path to the file containing the graph image. |
273 | returns a path to the file containing the graph image. |
| 274 | |
274 | |
| 275 | insertGraph(graphObject) writes a gif file to the C<html/tmp/gif> directory of the current course. |
275 | insertGraph(graphObject) writes a gif file to the C<html/tmp/gif> directory of the current course. |
| 276 | The file name |
276 | The file name |
| 277 | is obtained from the graphObject. Warnings are issued if errors occur while writing to |
277 | is obtained from the graphObject. Warnings are issued if errors occur while writing to |
| 278 | the file. |
278 | the file. |
| 279 | |
279 | |
| 280 | The permissions and ownership of the file are controlled by C<$main::tmp_file_permission> |
280 | The permissions and ownership of the file are controlled by C<$main::tmp_file_permission> |
| 281 | and C<$main::numericalGroupID>. |
281 | and C<$main::numericalGroupID>. |
| 282 | |
282 | |
| 283 | B<Returns:> A string containing the full path to the temporary file containing the GIF image. |
283 | B<Returns:> A string containing the full path to the temporary file containing the GIF image. |
| … | |
… | |
| 285 | |
285 | |
| 286 | |
286 | |
| 287 | InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$gifName.gif (or .png)" where |
287 | InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$gifName.gif (or .png)" where |
| 288 | the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure |
288 | the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure |
| 289 | that the correct directory separators are used for the platform and that the necessary directories |
289 | that the correct directory separators are used for the platform and that the necessary directories |
| 290 | are created if they are not already present. |
290 | are created if they are not already present. |
| 291 | |
291 | |
| 292 | The directory address to the file is the result. This is most often used in the construct |
292 | The directory address to the file is the result. This is most often used in the construct |
| 293 | |
293 | |
| 294 | TEXT(alias(insertGraph($graph)) ); |
294 | TEXT(alias(insertGraph($graph)) ); |
| 295 | |
295 | |
| 296 | where alias converts the directory address to a URL when serving HTML pages and insures that |
296 | where alias converts the directory address to a URL when serving HTML pages and insures that |
| 297 | an eps file is generated when creating TeX code for downloading. |
297 | an eps file is generated when creating TeX code for downloading. |
| 298 | |
298 | |
| 299 | =cut |
299 | =cut |
| 300 | |
300 | |
| 301 | # Global variables used: |
301 | # Global variables used: |
| 302 | # $main::tmp_file_permission, |
302 | # $main::tmp_file_permission, |
| 303 | # $main::numericalGroupID |
303 | # $main::numericalGroupID |
| 304 | |
304 | |
| 305 | #Global macros used: |
305 | #Global macros used: |
| 306 | # &convertPath |
306 | # &convertPath |
| 307 | # &surePathToTmpFile |
307 | # &surePathToTmpFile |
| 308 | |
308 | |
| 309 | sub insertGraph { |
309 | sub insertGraph { |
| 310 | # Convert the image to GIF and print it on standard output |
310 | # Convert the image to GIF and print it on standard output |
| 311 | my $graph = shift; |
311 | my $graph = shift; |
| 312 | my $extension = ($WWPlot::use_png) ? '.png' : '.gif'; |
312 | my $extension = ($WWPlot::use_png) ? '.png' : '.gif'; |
| 313 | my $fileName = $graph->imageName . $extension; |
313 | my $fileName = $graph->imageName . $extension; |
| 314 | my $filePath = convertPath("gif/$fileName"); |
314 | my $filePath = convertPath("gif/$fileName"); |
| 315 | $filePath = &surePathToTmpFile( $filePath ); |
315 | $filePath = &surePathToTmpFile( $filePath ); |
| 316 | #createFile($filePath, $main::tmp_file_permission, $main::numericalGroupID); |
316 | #createFile($filePath, $main::tmp_file_permission, $main::numericalGroupID); |
| 317 | local(*OUTPUT); # create local file handle so it won't overwrite other open files. |
317 | local(*OUTPUT); # create local file handle so it won't overwrite other open files. |
| 318 | open(OUTPUT, ">$filePath")||warn ("$0","Can't open $filePath<BR>",""); |
318 | open(OUTPUT, ">$filePath")||warn ("$0","Can't open $filePath<BR>",""); |
| … | |
… | |
| 327 | =head2 tth |
327 | =head2 tth |
| 328 | |
328 | |
| 329 | tth(texString) |
329 | tth(texString) |
| 330 | returns an HTML version of the tex code passed to it. |
330 | returns an HTML version of the tex code passed to it. |
| 331 | |
331 | |
| 332 | This macro sends the texString to the filter program C<tth> created by Ian Hutchinson. |
332 | This macro sends the texString to the filter program C<tth> created by Ian Hutchinson. |
| 333 | The tth program was created by Ian Hutchinson and is freely available |
333 | The tth program was created by Ian Hutchinson and is freely available |
| 334 | for B<non-commerical purposes> at the C<tth> main site: C<http://hutchinson.belmont.ma.us/tth/>. |
334 | for B<non-commerical purposes> at the C<tth> main site: C<http://hutchinson.belmont.ma.us/tth/>. |
| 335 | |
335 | |
| 336 | The purpose of C<tth> is to translate text in the TeX or Latex markup language into |
336 | The purpose of C<tth> is to translate text in the TeX or Latex markup language into |
| 337 | HTML markup as best as possible. Some symbols, such as square root symbols are not |
337 | HTML markup as best as possible. Some symbols, such as square root symbols are not |
| 338 | translated completely. Macintosh users must use the "MacRoman" encoding (available in 4.0 and |
338 | translated completely. Macintosh users must use the "MacRoman" encoding (available in 4.0 and |
| … | |
… | |
| 347 | on C<tth> is available at the C<tth> main site. |
347 | on C<tth> is available at the C<tth> main site. |
| 348 | |
348 | |
| 349 | This macro contains code which is system dependent and may need to be modified |
349 | This macro contains code which is system dependent and may need to be modified |
| 350 | to run on different systems. |
350 | to run on different systems. |
| 351 | |
351 | |
| 352 | =for html |
352 | =for html |
| 353 | The link to <CODE>tth</CODE> for <STRONG>non-commerical</STRONG> is |
353 | The link to <CODE>tth</CODE> for <STRONG>non-commerical</STRONG> is |
| 354 | <A HREF="http://hutchinson.belmont.ma.us/tth/">http://hutchinson.belmont.ma.us/tth/</A>. |
354 | <A HREF="http://hutchinson.belmont.ma.us/tth/">http://hutchinson.belmont.ma.us/tth/</A>. |
| 355 | Binaries for many operating systems are available as well as the source code. Links |
355 | Binaries for many operating systems are available as well as the source code. Links |
| 356 | describing how to obtain <CODE>tth</CODE> for commerical use are also available on this page. |
356 | describing how to obtain <CODE>tth</CODE> for commerical use are also available on this page. |
| 357 | |
357 | |
| 358 | =cut |
358 | =cut |
| … | |
… | |
| 369 | |
369 | |
| 370 | my ($tthPreambleFile, $tthPreambleContents); # the contents of this file will not change during problem compilation |
370 | my ($tthPreambleFile, $tthPreambleContents); # the contents of this file will not change during problem compilation |
| 371 | # it only needs to be read once |
371 | # it only needs to be read once |
| 372 | sub tth { |
372 | sub tth { |
| 373 | my $inputString = shift; |
373 | my $inputString = shift; |
| 374 | |
374 | |
| 375 | # read the contents of the tthPreamble.tex file, unless it has already been read |
375 | # read the contents of the tthPreamble.tex file, unless it has already been read |
| 376 | unless ( defined( $tthPreambleContents) ) { |
376 | unless ( defined( $tthPreambleContents) ) { |
| 377 | $tthPreambleFile = "${main::templateDirectory}tthPreamble.tex" if ( -r "${main::templateDirectory}tthPreamble.tex" ); |
377 | $tthPreambleFile = "${main::templateDirectory}tthPreamble.tex" if ( -r "${main::templateDirectory}tthPreamble.tex" ); |
| 378 | if ( defined($tthPreambleFile) ) { |
378 | if ( defined($tthPreambleFile) ) { |
| 379 | local(*TTHIN); |
379 | local(*TTHIN); |
| 380 | open (TTHIN, "${main::templateDirectory}tthPreamble.tex") || die "Can't open file ${main::templateDirectory}tthPreamble.tex"; |
380 | open (TTHIN, "${main::templateDirectory}tthPreamble.tex") || die "Can't open file ${main::templateDirectory}tthPreamble.tex"; |
| 381 | #my @tthPreambleArray = <TTHIN>; |
381 | #my @tthPreambleArray = <TTHIN>; |
| 382 | local($/); |
382 | local($/); |
| 383 | $/ = undef; |
383 | $/ = undef; |
| 384 | $tthPreambleContents = <TTHIN>;#join("",@tthPreambleArray); |
384 | $tthPreambleContents = <TTHIN>;#join("",@tthPreambleArray); |
| 385 | close(TTHIN); |
385 | close(TTHIN); |
| 386 | |
386 | |
| 387 | $tthPreambleContents =~ s/(.)\n/$1%\n/g; # thanks to Jim Martino |
387 | $tthPreambleContents =~ s/(.)\n/$1%\n/g; # thanks to Jim Martino |
| 388 | # each line in the definition file |
388 | # each line in the definition file |
| 389 | # should end with a % to prevent |
389 | # should end with a % to prevent |
| 390 | # adding supurious paragraphs to output. |
390 | # adding supurious paragraphs to output. |
| 391 | |
391 | |
| 392 | $tthPreambleContents .="%\n"; # solves the problem if the file doesn't end with a return. |
392 | $tthPreambleContents .="%\n"; # solves the problem if the file doesn't end with a return. |
| 393 | |
393 | |
| 394 | } else { |
394 | } else { |
| 395 | $tthPreambleContents = ""; |
395 | $tthPreambleContents = ""; |
| 396 | } |
396 | } |
| 397 | } |
397 | } |
| 398 | |
398 | |
| 399 | $inputString = $tthPreambleContents . $inputString; |
399 | $inputString = $tthPreambleContents . $inputString; |
| 400 | $inputString = "<<END_OF_TTH_INPUT_STRING;\n\n\n" . $inputString . "\nEND_OF_TTH_INPUT_STRING\necho \"\" >/dev/null"; #it's not clear why another command is needed. |
400 | $inputString = "<<END_OF_TTH_INPUT_STRING;\n\n\n" . $inputString . "\nEND_OF_TTH_INPUT_STRING\necho \"\" >/dev/null"; #it's not clear why another command is needed. |
| 401 | |
401 | |
| 402 | # $tthpath is now taken from $Global::externalTTHPath via %envir. |
402 | # $tthpath is now taken from $Global::externalTTHPath via %envir. |
| 403 | my $tthpath = $envir{externalTTHPath}; |
403 | my $tthpath = $envir{externalTTHPath}; |
| 404 | my $out; |
404 | my $out; |
| 405 | |
405 | |
| 406 | if (-x $tthpath ) { |
406 | if (-x $tthpath ) { |
| 407 | my $tthcmd = "$tthpath -L -f5 -u -r 2>/dev/null " . $inputString; |
407 | my $tthcmd = "$tthpath -L -f5 -u -r 2>/dev/null " . $inputString; |
| 408 | if (open(TTH, "$tthcmd |")) { |
408 | if (open(TTH, "$tthcmd |")) { |
| 409 | local($/); |
409 | local($/); |
| 410 | $/ = undef; |
410 | $/ = undef; |
| 411 | $out = <TTH>; |
411 | $out = <TTH>; |
| 412 | $/ = "\n"; |
412 | $/ = "\n"; |
| 413 | close(TTH); |
413 | close(TTH); |
| … | |
… | |
| 417 | } else { |
417 | } else { |
| 418 | $out = "<BR> Can't execute the program tth at |$tthpath|<BR>"; |
418 | $out = "<BR> Can't execute the program tth at |$tthpath|<BR>"; |
| 419 | } |
419 | } |
| 420 | |
420 | |
| 421 | $out; |
421 | $out; |
| 422 | } |
422 | } |
| 423 | |
423 | |
| 424 | # possible solution to the tth font problem? Works only for iCab. |
424 | # possible solution to the tth font problem? Works only for iCab. |
| 425 | sub symbolConvert { |
425 | sub symbolConvert { |
| 426 | my $string = shift; |
426 | my $string = shift; |
| 427 | $string =~ s/\x5C/\\/g; #\ 92 \ |
427 | $string =~ s/\x5C/\\/g; #\ 92 \ |
| … | |
… | |
| 460 | my $math2imgCount = 0; |
460 | my $math2imgCount = 0; |
| 461 | |
461 | |
| 462 | sub math2img { |
462 | sub math2img { |
| 463 | my $tex = shift; |
463 | my $tex = shift; |
| 464 | my $mode = shift; |
464 | my $mode = shift; |
| 465 | |
465 | |
| 466 | my $sourcePath = $envir{templateDirectory} . "/" . $envir{fileName}; |
466 | my $sourcePath = $envir{templateDirectory} . "/" . $envir{fileName}; |
| 467 | my $tempFile = "m2i/$envir{studentLogin}.$envir{setNumber}.$envir{probNum}." |
467 | my $tempFile = "m2i/$envir{studentLogin}.$envir{setNumber}.$envir{probNum}." |
| 468 | . $math2imgCount++ . ".png"; |
468 | . $math2imgCount++ . ".png"; |
| 469 | my $tempPath = surePathToTmpFile($tempFile); #my $tempPath = "$envir{tempDirectory}$tempFile"; |
469 | my $tempPath = surePathToTmpFile($tempFile); #my $tempPath = "$envir{tempDirectory}$tempFile"; |
| 470 | my $tempURL = "$envir{tempURL}/$tempFile"; |
470 | my $tempURL = "$envir{tempURL}/$tempFile"; |
| … | |
… | |
| 483 | dvipng( |
483 | dvipng( |
| 484 | $envir{dvipngTempDir}, $envir{externalLaTeXPath}, |
484 | $envir{dvipngTempDir}, $envir{externalLaTeXPath}, |
| 485 | $envir{externalDvipngPath}, $tex, $tempPath |
485 | $envir{externalDvipngPath}, $tex, $tempPath |
| 486 | ); |
486 | ); |
| 487 | } |
487 | } |
| 488 | |
488 | |
| 489 | if (-e $tempPath) { |
489 | if (-e $tempPath) { |
| 490 | return "<img align=\"middle\" src=\"$tempURL\" alt=\"$tex\">" if $mode eq "inline"; |
490 | return "<img align=\"middle\" src=\"$tempURL\" alt=\"$tex\">" if $mode eq "inline"; |
| 491 | return "<div align=\"center\"><img src=\"$tempURL\" alt=\"$tex\"></div>" if $mode eq "display"; |
491 | return "<div align=\"center\"><img src=\"$tempURL\" alt=\"$tex\"></div>" if $mode eq "display"; |
| 492 | } else { |
492 | } else { |
| 493 | return "<b>[math2img failed]</b>"; |
493 | return "<b>[math2img failed]</b>"; |
| … | |
… | |
| 505 | $latex, # path to latex binary |
505 | $latex, # path to latex binary |
| 506 | $dvipng, # path to dvipng binary |
506 | $dvipng, # path to dvipng binary |
| 507 | $tex, # tex string representing equation |
507 | $tex, # tex string representing equation |
| 508 | $targetPath # location of resulting image file |
508 | $targetPath # location of resulting image file |
| 509 | ) = @_; |
509 | ) = @_; |
| 510 | |
510 | |
| 511 | my $dvipngBroken = 0; |
511 | my $dvipngBroken = 0; |
| 512 | |
512 | |
| 513 | my $texFile = "$wd/equation.tex"; |
513 | my $texFile = "$wd/equation.tex"; |
| 514 | my $dviFile = "$wd/equation.dvi"; |
514 | my $dviFile = "$wd/equation.dvi"; |
| 515 | my $dviFile2 = "$wd/equationequation.dvi"; |
515 | my $dviFile2 = "$wd/equationequation.dvi"; |
| 516 | my $dviCall = "equation"; |
516 | my $dviCall = "equation"; |
| 517 | my $pngFile = "$wd/equation1.png"; |
517 | my $pngFile = "$wd/equation1.png"; |
| 518 | |
518 | |
| 519 | unless (-e $wd) { |
519 | unless (-e $wd) { |
| 520 | die "dvipng working directory $wd doesn't exist -- caller should have created it for us!\n"; |
520 | die "dvipng working directory $wd doesn't exist -- caller should have created it for us!\n"; |
| 521 | return 0; |
521 | return 0; |
| 522 | } |
522 | } |
| 523 | |
523 | |
| 524 | # write the tex file |
524 | # write the tex file |
| 525 | local *TEX; |
525 | local *TEX; |
| 526 | open TEX, ">", $texFile or warn "Failed to create $texFile: $!"; |
526 | open TEX, ">", $texFile or warn "Failed to create $texFile: $!"; |
| 527 | print TEX <<'EOF'; |
527 | print TEX <<'EOF'; |
| 528 | % BEGIN HEADER |
528 | % BEGIN HEADER |
| … | |
… | |
| 540 | % BEGIN FOOTER |
540 | % BEGIN FOOTER |
| 541 | \end{document} |
541 | \end{document} |
| 542 | % END FOOTER |
542 | % END FOOTER |
| 543 | EOF |
543 | EOF |
| 544 | close TEX; |
544 | close TEX; |
| 545 | |
545 | |
| 546 | # call latex |
546 | # call latex |
| 547 | system "cd $wd && $latex $texFile" |
547 | system "cd $wd && $latex $texFile" |
| 548 | and warn "Failed to call $latex with $texFile: $!"; |
548 | and warn "Failed to call $latex with $texFile: $!"; |
| 549 | |
549 | |
| 550 | unless (-e $dviFile) { |
550 | unless (-e $dviFile) { |
| 551 | warn "Failed to generate DVI file $dviFile"; |
551 | warn "Failed to generate DVI file $dviFile"; |
| 552 | return 0; |
552 | return 0; |
| 553 | } |
553 | } |
| 554 | |
554 | |
| 555 | if ($dvipngBroken) { |
555 | if ($dvipngBroken) { |
| 556 | # change the name of the DVI file to get around dvipng's |
556 | # change the name of the DVI file to get around dvipng's |
| 557 | # crackheadedness. This is no longer needed with the newest |
557 | # crackheadedness. This is no longer needed with the newest |
| 558 | # version of dvipng (10 something) |
558 | # version of dvipng (10 something) |
| 559 | system "/bin/mv", $dviFile, $dviFile2; |
559 | system "/bin/mv", $dviFile, $dviFile2; |
| 560 | } |
560 | } |
| 561 | |
561 | |
| 562 | # call dvipng -- using warn instead of die passes some extra information |
562 | # call dvipng -- using warn instead of die passes some extra information |
| 563 | # back to the user the complete warning is still printed in the apache |
563 | # back to the user the complete warning is still printed in the apache |
| 564 | # error log and a simple message (math2img failed) is returned to the |
564 | # error log and a simple message (math2img failed) is returned to the |
| 565 | # webpage. |
565 | # webpage. |
| 566 | my $cmdout; |
566 | my $cmdout; |
| 567 | $cmdout = system "cd $wd && $dvipng $dviCall" |
567 | $cmdout = system "cd $wd && $dvipng $dviCall" |
| 568 | and warn "Failed to call$dvipng with $dviCall: $! with signal $cmdout"; |
568 | and warn "Failed to call$dvipng with $dviCall: $! with signal $cmdout"; |
| 569 | |
569 | |
| 570 | unless (-e $pngFile) { |
570 | unless (-e $pngFile) { |
| 571 | warn "Failed to create PNG file $pngFile"; |
571 | warn "Failed to create PNG file $pngFile"; |
| 572 | return 0; |
572 | return 0; |
| 573 | } |
573 | } |
| 574 | |
574 | |
| 575 | $cmdout = system "/bin/mv", $pngFile, $targetPath and warn "Failed to mv: /bin/mv $pngFile $targetPath $!. Call returned $cmdout. \n"; |
575 | $cmdout = system "/bin/mv", $pngFile, $targetPath and warn "Failed to mv: /bin/mv $pngFile $targetPath $!. Call returned $cmdout. \n"; |
| 576 | } |
576 | } |
| 577 | |
577 | |
| 578 | |
578 | |
| 579 | # ----- ----- ----- ----- |
579 | # ----- ----- ----- ----- |
| 580 | |
580 | |
| 581 | =head2 alias |
581 | =head2 alias |
| 582 | |
582 | |
| 583 | alias(pathToFile); |
583 | alias(pathToFile); |
| 584 | returns A string describing the URL which links to GIF or html file |
584 | returns A string describing the URL which links to GIF or html file |
| 585 | (in HTML and Latex2HTML modes). |
585 | (in HTML and Latex2HTML modes). |
| 586 | or a path to the appropriate eps version of a GIF file |
586 | or a path to the appropriate eps version of a GIF file |
| 587 | (TeX Mode) |
587 | (TeX Mode) |
| 588 | |
588 | |
| 589 | |
589 | |
| 590 | |
590 | |
| 591 | C<alias> allows you to refer to auxiliary files which are in a directory along with |
591 | C<alias> allows you to refer to auxiliary files which are in a directory along with |
| 592 | the problem definition. In addition alias creates an eps copy of GIF files when |
592 | the problem definition. In addition alias creates an eps copy of GIF files when |
| 593 | downloading hard copy (TeX mode). |
593 | downloading hard copy (TeX mode). |
| 594 | |
594 | |
| 595 | As a rule auxiliary files that are used by |
595 | As a rule auxiliary files that are used by |
| 596 | a number of problems in a course should be placed in C<html/gif> or C<html> |
596 | a number of problems in a course should be placed in C<html/gif> or C<html> |
| 597 | or in a subdirectory of the C<html> directory, |
597 | or in a subdirectory of the C<html> directory, |
| 598 | while auxiliary files which are used in only one problem should be placed in |
598 | while auxiliary files which are used in only one problem should be placed in |
| … | |
… | |
| 612 | start with the prefix defined in $Global:htmlDirectory. |
612 | start with the prefix defined in $Global:htmlDirectory. |
| 613 | |
613 | |
| 614 | B<When in TeX mode:> |
614 | B<When in TeX mode:> |
| 615 | |
615 | |
| 616 | |
616 | |
| 617 | GIF files will be translated into an eps file (using system dependent code) |
617 | GIF files will be translated into an eps file (using system dependent code) |
| 618 | and placed in the directory C<tmp/eps>. The full path to this file is returned |
618 | and placed in the directory C<tmp/eps>. The full path to this file is returned |
| 619 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
619 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
| 620 | environment.) in producing the hard copy. (This should work even in a chrooted |
620 | environment.) in producing the hard copy. (This should work even in a chrooted |
| 621 | environment.) |
621 | environment.) |
| 622 | |
622 | |
| 623 | The conversion is done by a system dependent script |
623 | The conversion is done by a system dependent script |
| 624 | called C<gif2eps> which should be in the scripts directory |
624 | called C<gif2eps> which should be in the scripts directory |
| 625 | |
625 | |
| 626 | The URL's for the other files are produced as in non-tex mode |
626 | The URL's for the other files are produced as in non-tex mode |
| 627 | but will of course not be active. |
627 | but will of course not be active. |
| 628 | |
628 | |
| 629 | =item Files in the tmp subdirectory |
629 | =item Files in the tmp subdirectory |
| … | |
… | |
| 636 | start with the prefix defined in $Global:tempDirectory. |
636 | start with the prefix defined in $Global:tempDirectory. |
| 637 | |
637 | |
| 638 | B<When in TeX mode:> |
638 | B<When in TeX mode:> |
| 639 | |
639 | |
| 640 | |
640 | |
| 641 | GIF files will be translated into an eps file (using system dependent code) |
641 | GIF files will be translated into an eps file (using system dependent code) |
| 642 | and placed in the directory C<tmp/eps>. The full path to this file is returned |
642 | and placed in the directory C<tmp/eps>. The full path to this file is returned |
| 643 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
643 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
| 644 | environment.) |
644 | environment.) |
| 645 | |
645 | |
| 646 | The conversion is done by a system dependent script |
646 | The conversion is done by a system dependent script |
| 647 | called C<gif2eps> which should be in the scripts directory |
647 | called C<gif2eps> which should be in the scripts directory |
| 648 | |
648 | |
| 649 | The URL's for the other files are produced as in non-tex mode |
649 | The URL's for the other files are produced as in non-tex mode |
| 650 | but will of course not be active. |
650 | but will of course not be active. |
| 651 | |
651 | |
| 652 | =item Files in the course template subdirectory: |
652 | =item Files in the course template subdirectory: |
| 653 | |
653 | |
| 654 | B<When not in TeX mode:> |
654 | B<When not in TeX mode:> |
| 655 | |
655 | |
| 656 | If the file lies under the course templates subdirectory, |
656 | If the file lies under the course templates subdirectory, |
| 657 | it is assumed to lie in subdirectory rooted in the directory |
657 | it is assumed to lie in subdirectory rooted in the directory |
| 658 | containing the problem template file. |
658 | containing the problem template file. |
| 659 | An alias is created under the C<html/tmp/gif> or |
659 | An alias is created under the C<html/tmp/gif> or |
| 660 | C<html/tmp/html> directory and linked to the original file. |
660 | C<html/tmp/html> directory and linked to the original file. |
| 661 | The file path for this type of file is a relative |
661 | The file path for this type of file is a relative |
| 662 | path rooted at the directory containing the problem template file. |
662 | path rooted at the directory containing the problem template file. |
| 663 | |
663 | |
| 664 | B<When in TeX mode:> |
664 | B<When in TeX mode:> |
| 665 | |
665 | |
| 666 | GIF files will be translated into an eps file (using system dependent code) |
666 | GIF files will be translated into an eps file (using system dependent code) |
| 667 | and placed in the directory C<html/tmp/eps>. The full path to this file is returned |
667 | and placed in the directory C<html/tmp/eps>. The full path to this file is returned |
| 668 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
668 | for use by TeX in producing the hard copy. (This should work even in a chrooted |
| 669 | environment.) |
669 | environment.) |
| 670 | |
670 | |
| 671 | The conversion is done by a system dependent script |
671 | The conversion is done by a system dependent script |
| 672 | called C<gif2eps> which should be in the scripts directory |
672 | called C<gif2eps> which should be in the scripts directory |
| 673 | |
673 | |
| 674 | The URL's for the other files are produced as in non-tex mode |
674 | The URL's for the other files are produced as in non-tex mode |
| … | |
… | |
| 682 | |
682 | |
| 683 | # Currently gif, html and types are supported. |
683 | # Currently gif, html and types are supported. |
| 684 | # |
684 | # |
| 685 | # If the auxiliary file path has not extension then the extension .gif isassumed. |
685 | # If the auxiliary file path has not extension then the extension .gif isassumed. |
| 686 | # |
686 | # |
| 687 | # If the auxiliary file path leads to a file in the ${Global::htmlDirectory} |
687 | # If the auxiliary file path leads to a file in the ${Global::htmlDirectory} |
| 688 | # no changes are made to the file path. |
688 | # no changes are made to the file path. |
| 689 | # |
689 | # |
| 690 | # If the auxiliary file path is not complete, than it is assumed that it refers |
690 | # If the auxiliary file path is not complete, than it is assumed that it refers |
| 691 | # to a subdirectoy of the directory containing the problem.. |
691 | # to a subdirectoy of the directory containing the problem.. |
| 692 | # |
692 | # |
| 693 | # The output is either the correct URL for the file |
693 | # The output is either the correct URL for the file |
| 694 | # or (in TeX mode) the complete path to the eps version of the file |
694 | # or (in TeX mode) the complete path to the eps version of the file |
| 695 | # and can be used as input into the image macro. |
695 | # and can be used as input into the image macro. |
| 696 | # |
696 | # |
| 697 | # surePathToTmpFile takes a path and outputs the complete path: |
697 | # surePathToTmpFile takes a path and outputs the complete path: |
| 698 | # ${main::htmlDirectory}/tmp/path |
698 | # ${main::htmlDirectory}/tmp/path |
| 699 | # It insures that all of the directories in the path have been created, |
699 | # It insures that all of the directories in the path have been created, |
| 700 | # but does not create the |
700 | # but does not create the |
| 701 | # final file. |
701 | # final file. |
| 702 | |
702 | |
| 703 | # For postscript printing, alias generates an eps version of the gif image and places |
703 | # For postscript printing, alias generates an eps version of the gif image and places |
| 704 | # it in the directory eps. This slows down downloading postscript versions somewhat, |
704 | # it in the directory eps. This slows down downloading postscript versions somewhat, |
| 705 | # but not excessivevly. |
705 | # but not excessivevly. |
| 706 | # Alias does not do any garbage collection, so files and alias may accumulate and |
706 | # Alias does not do any garbage collection, so files and alias may accumulate and |
| 707 | # need to be removed manually or by a reaper daemon. |
707 | # need to be removed manually or by a reaper daemon. |
| 708 | |
708 | |
| 709 | |
709 | |
| 710 | # Global variables used: |
710 | # Global variables used: |
| 711 | # $main::fileName # the full path to the current problem template file |
711 | # $main::fileName # the full path to the current problem template file |
| … | |
… | |
| 726 | # directoryFromPath |
726 | # directoryFromPath |
| 727 | |
727 | |
| 728 | |
728 | |
| 729 | # This subroutine has commands which will not work on non-UNIX environments. |
729 | # This subroutine has commands which will not work on non-UNIX environments. |
| 730 | # system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") && |
730 | # system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") && |
| 731 | |
731 | |
| 732 | |
732 | |
| 733 | # local constants $User, $psvn $setNumber $probNum $displayMode |
733 | # local constants $User, $psvn $setNumber $probNum $displayMode |
| 734 | |
734 | |
| 735 | sub sourceAlias { |
735 | sub sourceAlias { |
| 736 | my $path_to_file = shift; |
736 | my $path_to_file = shift; |
| 737 | my $user = $main::inputs_ref->{user}; |
737 | my $user = $main::inputs_ref->{user}; |
| 738 | $user = " " unless defined($user); |
738 | $user = " " unless defined($user); |
| 739 | my $out = "source.pl?probSetKey=$main::psvn". |
739 | my $out = "source.pl?probSetKey=$main::psvn". |
| 740 | "&probNum=$main::probNum" . |
740 | "&probNum=$main::probNum" . |
| 741 | "&Mode=$main::displayMode" . |
741 | "&Mode=$main::displayMode" . |
| 742 | "&course=". $main::courseName . |
742 | "&course=". $main::courseName . |
| 743 | "&user=" . $user . |
743 | "&user=" . $user . |
| 744 | "&displayPath=$path_to_file" . |
744 | "&displayPath=$path_to_file" . |
| 745 | "&key=". $main::sessionKey; |
745 | "&key=". $main::sessionKey; |
| 746 | |
746 | |
| 747 | $out; |
747 | $out; |
| 748 | } |
748 | } |
| 749 | |
749 | |
| 750 | |
750 | |
| 751 | sub alias { |
751 | sub alias { |
| … | |
… | |
| 758 | #my $studentLogin = $main::studentLogin; |
758 | #my $studentLogin = $main::studentLogin; |
| 759 | #my $psvnNumber = $main::psvnNumber; |
759 | #my $psvnNumber = $main::psvnNumber; |
| 760 | #my $setNumber = $main::setNumber; |
760 | #my $setNumber = $main::setNumber; |
| 761 | #my $probNum = $main::probNum; |
761 | #my $probNum = $main::probNum; |
| 762 | #my $displayMode = $main::displayMode; |
762 | #my $displayMode = $main::displayMode; |
| 763 | |
763 | |
| 764 | |
764 | |
| 765 | my $aux_file_path = shift @_; |
765 | my $aux_file_path = shift @_; |
| 766 | warn "Empty string used as input into the function alias" unless $aux_file_path; |
766 | warn "Empty string used as input into the function alias" unless $aux_file_path; |
| 767 | |
767 | |
| 768 | # problem specific data |
768 | # problem specific data |
| 769 | warn "The path to the current problem file template is not defined." unless $main::fileName; |
769 | warn "The path to the current problem file template is not defined." unless $main::fileName; |
| 770 | warn "The current studentLogin is not defined " unless $main::studentLogin; |
770 | warn "The current studentLogin is not defined " unless $main::studentLogin; |
| 771 | warn "The current problem set number is not defined" if $main::setNumber eq ""; # allow for sets equal to 0 |
771 | warn "The current problem set number is not defined" if $main::setNumber eq ""; # allow for sets equal to 0 |
| 772 | warn "The current problem number is not defined" if $main::probNum eq ""; |
772 | warn "The current problem number is not defined" if $main::probNum eq ""; |
| 773 | warn "The current problem set version number (psvn) is not defined" unless $main::psvnNumber; |
773 | warn "The current problem set version number (psvn) is not defined" unless $main::psvnNumber; |
| 774 | warn "The displayMode is not defined" unless $main::displayMode; |
774 | warn "The displayMode is not defined" unless $main::displayMode; |
| 775 | |
775 | |
| 776 | # required macros |
776 | # required macros |
| 777 | warn "The macro &surePathToTmpFile can't be found" unless defined(&surePathToTmpFile); |
777 | warn "The macro &surePathToTmpFile can't be found" unless defined(&surePathToTmpFile); |
| 778 | warn "The macro &convertPath can't be found" unless defined(&convertPath); |
778 | warn "The macro &convertPath can't be found" unless defined(&convertPath); |
| 779 | warn "The macro &directoryFromPath can't be found" unless defined(&directoryFromPath); |
779 | warn "The macro &directoryFromPath can't be found" unless defined(&directoryFromPath); |
| 780 | warn "Can't execute the gif2eps script at ${main::externalGif2EpsPath}" unless ( -x "${main::externalGif2EpsPath}" ); |
780 | warn "Can't execute the gif2eps script at ${main::externalGif2EpsPath}" unless ( -x "${main::externalGif2EpsPath}" ); |
| 781 | warn "Can't execute the png2eps script at ${main::externalPng2EpsPath}" unless ( -x "${main::externalPng2EpsPath}" ); |
781 | warn "Can't execute the png2eps script at ${main::externalPng2EpsPath}" unless ( -x "${main::externalPng2EpsPath}" ); |
| 782 | |
782 | |
| 783 | # required directory addresses (and URL address) |
783 | # required directory addresses (and URL address) |
| 784 | warn "htmlDirectory is not defined in $main::htmlDirectory" unless $main::htmlDirectory; |
784 | warn "htmlDirectory is not defined in $main::htmlDirectory" unless $main::htmlDirectory; |
| 785 | warn "htmlURL is not defined in \$main::htmlURL" unless $main::htmlURL; |
785 | warn "htmlURL is not defined in \$main::htmlURL" unless $main::htmlURL; |
| 786 | warn "tempURL is not defined in \$main::tempURL" unless $main::tempURL; |
786 | warn "tempURL is not defined in \$main::tempURL" unless $main::tempURL; |
| 787 | #warn "The scripts directory is not defined in \$main::scriptDirectory" unless $main::scriptDirectory; |
787 | #warn "The scripts directory is not defined in \$main::scriptDirectory" unless $main::scriptDirectory; |
| 788 | # with the creation of externalGif2EpsPath and externalPng2EpsPath, the scripts directory is no longer used |
788 | # with the creation of externalGif2EpsPath and externalPng2EpsPath, the scripts directory is no longer used |
| 789 | |
789 | |
| 790 | # determine extension, if there is one |
790 | # determine extension, if there is one |
| 791 | # if extension exists, strip and use the value for $ext |
791 | # if extension exists, strip and use the value for $ext |
| 792 | # files without extensions are considered to be picture files: |
792 | # files without extensions are considered to be picture files: |
| 793 | |
793 | |
| 794 | my $ext; |
794 | my $ext; |
| 795 | if ($aux_file_path =~ s/\.([^\.]*)$// ) { |
795 | if ($aux_file_path =~ s/\.([^\.]*)$// ) { |
| 796 | $ext = $1; |
796 | $ext = $1; |
| 797 | } else { |
797 | } else { |
| 798 | warn "This file name $aux_file_path did not have an extension.<BR> " . |
798 | warn "This file name $aux_file_path did not have an extension.<BR> " . |
| 799 | "Every file name used as an argument to alias must have an extension.<BR> " . |
799 | "Every file name used as an argument to alias must have an extension.<BR> " . |
| 800 | "The permissable extensions are .gif, .png, and .html .<BR>"; |
800 | "The permissable extensions are .gif, .png, and .html .<BR>"; |
| 801 | $ext = "gif"; |
801 | $ext = "gif"; |
| 802 | } |
802 | } |
| 803 | |
803 | |
| 804 | # $adr_output is a url in HTML and Latex2HTML modes |
804 | # $adr_output is a url in HTML and Latex2HTML modes |
| 805 | # and a complete path in TEX mode. |
805 | # and a complete path in TEX mode. |
| 806 | my $adr_output; |
806 | my $adr_output; |
| 807 | |
807 | |
| 808 | # in order to facilitate maintenance of this macro the routines for handling |
808 | # in order to facilitate maintenance of this macro the routines for handling |
| 809 | # different file types are defined separately. This involves some redundancy |
809 | # different file types are defined separately. This involves some redundancy |
| 810 | # in the code but it makes it easier to define special handling for a new file |
810 | # in the code but it makes it easier to define special handling for a new file |
| 811 | # type, (but harder to change the behavior for all of the file types at once |
811 | # type, (but harder to change the behavior for all of the file types at once |
| 812 | # (sigh) ). |
812 | # (sigh) ). |
| 813 | |
813 | |
| 814 | |
814 | |
| 815 | if ($ext eq 'html') { |
815 | if ($ext eq 'html') { |
| 816 | ################################################################################ |
816 | ################################################################################ |
| 817 | # .html FILES in HTML, HTML_tth, HTML_dpng, HTML_img and Latex2HTML mode |
817 | # .html FILES in HTML, HTML_tth, HTML_dpng, HTML_img and Latex2HTML mode |
| 818 | ################################################################################ |
818 | ################################################################################ |
| 819 | |
819 | |
| 820 | # No changes are made for auxiliary files in the |
820 | # No changes are made for auxiliary files in the |
| 821 | # ${Global::htmlDirectory} subtree. |
821 | # ${Global::htmlDirectory} subtree. |
| 822 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
822 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
| 823 | $adr_output = $aux_file_path; |
823 | $adr_output = $aux_file_path; |
| 824 | $adr_output =~ s|$main::tempDirectory|$main::tempURL/|; |
824 | $adr_output =~ s|$main::tempDirectory|$main::tempURL/|; |
| 825 | $adr_output .= ".$ext"; |
825 | $adr_output .= ".$ext"; |
| 826 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
826 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
| 827 | $adr_output = $aux_file_path; |
827 | $adr_output = $aux_file_path; |
| 828 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
828 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
| 829 | $adr_output .= ".$ext"; |
829 | $adr_output .= ".$ext"; |
| 830 | } else { |
830 | } else { |
| 831 | # HTML files not in the htmlDirectory are assumed under live under the |
831 | # HTML files not in the htmlDirectory are assumed under live under the |
| 832 | # templateDirectory in the same directory as the problem. |
832 | # templateDirectory in the same directory as the problem. |
| 833 | # Create an alias file (link) in the directory html/tmp/html which |
833 | # Create an alias file (link) in the directory html/tmp/html which |
| 834 | # points to the original file and return the URL of this alias. |
834 | # points to the original file and return the URL of this alias. |
| 835 | # Create all of the subdirectories of html/tmp/html which are needed |
835 | # Create all of the subdirectories of html/tmp/html which are needed |
| 836 | # using sure file to path. |
836 | # using sure file to path. |
| 837 | |
837 | |
| 838 | # $fileName is obtained from environment for PGeval |
838 | # $fileName is obtained from environment for PGeval |
| 839 | # it gives the full path to the current problem |
839 | # it gives the full path to the current problem |
| 840 | my $filePath = directoryFromPath($main::fileName); |
840 | my $filePath = directoryFromPath($main::fileName); |
| 841 | my $htmlFileSource = convertPath("$main::templateDirectory${filePath}$aux_file_path.html"); |
841 | my $htmlFileSource = convertPath("$main::templateDirectory${filePath}$aux_file_path.html"); |
| 842 | my $link = "html/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
842 | my $link = "html/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
| 843 | my $linkPath = surePathToTmpFile($link); |
843 | my $linkPath = surePathToTmpFile($link); |
| 844 | $adr_output = "${main::tempURL}$link"; |
844 | $adr_output = "${main::tempURL}$link"; |
| 845 | if (-e $htmlFileSource) { |
845 | if (-e $htmlFileSource) { |
| 846 | if (-e $linkPath) { |
846 | if (-e $linkPath) { |
| 847 | unlink($linkPath) || warn "Unable to unlink alias file at |$linkPath|"; |
847 | unlink($linkPath) || warn "Unable to unlink alias file at |$linkPath|"; |
| 848 | # destroy the old link. |
848 | # destroy the old link. |
| 849 | } |
849 | } |
| 850 | symlink( $htmlFileSource, $linkPath) |
850 | symlink( $htmlFileSource, $linkPath) |
| 851 | || warn "The macro alias cannot create a link from |$linkPath| to |$htmlFileSource| <BR>" ; |
851 | || warn "The macro alias cannot create a link from |$linkPath| to |$htmlFileSource| <BR>" ; |
| 852 | } else { |
852 | } else { |
| 853 | warn("The macro alias cannot find an HTML file at: |$htmlFileSource|"); |
853 | warn("The macro alias cannot find an HTML file at: |$htmlFileSource|"); |
| 854 | } |
854 | } |
| 855 | } |
855 | } |
| 856 | } elsif ($ext eq 'gif') { |
856 | } elsif ($ext eq 'gif') { |
| 857 | if ( $main::displayMode eq 'HTML' || |
857 | if ( $main::displayMode eq 'HTML' || |
| 858 | $main::displayMode eq 'HTML_tth'|| |
858 | $main::displayMode eq 'HTML_tth'|| |
| 859 | $main::displayMode eq 'HTML_dpng'|| |
859 | $main::displayMode eq 'HTML_dpng'|| |
| 860 | $main::displayMode eq 'HTML_img'|| |
860 | $main::displayMode eq 'HTML_img'|| |
| 861 | $main::displayMode eq 'Latex2HTML') { |
861 | $main::displayMode eq 'Latex2HTML') { |
| 862 | ################################################################################ |
862 | ################################################################################ |
| 863 | # .gif FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes |
863 | # .gif FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes |
| 864 | ################################################################################ |
864 | ################################################################################ |
| 865 | |
865 | |
| 866 | #warn "tempDirectory is $main::tempDirectory"; |
866 | #warn "tempDirectory is $main::tempDirectory"; |
| 867 | #warn "file Path for auxiliary file is $aux_file_path"; |
867 | #warn "file Path for auxiliary file is $aux_file_path"; |
| 868 | |
868 | |
| 869 | # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree. |
869 | # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree. |
| 870 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
870 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
| 871 | $adr_output = $aux_file_path; |
871 | $adr_output = $aux_file_path; |
| 872 | $adr_output =~ s|$main::tempDirectory|$main::tempURL|; |
872 | $adr_output =~ s|$main::tempDirectory|$main::tempURL|; |
| 873 | $adr_output .= ".$ext"; |
873 | $adr_output .= ".$ext"; |
| 874 | #warn "adress out is $adr_output"; |
874 | #warn "adress out is $adr_output"; |
| 875 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
875 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
| 876 | $adr_output = $aux_file_path; |
876 | $adr_output = $aux_file_path; |
| 877 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
877 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
| 878 | $adr_output .= ".$ext"; |
878 | $adr_output .= ".$ext"; |
| 879 | } else { |
879 | } else { |
| 880 | # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory |
880 | # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory |
| 881 | # subtree in the same directory as the problem. |
881 | # subtree in the same directory as the problem. |
| 882 | |
882 | |
| 883 | # For a gif file the alias macro creates an alias under the html/images directory |
883 | # For a gif file the alias macro creates an alias under the html/images directory |
| 884 | # which points to the gif file in the problem directory. |
884 | # which points to the gif file in the problem directory. |
| 885 | # All of the subdirectories of html/tmp/gif which are needed are also created. |
885 | # All of the subdirectories of html/tmp/gif which are needed are also created. |
| 886 | my $filePath = directoryFromPath($main::fileName); |
886 | my $filePath = directoryFromPath($main::fileName); |
| 887 | |
887 | |
| 888 | # $fileName is obtained from environment for PGeval |
888 | # $fileName is obtained from environment for PGeval |
| 889 | # it gives the full path to the current problem |
889 | # it gives the full path to the current problem |
| 890 | my $gifSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.gif"); |
890 | my $gifSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.gif"); |
| 891 | #my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
891 | #my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
| 892 | my $link = "gif/$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
892 | my $link = "gif/$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
| 893 | |
893 | |
| 894 | my $linkPath = surePathToTmpFile($link); |
894 | my $linkPath = surePathToTmpFile($link); |
| 895 | $adr_output = "${main::tempURL}$link"; |
895 | $adr_output = "${main::tempURL}$link"; |
| 896 | #warn "linkPath is $linkPath"; |
896 | #warn "linkPath is $linkPath"; |
| 897 | #warn "adr_output is $adr_output"; |
897 | #warn "adr_output is $adr_output"; |
| 898 | if (-e $gifSourceFile) { |
898 | if (-e $gifSourceFile) { |
| … | |
… | |
| 907 | } |
907 | } |
| 908 | } elsif ($main::displayMode eq 'TeX') { |
908 | } elsif ($main::displayMode eq 'TeX') { |
| 909 | ################################################################################ |
909 | ################################################################################ |
| 910 | # .gif FILES in TeX mode |
910 | # .gif FILES in TeX mode |
| 911 | ################################################################################ |
911 | ################################################################################ |
| 912 | |
912 | |
| 913 | if ($envir{texDisposition} eq "pdf") { |
913 | if ($envir{texDisposition} eq "pdf") { |
| 914 | # We're going to create PDF files with our TeX (using pdflatex), so we |
914 | # We're going to create PDF files with our TeX (using pdflatex), so we |
| 915 | # need images in PNG format. |
915 | # need images in PNG format. |
| 916 | |
916 | |
| 917 | my $gifFilePath; |
917 | my $gifFilePath; |
| 918 | |
918 | |
| 919 | if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) { |
919 | if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) { |
| 920 | # we've got a full pathname to a file |
920 | # we've got a full pathname to a file |
| 921 | $gifFilePath = "$aux_file_path.gif"; |
921 | $gifFilePath = "$aux_file_path.gif"; |
| 922 | } else { |
922 | } else { |
| 923 | # we assume the file is in the same directory as the problem source file |
923 | # we assume the file is in the same directory as the problem source file |
| 924 | $gifFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.gif"; |
924 | $gifFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.gif"; |
| 925 | } |
925 | } |
| 926 | |
926 | |
| 927 | my $gifFileName = fileFromPath($gifFilePath); |
927 | my $gifFileName = fileFromPath($gifFilePath); |
| 928 | |
928 | |
| 929 | $gifFileName =~ /^(.*)\.gif$/; |
929 | $gifFileName =~ /^(.*)\.gif$/; |
| 930 | my $pngFilePath = surePathToTmpFile("$main::tempDirectory/png/$1.png"); |
930 | my $pngFilePath = surePathToTmpFile("$main::tempDirectory/png/$1.png"); |
| 931 | my $returnCode = system "$envir{externalGif2PngPath} $gifFilePath $pngFilePath"; |
931 | my $returnCode = system "$envir{externalGif2PngPath} $gifFilePath $pngFilePath"; |
| 932 | |
932 | |
| 933 | if ($returnCode or not -e $pngFilePath) { |
933 | if ($returnCode or not -e $pngFilePath) { |
| 934 | die "failed to convert gif->png with $envir{externalGif2PngPath}: $!\n"; |
934 | die "failed to convert gif->png with $envir{externalGif2PngPath}: $!\n"; |
| 935 | } |
935 | } |
| 936 | |
936 | |
| 937 | $adr_output = $pngFilePath; |
937 | $adr_output = $pngFilePath; |
| 938 | } else { |
938 | } else { |
| 939 | # Since we're not creating PDF files, we're probably just using a plain |
939 | # Since we're not creating PDF files, we're probably just using a plain |
| 940 | # vanilla latex. Hence, we need EPS images. |
940 | # vanilla latex. Hence, we need EPS images. |
| 941 | |
941 | |
| 942 | ################################################################################ |
942 | ################################################################################ |
| 943 | # This is statement used below is system dependent. |
943 | # This is statement used below is system dependent. |
| 944 | # Notice that the range of colors is restricted when converting to postscript to keep the files small |
944 | # Notice that the range of colors is restricted when converting to postscript to keep the files small |
| 945 | # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmtops -noturn > $adr_output" |
945 | # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmtops -noturn > $adr_output" |
| 946 | # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output" |
946 | # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output" |
| 947 | ################################################################################ |
947 | ################################################################################ |
| 948 | if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) { |
948 | if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) { |
| 949 | # To serve an eps file copy an eps version of the gif file to the subdirectory of eps/ |
949 | # To serve an eps file copy an eps version of the gif file to the subdirectory of eps/ |
| 950 | my $linkPath = directoryFromPath($main::fileName); |
950 | my $linkPath = directoryFromPath($main::fileName); |
| 951 | |
951 | |
| 952 | my $gifSourceFile = "$aux_file_path.gif"; |
952 | my $gifSourceFile = "$aux_file_path.gif"; |
| … | |
… | |
| 982 | } |
982 | } |
| 983 | } else { |
983 | } else { |
| 984 | wwerror("Error in alias: dangerousMacros.pl","unrecognizable displayMode = $main::displayMode",""); |
984 | wwerror("Error in alias: dangerousMacros.pl","unrecognizable displayMode = $main::displayMode",""); |
| 985 | } |
985 | } |
| 986 | } elsif ($ext eq 'png') { |
986 | } elsif ($ext eq 'png') { |
| 987 | if ( $main::displayMode eq 'HTML' || |
987 | if ( $main::displayMode eq 'HTML' || |
| 988 | $main::displayMode eq 'HTML_tth'|| |
988 | $main::displayMode eq 'HTML_tth'|| |
| 989 | $main::displayMode eq 'HTML_dpng'|| |
989 | $main::displayMode eq 'HTML_dpng'|| |
| 990 | $main::displayMode eq 'HTML_img'|| |
990 | $main::displayMode eq 'HTML_img'|| |
| 991 | $main::displayMode eq 'Latex2HTML') { |
991 | $main::displayMode eq 'Latex2HTML') { |
| 992 | ################################################################################ |
992 | ################################################################################ |
| 993 | # .png FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes |
993 | # .png FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes |
| 994 | ################################################################################ |
994 | ################################################################################ |
| 995 | |
995 | |
| 996 | #warn "tempDirectory is $main::tempDirectory"; |
996 | #warn "tempDirectory is $main::tempDirectory"; |
| 997 | #warn "file Path for auxiliary file is $aux_file_path"; |
997 | #warn "file Path for auxiliary file is $aux_file_path"; |
| 998 | |
998 | |
| 999 | # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree. |
999 | # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree. |
| 1000 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
1000 | if ( $aux_file_path =~ m|^$main::tempDirectory| ) { |
| 1001 | $adr_output = $aux_file_path; |
1001 | $adr_output = $aux_file_path; |
| 1002 | $adr_output =~ s|$main::tempDirectory|$main::tempURL|; |
1002 | $adr_output =~ s|$main::tempDirectory|$main::tempURL|; |
| 1003 | $adr_output .= ".$ext"; |
1003 | $adr_output .= ".$ext"; |
| 1004 | #warn "adress out is $adr_output"; |
1004 | #warn "adress out is $adr_output"; |
| 1005 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
1005 | } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) { |
| 1006 | $adr_output = $aux_file_path; |
1006 | $adr_output = $aux_file_path; |
| 1007 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
1007 | $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|; |
| 1008 | $adr_output .= ".$ext"; |
1008 | $adr_output .= ".$ext"; |
| 1009 | } else { |
1009 | } else { |
| 1010 | # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory |
1010 | # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory |
| 1011 | # subtree in the same directory as the problem. |
1011 | # subtree in the same directory as the problem. |
| 1012 | |
1012 | |
| 1013 | # For a png file the alias macro creates an alias under the html/images directory |
1013 | # For a png file the alias macro creates an alias under the html/images directory |
| 1014 | # which points to the png file in the problem directory. |
1014 | # which points to the png file in the problem directory. |
| 1015 | # All of the subdirectories of html/tmp/gif which are needed are also created. |
1015 | # All of the subdirectories of html/tmp/gif which are needed are also created. |
| 1016 | my $filePath = directoryFromPath($main::fileName); |
1016 | my $filePath = directoryFromPath($main::fileName); |
| 1017 | |
1017 | |
| 1018 | # $fileName is obtained from environment for PGeval |
1018 | # $fileName is obtained from environment for PGeval |
| 1019 | # it gives the full path to the current problem |
1019 | # it gives the full path to the current problem |
| 1020 | my $pngSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.png"); |
1020 | my $pngSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.png"); |
| 1021 | my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
1021 | my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext"; |
| 1022 | my $linkPath = surePathToTmpFile($link); |
1022 | my $linkPath = surePathToTmpFile($link); |
| … | |
… | |
| 1039 | ################################################################################ |
1039 | ################################################################################ |
| 1040 | |
1040 | |
| 1041 | if ($envir{texDisposition} eq "pdf") { |
1041 | if ($envir{texDisposition} eq "pdf") { |
| 1042 | # We're going to create PDF files with our TeX (using pdflatex), so we |
1042 | # We're going to create PDF files with our TeX (using pdflatex), so we |
| 1043 | # need images in PNG format. what luck! they're already in PDF format! |
1043 | # need images in PNG format. what luck! they're already in PDF format! |
| 1044 | |
1044 | |
| 1045 | my $pngFilePath; |
1045 | my $pngFilePath; |
| 1046 | |
1046 | |
| 1047 | if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) { |
1047 | if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) { |
| 1048 | # we've got a full pathname to a file |
1048 | # we've got a full pathname to a file |
| 1049 | $pngFilePath = "$aux_file_path.png"; |
1049 | $pngFilePath = "$aux_file_path.png"; |
| 1050 | } else { |
1050 | } else { |
| 1051 | # we assume the file is in the same directory as the problem source file |
1051 | # we assume the file is in the same directory as the problem source file |
| 1052 | $pngFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.png"; |
1052 | $pngFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.png"; |
| 1053 | } |
1053 | } |
| 1054 | |
1054 | |
| 1055 | $adr_output = $pngFilePath; |
1055 | $adr_output = $pngFilePath; |
| 1056 | } else { |
1056 | } else { |
| 1057 | # Since we're not creating PDF files, we're probably just using a plain |
1057 | # Since we're not creating PDF files, we're probably just using a plain |
| 1058 | # vanilla latex. Hence, we need EPS images. |
1058 | # vanilla latex. Hence, we need EPS images. |
| 1059 | |
1059 | |
| 1060 | ################################################################################ |
1060 | ################################################################################ |
| 1061 | # This is statement used below is system dependent. |
1061 | # This is statement used below is system dependent. |
| 1062 | # Notice that the range of colors is restricted when converting to postscript to keep the files small |
1062 | # Notice that the range of colors is restricted when converting to postscript to keep the files small |
| 1063 | # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmtops -noturn > $adr_output" |
1063 | # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmtops -noturn > $adr_output" |
| 1064 | # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output" |
1064 | # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output" |
| 1065 | ################################################################################ |
1065 | ################################################################################ |
| 1066 | |
1066 | |
| 1067 | if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) { |
1067 | if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) { |
| 1068 | # To serve an eps file copy an eps version of the png file to the subdirectory of eps/ |
1068 | # To serve an eps file copy an eps version of the png file to the subdirectory of eps/ |
| 1069 | my $linkPath = directoryFromPath($main::fileName); |
1069 | my $linkPath = directoryFromPath($main::fileName); |
| … | |
… | |
| 1103 | } |
1103 | } |
| 1104 | } else { # $ext is not recognized |
1104 | } else { # $ext is not recognized |
| 1105 | ################################################################################ |
1105 | ################################################################################ |
| 1106 | # FILES with unrecognized file extensions in any display modes |
1106 | # FILES with unrecognized file extensions in any display modes |
| 1107 | ################################################################################ |
1107 | ################################################################################ |
| 1108 | |
1108 | |
| 1109 | warn "Error in the macro alias. Alias does not understand how to process files with extension $ext. (Path ot problem file is $main::fileName) "; |
1109 | warn "Error in the macro alias. Alias does not understand how to process files with extension $ext. (Path ot problem file is $main::fileName) "; |
| 1110 | } |
1110 | } |
| 1111 | |
1111 | |
| 1112 | warn "The macro alias was unable to form a URL for some auxiliary file used in this problem." unless $adr_output; |
1112 | warn "The macro alias was unable to form a URL for some auxiliary file used in this problem." unless $adr_output; |
| 1113 | return $adr_output; |
1113 | return $adr_output; |
| 1114 | } |
1114 | } |
| 1115 | |
1115 | |
| 1116 | |
1116 | |
| 1117 | |
1117 | |
| 1118 | |
1118 | |
| 1119 | |
1119 | |
| 1120 | # Experiments |
1120 | # Experiments |
| 1121 | |
1121 | |
| 1122 | # It is important that these subroutines using sort are evaluated before |
1122 | # It is important that these subroutines using sort are evaluated before |
| 1123 | # the problem template is evaluated. |
1123 | # the problem template is evaluated. |
| 1124 | # Once the problem template has a "my $a;" susequent sort routines will not work. |
1124 | # Once the problem template has a "my $a;" susequent sort routines will not work. |
| 1125 | # |
1125 | # |
| 1126 | # PGsort can be used as a slightly slower but safer sort within problems. |
1126 | # PGsort can be used as a slightly slower but safer sort within problems. |
| 1127 | |
1127 | |
| … | |
… | |
| 1133 | have special significance. |
1133 | have special significance. |
| 1134 | |
1134 | |
| 1135 | C<sort {$a<=>$b} @list> |
1135 | C<sort {$a<=>$b} @list> |
| 1136 | C<sort {$a cmp $b} @list> |
1136 | C<sort {$a cmp $b} @list> |
| 1137 | |
1137 | |
| 1138 | sorts the list numerically and lexically respectively. |
1138 | sorts the list numerically and lexically respectively. |
| 1139 | |
1139 | |
| 1140 | If C<my $a;> is used in a problem, before the sort routine is defined in a macro, then |
1140 | If C<my $a;> is used in a problem, before the sort routine is defined in a macro, then |
| 1141 | things get badly confused. To correct this, the following macros are defined in |
1141 | things get badly confused. To correct this, the following macros are defined in |
| 1142 | dangerougMacros.pl which is evaluated before the problem template is read. |
1142 | dangerougMacros.pl which is evaluated before the problem template is read. |
| 1143 | |
1143 | |
| … | |
… | |
| 1161 | # trouble here when there was |
1161 | # trouble here when there was |
| 1162 | # more than one ans_eval in ANS() |
1162 | # more than one ans_eval in ANS() |
| 1163 | # No-one knows why? |
1163 | # No-one knows why? |
| 1164 | |
1164 | |
| 1165 | # This allows the use of i for imaginary numbers |
1165 | # This allows the use of i for imaginary numbers |
| 1166 | # one can write 3 +2i rather than 3+2i() |
1166 | # one can write 3 +2i rather than 3+2i() |
| 1167 | # |
1167 | # |
| 1168 | |
1168 | |
| 1169 | sub i; |
1169 | sub i; |
| 1170 | |
1170 | |
| 1171 | 1; # required to load properly |
1171 | 1; # required to load properly |