[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 3225 - (download) (as text) (annotate)
Sat May 14 01:42:25 2005 UTC (14 years, 8 months ago) by dpvc
File size: 49552 byte(s)
Changed loadMacros() to use search for amcros files via a
user-cusomizable path of directories.  This is specified in the
global.conf file, and can include any number of directories.

The path can include "." to mean look in the .pg file's directory.
This makes it possible to store special macros files with the code
that uses them.

By default, the path is ".", the course/templates/macro directory,
then the pg/macros directory (in that order).  This duplicates the
current behaviour, except for the ".", which is new.

You must also make the updates to the global.conf,
webwork2/lib/WeBWorK/PG.pm, and webwork2/lib/WeBWorK/PG/Local/pm files.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9