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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2932 - (download) (as text) (annotate)
Tue Oct 19 00:08:04 2004 UTC (15 years, 4 months ago) by dpvc
File size: 49249 byte(s)
Updated i(), j() and k() functions to check if the Parser is loaded,
and if not, return a value that will cause perl to report a better
error than calling the parser outside of its normal context.

Since the current answer checkers call perl directly to evaluate their
expressions, when a variable is used by a student that is not a
variable used by the checker, this can cause perl to try to parse
those variables as function calls, or other perl constructs (like
matches if you use 'm' or translations if you use 'y').  This is bad
(and is not a problem with the new parser).

In particular, if the student uses 'k' in a formula for which k is not
defined, for example, perl will try to call the k() function.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9