[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Problem.pm Repository:
ViewVC logotype

Annotation of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Problem.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 392 - (view) (download) (as text)

1 : malsyned 353 package WeBWorK::ContentGenerator::Problem;
2 :     our @ISA = qw(WeBWorK::ContentGenerator);
3 : gage 388 use lib '/Users/gage/webwork/xmlrpc/daemon';
4 :     use lib '/Users/gage/webwork-modperl/lib';
5 :     use PGtranslator5;
6 : malsyned 353 use WeBWorK::ContentGenerator;
7 :     use Apache::Constants qw(:common);
8 :    
9 : gage 392 ###############################################################################
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 : malsyned 353 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 : gage 392 ###############################################################################
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 : malsyned 353 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 : gage 388
103 : gage 392 my $SOURCE1 = readFile('set0/prob1c.pg');
104 :     print STDERR "SOURCEFILE: \n$SOURCE1\n\n";
105 : gage 388
106 :     ###########################################################################
107 :     # The pg problem class should have a method for installing it's problemEnvironment
108 :     ###########################################################################
109 :    
110 :     $problemEnvir_rh = defineProblemEnvir($self);
111 :    
112 : gage 392
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 : gage 388 print "<P>\n\nproblemEnvironment<P>\n\n";
311 :     print pretty_print_rh($problemEnvir_rh);
312 : gage 392
313 :     ##########################################################################################
314 :     # End
315 :     ##########################################################################################
316 :     "";
317 : malsyned 353 }
318 : gage 392 # End the"body" routine for the Problem object.
319 : malsyned 353
320 : gage 388
321 : gage 392
322 :    
323 :    
324 :    
325 : gage 388 ########################################################################################
326 : gage 392 # 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 : gage 388 ########################################################################################
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 : gage 392
390 : gage 388 # $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 : gage 392 # 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 : gage 388 # 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>=&gt;</td><td>&nbsp;".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 : gage 392
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 : malsyned 353 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9