Parent Directory
|
Revision Log
Problem.pm now works (kindof) to serve PG problems. There are configuration variables at the top that have to be customized to an individuals directory. (They could be placed in a config file to avoid having to update them constantly, but soon these values should be set by information from the course and problem environments.) The code is still rather delicate. It seems to work with some problems and not with others. I suspect that the macro files are not being properly read in and that perhaps the warning mechanisms are not yet working properly. Also beware the line ending problem. Some of these files were created on a mac (using unix). I've had completely mysterious errors that were fixed by checking the line endings. There is also a lot of code, particulary the error reporting code which should be put in its own module.
1 package WeBWorK::ContentGenerator::Problem; 2 our @ISA = qw(WeBWorK::ContentGenerator); 3 use lib '/Users/gage/webwork/xmlrpc/daemon'; 4 use lib '/Users/gage/webwork-modperl/lib'; 5 use PGtranslator5; 6 use WeBWorK::ContentGenerator; 7 use Apache::Constants qw(:common); 8 9 ############################################################################### 10 # Configuration 11 ############################################################################### 12 13 my $COURSE_SCRIPTS_DIRECTORY = '/Users/gage/webwork/system/courseScripts/'; 14 my $MACRO_DIRECTORY = '/Users/gage/webwork/courseData/templates/macro/'; 15 my $TEMPLATE_DIRECTORY = '/Users/gage/webwork/rochester_problib/'; 16 my $TEMP_URL = 'http://127.0.0.1/~gage/rochester_problibtmp/'; 17 ##my $HTML_DIRECTORY = '/Users/gage/Sites/rochester_problib/' #already obtained from courseEnvironment 18 my $HTML_URL = 'http://127.0.0.1/~gage/rochester_problib/'; 19 20 ############################################################################### 21 # End configuration 22 ############################################################################### 23 24 sub title { 25 my ($self, $problem_set, $problem) = @_; 26 my $r = $self->{r}; 27 my $user = $r->param('user'); 28 return "Problem $problem of problem set $problem_set for $user"; 29 } 30 31 ############################################################################### 32 # 33 # INITIALIZATION 34 # 35 # The following code initializes an instantiation of PGtranslator5 in the 36 # parent process. This initialized object is then share with each of the 37 # children forked from this parent process by the daemon. 38 # 39 # As far as I can tell, the child processes don't share any variable values even 40 # though their namespaces are the same. 41 ############################################################################### 42 # First some dummy values to use for testing. 43 # These should be available from the problemEnvironment(it might be ok to assume that PG and dangerousMacros 44 # live in the courseScripts (system level macros) directory. 45 46 print STDERR "Begin intitalization\n"; 47 my $dummy_envir = { courseScriptsDirectory => $COURSE_SCRIPTS_DIRECTORY, 48 displayMode => 'HTML_tth', 49 macroDirectory => $MACRO_DIRECTORY, 50 cgiURL => 'foo_cgiURL'}; 51 52 53 my $PG_PL = "${COURSE_SCRIPTS_DIRECTORY}PG.pl"; 54 my $DANGEROUS_MACROS_PL = "${COURSE_SCRIPTS_DIRECTORY}dangerousMacros.pl"; 55 my @MODULE_LIST = ( "Exporter", "DynaLoader", "GD", "WWPlot", "Fun", 56 "Circle", "Label", "PGrandom", "Units", "Hermite", 57 "List", "Match","Multiple", "Select", "AlgParser", 58 "AnswerHash", "Fraction", "VectorField", "Complex1", 59 "Complex", "MatrixReal1", "Matrix","Distributions", 60 "Regression" 61 ); 62 my @EXTRA_PACKAGES = ( "AlgParserWithImplicitExpand", "Expr", 63 "ExprWithImplicitExpand", "AnswerEvaluator", 64 65 ); 66 $INITIAL_MACRO_PACKAGES = <<END_OF_TEXT; 67 DOCUMENT(); 68 loadMacros( 69 "PGbasicmacros.pl", 70 "PGchoicemacros.pl", 71 "PGanswermacros.pl", 72 "PGnumericalmacros.pl", 73 "PGgraphmacros.pl", 74 "PGauxiliaryFunctions.pl", 75 "PGmatrixmacros.pl", 76 "PGcomplexmacros.pl", 77 "PGstatisticsmacros.pl" 78 79 ); 80 81 TEXT("Hello world"); 82 83 ENDDOCUMENT(); 84 85 END_OF_TEXT 86 87 #These here documents have their drawbacks. KEEP END_OF_TEXT left justified!!!!!! 88 89 ############################################################################### 90 # Now to define the body subroutine which does the hard work. 91 ############################################################################### 92 93 94 #my $SOURCE1 = $INITIAL_MACRO_PACKAGES; 95 96 sub body { 97 my ($self, $problem_set, $problem) = @_; 98 my $r = $self->{r}; 99 my $courseEnvironment = $self->{courseEnvironment}; 100 my $user = $r->param('user'); 101 102 103 my $SOURCE1 = readFile('set0/prob1c.pg'); 104 print STDERR "SOURCEFILE: \n$SOURCE1\n\n"; 105 106 ########################################################################### 107 # The pg problem class should have a method for installing it's problemEnvironment 108 ########################################################################### 109 110 $problemEnvir_rh = defineProblemEnvir($self); 111 112 113 ################################################################################## 114 # Prime the PGtranslator object and set it loose 115 ################################################################################## 116 117 118 ############################################################################### 119 120 ############################################################################### 121 #Create the PG translator. 122 ############################################################################### 123 124 my $pt = new PGtranslator5; #pt stands for problem translator; 125 126 127 # All of these hard coded directories need to be drawn from courseEnvironment. 128 # In addition I don't think that PGtranslator uses this stack internally yet. 129 # Passing these directories through the problemEnvironment variable is what 130 # is currently being done, but I don't think it is quite right, at least for most 131 # of them. 132 133 134 $pt ->rh_directories( { courseScriptsDirectory => $COURSE_SCRIPTS_DIRECTORY, 135 macroDirectory => $MACRO_DIRECTORY, 136 , 137 templateDirectory => $TEMPLATE_DIRECTORY, 138 tempDirectory => $TEMP_DIRECTORY, 139 } 140 ); 141 142 ############################################################################### 143 # First we load the modules from courseScripts directory. 144 # These do the "heavy lifting" in terms of formatting, creating graphs, and 145 # performing other heavy duty algorithms. 146 # 147 ############################################################################### 148 149 $pt -> evaluate_modules( @MODULE_LIST); 150 $pt -> load_extra_packages( @EXTRA_PACKAGES ); 151 152 ############################################################################### 153 # Load the environment constants. Some are used by the PGtranslator object but 154 # most of them are installed inside the Safe compartment where the problem 155 # runs. 156 ############################################################################### 157 #$pt -> environment($dummy_envir); 158 $pt -> environment($problemEnvir_rh); 159 160 161 # I've forgotten what this does exactly :-) 162 $pt->initialize(); 163 164 ############################################################################### 165 # PG.pl contains the basic code which defines the problem interface, input and output. 166 # dangerousMacros.pl contains subroutines which have access to the hard drive and 167 # and the directory structure. All use of external resources by the problem is supposed 168 # to go through these subroutines. The idea is to put the potentially dangerous 169 # algorithms in on place so they can be watched closely. 170 # These two files are evaluated in the Safe compartment without any restrictions. 171 # They have full use of the perl commands. 172 ############################################################################### 173 my $loadErrors = $pt -> unrestricted_load($PG_PL ); 174 print STDERR "$loadErrors\n" if ($loadErrors); 175 $loadErrors = $pt -> unrestricted_load($DANGEROUS_MACROS_PL); 176 print STDERR "$loadErrors\n" if ($loadErrors); 177 178 ############################################################################### 179 # Now set the mask to restrict the operations which can be performed within 180 # a problem or a macro file. 181 ############################################################################### 182 $pt-> set_mask(); 183 184 # print "\nPG.pl: $PG_PL<br>\n"; 185 # print "DANGEROUS_MACROS_PL: $DANGEROUS_MACROS_PL<br>\n"; 186 # print "Print dummy environment<br>\n"; 187 # print pretty_print_rh($dummy_envir), "<p>\n\n"; 188 189 # Read in the source code for the problem 190 191 #$INITIAL_MACRO_PACKAGES =~ tr /\r/\n/; # change everything to unix line endings. 192 $SOURCE1 =~ tr /\r/\n/; 193 #print STDERR "Source again \n $SOURCE1"; 194 $pt->source_string( $SOURCE1 ); 195 196 ############################################################################### 197 # Install a safety filter for screening student answers. The default is now the blank 198 # filter since the answer evaluators do a pretty good job of recompiling and screening 199 # student's answers. Still, you could prohibit back ticks, or something of the kind. 200 ############################################################################### 201 202 $pt ->rf_safety_filter( \&safetyFilter); # install blank safety filter 203 204 205 print STDERR "New PGtranslator object inititialization completed.<br>\n"; 206 ################################################################################ 207 ## This ends the initialization of the PGtranslator object 208 ################################################################################ 209 210 211 ################################################################################ 212 # Run the problem (output the html text) but also store it within the object. 213 # The correct answers are also calculated and stored within the object 214 ################################################################################ 215 $pt ->translate(); 216 217 #print problem output 218 print "Problem goes here<p>\n"; 219 print "Problem output <br>\n"; 220 print "################################################################################<br<br>"; 221 print ${$pt->r_text()}; 222 print "<br><br>################################################################################<br>"; 223 print "<p>End of problem output<br>"; 224 225 226 #print source code 227 print "Source code<pre>\n"; 228 print $SOURCE1; 229 print "</pre>End source code<p>"; 230 ################################################################################ 231 # The format for the output is described here. We'll need a local variable 232 # to handle the warnings. From within the problem the warning command 233 # has been slaved to the __WARNINGS__ routine which is defined in Global. 234 # We'll need to provide an alternate mechanism. 235 # The base64 encoding is only needed for xml transmission. 236 ################################################################################ 237 print "################################################################################<br>"; 238 print "Warnings output<br>"; 239 my $WARNINGS = "Let this be a warning:"; 240 241 print $WARNINGS; 242 243 ################################################################################ 244 # Install the standard problem grader. See gage/xmlrpc/daemon.pm or processProblem8 for detailed 245 # code on how to choose which problem grader to install, depending on courseEnvironment and problem data. 246 # See also PG.pl which provides for problem by problem overrides. 247 ################################################################################ 248 249 $pt->rf_problem_grader($pt->rf_std_problem_grader); 250 251 ################################################################################ 252 # creates and stores a hash of answer results inside the object: $rh_answer_results 253 ################################################################################ 254 $pt -> process_answers($rh->{envir}->{inputs_ref}); 255 256 257 # THE UPDATE AND GRADING LOGIC COULD USE AN OVERHAUL. IT WAS SOMEWHAT CONSTRAINED 258 # BY LEGACY CONDITIONS IN THE ORIGINAL PROCESSPROBLEM8. IT'S NOT BAD 259 # BUT IT COULD PROBABLY BE MADE A LITTLE MORE STRAIGHT FORWARD. 260 ################################################################################ 261 # updates the problem state stored by the translator object from the problemEnvironment data 262 ################################################################################ 263 264 # $pt->rh_problem_state({ recorded_score => $rh->{problem_state}->{recorded_score}, 265 # num_of_correct_ans => $rh->{problem_state}->{num_of_correct_ans} , 266 # num_of_incorrect_ans => $rh->{problem_state}->{num_of_incorrect_ans} 267 # } ); 268 ################################################################################ 269 # grade the problem (and update the problem state again.) 270 ################################################################################ 271 272 # Define an entry order -- the default is the order they are received from the browser. 273 # (Which as I understand it is NOT guaranteed to be the Left->Right Up-> Down order we're 274 # used to in the West. 275 276 my %PG_FLAGS = $pt->h_flags; 277 my $ra_answer_entry_order = ( defined($PG_FLAGS{ANSWER_ENTRY_ORDER}) ) ? 278 $PG_FLAGS{ANSWER_ENTRY_ORDER} : [ keys %{$pt->rh_evaluated_answers} ] ; 279 # Decide whether any answers were submitted. 280 my $answers_submitted = 0; 281 $answers_submitted = 1 if defined( $rh->{answer_form_submitted} ) and 1 == $rh->{answer_form_submitted}; 282 # If there are answers, grade them 283 my ($rh_problem_result,$rh_problem_state) = $pt->grade_problem( answers_submitted => $answers_submitted, 284 ANSWER_ENTRY_ORDER => $ra_answer_entry_order 285 ); # grades the problem. 286 287 # Output format expected by Webwork.pm (and I believe processProblem8, but check.) 288 my $out = { 289 text => ${$pt ->r_text()}, # encode_base64( ${$pt ->r_text()} ), 290 header_text => $pt->r_header, # encode_base64( ${ $pt->r_header } ), 291 answers => $pt->rh_evaluated_answers, 292 errors => $pt-> errors(), 293 WARNINGS => $WARNINGS, #encode_base64($WARNINGS ), 294 problem_result => $rh_problem_result, 295 problem_state => $rh_problem_state, 296 PG_flag => \%PG_flag 297 }; 298 ########################################################################################## 299 # Debugging printout of environment tables 300 ########################################################################################## 301 302 print "<P>Request item<P>\n\n"; 303 print "<TABLE border=\"3\">"; 304 print $self->print_form_data('<tr><td>','</td><td>','</td></tr>'); 305 print "</table>\n"; 306 print "path info <br>\n"; 307 print $r->path_info(); 308 print "<P>\n\ncourseEnvironment<P>\n\n"; 309 print pretty_print_rh($courseEnvironment); 310 print "<P>\n\nproblemEnvironment<P>\n\n"; 311 print pretty_print_rh($problemEnvir_rh); 312 313 ########################################################################################## 314 # End 315 ########################################################################################## 316 ""; 317 } 318 # End the"body" routine for the Problem object. 319 320 321 322 323 324 325 ######################################################################################## 326 # This is the problemEnvironment structure that needs to be filled out in order to provide 327 # information to PGtranslator which in turn supports the problem environment 328 ######################################################################################## 329 330 sub defineProblemEnvir { 331 my $self = shift; 332 my $r = $self->{r}; 333 my $courseEnvironment = $self->{courseEnvironment}; 334 my %envir=(); 335 # $envir{'refSubmittedAnswers'} = $refSubmittedAnswers if defined($refSubmittedAnswers); 336 $envir{'psvnNumber'} = 123456789; 337 $envir{'psvn'} = 123456789; 338 $envir{'studentName'} = 'Jane Doe'; 339 $envir{'studentLogin'} = 'jd001m'; 340 $envir{'studentID'} = 'xxx-xx-4321'; 341 $envir{'sectionName'} = 'gage'; 342 $envir{'sectionNumber'} = '111foobar'; 343 $envir{'recitationName'} = 'gage_recitation'; 344 $envir{'recitationNumber'} = '11_foobar recitation'; 345 $envir{'setNumber'} = 'setAlgebraicGeometry'; 346 $envir{'questionNumber'} = 43; 347 $envir{'probNum'} = 43; 348 $envir{'openDate'} = 3014438528; 349 $envir{'formattedOpenDate'} = '3/4/02'; 350 $envir{'dueDate'} = 4014438528; 351 $envir{'formattedDueDate'} = '10/4/04'; 352 $envir{'answerDate'} = 4014438528; 353 $envir{'formattedAnswerDate'} = '10/4/04'; 354 $envir{'problemValue'} = 1; 355 $envir{'fileName'} = 'problem1'; 356 $envir{'probFileName'} = 'problem1'; 357 $envir{'languageMode'} = 'HTML_tth'; 358 $envir{'displayMode'} = 'HTML_tth'; 359 $envir{'outputMode'} = 'HTML_tth'; 360 $envir{'courseName'} = $courseEnvironment ->{courseName}; 361 $envir{'sessionKey'} = 'asdf'; 362 363 # initialize constants for PGanswermacros.pl 364 $envir{'numRelPercentTolDefault'} = .1; 365 $envir{'numZeroLevelDefault'} = 1E-14; 366 $envir{'numZeroLevelTolDefault'} = 1E-12; 367 $envir{'numAbsTolDefault'} = .001; 368 $envir{'numFormatDefault'} = ''; 369 $envir{'functRelPercentTolDefault'} = .1; 370 $envir{'functZeroLevelDefault'} = 1E-14; 371 $envir{'functZeroLevelTolDefault'} = 1E-12; 372 $envir{'functAbsTolDefault'} = .001; 373 $envir{'functNumOfPoints'} = 3; 374 $envir{'functVarDefault'} = 'x'; 375 $envir{'functLLimitDefault'} = .0000001; 376 $envir{'functULimitDefault'} = .9999999; 377 $envir{'functMaxConstantOfIntegration'} = 1E8; 378 # kludge check definition of number of attempts again. The +1 is because this is used before the current answer is evaluated. 379 $envir{'numOfAttempts'} = 2; #&getProblemNumOfCorrectAns($probNum,$psvn) 380 # &getProblemNumOfIncorrectAns($probNum,$psvn)+1; 381 382 # 383 # 384 # defining directorys and URLs 385 $envir{'templateDirectory'} = $courseEnvironment ->{courseDirs}->{templates}; 386 ############ $envir{'classDirectory'} = $Global::classDirectory; 387 # $envir{'cgiDirectory'} = $Global::cgiDirectory; 388 # $envir{'cgiURL'} = getWebworkCgiURL(); 389 390 # $envir{'scriptDirectory'} = $Global::scriptDirectory;##omit 391 $envir{'webworkDocsURL'} = 'http://webwork.math.rochester.edu'; 392 $envir{'externalTTHPath'} = '/usr/local/bin/tth'; 393 394 395 # 396 $envir{'inputs_ref'} = $r->param; 397 $envir{'problemSeed'} = 3245; 398 $envir{'displaySolutionsQ'} = 1; 399 $envir{'displayHintsQ'} = 1; 400 401 # Directory values -- do we really need them here? 402 $envir{courseScriptsDirectory} = $COURSE_SCRIPTS_DIRECTORY; 403 $envir{macroDirectory} = $MACRO_DIRECTORY; 404 $envir{templateDirectory} = $TEMPLATE_DIRECTORY; 405 $envir{tempDirectory} = $TEMP_DIRECTORY; 406 $envir{tempURL} = $TEMP_URL; 407 $envir{htmlURL} = $HTML_URL; 408 $envir{'htmlDirectory'} = $courseEnvironment ->{courseDirectory}->{html}; 409 # here is a way to pass environment variables defined in webworkCourse.ph 410 # my $k; 411 # foreach $k (keys %Global::PG_environment ) { 412 # $envir{$k} = $Global::PG_environment{$k}; 413 # } 414 \%envir; 415 } 416 417 ######################################################################################## 418 # This recursive pretty_print function will print a hash and its sub hashes. 419 ######################################################################################## 420 sub pretty_print_rh { 421 my $r_input = shift; 422 my $out = ''; 423 if ( not ref($r_input) ) { 424 $out = $r_input; # not a reference 425 } elsif (is_hash_ref($r_input)) { 426 local($^W) = 0; 427 $out .= "<TABLE border = \"2\" cellpadding = \"3\" BGCOLOR = \"#FFFFFF\">"; 428 foreach my $key (sort keys %$r_input ) { 429 $out .= "<tr><TD> $key</TD><TD>=></td><td> ".pretty_print_rh($r_input->{$key}) . "</td></tr>"; 430 } 431 $out .="</table>"; 432 } elsif (is_array_ref($r_input) ) { 433 my @array = @$r_input; 434 $out .= "( " ; 435 while (@array) { 436 $out .= pretty_print_rh(shift @array) . " , "; 437 } 438 $out .= " )"; 439 } elsif (ref($r_input) eq 'CODE') { 440 $out = "$r_input"; 441 } else { 442 $out = $r_input; 443 } 444 $out; 445 } 446 447 sub is_hash_ref { 448 my $in =shift; 449 my $save_SIG_die_trap = $SIG{__DIE__}; 450 $SIG{__DIE__} = sub {CORE::die(@_) }; 451 my $out = eval{ %{ $in } }; 452 $out = ($@ eq '') ? 1 : 0; 453 $@=''; 454 $SIG{__DIE__} = $save_SIG_die_trap; 455 $out; 456 } 457 sub is_array_ref { 458 my $in =shift; 459 my $save_SIG_die_trap = $SIG{__DIE__}; 460 $SIG{__DIE__} = sub {CORE::die(@_) }; 461 my $out = eval{ @{ $in } }; 462 $out = ($@ eq '') ? 1 : 0; 463 $@=''; 464 $SIG{__DIE__} = $save_SIG_die_trap; 465 $out; 466 } 467 468 ###### 469 # Utility for slurping souce files 470 ####### 471 472 sub readFile { 473 my $input = shift; # The set and problem: 'set0/prob1.pg' 474 my $filePath =$TEMPLATE_DIRECTORY .$input; 475 print STDERR "Reading problem from file $filePath \n"; 476 print STDERR "<br>Reading problem from file $filePath <br>\n"; 477 my $out; 478 print "The file is readable = ", -r $filePath, "\n"; 479 if (-r $filePath) { 480 open IN, "<$filePath" or print STDERR "Hey, this file was supposed to be readable\n"; 481 local($/)=undef; 482 $out = <IN>; 483 close(IN); 484 } else { 485 print "Could not read file at |$filePath|"; 486 print STDERR "Could not read file at |$filePath|"; 487 } 488 return($out); 489 } 490 491 my $foo =0; 492 493 # The warning mechanism. This needs to be turned into an object of its own 494 ############### 495 ## Error message routines cribbed from CGI 496 ############### 497 498 BEGIN { #error message routines cribbed from CGI 499 500 my $CarpLevel = 0; # How many extra package levels to skip on carp. 501 my $MaxEvalLen = 0; # How much eval '...text...' to show. 0 = all. 502 503 sub longmess { 504 my $error = shift; 505 my $mess = ""; 506 my $i = 1 + $CarpLevel; 507 my ($pack,$file,$line,$sub,$eval,$require); 508 509 while (($pack,$file,$line,$sub,undef,undef,$eval,$require) = caller($i++)) { 510 if ($error =~ m/\n$/) { 511 $mess .= $error; 512 } 513 else { 514 if (defined $eval) { 515 if ($require) { 516 $sub = "require $eval"; 517 } 518 else { 519 $eval =~ s/[\\\']/\\$&/g; 520 if ($MaxEvalLen && length($eval) > $MaxEvalLen) { 521 substr($eval,$MaxEvalLen) = '...'; 522 } 523 $sub = "eval '$eval'"; 524 } 525 } 526 elsif ($sub eq '(eval)') { 527 $sub = 'eval {...}'; 528 } 529 530 $mess .= "\t$sub " if $error eq "called"; 531 $mess .= "$error at $file line $line\n"; 532 } 533 534 $error = "called"; 535 } 536 537 $mess || $error; 538 } 539 } 540 ############### 541 ### Our error messages for giving maximum feedback to the user for errors within problems. 542 ############### 543 BEGIN { 544 sub PG_floating_point_exception_handler { # 1st argument is signal name 545 my($sig) = @_; 546 print "Content-type: text/html\n\n<H4>There was a floating point arithmetic error (exception SIG$sig )</H4>--perhaps 547 you divided by zero or took the square root of a negative number? 548 <BR>\n Use the back button to return to the previous page and recheck your entries.<BR>\n"; 549 exit(0); 550 } 551 552 $SIG{'FPE'} = \&PG_floating_point_exception_handler; 553 554 sub PG_warnings_handler { 555 my @input = @_; 556 my $msg_string = longmess(@_); 557 my @msg_array = split("\n",$msg_string); 558 my $out_string = ''; 559 560 # Extra stack information is provided in this next block 561 # If the warning message does NOT end in \n then a line 562 # number is appended (see Perl manual about warn function) 563 # The presence of the line number is detected below and extra 564 # stack information is added. 565 # To suppress the line number and the extra stack information 566 # add \n to the end of a warn message (in .pl files. In .pg 567 # files add ~~n instead 568 569 if ($input[$#input]=~/line \d*\.\s*$/) { 570 $out_string .= "##More details: <BR>\n----"; 571 foreach my $line (@msg_array) { 572 chomp($line); 573 next unless $line =~/\w+\:\:/; 574 $out_string .= "----" .$line . "<BR>\n"; 575 } 576 } 577 578 $Global::WARNINGS .="* " . join("<BR>",@input) . "<BR>\n" . $out_string . 579 "<BR>\n--------------------------------------<BR>\n<BR>\n"; 580 $Global::background_plain_url = $Global::background_warn_url; 581 $Global::bg_color = '#FF99CC'; #for warnings -- this change may come too late 582 } 583 584 $SIG{__WARN__}=\&PG_warnings_handler; 585 586 $SIG{__DIE__} = sub { 587 my $message = longmess(@_); 588 $message =~ s/\n/<BR>\n/; 589 my ($package, $filename, $line) = caller(); 590 # use standard die for errors eminating from XML::Parser::Expat 591 # it uses a trapped eval which sometimes fails -- apparently on purpose 592 # and the error is handled by Expat itself. We don't want 593 # to interfer with that. 594 595 if ($package eq 'XML::Parser::Expat') { 596 die @_; 597 } 598 #print "$package $filename $line \n"; 599 print 600 "Content-type: text/html\r\n\r\n <h4>Software error</h4> <p>\n\n$message\n<p>\n 601 Please inform the webwork meister.<p>\n 602 In addition to the error message above the following warnings were detected: 603 <HR> 604 $Global::WARNINGS; 605 <HR> 606 It's sometimes hard to tell exactly what has gone wrong since the 607 full error message may have been sent to 608 standard error instead of to standard out. 609 <p> To debug you can 610 <ul> 611 <li> guess what went wrong and try to fix it. 612 <li> call the offending script directly from the command line 613 of unix 614 <li> enable the debugging features by redefining 615 \$cgiURL in Global.pm and checking the redirection scripts in 616 system/cgi. This will force the standard error to be placed 617 in the standard out pipe as well. 618 <li> Run tail -f error_log <br> 619 from the unix command line to see error messages from the webserver. 620 The standard error output is being placed in the error_log file for the apache 621 web server. To run this command you have to be in the directory containing the 622 error_log or enter the full path name of the error_log. <p> 623 In a standard apache installation, this file is at /usr/local/apache/logs/error_log<p> 624 In a RedHat Linux installation, this file is at /var/log/httpd/error_log<p> 625 At Rochester this file is at /ww/logs/error_log. 626 </ul> 627 Good luck.<p>\n" ; 628 }; 629 630 631 632 } 633 634 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |