[system] / trunk / webwork2 / lib / WeBWorK / PG / Local.pm Repository:
ViewVC logotype

Diff of /trunk/webwork2/lib/WeBWorK/PG/Local.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1537 Revision 1558
2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
3# $Id$ 3# $Id$
4################################################################################ 4################################################################################
5 5
6package WeBWorK::PG::Local; 6package WeBWorK::PG::Local;
7use base qw(WeBWorK::PG);
7 8
8=head1 NAME 9=head1 NAME
9 10
10WeBWorK::PG::Local - Use the WeBWorK::PG API to invoke a local 11WeBWorK::PG::Local - Use the WeBWorK::PG API to invoke a local
11WeBWorK::PG::Translator object. 12WeBWorK::PG::Translator object.
24=cut 25=cut
25 26
26use strict; 27use strict;
27use warnings; 28use warnings;
28use File::Path qw(rmtree); 29use File::Path qw(rmtree);
29use WeBWorK::PG::ImageGenerator;
30use WeBWorK::PG::Translator; 30use WeBWorK::PG::Translator;
31use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry makeTempDirectory); 31use WeBWorK::Utils qw(readFile writeTimingLogEntry);
32
32BEGIN { 33BEGIN {
33
34# This safe compartment is used to read the large macro files such as 34 # This safe compartment is used to read the large macro files such as
35# PG.pl, PGbasicmacros.pl and PGanswermacros and cache the results so that 35 # PG.pl, PGbasicmacros.pl and PGanswermacros and cache the results so that
36# future calls have preloaded versions of these large files. 36 # future calls have preloaded versions of these large files. This saves a
37# This saves a significant amount of time. 37 # significant amount of time.
38
39 $WeBWorK::PG::Local::safeCache = new Safe; 38 $WeBWorK::PG::Local::safeCache = new Safe;
40# warn "Creating new Safe cache compartment ".$WeBWorK::PG::Local::safeCache->root;
41} 39}
40
42sub new { 41sub new {
43 my $invocant = shift; 42 my $invocant = shift;
44 my $class = ref($invocant) || $invocant; 43 my $class = ref($invocant) || $invocant;
45 my ( 44 my (
46 $ce, 45 $ce,
50 $problem, 49 $problem,
51 $psvn, 50 $psvn,
52 $formFields, # in CGI::Vars format 51 $formFields, # in CGI::Vars format
53 $translationOptions, # hashref containing options for the 52 $translationOptions, # hashref containing options for the
54 # translator, such as whether to show 53 # translator, such as whether to show
55 # hints and the display mode to use 54 # hints and the display mode to use
56 ) = @_; 55 ) = @_;
57 56
58 # write timing log entry 57 # write timing log entry
59 writeTimingLogEntry($ce, "WeBWorK::PG::new", 58 writeTimingLogEntry($ce, "WeBWorK::PG::new",
60 "user=".$user->user_id.",problem=".$ce->{courseName}."/".$set->set_id."/".$problem->problem_id.",mode=".$translationOptions->{displayMode}, 59 "user=".$user->user_id.",problem=".$ce->{courseName}."/".$set->set_id."/".$problem->problem_id.",mode=".$translationOptions->{displayMode},
89 $translator->load_extra_packages(@extra_packages); 88 $translator->load_extra_packages(@extra_packages);
90 } 89 }
91 90
92 # set the environment (from defineProblemEnvir) 91 # set the environment (from defineProblemEnvir)
93 #warn "PG: setting the environment (from defineProblemEnvir)\n"; 92 #warn "PG: setting the environment (from defineProblemEnvir)\n";
94 my $envir = defineProblemEnvir( 93 my $envir = $class->defineProblemEnvir(
95 $ce, 94 $ce,
96 $user, 95 $user,
97 $key, 96 $key,
98 $set, 97 $set,
99 $problem, 98 $problem,
104 $translator->environment($envir); 103 $translator->environment($envir);
105 104
106 # initialize the Translator 105 # initialize the Translator
107 #warn "PG: initializing the Translator\n"; 106 #warn "PG: initializing the Translator\n";
108 $translator->initialize(); 107 $translator->initialize();
109# $translator->dumpSafe; # debugging code 108
110###############################################################################
111# Preload the macros files which are used routinely: PG.pl, dangerousMacros.pl, IO.pl 109 # Preload the macros files which are used routinely: PG.pl,
112# PGbasicmacros.pl and PGanswermacros.pl 110 # dangerousMacros.pl, IO.pl, PGbasicmacros.pl, and PGanswermacros.pl
113# Preloading the last two files safes a significant amount of time. 111 # (Preloading the last two files safes a significant amount of time.)
114############################################################################### 112 #
115
116 # IO.pl, PG.pl, and dangerousMacros.pl are loaded using unrestricted_load 113 # IO.pl, PG.pl, and dangerousMacros.pl are loaded using
117 # This is hard wired into the Translator::pre_load_macro_files subroutine 114 # unrestricted_load This is hard wired into the
115 # Translator::pre_load_macro_files subroutine. I'd like to change this
118 # I'd like to change this at some point to have the same sort of interface to global.conf 116 # at some point to have the same sort of interface to global.conf that
119 # that the module loading does -- have a list of macros to load unrestrictedly. 117 # the module loading does -- have a list of macros to load
120 118 # unrestrictedly.
119 #
121# This has been replaced by the pre_load_macro_files subroutine. It loads AND caches the files. 120 # This has been replaced by the pre_load_macro_files subroutine. It
121 # loads AND caches the files. While PG.pl and dangerousMacros are not
122# While PG.pl and dangerousMacros are not large, they are referred to by PGbasicmacros and PGanswermacros. 122 # large, they are referred to by PGbasicmacros and PGanswermacros.
123# Because these are loaded into the cached name space (e.g. Safe::Root1::) all calls to, say NEW_ANSWER_NAME 123 # Because these are loaded into the cached name space (e.g.
124# are actually calls to Safe::Root1::NEW_ANSWER_NAME. It is useful to have these names inside the Safe::Root1: 124 # Safe::Root1::) all calls to, say NEW_ANSWER_NAME are actually calls
125# cached safe compartment. (NEW_ANSWER_NAME and all other subroutine names are also automatically exported into 125 # to Safe::Root1::NEW_ANSWER_NAME. It is useful to have these names
126 # inside the Safe::Root1: cached safe compartment. (NEW_ANSWER_NAME
127 # and all other subroutine names are also automatically exported into
126# the current safe compartment Safe::Rootx:: 128 # the current safe compartment Safe::Rootx::
127 129 #
128# The headers of both PGbasicmacros and PGanswermacros has code that insures that the constants used are imported into 130 # The headers of both PGbasicmacros and PGanswermacros has code that
129# the current safe compartment. This involves evaluating references to, say $main::displayMode, at runtime to insure that main 131 # insures that the constants used are imported into the current safe
132 # compartment. This involves evaluating references to, say
133 # $main::displayMode, at runtime to insure that main refers to
130# refers to Safe::Rootx:: and NOT to Safe::Root1::, which is the value of main:: at compile time. 134 # Safe::Rootx:: and NOT to Safe::Root1::, which is the value of main::
131 135 # at compile time.
132 136 #
133###############################################################################
134# TO ENABLE CACHEING UNCOMMENT THE CACHEING CODE 137 # TO ENABLE CACHEING UNCOMMENT THE FOLLOWING:
135# On webwork3 cached code is .2 seconds faster than non-cached code for an existing child. 138 eval{$translator->pre_load_macro_files(
136 139 $WeBWorK::PG::Local::safeCache,
137# CACHING CODE: 140 $ce->{pg}->{directories}->{macros},
138 eval{
139 $translator->pre_load_macro_files($WeBWorK::PG::Local::safeCache, $ce->{pg}->{directories}->{macros},
140 'PG.pl', 'dangerousMacros.pl','IO.pl','PGbasicmacros.pl','PGanswermacros.pl');}; 141 'PG.pl', 'dangerousMacros.pl','IO.pl','PGbasicmacros.pl','PGanswermacros.pl'
142 )};
141 warn "Error while preloading macro files: $@" if $@; 143 warn "Error while preloading macro files: $@" if $@;
142 144
143# STANDARD LOADING CODE: for cached script files this merely initializes the constants. 145 # STANDARD LOADING CODE: for cached script files, this merely
146 # initializes the constants.
144 foreach (qw( PG.pl dangerousMacros.pl IO.pl)) { 147 foreach (qw(PG.pl dangerousMacros.pl IO.pl)) {
145 my $macroPath = $ce->{pg}->{directories}->{macros} . "/$_"; 148 my $macroPath = $ce->{pg}->{directories}->{macros} . "/$_";
146 my $err = $translator->unrestricted_load($macroPath); 149 my $err = $translator->unrestricted_load($macroPath);
147 warn "Error while loading $macroPath: |$err|" if $err; 150 warn "Error while loading $macroPath: $err" if $err;
148 } 151 }
149############################################################################### 152
150
151 # set the opcode mask (using default values) 153 # set the opcode mask (using default values)
152 #warn "PG: setting the opcode mask (using default values)\n"; 154 #warn "PG: setting the opcode mask (using default values)\n";
153 $translator->set_mask(); 155 $translator->set_mask();
154 156
155 # store the problem source 157 # store the problem source
277 warnings => $warnings, 279 warnings => $warnings,
278 flags => $translator->rh_flags, 280 flags => $translator->rh_flags,
279 }, $class; 281 }, $class;
280} 282}
281 283
282# -----
283
284sub defineProblemEnvir {
285 my (
286 $ce,
287 $user,
288 $key,
289 $set,
290 $problem,
291 $psvn,
292 $formFields,
293 $options,
294 ) = @_;
295
296 my %envir;
297
298 # ----------------------------------------------------------------------
299
300 # PG environment variables
301 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
302 # any changes are noted by "ADDED:" or "REMOVED:"
303
304 # Vital state information
305 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img,
306 # texDisposition
307
308 $envir{psvn} = $set->psvn;
309 $envir{psvnNumber} = $envir{psvn};
310 $envir{probNum} = $problem->problem_id;
311 $envir{questionNumber} = $envir{probNum};
312 $envir{fileName} = $problem->source_file;
313 $envir{probFileName} = $envir{fileName};
314 $envir{problemSeed} = $problem->problem_seed;
315 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
316 $envir{languageMode} = $envir{displayMode};
317 $envir{outputMode} = $envir{displayMode};
318 $envir{displayHintsQ} = $options->{showHints};
319 $envir{displaySolutionsQ} = $options->{showSolutions};
320 # FIXME: this is HTML_img specific
321 #$envir{refreshMath2img} = $options->{refreshMath2img};
322 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex
323
324 # Problem Information
325 # ADDED: courseName, formatedDueDate
326
327 $envir{openDate} = $set->open_date;
328 $envir{formattedOpenDate} = formatDateTime($envir{openDate});
329 $envir{dueDate} = $set->due_date;
330 $envir{formattedDueDate} = formatDateTime($envir{dueDate});
331 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
332 $envir{answerDate} = $set->answer_date;
333 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate});
334 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
335 $envir{problemValue} = $problem->value;
336 $envir{sessionKey} = $key;
337 $envir{courseName} = $ce->{courseName};
338
339 # Student Information
340 # ADDED: studentID
341
342 $envir{sectionName} = $user->section;
343 $envir{sectionNumber} = $envir{sectionName};
344 $envir{recitationName} = $user->recitation;
345 $envir{recitationNumber} = $envir{recitationName};
346 $envir{setNumber} = $set->set_id;
347 $envir{studentLogin} = $user->user_id;
348 $envir{studentName} = $user->first_name . " " . $user->last_name;
349 $envir{studentID} = $user->student_id;
350
351 # Answer Information
352 # REMOVED: refSubmittedAnswers
353
354 $envir{inputs_ref} = $formFields;
355
356 # External Programs
357 # ADDED: externalLaTeXPath, externalDvipngPath,
358 # externalGif2EpsPath, externalPng2EpsPath
359
360 $envir{externalTTHPath} = $ce->{externalPrograms}->{tth};
361 $envir{externalLaTeXPath} = $ce->{externalPrograms}->{latex};
362 $envir{externalDvipngPath} = $ce->{externalPrograms}->{dvipng};
363 $envir{externalGif2EpsPath} = $ce->{externalPrograms}->{gif2eps};
364 $envir{externalPng2EpsPath} = $ce->{externalPrograms}->{png2eps};
365 $envir{externalGif2PngPath} = $ce->{externalPrograms}->{gif2png};
366
367 # Directories and URLs
368 # REMOVED: courseName
369 # ADDED: dvipngTempDir
370
371 $envir{cgiDirectory} = undef;
372 $envir{cgiURL} = undef;
373 $envir{classDirectory} = undef;
374 $envir{courseScriptsDirectory} = $ce->{pg}->{directories}->{macros}."/";
375 $envir{htmlDirectory} = $ce->{courseDirs}->{html}."/";
376 $envir{htmlURL} = $ce->{courseURLs}->{html}."/";
377 $envir{macroDirectory} = $ce->{courseDirs}->{macros}."/";
378 $envir{templateDirectory} = $ce->{courseDirs}->{templates}."/";
379 $envir{tempDirectory} = $ce->{courseDirs}->{html_temp}."/";
380 $envir{tempURL} = $ce->{courseURLs}->{html_temp}."/";
381 $envir{scriptDirectory} = undef;
382 $envir{webworkDocsURL} = $ce->{webworkURLs}->{docs}."/";
383 # FIXME: this is HTML_img mode-specific
384 #$envir{dvipngTempDir} = $options->{displayMode} eq 'images'
385 # ? makeTempDirectory($envir{tempDirectory}, "webwork-dvipng")
386 # : undef;
387
388 # Information for sending mail
389
390 $envir{mailSmtpServer} = $ce->{mail}->{smtpServer};
391 $envir{mailSmtpSender} = $ce->{mail}->{smtpSender};
392 $envir{ALLOW_MAIL_TO} = $ce->{mail}->{allowedRecipients};
393
394 # Default values for evaluating answers
395
396 my $ansEvalDefaults = $ce->{pg}->{ansEvalDefaults};
397 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
398
399 # ----------------------------------------------------------------------
400
401 my $basename = "equation-$envir{psvn}.$envir{probNum}";
402 $basename .= ".$envir{problemSeed}" if $envir{problemSeed};
403
404 # Object for generating equation images
405 $envir{imagegen} = WeBWorK::PG::ImageGenerator->new(
406 tempDir => $ce->{webworkDirs}->{tmp}, # global temp dir
407 latex => $envir{externalLaTeXPath},
408 dvipng => $envir{externalDvipngPath},
409 useCache => 1,
410 cacheDir => $ce->{webworkDirs}->{equationCache},
411 cacheURL => $ce->{webworkURLs}->{equationCache},
412 cacheDB => $ce->{webworkFiles}->{equationCacheDB},
413 );
414
415 # Other things...
416 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
417 $envir{PROBLEM_GRADER_TO_USE} = $ce->{pg}->{options}->{grader};
418 $envir{PRINT_FILE_NAMES_FOR} = $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
419
420 # variables for interpreting capa problems.
421 $envir{CAPA_Tools} = $ce->{pg}->{specialPGEnvironmentVars}->{CAPA_Tools};
422 $envir{CAPA_MCTools} = $ce->{pg}->{specialPGEnvironmentVars}->{CAPA_MCTools};
423 $envir{CAPA_Graphics_URL} = $ce->{pg}->{specialPGEnvironmentVars}->{CAPA_Graphics_URL};
424 $envir{CAPA_GraphicsDirectory} = $ce->{pg}->{specialPGEnvironmentVars}->{CAPA_GraphicsDirectory};
425
426 return \%envir;
427}
428
429sub translateDisplayModeNames($) {
430 my $name = shift;
431 return {
432 tex => "TeX",
433 plainText => "HTML",
434 formattedText => "HTML_tth",
435 images => "HTML_dpng", # "HTML_img",
436 }->{$name};
437}
438
439sub oldSafetyFilter {
440 my $answer = shift; # accepts one answer and checks it
441 my $submittedAnswer = $answer;
442 $answer = '' unless defined $answer;
443 my ($errorno);
444 $answer =~ tr/\000-\037/ /;
445 # Return if answer field is empty
446 unless ($answer =~ /\S/) {
447 #$errorno = "<BR>No answer was submitted.";
448 $errorno = 0; ## don't report blank answer as error
449 return ($answer,$errorno);
450 }
451 # replace ^ with ** (for exponentiation)
452 # $answer =~ s/\^/**/g;
453 # Return if forbidden characters are found
454 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
455 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
456 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
457 return ($answer,$errorno);
458 }
459 $errorno = 0;
460 return($answer, $errorno);
461}
462
463sub nullSafetyFilter {
464 return shift, 0; # no errors
465}
466
4671; 2841;
468 285
469__END__ 286__END__
470 287
471=head1 OPERATION 288=head1 OPERATION
472 289
473WeBWorK::PG goes through the following operations when constructed: 290WeBWorK::PG::Local goes through the following operations when constructed:
474 291
475=over 292=over
476
477=item Get database information
478
479Retrieve information about the current user, set, and problem from the
480database.
481 293
482=item Create a translator 294=item Create a translator
483 295
484Instantiate a WeBWorK::PG::Translator object. 296Instantiate a WeBWorK::PG::Translator object.
485 297
493Using the module list from the course environment (pg->modules), perform a 305Using the module list from the course environment (pg->modules), perform a
494"use"-like operation to evaluate modules at runtime. 306"use"-like operation to evaluate modules at runtime.
495 307
496=item Set the problem environment 308=item Set the problem environment
497 309
498Use data from the user, set, and problem, as well as the course environemnt and 310Use data from the user, set, and problem, as well as the course
499translation options, to set the problem environment. 311environemnt and translation options, to set the problem environment. The
312default subroutine, &WeBWorK::PG::defineProblemEnvir, is used.
500 313
501=item Initialize the translator 314=item Initialize the translator
502 315
503Call &WeBWorK::PG::Translator::initialize. What more do you want? 316Call &WeBWorK::PG::Translator::initialize. What more do you want?
504 317
505=item Load PG.pl and dangerousMacros.pl 318=item Load IO.pl, PG.pl and dangerousMacros.pl
506 319
507These macros must be loaded without opcode masking, so they are loaded here. 320These macros must be loaded without opcode masking, so they are loaded here.
508 321
509=item Set the opcode mask 322=item Set the opcode mask
510 323

Legend:
Removed from v.1537  
changed lines
  Added in v.1558

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9