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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.6244  
changed lines
  Added in v.6245

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9