[system] / branches / rel-2-4-dev / webwork-modperl / lib / WeBWorK.pm Repository:
ViewVC logotype

Diff of /branches/rel-2-4-dev/webwork-modperl/lib/WeBWorK.pm

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

Revision 1612 Revision 3598
1################################################################################ 1################################################################################
2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 2# WeBWorK Online Homework Delivery System
3# $Id$ 3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: webwork2/lib/WeBWorK.pm,v 1.74 2005/08/17 16:05:48 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; 17package WeBWorK;
7 18
8=head1 NAME 19=head1 NAME
19 30
20C<WeBWorK> is the dispatcher for the WeBWorK system. Given an Apache request 31C<WeBWorK> is the dispatcher for the WeBWorK system. Given an Apache request
21object, it performs authentication and determines which subclass of 32object, it performs authentication and determines which subclass of
22C<WeBWorK::ContentGenerator> to call. 33C<WeBWorK::ContentGenerator> to call.
23 34
24=head1 REQUEST FORMAT
25
26 FIXME: write this part
27 summary: the URI controls
28
29=cut 35=cut
30 36
31BEGIN { $main::VERSION = "2.0"; } 37BEGIN { $main::VERSION = "2.1"; }
32
33my $timingON = 0;
34
35 38
36use strict; 39use strict;
37use warnings; 40use warnings;
38use Apache::Constants qw(:common REDIRECT DONE); 41use Apache::Constants qw(:common REDIRECT DONE);
39use Apache::Request; 42use Time::HiRes qw/time/;
43
44# load WeBWorK::Constants before anything else
45# this sets package variables in several packages
46use WeBWorK::Constants;
47
48# the rest of these are modules that are acutally used by this one
40use WeBWorK::Authen; 49use WeBWorK::Authen;
41use WeBWorK::Authz; 50use WeBWorK::Authz;
42use WeBWorK::ContentGenerator::Feedback;
43use WeBWorK::ContentGenerator::GatewayQuiz;
44use WeBWorK::ContentGenerator::Hardcopy;
45use WeBWorK::ContentGenerator::Instructor::AddUsers;
46use WeBWorK::ContentGenerator::Instructor::Assigner;
47use WeBWorK::ContentGenerator::Instructor::Index;
48#use WeBWorK::ContentGenerator::Instructor::Index2;
49use WeBWorK::ContentGenerator::Instructor::PGProblemEditor;
50use WeBWorK::ContentGenerator::Instructor::ProblemList;
51use WeBWorK::ContentGenerator::Instructor::ProblemSetEditor;
52use WeBWorK::ContentGenerator::Instructor::ProblemSetList;
53use WeBWorK::ContentGenerator::Instructor::UserList;
54use WeBWorK::ContentGenerator::Instructor::SendMail;
55use WeBWorK::ContentGenerator::Instructor::ShowAnswers;
56use WeBWorK::ContentGenerator::Instructor::Scoring;
57use WeBWorK::ContentGenerator::Instructor::ScoringDownload;
58use WeBWorK::ContentGenerator::Instructor::ScoringTotals;
59use WeBWorK::ContentGenerator::Instructor::Stats;
60use WeBWorK::ContentGenerator::Login;
61use WeBWorK::ContentGenerator::Logout;
62use WeBWorK::ContentGenerator::Options;
63use WeBWorK::ContentGenerator::Problem;
64use WeBWorK::ContentGenerator::ProblemSet;
65use WeBWorK::ContentGenerator::ProblemSets;
66use WeBWorK::ContentGenerator::Test;
67use WeBWorK::CourseEnvironment; 51use WeBWorK::CourseEnvironment;
68use WeBWorK::DB; 52use WeBWorK::DB;
69use WeBWorK::Timing; 53use WeBWorK::Debug;
54use WeBWorK::Request;
55use WeBWorK::Upload;
56use WeBWorK::URLPath;
57use WeBWorK::Utils qw(runtime_use writeTimingLogEntry);
70 58
71=head1 THE C<&dispatch> FUNCTION 59use constant AUTHEN_MODULE => "WeBWorK::ContentGenerator::Login";
60use constant PROCTOR_AUTHEN_MODULE => "WeBWorK::ContentGenerator::LoginProctor";
61use constant FIXDB_MODULE => "WeBWorK::ContentGenerator::FixDB";
72 62
73The C<&dispatch> function takes an Apache request object (REQUEST) and returns 63our %SeedCE;
74an apache status code. Below is an overview of its operation:
75
76=over
77
78=cut
79 64
80sub dispatch($) { 65sub dispatch($) {
81 my ($apache) = @_; 66 my ($apache) = @_;
82 my $r = Apache::Request->new($apache); 67 my $r = new WeBWorK::Request $apache;
83 # have to deal with unpredictable GET or POST data, and sift
84 # through it for the key. So use Apache::Request
85 68
86 # This stuff is pretty much copied out of the O'Reilly mod_perl book. 69 my $method = $r->method;
87 # It's for figuring out the basepath. I may change this up if I find a 70 my $location = $r->location;
88 # better way to do it. 71 my $uri = $r->uri;
89 my $path_info = $r->path_info || ""; 72 my $path_info = $r->path_info | "";
90 $path_info =~ s!/+!/!g; # strip multiple forward slashes
91 my $current_uri = $r->uri;
92 my $args = $r->args; 73 my $args = $r->args || "";
74 #my $webwork_root = $r->dir_config("webwork_root");
75 #my $pg_root = $r->dir_config("pg_root");
93 76
94 my ($urlRoot) = $current_uri =~ m/^(.*)$path_info/; 77 debug("\n\n===> Begin " . __PACKAGE__ . "::dispatch() <===\n\n");
95 78 debug("Hi, I'm the new dispatcher!\n");
96=item Ensure that the URI ends with a "/" 79 debug(("-" x 80) . "\n");
97
98Parts of WeBWorK assume that the current URI of a request ends with a "/". If
99this is not the case, a redirection is issued to add the "/". This action will
100discard any POST data associated with the request, so it is essential that all
101POST requests include a "/" at the end of the URI.
102
103=cut
104 80
105 # If it's a valid WeBWorK URI, it ends in a /. This is assumed 81 debug("Okay, I got some basic information:\n");
106 # alllll over the place. 82 debug("The apache location is $location\n");
107 unless (substr($current_uri,-1) eq '/') { 83 debug("The request method is $method\n");
108 $r->header_out(Location => "$current_uri/" . ($args ? "?$args" : "")); 84 debug("The URI is $uri\n");
109 return REDIRECT; 85 debug("The path-info is $path_info\n");
110 # *** any post data gets lost here -- fix that. 86 debug("The argument string is $args\n");
111 # (actually, it's not a problem, since all URLs generated 87 #debug("The WeBWorK root directory is $webwork_root\n");
112 # from within the system have trailing slashes, and we don't 88 #debug("The PG root directory is $pg_root\n");
113 # need POST data from outside the system anyway!) 89 debug(("-" x 80) . "\n");
90
91 debug("The first thing we need to do is munge the path a little:\n");
92
93 my ($path) = $uri =~ m/$location(.*)/;
94 $path = "/" if $path eq ""; # no path at all
95
96 debug("We can't trust the path-info, so we make our own path.\n");
97 debug("path-info claims: $path_info\n");
98 debug("but it's really: $path\n");
99 debug("(if it's empty, we set it to \"/\".)\n");
100
101 $path =~ s|/+|/|g;
102 debug("...and here it is without repeated slashes: $path\n");
103
104 # lookbehind assertion for "not a slash"
105 # matches the boundary after the last char
106 $path =~ s|(?<=[^/])$|/|;
107 debug("...and here it is with a trailing slash: $path\n");
108
109 debug(("-" x 80) . "\n");
110
111 debug("Now we need to look at the path a little to figure out where we are\n");
112
113 debug("-------------------- call to WeBWorK::URLPath::newFromPath\n");
114 my $urlPath = WeBWorK::URLPath->newFromPath($path);
115 debug("-------------------- call to WeBWorK::URLPath::newFromPath\n");
116
117 unless ($urlPath) {
118 debug("This path is invalid... see you later!\n");
119 die "The path '$path' is not valid.\n";
120 }
121
122 my $displayModule = $urlPath->module;
123 my %displayArgs = $urlPath->args;
124
125 unless ($displayModule) {
126 debug("The display module is empty, so we can DECLINE here.\n");
127 die "No display module found for path '$path'.";
128 }
129
130 debug("The display module for this path is: $displayModule\n");
131 debug("...and here are the arguments we'll pass to it:\n");
132 foreach my $key (keys %displayArgs) {
133 debug("\t$key => $displayArgs{$key}\n");
134 }
135
136 my $selfPath = $urlPath->path;
137 my $parent = $urlPath->parent;
138 my $parentPath = $parent ? $parent->path : "<no parent>";
139
140 debug("Reconstructing the original path gets us: $selfPath\n");
141 debug("And we can generate the path to our parent, too: $parentPath\n");
142 debug("(We could also figure out who our children are, but we'd need to supply additional arguments.)\n");
143 debug(("-" x 80) . "\n");
144
145 debug("The URLPath looks good, we'll add it to the request.\n");
146 $r->urlpath($urlPath);
147
148 debug("Now we want to look at the parameters we got.\n");
149
150 debug("The raw params:\n");
151 foreach my $key ($r->param) {
152 debug("\t$key\n");
153 debug("\t\t$_\n") foreach $r->param($key);
154 }
155
156 #mungeParams($r);
157
158 debug("The munged params:\n");
159 foreach my $key ($r->param) {
160 debug("\t$key\n");
161 debug("\t\t$_\n") foreach $r->param($key);
162 }
163
164 debug(("-" x 80) . "\n");
165
166 debug("We need to get a course environment (with or without a courseID!)\n");
167 my $ce = eval { new WeBWorK::CourseEnvironment({
168 #webworkRoot => $r->dir_config("webwork_root"),
169 #webworkURLRoot => $location,
170 #pgRoot => $r->dir_config("pg_root"),
171 %SeedCE,
172 courseName => $displayArgs{courseID},
173 }) };
174 $@ and die "Failed to initialize course environment: $@\n";
175 debug("Here's the course environment: $ce\n");
176 $r->ce($ce);
177
178 my @uploads = $r->upload;
179 foreach my $u (@uploads) {
180 # make sure it's a "real" upload
181 next unless $u->filename;
182
183 # store the upload
184 my $upload = WeBWorK::Upload->store($u,
185 dir => $ce->{webworkDirs}->{uploadCache}
186 );
187
188 # store the upload ID and hash in the file upload field
189 my $id = $upload->id;
190 my $hash = $upload->hash;
191 $r->param($u->name => "$id $hash");
192 }
193
194 my ($db, $authz);
195
196 if ($displayArgs{courseID}) {
197 debug("We got a courseID from the URLPath, now we can do some stuff:\n");
198
199 unless (-e $ce->{courseDirs}->{root}) {
200 die "Course '$displayArgs{courseID}' not found: $!";
114 } 201 }
115 202
116 # Create the @components array, which contains the path specified in the URL 203 debug("...we can create a database object...\n");
117 my($junk, @components) = split "/", $path_info; 204 $db = new WeBWorK::DB($ce->{dbLayout});
118 my $webwork_root = $r->dir_config('webwork_root'); # From a PerlSetVar in httpd.conf 205 debug("(here's the DB handle: $db)\n");
119 my $pg_root = $r->dir_config('pg_root'); # From a PerlSetVar in httpd.conf 206 $r->db($db);
120 my $course = shift @components; 207
121 208 debug("Now we check the database...\n");
122=item Read the course environment 209 debug("(we can detect if a hash-style database from WW1 has not be converted properly.)\n");
123 210 my ($dbOK, @dbMessages) = $db->hashDatabaseOK(0); # 0 == don't fix
124C<WeBWorK::CourseEnvironment> is used to read the F<global.conf> configuration 211 if (not $dbOK) {
125file. If a course name was given in the request's URI, it is passed to 212 debug("hashDatabaseOK() returned $dbOK -- looks like trouble...\n");
126C<WeBWorK::CourseEnvironment>. In this case, the course-specific configuration 213 $displayModule = FIXDB_MODULE;
127file (usually F<course.conf>) is also read by C<WeBWorK::CourseEnvironment> at 214 debug("set displayModule to $displayModule\n");
128this point.
129
130See also L<WeBWorK::CourseEnvironment>.
131
132=cut
133
134 # Try to get the course environment.
135 my $ce = eval {WeBWorK::CourseEnvironment->new($webwork_root, $urlRoot, $pg_root, $course);};
136 if ($@) { # If there was an error getting the requested course
137 die "Failed to read course environment for $course: $@";
138 }
139
140=item If no course was given, go to the site home page
141
142If the URI did not include the name of a course, a redirection is issued to the
143site home page, given but the course environemnt variable
144C<$ce-E<gt>{webworkURLs}-E<gt>{home}>.
145
146=cut
147
148 # If no course was specified, redirect to the home URL
149 unless (defined $course) {
150 $r->header_out(Location => $ce->{webworkURLs}->{home});
151 return REDIRECT;
152 }
153
154=item If the given course does not exist, fail
155
156If the URI did include the name of a course, but the course directory was not
157found, an exception is thrown.
158
159=cut
160
161 # Freak out if the requested course doesn't exist. For now, this is just a
162 # check to see if the course directory exists.
163 my $courseDir = $ce->{webworkDirs}->{courses} . "/$course";
164 unless (-e $courseDir) {
165 die "Course directory for $course ($courseDir) not found. Perhaps the course does not exist?";
166 }
167
168=item Initialize the database system
169
170A C<WeBWorK::DB> object is created from the current course environment.
171
172See also L<WeBWorK::DB>.
173
174=cut
175
176 # Bring up a connection to the database (for Authen/Authz, and eventually
177 # to be passed to content generators, when we clean this file up).
178 my $db = WeBWorK::DB->new($ce);
179
180 ### Begin dispatching ###
181
182 #my $dispatchTimer = WeBWorK::Timing->new(__PACKAGE__."::dispatch");
183 #$dispatchTimer->start;
184
185 my $result;
186
187=item Check authentication
188
189Use C<WeBWorK::Authen> to verify that the remote user has authenticated.
190
191See also L<WeBWorK::Authen>.
192
193=cut
194
195 # WeBWorK::Authen::verify erases the passwd field and sets the key field
196 # if login is successful.
197 if (!WeBWorK::Authen->new($r, $ce, $db)->verify) {
198 $result = WeBWorK::ContentGenerator::Login->new($r, $ce, $db)->go;
199 } else { 215 } else {
200 216 debug("hashDatabaseOK() returned $dbOK -- leaving displayModule as-is\n");
201=item Determine if the user is allowed to set C<effectiveUser> 217 }
202 218
203Use C<WeBWorK::Authz> to determine if the user is allowed to set 219 debug("Create an authz object (Authen needs it to check login permission)...\n");
204C<effectiveUser>. If so, set it to the requested value (or set it to the real 220 $authz = new WeBWorK::Authz($r);
205user name if no value is supplied). If not, set it to the real user name. 221 debug("(here's the authz object: $authz)\n");
206 222 $r->authz($authz);
207See also L<WeBWorK::Authz>. 223
208 224 debug("...and now we can authenticate the remote user...\n");
209=cut 225 my $authen = new WeBWorK::Authen($r);
210 226 my $authenOK = $authen->verify;
211 # After we are authenticated, there are some things that need to be 227 if ($authenOK) {
212 # sorted out, Authorization-wize, before we start dispatching to individual
213 # content generators.
214 my $user = $r->param("user"); 228 my $userID = $r->param("user");
215 my $effectiveUser = $r->param("effectiveUser") || $user; 229 debug("Hi, $userID, glad you made it.\n");
216 my $su_authorized = WeBWorK::Authz->new($r, $ce, $db)->hasPermissions($user, "become_student", $effectiveUser);
217 $effectiveUser = $user unless $su_authorized;
218 $r->param("effectiveUser", $effectiveUser);
219
220=item Create and call the appropriate subclass of C<WeBWorK::ContentGenerator> based on the URI.
221
222The dispatcher logic currently looks like this:
223
224 FIXME: write this part
225 for now, consult the code
226
227=cut
228
229 my $arg = shift @components;
230 if (!defined $arg) { # We want the list of problem sets
231 $result = WeBWorK::ContentGenerator::ProblemSets->new($r, $ce, $db)->go;
232 } elsif ($arg eq "hardcopy") {
233 230
234 my $hardcopyArgument = shift @components; 231 # tell authorizer to cache this user's permission level
235 $hardcopyArgument = "" unless defined $hardcopyArgument; 232 $authz->setCachedUser($userID);
236 $WeBWorK::timer1 = WeBWorK::Timing->new("hardcopy: $hardcopyArgument") if $timingON == 1;
237 $WeBWorK::timer1->start if $timingON == 1;
238 233
239 my $result = WeBWorK::ContentGenerator::Hardcopy->new($r, $ce, $db)->go($hardcopyArgument); 234 debug("Now we deal with the effective user:\n");
240 $WeBWorK::timer1 ->stop if $timingON == 1; 235 my $eUserID = $r->param("effectiveUser") || $userID;
241 $WeBWorK::timer1 ->save if $timingON == 1; 236 debug("userID=$userID eUserID=$eUserID\n");
242 return $result; 237 # FIXME: hasPermissions does nothing with $eUserID, and lately we want it to
243 } elsif ($arg eq "instructor2") { 238 # only accept two arguments, so we're removing $eUserID from this call.
244 my $instructorArgument = shift @components; 239 #my $su_authorized = $authz->hasPermissions($userID, "become_student", $eUserID);
245 if (!defined $instructorArgument) { 240 my $su_authorized = $authz->hasPermissions($userID, "become_student");
246 $result = WeBWorK::ContentGenerator::Instructor::Index2->new($r, $ce, $db)->go; 241 if ($su_authorized) {
242 debug("Ok, looks like you're allowed to become $eUserID. Whoopie!\n");
243 } else {
244 debug("Uh oh, you're not allowed to become $eUserID. Nice try!\n");
245 $eUserID = $userID;
247 } 246 }
248 } elsif ($arg eq "instructor") { 247 $r->param("effectiveUser" => $eUserID);
249 my $instructorArgument = shift @components; 248 # if we're doing a proctored test, after the user has been authenticated
250 if (!defined $instructorArgument) { 249 # we need to also check on the proctor. note that in the gateway quiz
251 $WeBWorK::timer2 = WeBWorK::Timing->new("Instructor index $course:") if $timingON == 1; 250 # module we double check this, to be sure that someone isn't taking a
252 $WeBWorK::timer2->start if $timingON == 1; 251 # proctored quiz but calling the unproctored ContentGenerator
253 $result = WeBWorK::ContentGenerator::Instructor::Index->new($r, $ce, $db)->go; 252 my $urlProducedPath = $urlPath->path();
254 $WeBWorK::timer2->continue("Listing instructor page is done") if $timingON == 1;
255 $WeBWorK::timer2->stop if $timingON == 1;
256 $WeBWorK::timer2->save if $timingON == 1;
257 } elsif ($instructorArgument eq "scoring") {
258 $result = WeBWorK::ContentGenerator::Instructor::Scoring->new($r, $ce, $db)->go; #FIXME!!!!
259 } elsif ($instructorArgument eq "add_users") {
260 $result = WeBWorK::ContentGenerator::Instructor::AddUsers->new($r, $ce, $db)->go; #FIXME!!!!
261 } elsif ($instructorArgument eq "scoringDownload") {
262 $result = WeBWorK::ContentGenerator::Instructor::ScoringDownload->new($r, $ce, $db)->go;
263 } elsif ($instructorArgument eq "scoring_totals") {
264 $result = WeBWorK::ContentGenerator::Instructor::ScoringTotals->new($r, $ce, $db)->go;
265 } elsif ($instructorArgument eq "users") {
266 $result = WeBWorK::ContentGenerator::Instructor::UserList->new($r, $ce, $db)->go;
267 } elsif ($instructorArgument eq "sets") {
268 my $setID = shift @components;
269 if (defined $setID) {
270 my $setArg = shift @components;
271 if (!defined $setArg) {
272 $result = WeBWorK::ContentGenerator::Instructor::ProblemSetEditor->new($r, $ce, $db)->go($setID);
273 } elsif ($setArg eq "problems") {
274 $result = WeBWorK::ContentGenerator::Instructor::ProblemList->new($r, $ce, $db)->go($setID);
275 } elsif ($setArg eq "users") {
276 $result = WeBWorK::ContentGenerator::Instructor::Assigner->new($r, $ce, $db)->go($setID);
277 }
278 } else {
279 $WeBWorK::timer2 = WeBWorK::Timing->new("Problem Set List $course:") if $timingON == 1;
280 $WeBWorK::timer2->start if $timingON == 1;
281 $result = WeBWorK::ContentGenerator::Instructor::ProblemSetList->new($r, $ce, $db)->go;
282 $WeBWorK::timer2->continue("Problem Set List is done");
283 $WeBWorK::timer2->stop if $timingON == 1;
284 $WeBWorK::timer2->save if $timingON == 1;
285 253
254 if ( $urlProducedPath =~ /proctored_quiz_mode/i ) {
255 my $procAuthOK = $authen->verifyProctor();
256
257 if ( $procAuthOK ) {
258 my $proctorUserID = $r->param("proctor_user");
259 my $proctor_authorized =
260 $authz->hasPermissions($proctorUserID,
261 "proctor_quiz", $userID);
262 if ( ! $proctor_authorized ) {
263 $r->notes("authen_error",
264 "Proctor $proctorUserID is not " .
265 "authorized to proctor tests in " .
266 "this course.");
267 $displayModule = PROCTOR_AUTHEN_MODULE;
286 } 268 }
287 } elsif ($instructorArgument eq "pgProblemEditor") { 269
288 $result = WeBWorK::ContentGenerator::Instructor::PGProblemEditor->new($r, $ce, $db)->go(@components); 270 } else {
289 } elsif ($instructorArgument eq "send_mail") { 271 $displayModule = PROCTOR_AUTHEN_MODULE;
290 $result = WeBWorK::ContentGenerator::Instructor::SendMail->new($r, $ce, $db)->go(@components); 272 }
291 } elsif ($instructorArgument eq "show_answers") {
292 $result = WeBWorK::ContentGenerator::Instructor::ShowAnswers->new($r, $ce, $db)->go(@components);
293 } elsif ($instructorArgument eq "stats") {
294 $result = WeBWorK::ContentGenerator::Instructor::Stats->new($r, $ce, $db)->go(@components);
295 } 273 }
296 } elsif ($arg eq "options") {
297 $result = WeBWorK::ContentGenerator::Options->new($r, $ce, $db)->go;
298 } elsif ($arg eq "feedback") {
299 $result = WeBWorK::ContentGenerator::Feedback->new($r, $ce, $db)->go;
300 } elsif ($arg eq "logout") {
301 $result = WeBWorK::ContentGenerator::Logout->new($r, $ce, $db)->go;
302 } elsif ($arg eq "test") {
303 $result = WeBWorK::ContentGenerator::Test->new($r, $ce, $db)->go;
304 } elsif ($arg eq "quiz_mode" ) {
305 # Gateway quiz capability -- very similar to problem set (initially)
306 $result = WeBWorK::ContentGenerator::GatewayQuiz->new($r, $ce, $db)->go(@components);
307 } else { # We've got the name of a problem set.
308 my $problem_set = $arg;
309 my $ps_arg = shift @components;
310 274
311 if (!defined $ps_arg) { 275 } else {
312 # list the problems in the problem set 276 debug("Bad news: authentication failed!\n");
313 $WeBWorK::timer0 = WeBWorK::Timing->new("Problem $course:$problem_set") if $timingON == 1; 277 $displayModule = AUTHEN_MODULE;
314 $WeBWorK::timer0->start if $timingON == 1; 278 debug("set displayModule to $displayModule\n");
315 $result = WeBWorK::ContentGenerator::ProblemSet->new($r, $ce, $db)->go($problem_set); 279 }
316 $WeBWorK::timer0->continue("problem set listing is done") if $timingON == 1; 280 }
317 $WeBWorK::timer0->stop if $timingON == 1; 281
318 $WeBWorK::timer0->save if $timingON == 1; 282 ## if a course ID was given in the URL and resulted in an error (as stored in $!)
283 ## it probably means that the course does not exist or was misspelled
284 #if ($displayArgs{courseID} and $ce->{'!'}) {
285 # debug("Something was wrong with the courseID: \n");
286 # debug("\t\t" . $ce->{'!'} . "\n");
287 # debug("Time to bail!\n");
288 # die "An error occured while accessing '$displayArgs{courseID}': '", $ce->{'!'}, "'.\n";
289 #}
290
291 # store the time before we invoke the content generator
292 my $cg_start = time; # this is Time::HiRes's time, which gives floating point values
293
294 debug(("-" x 80) . "\n");
295 debug("Finally, we'll load the display module...\n");
296
297 runtime_use($displayModule);
298
299 debug("...instantiate it...\n");
300
301 my $instance = $displayModule->new($r);
302
303 debug("...and call it:\n");
304 debug("-------------------- call to ${displayModule}::go\n");
305
306 my $result = $instance->go();
307
308 debug("-------------------- call to ${displayModule}::go\n");
309
310 my $cg_end = time;
311 my $cg_duration = $cg_end - $cg_start;
312 writeTimingLogEntry($ce, "[".$r->uri."]", sprintf("runTime = %.3f sec", $cg_duration)." ".$ce->{dbLayoutName}, "");
313
314 debug("returning result: " . (defined $result ? $result : "UNDEF") . "\n");
315
316 return $result;
317}
318
319sub mungeParams {
320 my ($r) = @_;
321
322 my @paramQueue;
323
324 # remove all the params from the request, and store them in the param queue
325 foreach my $key ($r->param) {
326 push @paramQueue, [ $key => [ $r->param($key) ] ];
327 $r->parms->unset($key)
328 }
329
330 # exhaust the param queue, decoding encoded params
331 while (@paramQueue) {
332 my ($key, $values) = @{ shift @paramQueue };
333
334 if ($key =~ m/\,/) {
335 # we have multiple params encoded in a single param
336 # split them up and add them to the end of the queue
337 push @paramQueue, map { [ $_, $values ] } split m/\,/, $key;
338 } elsif ($key =~ m/\:/) {
339 # we have a whole param encoded in a key
340 # split it up and add it to the end of the queue
341 my ($newKey, $newValue) = split m/\:/, $key;
342 push @paramQueue, [ $newKey, [ $newValue ] ];
343 } else {
344 # this is a "normal" param
345 # add it to the param list
346 if (defined $r->param($key)) {
347 # the param already exists -- append the values we have
348 $r->param($key => [ $r->param($key), @$values ]);
319 } else { 349 } else {
320 # We've got the name of a problem 350 # the param doesn't exist -- create it with the values we have
321 my $problem = $ps_arg; 351 $r->param($key => $values);
322
323 $WeBWorK::timer0 = WeBWorK::Timing->new("Problem $course:$problem_set/$problem") if $timingON == 1;
324 $WeBWorK::timer0->start if $timingON == 1;
325# my $pid = fork();
326# if ($pid) {
327# wait;
328# } else {
329 my $result = WeBWorK::ContentGenerator::Problem->new($r, $ce, $db)->go($problem_set, $problem);
330# $WeBWorK::timer0->continue("Exiting child process");
331# #$WeBWorK::timer0->stop;
332# #$WeBWorK::timer0->save;
333# eval{ APACHE::exit(0);} || warn "Error in leaving child |$@|";
334# # We REALLY REALLY want this grandchild to exit. But not the child. How to do this
335# # cleanly???? FIXME
336# }
337 $WeBWorK::timer0->continue("Problem done)") if $timingON == 1;
338 $WeBWorK::timer0->stop if $timingON == 1;
339 $WeBWorK::timer0->save if $timingON == 1;
340 return $result;
341
342
343 } 352 }
344 } 353 }
345 } 354 }
346 355}
347 #$dispatchTimer->stop;
348 356
349=item Return the result of calling the content generator
350 357
351The return value of the content generator's C<&go> function is returned. 358=head1 AUTHOR
359
360Written by Dennis Lambe, malsyned at math.rochester.edu. Modified by Sam
361Hathaway, sh002i at math.rochester.edu.
352 362
353=cut 363=cut
354
355 return $result;
356}
357
358=back
359
360=head1 AUTHOR
361
362Written by Dennis Lambe, malsyned at math.rochester.edu.
363
364=cut
365 364
3661; 3651;

Legend:
Removed from v.1612  
changed lines
  Added in v.3598

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9