[system] / branches / rel-2-4-patches / webwork2 / lib / WeBWorK / PG.pm Repository:
ViewVC logotype

Diff of /branches/rel-2-4-patches/webwork2/lib/WeBWorK/PG.pm

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

trunk/webwork2/lib/WeBWorK/PG.pm Revision 698 branches/rel-2-4-dev/webwork2/lib/WeBWorK/PG.pm Revision 5243
1################################################################################ 1################################################################################
2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 2# WeBWorK Online Homework Delivery System
3# $Id$ 3# Copyright © 2000-2006 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: webwork2/lib/WeBWorK/PG.pm,v 1.71 2006/12/05 20:59:45 sh002i Exp $
5#
6# This program is free software; you can redistribute it and/or modify it under
7# the terms of either: (a) the GNU General Public License as published by the
8# Free Software Foundation; either version 2, or (at your option) any later
9# version, or (b) the "Artistic License" which comes with this package.
10#
11# This program is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14# Artistic License for more details.
4################################################################################ 15################################################################################
5 16
6package WeBWorK::PG; 17package WeBWorK::PG;
7 18
8=head1 NAME 19=head1 NAME
9 20
10WeBWorK::PG - Wrap the action of the PG Translator in an easy-to-use API. 21WeBWorK::PG - Invoke one of several PG rendering methods using an easy-to-use
22API.
11 23
12=cut 24=cut
13 25
14use strict; 26use strict;
15use warnings; 27use warnings;
16use File::Path qw(rmtree);
17use File::Temp qw(tempdir);
18use WeBWorK::DB::Classlist;
19use WeBWorK::DB::WW;
20use WeBWorK::PG::Translator; 28use WeBWorK::PG::ImageGenerator;
21use WeBWorK::Problem; 29use WeBWorK::Utils qw(runtime_use formatDateTime makeTempDirectory);
22use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry); 30use WeBWorK::Utils::RestrictedClosureClass;
23 31
24sub new($$$$$$$$) { 32use constant DISPLAY_MODES => {
25 my $invocant = shift; 33 # display name # mode name
26 my $class = ref($invocant) || $invocant; 34 tex => "TeX",
35 plainText => "HTML",
36 formattedText => "HTML_tth",
37 images => "HTML_dpng",
38 jsMath => "HTML_jsMath",
39 asciimath => "HTML_asciimath",
40 LaTeXMathML => "HTML_LaTeXMathML",
41};
42
43sub new {
44 shift; # throw away invocant -- we don't need it
45 my ($ce, $user, $key, $set, $problem, $psvn, $formFields,
46 $translationOptions) = @_;
47
48 my $renderer = $ce->{pg}->{renderer};
49
50 runtime_use $renderer;
51
52 return $renderer->new(@_);
53}
54
55sub defineProblemEnvir {
27 my ( 56 my (
28 $courseEnv,
29 $user,
30 $key,
31 $set, 57 $self,
32 $problem,
33 $psvn,
34 $formFields, # in CGI::Vars format
35 $translationOptions, # hashref containing options for the
36 # translator, such as whether to show
37 # hints and the display mode to use
38 ) = @_;
39
40 # write timing log entry
41 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
42 "user=".$user->id.",problem=".$courseEnv->{courseName}."/".$set->id."/".$problem->id.",mode=".$translationOptions->{displayMode},
43 "begin");
44
45 # install a local warn handler to collect warnings
46 my $warnings = "";
47 local $SIG{__WARN__} = sub { $warnings .= shift }
48 if $courseEnv->{pg}->{options}->{catchWarnings};
49
50 # create a Translator
51 #warn "PG: creating a Translator\n";
52 my $translator = WeBWorK::PG::Translator->new;
53
54 # set the directory hash
55 #warn "PG: setting the directory hash\n";
56 $translator->rh_directories({
57 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
58 macroDirectory => $courseEnv->{courseDirs}->{macros},
59 templateDirectory => $courseEnv->{courseDirs}->{templates},
60 tempDirectory => $courseEnv->{courseDirs}->{html_temp},
61 });
62
63 # evaluate modules and "extra packages"
64 #warn "PG: evaluating modules and \"extra packages\"\n";
65 my @modules = @{ $courseEnv->{pg}->{modules} };
66 foreach my $module_packages_ref (@modules) {
67 my ($module, @extra_packages) = @$module_packages_ref;
68 # the first item is the main package
69 $translator->evaluate_modules($module);
70 # the remaining items are "extra" packages
71 $translator->load_extra_packages(@extra_packages);
72 }
73
74 # set the environment (from defineProblemEnvir)
75 #warn "PG: setting the environment (from defineProblemEnvir)\n";
76 my $envir = defineProblemEnvir(
77 $courseEnv,
78 $user,
79 $key, 58 $ce,
80 $set,
81 $problem,
82 $psvn,
83 $formFields,
84 $translationOptions,
85 );
86 $translator->environment($envir);
87
88 # initialize the Translator
89 #warn "PG: initializing the Translator\n";
90 $translator->initialize();
91
92 # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load
93 # i'd like to change this at some point to have the same sort of interface to global.conf
94 # that the module loading does -- have a list of macros to load unrestrictedly.
95 #warn "PG: loading IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load\n";
96 foreach (qw(IO.pl PG.pl dangerousMacros.pl)) {
97 my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
98 my $err = $translator->unrestricted_load($macroPath);
99 warn "Error while loading $macroPath: $err" if $err;
100 }
101
102 # set the opcode mask (using default values)
103 #warn "PG: setting the opcode mask (using default values)\n";
104 $translator->set_mask();
105
106 # store the problem source
107 #warn "PG: storing the problem source\n";
108 my $sourceFile = $problem->source_file;
109 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
110 unless ($sourceFile =~ /^\//);
111 eval { $translator->source_string(readFile($sourceFile)) };
112 if ($@) {
113 # well, we couldn't get the problem source, for some reason.
114 return bless {
115 translator => $translator,
116 head_text => "",
117 body_text => <<EOF,
118WeBWorK::Utils::readFile($sourceFile) says:
119$@
120EOF
121 answers => {},
122 result => {},
123 state => {},
124 errors => "Failed to read the problem source file.",
125 warnings => $warnings,
126 flags => {error_flag => 1},
127 }, $class;
128 }
129
130 # install a safety filter (&safetyFilter)
131 #warn "PG: installing a safety filter\n";
132 $translator->rf_safety_filter(\&safetyFilter);
133
134 # write timing log entry -- the translator is now all set up
135 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
136 "initialized",
137 "intermediate");
138
139 # translate the PG source into text
140 #warn "PG: translating the PG source into text\n";
141 $translator->translate();
142
143 # after we're done translating, we may have to clean up after the translator.
144 # for example, 'images' mode uses a tempdir for dvipng's temp files. We have
145 # to remove it.
146 if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) {
147 rmtree($envir->{dvipngTempDir}, 0, 0);
148 }
149
150 my ($result, $state); # we'll need these on the other side of the if block!
151 if ($translationOptions->{processAnswers}) {
152
153 # process student answers
154 #warn "PG: processing student answers\n";
155 $translator->process_answers($formFields);
156
157 # retrieve the problem state and give it to the translator
158 #warn "PG: retrieving the problem state and giving it to the translator\n";
159 $translator->rh_problem_state({
160 recorded_score => $problem->status,
161 num_of_correct_ans => $problem->num_correct,
162 num_of_incorrect_ans => $problem->num_incorrect,
163 });
164
165 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
166 # the PG macro package (PG.pl)
167 #warn "PG: determining an entry order\n";
168 my @answerOrder =
169 $translator->rh_flags->{ANSWER_ENTRY_ORDER}
170 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
171 : keys %{ $translator->rh_evaluated_answers };
172
173 # install a grader -- use the one specified in the problem,
174 # or fall back on the default from the course environment.
175 # (two magic strings are accepted, to avoid having to
176 # reference code when it would be difficult.)
177 #warn "PG: installing a grader\n";
178 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
179 || $courseEnv->{pg}->{options}->{grader};
180 $grader = $translator->rf_std_problem_grader
181 if $grader eq "std_problem_grader";
182 $grader = $translator->rf_avg_problem_grader
183 if $grader eq "avg_problem_grader";
184 die "Problem grader $grader is not a CODE reference."
185 unless ref $grader eq "CODE";
186 $translator->rf_problem_grader($grader);
187
188 # grade the problem
189 #warn "PG: grading the problem\n";
190 ($result, $state) = $translator->grade_problem(
191 answers_submitted => $translationOptions->{processAnswers},
192 ANSWER_ENTRY_ORDER => \@answerOrder,
193 );
194
195 }
196
197 # write timing log entry
198 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
199
200 # return an object which contains the translator and the results of
201 # the translation process. this is DIFFERENT from the "format expected
202 # by Webwork.pm (and I believe processProblem8, but check.)"
203 return bless {
204 translator => $translator,
205 head_text => ${ $translator->r_header },
206 body_text => ${ $translator->r_text },
207 answers => $translator->rh_evaluated_answers,
208 result => $result,
209 state => $state,
210 errors => $translator->errors,
211 warnings => $warnings,
212 flags => $translator->rh_flags,
213 }, $class;
214}
215
216# -----
217
218sub defineProblemEnvir($$$$$$$) {
219 my (
220 $courseEnv,
221 $user, 59 $user,
222 $key, 60 $key,
223 $set, 61 $set,
224 $problem, 62 $problem,
225 $psvn, 63 $psvn,
226 $formFields, 64 $formFields,
227 $options, 65 $options,
66 $extras,
228 ) = @_; 67 ) = @_;
229 68
230 my %envir; 69 my %envir;
70
71 # ----------------------------------------------------------------------
231 72
232 # PG environment variables 73 # PG environment variables
233 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 74 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
234 # any changes are noted by "ADDED:" or "REMOVED:" 75 # any changes are noted by "ADDED:" or "REMOVED:"
235 76
236 # Vital state information 77 # Vital state information
237 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img, 78 # ADDED: displayModeFailover, displayHintsQ, displaySolutionsQ,
238 # texDisposition 79 # refreshMath2img, texDisposition
239 80
240 $envir{psvn} = $psvn; 81 $envir{psvn} = $set->psvn;
241 $envir{psvnNumber} = $envir{psvn}; 82 $envir{psvnNumber} = $envir{psvn};
242 $envir{probNum} = $problem->id; 83 $envir{probNum} = $problem->problem_id;
243 $envir{questionNumber} = $envir{probNum}; 84 $envir{questionNumber} = $envir{probNum};
244 $envir{fileName} = $problem->source_file; 85 $envir{fileName} = $problem->source_file;
245 $envir{probFileName} = $envir{fileName}; 86 $envir{probFileName} = $envir{fileName};
246 $envir{problemSeed} = $problem->problem_seed; 87 $envir{problemSeed} = $problem->problem_seed;
247 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 88 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
248 $envir{languageMode} = $envir{displayMode}; 89 $envir{languageMode} = $envir{displayMode};
249 $envir{outputMode} = $envir{displayMode}; 90 $envir{outputMode} = $envir{displayMode};
250 $envir{displayHintsQ} = $options->{showHints}; 91 $envir{displayHintsQ} = $options->{showHints};
251 $envir{displaySolutionsQ} = $options->{showSolutions}; 92 $envir{displaySolutionsQ} = $options->{showSolutions};
252 $envir{refreshMath2img} = $options->{refreshMath2img};
253 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex 93 $envir{texDisposition} = "pdf"; # in webwork2, we use pdflatex
254 94
255 # Problem Information 95 # Problem Information
256 # ADDED: courseName, formatedDueDate 96 # ADDED: courseName, formatedDueDate
257 97
258 $envir{openDate} = $set->open_date; 98 $envir{openDate} = $set->open_date;
259 $envir{formattedOpenDate} = formatDateTime($envir{openDate}); 99 $envir{formattedOpenDate} = formatDateTime($envir{openDate}, $ce->{siteDefaults}{timezone});
260 $envir{dueDate} = $set->due_date; 100 $envir{dueDate} = $set->due_date;
261 $envir{formattedDueDate} = formatDateTime($envir{dueDate}); 101 $envir{formattedDueDate} = formatDateTime($envir{dueDate}, $ce->{siteDefaults}{timezone});
262 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files 102 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
263 $envir{answerDate} = $set->answer_date; 103 $envir{answerDate} = $set->answer_date;
264 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}); 104 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}, $ce->{siteDefaults}{timezone});
265 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0); 105 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
266 $envir{problemValue} = $problem->value; 106 $envir{problemValue} = $problem->value;
267 $envir{sessionKey} = $key; 107 $envir{sessionKey} = $key;
268 $envir{courseName} = $courseEnv->{courseName}; 108 $envir{courseName} = $ce->{courseName};
269 109
270 # Student Information 110 # Student Information
271 # ADDED: studentID 111 # ADDED: studentID
272 112
273 $envir{sectionName} = $user->section; 113 $envir{sectionName} = $user->section;
274 $envir{sectionNumber} = $envir{sectionName}; 114 $envir{sectionNumber} = $envir{sectionName};
275 $envir{recitationName} = $user->recitation; 115 $envir{recitationName} = $user->recitation;
276 $envir{recitationNumber} = $envir{recitationName}; 116 $envir{recitationNumber} = $envir{recitationName};
277 $envir{setNumber} = $set->id; 117 $envir{setNumber} = $set->set_id;
278 $envir{studentLogin} = $user->id; 118 $envir{studentLogin} = $user->user_id;
279 $envir{studentName} = $user->first_name . " " . $user->last_name; 119 $envir{studentName} = $user->first_name . " " . $user->last_name;
280 $envir{studentID} = $user->student_id; 120 $envir{studentID} = $user->student_id;
281 121
282 # Answer Information 122 # Answer Information
283 # REMOVED: refSubmittedAnswers 123 # REMOVED: refSubmittedAnswers
286 126
287 # External Programs 127 # External Programs
288 # ADDED: externalLaTeXPath, externalDvipngPath, 128 # ADDED: externalLaTeXPath, externalDvipngPath,
289 # externalGif2EpsPath, externalPng2EpsPath 129 # externalGif2EpsPath, externalPng2EpsPath
290 130
291 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth}; 131 $envir{externalTTHPath} = $ce->{externalPrograms}->{tth};
292 $envir{externalLaTeXPath} = $courseEnv->{externalPrograms}->{latex}; 132 $envir{externalLaTeXPath} = $ce->{externalPrograms}->{latex};
293 $envir{externalDvipngPath} = $courseEnv->{externalPrograms}->{dvipng}; 133 $envir{externalDvipngPath} = $ce->{externalPrograms}->{dvipng};
294 $envir{externalGif2EpsPath} = $courseEnv->{externalPrograms}->{gif2eps}; 134 $envir{externalGif2EpsPath} = $ce->{externalPrograms}->{gif2eps};
295 $envir{externalPng2EpsPath} = $courseEnv->{externalPrograms}->{png2eps}; 135 $envir{externalPng2EpsPath} = $ce->{externalPrograms}->{png2eps};
296 $envir{externalGif2PngPath} = $courseEnv->{externalPrograms}->{gif2png}; 136 $envir{externalGif2PngPath} = $ce->{externalPrograms}->{gif2png};
297 137 $envir{externalCheckUrl} = $ce->{externalPrograms}->{checkurl};
298 # Directories and URLs 138 # Directories and URLs
299 # REMOVED: courseName 139 # REMOVED: courseName
300 # ADDED: dvipngTempDir 140 # ADDED: dvipngTempDir
141 # ADDED: jsMathURL
142 # ADDED: asciimathURL
143 # ADDED: macrosPath
144 # REMOVED: macrosDirectory, courseScriptsDirectory
145 # ADDED: LaTeXMathML
301 146
302 $envir{cgiDirectory} = undef; 147 $envir{cgiDirectory} = undef;
303 $envir{cgiURL} = undef; 148 $envir{cgiURL} = undef;
304 $envir{classDirectory} = undef; 149 $envir{classDirectory} = undef;
305 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/"; 150 $envir{macrosPath} = $ce->{pg}->{directories}{macrosPath};
151 $envir{appletPath} = $ce->{pg}->{directories}{appletPath};
152 $envir{pgDirectories} = $ce->{pg}->{directories};
306 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/"; 153 $envir{htmlDirectory} = $ce->{courseDirs}->{html}."/";
307 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}."/"; 154 $envir{htmlURL} = $ce->{courseURLs}->{html}."/";
308 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/";
309 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 155 $envir{templateDirectory} = $ce->{courseDirs}->{templates}."/";
310 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 156 $envir{tempDirectory} = $ce->{courseDirs}->{html_temp}."/";
311 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/"; 157 $envir{tempURL} = $ce->{courseURLs}->{html_temp}."/";
312 $envir{scriptDirectory} = undef; 158 $envir{scriptDirectory} = undef;
313 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/"; 159 $envir{webworkDocsURL} = $ce->{webworkURLs}->{docs}."/";
314 $envir{dvipngTempDir} = $options->{displayMode} eq 'images' 160 $envir{localHelpURL} = $ce->{webworkURLs}->{local_help}."/";
315 ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory}) 161 $envir{jsMathURL} = $ce->{webworkURLs}->{jsMath};
316 : undef; 162 $envir{asciimathURL} = $ce->{webworkURLs}->{asciimath};
163 $envir{LaTeXMathMLURL} = $ce->{webworkURLs}->{LaTeXMathML};
164 $envir{server_root_url} = $ce->{apache_root_url};
317 165
318 # Information for sending mail 166 # Information for sending mail
319 167
320 $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer}; 168 $envir{mailSmtpServer} = $ce->{mail}->{smtpServer};
321 $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender}; 169 $envir{mailSmtpSender} = $ce->{mail}->{smtpSender};
170 $envir{ALLOW_MAIL_TO} = $ce->{mail}->{allowedRecipients};
322 171
323 # Default values for evaluating answers 172 # Default values for evaluating answers
324 173
325 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 174 my $ansEvalDefaults = $ce->{pg}->{ansEvalDefaults};
326 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 175 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
327 176
177 # ----------------------------------------------------------------------
178
179 # ADDED: ImageGenerator for images mode
180 if (defined $extras->{image_generator}) {
181 #$envir{imagegen} = $extras->{image_generator};
182 # only allow access to the add() method
183 $envir{imagegen} = new WeBWorK::Utils::RestrictedClosureClass($extras->{image_generator}, "add");
184 }
185
186 if (defined $extras->{mailer}) {
187 #my $rmailer = new WeBWorK::Utils::RestrictedClosureClass($extras->{mailer},
188 # qw/Open SendEnc Close Cancel skipped_recipients error error_msg/);
189 #my $safe_hole = new Safe::Hole {};
190 #$envir{mailer} = $safe_hole->wrap($rmailer);
191 $envir{mailer} = new WeBWorK::Utils::RestrictedClosureClass($extras->{mailer}, "add_message");
192 }
193
194 # ADDED: jsMath options
195 $envir{jsMath} = {%{$ce->{pg}{displayModeOptions}{jsMath}}};
196
328 # Other things... 197 # Other things...
329 198 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
330 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 199 $envir{PROBLEM_GRADER_TO_USE} = $ce->{pg}->{options}->{grader};
331 $envir{ALLOW_MAIL_TO} = $courseEnv->{email}->{allowedRecipients}; 200 $envir{PRINT_FILE_NAMES_FOR} = $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
201
202 # ADDED: __files__
203 # an array for mapping (eval nnn) to filenames in error messages
204 $envir{__files__} = {
205 root => $ce->{webworkDirs}{root}, # used to shorten filenames
206 pg => $ce->{pg}{directories}{root}, # ditto
207 tmpl => $ce->{courseDirs}{templates}, # ditto
208 };
209
210 # variables for interpreting capa problems and other things to be
211 # seen in a pg file
212 my $specialPGEnvironmentVarHash = $ce->{pg}->{specialPGEnvironmentVars};
213 for my $SPGEV (keys %{$specialPGEnvironmentVarHash}) {
214 $envir{$SPGEV} = $specialPGEnvironmentVarHash->{$SPGEV};
215 }
332 216
333 return \%envir; 217 return \%envir;
334} 218}
335 219
336sub translateDisplayModeNames($) { 220sub translateDisplayModeNames($) {
337 my $name = shift; 221 my $name = shift;
338 return { 222 return DISPLAY_MODES()->{$name};
339 tex => "TeX",
340 plainText => "HTML",
341 formattedText => "HTML_tth",
342 images => "HTML_img"
343 }->{$name};
344} 223}
345 224
346sub safetyFilter { 225sub oldSafetyFilter {
347 my $answer = shift; # accepts one answer and checks it 226 my $answer = shift; # accepts one answer and checks it
348 my $submittedAnswer = $answer; 227 my $submittedAnswer = $answer;
349 $answer = '' unless defined $answer; 228 $answer = '' unless defined $answer;
350 my ($errorno); 229 my ($errorno);
351 $answer =~ tr/\000-\037/ /; 230 $answer =~ tr/\000-\037/ /;
356 return ($answer,$errorno); 235 return ($answer,$errorno);
357 } 236 }
358 # replace ^ with ** (for exponentiation) 237 # replace ^ with ** (for exponentiation)
359 # $answer =~ s/\^/**/g; 238 # $answer =~ s/\^/**/g;
360 # Return if forbidden characters are found 239 # Return if forbidden characters are found
361 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 240 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
362 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 241 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
363 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 242 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
364 return ($answer,$errorno); 243 return ($answer,$errorno);
365 } 244 }
366 $errorno = 0; 245 $errorno = 0;
367 return($answer, $errorno); 246 return($answer, $errorno);
368} 247}
369 248
249sub nullSafetyFilter {
250 return shift, 0; # no errors
251}
252
3701; 2531;
371 254
372__END__ 255__END__
373 256
374=head1 SYNOPSIS 257=head1 SYNOPSIS
375 258
376 $pg = WeBWorK::PG->new( 259 $pg = WeBWorK::PG->new(
377 $courseEnv, # a WeBWorK::CourseEnvironment object 260 $ce, # a WeBWorK::CourseEnvironment object
378 $user, # a WeBWorK::User object 261 $user, # a WeBWorK::DB::Record::User object
379 $sessionKey, 262 $sessionKey,
380 $set, # a WeBWorK::Set object 263 $set, # a WeBWorK::DB::Record::UserSet object
381 $problem, # a WeBWorK::Problem object 264 $problem, # a WeBWorK::DB::Record::UserProblem object
382 $psvn, 265 $psvn,
383 $formFields # in &WeBWorK::Form::Vars format 266 $formFields # in &WeBWorK::Form::Vars format
384 { # translation options 267 { # translation options
385 displayMode => "images", # (plainText|formattedText|images) 268 displayMode => "images", # (plainText|formattedText|images)
386 showHints => 1, # (0|1) 269 showHints => 1, # (0|1)
400 $warnings = $pg->{warnings}; # text string 283 $warnings = $pg->{warnings}; # text string
401 $flags = $pg->{flags}; # hash reference 284 $flags = $pg->{flags}; # hash reference
402 285
403=head1 DESCRIPTION 286=head1 DESCRIPTION
404 287
405WeBWorK::PG encapsulates the PG translation process, making multiple calls to 288WeBWorK::PG is a factory for modules which use the WeBWorK::PG API. Notable
406WeBWorK::PG::Translator. Much of the flexibility of the Translator is hidden, 289modules which use this API (and exist) are WeBWorK::PG::Local and
407instead making choices that are appropriate for the webwork-modperl system. 290WeBWorK::PG::Remote. The course environment key $pg{renderer} is consulted to
291determine which render to use.
408 292
409=head1 CONSTRUCTION 293=head1 THE WEBWORK::PG API
294
295Modules which support this API must implement the following method:
410 296
411=over 297=over
412 298
413=item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS) 299=item new ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
414 300
415The C<new> method creates a translator, initializes it using the parameters 301The C<new> method creates a translator, initializes it using the parameters
416specified, translates a PG file, and processes answers. It returns a reference 302specified, translates a PG file, and processes answers. It returns a reference
417to a blessed hash containing the results of the translation process. 303to a blessed hash containing the results of the translation process.
418 304
438 324
439a WeBWorK::Set object 325a WeBWorK::Set object
440 326
441=item PROBLEM 327=item PROBLEM
442 328
443a WeBWorK::Problem object. The contents of the source_file field can specify a 329a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
444PG file either by absolute path or path relative to the "templates" directory. 330field can specify a PG file either by absolute path or path relative to the
445I<The caller should remove taint from this value before passing!> 331"templates" directory. I<The caller should remove taint from this value before
332passing!>
446 333
447=item PSVN 334=item PSVN
448 335
449the problem set version number 336the problem set version number
450 337
473boolean, render solutions 360boolean, render solutions
474 361
475=item refreshMath2img 362=item refreshMath2img
476 363
477boolean, force images created by math2img (in "images" mode) to be recreated, 364boolean, force images created by math2img (in "images" mode) to be recreated,
478even if the PG source has not been updated. 365even if the PG source has not been updated. FIXME: remove this option.
479 366
480=item processAnswers 367=item processAnswers
481 368
482boolean, call answer evaluators and graders 369boolean, call answer evaluators and graders
483 370
531 418
532A hash containing PG_flags (see the Translator docs). 419A hash containing PG_flags (see the Translator docs).
533 420
534=back 421=back
535 422
536=head1 OPERATION 423=head1 METHODS PROVIDED BY THE BASE CLASS
537 424
538WeBWorK::PG goes through the following operations when constructed: 425The following methods are provided for use by subclasses of WeBWorK::PG.
539 426
540=over 427=over
541 428
542=item Get database information 429=item defineProblemEnvir ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
543 430
544Retrieve information about the current user, set, and problem from the 431Generate a problem environment hash to pass to the renderer.
545database.
546 432
547=item Create a translator 433=item translateDisplayModeNames NAME
548 434
549Instantiate a WeBWorK::PG::Translator object. 435NAME contains
550
551=item Set the directory hash
552
553Set the translator's directory hash (courseScripts, macros, templates, and temp
554directories) from the course environment.
555
556=item Evaluate PG modules
557
558Using the module list from the course environment (pg->modules), perform a
559"use"-like operation to evaluate modules at runtime.
560
561=item Set the problem environment
562
563Use data from the user, set, and problem, as well as the course environemnt and
564translation options, to set the problem environment.
565
566=item Initialize the translator
567
568Call &WeBWorK::PG::Translator::initialize. What more do you want?
569
570=item Load PG.pl and dangerousMacros.pl
571
572These macros must be loaded without opcode masking, so they are loaded here.
573
574=item Set the opcode mask
575
576Set the opcode mask to the default specified by WeBWorK::PG::Translator.
577
578=item Load the problem source
579
580Give the problem source to the translator.
581
582=item Install a safety filter
583
584The safety filter is used to preprocess student input before evaluation. The
585default safety filter, &WeBWorK::PG::safetyFilter, is used.
586
587=item Translate the problem source
588
589Call &WeBWorK::PG::Translator::translate to render the problem source into the
590format given by the display mode.
591
592=item Process student answers
593
594Use form field inputs to evaluate student answers.
595
596=item Load the problem state
597
598Use values from the database to initialize the problem state, so that the
599grader will have a point of reference.
600
601=item Determine an entry order
602
603Use the ANSWER_ENTRY_ORDER flag to determine the order of answers in the
604problem. This is important for problems with dependancies among parts.
605
606=item Install a grader
607
608Use the PROBLEM_GRADER_TO_USE flag, or a default from the course environment,
609to install a grader.
610
611=item Grade the problem
612
613Use the selected grader to grade the problem.
614 436
615=back 437=back
616 438
617=head1 AUTHOR 439=head1 AUTHOR
618 440

Legend:
Removed from v.698  
changed lines
  Added in v.5243

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9