[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 1690 - (download) (as text) (annotate)
Sun Dec 28 19:46:57 2003 UTC (15 years, 11 months ago) by gage
File size: 49352 byte(s)
Zeroed the variable storing the responses to questionnaires.  Should
fix the error on questionnaires revealed by the persistance of mod_perl
modules.

Changed warning message in dangerousMacros.pl to more accurately describe
what is wrong when the gif2eps script cannot be executed.  (Based on actual
experience running a course on webwork.math.rochester.edu -- I couldn't remember
what my own warning message implied.)
--Mike

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9