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

View of /trunk/webwork2/lib/WeBWorK.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2437 - (download) (as text) (annotate)
Sat Jul 3 17:13:29 2004 UTC (8 years, 11 months ago) by sh002i
File size: 10346 byte(s)
changed the way invalid courses are detected. $ce->{'!'} is no longer
used. also, if CE initialization throws an exception, it is caught and
labeled as a problem with CE init.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork-modperl/lib/WeBWorK.pm,v 1.61 2004/07/01 23:35:22 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.
   15 ################################################################################
   16 
   17 package WeBWorK;
   18 
   19 =head1 NAME
   20 
   21 WeBWorK - Dispatch requests to the appropriate content generator.
   22 
   23 =head1 SYNOPSIS
   24 
   25  my $r = Apache->request;
   26  my $result = eval { WeBWorK::dispatch($r) };
   27  die "something bad happened: $@" if $@;
   28 
   29 =head1 DESCRIPTION
   30 
   31 C<WeBWorK> is the dispatcher for the WeBWorK system. Given an Apache request
   32 object, it performs authentication and determines which subclass of
   33 C<WeBWorK::ContentGenerator> to call.
   34 
   35 =cut
   36 
   37 BEGIN { $main::VERSION = "2.0"; }
   38 
   39 use strict;
   40 use warnings;
   41 use Apache::Constants qw(:common REDIRECT DONE);
   42 
   43 # load WeBWorK::Constants before anything else
   44 # this sets package variables in several packages
   45 use WeBWorK::Constants;
   46 
   47 # the rest of these are modules that are acutally used by this one
   48 use WeBWorK::Authen;
   49 use WeBWorK::Authz;
   50 use WeBWorK::CourseEnvironment;
   51 use WeBWorK::DB;
   52 use WeBWorK::Debug;
   53 use WeBWorK::Request;
   54 use WeBWorK::Timing;
   55 use WeBWorK::Upload;
   56 use WeBWorK::URLPath;
   57 use WeBWorK::Utils qw(runtime_use);
   58 
   59 use constant AUTHEN_MODULE => "WeBWorK::ContentGenerator::Login";
   60 use constant FIXDB_MODULE => "WeBWorK::ContentGenerator::FixDB";
   61 
   62 sub dispatch($) {
   63   my ($apache) = @_;
   64   my $r = new WeBWorK::Request $apache;
   65 
   66   my $method = $r->method;
   67   my $location = $r->location;
   68   my $uri = $r->uri;
   69   my $path_info = $r->path_info | "";
   70   my $args = $r->args || "";
   71   my $webwork_root = $r->dir_config("webwork_root");
   72   my $pg_root = $r->dir_config("pg_root");
   73 
   74   debug("Hi, I'm the new dispatcher!\n");
   75   debug(("-" x 80) . "\n");
   76 
   77   debug("Okay, I got some basic information:\n");
   78   debug("The apache location is $location\n");
   79   debug("The request method is $method\n");
   80   debug("The URI is $uri\n");
   81   debug("The path-info is $path_info\n");
   82   debug("The argument string is $args\n");
   83   debug("The WeBWorK root directory is $webwork_root\n");
   84   debug("The PG root directory is $pg_root\n");
   85   debug(("-" x 80) . "\n");
   86 
   87   debug("The first thing we need to do is munge the path a little:\n");
   88 
   89   my ($path) = $uri =~ m/$location(.*)/;
   90   $path = "/" if $path eq ""; # no path at all
   91 
   92   debug("We can't trust the path-info, so we make our own path.\n");
   93   debug("path-info claims: $path_info\n");
   94   debug("but it's really: $path\n");
   95   debug("(if it's empty, we set it to \"/\".)\n");
   96 
   97   $path =~ s|/+|/|g;
   98   debug("...and here it is without repeated slashes: $path\n");
   99 
  100   # lookbehind assertion for "not a slash"
  101   # matches the boundary after the last char
  102   $path =~ s|(?<=[^/])$|/|;
  103   debug("...and here it is with a trailing slash: $path\n");
  104 
  105   debug(("-" x 80) . "\n");
  106 
  107   debug("Now we need to look at the path a little to figure out where we are\n");
  108 
  109   debug("-------------------- call to WeBWorK::URLPath::newFromPath\n");
  110   my $urlPath = WeBWorK::URLPath->newFromPath($path);
  111   debug("-------------------- call to WeBWorK::URLPath::newFromPath\n");
  112 
  113   unless ($urlPath) {
  114     debug("This path is invalid... see you later!\n");
  115     die "The path '$path' is not valid.\n";
  116   }
  117 
  118   my $displayModule = $urlPath->module;
  119   my %displayArgs = $urlPath->args;
  120 
  121   debug("The display module for this path is: $displayModule\n");
  122   debug("...and here are the arguments we'll pass to it:\n");
  123   foreach my $key (keys %displayArgs) {
  124     debug("\t$key => $displayArgs{$key}\n");
  125   }
  126 
  127   unless ($displayModule) {
  128     debug("The display module is empty, so we can DECLINE here.\n");
  129     die "No display module found for this path.";
  130   }
  131 
  132   my $selfPath = $urlPath->path;
  133   my $parent = $urlPath->parent;
  134   my $parentPath = $parent ? $parent->path : "<no parent>";
  135 
  136   debug("Reconstructing the original path gets us: $selfPath\n");
  137   debug("And we can generate the path to our parent, too: $parentPath\n");
  138   debug("(We could also figure out who our children are, but we'd need to supply additional arguments.)\n");
  139   debug(("-" x 80) . "\n");
  140 
  141   debug("The URLPath looks good, we'll add it to the request.\n");
  142   $r->urlpath($urlPath);
  143 
  144   debug("Now we want to look at the parameters we got.\n");
  145 
  146   debug("The raw params:\n");
  147   foreach my $key ($r->param) {
  148     debug("\t$key\n");
  149     debug("\t\t$_\n") foreach $r->param($key);
  150   }
  151 
  152   #mungeParams($r);
  153 
  154   debug("The munged params:\n");
  155   foreach my $key ($r->param) {
  156     debug("\t$key\n");
  157     debug("\t\t$_\n") foreach $r->param($key);
  158   }
  159 
  160   debug(("-" x 80) . "\n");
  161 
  162   # create a package-global timing object
  163   # FIXME: this is used by other modules!
  164   # FIXME: this is not thread-safe!
  165   my $label = defined $displayArgs{courseID} ? $displayArgs{courseID} : "ROOT";
  166   $WeBWorK::timer = WeBWorK::Timing->new($label);
  167   $WeBWorK::timer->start;
  168 
  169   debug("We need to get a course environment (with or without a courseID!)\n");
  170   my $ce = eval { new WeBWorK::CourseEnvironment($webwork_root, $location, $pg_root, $displayArgs{courseID}) };
  171   $@ and die "Failed to initialize course environment: $@\n";
  172   debug("Here's the course environment: $ce\n");
  173   $r->ce($ce);
  174 
  175   my @uploads = $r->upload;
  176   foreach my $u (@uploads) {
  177     # make sure it's a "real" upload
  178     next unless $u->filename;
  179 
  180     # store the upload
  181     my $upload = WeBWorK::Upload->store($u,
  182       dir => $ce->{webworkDirs}->{uploadCache}
  183     );
  184 
  185     # store the upload ID and hash in the file upload field
  186     my $id = $upload->id;
  187     my $hash = $upload->hash;
  188     $r->param($u->name => "$id $hash");
  189   }
  190 
  191   my ($db, $authz);
  192 
  193   if ($displayArgs{courseID}) {
  194     debug("We got a courseID from the URLPath, now we can do some stuff:\n");
  195 
  196     unless (-e $ce->{courseDirs}->{root}) {
  197       die "Course '$displayArgs{courseID}' not found: $!";
  198     }
  199 
  200     debug("...we can create a database object...\n");
  201     $db = new WeBWorK::DB($ce->{dbLayout});
  202     debug("(here's the DB handle: $db)\n");
  203     $r->db($db);
  204 
  205     debug("Now we check the database...\n");
  206     debug("(we can detect if a hash-style database from WW1 has not be converted properly.)\n");
  207     my ($dbOK, @dbMessages) = $db->hashDatabaseOK(0); # 0 == don't fix
  208     if (not $dbOK) {
  209       debug("hashDatabaseOK() returned $dbOK -- looks like trouble...\n");
  210       $displayModule = FIXDB_MODULE;
  211       debug("set displayModule to $displayModule\n");
  212     } else {
  213       debug("hashDatabaseOK() returned $dbOK -- leaving displayModule as-is\n");
  214     }
  215 
  216     debug("...and now we can authenticate the remote user...\n");
  217     my $authen = new WeBWorK::Authen($r);
  218     my $authenOK = $authen->verify;
  219     if ($authenOK) {
  220       debug("Hi, ", $r->param("user"), ", glad you made it.\n");
  221 
  222       debug("Authentication succeeded, so it makes sense to create an authz object...\n");
  223       $authz = new WeBWorK::Authz($r, $ce, $db);
  224       debug("(here's the authz object: $authz)\n");
  225       $r->authz($authz);
  226 
  227       debug("Now we deal with the effective user:\n");
  228       my $userID = $r->param("user");
  229       my $eUserID = $r->param("effectiveUser") || $userID;
  230       debug("userID=$userID eUserID=$eUserID\n");
  231       my $su_authorized = $authz->hasPermissions($userID, "become_student", $eUserID);
  232       if ($su_authorized) {
  233         debug("Ok, looks like you're allowed to become $eUserID. Whoopie!\n");
  234       } else {
  235         debug("Uh oh, you're not allowed to become $eUserID. Nice try!\n");
  236         $eUserID = $userID;
  237       }
  238       $r->param("effectiveUser" => $eUserID);
  239     } else {
  240       debug("Bad news: authentication failed!\n");
  241       $displayModule = AUTHEN_MODULE;
  242       debug("set displayModule to $displayModule\n");
  243     }
  244   }
  245 
  246   ## if a course ID was given in the URL and resulted in an error (as stored in $!)
  247   ## it probably means that the course does not exist or was misspelled
  248   #if ($displayArgs{courseID} and $ce->{'!'}) {
  249   # debug("Something was wrong with the courseID: \n");
  250   # debug("\t\t" . $ce->{'!'} . "\n");
  251   # debug("Time to bail!\n");
  252   # die "An error occured while accessing '$displayArgs{courseID}': '", $ce->{'!'}, "'.\n";
  253   #}
  254 
  255   debug(("-" x 80) . "\n");
  256   debug("Finally, we'll load the display module...\n");
  257 
  258   runtime_use($displayModule);
  259 
  260   debug("...instantiate it...\n");
  261 
  262   my $instance = $displayModule->new($r);
  263 
  264   debug("...and call it:\n");
  265   debug("-------------------- call to ${displayModule}::go\n");
  266 
  267   my $result = $instance->go();
  268 
  269   debug("-------------------- call to ${displayModule}::go\n");
  270 
  271   debug("returning result: " . (defined $result ? $result : "UNDEF") . "\n");
  272 
  273   $WeBWorK::timer->save();
  274 
  275   return $result;
  276 
  277 }
  278 
  279 sub mungeParams {
  280   my ($r) = @_;
  281 
  282   my @paramQueue;
  283 
  284   # remove all the params from the request, and store them in the param queue
  285   foreach my $key ($r->param) {
  286     push @paramQueue, [ $key => [ $r->param($key) ] ];
  287     $r->parms->unset($key)
  288   }
  289 
  290   # exhaust the param queue, decoding encoded params
  291   while (@paramQueue) {
  292     my ($key, $values) = @{ shift @paramQueue };
  293 
  294     if ($key =~ m/\,/) {
  295       # we have multiple params encoded in a single param
  296       # split them up and add them to the end of the queue
  297       push @paramQueue, map { [ $_, $values ] } split m/\,/, $key;
  298     } elsif ($key =~ m/\:/) {
  299       # we have a whole param encoded in a key
  300       # split it up and add it to the end of the queue
  301       my ($newKey, $newValue) = split m/\:/, $key;
  302       push @paramQueue, [ $newKey, [ $newValue ] ];
  303     } else {
  304       # this is a "normal" param
  305       # add it to the param list
  306       if (defined $r->param($key)) {
  307         # the param already exists -- append the values we have
  308         $r->param($key => [ $r->param($key), @$values ]);
  309       } else {
  310         # the param doesn't exist -- create it with the values we have
  311         $r->param($key => $values);
  312       }
  313     }
  314   }
  315 }
  316 
  317 
  318 =head1 AUTHOR
  319 
  320 Written by Dennis Lambe, malsyned at math.rochester.edu. Modified by Sam
  321 Hathaway, sh002i at math.rochester.edu.
  322 
  323 =cut
  324 
  325 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9