--- loncom/homework/bridgetask.pm 2008/08/13 09:10:44 1.239
+++ loncom/homework/bridgetask.pm 2025/04/02 23:44:02 1.275
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# definition of tags that give a structure to a document
#
-# $Id: bridgetask.pm,v 1.239 2008/08/13 09:10:44 bisitz Exp $
+# $Id: bridgetask.pm,v 1.275 2025/04/02 23:44:02 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -32,11 +32,14 @@ package Apache::bridgetask;
use strict;
use Apache::lonnet;
+use Apache::loncommon;
use Apache::File();
use Apache::lonmenu;
use Apache::lonlocal;
use Apache::lonxml;
use Apache::slotrequest();
+use Apache::structuretags();
+use HTML::Entities();
use Time::HiRes qw( gettimeofday tv_interval );
use LONCAPA;
@@ -64,6 +67,7 @@ sub initialize_bridgetask {
sub proctor_check_auth {
my ($slot_name,$slot,$type)=@_;
my $user=$env{'form.proctorname'};
+ $user =~ s/^\s+|\s+$//g;
my $domain=$env{'form.proctordomain'};
my @allowed=split(",",$slot->{'proctor'});
@@ -82,7 +86,10 @@ sub proctor_check_auth {
}
}
if ($authenticated) {
- &check_in($type,$user,$domain,$slot_name);
+ my $check = &check_in($type,$user,$domain,$slot_name,$slot->{'iptied'});
+ if ($check =~ /^error:/) {
+ return 0;
+ }
return 1;
}
}
@@ -91,41 +98,82 @@ sub proctor_check_auth {
}
sub check_in {
- my ($type,$user,$domain,$slot_name) = @_;
+ my ($type,$user,$domain,$slot_name,$needsiptied) = @_;
my $useslots = &Apache::lonnet::EXT("resource.0.useslots");
+ my $ip=$ENV{'REMOTE_ADDR'} || $env{'request.host'};
if ( $useslots eq 'map_map') {
- &check_in_sequence($user,$domain,$slot_name);
+ my $result = &check_in_sequence($user,$domain,$slot_name,$ip,$needsiptied);
+ if ($result =~ /^error: /) {
+ return $result;
+ }
} else {
- &create_new_version($type,$user,$domain,$slot_name);
- &Apache::structuretags::finalize_storage();
+ my ($symb) = &Apache::lonnet::whichuser();
+ my $result = &create_new_version($type,$user,$domain,$slot_name,$symb,$ip,$needsiptied);
+ if ($result eq 'ok') {
+ &Apache::structuretags::finalize_storage();
+ }
+ return $result;
}
return 1;
}
sub check_in_sequence {
- my ($user,$domain,$slot_name) = @_;
+ my ($user,$domain,$slot_name,$ip,$needsiptied) = @_;
my $navmap = Apache::lonnavmaps::navmap->new();
+ if (!defined($navmap)) {
+ return 'error: No navmap';
+ }
my ($symb) = &Apache::lonnet::whichuser();
my ($map) = &Apache::lonnet::decode_symb($symb);
my @resources =
- $navmap->retrieveResources($map, sub { $_[0]->is_problem() },0,0);
+ $navmap->retrieveResources($map, sub { $_[0]->is_problem() || $_[0]->is_tool() },0,0);
my %old_history = %Apache::lonhomework::history;
my %old_results = %Apache::lonhomework::results;
+ my $errorcount;
foreach my $res (@resources) {
&Apache::lonxml::debug("doing ".$res->src);
&Apache::structuretags::initialize_storage($res->symb);
- my $type = ($res->is_task()) ? 'Task' : 'problem';
- &create_new_version($type,$user,$domain,$slot_name);
- &Apache::structuretags::finalize_storage($res->symb);
+ my $type;
+ if ($res->is_task()) {
+ $type = 'Task';
+ } elsif ($res->is_tool) {
+ $type = 'tool';
+ } else {
+ $type = 'problem';
+ }
+ my $result = &create_new_version($type,$user,$domain,$slot_name,$res->symb,$ip,$needsiptied);
+ if ($result eq 'ok') {
+ &Apache::structuretags::finalize_storage($res->symb);
+ } else {
+ $errorcount ++;
+ }
}
%Apache::lonhomework::history = %old_history;
%Apache::lonhomework::results = %old_results;
+ if ($errorcount) {
+ return 'error: IP taken';
+ }
}
sub create_new_version {
- my ($type,$user,$domain,$slot_name) = @_;
+ my ($type,$user,$domain,$slot_name,$symb,$ip,$needsiptied) = @_;
+
+ if ($needsiptied) {
+ my $uniqkey = "$slot_name\0$symb\0$ip";
+ my ($cdom,$cnum);
+ if ($env{'request.course.id'}) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my %hash = (
+ "$slot_name\0$symb\0$ip" => $env{'user.name'}.':'.$env{'user.domain'},
+ );
+ unless (&Apache::lonnet::newput('slot_uniqueips',\%hash,$cdom,$cnum) eq 'ok') {
+ return 'error: IP taken';
+ }
+ }
+ }
my $id = '0';
if ($type eq 'Task') {
@@ -149,7 +197,7 @@ sub create_new_version {
$domain = $env{'user.domain'};
}
- } elsif ($type eq 'problem') {
+ } elsif (($type eq 'problem') || ($type eq 'tool')) {
&Apache::lonxml::debug("authed $slot_name");
}
if (!defined($user) || !defined($domain)) {
@@ -159,11 +207,13 @@ sub create_new_version {
$Apache::lonhomework::results{"resource.$id.checkedin"}=
$user.':'.$domain;
+ $Apache::lonhomework::results{"resource.$id.checkedin.ip"}=$ip;
if (defined($slot_name)) {
$Apache::lonhomework::results{"resource.$id.checkedin.slot"}=
$slot_name;
}
+ return 'ok';
}
sub get_version {
@@ -189,6 +239,10 @@ sub get_version {
sub add_previous_version_button {
my ($status)=@_;
+ my (undef,undef,$udom,$uname)=&Apache::lonnet::whichuser();
+ if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
+ return;
+ }
my $result;
if ($Apache::lonhomework::history{'resource.0.version'} eq '') {
return '';
@@ -225,7 +279,10 @@ sub add_previous_version_button {
}
sub add_grading_button {
- my (undef,$cid)=&Apache::lonnet::whichuser();
+ my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
+ if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
+ return;
+ }
my $cnum=$env{'course.'.$cid.'.num'};
my $cdom=$env{'course.'.$cid.'.domain'};
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
@@ -235,15 +292,19 @@ sub add_grading_button {
$size=scalar(keys(%sections))+2;
}
my $sec_select = "\n".'\n";
-
- my $result="\n\t".'';
- $result.="\n\t".'';
+ $sec_select .= "\t".'\n\n";
+
+ my $uri=$env{'request.uri'};
+ if ($env{'request.enc'}) { $uri=&Apache::lonenc::encrypted($uri); }
+ my $result =
+ '
'."\n";
+ return $result;
+}
+
+sub add_slotlist_button {
+ my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
+ if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
+ return;
+ }
+ my $symb=&Apache::lonnet::symbread();
+ my $result;
+ if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'}) ||
+ &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
+ $result = '';
+ my $target_id =
+ &Apache::lonstathelpers::make_target_id({symb => $symb,
+ part => '0'});
+ if (!§ion_restricted()) {
+ $result.='';
+ }
+ }
return $result;
}
sub add_request_another_attempt_button {
my ($text)=@_;
+ my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
+ if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
+ return;
+ }
if (!$text) { $text=&mt('Request another attempt'); }
my $result;
my $symb=&Apache::lonnet::symbread();
@@ -306,7 +402,7 @@ sub add_request_another_attempt_button {
my ($slot_name,$slot)=&Apache::slotrequest::check_for_reservation($symb);
my $action='get_reservation';
if ($slot_name) {
- $text=&mt('Change reservation.');
+ $text=&mt('Change reservation');
$action='change_reservation';
my $description=&Apache::slotrequest::get_description($slot_name,
$slot);
@@ -316,11 +412,16 @@ sub add_request_another_attempt_button {
.'';
}
- if ($env{'request.enc'}) { $symb=&Apache::lonenc::encrypted($symb); }
- $symb=&escape($symb);
+ my $shownsymb;
+ if ($env{'request.enc'}) {
+ $shownsymb = &Apache::lonenc::encrypted($symb);
+ } else {
+ $shownsymb = $symb;
+ }
+ $shownsymb=&escape($shownsymb);
$result.=
"\n\t".'
DONEBUTTON
}
@@ -1161,7 +1304,9 @@ DONEBUTTON
}
$result.="\n\n".
&Apache::loncommon::end_page({'discussion' => 1});
- }
+ } elsif ($target eq 'answer') {
+ $result.="\n\n";
+ }
}
my $useslots = &Apache::lonnet::EXT("resource.0.useslots");
@@ -1172,13 +1317,16 @@ DONEBUTTON
} elsif (defined($Apache::lonhomework::history{"resource.$version.0.checkedin.slot"})) {
$queue_data{'slot'} = $Apache::lonhomework::history{"resource.$version.0.checkedin.slot"};
}
-
+
if ($target eq 'grade' && !$env{'form.webgrade'} && !$previous
&& $status eq 'CAN_ANSWER') {
my $award='SUBMITTED';
+ my $uploadedflag=0;
+ my $totalsize=0;
+ my @deletions = &Apache::loncommon::get_env_multiple('form.HWFILE'.$version.'_0_bridgetask_delete');
&Apache::essayresponse::file_submission("$version.0",'bridgetask',
- 'portfiles',\$award);
+ \$award,\$uploadedflag,\$totalsize,\@deletions);
if ($award eq 'SUBMITTED' &&
$Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}) {
$Apache::lonhomework::results{"resource.0.tries"}=
@@ -1191,7 +1339,9 @@ DONEBUTTON
$Apache::lonhomework::results{"resource.0.submission"}=
$Apache::lonhomework::results{"resource.$version.0.submission"}='';
} else {
- delete($Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"});
+ unless($uploadedflag) {
+ delete($Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"});
+ }
$award = '';
}
&Apache::lonhomework::showhash(%Apache::lonhomework::results);
@@ -1294,38 +1444,64 @@ DONEBUTTON
$Apache::lonhomework::results{"resource.$version.0.solved"};
}
&minimize_storage();
- &Apache::structuretags::finalize_storage();
-
- # data stored, now handle queue
- if ($review) {
- if ($env{'form.queue'} eq 'reviewqueue') {
- &check_queue_unlock($env{'form.queue'});
- &Apache::lonxml::debug(" still needs review not changing status.");
- } else {
- if ($env{'form.queue'} ne 'none') {
- &move_between_queues($env{'form.queue'},'reviewqueue');
+ my ($canstore,$domain,$name,$symb,$courseid);
+ ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
+
+ if ($env{'form.gradingkey'}) {
+ my $todo=&unescape($env{'form.gradingkey'});
+ my ($keysymb,$uname,$udom)=&decode_queue_key($todo);
+ if ($symb eq $keysymb) {
+ if (($domain eq $udom) && ($name eq $uname)) {
+ $canstore = 1;
+ }
+ }
+ }
+ if ($canstore) {
+ &Apache::structuretags::finalize_storage();
+ my @interval = &Apache::lonnet::EXT("resource.0.interval");
+ if ($interval[0] =~ /^\d+/ && $interval[1] eq 'resource') {
+ my $key=$courseid."\0".$symb;
+ my %times=&Apache::lonnet::get('firstaccesstimes',
+ [$key],$domain,$name);
+ if ($times{$key}) {
+ my $delresult.=&Apache::lonnet::del('firstaccesstimes',
+ [$key],$domain,$name);
+ }
+ }
+ # data stored, now handle queue
+ if ($review) {
+ if ($env{'form.queue'} eq 'reviewqueue') {
+ &check_queue_unlock($env{'form.queue'});
+ &Apache::lonxml::debug(" still needs review not changing status.");
} else {
- &add_to_queue('reviewqueue',\%queue_data);
+ if ($env{'form.queue'} ne 'none') {
+ &move_between_queues($env{'form.queue'},'reviewqueue');
+ } else {
+ &add_to_queue('reviewqueue',\%queue_data);
+ }
}
- }
- } elsif ($ungraded) {
- if ($env{'form.queue'} eq 'reviewqueue') {
- &Apache::lonxml::debug("moving back.");
- &move_between_queues($env{'form.queue'},
- 'gradingqueue');
- } elsif ($env{'form.queue'} eq 'none' ) {
- &add_to_queue('gradingqueue',\%queue_data);
- } else {
- &check_queue_unlock($env{'form.queue'});
- }
- } elsif ($mandatory_failed) {
- &remove_from_queue($env{'form.queue'});
- } else {
- &remove_from_queue($env{'form.queue'});
- }
- }
+ } elsif ($ungraded) {
+ if ($env{'form.queue'} eq 'reviewqueue') {
+ &Apache::lonxml::debug("moving back.");
+ &move_between_queues($env{'form.queue'},
+ 'gradingqueue');
+ } elsif ($env{'form.queue'} eq 'none' ) {
+ &add_to_queue('gradingqueue',\%queue_data);
+ } else {
+ &check_queue_unlock($env{'form.queue'});
+ }
+ } elsif ($mandatory_failed) {
+ &remove_from_queue($env{'form.queue'});
+ } else {
+ &remove_from_queue($env{'form.queue'});
+ }
+ } else {
+ &check_queue_unlock($env{'form.queue'});
+ $env{'form.terminated'} = $name.':'.$domain;
+ }
+ }
if (exists($Apache::lonhomework::results{'INTERNAL_store'})) {
- # instance generation occured and hasn't yet been stored
+ # instance generation occurred and hasn't yet been stored
&Apache::structuretags::finalize_storage();
}
} elsif ($target eq 'webgrade') {
@@ -1381,6 +1557,13 @@ DONEBUTTON
}
&Apache::structuretags::reset_problem_globals('Task');
undef($Apache::lonhomework::parsing_a_task);
+ if ( ($target eq 'grade' && $env{'form.webgrade'}) ||
+ $target eq 'webgrade') {
+ delete($env{'form.grade_symb'});
+ delete($env{'form.grade_domain'});
+ delete($env{'form.grade_username'});
+ delete($env{'form.grade_courseid'});
+ }
return $result;
}
@@ -1665,7 +1848,7 @@ sub show_queue {
$result.=(<