[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 5017 - (download) (as text) (annotate)
Fri Jun 22 12:40:32 2007 UTC (12 years, 8 months ago) by dpvc
File size: 51978 byte(s)
Left out a "return" in my changes of two weeks ago.  OOPS!

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9