';
foreach my $ltirole (@lticourseroles) {
my ($selected,$selectnone);
@@ -6421,13 +7177,18 @@ sub print_usersessions {
if ($position eq 'top') {
if (keys(%serverhomes) > 1) {
my %spareid = ¤t_offloads_to($dom,$settings,\%servers);
- my $curroffloadnow;
+ my ($curroffloadnow,$curroffloadoth);
if (ref($settings) eq 'HASH') {
if (ref($settings->{'offloadnow'}) eq 'HASH') {
$curroffloadnow = $settings->{'offloadnow'};
}
+ if (ref($settings->{'offloadoth'}) eq 'HASH') {
+ $curroffloadoth = $settings->{'offloadoth'};
+ }
}
- $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,$curroffloadnow,$rowtotal);
+ my $other_insts = scalar(keys(%by_location));
+ $datatable .= &spares_row($dom,\%servers,\%spareid,\%serverhomes,\%altids,
+ $other_insts,$curroffloadnow,$curroffloadoth,$rowtotal);
} else {
$datatable .= '
'.
&mt('Nothing to set here, as the cluster to which this domain belongs only contains one server.').
@@ -6871,7 +7632,8 @@ sub current_offloads_to {
}
sub spares_row {
- my ($dom,$servers,$spareid,$serverhomes,$altids,$curroffloadnow,$rowtotal) = @_;
+ my ($dom,$servers,$spareid,$serverhomes,$altids,$other_insts,
+ $curroffloadnow,$curroffloadoth,$rowtotal) = @_;
my $css_class;
my $numinrow = 4;
my $itemcount = 1;
@@ -6891,12 +7653,17 @@ sub spares_row {
}
}
next unless (ref($spareid->{$server}) eq 'HASH');
- my $checkednow;
+ my ($checkednow,$checkedoth);
if (ref($curroffloadnow) eq 'HASH') {
if ($curroffloadnow->{$server}) {
$checkednow = ' checked="checked"';
}
}
+ if (ref($curroffloadoth) eq 'HASH') {
+ if ($curroffloadoth->{$server}) {
+ $checkedoth = ' checked="checked"';
+ }
+ }
$css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
$datatable .= '
@@ -6905,8 +7672,15 @@ sub spares_row {
,''.$server.'').' '.
''."\n".
''.
+ ' '.&mt('Switch any active user on next access').''.
"\n";
+ if ($other_insts) {
+ $datatable .= ' '.
+ ''."\n".
+ ''.
+ "\n";
+ }
my (%current,%canselect);
my @choices =
&possible_newspares($server,$spareid->{$server},$serverhomes,$altids);
@@ -12410,7 +13184,7 @@ sub modify_ltitools {
}
}
if (!$numconfig) {
- $resulttext .= &mt('None');
+ $resulttext .= ' '.&mt('None');
}
$resulttext .= '';
foreach my $item ('passback','roster') {
@@ -12589,6 +13363,536 @@ sub get_ltitools_id {
return ($id,$error);
}
+sub modify_proctoring {
+ my ($r,$dom,$action,$lastactref,%domconfig) = @_;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my (@allpos,%changes,%confhash,%encconfhash,$errors,$resulttext,%imgdeletions);
+ my $confname = $dom.'-domainconfig';
+ my $servadm = $r->dir_config('lonAdmEMail');
+ my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm);
+ my %providernames = &proctoring_providernames();
+ my $maxnum = scalar(keys(%providernames));
+
+ my (%requserfields,%optuserfields,%defaults,%extended,%crsconf,@courseroles,@ltiroles);
+ my ($requref,$opturef,$defref,$extref,$crsref,$rolesref,$ltiref) = &proctoring_data();
+ if (ref($requref) eq 'HASH') {
+ %requserfields = %{$requref};
+ }
+ if (ref($opturef) eq 'HASH') {
+ %optuserfields = %{$opturef};
+ }
+ if (ref($defref) eq 'HASH') {
+ %defaults = %{$defref};
+ }
+ if (ref($extref) eq 'HASH') {
+ %extended = %{$extref};
+ }
+ if (ref($crsref) eq 'HASH') {
+ %crsconf = %{$crsref};
+ }
+ if (ref($rolesref) eq 'ARRAY') {
+ @courseroles = @{$rolesref};
+ }
+ if (ref($ltiref) eq 'ARRAY') {
+ @ltiroles = @{$ltiref};
+ }
+
+ if (ref($domconfig{$action}) eq 'HASH') {
+ my @todeleteimages = &Apache::loncommon::get_env_multiple('form.proctoring_image_del');
+ if (@todeleteimages) {
+ map { $imgdeletions{$_} = 1; } @todeleteimages;
+ }
+ }
+ my %customadds;
+ my @newcustom = &Apache::loncommon::get_env_multiple('form.proctoring_customadd');
+ if (@newcustom) {
+ map { $customadds{$_} = 1; } @newcustom;
+ }
+ foreach my $provider (sort(keys(%providernames))) {
+ $confhash{$provider} = {};
+ my $pos = $env{'form.proctoring_pos_'.$provider};
+ $pos =~ s/\D+//g;
+ $allpos[$pos] = $provider;
+ my (%current,%currentenc);
+ my $showroles = 0;
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$provider}) eq 'HASH') {
+ %current = %{$domconfig{$action}{$provider}};
+ foreach my $item ('key','secret') {
+ $currentenc{$item} = $current{$item};
+ delete($current{$item});
+ }
+ }
+ }
+ if ($env{'form.proctoring_available_'.$provider}) {
+ $confhash{$provider}{'available'} = 1;
+ unless ($current{'available'}) {
+ $changes{$provider} = 1;
+ }
+ } else {
+ %{$confhash{$provider}} = %current;
+ %{$encconfhash{$provider}} = %currentenc;
+ $confhash{$provider}{'available'} = 0;
+ if ($current{'available'}) {
+ $changes{$provider} = 1;
+ }
+ }
+ if ($confhash{$provider}{'available'}) {
+ foreach my $field ('lifetime','version','sigmethod','url','key','secret') {
+ my $possval = $env{'form.proctoring_'.$provider.'_'.$field};
+ if ($field eq 'lifetime') {
+ if ($possval =~ /^\d+$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'version') {
+ if ($possval =~ /^\d+\.\d+$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'sigmethod') {
+ if ($possval =~ /^\QHMAC-SHA\E(1|256)$/) {
+ $confhash{$provider}{$field} = $possval;
+ }
+ } elsif ($field eq 'url') {
+ $confhash{$provider}{$field} = $possval;
+ } elsif (($field eq 'key') || ($field eq 'secret')) {
+ $encconfhash{$provider}{$field} = $possval;
+ unless ($currentenc{$field} eq $possval) {
+ $changes{$provider} = 1;
+ }
+ }
+ unless (($field eq 'key') || ($field eq 'secret')) {
+ unless ($current{$field} eq $confhash{$provider}{$field}) {
+ $changes{$provider} = 1;
+ }
+ }
+ }
+ if ($imgdeletions{$provider}) {
+ $changes{$provider} = 1;
+ } elsif ($env{'form.proctoring_image_'.$provider.'.filename'} ne '') {
+ my ($imageurl,$error) =
+ &process_proctoring_image($r,$dom,$confname,'proctoring_image_'.$provider,$provider,
+ $configuserok,$switchserver,$author_ok);
+ if ($imageurl) {
+ $confhash{$provider}{'image'} = $imageurl;
+ $changes{$provider} = 1;
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= '