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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9