Parent Directory
|
Revision Log
nothing should change
1 #!/usr/local/bin/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'} = \&PG_floating_point_exception_handler; 51 $SIG{__WARN__}=\&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 138 139 ###### check to see that it is after the open date 140 my ($currentTime,$odts,$ddts,$remainingTime, $TimeString); 141 $currentTime = time; 142 $odts=&getOpenDate($psvn); 143 $ddts=&getDueDate($psvn); 144 $remainingTime=$ddts-$currentTime; 145 146 if($currentTime<$odts && $permissions !=$Global::instructor_permissions) { 147 print &htmlTOP("Before open date error"); 148 print "<CENTER><h2>Sorry, cannot download or do problem set $setNumber yet. 149 <BR>It is before the open date.</h2></CENTER>"; 150 print &htmlBOTTOM("downloadPS.pl",\%inputs); 151 exit(0); 152 } 153 154 my %PSVNHashForSet = %{getPSVNHashForSet($setNumber)}; 155 my $action = $inputs{'action'}; 156 my $downloadType= $inputs{'downloadType'}; # either pdf, ps, tex, or dvi 157 158 # Verify that the problem set has been created if a psvn number has been passed 159 unless ($action eq 'Get_all_copies') { 160 unless (defined $PSVNHashForSet{$psvn} ) { 161 print &htmlTOP("Problem set version number $psvn not created"); 162 print ( "Pin number $psvn was not created for set $setNumber"); 163 print &htmlBOTTOM("downloadPS.pl", \%inputs); 164 exit(0); 165 } 166 } 167 168 my $texFile = "${login_name_for_psvn}.tempTex-CGIscript"; 169 my $save_errors=''; 170 171 if ($action eq 'Do problem set' or $action eq 'Do_problem_set') {displayProbSet();} 172 #elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') {downloadIndividualSet();} 173 elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') {downloadAllSets();} 174 elsif ($action eq 'Get_all_copies') {downloadAllSets();} 175 else {wwerror($0, "Unknown action: $action");} 176 177 178 # begin Timing code 179 # my $endTime = new Benchmark; 180 # &Global::logTimingInfo($main::beginTime,$endTime,$0,$Course,$User); 181 # end Timing code 182 183 exit; 184 ############################################# 185 186 sub displayProbSet { 187 my $studentName=&CL_getStudentName($login_name_for_psvn); 188 my $probHeaderFileName = &getProbHeaderFileName($psvn); 189 190 my @problems=sort numerical &getAllProblemsForProbSetRecord($psvn); 191 sub numerical { $a <=> $b}; 192 193 my $numberOfProblems=0; 194 my $prob; 195 foreach $prob (@problems) {$numberOfProblems++;} 196 197 198 print &probSet_htmlTOP("Problem Set $setNumber from $inputs{'course'} for $studentName"); 199 #see subroutines at the bottom of this file 200 #this allows the use of a small gif for the webwork logo 201 #and takes up less screen real estate. 202 203 print &probSet_titleBar("Problem Set $setNumber from $inputs{'course'} for $studentName"); 204 205 print <<"ENDOFHTML"; 206 <TABLE BORDER=1> 207 <TR> 208 <!-- Row 1 Column 1 --> 209 <TD> 210 211 Select one of the $numberOfProblems problems to try: 212 <FORM METHOD=POST ACTION="$Global::processProblem_CGI"> 213 <INPUT TYPE=HIDDEN NAME=probSetKey VALUE=$psvn> 214 <P> 215 <SELECT NAME=probNum SIZE=11> 216 ENDOFHTML 217 218 my ($problem,$problemAttempted, $problemStatus,$longProblemStatus); 219 foreach $problem(@problems) { 220 $problemStatus = getProblemStatus($problem,$psvn); 221 $problemAttempted = getProblemAttempted($problem,$psvn); 222 223 if (!$problemAttempted) { 224 $longProblemStatus = ''; # default value 225 } elsif ($problemStatus >= 0 and $problemStatus <=1 ) { 226 my $percentCorr = int(100*$problemStatus+.5); 227 $longProblemStatus = "${percentCorr}\% correct" 228 } else { 229 $longProblemStatus = 'unknown status'; # default value 230 } 231 print "<OPTION VALUE=$problem>Problem $problem -- $longProblemStatus </OPTION>\n"; 232 } 233 234 ## nice note to warn if there's less than one day left to complete problem set 235 if ($remainingTime<86400 && $remainingTime>0) { 236 $TimeString = "<BR><RM>Note: you have less than one day left 237 to complete this problem set</EM>"; 238 } 239 else { 240 $TimeString = ""; 241 } 242 243 print <<"ENDOFHTML"; 244 </SELECT> 245 <BR> 246 ENDOFHTML 247 248 249 print &sessionKeyInputs(\%inputs); 250 my $mode = $inputs{'Mode'}; 251 $mode = $Global::htmlModeDefault unless ($mode); 252 &displaySelectModeLine($mode); ## displays mode select buttons 253 ## the sub displaySelectModeLine is in 254 ## "${courseScriptsDirectory}$Global::displayMacros_pl" 255 print <<"ENDOFHTML"; 256 <BR> 257 <INPUT TYPE=SUBMIT VALUE="Get Problem"> 258 $TimeString 259 260 </FORM> 261 262 ENDOFHTML 263 264 print "<FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P>"; 265 print &sessionKeyInputs(\%inputs); 266 267 print <<"ENDOFHTML"; 268 <INPUT TYPE=HIDDEN NAME="probSetKey" VALUE=$psvn> 269 <INPUT TYPE=SUBMIT VALUE="Problem Sets"> 270 </FORM> 271 272 273 </TD> 274 <!-- Row 1 Column 2 --> 275 <TD> 276 ENDOFHTML 277 278 279 ## process problem and save @printlines 280 my $probHeader = $Global::PROB_HEADER; # default value 281 282 if ( (defined($probHeaderFileName)) and ($probHeaderFileName =~ /\S/)) { 283 $probHeader = $probHeaderFileName; 284 } 285 ## use $probHeader as default unless $probHeaderFileName is defined 286 ## in the set definition file 287 my $source; 288 if (-e "${templateDirectory}$probHeader" ) { 289 unless (-r "${templateDirectory}$probHeader") { 290 wwerror($0, "Can't read ${templateDirectory}$probHeader"); 291 } 292 open(PROB,"<${templateDirectory}$probHeader"); 293 $source = join("",<PROB>); 294 close(PROB); 295 } 296 my %envir=defineProblemEnvir($mode,0,$psvn,$Course); 297 my $pt = new PGtranslator; #pt stands for problem translator; 298 $pt->environment(\%envir); 299 $pt->initialize(); 300 $pt-> set_mask(); 301 $pt->source_string($source); 302 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 303 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 304 $pt ->translate(); 305 my $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 306 my $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 307 my $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 308 my $PG_FLAGS_REF =$pt ->rh_flags; 309 310 311 312 my @printlines; 313 if($mode eq "HTML" || $mode eq 'HTML_tth') { 314 @printlines=@{$pt->ra_text()}; 315 } 316 elsif ($mode eq 'Latex2HTML') { 317 @printlines = &createDisplayedInsert($setNumber, 318 $probHeader,$psvn,$Course,$pt->ra_text()); 319 } 320 print @printlines; 321 print <<"ENDOFHTML"; 322 </TD> 323 </TR> 324 </TABLE> 325 ENDOFHTML 326 print &htmlBOTTOM('welcomeAction.pl', \%inputs,'probSetHelp.html'); 327 exit; 328 } ## end of problem selection form and end of sub displayProbSet 329 330 #################### 331 ## subroutines 332 #################### 333 334 $/ = "\n"; 335 sub createTexSource { 336 my $psvn = shift; 337 338 # check that the psvn corresponds to the user and that it is after the open 339 # date. This should only fail if someone is trying to break into WeBWorK. 340 341 &attachProbSetRecord($psvn); 342 $login_name_for_psvn = &getStudentLogin($psvn); 343 attachCLRecord($login_name_for_psvn); 344 345 if ( ( ( $User ne &getStudentLogin($psvn)) ||($currentTime < $odts) ) 346 and ($permissions != $Global::instructor_permissions) 347 and ($permissions != $Global::TA_permissions) 348 ) { 349 &hackerError; 350 exit; 351 } 352 353 my $probSetHeader = $Global::SET_HEADER; 354 355 my $setHeaderFileName = &getSetHeaderFileName($psvn); 356 357 my $answersRequestedQ = 0; 358 $answersRequestedQ= $inputs{'ShowAns'} if defined($inputs{'ShowAns'}); 359 360 my $adts=&getAnswerDate($psvn); 361 my $displayCorrectAnswersQ = 0; #initialize 362 $displayCorrectAnswersQ =1 if $answersRequestedQ && ($currentTime > $adts); 363 $displayCorrectAnswersQ =1 if $answersRequestedQ && ($permissions == $Global::instructor_permissions); 364 365 366 # chdir "$tempDirectory"; 367 # umask(022); 368 369 my $texSource =''; 370 371 # open(OUTPUT, ">${tempDirectory}${texFile}${psvn}.tex") 372 #|| wwerror("Can't create $tempDirectory${texFile}$psvn.tex\n"); 373 374 375 376 print STDERR "%%Creating a tex version of set $setNumber<BR>\n" if $debugON; 377 print STDERR "%%For", &CL_getStudentName($login_name_for_psvn), "psvn=$psvn<BR>\n" if $debugON; 378 379 380 # input TeX preamble 381 # print OUTPUT &texInput($Global::TEX_SET_PREAMBLE); 382 $texSource = &texInput($Global::TEX_SET_PREAMBLE); 383 384 # print TeX Header 385 # print OUTPUT &texInput($Global::TEX_SET_HEADER); 386 $texSource .= &texInput($Global::TEX_SET_HEADER); 387 388 # Print setheader 389 my $mode = "TeX"; 390 my @PG_COMPILE_ERRORS = (); 391 if ( (defined($setHeaderFileName)) and $setHeaderFileName =~ /\S/) { 392 $probSetHeader = $setHeaderFileName; 393 } 394 ## use $probSetHeader as default unless $setHeaderFileName is defined 395 ## in the set definition file 396 if ( open(INPUT,"${templateDirectory}$probSetHeader") ) { 397 398 # ##Determine language 399 400 $probSetHeader =~ /\.([^\.]*)$/; 401 my $displayMode = $1; 402 403 if ($displayMode eq 'pg') { 404 my %envir=defineProblemEnvir($mode,0, $psvn,$Course,undef()); 405 my $input_string= join("",<INPUT> ); 406 my ($PG_PROBLEM_TEXT_REF, $PG_HEADER_TEXT_REF, $PG_ANSWER_HASH_REF, $PG_FLAGS_REF); 407 my $pt = new PGtranslator; #pt stands for problem translator; 408 $pt -> evaluate_modules( @{main::modules_to_evaluate}) ; 409 $pt -> load_extra_packages(@{main::extra_packages_to_be_loaded}); 410 411 # The variables in the two preceding lines are defined in PG_module_list.pl 412 # require "${courseScriptsDirectory}PG_module_list.pl"; 413 # (Modules are defined by require statement above found near the top of this file, outside the loop.) 414 $pt->environment(\%envir); 415 $pt->initialize(); 416 $pt-> set_mask(); 417 $pt->source_string($input_string); 418 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 419 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 420 $pt ->translate(); 421 $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 422 $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 423 $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 424 $PG_FLAGS_REF =$pt ->rh_flags; 425 # print OUTPUT @{$PG_PROBLEM_TEXT_REF}; 426 $texSource .= join '', @{$PG_PROBLEM_TEXT_REF}; 427 428 } else { 429 # print OUTPUT "Don't understand languages with extension $displayMode.<BR>\n"; 430 $texSource .= "Don't understand languages with extension $displayMode.<BR>\n"; 431 } 432 close INPUT; 433 } else { 434 print STDERR ( "Can't open ${templateDirectory}${probSetHeader}\n") if $debugON; 435 wwerror("$0", "\n######## Could not open the set header file: ${templateDirectory}${probSetHeader}","",""); 436 } 437 438 439 # Print problems 440 my @problems = sort {$a <=> $b } &getAllProblemsForProbSetRecord($psvn); 441 my @refSubmittedAnswers = (); 442 # print "content-type: text/plain\n\nproblems @problems"; 443 444 my $probNum; 445 foreach $probNum (@problems) { 446 my $source; 447 my $probFileName = &getProblemFileName($probNum,$psvn); 448 if (-e "${templateDirectory}$probFileName" ) { 449 unless (-r "${templateDirectory}$probFileName") { 450 wwerror($0, "Can't read ${templateDirectory}$probFileName"); 451 } 452 open(PROB,"<${templateDirectory}$probFileName"); 453 $source = join("",<PROB>); 454 close(PROB); 455 } 456 local($^W) =0; ##########CHANGE THIS BACK!!!! 457 my %envir=defineProblemEnvir('TeX',$probNum,$psvn,$Course,undef()); 458 my ($PG_PROBLEM_TEXT_REF, $PG_HEADER_TEXT_REF, $PG_ANSWER_HASH_REF, $PG_FLAGS_REF,$PG_EVALUATED_ANSWERS_REF); 459 # 460 my $pt = new PGtranslator; #pt stands for problem translator; 461 $pt->environment(\%envir) ; 462 $pt->initialize(); 463 $pt-> set_mask(); 464 $pt->source_string($source); 465 $pt -> unrestricted_load("${courseScriptsDirectory}PG.pl"); 466 $pt -> unrestricted_load("${courseScriptsDirectory}dangerousMacros.pl"); 467 $pt ->translate(); 468 469 $PG_PROBLEM_TEXT_REF = $pt->ra_text(); 470 $PG_HEADER_TEXT_REF = $pt->r_header;#\$PG_HEADER_TEXT; 471 472 # $PG_ANSWER_HASH_REF = $pt->rh_correct_answers; 473 $PG_EVALUATED_ANSWERS_REF = $pt->process_answers; 474 $PG_FLAGS_REF = $pt ->rh_flags; 475 476 477 print OUTPUT @{$PG_PROBLEM_TEXT_REF}; 478 $texSource .= join '', @{$PG_PROBLEM_TEXT_REF}; 479 480 if (defined($PG_FLAGS_REF->{'error_flag'}) and $PG_FLAGS_REF->{'error_flag'} ==1) { 481 push(@PG_COMPILE_ERRORS, qq{<A HREF="#problem$probNum">$probNum</A>} ); 482 } 483 if ($displayCorrectAnswersQ) { 484 my %correctAnswerHash = (); 485 486 487 my @correctAnswerList = (); 488 489 my %submittedAnswerHash = (); 490 if ( ref($PG_EVALUATED_ANSWERS_REF) eq 'HASH' ) { 491 %correctAnswerHash = %$PG_EVALUATED_ANSWERS_REF; 492 } else { 493 warn "ERROR: Please pass the PG answer list as a hash not a list."; 494 } 495 496 # insert answers (if any) 497 498 if ( %correctAnswerHash ) { 499 $texSource .= "Correct Answers:\\par\\begin{itemize}\n"; 500 my ($correctFlag,$normalizedCorrectAnswer, 501 $normalizedSubmittedAnswer, 502 $answerMessage) = (); 503 # determine the correct order for the answers 504 my @answer_entry_order = ( defined($pt->{PG_FLAGS_REF}->{ANSWER_ENTRY_ORDER}) ) ? 505 @{$pt->{PG_FLAGS_REF}->{ANSWER_ENTRY_ORDER}} : keys %{$pt->rh_evaluated_answers} ; 506 507 foreach my $ky (@answer_entry_order) { 508 509 $normalizedCorrectAnswer = $correctAnswerHash{$ky}->{correct_ans}; 510 $normalizedCorrectAnswer =~ s/\^/\\\^\{\}/g; 511 $normalizedCorrectAnswer =~ s/\_/\\\_/g; 512 $texSource .= "\\item $normalizedCorrectAnswer\n"; 513 514 } 515 516 $texSource .= "\\end{itemize} \\par\n"; 517 } 518 } 519 520 521 } 522 523 # print Tex postamble 524 # print OUTPUT &texInput($Global::TEX_SET_FOOTER); 525 $texSource .= &texInput($Global::TEX_SET_FOOTER); 526 527 return \$texSource, \@PG_COMPILE_ERRORS; 528 } 529 530 ################### END main routine ################################## 531 532 sub downloadPS { 533 my $psvn = shift; 534 my $texFile = shift; 535 536 my ($texSourceRef, $errorRef) = &createTexSource($psvn); 537 538 539 open(OUTPUT, ">${tempDirectory}${texFile}${psvn}.tex") 540 || wwerror("Can't create $tempDirectory${texFile}$psvn.tex\n"); 541 print OUTPUT $$texSourceRef; 542 close OUTPUT; 543 544 545 print STDERR "Finished making tex file $tempDirectory${texFile}$psvn.tex <br>\n\n" if $debugON; 546 # chdir "$tempDirectory"; 547 # umask(022); 548 549 # Now that the complete TeX version of the problem set has been 550 # constructed in the $tempDirectory We first attempt to convert it to 551 # postscript, first running TeX and then running dvips The system commands 552 # for this are located in the file makePS which is in the script directory. 553 # If this command fails then an error is reported, otherwise &psPrint 554 # ships the postscript file off to the client which requested the download. 555 my @PG_COMPILE_ERRORS = @$errorRef; 556 if ( @PG_COMPILE_ERRORS ) { 557 &PG_error_print(@PG_COMPILE_ERRORS); 558 # $PG_COMPILE_ERRORS contains the number of the first problem with an error. 559 return 'errors'; 560 } 561 else {return 'no_errors';} 562 } 563 564 565 sub psPrint { 566 open(INPUT, "$tempDirectory${texFile}$psvn.ps") 567 or wwerror( $0, "Can't open $tempDirectory${texFile}$psvn.ps: $!\n", "", ""); 568 569 print "Content-disposition: attachment; filename= \"${login_name_for_psvn}_Set${setNumber}.ps\"\n"; 570 print "Content-type: application/postscript\n\n"; 571 while (<INPUT>) { 572 print; 573 } 574 close INPUT; 575 print STDERR "Finished TeX $texFile for $login_name_for_psvn in $Course\n" if $debugON; 576 577 } 578 579 sub pdfPrint { 580 581 system( "${scriptDirectory}makePDF $tempDirectory ${texFile}$psvn 1>&2" ) == 0 582 or wwerror("$0", "Unable to create PDF output using makePDF file:<BR> ${scriptDirectory}makePDF $tempDirectory ${texFile}$psvn 1>&2<BR>Error is: $!", "", ""); 583 open(INPUT, "$tempDirectory${texFile}$psvn.pdf") 584 || wwerror("$0", "Can't open $tempDirectory${texFile}$psvn.pdf: $!\n","",""); 585 586 print "Content-type: application/pdf\n\n" ; 587 print "Content-disposition: attachment; filename= \"${login_name_for_psvn}_Set${setNumber}.pdf\"\n"; 588 #print "Content-type: application/pdf\n\n" ; 589 while (<INPUT>) { 590 print; 591 } 592 close INPUT; 593 print STDERR "Finished TeX $texFile for $login_name_for_psvn in $Course\n" if $debugON; 594 595 } 596 597 sub texPrint { 598 open(INPUT, "$tempDirectory${texFile}$psvn.tex") || 599 wwerror("$0", "Can't open $tempDirectory${texFile}$psvn.tex:<BR> $!\n", "", ""); 600 601 print "Content-disposition: attachment; filename= \"${login_name_for_psvn}_Set${setNumber}.tex\"\n"; 602 print "Content-type: application/tex\n\n"; 603 604 while (<INPUT>) { 605 print; 606 } 607 close INPUT; 608 } 609 610 sub dviPrint { 611 open(INPUT, "$tempDirectory${texFile}$psvn.dvi") || 612 wwerror("$0", "Can't open $tempDirectory${texFile}$psvn.dvi:<BR> $!\n", "", ""); 613 614 print "Content-disposition: attachment; filename= \"${login_name_for_psvn}_Set${setNumber}.dvi\"\n"; 615 print "Content-type: application/x-dvi\n\n" ; 616 while (<INPUT>) { 617 print; 618 } 619 close INPUT; 620 } 621 622 sub logPrint { 623 print &htmlTOP("TeX Error or error in creating PostScript file"); 624 open (LOGFILE, " $tempDirectory$texFile$psvn.log") 625 || print "<H3>Can't open log file:</H3> path= $tempDirectory$texFile$psvn.log<BR>$!<BR><BR>" ; 626 627 628 print "<H3>TeX Error Log:</H3>"; 629 my $print_error_switch = ($debugON) ? 1: 0; 630 my $out=''; 631 #warn ord $/, ord "\n", ord "\r"; 632 #warn "length of separator = ", length($/); 633 $/ = "\n"; 634 #warn ord $/, ord "\n", ord "\r"; 635 while (<LOGFILE>) { 636 $out = $_; 637 $print_error_switch = 1 if $out =~ /^!/; # after a fatal error start printing messages 638 print protect_HTML($out)."<BR>\n" if $print_error_switch; 639 } 640 close(LOGFILE); 641 642 open (TEXFILE, "${tempDirectory}${texFile}${psvn}.tex") 643 || print "<H3>Can't open tex source file:</H3> path= ${tempDirectory}${texFile}${psvn}.tex:<BR> $!<BR><BR>\n"; 644 print "<BR>\n<H3>TeX Source File:</H3><BR>\n"; 645 print "<PRE>"; 646 647 my $lineNumber = 1; 648 while (<TEXFILE>) { 649 print protect_HTML("$lineNumber $_")."\n"; 650 $lineNumber++; 651 } 652 close(TEXFILE); 653 print "</PRE>"; 654 print &htmlBOTTOM("downloadPS.pl", \%inputs); 655 } 656 sub protect_HTML { 657 my $line = shift; 658 chomp($line); 659 $line =~s/\&/&/g; 660 $line =~s/</</g; 661 $line =~s/>/>/g; 662 $line; 663 } 664 sub PG_error_print { 665 my @probNums = @_; 666 open (TEXFILE, "${tempDirectory}${texFile}${psvn}.tex") 667 || ! $debugON || print STDERR "Can't open $tempDirectory$texFile$psvn.tex" ; 668 print &htmlTOP("PG compile error"); 669 print "<H3>PG error while compiling problem number", 670 (@probNums>1) ? 's ' : ' ', 671 join(',', @probNums), 672 "</H3>"; 673 print "(Search for "ERROR" to find the line where the error occurs.)"; 674 print "<H3>TeX Source File:</H3>"; 675 print "<PRE>"; 676 my $lineNumber = 1; 677 local($/) = "\n"; 678 while (<TEXFILE>) { 679 if ( $_ =~/^<A NAME/ ) { # skip lines starting with a destination anchor 680 print $_; 681 } else { 682 print protect_HTML("$lineNumber $_")."\n"; 683 } 684 $lineNumber++; 685 } 686 close(TEXFILE); 687 print &htmlBOTTOM("downloadPS.pl", \%inputs); 688 } 689 690 sub selectionError { 691 print &htmlTOP("Selection error"); 692 print"<H2>Error:</H2> You must first select a problem set in order to download a hard copy!\n"; 693 print "<FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P>"; 694 print &sessionKeyInputs(\%inputs); 695 print <<"ENDOFHTML"; 696 <INPUT TYPE=SUBMIT VALUE="Return to Welcome Page"> 697 </FORM> 698 ENDOFHTML 699 print &htmlBOTTOM("welcomeAction.pl", \%inputs); 700 } 701 702 sub probSet_htmlTOP { 703 my ($title, $bg_url) = @_; 704 my $background_url = $bg_url || $Global::background_plain_url; 705 706 707 my $out = <<ENDhtmlTOP; 708 content-type: text/html 709 Expires: 0 710 711 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 712 <HTML> 713 <HEAD> 714 <TITLE>$title</TITLE> 715 </HEAD> 716 <BODY BACKGROUND="$background_url"><p> 717 <P> 718 719 ENDhtmlTOP 720 $out; 721 } 722 723 sub probSet_titleBar { 724 my ($title) = @_; 725 my $title_bar = ""; 726 $title_bar .= qq{ 727 <TABLE BORDER="0" WIDTH="100%"> 728 <TR ALIGN=CENTER > 729 <TD ALIGN=LEFT > 730 <A HREF="$Global::webworkDocsURL"> 731 <IMG SRC="$Global::squareWebworkGif" BORDER=1 ALT="WeBWorK"></A> 732 </TD> 733 <TD VALIGN=MIDDLE> 734 <H2 ALIGN=CENTER> 735 $title 736 </H2> 737 </TD> 738 <TD ALIGN=RIGHT > 739 <FORM METHOD=POST ACTION=\"${Global::cgiWebworkURL}welcome.pl\"><P> 740 }; 741 my $inputkeys = &sessionKeyInputs(\%inputs); 742 743 $title_bar .= qq{ 744 $inputkeys 745 <INPUT TYPE=HIDDEN NAME=\"probSetKey\" VALUE=$psvn> 746 <INPUT TYPE=SUBMIT VALUE=\"Problem Sets\"> 747 </FORM> 748 </TD> 749 </TABLE> 750 }; 751 $title_bar; 752 } 753 754 sub downloadIndividualSet { 755 system("/usr/bin/renice +$main::DOWNLOAD_NICE -p $$ 1>/dev/null") && warn "Could not renice process. pid $$"; 756 alarm( $main::DOWNLOAD_TIME_OUT_CONSTANT); 757 my $return_status=''; 758 eval {$return_status = downloadPS($psvn,$texFile)}; ## trap any errors 759 $save_errors=$@; ## errors will be printed out by END 760 if ($return_status eq 'errors') {exit;} 761 elsif ($return_status eq 'no_errors') { 762 if ($downloadType eq "TeX" ) { 763 &texPrint; 764 } 765 elsif (system( "${scriptDirectory}makePS $tempDirectory $texFile$psvn 1>&2" )) { 766 &logPrint; 767 # wwerror("$0", "downloadPS: Error in creating postscript file. <BR> 768 # System command ${scriptDirectory}makePS $tempDirectory $texFile$psvn 1>&2", "", ""); 769 } 770 else { # tex file has been processed successfully 771 if ($downloadType eq 'pdf') {&pdfPrint;} 772 elsif ($downloadType eq 'dvi') {&dviPrint;} 773 else {&psPrint;} 774 } 775 } 776 else {wwerror($0, "The subroutine downloadPS returned an unknown status");} 777 } 778 779 sub downloadAllSets { 780 system("/usr/bin/renice +$main::CLASS_DOWNLOAD_NICE -p $$ 1>/dev/null") && warn "Could not renice process. pid $$"; 781 alarm( $main::CLASS_DOWNLOAD_TIME_OUT_CONSTANT); 782 my $localpsvn; ## psvn numbers for individual students 783 my $return_status=''; 784 my $texSource =''; 785 my $individualTexSource =''; 786 my ($texSourceRef, $errorRef); 787 788 my @local_psvns = $query -> param('local_psvns'); 789 790 my $max = $Global::max_num_of_ps_downloads_allowed; 791 792 ## make sure non professors can not download more than one set by submitting an altered form 793 @local_psvns = ($local_psvns[0]) unless $permissions == $Global::instructor_permissions; 794 795 my $length = @local_psvns; 796 797 if ($length > $max) { 798 wwerror ("Too many students selected", "The maximun number of sets which can be downloaded at one time is $max. You selected $length. 799 Go back and select fewer students. This maximun is set by the variable 800 \$max_num_of_ps_downloads_allowed in Global.pm."); 801 } 802 $localpsvn = shift @local_psvns; ## get first set which will contain TeX header info 803 # attachProbSetRecord($localpsvn); 804 ($texSourceRef, $errorRef) = &createTexSource($localpsvn); 805 ## don't do anything with $errorRef at this time 806 ## only contains prob numbers of bad problems 807 $texSource = $$texSourceRef; ## contains initial header info 808 $texSource =~ s|\\end\{document\}\s$|\n|s; ## remove end{document} statement 809 810 foreach $localpsvn (@local_psvns) { ## get the rest of the sets and strip TeX header info 811 # attachProbSetRecord($localpsvn); 812 ($texSourceRef, $errorRef) = &createTexSource($localpsvn); 813 ## don't do anything with $errorRef at this time 814 ## only contains prob numbers of bad problems 815 $individualTexSource = $$texSourceRef; 816 $individualTexSource =~ s|^.*?\\begin\{document\}|\n\\newpage\n|s; ## remove header material and start new page 817 $individualTexSource =~ s|\\end\{document\}\s$|\n|s; ## remove end{document} statement 818 $texSource .= $individualTexSource; 819 } 820 $texSource .= "\n\\end{document}\n"; ## append end{document} statement 821 822 $psvn = -1; 823 $texFile = "set${setNumber}.tempTex-CGIscript"; 824 $login_name_for_psvn = 'all_students'; 825 826 open(OUTPUT, ">${tempDirectory}${texFile}${psvn}.tex") 827 || wwerror("Can't create $tempDirectory${texFile}$psvn.tex\n"); 828 print OUTPUT $texSource; 829 close OUTPUT; 830 831 if ($downloadType eq "TeX" ) { 832 &texPrint; 833 } 834 elsif (system( "${scriptDirectory}makePS $tempDirectory $texFile$psvn 1>&2" )) { 835 &logPrint; 836 } 837 else { # tex file has been processed successfully 838 if ($downloadType eq 'pdf') {&pdfPrint;} 839 elsif ($downloadType eq 'dvi') {&dviPrint;} 840 else {&psPrint;} 841 } 842 } 843 844 845 846 847 sub hackerError { ## prints hacker error message 848 849 my $msg = "Attempt to hack into WeBWorK \n Remote Host is: ". remote_host()."\n"; 850 $msg .= query_string; 851 &Global::log_error('hacker error', $msg); ## log attempt 852 853 ## notify by email 854 855 my $toAdd = $Global::feedbackAddress; 856 857 my $emailMsg = "To: $toAdd 858 Subject: Attempt to hack into WeBWorK 859 860 Here are the details on the attempt to hack into weBWorK:\n 861 $msg 862 \n"; 863 864 my $smtp = Net::SMTP->new($Global::smtpServer, Timeout=>20); 865 $smtp->mail($Global::webmaster); 866 $smtp->recipient($Global::feedbackAddress); 867 $smtp->data($msg); 868 $smtp->quit; 869 870 871 # my $SENDMAIL = $Global::SENDMAIL; 872 # open (MAIL,"|$SENDMAIL"); 873 # print MAIL "$emailMsg"; 874 # close (MAIL); 875 876 print &htmlTOP("Hacker Error"), 877 "<H2>Error:Please do not try to hack into WeBWorK!</H2>", 878 startform(-action=>"${Global::cgiWebworkURL}${Global::welcomeAction_CGI}"), 879 "<p>", 880 &sessionKeyInputs(\%inputs), 881 hidden(-name=>'local_psvns', -value=>$psvn), 882 hidden(-name=>'action', -value=>'Do_problem_set'), 883 submit(-value=>"Return to Problem Set"), 884 endform(), 885 &htmlBOTTOM($0, \%inputs); 886 } 887 888 sub defineProblemEnvir { 889 my ($mode,$probNum,$psvn,$courseName,$refSubmittedAnswers) = @_; 890 my %envir=(); 891 my $loginName = &getStudentLogin($psvn); 892 ##how to put an array submittedAnswers in a hash?? 893 $envir{'refSubmittedAnswers'} = $refSubmittedAnswers if defined($refSubmittedAnswers); 894 $envir{'psvnNumber'} = $psvn; 895 $envir{'psvn'} = $psvn; 896 $envir{'studentName'} = &CL_getStudentName($loginName); 897 $envir{'studentLogin'} = $loginName; 898 $envir{'sectionName'} = &CL_getClassSection($loginName); 899 $envir{'sectionNumber'} = &CL_getClassSection($loginName); 900 $envir{'recitationName'} = &CL_getClassRecitation($loginName); 901 $envir{'recitationNumber'} = &CL_getClassRecitation($loginName); 902 $envir{'setNumber'} = &getSetNumber($psvn); 903 $envir{'questionNumber'} = $probNum; 904 $envir{'probNum'} = $probNum; 905 $envir{'openDate'} = &getOpenDate($psvn); 906 $envir{'formatedOpenDate'} = &formatDateAndTime(&getOpenDate($psvn)); 907 $envir{'formattedOpenDate'} = &formatDateAndTime(&getOpenDate($psvn)); 908 $envir{'dueDate'} = &getDueDate($psvn); 909 $envir{'formatedDueDate'} = &formatDateAndTime(&getDueDate($psvn)); 910 $envir{'formattedDueDate'} = &formatDateAndTime(&getDueDate($psvn)); 911 $envir{'answerDate'} = &getAnswerDate($psvn); 912 $envir{'formatedAnswerDate'} = &formatDateAndTime(&getAnswerDate($psvn)); 913 $envir{'formattedAnswerDate'} = &formatDateAndTime(&getAnswerDate($psvn)); 914 $envir{'problemValue'} = &getProblemValue($probNum,$psvn); 915 $envir{'fileName'} = &getProblemFileName($probNum,$psvn); 916 $envir{'probFileName'} = &getProblemFileName($probNum,$psvn); 917 $envir{'languageMode'} = $mode; 918 $envir{'displayMode'} = $mode; 919 $envir{'outputMode'} = $mode; 920 $envir{'courseName'} = $courseName; 921 $envir{'sessionKey'} = ( defined($inputs{'key'}) ) ?$inputs{'key'} : " "; 922 923 # initialize constants for PGanswermacros.pl 924 $envir{'numRelPercentTolDefault'} = getNumRelPercentTolDefault(); 925 $envir{'numZeroLevelDefault'} = getNumZeroLevelDefault(); 926 $envir{'numZeroLevelTolDefault'} = getNumZeroLevelTolDefault(); 927 $envir{'numAbsTolDefault'} = getNumAbsTolDefault(); 928 $envir{'numFormatDefault'} = getNumFormatDefault(); 929 $envir{'functRelPercentTolDefault'} = getFunctRelPercentTolDefault(); 930 $envir{'functZeroLevelDefault'} = getFunctZeroLevelDefault(); 931 $envir{'functZeroLevelTolDefault'} = getFunctZeroLevelTolDefault(); 932 $envir{'functAbsTolDefault'} = getFunctAbsTolDefault(); 933 $envir{'functNumOfPoints'} = getFunctNumOfPoints(); 934 $envir{'functVarDefault'} = getFunctVarDefault(); 935 $envir{'functLLimitDefault'} = getFunctLLimitDefault(); 936 $envir{'functULimitDefault'} = getFunctULimitDefault(); 937 $envir{'functMaxConstantOfIntegration'} = getFunctMaxConstantOfIntegration(); 938 $envir{'numOfAttempts'} = undef(); # this is defined only for problems 939 940 # defining directorys and URLs 941 $envir{'templateDirectory'} = &getCourseTemplateDirectory(); 942 $envir{'classDirectory'} = $Global::classDirectory; 943 $envir{'cgiDirectory'} = $Global::cgiDirectory; 944 $envir{'macroDirectory'} = getCourseMacroDirectory(); 945 $envir{'courseScriptsDirectory'} = getCourseScriptsDirectory(); 946 $envir{'htmlDirectory'} = getCourseHtmlDirectory(); 947 $envir{'htmlURL'} = getCourseHtmlURL(); 948 $envir{'tempDirectory'} = getCourseTempDirectory(); 949 $envir{'tempURL'} = getCourseTempURL(); 950 $envir{'scriptDirectory'} = $Global::scriptDirectory; 951 $envir{'webworkDocsURL'} = $Global::webworkDocsURL; 952 953 954 $envir{'inputs_ref'} = \%inputs; 955 956 957 my $seed = &getProblemSeed($probNum, $psvn); 958 $seed = 1111 unless defined($seed); 959 $envir{'problemSeed'} = $seed if defined($seed); 960 961 # here is a way to pass environment variables defined in webworkCourse.ph 962 my $k; 963 foreach $k (keys %Global::PG_environment ) { 964 $envir{$k} = $Global::PG_environment{$k}; 965 } 966 %envir; 967 } 968 969 BEGIN { 970 971 972 # This subroutine cleans up temporary files after the postscript copy has been created. 973 # 974 sub cleanup_downloadPS { 975 976 unless (defined($action ) and ($action eq 'Do problem set' or $action eq 'Do_problem_set')) { 977 my $ERRORS = $save_errors; 978 unless ($debugON) { #clean up the directory 979 eval { 980 chdir $tempDirectory; 981 unlink("$texFile$psvn.dvi", "$texFile$psvn.ps","$texFile$psvn.pdf", 982 "$texFile$psvn.log", "$texFile$psvn.aux", 983 "$texFile$psvn.tex",); 984 unlink("${tempDirectory}eps/${login_name_for_psvn}*.eps"); 985 }; # clean up 986 $ERRORS .= $ERRORS . $@; 987 } 988 my $query = query_string(); 989 $query = "" unless defined($query); 990 wwerror("$0", "ERROR: in downloadPS subroutine of welcomeAction.pl $ERRORS","","",$query) if $ERRORS; 991 } 992 } 993 } 994 995 END { 996 if (defined($main::SIG_TIME_OUT) && $main::SIG_TIME_OUT == 1) { 997 alarm(0); # turn off the alarm 998 my $hard_copy_message = qq{Content-type: text/html\n\n 999 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 1000 <HTML><BODY BGCOLOR = "FF99CC"> 1001 <BLOCKQUOTE><H3>WeBWorK hard copy download time out.</H3>\n 1002 <H4>This download was cancelled because it took more than $main::TIME_OUT_CONSTANT seconds.</H4> This may be because the 1003 WeBWorK server is extraordinarily busy, or because there was an error in the problem, 1004 or because you tried to download a set with too many problems (more than 50).<P>\n 1005 Use the back button to return to the previous page and try again.<BR>\n 1006 If the problem is repeated you can report this to your instructor using the feedback button. 1007 <P> 1008 Because the WeBWorK server at the Unversity of Rochester is experiencing heavy use we have made downloading 1009 hard copies a low priority during the times of very heavy useage. It will be helpful if you 1010 download hard copies during times when the load is not too heavy. 1011 <P> 1012 The load is usually heaviest in the evenings , particularly a few hours before assignments 1013 are due. The best times to download hard copies are in the morning and afternoon 1014 -- or an hour after the due date and time of the previous assignment -- nobody is using the system then :-) 1015 </BLOCKQUOTE></BODY></HTML> 1016 }; 1017 my $do_problem_message = qq{Content-type: text/html\n\n 1018 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 1019 <HTML><BODY BGCOLOR = "FF99CC"> 1020 <BLOCKQUOTE><H3>WeBWorK heavy useage time out.</H3>\n 1021 <H4>Your request (action = $action) was cancelled because it took more than $main::TIME_OUT_CONSTANT seconds.</H4> 1022 This is probably because the 1023 WeBWorK server is extraordinarily busy.<P>\n 1024 You should be warned that WeBWorK response will be unusually slow. If possible you should try 1025 to use WeBWorK at another time when the load is not as high. The highest useage periods are in the 1026 evening, particularly in the two hours before assignments are due.<P>\n 1027 Use the back button to return to the previous page and try again.<P>\n 1028 If the high useage problem continues you can report this to your instructor using the feedback button. 1029 <P> 1030 1031 </BLOCKQUOTE></BODY></HTML> 1032 }; 1033 if ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') { 1034 print $hard_copy_message; 1035 } else{ 1036 print $do_problem_message; 1037 } 1038 1039 1040 } 1041 1042 # begin Timing code 1043 if( $main::logTimingData == 1 ) { 1044 my $endTime = new Benchmark; 1045 my $error_str=''; 1046 1047 if ($main::SIGPIPE) { 1048 $error_str = 'broken PIPE--'; 1049 } 1050 elsif ($main::SIG_TIME_OUT) { 1051 $error_str = "TIME_OUT after $main::TIME_OUT_CONSTANT secs --"; 1052 } 1053 elsif ($action eq 'Get hard copy' or $action eq 'Get_hard_copy') { 1054 $error_str = 'successful download -- '; 1055 } 1056 1057 &Global::logTimingInfo($main::beginTime,$endTime,$error_str.'welcomeAction.pl',$Course,$User); 1058 } 1059 # end Timing code 1060 cleanup_downloadPS(); 1061 } 1062 1063 1064 ######## DEBUGGING TOOLS 1065 1066 # sub downloadPS_dumpvar { 1067 # my ($packageName) = @_; 1068 # 1069 # local(*alias); 1070 # 1071 # 1072 # *stash = *{"${packageName}::"}; 1073 # $, = " "; 1074 # 1075 # print OUTPUT "Content-type: text/html\n\n<PRE>\n"; 1076 # 1077 # 1078 # while ( ($varName, $globValue) = each %stash) { 1079 # print OUTPUT "$varName =================================\n"; 1080 # 1081 # *alias = $globValue; 1082 # next if $varName=~/main/; 1083 # next unless $varName =~/::/; 1084 # 1085 # if (defined($alias) ) { 1086 # print OUTPUT "\t \$$varName $alias \n"; 1087 # } 1088 # 1089 # if ( defined(@alias) ) { 1090 # print OUTPUT "\t \@$varName @alias \n"; 1091 # } 1092 # if (defined(%alias) ) { 1093 # print OUTPUT "\t \%$varName \n"; 1094 # foreach $key (keys %alias) { 1095 # print OUTPUT "\t\t $key => $alias{$key}\n"; 1096 # } 1097 # 1098 # 1099 # } 1100 # } 1101 # 1102 # 1103 # 1104 # } 1105 1106 1107 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |