[system] / trunk / pg / macros / dangerousMacros.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/dangerousMacros.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1250 - (view) (download) (as text)

1 : sh002i 1050
2 :    
3 : apizer 1080
4 : sh002i 1050 ####################################################################
5 :     # Copyright @ 1995-1999 University of Rochester
6 :     # All Rights Reserved
7 :     ####################################################################
8 :    
9 :     ####################################################################
10 :     #
11 :     # dangerousMacros.pl contains macros with potentially dangerous commands
12 : apizer 1080 # such as require and eval. They can reference disk files for reading and
13 : sh002i 1050 # 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.
15 :     #
16 :     #
17 :    
18 :     =head1 NAME
19 :    
20 :     dangerousMacros.pl --- located in the courseScripts directory
21 :    
22 :     =head1 SYNPOSIS
23 :    
24 :     loadMacros(macrofile1,macrofile2,...)
25 : apizer 1080
26 :     insertGraph(graphObject);
27 : sh002i 1050 returns a path to the file containing the graph image.
28 : apizer 1080
29 : sh002i 1050 tth(texString)
30 :     returns an HTML version of the tex code passed to it.
31 : apizer 1080
32 :     alias(pathToFile);
33 : sh002i 1050 returns URL which links to that file
34 :    
35 : apizer 1080
36 : sh002i 1050 =head1 DESCRIPTION
37 :    
38 :    
39 :     C<dangerousMacros.pl> contains macros with potentially dangerous commands
40 : apizer 1080 such as require and eval. They can reference disk files for reading and
41 : sh002i 1050 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.
43 :    
44 :     C<dangerousMacros.pl> is loaded and reinitialized
45 :     every time a new problem is rendered.
46 :    
47 :     =cut
48 :    
49 :    
50 :     ######## Dangerous macros#########
51 :     ## The macros in this file are defined while the safe compartment is wide open.
52 :     ## Be careful!
53 :     #########################################
54 :    
55 :    
56 :     =head2 Sharing modules:
57 :    
58 :     Most modules are loaded by dangerousMacros.pl
59 :    
60 :     The modules must be loaded using require (not use) since the courseScriptsDirectory is
61 :     defined at run time.
62 :    
63 :    
64 :     The following considerations come into play.
65 :    
66 :     * One needs to limit the access to modules for safety -- hence only
67 : apizer 1080 modules in the F<courseScriptsDirectory> can be loaded.
68 :    
69 : sh002i 1050 * Loading them in dangerousMacros.pl is wasteful, since the modules
70 :     would need to be reloaded everytime a new safe compartment is created.
71 :     (I believe that using require takes care of this.)
72 : apizer 1080
73 : sh002i 1050 * 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
75 :     the safe compartment.
76 : apizer 1080
77 : sh002i 1050 * Other modules loaded by translate.pl are C<Exporter> and C<DynaLoader.
78 : apizer 1080
79 : sh002i 1050 * PGrandom is loaded by F<PG.pl> , since it is needed there.
80 :    
81 :    
82 : apizer 1080
83 : sh002i 1050 The module name spaces loaded in dangerousMacros are:
84 :    
85 :     PGrandom (if not previously loaded)
86 :     WWPlot
87 :     Fun
88 :     Label
89 : apizer 1080 Circle
90 : sh002i 1050
91 :     in addition the subroutine &evaluate_units is shared from the module Units.
92 :    
93 :     =cut
94 :    
95 :     BEGIN {
96 :     be_strict(); # an alias for use strict. This means that all global variable must contain main:: as a prefix.
97 : gage 1250
98 : sh002i 1050 }
99 : gage 1069
100 : gage 1250 my $debugON = 0;
101 : gage 1069
102 : sh002i 1050 sub _dangerousMacros_init {
103 :     }
104 :    
105 :     sub _dangerousMacros_export {
106 :     my @EXPORT= (
107 :     '&_dangerousMacros_init',
108 :     '&alias',
109 :     '&compile_file',
110 :     '&insertGraph',
111 :     '&loadMacros',
112 :     '&HEADER_TEXT',
113 :     '&sourceAlias',
114 :     '&tth',
115 :     );
116 :     @EXPORT;
117 :     }
118 :    
119 :    
120 :     =head2 loadMacros
121 :    
122 :     C<loadMacros(macrofile1,macrofile2,...)>
123 :    
124 :     loadMacros takes a list of file names and evaluates the contents of each file. This is used to load macros
125 :     which define and augment the PG language. The macro files are first searched for in the macro
126 :     directory of the course C<($macroDirectory)> and then, if not found, in the WeBWorK courseScripts
127 :     directory C<($courseScriptsDirectory)> where the default behavior of the PG language is defined.
128 :    
129 :     An individual course can modify the PG language, B<for that course only>, by
130 :     duplicating one of the macro files in the courseScripts directory and placing this
131 : apizer 1080 file in the macro directory for the course. The new file in the course
132 : sh002i 1050 macro directory will now be used instead of the file in the courseScripts directory.
133 :    
134 :     The new file in the course macro directory can by modified by adding macros or modifying existing macros.
135 :    
136 :     I< Modifying macros is for users with some experience.>
137 :    
138 : apizer 1080 Modifying existing macros might break other standard macros or problems which depend on the
139 : sh002i 1050 unmodified behavior of these macors so do this with great caution.
140 : apizer 1080 In addition problems which use new macros defined in these files or which depend on the
141 : sh002i 1050 modified behavior of existing macros will not work in other courses unless the macros are also
142 :     transferred to the new course. It helps to document the problems by indicating any special macros
143 :     which the problems require.
144 :    
145 :     There is no facility for modifying or overloading a single macro. The entire file containing the macro
146 :     must be overloaded.
147 :    
148 :     Modifications to files in the course macros directory affect only that course,
149 :     they will not interfere with the normal behavior of B<WeBWorK> in other courses.
150 :    
151 :    
152 :    
153 :     =cut
154 :    
155 :     # Global variables used
156 :     # ${main::macroDirectory}
157 :     # ${main::courseScriptsDirectory}
158 :     # Global macros used
159 :     # None
160 :    
161 : apizer 1080 # Because of the need to use the directory variables it is tricky to define this
162 :     # in translate.pl since, as currently written, the directories are not available
163 : sh002i 1050 # at that time. Perhaps if I rewrite translate as an object that method will work.
164 :    
165 :     # The only difficulty with defining loadMacros inside the Safe compartment is that
166 :     # the error reporting does not work with syntax errors.
167 :     # A kludge using require works around this problem
168 :    
169 :    
170 :     my ($macroDirectory,
171 :     $courseScriptsDirectory,
172 :     $templateDirectory,
173 :     $scriptDirectory,
174 :     );
175 : apizer 1080
176 : sh002i 1050 sub loadMacros {
177 :     my @files = @_;
178 :     my $fileName;
179 : gage 1250 eval {main::time_it("begin load macros");};
180 : sh002i 1050 ###############################################################################
181 :     # At this point the directories have been defined from %envir and we can define
182 :     # the directories for this file
183 :     ###############################################################################
184 :    
185 :     $macroDirectory = eval('$main::macroDirectory') unless defined($macroDirectory);
186 :     $courseScriptsDirectory = eval('$main::courseScriptsDirectory') unless defined($courseScriptsDirectory);
187 :     $templateDirectory = eval('$main::courseScriptsDirectory') unless defined($templateDirectory);
188 :     $scriptDirectory = eval('$main::scriptDirectory') unless defined($scriptDirectory);
189 : gage 1250
190 :     unless (defined( eval('$main::externalTTHPath') and eval('$main::externalTTHPath') )){
191 : sh002i 1050 warn "WARNING::Please make sure that the DOCUMENT() statement comes before<BR>\n" .
192 :     " the loadMacros() statement in the problem template.<p>" .
193 :     " The externalTTHPath variable |$main::externalTTHPath| was\n".
194 :     " not defined which usually indicates the problem above.<br>\n";
195 : apizer 1080
196 : sh002i 1050 }
197 :     #warn "running load macros";
198 :     while (@files) {
199 :     $fileName = shift @files;
200 :     next if ($fileName =~ /^PG.pl$/) ; # the PG.pl macro package is already loaded.
201 : apizer 1080
202 : sh002i 1050 my $macro_file_name = $fileName;
203 :     $macro_file_name =~s/\.pl//; # trim off the extension
204 :     $macro_file_name =~s/\.pg//; # sometimes the extension is .pg (e.g. CAPA files)
205 :     my $init_subroutine_name = "_${macro_file_name}_init";
206 : gage 1250
207 : sh002i 1050 #no strict;
208 :     ###############################################################################
209 :     # For some reason the "no stict" which works on webwork-db doesn't work on
210 :     # webwork. For this reason the constuction &{$init_subroutine_name}
211 :     # was abandoned and replaced by eval. This is considerably more dangerous
212 :     # since one could hide something nasty in a file name.
213 :     # Keep an eye on this ???
214 :     # webwork-db used perl 5.6.1 and webwork used perl 5.6.0 It seems
215 :     # unlikely that this was the problem. Otherwise all files seemed to
216 :     # be the same.
217 : gage 1250
218 :     # local($temp::rf_init_subroutine);
219 :     # eval qq{ \$temp::rf_init_subroutine = \\&main::$init_subroutine_name;};
220 :     # #warn "loadMacros: defining \$temp::rf_init_subroutine ",$temp::rf_init_subroutine;
221 :     #
222 :     # $macro_file_loaded = defined($temp::rf_init_subroutine) && defined( &{$temp::rf_init_subroutine} );
223 : sh002i 1050 ###############################################################################
224 : gage 1250 no strict;
225 :     # warn "dangerousMacros main:: contains <br>\n ".join("<br>\n ", %main::) if $debugON;
226 :     my $init_subroutine = eval { \&{$init_subroutine_name} };
227 :     use strict;
228 :     my $macro_file_loaded = defined($init_subroutine);
229 :     warn "dangerousMacros: macro init $init_subroutine_name defined |$init_subroutine| |$macro_file_loaded|" if $debugON;
230 : sh002i 1050 # macros are searched for first in the $macroDirectory of the course
231 :     # and then in the webwork $courseScripts directory.
232 :     unless ($macro_file_loaded) {
233 :     #print STDERR "loadMacros: loading macro file $fileName\n";
234 : gage 1250 if (-r "$macroDirectory$fileName") {
235 :     compile_file("$macroDirectory$fileName");
236 : apizer 1080
237 : gage 1250 } elsif (-r "$courseScriptsDirectory$fileName" ) {
238 :     compile_file("$courseScriptsDirectory$fileName");
239 : sh002i 1050 } else {
240 : gage 1250 die "Can't locate macro file via path: |$macroDirectory$fileName| or |$courseScriptsDirectory$fileName|";
241 : sh002i 1050 }
242 :     }
243 :     # Try again to define the initialization subroutine.
244 : gage 1250 #eval qq{ \$temp::rf_init_subroutine = \\&main::$init_subroutine_name;};
245 :     no strict;
246 :     $init_subroutine = eval { \&{'main::'.$init_subroutine_name} };
247 :     use strict;
248 : sh002i 1050 #warn "loadMacros: defining \$temp::rf_init_subroutine ",$temp::rf_init_subroutine;
249 : gage 1250 warn "init file defined: $macro_file_name = ", defined(&{$init_subroutine}) if $debugON;
250 :    
251 :     if ( defined( &{$init_subroutine} ) ) {
252 : sh002i 1050
253 : gage 1250 warn "dangerousMacros: initializing $macro_file_name" if $debugON;
254 :     &$init_subroutine($main::displayMode);
255 : sh002i 1050 }
256 : gage 1250 #warn "main:: contains <br>\n $macro_file_name ".join("<br>\n $macro_file_name ", %main::);
257 : apizer 1080
258 : sh002i 1050 }
259 : gage 1250 eval{main::time_it("end load macros");};
260 : sh002i 1050 }
261 :    
262 :     # errors in compiling macros is not always being reported.
263 :     sub compile_file {
264 :     my $filePath = shift;
265 : gage 1250 warn "loading $filePath" if $debugON;
266 : sh002i 1050 local(*MACROFILE);
267 :     local($/);
268 :     $/ = undef; # allows us to treat the file as a single line
269 :     open(MACROFILE, "<$filePath") || die "Cannot open file: $filePath";
270 :     my $string = <MACROFILE>;
271 :     my ($result,$error,$fullerror) = PG_restricted_eval($string);
272 :     if ($error) { # the $fullerror report has formatting and is never empty
273 :     $fullerror =~ s/\(eval \d+\)/ $filePath\n/; # attempt to insert file name instead of eval number
274 :     die "Error detected while loading $filePath:\n$fullerror";
275 : apizer 1080
276 : sh002i 1050 }
277 :    
278 :     close(MACROFILE);
279 : apizer 1080
280 : sh002i 1050 }
281 :    
282 :     # This creates on the fly graphs
283 :    
284 :     =head2 insertGraph
285 :    
286 : apizer 1080 $filePath = insertGraph(graphObject);
287 : sh002i 1050 returns a path to the file containing the graph image.
288 :    
289 :     insertGraph(graphObject) writes a gif file to the C<html/tmp/gif> directory of the current course.
290 :     The file name
291 :     is obtained from the graphObject. Warnings are issued if errors occur while writing to
292 : apizer 1080 the file.
293 : sh002i 1050
294 :     The permissions and ownership of the file are controlled by C<$main::tmp_file_permission>
295 :     and C<$main::numericalGroupID>.
296 :    
297 :     B<Returns:> A string containing the full path to the temporary file containing the GIF image.
298 :    
299 :    
300 :    
301 :     InsertGraph draws the object $graph, stores it in "${tempDirectory}gif/$gifName.gif (or .png)" where
302 :     the $imageName is obtained from the graph object. ConvertPath and surePathToTmpFile are used to insure
303 :     that the correct directory separators are used for the platform and that the necessary directories
304 : apizer 1080 are created if they are not already present.
305 : sh002i 1050
306 :     The directory address to the file is the result. This is most often used in the construct
307 :    
308 :     TEXT(alias(insertGraph($graph)) );
309 :    
310 : apizer 1080 where alias converts the directory address to a URL when serving HTML pages and insures that
311 : sh002i 1050 an eps file is generated when creating TeX code for downloading.
312 :    
313 :     =cut
314 :    
315 :     # Global variables used:
316 : apizer 1080 # $main::tmp_file_permission,
317 : sh002i 1050 # $main::numericalGroupID
318 :    
319 :     #Global macros used:
320 :     # &convertPath
321 :     # &surePathToTmpFile
322 :    
323 :     sub insertGraph {
324 :     # Convert the image to GIF and print it on standard output
325 :     my $graph = shift;
326 :     my $extension = ($WWPlot::use_png) ? '.png' : '.gif';
327 : apizer 1080 my $fileName = $graph->imageName . $extension;
328 : sh002i 1050 my $filePath = convertPath("gif/$fileName");
329 :     $filePath = &surePathToTmpFile( $filePath );
330 :     #createFile($filePath, $main::tmp_file_permission, $main::numericalGroupID);
331 :     local(*OUTPUT); # create local file handle so it won't overwrite other open files.
332 :     open(OUTPUT, ">$filePath")||warn ("$0","Can't open $filePath<BR>","");
333 :     chmod( 0777, $filePath);
334 :     print OUTPUT $graph->draw|| warn("$0","Can't print graph to $filePath<BR>","");
335 :     close(OUTPUT)||warn("$0","Can't close $filePath<BR>","");
336 :     $filePath;
337 :     }
338 :    
339 :    
340 :    
341 :     =head2 tth
342 :    
343 :     tth(texString)
344 :     returns an HTML version of the tex code passed to it.
345 :    
346 : apizer 1080 This macro sends the texString to the filter program C<tth> created by Ian Hutchinson.
347 :     The tth program was created by Ian Hutchinson and is freely available
348 : sh002i 1050 for B<non-commerical purposes> at the C<tth> main site: C<http://hutchinson.belmont.ma.us/tth/>.
349 :    
350 :     The purpose of C<tth> is to translate text in the TeX or Latex markup language into
351 :     HTML markup as best as possible. Some symbols, such as square root symbols are not
352 :     translated completely. Macintosh users must use the "MacRoman" encoding (available in 4.0 and
353 :     higher browsers) in order to view the symbols correctly. WeBWorK attempts to force Macintosh
354 :     browsers to use this encoding when such a browser is detected.
355 :    
356 :     The contents of the file C<tthPreamble.tex> in the courses template directory are prepended
357 :     to each string. This allows one to define TeX macros which can be used in every problem.
358 :     Currently there is no default C<tthPreamble.tex> file, so if the file is not present in the
359 :     course template directory no TeX macro definitions are prepended. C<tth> already understands most
360 :     Latex commands, but will not, in general know I<AMS-Latex> commands. Additional information
361 :     on C<tth> is available at the C<tth> main site.
362 :    
363 :     This macro contains code which is system dependent and may need to be modified
364 :     to run on different systems.
365 :    
366 : apizer 1080 =for html
367 :     The link to <CODE>tth</CODE> for <STRONG>non-commerical</STRONG> is
368 : sh002i 1050 <A HREF="http://hutchinson.belmont.ma.us/tth/">http://hutchinson.belmont.ma.us/tth/</A>.
369 :     Binaries for many operating systems are available as well as the source code. Links
370 :     describing how to obtain <CODE>tth</CODE> for commerical use are also available on this page.
371 :    
372 :     =cut
373 :    
374 :    
375 :    
376 :     # This file allows the tth display.
377 :     # Global variables:
378 :     # ${main::templateDirectory}tthPreamble.tex # location of any preamble TeX commands for tth
379 :     # ${main::templateDirectory}
380 :     # ${main::scriptDirectory}tth # path to tth application
381 :     # Global macros:
382 :     # None
383 :    
384 :     my ($tthPreambleFile, $tthPreambleContents); # the contents of this file will not change during problem compilation
385 :     # it only needs to be read once
386 :     sub tth {
387 :     my $inputString = shift;
388 : apizer 1080
389 : sh002i 1050 # read the contents of the tthPreamble.tex file, unless it has already been read
390 :     unless ( defined( $tthPreambleContents) ) {
391 :     $tthPreambleFile = "${main::templateDirectory}tthPreamble.tex" if ( -r "${main::templateDirectory}tthPreamble.tex" );
392 :     if ( defined($tthPreambleFile) ) {
393 :     local(*TTHIN);
394 : apizer 1080 open (TTHIN, "${main::templateDirectory}tthPreamble.tex") || die "Can't open file ${main::templateDirectory}tthPreamble.tex";
395 : sh002i 1050 #my @tthPreambleArray = <TTHIN>;
396 :     local($/);
397 :     $/ = undef;
398 :     $tthPreambleContents = <TTHIN>;#join("",@tthPreambleArray);
399 :     close(TTHIN);
400 : apizer 1080
401 : sh002i 1050 $tthPreambleContents =~ s/(.)\n/$1%\n/g; # thanks to Jim Martino
402 :     # each line in the definition file
403 :     # should end with a % to prevent
404 :     # adding supurious paragraphs to output.
405 : apizer 1080
406 : sh002i 1050 $tthPreambleContents .="%\n"; # solves the problem if the file doesn't end with a return.
407 : apizer 1080
408 : sh002i 1050 } else {
409 :     $tthPreambleContents = "";
410 :     }
411 : apizer 1080 }
412 :    
413 : sh002i 1050 $inputString = $tthPreambleContents . $inputString;
414 :     $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.
415 : apizer 1080
416 : sh002i 1050 # $tthpath is now taken from $Global::externalTTHPath via %envir.
417 :     my $tthpath = $envir{externalTTHPath};
418 :     my $out;
419 : apizer 1080
420 : sh002i 1050 if (-x $tthpath ) {
421 : gage 1069 my $tthcmd = "$tthpath -L -f5 -u -r 2>/dev/null " . $inputString;
422 : apizer 1080 if (open(TTH, "$tthcmd |")) {
423 : sh002i 1050 local($/);
424 :     $/ = undef;
425 :     $out = <TTH>;
426 :     $/ = "\n";
427 :     close(TTH);
428 :     }else {
429 :     $out = "<BR>there has been an error in executing $tthcmd<BR>";
430 :     }
431 :     } else {
432 :     $out = "<BR> Can't execute the program tth at |$tthpath|<BR>";
433 :     }
434 :    
435 :     $out;
436 : apizer 1080 }
437 : sh002i 1050
438 : gage 1069 # possible solution to the tth font problem? Works only for iCab.
439 :     sub symbolConvert {
440 :     my $string = shift;
441 :     $string =~ s/\x5C/\&#092;/g; #\ 92 &#092;
442 :     $string =~ s/\x7B/\&#123;/g; #{ 123 &#123;
443 :     $string =~ s/\x7D/\&#125;/g; #} 125 &#125;
444 :     $string =~ s/\xE7/\&#193;/g; # 231 &#193;
445 :     $string =~ s/\xE6/\&#202;/g; # 230 &#202;
446 :     $string =~ s/\xE8/\&#203;/g; # 232 &#203;
447 :     $string =~ s/\xF3/\&#219;/g; # 243 &#219;
448 :     $string =~ s/\xA5/\&bull;/g; # 165 &bull;
449 :     $string =~ s/\xB2/\&le;/g; # 178 &le;
450 :     $string =~ s/\xB3/\&ge;/g; # 179 &ge;
451 :     $string =~ s/\xB6/\&part;/g; # 182 &part;
452 :     $string =~ s/\xCE/\&#338;/g; # 206 &#338;
453 :     $string =~ s/\xD6/\&#732/g; # 214 &#732;
454 :     $string =~ s/\xD9/\&Yuml;/g; # 217 &Yuml;
455 :     $string =~ s/\xDA/\&frasl;/g; # 218 &frasl;
456 :     $string =~ s/\xF5/\&#305;/g; # 245 &#305
457 :     $string =~ s/\xF6/\&#710;/g; # 246 &#710;
458 :     $string =~ s/\xF7/\&#193;/g; # 247 &#193;
459 :     $string =~ s/\xF8/\&#175;/g; # 248 &#175;
460 :     $string =~ s/\xF9/\&#728;/g; # 249 &#728;
461 :     $string =~ s/\xFA/\&#729;/g; # 250 &#729;
462 :     $string =~ s/\xFB/\&#730;;/g; # 251 &#730;
463 :     $string;
464 :     }
465 :    
466 : sh002i 1050 # ----- ----- ----- -----
467 :    
468 :     =head2 math2img
469 :    
470 :     math2img(texString) - returns an IMG tag pointing to an image version of the supplied TeX
471 :    
472 :     =cut
473 :    
474 :     my $math2imgCount = 0;
475 :    
476 :     sub math2img {
477 :     my $tex = shift;
478 :     my $mode = shift;
479 : apizer 1080
480 : sh002i 1050 my $sourcePath = $envir{templateDirectory} . "/" . $envir{fileName};
481 :     my $tempFile = "m2i/$envir{studentLogin}.$envir{setNumber}.$envir{probNum}."
482 :     . $math2imgCount++ . ".png";
483 :     my $tempPath = surePathToTmpFile($tempFile); #my $tempPath = "$envir{tempDirectory}$tempFile";
484 :     my $tempURL = "$envir{tempURL}/$tempFile";
485 :     my $forceRefresh = $envir{refreshMath2img};
486 :     my $imageMissing = not -e $tempPath;
487 : gage 1069 my $imageStale = (stat $sourcePath)[9] > (stat $tempPath)[9] if -e $tempPath;
488 : sh002i 1050 if ($forceRefresh or $imageMissing or $imageStale) {
489 :     # image file doesn't exist, or source file is newer then image file
490 :     #warn "math2img: refreshMath2img forcing image generation for $tempFile\n" if $forceRefresh;
491 :     #warn "math2img: $tempFile doesn't exist, so generating it\n" if $imageMissing;
492 :     #warn "math2img: source file (", (stat $sourcePath)[9], ") is newer than image file (",
493 :     # (stat $tempPath)[9], ") so re-generating image\n" if $imageStale;
494 : gage 1069 if (-e $tempPath) {
495 : sh002i 1050 unlink $tempPath or die "Failed to delete stale math2img file $tempPath: $!";
496 :     }
497 :     dvipng(
498 :     $envir{dvipngTempDir}, $envir{externalLaTeXPath},
499 :     $envir{externalDvipngPath}, $tex, $tempPath
500 :     );
501 :     }
502 : apizer 1080
503 : sh002i 1050 if (-e $tempPath) {
504 :     return "<img align=\"middle\" src=\"$tempURL\" alt=\"$tex\">" if $mode eq "inline";
505 :     return "<div align=\"center\"><img src=\"$tempURL\" alt=\"$tex\"></div>" if $mode eq "display";
506 :     } else {
507 :     return "<b>[math2img failed]</b>";
508 :     # it might be nice to call tth here as a fallback instead:
509 :     #return tth($tex);
510 :     }
511 :     };
512 :    
513 :    
514 : gage 1069 # copied from IO.pm for backward compatibility with WeBWorK1.8;
515 :     sub dvipng($$$$$) {
516 :     my (
517 :     $wd, # working directory, for latex and dvipng garbage
518 :     # (must already exist!)
519 :     $latex, # path to latex binary
520 :     $dvipng, # path to dvipng binary
521 :     $tex, # tex string representing equation
522 :     $targetPath # location of resulting image file
523 :     ) = @_;
524 : apizer 1080
525 : gage 1069 my $dvipngBroken = 0;
526 : apizer 1080
527 : gage 1069 my $texFile = "$wd/equation.tex";
528 :     my $dviFile = "$wd/equation.dvi";
529 :     my $dviFile2 = "$wd/equationequation.dvi";
530 :     my $dviCall = "equation";
531 :     my $pngFile = "$wd/equation1.png";
532 : apizer 1080
533 : gage 1069 unless (-e $wd) {
534 :     die "dvipng working directory $wd doesn't exist -- caller should have created it for us!\n";
535 :     return 0;
536 :     }
537 : apizer 1080
538 : gage 1069 # write the tex file
539 :     local *TEX;
540 :     open TEX, ">", $texFile or warn "Failed to create $texFile: $!";
541 :     print TEX <<'EOF';
542 :     % BEGIN HEADER
543 :     \batchmode
544 :     \documentclass[12pt]{article}
545 :     \usepackage{amsmath,amsfonts,amssymb}
546 :     \def\gt{>}
547 :     \def\lt{<}
548 :     \usepackage[active,textmath,displaymath]{preview}
549 :     \begin{document}
550 :     % END HEADER
551 :     EOF
552 :     print TEX "\\( \\displaystyle{$tex} \\)\n";
553 :     print TEX <<'EOF';
554 :     % BEGIN FOOTER
555 :     \end{document}
556 :     % END FOOTER
557 :     EOF
558 :     close TEX;
559 : apizer 1080
560 : gage 1069 # call latex
561 : gage 1091 system "cd $wd && $latex $texFile > /dev/null"
562 : gage 1069 and warn "Failed to call $latex with $texFile: $!";
563 : apizer 1080
564 : gage 1069 unless (-e $dviFile) {
565 :     warn "Failed to generate DVI file $dviFile";
566 :     return 0;
567 :     }
568 : apizer 1080
569 : gage 1069 if ($dvipngBroken) {
570 :     # change the name of the DVI file to get around dvipng's
571 :     # crackheadedness. This is no longer needed with the newest
572 :     # version of dvipng (10 something)
573 :     system "/bin/mv", $dviFile, $dviFile2;
574 :     }
575 : apizer 1080
576 : gage 1069 # call dvipng -- using warn instead of die passes some extra information
577 :     # back to the user the complete warning is still printed in the apache
578 :     # error log and a simple message (math2img failed) is returned to the
579 :     # webpage.
580 :     my $cmdout;
581 : gage 1091 $cmdout = system "cd $wd && $dvipng $dviCall > /dev/null"
582 : gage 1069 and warn "Failed to call$dvipng with $dviCall: $! with signal $cmdout";
583 : apizer 1080
584 : gage 1069 unless (-e $pngFile) {
585 :     warn "Failed to create PNG file $pngFile";
586 :     return 0;
587 :     }
588 : apizer 1080
589 : gage 1069 $cmdout = system "/bin/mv", $pngFile, $targetPath and warn "Failed to mv: /bin/mv $pngFile $targetPath $!. Call returned $cmdout. \n";
590 :     }
591 :    
592 :    
593 : sh002i 1050 # ----- ----- ----- -----
594 :    
595 :     =head2 alias
596 :    
597 : apizer 1080 alias(pathToFile);
598 :     returns A string describing the URL which links to GIF or html file
599 : sh002i 1050 (in HTML and Latex2HTML modes).
600 :     or a path to the appropriate eps version of a GIF file
601 :     (TeX Mode)
602 :    
603 :    
604 :    
605 :     C<alias> allows you to refer to auxiliary files which are in a directory along with
606 :     the problem definition. In addition alias creates an eps copy of GIF files when
607 : apizer 1080 downloading hard copy (TeX mode).
608 : sh002i 1050
609 :     As a rule auxiliary files that are used by
610 :     a number of problems in a course should be placed in C<html/gif> or C<html>
611 :     or in a subdirectory of the C<html> directory,
612 :     while auxiliary files which are used in only one problem should be placed in
613 :     the same directory as the problem in order to make the problem more portable.
614 :    
615 :    
616 :    
617 :     =over 4
618 :    
619 :     =item Files in the html subdirectory
620 :    
621 :     B<When not in TeX mode:>
622 :    
623 :     If the file lies under the C<html> subdirectory, then the approriate URL for the file is created.
624 :     Since the C<html> subdirectory is already accessible to the webserver no other changes need to be made.
625 :     The file path for this type of file should be the complete file path. The path should
626 :     start with the prefix defined in $Global:htmlDirectory.
627 :    
628 :     B<When in TeX mode:>
629 :    
630 :    
631 : apizer 1080 GIF files will be translated into an eps file (using system dependent code)
632 : sh002i 1050 and placed in the directory C<tmp/eps>. The full path to this file is returned
633 :     for use by TeX in producing the hard copy. (This should work even in a chrooted
634 :     environment.) in producing the hard copy. (This should work even in a chrooted
635 : apizer 1080 environment.)
636 : sh002i 1050
637 :     The conversion is done by a system dependent script
638 : apizer 1080 called C<gif2eps> which should be in the scripts directory
639 : sh002i 1050
640 :     The URL's for the other files are produced as in non-tex mode
641 :     but will of course not be active.
642 :    
643 :     =item Files in the tmp subdirectory
644 :    
645 :     B<When not in TeX mode:>
646 :    
647 :     If the file lies under the C<tmp> subdirectory, then the approriate URL for the file is created.
648 :     Since the C<tmp> subdirectory is already accessible to the webserver no other changes need to be made.
649 :     The file path for this type of file should be the complete file path. The path should
650 :     start with the prefix defined in $Global:tempDirectory.
651 :    
652 :     B<When in TeX mode:>
653 :    
654 :    
655 : apizer 1080 GIF files will be translated into an eps file (using system dependent code)
656 : sh002i 1050 and placed in the directory C<tmp/eps>. The full path to this file is returned
657 :     for use by TeX in producing the hard copy. (This should work even in a chrooted
658 : apizer 1080 environment.)
659 : sh002i 1050
660 :     The conversion is done by a system dependent script
661 : apizer 1080 called C<gif2eps> which should be in the scripts directory
662 : sh002i 1050
663 :     The URL's for the other files are produced as in non-tex mode
664 :     but will of course not be active.
665 :    
666 :     =item Files in the course template subdirectory:
667 :    
668 :     B<When not in TeX mode:>
669 :    
670 : apizer 1080 If the file lies under the course templates subdirectory,
671 : sh002i 1050 it is assumed to lie in subdirectory rooted in the directory
672 :     containing the problem template file.
673 :     An alias is created under the C<html/tmp/gif> or
674 : apizer 1080 C<html/tmp/html> directory and linked to the original file.
675 : sh002i 1050 The file path for this type of file is a relative
676 :     path rooted at the directory containing the problem template file.
677 :    
678 :     B<When in TeX mode:>
679 :    
680 :     GIF files will be translated into an eps file (using system dependent code)
681 :     and placed in the directory C<html/tmp/eps>. The full path to this file is returned
682 :     for use by TeX in producing the hard copy. (This should work even in a chrooted
683 : apizer 1080 environment.)
684 : sh002i 1050
685 :     The conversion is done by a system dependent script
686 :     called C<gif2eps> which should be in the scripts directory
687 :    
688 :     The URL's for the other files are produced as in non-tex mode
689 :     but will of course not be active.
690 :    
691 :     =back
692 :    
693 :     =cut
694 :    
695 :    
696 :    
697 :     # Currently gif, html and types are supported.
698 :     #
699 :     # If the auxiliary file path has not extension then the extension .gif isassumed.
700 :     #
701 : apizer 1080 # If the auxiliary file path leads to a file in the ${Global::htmlDirectory}
702 : sh002i 1050 # no changes are made to the file path.
703 :     #
704 : apizer 1080 # If the auxiliary file path is not complete, than it is assumed that it refers
705 : sh002i 1050 # to a subdirectoy of the directory containing the problem..
706 :     #
707 :     # The output is either the correct URL for the file
708 :     # or (in TeX mode) the complete path to the eps version of the file
709 :     # and can be used as input into the image macro.
710 :     #
711 : apizer 1080 # surePathToTmpFile takes a path and outputs the complete path:
712 : sh002i 1050 # ${main::htmlDirectory}/tmp/path
713 : apizer 1080 # It insures that all of the directories in the path have been created,
714 : sh002i 1050 # but does not create the
715 :     # final file.
716 :    
717 :     # For postscript printing, alias generates an eps version of the gif image and places
718 :     # it in the directory eps. This slows down downloading postscript versions somewhat,
719 :     # but not excessivevly.
720 : apizer 1080 # Alias does not do any garbage collection, so files and alias may accumulate and
721 : sh002i 1050 # need to be removed manually or by a reaper daemon.
722 :    
723 :    
724 :     # Global variables used:
725 :     # $main::fileName # the full path to the current problem template file
726 :     # $main::htmlDirectory
727 :     # $main::htmlURL
728 :     # $main::tempDirectory
729 :     # $main::tempURL
730 :     # $main::studentLogin
731 :     # $main::psvnNumber
732 :     # $main::setNumber
733 :     # $main::probNum
734 :     # $main::displayMode
735 :    
736 :     # Global macros used
737 :     # gif2eps An external file called by system
738 :     # surePathToTmpFile
739 :     # convertPath
740 :     # directoryFromPath
741 :    
742 :    
743 :     # This subroutine has commands which will not work on non-UNIX environments.
744 :     # system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") &&
745 :    
746 : apizer 1080
747 : sh002i 1050 # local constants $User, $psvn $setNumber $probNum $displayMode
748 :    
749 :     sub sourceAlias {
750 :     my $path_to_file = shift;
751 :     my $user = $main::inputs_ref->{user};
752 :     $user = " " unless defined($user);
753 : apizer 1080 my $out = "source.pl?probSetKey=$main::psvn".
754 : sh002i 1050 "&amp;probNum=$main::probNum" .
755 :     "&amp;Mode=$main::displayMode" .
756 : apizer 1080 "&amp;course=". $main::courseName .
757 : sh002i 1050 "&amp;user=" . $user .
758 :     "&amp;displayPath=$path_to_file" .
759 :     "&amp;key=". $main::sessionKey;
760 : apizer 1080
761 : sh002i 1050 $out;
762 :     }
763 :    
764 :    
765 :     sub alias {
766 :     # input is a path to the original auxiliary file
767 :     #my $fileName = $main::fileName;
768 :     #my $htmlDirectory = $main::htmlDirectory;
769 :     #my $htmlURL = $main::htmlURL;
770 :     #my $tempDirectory = $main::tempDirectory;
771 :     #my $tempURL = $main::tempURL;
772 :     #my $studentLogin = $main::studentLogin;
773 :     #my $psvnNumber = $main::psvnNumber;
774 :     #my $setNumber = $main::setNumber;
775 :     #my $probNum = $main::probNum;
776 :     #my $displayMode = $main::displayMode;
777 : apizer 1080
778 :    
779 : sh002i 1050 my $aux_file_path = shift @_;
780 :     warn "Empty string used as input into the function alias" unless $aux_file_path;
781 : apizer 1080
782 : sh002i 1050 # problem specific data
783 : apizer 1080 warn "The path to the current problem file template is not defined." unless $main::fileName;
784 : sh002i 1050 warn "The current studentLogin is not defined " unless $main::studentLogin;
785 :     warn "The current problem set number is not defined" if $main::setNumber eq ""; # allow for sets equal to 0
786 :     warn "The current problem number is not defined" if $main::probNum eq "";
787 :     warn "The current problem set version number (psvn) is not defined" unless $main::psvnNumber;
788 :     warn "The displayMode is not defined" unless $main::displayMode;
789 : apizer 1080
790 : sh002i 1050 # required macros
791 :     warn "The macro &surePathToTmpFile can't be found" unless defined(&surePathToTmpFile);
792 :     warn "The macro &convertPath can't be found" unless defined(&convertPath);
793 :     warn "The macro &directoryFromPath can't be found" unless defined(&directoryFromPath);
794 :     warn "Can't execute the gif2eps script at ${main::externalGif2EpsPath}" unless ( -x "${main::externalGif2EpsPath}" );
795 :     warn "Can't execute the png2eps script at ${main::externalPng2EpsPath}" unless ( -x "${main::externalPng2EpsPath}" );
796 : apizer 1080
797 : sh002i 1050 # required directory addresses (and URL address)
798 :     warn "htmlDirectory is not defined in $main::htmlDirectory" unless $main::htmlDirectory;
799 :     warn "htmlURL is not defined in \$main::htmlURL" unless $main::htmlURL;
800 :     warn "tempURL is not defined in \$main::tempURL" unless $main::tempURL;
801 :     #warn "The scripts directory is not defined in \$main::scriptDirectory" unless $main::scriptDirectory;
802 :     # with the creation of externalGif2EpsPath and externalPng2EpsPath, the scripts directory is no longer used
803 : apizer 1080
804 : sh002i 1050 # determine extension, if there is one
805 :     # if extension exists, strip and use the value for $ext
806 :     # files without extensions are considered to be picture files:
807 : apizer 1080
808 : sh002i 1050 my $ext;
809 : apizer 1080 if ($aux_file_path =~ s/\.([^\.]*)$// ) {
810 : sh002i 1050 $ext = $1;
811 : apizer 1080 } else {
812 : sh002i 1050 warn "This file name $aux_file_path did not have an extension.<BR> " .
813 :     "Every file name used as an argument to alias must have an extension.<BR> " .
814 :     "The permissable extensions are .gif, .png, and .html .<BR>";
815 :     $ext = "gif";
816 :     }
817 : apizer 1080
818 : sh002i 1050 # $adr_output is a url in HTML and Latex2HTML modes
819 :     # and a complete path in TEX mode.
820 : apizer 1080 my $adr_output;
821 : sh002i 1050
822 : apizer 1080 # in order to facilitate maintenance of this macro the routines for handling
823 : sh002i 1050 # different file types are defined separately. This involves some redundancy
824 : apizer 1080 # in the code but it makes it easier to define special handling for a new file
825 :     # type, (but harder to change the behavior for all of the file types at once
826 : sh002i 1050 # (sigh) ).
827 : apizer 1080
828 :    
829 : sh002i 1050 if ($ext eq 'html') {
830 :     ################################################################################
831 :     # .html FILES in HTML, HTML_tth, HTML_dpng, HTML_img and Latex2HTML mode
832 :     ################################################################################
833 : apizer 1080
834 :     # No changes are made for auxiliary files in the
835 : sh002i 1050 # ${Global::htmlDirectory} subtree.
836 :     if ( $aux_file_path =~ m|^$main::tempDirectory| ) {
837 :     $adr_output = $aux_file_path;
838 :     $adr_output =~ s|$main::tempDirectory|$main::tempURL/|;
839 :     $adr_output .= ".$ext";
840 :     } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) {
841 :     $adr_output = $aux_file_path;
842 :     $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|;
843 :     $adr_output .= ".$ext";
844 : apizer 1080 } else {
845 : sh002i 1050 # HTML files not in the htmlDirectory are assumed under live under the
846 :     # templateDirectory in the same directory as the problem.
847 : apizer 1080 # Create an alias file (link) in the directory html/tmp/html which
848 : sh002i 1050 # points to the original file and return the URL of this alias.
849 :     # Create all of the subdirectories of html/tmp/html which are needed
850 :     # using sure file to path.
851 : apizer 1080
852 : sh002i 1050 # $fileName is obtained from environment for PGeval
853 :     # it gives the full path to the current problem
854 : apizer 1080 my $filePath = directoryFromPath($main::fileName);
855 : sh002i 1050 my $htmlFileSource = convertPath("$main::templateDirectory${filePath}$aux_file_path.html");
856 :     my $link = "html/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext";
857 :     my $linkPath = surePathToTmpFile($link);
858 :     $adr_output = "${main::tempURL}$link";
859 :     if (-e $htmlFileSource) {
860 :     if (-e $linkPath) {
861 : apizer 1080 unlink($linkPath) || warn "Unable to unlink alias file at |$linkPath|";
862 : sh002i 1050 # destroy the old link.
863 :     }
864 :     symlink( $htmlFileSource, $linkPath)
865 :     || warn "The macro alias cannot create a link from |$linkPath| to |$htmlFileSource| <BR>" ;
866 :     } else {
867 :     warn("The macro alias cannot find an HTML file at: |$htmlFileSource|");
868 :     }
869 :     }
870 :     } elsif ($ext eq 'gif') {
871 : apizer 1080 if ( $main::displayMode eq 'HTML' ||
872 :     $main::displayMode eq 'HTML_tth'||
873 :     $main::displayMode eq 'HTML_dpng'||
874 : sh002i 1050 $main::displayMode eq 'HTML_img'||
875 :     $main::displayMode eq 'Latex2HTML') {
876 :     ################################################################################
877 :     # .gif FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes
878 :     ################################################################################
879 : apizer 1080
880 : sh002i 1050 #warn "tempDirectory is $main::tempDirectory";
881 :     #warn "file Path for auxiliary file is $aux_file_path";
882 : apizer 1080
883 : sh002i 1050 # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree.
884 :     if ( $aux_file_path =~ m|^$main::tempDirectory| ) {
885 :     $adr_output = $aux_file_path;
886 :     $adr_output =~ s|$main::tempDirectory|$main::tempURL|;
887 :     $adr_output .= ".$ext";
888 :     #warn "adress out is $adr_output";
889 :     } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) {
890 :     $adr_output = $aux_file_path;
891 :     $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|;
892 :     $adr_output .= ".$ext";
893 : apizer 1080 } else {
894 : sh002i 1050 # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory
895 :     # subtree in the same directory as the problem.
896 : apizer 1080
897 : sh002i 1050 # For a gif file the alias macro creates an alias under the html/images directory
898 :     # which points to the gif file in the problem directory.
899 :     # All of the subdirectories of html/tmp/gif which are needed are also created.
900 : apizer 1080 my $filePath = directoryFromPath($main::fileName);
901 :    
902 : sh002i 1050 # $fileName is obtained from environment for PGeval
903 :     # it gives the full path to the current problem
904 :     my $gifSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.gif");
905 :     #my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext";
906 :     my $link = "gif/$main::setNumber-prob$main::probNum-$aux_file_path.$ext";
907 : apizer 1080
908 : sh002i 1050 my $linkPath = surePathToTmpFile($link);
909 :     $adr_output = "${main::tempURL}$link";
910 :     #warn "linkPath is $linkPath";
911 :     #warn "adr_output is $adr_output";
912 :     if (-e $gifSourceFile) {
913 :     if (-e $linkPath) {
914 :     unlink($linkPath) || warn "Unable to unlink old alias file at $linkPath";
915 :     }
916 :     symlink($gifSourceFile, $linkPath)
917 :     || warn "The macro alias cannot create a link from |$linkPath| to |$gifSourceFile| <BR>" ;
918 :     } else {
919 :     warn("The macro alias cannot find a GIF file at: |$gifSourceFile|");
920 :     }
921 :     }
922 :     } elsif ($main::displayMode eq 'TeX') {
923 :     ################################################################################
924 :     # .gif FILES in TeX mode
925 :     ################################################################################
926 : apizer 1080
927 : sh002i 1050 if ($envir{texDisposition} eq "pdf") {
928 :     # We're going to create PDF files with our TeX (using pdflatex), so we
929 :     # need images in PNG format.
930 : apizer 1080
931 : sh002i 1050 my $gifFilePath;
932 : apizer 1080
933 : sh002i 1050 if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) {
934 :     # we've got a full pathname to a file
935 :     $gifFilePath = "$aux_file_path.gif";
936 :     } else {
937 :     # we assume the file is in the same directory as the problem source file
938 :     $gifFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.gif";
939 :     }
940 : apizer 1080
941 : sh002i 1050 my $gifFileName = fileFromPath($gifFilePath);
942 : apizer 1080
943 : sh002i 1050 $gifFileName =~ /^(.*)\.gif$/;
944 :     my $pngFilePath = surePathToTmpFile("$main::tempDirectory/png/$1.png");
945 :     my $returnCode = system "$envir{externalGif2PngPath} $gifFilePath $pngFilePath";
946 : apizer 1080
947 : sh002i 1050 if ($returnCode or not -e $pngFilePath) {
948 :     die "failed to convert gif->png with $envir{externalGif2PngPath}: $!\n";
949 :     }
950 : apizer 1080
951 : sh002i 1050 $adr_output = $pngFilePath;
952 :     } else {
953 :     # Since we're not creating PDF files, we're probably just using a plain
954 :     # vanilla latex. Hence, we need EPS images.
955 : apizer 1080
956 : sh002i 1050 ################################################################################
957 :     # This is statement used below is system dependent.
958 :     # Notice that the range of colors is restricted when converting to postscript to keep the files small
959 : apizer 1080 # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmtops -noturn > $adr_output"
960 :     # "cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output"
961 :     ################################################################################
962 : sh002i 1050 if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) {
963 :     # To serve an eps file copy an eps version of the gif file to the subdirectory of eps/
964 :     my $linkPath = directoryFromPath($main::fileName);
965 :    
966 :     my $gifSourceFile = "$aux_file_path.gif";
967 :     my $gifFileName = fileFromPath($gifSourceFile);
968 :     $adr_output = surePathToTmpFile("$main::tempDirectory/eps/$main::studentLogin-$main::psvnNumber-$gifFileName.eps") ;
969 :    
970 :     if (-e $gifSourceFile) {
971 :     #system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output")
972 :     system("${main::externalGif2EpsPath} $gifSourceFile $adr_output" )
973 :     && die "Unable to create eps file:\n |$adr_output| from file\n |$gifSourceFile|\n in problem $main::probNum " .
974 :     "using the system dependent script\n |${main::externalGif2EpsPath}| \n";
975 :     } else {
976 :     die "|$gifSourceFile| cannot be found. Problem number: |$main::probNum|";
977 :     }
978 :     } else {
979 :     # To serve an eps file copy an eps version of the gif file to a subdirectory of eps/
980 :     my $filePath = directoryFromPath($main::fileName);
981 :     my $gifSourceFile = "${main::templateDirectory}${filePath}$aux_file_path.gif";
982 :     #print "content-type: text/plain \n\nfileName = $fileName and aux_file_path =$aux_file_path<BR>";
983 :     $adr_output = surePathToTmpFile("eps/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.eps");
984 :    
985 :     if (-e $gifSourceFile) {
986 :     #system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") &&
987 :     #warn "Unable to create eps file: |$adr_output|\n from file\n |$gifSourceFile|\n in problem $main::probNum";
988 :     #warn "Help ${main::externalGif2EpsPath}" unless -x "${main::externalGif2EpsPath}";
989 :     system("${main::externalGif2EpsPath} $gifSourceFile $adr_output" )
990 :     && die "Unable to create eps file:\n |$adr_output| from file\n |$gifSourceFile|\n in problem $main::probNum " .
991 :     "using the system dependent script\n |${main::externalGif2EpsPath}| \n ";
992 :     } else {
993 :     die "|$gifSourceFile| cannot be found. Problem number: |$main::probNum|";
994 :     }
995 :     }
996 :     }
997 :     } else {
998 :     wwerror("Error in alias: dangerousMacros.pl","unrecognizable displayMode = $main::displayMode","");
999 :     }
1000 :     } elsif ($ext eq 'png') {
1001 : apizer 1080 if ( $main::displayMode eq 'HTML' ||
1002 :     $main::displayMode eq 'HTML_tth'||
1003 :     $main::displayMode eq 'HTML_dpng'||
1004 : sh002i 1050 $main::displayMode eq 'HTML_img'||
1005 :     $main::displayMode eq 'Latex2HTML') {
1006 :     ################################################################################
1007 :     # .png FILES in HTML, HTML_tth, HTML_dpng, HTML_img, and Latex2HTML modes
1008 :     ################################################################################
1009 : apizer 1080
1010 : sh002i 1050 #warn "tempDirectory is $main::tempDirectory";
1011 :     #warn "file Path for auxiliary file is $aux_file_path";
1012 : apizer 1080
1013 : sh002i 1050 # No changes are made for auxiliary files in the htmlDirectory or in the tempDirectory subtree.
1014 :     if ( $aux_file_path =~ m|^$main::tempDirectory| ) {
1015 :     $adr_output = $aux_file_path;
1016 :     $adr_output =~ s|$main::tempDirectory|$main::tempURL|;
1017 :     $adr_output .= ".$ext";
1018 :     #warn "adress out is $adr_output";
1019 :     } elsif ($aux_file_path =~ m|^$main::htmlDirectory| ) {
1020 :     $adr_output = $aux_file_path;
1021 :     $adr_output =~ s|$main::htmlDirectory|$main::htmlURL|;
1022 :     $adr_output .= ".$ext";
1023 : apizer 1080 } else {
1024 : sh002i 1050 # files not in the htmlDirectory sub tree are assumed to live under the templateDirectory
1025 :     # subtree in the same directory as the problem.
1026 : apizer 1080
1027 : sh002i 1050 # For a png file the alias macro creates an alias under the html/images directory
1028 :     # which points to the png file in the problem directory.
1029 :     # All of the subdirectories of html/tmp/gif which are needed are also created.
1030 : apizer 1080 my $filePath = directoryFromPath($main::fileName);
1031 :    
1032 : sh002i 1050 # $fileName is obtained from environment for PGeval
1033 :     # it gives the full path to the current problem
1034 :     my $pngSourceFile = convertPath("$main::templateDirectory${filePath}$aux_file_path.png");
1035 :     my $link = "gif/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.$ext";
1036 :     my $linkPath = surePathToTmpFile($link);
1037 :     $adr_output = "${main::tempURL}$link";
1038 :     #warn "linkPath is $linkPath";
1039 :     #warn "adr_output is $adr_output";
1040 :     if (-e $pngSourceFile) {
1041 :     if (-e $linkPath) {
1042 :     unlink($linkPath) || warn "Unable to unlink old alias file at $linkPath";
1043 :     }
1044 :     symlink($pngSourceFile, $linkPath)
1045 :     || warn "The macro alias cannot create a link from |$linkPath| to |$pngSourceFile| <BR>" ;
1046 :     } else {
1047 :     warn("The macro alias cannot find a PNG file at: |$pngSourceFile|");
1048 :     }
1049 :     }
1050 :     } elsif ($main::displayMode eq 'TeX') {
1051 :     ################################################################################
1052 :     # .png FILES in TeX mode
1053 :     ################################################################################
1054 :    
1055 :     if ($envir{texDisposition} eq "pdf") {
1056 :     # We're going to create PDF files with our TeX (using pdflatex), so we
1057 :     # need images in PNG format. what luck! they're already in PDF format!
1058 : apizer 1080
1059 : sh002i 1050 my $pngFilePath;
1060 : apizer 1080
1061 : sh002i 1050 if ($aux_file_path =~ m/^$main::htmlDirectory/ or $aux_file_path =~ m/^$main::tempDirectory/) {
1062 :     # we've got a full pathname to a file
1063 :     $pngFilePath = "$aux_file_path.png";
1064 :     } else {
1065 :     # we assume the file is in the same directory as the problem source file
1066 :     $pngFilePath = $main::templateDirectory . directoryFromPath($main::fileName) . "$aux_file_path.png";
1067 :     }
1068 : apizer 1080
1069 : sh002i 1050 $adr_output = $pngFilePath;
1070 :     } else {
1071 :     # Since we're not creating PDF files, we're probably just using a plain
1072 :     # vanilla latex. Hence, we need EPS images.
1073 : apizer 1080
1074 : sh002i 1050 ################################################################################
1075 :     # This is statement used below is system dependent.
1076 :     # Notice that the range of colors is restricted when converting to postscript to keep the files small
1077 : apizer 1080 # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmtops -noturn > $adr_output"
1078 :     # "cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn > $adr_output"
1079 : sh002i 1050 ################################################################################
1080 :    
1081 :     if ($aux_file_path =~ m|^$main::htmlDirectory| or $aux_file_path =~ m|^$main::tempDirectory|) {
1082 :     # To serve an eps file copy an eps version of the png file to the subdirectory of eps/
1083 :     my $linkPath = directoryFromPath($main::fileName);
1084 :    
1085 :     my $pngSourceFile = "$aux_file_path.png";
1086 :     my $pngFileName = fileFromPath($pngSourceFile);
1087 :     $adr_output = surePathToTmpFile("$main::tempDirectory/eps/$main::studentLogin-$main::psvnNumber-$pngFileName.eps") ;
1088 :    
1089 :     if (-e $pngSourceFile) {
1090 :     #system("cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output")
1091 :     system("${main::externalPng2EpsPath} $pngSourceFile $adr_output" )
1092 :     && die "Unable to create eps file:\n |$adr_output| from file\n |$pngSourceFile|\n in problem $main::probNum " .
1093 :     "using the system dependent script\n |${main::externalPng2EpsPath}| \n";
1094 :     } else {
1095 :     die "|$pngSourceFile| cannot be found. Problem number: |$main::probNum|";
1096 :     }
1097 :     } else {
1098 :     # To serve an eps file copy an eps version of the png file to a subdirectory of eps/
1099 :     my $filePath = directoryFromPath($main::fileName);
1100 :     my $pngSourceFile = "${main::templateDirectory}${filePath}$aux_file_path.png";
1101 :     #print "content-type: text/plain \n\nfileName = $fileName and aux_file_path =$aux_file_path<BR>";
1102 :     $adr_output = surePathToTmpFile("eps/$main::studentLogin-$main::psvnNumber-set$main::setNumber-prob$main::probNum-$aux_file_path.eps") ;
1103 :     if (-e $pngSourceFile) {
1104 :     #system("cat $pngSourceFile | /usr/math/bin/pngtopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") &&
1105 :     #warn "Unable to create eps file: |$adr_output|\n from file\n |$pngSourceFile|\n in problem $main::probNum";
1106 :     #warn "Help ${main::externalPng2EpsPath}" unless -x "${main::externalPng2EpsPath}";
1107 :     system("${main::externalPng2EpsPath} $pngSourceFile $adr_output" )
1108 :     && die "Unable to create eps file:\n |$adr_output| from file\n |$pngSourceFile|\n in problem $main::probNum " .
1109 :     "using the system dependent script\n |${main::externalPng2EpsPath}| \n ";
1110 :     } else {
1111 :     die "|$pngSourceFile| cannot be found. Problem number: |$main::probNum|";
1112 :     }
1113 :     }
1114 :     }
1115 :     } else {
1116 :     wwerror("Error in alias: dangerousMacros.pl","unrecognizable displayMode = $main::displayMode","");
1117 :     }
1118 :     } else { # $ext is not recognized
1119 :     ################################################################################
1120 :     # FILES with unrecognized file extensions in any display modes
1121 :     ################################################################################
1122 : apizer 1080
1123 : sh002i 1050 warn "Error in the macro alias. Alias does not understand how to process files with extension $ext. (Path ot problem file is $main::fileName) ";
1124 :     }
1125 : apizer 1080
1126 : sh002i 1050 warn "The macro alias was unable to form a URL for some auxiliary file used in this problem." unless $adr_output;
1127 :     return $adr_output;
1128 :     }
1129 :    
1130 :    
1131 :    
1132 :    
1133 :    
1134 :     # Experiments
1135 :    
1136 : apizer 1080 # It is important that these subroutines using sort are evaluated before
1137 : sh002i 1050 # the problem template is evaluated.
1138 :     # Once the problem template has a "my $a;" susequent sort routines will not work.
1139 :     #
1140 :     # PGsort can be used as a slightly slower but safer sort within problems.
1141 :    
1142 :    
1143 :    
1144 :     =head2 PGsort
1145 :    
1146 :     Because of the way sort is optimized in Perl, the symbols $a and $b
1147 :     have special significance.
1148 :    
1149 :     C<sort {$a<=>$b} @list>
1150 :     C<sort {$a cmp $b} @list>
1151 :    
1152 : apizer 1080 sorts the list numerically and lexically respectively.
1153 : sh002i 1050
1154 :     If C<my $a;> is used in a problem, before the sort routine is defined in a macro, then
1155 :     things get badly confused. To correct this, the following macros are defined in
1156 :     dangerougMacros.pl which is evaluated before the problem template is read.
1157 :    
1158 :     PGsort sub { $_[0] <=> $_[1] }, @list;
1159 :     PGsort sub { $_[0] cmp $_[1] }, @list;
1160 :    
1161 :     provide slightly slower, but safer, routines for the PG language. (The subroutines
1162 :     for ordering are B<required>. Note the commas!)
1163 :    
1164 :     =cut
1165 :    
1166 :    
1167 :    
1168 :     # sub PGsort {
1169 :     # my $sort_order = shift;
1170 :     # die "Must supply an ordering function with PGsort: PGsort sub {\$a cmp \$b }, \@list\n" unless ref($sort_order) eq 'CODE';
1171 :     # sort {&$sort_order($a,$b)} @_;
1172 :     # }
1173 :     # Moved to translate.pl
1174 :     # For some reason it still caused
1175 :     # trouble here when there was
1176 :     # more than one ans_eval in ANS()
1177 :     # No-one knows why?
1178 :    
1179 :     # This allows the use of i for imaginary numbers
1180 : apizer 1080 # one can write 3 +2i rather than 3+2i()
1181 : sh002i 1050 #
1182 :    
1183 :    
1184 : gage 1250 sub i {
1185 :     }
1186 :    
1187 : sh002i 1050 1; # required to load properly

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9