[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 3502 - (download) (as text) (annotate)
Sat Aug 13 05:54:10 2005 UTC (14 years, 4 months ago) by jj
File size: 49984 byte(s)
If a problem file sets $refreshCachedImages=1 inside the pg file, then
cached copies of on the fly graphics are ignored and the graphic is
regenerated.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9