[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 5407 - (download) (as text) (annotate)
Fri Aug 24 01:44:56 2007 UTC (12 years, 3 months ago) by dpvc
File size: 52453 byte(s)
Fix loadMacros() and alias() so that they find auxiliary files even
when the .pg file is in templates/tmpEdit.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9