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

Legend:
Removed from v.692  
changed lines
  Added in v.5744

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9