From d9f3aca29b1a5dad715038baf114d788638b96a7 Mon Sep 17 00:00:00 2001 From: apizer Date: Fri, 12 Oct 2012 15:18:21 -0500 Subject: [PATCH 01/19] Move course tmp files from the course directory to WeBWorK's tmp directory. Changed the default location of all WeBWorK tmp files to .../webwork2/htdocs/tmp. We only had to change where course tmp files are put. Thhey now go to .../webwork2/htdocs/tmp/course_name/ So .../webwork2/htdocs/tmp is set up in exactly the same way we suggest people set up /var/www/wwtmp. There is no real reason now for people to have to set up /var/www/wwtmp. --- conf/defaults.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/defaults.config b/conf/defaults.config index 8529016d28..50e174eb70 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -261,8 +261,8 @@ $courseDirs{html_images} = "$courseDirs{html}/images"; # Location of web-accessible, course-specific temporary files, like static and # dynamically-generated PG graphics. -$courseDirs{html_temp} = "$courseDirs{html}/tmp"; -$courseURLs{html_temp} = "$courseURLs{html}/tmp"; +$courseDirs{html_temp} = "$webworkDirs{htdocs_temp}/$courseName"; +$courseURLs{html_temp} = "$webworkURLs{htdocs_temp}/$courseName"; # Location of course-specific logs, like the transaction log. $courseDirs{logs} = "$courseDirs{root}/logs"; From f38350c2a62f92144c02be813183e400aefd6440 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Wed, 24 Oct 2012 15:33:07 -0500 Subject: [PATCH 02/19] removed errant submodule references --- htdocs/themes/math2/codemirror2 | 1 - htdocs/themes/ubc/codemirror2 | 1 - 2 files changed, 2 deletions(-) delete mode 160000 htdocs/themes/math2/codemirror2 delete mode 160000 htdocs/themes/ubc/codemirror2 diff --git a/htdocs/themes/math2/codemirror2 b/htdocs/themes/math2/codemirror2 deleted file mode 160000 index 73edae2aaa..0000000000 --- a/htdocs/themes/math2/codemirror2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73edae2aaabf867f45119804b7816a339762414e diff --git a/htdocs/themes/ubc/codemirror2 b/htdocs/themes/ubc/codemirror2 deleted file mode 160000 index 73edae2aaa..0000000000 --- a/htdocs/themes/ubc/codemirror2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73edae2aaabf867f45119804b7816a339762414e From 198edbf52e140e3f6f37c1e381a1753222d01059 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Wed, 24 Oct 2012 16:05:59 -0500 Subject: [PATCH 03/19] Removed errant submodule references --- htdocs/themes/math2/codemirror2 | 1 - htdocs/themes/ubc/codemirror2 | 1 - 2 files changed, 2 deletions(-) delete mode 160000 htdocs/themes/math2/codemirror2 delete mode 160000 htdocs/themes/ubc/codemirror2 diff --git a/htdocs/themes/math2/codemirror2 b/htdocs/themes/math2/codemirror2 deleted file mode 160000 index 73edae2aaa..0000000000 --- a/htdocs/themes/math2/codemirror2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73edae2aaabf867f45119804b7816a339762414e diff --git a/htdocs/themes/ubc/codemirror2 b/htdocs/themes/ubc/codemirror2 deleted file mode 160000 index 73edae2aaa..0000000000 --- a/htdocs/themes/ubc/codemirror2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73edae2aaabf867f45119804b7816a339762414e From c1ceb3755941e70af505477469eeffbc39a7510c Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Fri, 12 Oct 2012 13:05:58 -0500 Subject: [PATCH 04/19] Fixed OPL-update to use libraryVersion from \$ce rather than a VERSION file Changed cherry-picked from webwork2/master 4663e15316233ec81d56ff75ca7113d5ded9ca1b --- bin/OPL-update | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/bin/OPL-update b/bin/OPL-update index d8a0aedb01..ea022d4d9a 100755 --- a/bin/OPL-update +++ b/bin/OPL-update @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # This is the script formerly known as loadDB2, and then known as NPL-update. @@ -84,6 +84,7 @@ my $dbh = DBI->connect( my $passwd = $ce->{database_password}; my $user = $ce->{database_username}; my $libraryRoot = $ce->{problemLibrary}->{root}; +my $libraryVersion = $ce->{problemLibrary}->{version}; my $verbose = 0; my $cnt2 = 0; @@ -98,21 +99,14 @@ sub dbug { ##Figure out which set of tables to use my %tables; -if( -e "$libraryRoot/VERSION") { - require("$libraryRoot/VERSION"); - if($OPL_VERSION eq '2.5.0') { +if($libraryVersion eq '2.5') { %tables = %OPLtables; my $lib = 'OPL'; - print "Got OPLtables!\n"; - } else { - %tables = %NPLtables; - my $lib = 'NPL'; - print "Got NPLtables! (1)\n"; - } + warn "Library version is $libraryVersion; using OPLtables!\n"; } else { %tables = %NPLtables; my $lib = 'NPL'; - print "Got NPLtables! (2)\n"; + print "Library version is $libraryVersion; NPLtables! \n"; } @create_tables = ( From 0d0535ce0c2aff7abcc5fafcd9112f7374e0c850 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Wed, 24 Oct 2012 17:06:49 -0500 Subject: [PATCH 05/19] CONFIG-README directions out of date and superceeded by directions in README" --- conf/CONFIG-README | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 conf/CONFIG-README diff --git a/conf/CONFIG-README b/conf/CONFIG-README deleted file mode 100644 index 47258870c7..0000000000 --- a/conf/CONFIG-README +++ /dev/null @@ -1,37 +0,0 @@ - -FIRST TIME RECONFIGURATION - -RENAME global.conf to global.save in order to make sure that the global.conf.dist is read. -Otherwise the global.conf file will be read instead of global.conf.dist. prelocal.conf and postlocal.conf -and the behavior will be the same as with the old system. - -COPY prelocal.conf.dist to prelocal.conf. -COPY postlocal.conf.dist to postlocal.conf. - -MODIFY prelocal.conf using the data from your global.conf file. -In particular you will need to fill in the server name, the -password for the database and any modifications you have made as to the -location of the temporary files directory. Notice that the location of the temporary files directory -is used to define several other related subdirectories, so this modification needs to be made -in prelocal.conf BEFORE the standard global.conf.dist file is read. - - -INSPECT and possibly modify postlocal.conf to add any further local modifications that you had -made to your global.conf file. - -Use the prelocal.conf and postlocal.conf files to make modifications. - -The prelocal.conf file is read before the global.conf.dist file is processed. Non-local variables in this file -are then available for use in global.conf.dist. - -The postlocal.conf file is read after the global.conf.dist file is processed and will overright configurations in global.conf.dist - -This new configuration system should greatly simplify the process of -updating webwork2 since it is less likely -that one will need to modify the config files when upgrading. Default configurations or permissions for -new features will be defined in global.conf.dist and will allow automatic upgrades. - -Overrides for these new features can be added later to postlocal.conf - - - From c6a5871db0ec8883fa75e6eed1b0b6a90422c42e Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Sun, 4 Nov 2012 12:06:15 -0600 Subject: [PATCH 06/19] Added wwapache2ctl and webwork2.komodoproject to .gitignore (the last is a project file generated by an IDE I'm trying out). --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 50679cec15..d384242114 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ logs/* conf/*.conf conf/*.apache2-config htdocs/site_info.txt +bin/wwapache2ctl +webwork2.komodoproject #courses.dist/* From 1051ffe217297daf4651d2a178c864981b326510 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Sun, 4 Nov 2012 12:13:16 -0600 Subject: [PATCH 07/19] Sometimes users change user_id's. Given a course_id, an existing user_id in that course, and a different user_id, this script will (a) create a user for the new user_id if the account doesn't exist and (b) will also copy all existing data in the database associated with the old user_id to the new user_id. TODO: Currently copies all user set and problem data, but does not yet copy achievment data. We also want it to modify answer_log data so that the new user_id gets the same past answers. --- bin/change_user_id | 107 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 bin/change_user_id diff --git a/bin/change_user_id b/bin/change_user_id new file mode 100644 index 0000000000..7bbd6c1ccf --- /dev/null +++ b/bin/change_user_id @@ -0,0 +1,107 @@ +#!/usr/bin/env perl +# +#Sometimes a webwork user id changes. This script transfers the webwork data for the old user_id to the new user_id +# Update database tables +#user +#permission +#password +#key +#set_user +#problem_user +#set_locations_user +#global_achievement_user +#achievement_user +# +# Update answer_log + +use strict; +use warnings; + +BEGIN { + die "WEBWORK_ROOT not found in environment.\n" + unless exists $ENV{WEBWORK_ROOT}; +} + +use lib "$ENV{WEBWORK_ROOT}/lib"; +use WeBWorK::CourseEnvironment; +use WeBWorK::DB; +use WeBWorK::Utils qw(runtime_use readFile cryptPassword); +use Data::Dumper; + +if((scalar(@ARGV) != 3)) { + print "\nSyntax is: change_user_id course_id old_user_id new_user_id"; + print "\n (e.g. newpassword MAT_123 jjones jsmith\n\n"; + exit(); +} + +my $courseID = shift; +my $old_user_id = shift; +my $new_user_id = shift; + +my $ce = WeBWorK::CourseEnvironment->new({ + webwork_dir => $ENV{WEBWORK_ROOT}, + courseName => $courseID +}); + +my $db = new WeBWorK::DB($ce->{dbLayout}); +die "Error: $old_user_id does not exist!" unless $db->existsUser($old_user_id); + +unless($db->existsUser($new_user_id)) { + my $user = $db->getUser($old_user_id); + $user->{user_id}=$new_user_id; + $user->{comment} = $user->{comment}."Record created from $old_user_id record"; + $db->addUser($user); +} + +unless($db->existsPassword($new_user_id)) { + my $password = $db->getPassword($old_user_id); + $password->{user_id} = $new_user_id; + $db->addPassword($password); +} + +unless($db->existsPermissionLevel($new_user_id)) { + my $permission = $db->getPermissionLevel($old_user_id); + $permission->{user_id} = $new_user_id; + $db->addPermissionLevel($permission); +} + + +my @old_user_sets = $db->listUserSets($old_user_id); +foreach(@old_user_sets) { + my $set_id = $_; + my $new_set = $db->newUserSet; + $new_set->user_id($new_user_id); + $new_set->set_id($set_id); + eval{$db->addUserSet($new_set)}; + my $old_set = $db->getUserSet($old_user_id,$set_id); + foreach(keys %$old_set) { + next if /user_id|set_id/; + $new_set->$_($old_set->$_); + } + + $db->putUserSet($new_set) unless $db->existsUserSet($new_user_id,$set_id); + my @global_problems = grep { defined $_} $db->getAllGlobalProblems($set_id); + foreach(@global_problems) { + if($db->existsUserProblem($old_user_id,$set_id,$_->{problem_id})) { + my $old_user_problem = $db->getUserProblem($old_user_id,$set_id,$_->{problem_id}); + my $new_user_problem = $db->newUserProblem; + $new_user_problem->user_id($new_user_id); + $new_user_problem->set_id($set_id); + $new_user_problem->problem_id($_->{problem_id}); + $db->addUserProblem($new_user_problem) unless $db->existsUserProblem($new_user_id,$set_id,$_->{problem_id}); + foreach(keys %$old_user_problem) { + next if /(user_id|set_id|problem_id)/; + $new_user_problem->$_($old_user_problem->$_); + } + $db->putUserProblem($new_user_problem); + } + } +} + +my $answer_log = $ce->{courseFiles}->{logs}->{answer_log}; +open(my $fh,">>",$answer_log); +foreach(<$fh>) { + s/$// +} + + From d63615088c284e7c11301d137b4ba7afda36d677 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 4 Nov 2012 14:48:20 -0500 Subject: [PATCH 08/19] Add a cleanup routine to PG so that MathObjects that are part of the output or answer checkers are freed (in order to prevent errors about missing packages). --- lib/WeBWorK.pm | 5 ----- lib/WeBWorK/ContentGenerator/Problem.pm | 7 +++++++ lib/WeBWorK/PG.pm | 13 +++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/WeBWorK.pm b/lib/WeBWorK.pm index d7fc724447..759b8e540e 100644 --- a/lib/WeBWorK.pm +++ b/lib/WeBWorK.pm @@ -377,11 +377,6 @@ sub dispatch($) { writeTimingLogEntry($ce, "[".$r->uri."]", sprintf("runTime = %.3f sec", $cg_duration)." ".$ce->{dbLayoutName}, ""); debug("returning result: " . (defined $result ? $result : "UNDEF") . "\n"); - #@LimitedPolynomial::BOP::ISA; #FIXME this is needed to zero out - #@LimitedPolynomial::UOP::ISA; - #\@LimitedPolynomial::BOP::ISA and prevent error messages of the form - #[Sat May 15 14:23:08 2010] [warn] [client 127.0.0.1] [/webwork2/gage_course/test_set/6/] - #Can't locate package LimitedPolynomial::BOP for @LimitedPolynomial::BOP::add::ISA at /opt/webwork/webwork2/lib/Apache/WeBWorK.pm line 115., referer: http://localhost/webwork2/gage_course/test_set/6/ no one knows why return $result; } diff --git a/lib/WeBWorK/ContentGenerator/Problem.pm b/lib/WeBWorK/ContentGenerator/Problem.pm index cefd5ca099..4e541a6598 100644 --- a/lib/WeBWorK/ContentGenerator/Problem.pm +++ b/lib/WeBWorK/ContentGenerator/Problem.pm @@ -472,6 +472,13 @@ sub previewCorrectAnswer { # Template escape implementations ################################################################################ +sub content { + my $self = shift; + my $result = $self->SUPER::content(@_); + $self->{pg}->free if $self->{pg}; # be sure to clean up PG environment when the page is done + return $result; +} + sub pre_header_initialize { my ($self) = @_; my $r = $self->r; diff --git a/lib/WeBWorK/PG.pm b/lib/WeBWorK/PG.pm index dffa5107c1..651518ffe2 100644 --- a/lib/WeBWorK/PG.pm +++ b/lib/WeBWorK/PG.pm @@ -53,6 +53,19 @@ sub new { return $renderer->new(@_); } +sub free { + my $self = shift; + # + # If certain MathObjects (e.g. LimitedPolynomials) are left in the PG structure, then + # freeing them later can cause "Can't locate package ..." errors in the log during + # perl garbage collection. So free them here. + # + $self->{pgcore}{OUTPUT_ARRAY} = []; + $self->{answers} = {}; + undef $self->{translator}; + foreach (keys %{$self->{pgcore}{PG_ANSWERS_HASH}}) {undef $self->{pgcore}{PG_ANSWERS_HASH}{$_}} +} + sub defineProblemEnvir { my ( $self, From 26d297985aa745398210a4dd51fc2ca394bfd26f Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Tue, 6 Nov 2012 09:07:25 -0600 Subject: [PATCH 09/19] I think having the shebang line '/usr/bin/env perl' is more portable than /usr/bin/perl. It works on all *nix's and also allows for the script to work unmodified when a local administrator changes the perl path --- bin/check_modules.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/check_modules.pl b/bin/check_modules.pl index fcca289b6b..d0fd873afd 100755 --- a/bin/check_modules.pl +++ b/bin/check_modules.pl @@ -1,5 +1,5 @@ -#!/usr/bin/perl - +#!/usr/bin/env perl +# use strict; use warnings; From e96d5a50d84774170b6018475d28b6aff4d49823 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Tue, 6 Nov 2012 11:02:53 -0600 Subject: [PATCH 10/19] Added code to back up existing answer_log and then replace old user_id with new user_id --- bin/change_user_id | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) mode change 100644 => 100755 bin/change_user_id diff --git a/bin/change_user_id b/bin/change_user_id old mode 100644 new mode 100755 index 7bbd6c1ccf..3cd0bde055 --- a/bin/change_user_id +++ b/bin/change_user_id @@ -16,6 +16,8 @@ use strict; use warnings; +use File::Copy; +use File::Basename; BEGIN { die "WEBWORK_ROOT not found in environment.\n" @@ -99,9 +101,11 @@ foreach(@old_user_sets) { } my $answer_log = $ce->{courseFiles}->{logs}->{answer_log}; -open(my $fh,">>",$answer_log); -foreach(<$fh>) { - s/$// +my $dirname = dirname($answer_log); +copy($answer_log,"$dirname/answer_log.bak"); +open(my $in,'<',"$dirname/answer_log.bak") or die "Can't open $dirname/answer_log.bak:$!"; +open(my $out,'>',$answer_log); +while(<$in>) { + s/$old_user_id/$new_user_id/g; + print $out $_; } - - From d42b671eb7e42289d7ea1e76647570d3d48d91cb Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Tue, 6 Nov 2012 11:03:58 -0600 Subject: [PATCH 11/19] Modified DB.pm to fix issue #68 --- lib/WeBWorK/DB.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/WeBWorK/DB.pm b/lib/WeBWorK/DB.pm index d118257e79..7e44575519 100644 --- a/lib/WeBWorK/DB.pm +++ b/lib/WeBWorK/DB.pm @@ -779,10 +779,10 @@ sub addKey { my ($userID, $proctorID) = ($1, $2); croak "addKey: user $userID not found" # unless $self->{user}->exists($userID); - unless $Key -> key eq "nonce" or $self->{user}->exists($Key->user_id); + unless $Key -> key eq "nonce" or $self->{user}->exists($userID); croak "addKey: proctor $proctorID not found" # unless $self->{user}->exists($proctorID); - unless $Key -> key eq "nonce" or $self->{user}->exists($Key->user_id); + unless $Key -> key eq "nonce" or $self->{user}->exists($proctorID); } else { croak "addKey: user ", $Key->user_id, " not found" # unless $self->{user}->exists($Key->user_id); From 0010fb8dc59f73398e27740d2ad0e1311c5b9acd Mon Sep 17 00:00:00 2001 From: Paul Vojta Date: Sun, 9 Dec 2012 11:19:39 -0600 Subject: [PATCH 12/19] CAS authentication module, associated conf file and changes to Login.pm and Logout.pm --- conf/authen_CAS.conf.dist | 36 +++++++ lib/WeBWorK/Authen/CAS.pm | 136 +++++++++++++++++++++++++ lib/WeBWorK/ContentGenerator/Login.pm | 10 ++ lib/WeBWorK/ContentGenerator/Logout.pm | 3 + 4 files changed, 185 insertions(+) create mode 100644 conf/authen_CAS.conf.dist create mode 100644 lib/WeBWorK/Authen/CAS.pm diff --git a/conf/authen_CAS.conf.dist b/conf/authen_CAS.conf.dist new file mode 100644 index 0000000000..62417696a1 --- /dev/null +++ b/conf/authen_CAS.conf.dist @@ -0,0 +1,36 @@ +#!perl + +######################################################################################## +# authen_CAS.conf.dist +# Copy this file to authen_CAS.conf. Then configure it to match your server's CAS configuration. +# Then to activate add the following line to localOverrides.conf: +# include("conf/authen_CAS.conf") +######################################################################################## + +# Set CAS as the authentication module to use. +$authen{user_module} = { + "*" => "WeBWorK::Authen::CAS", +}; + +$authen{cas_options} = { + # Options to pass to the AuthCAS module. + # Note that this is (plain) AuthCAS, not Apache::AuthCAS + # or Apache2::AuthCAS. + # You need at least casUrl and CAFile; others can be set as well. + AuthCAS_opts => { + # URL of CAS server. Edit the host below. + casURL => '', #e.g. 'https://auth.berkeley.edu/cas', + + # Path of certificate file for CAS server. + CAFile => '', #e.g. '/etc/pki/tls/certs/ca-bundle.crt', + }, + # There are no options specific to CAS at this time. If there were, + # though, they would go here. + + # For debugging: + #su_from => '8315', + su_to => '999999', +}; + + +1; #final line of the file to reassure perl that it was read properly. diff --git a/lib/WeBWorK/Authen/CAS.pm b/lib/WeBWorK/Authen/CAS.pm new file mode 100644 index 0000000000..1cc78fea15 --- /dev/null +++ b/lib/WeBWorK/Authen/CAS.pm @@ -0,0 +1,136 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +package WeBWorK::Authen::CAS; +use base qw/WeBWorK::Authen/; + +use strict; +use warnings; +use AuthCAS; + +use WeBWorK::Debug; +#$WeBWorK::Debug::Enabled = 1; +#$WeBWorK::Debug::Logfile = "/opt/webwork/webwork2/logs/cas-debug.log"; +#$WeBWorK::Debug::AllowSubroutineOutput = "get_credentials"; + +sub get_credentials { + my ($self) = @_; + my $r = $self->{r}; + my $ce = $r->ce; + + # if we come in with a user_id, then we've already authenticated + # through the CAS. So just check the provided user and session key. + $self->{external_auth} = 1; + if (defined $r->param('key') && defined $r->param('user')) { + # These lines were copied from the superclass get_credentials. + $self->{session_key} = $r->param('key'); + $self->{user_id} = $r->param('user'); + $self->{login_type} = 'normal'; + $self->{credential_source} = 'params'; + debug("CAS params user '", $self->{user_id}, + "' key '", $self->{session_key}, "'"); + # Check session key and user here. Otherwise, a student can + # determine the enrollment status of any other student if + # they know the userid (which is public information at + # Berkeley). That would be a privacy violation. + my $Key = $r->db->getKey($self->{user_id}); + unless (defined $Key && $Key->key eq $self->{session_key}) { + debug('undefined or invalid session key: $Key->key = ', + defined $Key ? $Key->key : undef, ', user value = ', + $self->{session_key}); + $self->{error} = "Invalid session key"; + return 0; + } + return 1; + #debug("falling back to superclass get_credentials"); + #return $self->SUPER::get_credentials( @_ ); + } else { + #my $cas_url = $ce->{authen}{cas_options}{url}; + #my $cas_certs = $ce->{authen}{cas_options}{certs}; + #my $cas = new AuthCAS(casUrl => $cas_url, + # CAFile => $cas_certs); + my $cas = new AuthCAS( + %{ $ce->{authen}{cas_options}{AuthCAS_opts} }); + + my $service = $ce->{apache_root_url} . $r->location . '/' + . $r->urlpath->arg('courseID') . '/'; + debug("service = $service"); + my $ticket = $r->param('ticket') || 0; + unless ($ticket) { + # there's no ticket, so redirect to get one + # + my $go_to = $cas->getServerLoginURL($service); + #$go_to = 'http://math.berkeley.edu/'; # for debugging + debug("no ticket. Redirecting to $go_to"); + $self->{redirect} = $go_to; + return 0; + } + # We have a ticket. Validate it. + my $user_id = $cas->validateST($service, $ticket); + if (!defined $user_id) { + my $err = $cas->get_errors(); + $err = '' unless defined $err; + $self->{error} = $err; + debug("ticket error $err"); + #return $self->SUPER::get_credentials( @_ ); + return 0; + } else { + debug("ticket is good, user is $user_id"); + if (defined $ce->{authen}{cas_options}{su_from} + && $user_id eq $ce->{authen}{cas_options}{su_from} + && defined $ce->{authen}{cas_options}{su_to}) { + $user_id = $ce->{authen}{cas_options}{su_to}; + debug("hackily changing user to $user_id"); + } + $self->{'user_id'} = $user_id; + $self->{r}->param('user', $user_id); + $self->{session_key} = undef; + $self->{password} = "not\tvalid"; + $self->{login_type} = 'normal'; + $self->{credential_source} = 'cas'; + return 1; + } + } +} + +# There's no need to provide site_checkPassword, since it's only accessed +# from checkPassword, which we're replacing. + +sub checkPassword { + my ( $self, $userID, $clearTextPassword ) = @_; + # if we got here, we know we've already successfully authenticated + # against the CAS + return 1; +} + +# Handle logout by redirecting to the relevant CAS url. + +sub logout_user { + my ($self) = @_; + + my $ce = $self->{r}->ce; + + # Using AuthCAS::getServerLogoutURL($service) would be overkill, + # and (more important) it would send us back here after logging out, + # so we'd end up back at the CAS login screen. + + my $go_to = $ce->{authen}{cas_options}{AuthCAS_opts}{casUrl} + . '/logout'; + debug("logging out. Redirecting to $go_to"); + $self->{redirect} = $go_to; +} + +1; diff --git a/lib/WeBWorK/ContentGenerator/Login.pm b/lib/WeBWorK/ContentGenerator/Login.pm index 80ea73c2a1..851913e228 100644 --- a/lib/WeBWorK/ContentGenerator/Login.pm +++ b/lib/WeBWorK/ContentGenerator/Login.pm @@ -117,6 +117,16 @@ sub links { return( @return); } +sub pre_header_initialize { + my ($self) = @_; + my $authen = $self->r->authen; + + if ( defined($authen->{redirect}) && $authen->{redirect} ) { + $self->reply_with_redirect($authen->{redirect}); + } +} + + sub body { my ($self) = @_; my $r = $self->r; diff --git a/lib/WeBWorK/ContentGenerator/Logout.pm b/lib/WeBWorK/ContentGenerator/Logout.pm index 4ea4cde833..643deed077 100644 --- a/lib/WeBWorK/ContentGenerator/Logout.pm +++ b/lib/WeBWorK/ContentGenerator/Logout.pm @@ -82,6 +82,9 @@ sub pre_header_initialize { } $self->{keyError} = $keyError; + # Do any special processing needed by external authentication + $authen->logout_user() if $authen->can('logout_user'); + # if we have an authen redirect, all of those errors may be # moot, but I think that's unavoidable (-glarose) if ( defined($authen->{redirect}) && $authen->{redirect} ) { From 3dcb38f6be76026d97ee62b0c1fa98890e05e1f1 Mon Sep 17 00:00:00 2001 From: Paul Vojta Date: Wed, 2 Jan 2013 14:02:00 -0800 Subject: [PATCH 13/19] Added support for URLs as provided in WWfeedback messages I had inadvertently provided an older version of CAS.pm when submitting the original version. This brings CAS.pm up to date. The only change was/is to add support to keep params on the URL being sent to the CAS server (so that URLs provided by WWfeedback messages work properly). --- lib/WeBWorK/Authen/CAS.pm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/WeBWorK/Authen/CAS.pm b/lib/WeBWorK/Authen/CAS.pm index 1cc78fea15..a128c0b21e 100644 --- a/lib/WeBWorK/Authen/CAS.pm +++ b/lib/WeBWorK/Authen/CAS.pm @@ -65,8 +65,12 @@ sub get_credentials { my $cas = new AuthCAS( %{ $ce->{authen}{cas_options}{AuthCAS_opts} }); - my $service = $ce->{apache_root_url} . $r->location . '/' - . $r->urlpath->arg('courseID') . '/'; + my $service = $r->unparsed_uri(); + # Remove the "ticket=..." parameter that the CAS server added + # (Not sure if the second test is really needed.) + $service =~ s/[?&]ticket=[^&]*$// + or $service =~ s/([?&])ticket=[^&]*&/$1/; + $service = $ce->{apache_root_url} . $service; debug("service = $service"); my $ticket = $r->param('ticket') || 0; unless ($ticket) { From cb0a29158d5b05f311b0142724227e7f5a679f6e Mon Sep 17 00:00:00 2001 From: Paul Vojta Date: Wed, 2 Jan 2013 14:06:41 -0800 Subject: [PATCH 14/19] Fixed copyright date, and minor code cleanup --- lib/WeBWorK/Authen/CAS.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/WeBWorK/Authen/CAS.pm b/lib/WeBWorK/Authen/CAS.pm index a128c0b21e..c3ed38da15 100644 --- a/lib/WeBWorK/Authen/CAS.pm +++ b/lib/WeBWorK/Authen/CAS.pm @@ -1,6 +1,6 @@ ################################################################################ # WeBWorK Online Homework Delivery System -# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# Copyright © 2012 The WeBWorK Project, http://openwebwork.sf.net/ # $CVSHeader: $ # # This program is free software; you can redistribute it and/or modify it under @@ -72,8 +72,8 @@ sub get_credentials { or $service =~ s/([?&])ticket=[^&]*&/$1/; $service = $ce->{apache_root_url} . $service; debug("service = $service"); - my $ticket = $r->param('ticket') || 0; - unless ($ticket) { + my $ticket = $r->param('ticket'); + unless (defined $ticket) { # there's no ticket, so redirect to get one # my $go_to = $cas->getServerLoginURL($service); From b7afc277a57dd40b00e60de14bc5838e1a3dbf32 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Fri, 4 Jan 2013 10:02:13 -0600 Subject: [PATCH 15/19] Fixed typo in authen_CAS.conf.dist --- conf/authen_CAS.conf.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/authen_CAS.conf.dist b/conf/authen_CAS.conf.dist index 62417696a1..60f4c62e60 100644 --- a/conf/authen_CAS.conf.dist +++ b/conf/authen_CAS.conf.dist @@ -19,7 +19,7 @@ $authen{cas_options} = { # You need at least casUrl and CAFile; others can be set as well. AuthCAS_opts => { # URL of CAS server. Edit the host below. - casURL => '', #e.g. 'https://auth.berkeley.edu/cas', + casUrl => '', #e.g. 'https://auth.berkeley.edu/cas', # Path of certificate file for CAS server. CAFile => '', #e.g. '/etc/pki/tls/certs/ca-bundle.crt', From ba90466c1faf487e431aec43ada56bf0380cc7e0 Mon Sep 17 00:00:00 2001 From: John Hsu Date: Fri, 4 Jan 2013 17:05:27 -0800 Subject: [PATCH 16/19] Enable comma escaping, unicode chars in classlists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Classlists files as processed by the addcourse script can't deal with users who, for one reason or another, has a comma in either their first or last name. Using the Text::CSV module for CSV parsing instead of split() enables comma escaping values by putting them in double quotes. Users who have non-ASCII characters in their name gets their name (e.g.: Frøystein) mangled after going through addcourse. This commit forces Perl to open the the classlist file with UTF8 encoding. This way the unicode characters survive intact into the database. --- bin/check_modules.pl | 1 + lib/WeBWorK/File/Classlist.pm | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bin/check_modules.pl b/bin/check_modules.pl index d0fd873afd..c1b95fc31e 100755 --- a/bin/check_modules.pl +++ b/bin/check_modules.pl @@ -84,6 +84,7 @@ Socket SQL::Abstract String::ShellQuote + Text::CSV Text::Wrap Tie::IxHash Time::HiRes diff --git a/lib/WeBWorK/File/Classlist.pm b/lib/WeBWorK/File/Classlist.pm index cd6312f085..0f28ba7904 100644 --- a/lib/WeBWorK/File/Classlist.pm +++ b/lib/WeBWorK/File/Classlist.pm @@ -26,6 +26,7 @@ WeBWorK::File::Classlist - parse and write classlist files. use strict; use warnings; use IO::File; +use Text::CSV; our $MIN_FIELDS = 9; our $MAX_FIELDS = 11; @@ -38,10 +39,13 @@ our @EXPORT = qw/parse_classlist write_classlist/; sub parse_classlist($) { my ($file) = @_; + use open qw( :encoding(UTF-8) :std ); # assume classlist is utf8 encoded my $fh = new IO::File($file, "<") or die "Failed to open classlist '$file' for reading: $!\n"; my (@records); + + my $csv = Text::CSV->new({ binary => 1 }); # binary for utf8 compat while (<$fh>) { chomp; @@ -50,7 +54,12 @@ sub parse_classlist($) { s/^\s*//; s/\s*$//; - my @fields = split /\s*,\s*/, $_, -1; # -1 == don't delete empty trailing fields + if (!$csv->parse($_)) { + warn "Unable to parse line $. of classlist '$file' as CSV."; + next; + } + my @fields = $csv->fields; + my $fields = @fields; if ($fields < $MIN_FIELDS) { warn "Skipped invalid line $. of classlist '$file': expected at least $MIN_FIELDS fields, got $fields fields.\n"; From 4d6aad603921565740f84b0c805e0ffef3078b28 Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Fri, 11 Jan 2013 12:23:57 -0800 Subject: [PATCH 17/19] Fixed OPL-update to symlink applets to web accessible directory --- bin/OPL-update | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/OPL-update b/bin/OPL-update index ea022d4d9a..6b075d409e 100755 --- a/bin/OPL-update +++ b/bin/OPL-update @@ -416,6 +416,10 @@ sub pgfiles { my ($edition, $textauthor, $textsection, $textproblem, $tagged); %textinfo=(); my @textproblems = (-1); + if ($name =~ /swf$/ { + my $applet_file = basename($name); + symlink($name,"$webworkDirs{htdocs}/applets/$applet_file"); + } if ($name =~ /pg$/) { $pgfile = basename($name); $pgpath = dirname($name); From 64af8b9bfcdf372031fca158ec8fe616072d95be Mon Sep 17 00:00:00 2001 From: Jason Aubrey Date: Fri, 11 Jan 2013 15:21:19 -0800 Subject: [PATCH 18/19] OPL-update now symlinks swf applets in the OPL to webwork2/htdocs/applets so they can be used in problems easily --- bin/OPL-update | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/OPL-update b/bin/OPL-update index 6b075d409e..b55f406195 100755 --- a/bin/OPL-update +++ b/bin/OPL-update @@ -416,9 +416,9 @@ sub pgfiles { my ($edition, $textauthor, $textsection, $textproblem, $tagged); %textinfo=(); my @textproblems = (-1); - if ($name =~ /swf$/ { + if ($name =~ /swf$/) { my $applet_file = basename($name); - symlink($name,"$webworkDirs{htdocs}/applets/$applet_file"); + symlink($name,$ce->{webworkDirs}->{htdocs}."/applets/".$applet_file); } if ($name =~ /pg$/) { $pgfile = basename($name); From 3e4dbda26711ba887222546eefed088161c4b824 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 17 Jan 2013 12:44:03 -0500 Subject: [PATCH 19/19] Remove LimitedPolynomials and Inequalities::common from the preloaded list (now that the package errors are resolved). Must put back the original contextLimitedPolynomials.pl and contextInequalities.pl as well --- conf/defaults.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/conf/defaults.config b/conf/defaults.config index 50e174eb70..3afe7dcac6 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -938,9 +938,7 @@ ${pg}{modules} = [ [qw(Fraction)], [qw(Fun)], [qw(Hermite)], - [qw(Inequalities::common)], [qw(Label)], - [qw(LimitedPolynomial)], [qw(ChoiceList)], [qw(Match)], [qw(MatrixReal1)], # required by Matrix