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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9