Parent Directory
|
Revision Log
Added code to handle warning messages for the paperHeader.pg file as well as the problems. Made sure that the warning messages are protected for TeX ONLY when the output will be hard copy (i.e. when the list @PG_COMPILE_ERRORS is empty.) otherwise the warning messages are left as HTML
1 #!/usr/local/bin/webwork-perl 2 3 4 ################################################################ 5 # Copyright @1995-1999 by Michael E. Gage, Arnold K. Pizer and 6 # WeBWorK at the University of Rochester. All rights reserved. 7 ################################################################ 8 9 my $debugON=0; ## set this to 1 to save debugging information for errors in hardcopy output 10 11 use lib '.'; use webworkInit; # WeBWorKInitLine 12 require 5.001; 13 14 $/ ="\n"; 15 16 use strict; 17 use Global; 18 use Auth; 19 use CGI qw(:standard); 20 use Net::SMTP; 21 use Safe; 22 23 24 use PGtranslator; 25 #use sigtrap; 26 BEGIN { 27 # set to 1 to enable timing_log 28 # (contains information about time taken by scripts to run) 29 $main::logTimingData = 0; 30 31 # begin Timing code 32 if( $main::logTimingData == 1 ) { 33 use Benchmark; 34 $main::beginTime = new Benchmark; 35 } 36 # end Timing code 37 38 # ## Setting these time out comstants to zeros removes the time constraint completely. (zero = infinity :=) ) 39 $main::TIME_OUT_CONSTANT = 60; # one minute wait for on screen problems 40 # $main::DOWNLOAD_TIME_OUT_CONSTANT = 300; # give it five minutes 41 $main::CLASS_DOWNLOAD_TIME_OUT_CONSTANT = 1200; #twenty minutes 42 # $main::DOWNLOAD_NICE = 2; 43 $main::CLASS_DOWNLOAD_NICE = 5; # higher numbers indicated lower priorities 44 45 # ## ATTENTION: The handlers PG_floating_point_exception_handler and PG_warnings_handler 46 # ## have to be installed after CGI::Carp is called since it also 47 # ## modifes the die and warn labels. Finding the right warning mechanism using these two 48 # ## methods bears further investigation 49 # ## They are defined in Global.pm 50 $SIG{'FPE'} = \&Global::PG_floating_point_exception_handler; 51 $SIG{__WARN__}=\&Global::PG_warnings_handler; 52 $SIG{'TERM'} = sub {die '[',scalar(localtime),"] Caught a SIGTERM, Error: $! stopped at $0\n"; }; 53 $SIG{'PIPE'} = sub {$main::SIGPIPE = 1, die '[',scalar(localtime),"] Caught a SIGPIPE, Error: $! stopped at $0\n"; }; 54 $SIG{ALRM} = sub { $main::SIG_TIME_OUT = 1; exit(0) }; 55 56 alarm($main::TIME_OUT_CONSTANT); 57 # By explicitly catching the signals and dieing one forces the execution of the END statements which clean up the files. 58 # 59 }; 60 61 use vars qw ($modules_to_evaluate $extra_packages_to_be_loaded 62 ); 63 64 &CGI::ReadParse; 65 my %inputs=%main::in; 66 67 my $query = $main::in{CGI}; 68 69 # verify that the rest of the information has been received 70 my $Course = $inputs{'course'}; 71 my $User = $inputs{'user'}; 72 73 #my $psvn = $inputs{'probSetKey'}; 74 75 my @local_psvns = $query -> param('local_psvns'); 76 my $psvn = $local_psvns[0]; ## get the first one for doing problem sets 77 $inputs{'probSetKey'} = $psvn; ## only used by htmlBOTTOM 78 my $Session_key = $inputs{'key'}; 79 80 81 &Global::getCourseEnvironment($Course); 82 83 my $scriptDirectory = getWebworkScriptDirectory(); #$Global::scriptDirectory; 84 my $databaseDirectory = getCourseDatabaseDirectory(); #$Global::databaseDirectory; 85 my $courseScriptsDirectory = getCourseScriptsDirectory(); #$Global::courseScriptsDirectory; 86 my $templateDirectory = getCourseTemplateDirectory(); #$Global::templateDirectory; 87 88 # this is globally defined for the file, since it is needed for cleanup in END 89 my $tempDirectory = getCourseTempDirectory(); 90 91 eval{require "${courseScriptsDirectory}$Global::displayMacros_pl";} ; 92 eval{require "${scriptDirectory}$Global::DBglue_pl";}; 93 eval{require "${scriptDirectory}$Global::classlist_DBglue_pl";}; 94 eval{require "${scriptDirectory}$Global::HTMLglue_pl";}; 95 eval{require "${scriptDirectory}$Global::FILE_pl";} ; 96 97 98 99 #################################################################### 100 # load the modules to be used in PGtranslator 101 102 require "${courseScriptsDirectory}PG_module_list.pl" or 103 wwerror($0, "Can't read ${courseScriptsDirectory}PG_module_list.pl"); 104 #################################################################### 105 106 my $keyFile = &Global::getCourseKeyFile($Course); 107 my $permissionsFile = &getCoursePermissionsFile($Course); 108 109 ## check to see if prob set has been selected ## 110 verifyInput(); 111 112 ############################################## 113 sub verifyInput { 114 115 if(!defined($psvn) || $psvn eq "") { 116 &selectionError; # The calling script did not specify a problem set. 117 #die "Content-type: text/html\n\nThe calling script did not specify a problem set."; 118 exit(); 119 } 120 } 121 122 # log access 123 &Global::log_info('', query_string); 124 125 126 &verify_key($inputs{'user'}, $Session_key, $keyFile, $Course); 127 128 my $permissions = &get_permissions($User,$permissionsFile); 129 130 &attachProbSetRecord($psvn); 131 my $login_name_for_psvn = &getStudentLogin($psvn); 132 attachCLRecord($login_name_for_psvn); 133 134 my $setNumber=&getSetNumber($psvn); 135 $setNumber = $inputs{'setNo'} if defined $inputs{'setNo'}; ## script called from profChangeDates.pl 136 137 # keep strict happy 138 my $tempTexFileBaseName; 139 140 ###### check to see that it is after the open date 141 my ($currentTime,$odts,$ddts,$remainingTime, $TimeString); 142 $currentTime = time; 143 $odts=&getOpenDate($psvn); 144 $ddts=&getDueDate($psvn); 145 $remainingTime=$ddts-$currentTime; 146 147 if($currentTime<$odts && $permissions !=$Global::instructor_permissions) { 148 print &htmlTOP("Before open date error"); 149 print "<CENTER><h2>Sorry, cannot download or do problem set $setNumber yet. 150 <BR>It is before the open date.</h2></CENTER>"; 151 print &htmlBOTTOM("downloadPS.pl",\%inputs); 152 exit(0); 153 } 154 155 my %PSVNHashForSet = %{getPSVNHashForSet($setNumber)}; 156 my $action = $inputs{'action'}; 157 my $downloadType= $inputs{'downloadType'}; # either pdf, ps, tex, or dvi 158 159 # Verify that the problem set has been created if a psvn number has been passed 160 unless ($action eq 'Get_all_copies') { 161 unless (defined $PSVNHashForSet{$psvn} ) { 162 print &htmlTOP("Problem set version number $psvn not created"); 163 print ( "Pin number $psvn was not created for set $setNumber"); 164 print &htmlBOTTOM("downloadPS.pl", \%inputs); 165 exit(0); 166 } 167 } 168 169 my $texFile = "${login_name_for_psvn}.tempTex-CGIscript"; 170 my $save_errors=''; 171 172 if ($action eq 'Do problem set' or $action eq 'Do_problem_set') {displayProbSet();} 173 #elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') {downloadIndividualSet();} 174 elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') {downloadAllSets();} 175 elsif ($action eq 'Get_all_copies') {downloadAllSets();} 176 else {wwerror($0, "Unknown action: $action");} 177 178 179 # begin Timing code 180 # my $endTime = new Benchmark; 181 # &Global::logTimingInfo($main::beginTime,$endTime,$0,$Course,$User); 182 # end Timing code 183 184 exit; 185 ############################################# 186 187 sub displayProbSet { 188 my $studentName=&CL_getStudentName($login_name_for_psvn); 189 my $probHeaderFileName = &getProbHeaderFileName($psvn); 190 191 my @problems=sort numerical &getAllProblemsForProbSetRecord($psvn); 192 sub numerical { $a <=> $b}; 193 194 my $numberOfProblems=0; 195 my $prob; 196 foreach $prob (@problems) {$numberOfProblems++;} 197 198 199 print &probSet_htmlTOP("Problem Set $setNumber from $inputs{'course'} for $studentName"); 200 #see subroutines at the bottom of this file 201 #this allows the use of a small gif for the webwork logo 202 #and takes up less screen real estate. 203 204 print &probSet_titleBar("Problem Set $setNumber from $inputs{'course'} for $studentName"); 205 206 print <<"ENDOFHTML"; 207 <TABLE BORDER=1> 208 <TR> 209 <!-- Row 1 Column 1 --> 210 <TD> 211 212 Select one of the $numberOfProblems problems to try: 213 <FORM METHOD=POST ACTION="$Global::processProblem_CGI"> 214 <INPUT TYPE=HIDDEN NAME=probSetKey VALUE=$psvn> 215 <P> 216 <SELECT NAME=probNum SIZE=11> 217 ENDOFHTML 218 219 my ($problem,$problemAttempted, $problemStatus,$longProblemStatus); 220 foreach $problem(@problems) { 221 $problemStatus = getProblemStatus($problem,$psvn); 222 $problemAttempted = getProblemAttempted($problem,$psvn); 223 224 if (!$problemAttempted) { 225 $longProblemStatus = ''; # default value 226 } elsif ($problemStatus >= 0 and $problemStatus <=1 ) { 227 my $percentCorr = int(100*$problemStatus+.5); 228 $longProblemStatus = "${percentCorr}\% correct" 229 } else { 230 $longProblemStatus = 'unknown status'; # default value 231 } 232 print "<OPTION VALUE=$problem>Problem $problem -- $longProblemStatus </OPTION>\n"; 233 } 234 235 ## nice note to warn if there's less than one day left to complete problem set 236 if ($remainingTime<86400 && $remainingTime>0) { 237 $TimeString = "<BR><RM>Note: you have less than one day left 238 to complete this problem set</EM>"; 239 } 240 else { 241 $TimeString = ""; 242 } 243 244 print <<"ENDOFHTML"; 245 </SELECT> 246 <BR> 247 ENDOFHTML 248 249 250 my $practiceUser = $Global::practiceUser; 251 if (($currentTime > $ddts) or ($User =~ /^$practiceUser/)) { 252 print q!<INPUT type="checkbox" name="show_old_answers" value=1> Show my old answers<BR>!; 253 } 254 else { 255 print q!<INPUT type="checkbox" name="show_old_answers" checked value=1> Show my old answers<BR>!; 256 } 257 258 print &sessionKeyInputs(\%inputs); 259 my $mode = $inputs{'Mode'}; 260 $mode = $Global::htmlModeDefault unless ($mode); 261 &displaySelectModeLine($mode); ## displays mode select buttons 262 ## the sub displaySelectModeLine is in 263 ## "${courseScriptsDirectory}$Global::displayMacros_pl" 264 print <<"ENDOFHTML"; 265 <BR> 266 <INPUT TYPE=SUBMIT VALUE="Get Problem"> 267 $TimeString 268 269 </FORM> 270 271 ENDOFHTML 272 273 print "<FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P>"; 274 print &sessionKeyInputs(\%inputs); 275 276 print <<"ENDOFHTML"; 277 <INPUT TYPE=HIDDEN NAME="probSetKey" VALUE=$psvn> 278 <INPUT TYPE=SUBMIT VALUE="Problem Sets"> 279 </FORM> 280 281 282 </TD> 283 <!-- Row 1 Column 2 --> 284 <TD> 285 ENDOFHTML 286 287 288 ## process problem and save @printlines 289 my $probHeader = $Global::PROB_HEADER; # default value 290 291 if ( (defined($probHeaderFileName)) and ($probHeaderFileName =~ /\S/)) { 292 $probHeader = $probHeaderFileName; 293 } 294 ## use $probHeader as default unless $probHeaderFileName is defined 295 ## in the set definition file 296 my $source; 297 if (-e "${templateDirectory}$probHeader" ) { 298 unless (-r "${templateDirectory}$probHeader") { 299 wwerror($0, "Can't read ${templateDirectory}$probHeader"); 300 } 301 open(PROB,"<${templateDirectory}$probHeader"); 302 $source = join("",<PROB>); 303 close(PROB); 304 } 305 my %envir=defineProblemEnvir($mode,0,$psvn,$Course); 306 my $pt = new PGtranslator; #pt stands for problem translator; 307 $pt->environment(\%envir); 308 $pt->initialize(); 309 $pt-> set_mask(); 310 $pt->source_string($source); 311 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 312 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 313 $pt ->translate(); 314 my $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 315 my $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 316 my $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 317 my $PG_FLAGS_REF =$pt ->rh_flags; 318 319 320 321 my @printlines; 322 if($mode eq "HTML" || $mode eq 'HTML_tth') { 323 @printlines=@{$pt->ra_text()}; 324 } 325 elsif ($mode eq 'Latex2HTML') { 326 @printlines = &createDisplayedInsert($setNumber, 327 $probHeader,$psvn,$Course,$pt->ra_text()); 328 } 329 print @printlines; 330 print <<"ENDOFHTML"; 331 </TD> 332 </TR> 333 </TABLE> 334 ENDOFHTML 335 print &htmlBOTTOM('welcomeAction.pl', \%inputs,'probSetHelp.html'); 336 exit; 337 } ## end of problem selection form and end of sub displayProbSet 338 339 #################### 340 ## subroutines 341 #################### 342 343 $/ = "\n"; 344 sub createTexSource { 345 my $psvn = shift; 346 347 # check that the psvn corresponds to the user and that it is after the open 348 # date. This should only fail if someone is trying to break into WeBWorK. 349 350 &attachProbSetRecord($psvn); 351 $login_name_for_psvn = &getStudentLogin($psvn); 352 attachCLRecord($login_name_for_psvn); 353 354 if ( ( ( $User ne &getStudentLogin($psvn)) ||($currentTime < $odts) ) 355 and ($permissions != $Global::instructor_permissions) 356 and ($permissions != $Global::TA_permissions) 357 ) { 358 &hackerError; 359 exit; 360 } 361 362 my $probSetHeader = $Global::SET_HEADER; 363 364 my $setHeaderFileName = &getSetHeaderFileName($psvn); 365 366 my $answersRequestedQ = 0; 367 $answersRequestedQ= $inputs{'ShowAns'} if defined($inputs{'ShowAns'}); 368 369 my $adts=&getAnswerDate($psvn); 370 my $displayCorrectAnswersQ = 0; #initialize 371 $displayCorrectAnswersQ =1 if $answersRequestedQ && ($currentTime > $adts); 372 $displayCorrectAnswersQ =1 if $answersRequestedQ && ($permissions == $Global::instructor_permissions); 373 374 375 # chdir "$tempDirectory"; 376 # umask(022); 377 378 my $texSource =''; 379 380 # open(OUTPUT, ">${tempDirectory}${texFile}${psvn}.tex") 381 #|| wwerror("Can't create $tempDirectory${texFile}$psvn.tex\n"); 382 383 384 385 print STDERR "%%Creating a tex version of set $setNumber<BR>\n" if $debugON; 386 print STDERR "%%For", &CL_getStudentName($login_name_for_psvn), "psvn=$psvn<BR>\n" if $debugON; 387 388 389 # input TeX preamble 390 # print OUTPUT &texInput($Global::TEX_SET_PREAMBLE); 391 $texSource = &texInput($Global::TEX_SET_PREAMBLE); 392 393 # print TeX Header 394 # print OUTPUT &texInput($Global::TEX_SET_HEADER); 395 $texSource .= &texInput($Global::TEX_SET_HEADER); 396 397 # Print setheader 398 my $mode = "TeX"; 399 my @PG_COMPILE_ERRORS = (); 400 if ( (defined($setHeaderFileName)) and $setHeaderFileName =~ /\S/) { 401 $probSetHeader = $setHeaderFileName; 402 } 403 ## use $probSetHeader as default unless $setHeaderFileName is defined 404 ## in the set definition file 405 if ( open(INPUT,"${templateDirectory}$probSetHeader") ) { 406 407 # ##Determine language 408 409 $probSetHeader =~ /\.([^\.]*)$/; 410 my $displayMode = $1; 411 412 if ($displayMode eq 'pg') { 413 my %envir=defineProblemEnvir($mode,0, $psvn,$Course,undef()); 414 my $input_string= join("",<INPUT> ); 415 my ($PG_PROBLEM_TEXT_REF, $PG_HEADER_TEXT_REF, $PG_ANSWER_HASH_REF, $PG_FLAGS_REF); 416 my $pt = new PGtranslator; #pt stands for problem translator; 417 $pt -> evaluate_modules( @{main::modules_to_evaluate}) ; 418 $pt -> load_extra_packages(@{main::extra_packages_to_be_loaded}); 419 420 # The variables in the two preceding lines are defined in PG_module_list.pl 421 # require "${courseScriptsDirectory}PG_module_list.pl"; 422 # (Modules are defined by require statement above found near the top of this file, outside the loop.) 423 $pt->environment(\%envir); 424 $pt->initialize(); 425 $pt-> set_mask(); 426 $pt->source_string($input_string); 427 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 428 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 429 $pt ->translate(); 430 $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 431 $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 432 $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 433 $PG_FLAGS_REF =$pt ->rh_flags; 434 # print OUTPUT @{$PG_PROBLEM_TEXT_REF}; 435 $texSource .= join '', @{$PG_PROBLEM_TEXT_REF}; 436 if (defined($PG_FLAGS_REF->{'error_flag'}) and $PG_FLAGS_REF->{'error_flag'} ==1) { 437 push(@PG_COMPILE_ERRORS, qq{<A HREF="#problem0">$probSetHeader</A>} ); 438 } 439 if (defined($Global::WARNINGS) and $Global::WARNINGS) { 440 my $warnings = '{\\bf WARNINGS:\par{\\tiny ' . $Global::WARNINGS . ' }}'; 441 $warnings =~ s|/|\\\-/|g; #allow linebreaks in the middle of URLs 442 $warnings =~ s/<br>/\\par\n/ig; #introduce breaks at linebreaks and paragraphs 443 $warnings =~ s/<p>/\\par\n/ig; 444 $warnings =~ s/\#/\\\#/g; #protect against some of the symbols which are reserved in tex 445 $warnings =~ s/\_/\\\_/g; 446 $warnings =~ s/\>/\\\>/g; 447 $warnings =~ s/\</\\\</g; 448 $texSource .= $warnings; 449 } 450 $Global::WARNINGS = ''; #reset the Global::WARNINGS parameter 451 452 } else { 453 # print OUTPUT "Don't understand languages with extension $displayMode.<BR>\n"; 454 $texSource .= "Don't understand languages with extension $displayMode.<BR>\n"; 455 } 456 close INPUT; 457 } else { 458 print STDERR ( "Can't open ${templateDirectory}${probSetHeader}\n") if $debugON; 459 wwerror("$0", "\n######## Could not open the set header file: ${templateDirectory}${probSetHeader}","",""); 460 } 461 462 463 # Print problems 464 my @problems = sort {$a <=> $b } &getAllProblemsForProbSetRecord($psvn); 465 my @refSubmittedAnswers = (); 466 # print "content-type: text/plain\n\nproblems @problems"; 467 468 my $probNum; 469 foreach $probNum (@problems) { 470 my $source; 471 my $probFileName = &getProblemFileName($probNum,$psvn); 472 if (-e "${templateDirectory}$probFileName" ) { 473 unless (-r "${templateDirectory}$probFileName") { 474 wwerror($0, "Can't read ${templateDirectory}$probFileName"); 475 } 476 open(PROB,"<${templateDirectory}$probFileName"); 477 $source = join("",<PROB>); 478 close(PROB); 479 } 480 local($^W) =0; ##########CHANGE THIS BACK!!!! 481 my %envir=defineProblemEnvir('TeX',$probNum,$psvn,$Course,undef()); 482 my ($PG_PROBLEM_TEXT_REF, $PG_HEADER_TEXT_REF, $PG_ANSWER_HASH_REF, $PG_FLAGS_REF,$PG_EVALUATED_ANSWERS_REF); 483 # 484 my $pt = new PGtranslator; #pt stands for problem translator; 485 $pt->environment(\%envir) ; 486 $pt->initialize(); 487 $pt-> set_mask(); 488 $pt->source_string($source); 489 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 490 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 491 $pt ->translate(); 492 493 $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 494 $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 495 496 # $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 497 $PG_EVALUATED_ANSWERS_REF = $pt->process_answers; 498 $PG_FLAGS_REF = $pt ->rh_flags; 499 500 501 # print OUTPUT @{$PG_PROBLEM_TEXT_REF}; 502 $texSource .= join '', @{$PG_PROBLEM_TEXT_REF}; 503 504 if (defined($PG_FLAGS_REF->{'error_flag'}) and $PG_FLAGS_REF->{'error_flag'} ==1) { 505 push(@PG_COMPILE_ERRORS, qq{<A HREF="#problem$probNum">$probNum</A>} ); 506 } 507 if ($displayCorrectAnswersQ) { 508 my %correctAnswerHash = (); 509 510 511 my @correctAnswerList = (); 512 513 my %submittedAnswerHash = (); 514 if ( ref($PG_EVALUATED_ANSWERS_REF) eq 'HASH' ) { 515 %correctAnswerHash = %$PG_EVALUATED_ANSWERS_REF; 516 } else { 517 warn "ERROR: Please pass the PG answer list as a hash not a list."; 518 } 519 520 # insert answers (if any) 521 522 if ( %correctAnswerHash ) { 523 $texSource .= "Correct Answers:\\par\\begin{itemize}\n"; 524 my ($correctFlag,$normalizedCorrectAnswer, 525 $normalizedSubmittedAnswer, 526 $answerMessage) = (); 527 # determine the correct order for the answers 528 my @answer_entry_order = ( defined($pt->{PG_FLAGS_REF}->{ANSWER_ENTRY_ORDER}) ) ? 529 @{$pt->{PG_FLAGS_REF}->{ANSWER_ENTRY_ORDER}} : keys %{$pt->rh_evaluated_answers} ; 530 531 foreach my $ky (@answer_entry_order) { 532 533 $normalizedCorrectAnswer = $correctAnswerHash{$ky}->{correct_ans}; 534 $normalizedCorrectAnswer =~ s/\^/\\\^\{\}/g; 535 $normalizedCorrectAnswer =~ s/\_/\\\_/g; 536 $texSource .= "\\item $normalizedCorrectAnswer\n"; 537 538 } 539 540 $texSource .= "\\end{itemize} \\par\n"; 541 } 542 if (defined($Global::WARNINGS) and $Global::WARNINGS) { 543 my $warnings = '{\\bf WARNINGS:\par{\\tiny ' . $Global::WARNINGS . ' }}'; 544 unless (@PG_COMPILE_ERRORS) { # prepare warnings for TeX output in this case 545 $warnings =~ s|/|\\\-/|g; #allow linebreaks in the middle of URLs 546 $warnings =~ s/<br>/\\par\n/ig; #introduce breaks at linebreaks and paragraphs 547 $warnings =~ s/<p>/\\par\n/ig; 548 $warnings =~ s/\#/\\\#/g; #protect against some of the symbols which are reserved in tex 549 $warnings =~ s/\_/\\\_/g; 550 $warnings =~ s/\>/\\\>/g; 551 $warnings =~ s/\</\\\</g; 552 $texSource .= $warnings; 553 } 554 } 555 $Global::WARNINGS = ''; #reset the Global::WARNINGS parameter 556 } 557 558 559 } 560 561 # print Tex postamble 562 # print OUTPUT &texInput($Global::TEX_SET_FOOTER); 563 $texSource .= &texInput($Global::TEX_SET_FOOTER); 564 565 return \$texSource, \@PG_COMPILE_ERRORS; 566 } 567 568 ################### END main routine ################################## 569 570 sub downloadAllSets { 571 system("/usr/bin/renice +$main::CLASS_DOWNLOAD_NICE -p $$ 1>/dev/null") && warn "Could not renice process. pid $$"; 572 alarm( $main::CLASS_DOWNLOAD_TIME_OUT_CONSTANT); 573 574 my $downloadMulti = "unknown"; 575 $downloadMulti = "multistudent" if $action eq "Get_all_copies"; 576 $downloadMulti = "multiset" if $action eq "Get_hard_copy"; 577 578 my @psvns_to_download = $query->param('local_psvns'); 579 my $num_psvns_to_download = @psvns_to_download; 580 my $max_psvns_to_download = $Global::max_num_of_ps_downloads_allowed; 581 582 if($num_psvns_to_download > 1 and $permissions != $Global::instructor_permissions) { 583 wwerror("Non-professors are not permitted to download more than one problem set at a time."); 584 } 585 586 if(@psvns_to_download > $Global::max_num_of_ps_downloads_allowed) { 587 my $tooManyWhat = $downloadMulti eq "multiset" ? "problem sets" : "students"; 588 wwerror("Too many $tooManyWhat are selected for download.", 589 "The maximum number of $tooManyWhat which can be downloaded at one time is $Global::max_num_of_ps_downloads_allowed." 590 ." You selected $num_psvns_to_download. Go back and select fewer $tooManyWhat." 591 ." (This maximun is set by the variable \$max_num_of_ps_downloads_allowed in Global.pm.)"); 592 } 593 594 my ($cumulativeTexSource, $currentTexSourceRef, $currentTexSource, $currentTexErrorRef); 595 596 # this could be used when eliminating pre-foreach createTexSourceHandleErrors call 597 # s/\\end\{document\}.*?\\begin\{document\}/\n\\newpage\n/s; 598 599 $tempTexFileBaseName = "${tempDirectory}Temp_downloadAllSets_$User"; 600 my $first_psvn = $psvns_to_download[0]; 601 602 my $current_psvn = shift @psvns_to_download; 603 ($currentTexSourceRef, $currentTexErrorRef) = createTexSource($current_psvn); 604 @psvns_to_download = () if(@$currentTexErrorRef); 605 $currentTexSource = $$currentTexSourceRef; 606 $currentTexSource =~ s|\\end\{document\}\s$|\n|s; 607 $cumulativeTexSource .= $currentTexSource; 608 609 foreach $current_psvn (@psvns_to_download) { 610 ($currentTexSourceRef, $currentTexErrorRef) = createTexSource($current_psvn); 611 @psvns_to_download = () if(@$currentTexErrorRef); 612 $currentTexSource = $$currentTexSourceRef; 613 $currentTexSource =~ s|^.*?\\begin\{document\}|\n\\newpage\n|s; 614 $currentTexSource =~ s|\\end\{document\}\s$|\n|s; 615 $cumulativeTexSource .= $currentTexSource; 616 } 617 618 $cumulativeTexSource .= "\n\\end{document}\n"; 619 620 open TEXOUTPUT, ">$tempTexFileBaseName.tex" 621 or wwerror("Can't open $tempTexFileBaseName.tex for output."); 622 print TEXOUTPUT $cumulativeTexSource; 623 close TEXOUTPUT; 624 625 if(@$currentTexErrorRef) { 626 PG_error_print($tempTexFileBaseName, $current_psvn, @$currentTexErrorRef); 627 } else { 628 $downloadType = lc $downloadType; 629 my $mimeType = prepareHardcopy($tempTexFileBaseName, $downloadType); 630 631 my ($setName, $userName); 632 &attachProbSetRecord($first_psvn); 633 if($downloadMulti eq "multistudent") { 634 if($num_psvns_to_download == 1) { 635 $setName = getSetNumber($first_psvn); 636 $userName = getStudentLogin($first_psvn); 637 } else { 638 $setName = getSetNumber($first_psvn); 639 $userName = "multistudent"; 640 } 641 } elsif($downloadMulti eq "multiset") { 642 if($num_psvns_to_download == 1) { 643 $setName = getSetNumber($first_psvn); 644 $userName = getStudentLogin($first_psvn); 645 } else { 646 $setName = "multiset"; 647 $userName = getStudentLogin($first_psvn); 648 } 649 } 650 my $hardCopyName = "$Course.$userName.$setName.$downloadType"; 651 652 open(TEXINPUT, "$tempTexFileBaseName.$downloadType") 653 or wwerror($0, "Can't open $tempTexFileBaseName.$downloadType: $!\n"); 654 print "Content-type: $mimeType\n"; 655 print "Content-disposition: attachment; filename=\"$hardCopyName\"\n\n"; 656 print while (<TEXINPUT>); 657 close TEXINPUT; 658 } 659 } 660 661 sub prepareHardcopy 662 { 663 my ($texFileBaseName, $targetFormat) = @_; 664 my $mimeType; 665 666 chdir $tempDirectory; 667 668 my $dviCommandLine = "$Global::externalLatexPath $texFileBaseName.tex >/dev/null 2>/dev/null"; 669 my $psCommandLine = "$Global::externalDvipsPath -o $texFileBaseName.ps $texFileBaseName.dvi >/dev/null 2>/dev/null"; 670 my $pdfCommandLine = "$Global::externalPs2pdfPath $texFileBaseName.ps $texFileBaseName.pdf"; 671 672 # make sure that you are not using old copies of the following files: 673 unlink("$texFileBaseName.dvi","$texFileBaseName.ps", "$texFileBaseName.pdf"); 674 675 if($targetFormat eq "pdf") { 676 #system($dviCommandLine); -e "$texFileBaseName.dvi" or die "dvi generation failed."; 677 system($dviCommandLine); -e "$texFileBaseName.dvi" or &logPrint($texFileBaseName); 678 # this gives more information about pure TeX errors 679 # (i.e. the .pg file has compiled but the resulting TeX is not well formed.) 680 681 # The following commands don't usually give very useful error messages anyway so just report failure. 682 system($psCommandLine); -e "$texFileBaseName.ps" or die "ps generation failed."; 683 system($pdfCommandLine); -e "$texFileBaseName.pdf" or die "pdf generation failed."; 684 $mimeType = "application/pdf"; 685 } elsif($targetFormat eq "ps") { 686 #system($dviCommandLine); -e "$texFileBaseName.dvi" or die "dvi generation failed."; 687 system($dviCommandLine); -e "$texFileBaseName.dvi" or &logPrint($texFileBaseName); 688 # this gives more information about pure TeX errors 689 # (i.e. the .pg file has compiled but the resulting TeX is not well formed.) 690 system($psCommandLine); -e "$texFileBaseName.ps" or die "ps generation failed."; 691 $mimeType = "application/postscript"; 692 } elsif($targetFormat eq "dvi") { 693 #system($dviCommandLine); -e "$texFileBaseName.dvi" or die "dvi generation failed."; 694 system($dviCommandLine); -e "$texFileBaseName.dvi" or &logPrint($texFileBaseName); 695 # this gives more information about pure TeX errors 696 # (i.e. the .pg file has compiled but the resulting TeX is not well formed.) 697 $mimeType = "application/x-dvi"; 698 } elsif($targetFormat eq "tex") { 699 $mimeType = "application/tex"; 700 } else { 701 die "unrecognized format: $targetFormat"; 702 } 703 704 return $mimeType; 705 } 706 707 sub PG_error_print 708 { 709 my ($tempTexFileBaseName, $current_psvn, @errors) = @_; 710 711 # get set name and student name from psvn 712 &attachProbSetRecord($current_psvn); 713 my $userName = &getStudentLogin($current_psvn); 714 my $setName = &getSetNumber($current_psvn); 715 716 # print error page header 717 print &htmlTOP("PG compile error"); 718 print "<H3>PG error while compiling problem number", (@errors>1) ? 's ' : ' ', 719 join(', ', @errors), " in problem set $setName for $userName.</H3>"; 720 print "<h3>TeX source file:</h3>"; 721 722 # open temp tex file 723 if(open TEXINPUT, "$tempTexFileBaseName.tex") { 724 print "<pre>\n"; 725 my $lineNumber = 1; 726 while(<TEXINPUT>) { 727 if(/<A NAME/) { print $_; } 728 else { print protect_HTML("$lineNumber $_"), "\n"; } 729 $lineNumber++; 730 } 731 print "</pre>\n"; 732 close TEXINPUT; 733 } else { 734 print "<p>Unable to open TeX source file:<br><tt>$tempTexFileBaseName.tex</tt></p>"; 735 } 736 737 # print page footer 738 print &htmlBOTTOM("welcomeAction.pl", \%inputs); 739 exit; 740 } 741 742 # ----- 743 744 sub logPrint { 745 my $texFileBaseName=shift; 746 print &htmlTOP("TeX Error or error in creating PostScript file"); 747 open (LOGFILE, " $texFileBaseName.log") 748 || print "<H3>Can't open log file:</H3> path= $texFileBaseName.log<BR>$!<BR><BR>" ; 749 750 751 print "<H3>TeX Error Log:</H3>"; 752 my $print_error_switch = ($debugON) ? 1: 0; 753 my $out=''; 754 #warn ord $/, ord "\n", ord "\r"; 755 #warn "length of separator = ", length($/); 756 $/ = "\n"; 757 #warn ord $/, ord "\n", ord "\r"; 758 while (<LOGFILE>) { 759 $out = $_; 760 $print_error_switch = 1 if $out =~ /^!/; # after a fatal error start printing messages 761 print protect_HTML($out)."<BR>\n" if $print_error_switch; 762 } 763 close(LOGFILE); 764 765 open (TEXFILE, "$texFileBaseName.tex") 766 || print "<H3>Can't open tex source file:</H3> path= $texFileBaseName.tex:<BR> $!<BR><BR>\n"; 767 print "<BR>\n<H3>TeX Source File:</H3><BR>\n"; 768 print "<PRE>"; 769 770 my $lineNumber = 1; 771 while (<TEXFILE>) { 772 print protect_HTML("$lineNumber $_")."\n"; 773 $lineNumber++; 774 } 775 close(TEXFILE); 776 print "</PRE>"; 777 print &htmlBOTTOM("welcomeAction.pl", \%inputs); 778 } 779 sub protect_HTML { 780 my $line = shift; 781 chomp($line); 782 $line =~s/\&/&/g; 783 $line =~s/</</g; 784 $line =~s/>/>/g; 785 $line; 786 } 787 sub selectionError { 788 print &htmlTOP("Selection error"); 789 print"<H2>Error:</H2> You must first select a problem set in order to download a hard copy!\n"; 790 print "<FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P>"; 791 print &sessionKeyInputs(\%inputs); 792 print <<"ENDOFHTML"; 793 <INPUT TYPE=SUBMIT VALUE="Return to Welcome Page"> 794 </FORM> 795 ENDOFHTML 796 print &htmlBOTTOM("welcomeAction.pl", \%inputs); 797 } 798 799 sub probSet_htmlTOP { 800 my ($title, $bg_url) = @_; 801 my $background_url = $bg_url || $Global::background_plain_url; 802 803 804 my $out = <<ENDhtmlTOP; 805 content-type: text/html 806 Expires: 0 807 808 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 809 <HTML> 810 <HEAD> 811 <TITLE>$title</TITLE> 812 </HEAD> 813 <BODY BACKGROUND="$background_url"><p> 814 <P> 815 816 ENDhtmlTOP 817 $out; 818 } 819 820 sub probSet_titleBar { 821 my ($title) = @_; 822 my $title_bar = ""; 823 $title_bar .= qq{ 824 <TABLE BORDER="0" WIDTH="100%"> 825 <TR ALIGN=CENTER > 826 <TD ALIGN=LEFT > 827 <A HREF="$Global::webworkDocsURL"> 828 <IMG SRC="$Global::squareWebworkGif" BORDER=1 ALT="WeBWorK"></A> 829 </TD> 830 <TD VALIGN=MIDDLE> 831 <H2 ALIGN=CENTER> 832 $title 833 </H2> 834 </TD> 835 <TD ALIGN=RIGHT > 836 <FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P> 837 }; 838 my $inputkeys = &sessionKeyInputs(\%inputs); 839 840 $title_bar .= qq{ 841 $inputkeys 842 <INPUT TYPE=HIDDEN NAME=\"probSetKey\" VALUE=$psvn> 843 <INPUT TYPE=SUBMIT VALUE=\"Problem Sets\"> 844 </FORM> 845 </TD> 846 </TABLE> 847 }; 848 $title_bar; 849 } 850 851 sub hackerError { ## prints hacker error message 852 853 my $msg = "Attempt to hack into WeBWorK \n Remote Host is: ". remote_host()."\n"; 854 $msg .= query_string; 855 &Global::log_error('hacker error', $msg); ## log attempt 856 857 ## notify by email 858 859 my $toAdd = $Global::feedbackAddress; 860 861 my $emailMsg = "To: $toAdd 862 Subject: Attempt to hack into WeBWorK 863 864 Here are the details on the attempt to hack into weBWorK:\n 865 $msg 866 \n"; 867 868 my $smtp = Net::SMTP->new($Global::smtpServer, Timeout=>20); 869 $smtp->mail($Global::webmaster); 870 $smtp->recipient($Global::feedbackAddress); 871 $smtp->data($msg); 872 $smtp->quit; 873 874 875 # my $SENDMAIL = $Global::SENDMAIL; 876 # open (MAIL,"|$SENDMAIL"); 877 # print MAIL "$emailMsg"; 878 # close (MAIL); 879 880 print &htmlTOP("Hacker Error"), 881 "<H2>Error:Please do not try to hack into WeBWorK!</H2>", 882 startform(-action=>"${Global::cgiWebworkURL}${Global::welcomeAction_CGI}"), 883 "<p>", 884 &sessionKeyInputs(\%inputs), 885 hidden(-name=>'local_psvns', -value=>$psvn), 886 hidden(-name=>'action', -value=>'Do_problem_set'), 887 submit(-value=>"Return to Problem Set"), 888 endform(), 889 &htmlBOTTOM($0, \%inputs); 890 } 891 892 sub defineProblemEnvir { 893 my ($mode,$probNum,$psvn,$courseName,$refSubmittedAnswers) = @_; 894 my %envir=(); 895 my $loginName = &getStudentLogin($psvn); 896 ##how to put an array submittedAnswers in a hash?? 897 $envir{'refSubmittedAnswers'} = $refSubmittedAnswers if defined($refSubmittedAnswers); 898 $envir{'psvnNumber'} = $psvn; 899 $envir{'psvn'} = $psvn; 900 $envir{'studentName'} = &CL_getStudentName($loginName); 901 $envir{'studentLogin'} = $loginName; 902 $envir{'sectionName'} = &CL_getClassSection($loginName); 903 $envir{'sectionNumber'} = &CL_getClassSection($loginName); 904 $envir{'recitationName'} = &CL_getClassRecitation($loginName); 905 $envir{'recitationNumber'} = &CL_getClassRecitation($loginName); 906 $envir{'setNumber'} = &getSetNumber($psvn); 907 $envir{'questionNumber'} = $probNum; 908 $envir{'probNum'} = $probNum; 909 $envir{'openDate'} = &getOpenDate($psvn); 910 $envir{'formatedOpenDate'} = &formatDateAndTime(&getOpenDate($psvn)); 911 $envir{'formattedOpenDate'} = &formatDateAndTime(&getOpenDate($psvn)); 912 $envir{'dueDate'} = &getDueDate($psvn); 913 $envir{'formatedDueDate'} = &formatDateAndTime(&getDueDate($psvn)); 914 $envir{'formattedDueDate'} = &formatDateAndTime(&getDueDate($psvn)); 915 $envir{'answerDate'} = &getAnswerDate($psvn); 916 $envir{'formatedAnswerDate'} = &formatDateAndTime(&getAnswerDate($psvn)); 917 $envir{'formattedAnswerDate'} = &formatDateAndTime(&getAnswerDate($psvn)); 918 $envir{'problemValue'} = &getProblemValue($probNum,$psvn); 919 $envir{'fileName'} = &getProblemFileName($probNum,$psvn); 920 $envir{'probFileName'} = &getProblemFileName($probNum,$psvn); 921 $envir{'languageMode'} = $mode; 922 $envir{'displayMode'} = $mode; 923 $envir{'outputMode'} = $mode; 924 $envir{'courseName'} = $courseName; 925 $envir{'sessionKey'} = ( defined($inputs{'key'}) ) ?$inputs{'key'} : " "; 926 927 # initialize constants for PGanswermacros.pl 928 $envir{'numRelPercentTolDefault'} = getNumRelPercentTolDefault(); 929 $envir{'numZeroLevelDefault'} = getNumZeroLevelDefault(); 930 $envir{'numZeroLevelTolDefault'} = getNumZeroLevelTolDefault(); 931 $envir{'numAbsTolDefault'} = getNumAbsTolDefault(); 932 $envir{'numFormatDefault'} = getNumFormatDefault(); 933 $envir{'functRelPercentTolDefault'} = getFunctRelPercentTolDefault(); 934 $envir{'functZeroLevelDefault'} = getFunctZeroLevelDefault(); 935 $envir{'functZeroLevelTolDefault'} = getFunctZeroLevelTolDefault(); 936 $envir{'functAbsTolDefault'} = getFunctAbsTolDefault(); 937 $envir{'functNumOfPoints'} = getFunctNumOfPoints(); 938 $envir{'functVarDefault'} = getFunctVarDefault(); 939 $envir{'functLLimitDefault'} = getFunctLLimitDefault(); 940 $envir{'functULimitDefault'} = getFunctULimitDefault(); 941 $envir{'functMaxConstantOfIntegration'} = getFunctMaxConstantOfIntegration(); 942 $envir{'numOfAttempts'} = undef(); # this is defined only for problems 943 944 # defining directorys and URLs 945 $envir{'templateDirectory'} = &getCourseTemplateDirectory(); 946 $envir{'classDirectory'} = $Global::classDirectory; 947 $envir{'cgiDirectory'} = $Global::cgiDirectory; 948 $envir{'macroDirectory'} = getCourseMacroDirectory(); 949 $envir{'courseScriptsDirectory'} = getCourseScriptsDirectory(); 950 $envir{'htmlDirectory'} = getCourseHtmlDirectory(); 951 $envir{'htmlURL'} = getCourseHtmlURL(); 952 $envir{'tempDirectory'} = getCourseTempDirectory(); 953 $envir{'tempURL'} = getCourseTempURL(); 954 $envir{'scriptDirectory'} = $Global::scriptDirectory; 955 $envir{'webworkDocsURL'} = $Global::webworkDocsURL; 956 $envir{'externalTTHPath'} = $Global::externalTTHPath; 957 958 959 $envir{'inputs_ref'} = \%inputs; 960 961 962 my $seed = &getProblemSeed($probNum, $psvn); 963 $seed = 1111 unless defined($seed); 964 $envir{'problemSeed'} = $seed if defined($seed); 965 966 # here is a way to pass environment variables defined in webworkCourse.ph 967 my $k; 968 foreach $k (keys %Global::PG_environment ) { 969 $envir{$k} = $Global::PG_environment{$k}; 970 } 971 %envir; 972 } 973 974 BEGIN { 975 976 977 # This subroutine cleans up temporary files after the postscript copy has been created. 978 # 979 sub cleanup_downloadPS { 980 981 unless (defined($action ) and ($action eq 'Do problem set' or $action eq 'Do_problem_set')) { 982 my $ERRORS = $save_errors; 983 unless ($debugON) { #clean up the directory 984 eval { 985 chdir $tempDirectory; 986 unlink( 987 "#tempTexFileBaseName.dvi", 988 "$tempTexFileBaseName.ps", 989 "$tempTexFileBaseName.pdf", 990 "$tempTexFileBaseName.log", 991 "$tempTexFileBaseName.aux", 992 "$tempTexFileBaseName.tex" 993 ); 994 unlink("${tempDirectory}eps/${login_name_for_psvn}*.eps"); 995 }; # clean up 996 $ERRORS .= $ERRORS . $@; 997 } 998 my $query = query_string(); 999 $query = "" unless defined($query); 1000 wwerror("$0", "ERROR: in downloadPS subroutine of welcomeAction.pl $ERRORS","","",$query) if $ERRORS; 1001 } 1002 } 1003 } 1004 1005 END { 1006 if (defined($main::SIG_TIME_OUT) && $main::SIG_TIME_OUT == 1) { 1007 alarm(0); # turn off the alarm 1008 my $hard_copy_message = qq{Content-type: text/html\n\n 1009 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 1010 <HTML><BODY BGCOLOR = "FF99CC"> 1011 <BLOCKQUOTE><H3>WeBWorK hard copy download time out.</H3>\n 1012 <H4>This download was cancelled because it took more than $main::TIME_OUT_CONSTANT seconds.</H4> This may be because the 1013 WeBWorK server is extraordinarily busy, or because there was an error in the problem, 1014 or because you tried to download a set with too many problems (more than 50).<P>\n 1015 Use the back button to return to the previous page and try again.<BR>\n 1016 If the problem is repeated you can report this to your instructor using the feedback button. 1017 <P> 1018 Because the WeBWorK server at the Unversity of Rochester is experiencing heavy use we have made downloading 1019 hard copies a low priority during the times of very heavy useage. It will be helpful if you 1020 download hard copies during times when the load is not too heavy. 1021 <P> 1022 The load is usually heaviest in the evenings , particularly a few hours before assignments 1023 are due. The best times to download hard copies are in the morning and afternoon 1024 -- or an hour after the due date and time of the previous assignment -- nobody is using the system then :-) 1025 </BLOCKQUOTE></BODY></HTML> 1026 }; 1027 my $do_problem_message = qq{Content-type: text/html\n\n 1028 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 1029 <HTML><BODY BGCOLOR = "FF99CC"> 1030 <BLOCKQUOTE><H3>WeBWorK heavy useage time out.</H3>\n 1031 <H4>Your request (action = $action) was cancelled because it took more than $main::TIME_OUT_CONSTANT seconds.</H4> 1032 This is probably because the 1033 WeBWorK server is extraordinarily busy.<P>\n 1034 You should be warned that WeBWorK response will be unusually slow. If possible you should try 1035 to use WeBWorK at another time when the load is not as high. The highest useage periods are in the 1036 evening, particularly in the two hours before assignments are due.<P>\n 1037 Use the back button to return to the previous page and try again.<P>\n 1038 If the high useage problem continues you can report this to your instructor using the feedback button. 1039 <P> 1040 1041 </BLOCKQUOTE></BODY></HTML> 1042 }; 1043 if ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') { 1044 print $hard_copy_message; 1045 } else{ 1046 print $do_problem_message; 1047 } 1048 1049 1050 } 1051 1052 # begin Timing code 1053 if( $main::logTimingData == 1 ) { 1054 my $endTime = new Benchmark; 1055 my $error_str=''; 1056 1057 if ($main::SIGPIPE) { 1058 $error_str = 'broken PIPE--'; 1059 } 1060 elsif ($main::SIG_TIME_OUT) { 1061 $error_str = "TIME_OUT after $main::TIME_OUT_CONSTANT secs --"; 1062 } 1063 elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') { 1064 $error_str = 'successful download -- '; 1065 } 1066 1067 &Global::logTimingInfo($main::beginTime,$endTime,$error_str.'welcomeAction.pl',$Course,$User); 1068 } 1069 # end Timing code 1070 cleanup_downloadPS(); 1071 } 1072 1073 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |