Parent Directory
|
Revision Log
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/\\/g; #\ 92 \ 552 $string =~ s/\x7B/\{/g; #{ 123 { 553 $string =~ s/\x7D/\}/g; #} 125 } 554 $string =~ s/\xE7/\Á/g; #Á 231 Á 555 $string =~ s/\xE6/\Ê/g; #Ê 230 Ê 556 $string =~ s/\xE8/\Ë/g; #Ë 232 Ë 557 $string =~ s/\xF3/\Û/g; #Û 243 Û 558 $string =~ s/\xA5/\•/g; #€ 165 • 559 $string =~ s/\xB2/\≤/g; #¾ 178 ≤ 560 $string =~ s/\xB3/\≥/g; #„ 179 ≥ 561 $string =~ s/\xB6/\∂/g; # 182 ∂ 562 $string =~ s/\xCE/\Œ/g; #‘ 206 Œ 563 $string =~ s/\xD6/\˜/g; #÷ 214 ˜ 564 $string =~ s/\xD9/\Ÿ/g; # 217 Ÿ 565 $string =~ s/\xDA/\⁄/g; #Ž 218 ⁄ 566 $string =~ s/\xF5/\ı/g; #ž 245 ı 567 $string =~ s/\xF6/\ˆ/g; #– 246 ˆ 568 $string =~ s/\xF7/\Á/g; #— 247 Á 569 $string =~ s/\xF8/\¯/g; #¯ 248 ¯ 570 $string =~ s/\xF9/\˘/g; #˜ 249 ˘ 571 $string =~ s/\xFA/\˙/g; #™ 250 ˙ 572 $string =~ s/\xFB/\˚;/g; #š 251 ˚ 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 '&probNum=' . $envir->{probNum} . 866 '&Mode=' . $envir->{displayMode} . 867 '&course=' . $envir->{courseName} . 868 '&user=' . $user . 869 '&displayPath=' . $path_to_file . 870 '&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 |