version 1.371, 2020/03/15 23:04:15
|
version 1.372, 2020/09/17 00:35:04
|
Line 219 sub handler {
|
Line 219 sub handler {
|
'serverstatuses','requestcourses','helpsettings', |
'serverstatuses','requestcourses','helpsettings', |
'coursedefaults','usersessions','loadbalancing', |
'coursedefaults','usersessions','loadbalancing', |
'requestauthor','selfenrollment','inststatus', |
'requestauthor','selfenrollment','inststatus', |
'ltitools','ssl','trust','lti','privacy','passwords'],$dom); |
'ltitools','ssl','trust','lti','privacy','passwords', |
|
'proctoring'],$dom); |
my %encconfig = |
my %encconfig = |
&Apache::lonnet::get_dom('encconfig',['ltitools','lti'],$dom); |
&Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring'],$dom); |
if (ref($domconfig{'ltitools'}) eq 'HASH') { |
if (ref($domconfig{'ltitools'}) eq 'HASH') { |
if (ref($encconfig{'ltitools'}) eq 'HASH') { |
if (ref($encconfig{'ltitools'}) eq 'HASH') { |
foreach my $id (keys(%{$domconfig{'ltitools'}})) { |
foreach my $id (keys(%{$domconfig{'ltitools'}})) { |
Line 246 sub handler {
|
Line 247 sub handler {
|
} |
} |
} |
} |
} |
} |
|
if (ref($domconfig{'proctoring'}) eq 'HASH') { |
|
if (ref($encconfig{'proctoring'}) eq 'HASH') { |
|
foreach my $provider (keys(%{$domconfig{'proctoring'}})) { |
|
if ((ref($domconfig{'proctoring'}{$provider}) eq 'HASH') && |
|
(ref($encconfig{'proctoring'}{$provider}) eq 'HASH')) { |
|
foreach my $item ('key','secret') { |
|
$domconfig{'proctoring'}{$provider}{$item} = $encconfig{'proctoring'}{$provider}{$item}; |
|
} |
|
} |
|
} |
|
} |
|
} |
my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll', |
my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll', |
'autoupdate','autocreate','directorysrch','contacts','privacy', |
'autoupdate','autocreate','directorysrch','contacts','privacy', |
'usercreation','selfcreation','usermodification','scantron', |
'usercreation','selfcreation','usermodification','scantron', |
'requestcourses','requestauthor','coursecategories', |
'requestcourses','requestauthor','coursecategories', |
'serverstatuses','helpsettings','coursedefaults', |
'serverstatuses','helpsettings','coursedefaults', |
'ltitools','selfenrollment','usersessions','ssl','trust','lti'); |
'ltitools','proctoring','selfenrollment','usersessions','ssl', |
|
'trust','lti'); |
my %existing; |
my %existing; |
if (ref($domconfig{'loadbalancing'}) eq 'HASH') { |
if (ref($domconfig{'loadbalancing'}) eq 'HASH') { |
%existing = %{$domconfig{'loadbalancing'}}; |
%existing = %{$domconfig{'loadbalancing'}}; |
Line 541 sub handler {
|
Line 555 sub handler {
|
print => \&print_ltitools, |
print => \&print_ltitools, |
modify => \&modify_ltitools, |
modify => \&modify_ltitools, |
}, |
}, |
|
'proctoring' => |
|
{text => 'Remote Proctoring Integration', |
|
help => 'Domain_Configuration_Proctoring', |
|
header => [{col1 => 'Name', |
|
col2 => 'Configuration'}], |
|
print => \&print_proctoring, |
|
modify => \&modify_proctoring, |
|
}, |
'ssl' => |
'ssl' => |
{text => 'LON-CAPA Network (SSL)', |
{text => 'LON-CAPA Network (SSL)', |
help => 'Domain_Configuration_Network_SSL', |
help => 'Domain_Configuration_Network_SSL', |
Line 771 sub process_changes {
|
Line 793 sub process_changes {
|
$output = &modify_loadbalancing($dom,%domconfig); |
$output = &modify_loadbalancing($dom,%domconfig); |
} elsif ($action eq 'ltitools') { |
} elsif ($action eq 'ltitools') { |
$output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig); |
$output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig); |
|
} elsif ($action eq 'proctoring') { |
|
$output = &modify_proctoring($r,$dom,$action,$lastactref,%domconfig); |
} elsif ($action eq 'ssl') { |
} elsif ($action eq 'ssl') { |
$output = &modify_ssl($dom,$lastactref,%domconfig); |
$output = &modify_ssl($dom,$lastactref,%domconfig); |
} elsif ($action eq 'trust') { |
} elsif ($action eq 'trust') { |
Line 815 sub print_config_box {
|
Line 839 sub print_config_box {
|
$output .= <itools_javascript($settings); |
$output .= <itools_javascript($settings); |
} elsif ($action eq 'lti') { |
} elsif ($action eq 'lti') { |
$output .= <i_javascript($settings); |
$output .= <i_javascript($settings); |
|
} elsif ($action eq 'proctoring') { |
|
$output .= &proctoring_javascript($settings); |
} |
} |
$output .= |
$output .= |
'<table class="LC_nested_outer"> |
'<table class="LC_nested_outer"> |
Line 1162 sub print_config_box {
|
Line 1188 sub print_config_box {
|
$output .= &print_quotas($dom,$settings,\$rowtotal,$action); |
$output .= &print_quotas($dom,$settings,\$rowtotal,$action); |
} elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || |
} elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || |
($action eq 'serverstatuses') || ($action eq 'loadbalancing') || |
($action eq 'serverstatuses') || ($action eq 'loadbalancing') || |
($action eq 'ltitools') || ($action eq 'lti')) { |
($action eq 'ltitools') || ($action eq 'lti') || |
|
($action eq 'proctoring')) { |
$output .= $item->{'print'}->($dom,$settings,\$rowtotal); |
$output .= $item->{'print'}->($dom,$settings,\$rowtotal); |
} |
} |
} |
} |
Line 2803 function toggleLTITools(form,setting,ite
|
Line 2830 function toggleLTITools(form,setting,ite
|
ENDSCRIPT |
ENDSCRIPT |
} |
} |
|
|
|
sub proctoring_javascript { |
|
my ($settings) = @_; |
|
my (%ordered,$total,%jstext); |
|
$total = 0; |
|
if (ref($settings) eq 'HASH') { |
|
foreach my $item (keys(%{$settings})) { |
|
if (ref($settings->{$item}) eq 'HASH') { |
|
my $num = $settings->{$item}{'order'}; |
|
$ordered{$num} = $item; |
|
} |
|
} |
|
$total = scalar(keys(%{$settings})); |
|
} else { |
|
%ordered = ( |
|
0 => 'proctorio', |
|
1 => 'examity', |
|
); |
|
$total = 2; |
|
} |
|
my @jsarray = (); |
|
foreach my $item (sort {$a <=> $b } (keys(%ordered))) { |
|
push(@jsarray,$ordered{$item}); |
|
} |
|
my $jstext = ' var proctors = Array('."'".join("','",@jsarray)."'".');'."\n"; |
|
return <<"ENDSCRIPT"; |
|
<script type="text/javascript"> |
|
// <![CDATA[ |
|
function reorderProctoring(form,item) { |
|
var changedVal; |
|
$jstext |
|
var maxh = $total; |
|
var current = new Array; |
|
var changedVal = form.elements[item].options[form.elements[item].selectedIndex].value; |
|
for (var i=0; i<proctors.length; i++) { |
|
var elementName = 'proctoring_pos_'+proctors[i]; |
|
if (elementName != item) { |
|
if (form.elements[elementName]) { |
|
var currVal = form.elements[elementName].options[form.elements[elementName].selectedIndex].value; |
|
current[currVal] = elementName; |
|
} |
|
} |
|
} |
|
var oldVal; |
|
for (var j=0; j<maxh; j++) { |
|
if (current[j] == undefined) { |
|
oldVal = j; |
|
} |
|
} |
|
if (oldVal < changedVal) { |
|
for (var k=oldVal+1; k<=changedVal ; k++) { |
|
var elementName = current[k]; |
|
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex - 1; |
|
} |
|
} else { |
|
for (var k=changedVal; k<oldVal; k++) { |
|
var elementName = current[k]; |
|
form.elements[elementName].selectedIndex = form.elements[elementName].selectedIndex + 1; |
|
} |
|
} |
|
return; |
|
} |
|
|
|
function toggleProctoring(form,item) { |
|
var fieldsets = document.getElementsByClassName('proctoring_'+item); |
|
if (fieldsets.length) { |
|
var radioname = 'proctoring_available_'+item; |
|
var num = form.elements[radioname].length; |
|
if (num) { |
|
var setvis = ''; |
|
for (var i=0; i<num; i++) { |
|
if (form.elements[radioname][i].checked) { |
|
if (form.elements[radioname][i].value == '1') { |
|
setvis = 1; |
|
break; |
|
} |
|
} |
|
} |
|
for (var j=0; j<fieldsets.length; j++) { |
|
if (setvis) { |
|
fieldsets[j].style.display = 'block'; |
|
} else { |
|
fieldsets[j].style.display = 'none'; |
|
} |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
// ]]> |
|
</script> |
|
|
|
ENDSCRIPT |
|
} |
|
|
|
|
sub lti_javascript { |
sub lti_javascript { |
my ($settings) = @_; |
my ($settings) = @_; |
my $togglejs = <i_toggle_js(); |
my $togglejs = <i_toggle_js(); |
Line 4620 sub print_ltitools {
|
Line 4743 sub print_ltitools {
|
} |
} |
$datatable .= '<label>'. |
$datatable .= '<label>'. |
'<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'. |
'<input type="checkbox" name="ltitools_courseconfig_'.$i.'" value="'.$item.'"'.$checked.' />'. |
$lt{'crs'.$item}.'</label>'.(' ' x2)."\n"; |
$lt{'crs'.$item}.'</label> '."\n"; |
} |
} |
$datatable .= '</span></fieldset>'. |
$datatable .= '</span></fieldset>'. |
'<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'. |
'<fieldset><legend>'.&mt('Custom items sent on launch').'</legend>'. |
Line 4822 sub ltitools_names {
|
Line 4945 sub ltitools_names {
|
return %lt; |
return %lt; |
} |
} |
|
|
|
sub print_proctoring { |
|
my ($dom,$settings,$rowtotal) = @_; |
|
my $itemcount = 1; |
|
my (%ordered,%providernames,%current,%currentdef); |
|
my $confname = $dom.'-domainconfig'; |
|
my $switchserver = &check_switchserver($dom,$confname); |
|
if (ref($settings) eq 'HASH') { |
|
foreach my $item (keys(%{$settings})) { |
|
if (ref($settings->{$item}) eq 'HASH') { |
|
my $num = $settings->{$item}{'order'}; |
|
$ordered{$num} = $item; |
|
} |
|
} |
|
} else { |
|
%ordered = ( |
|
1 => 'proctorio', |
|
2 => 'examity', |
|
); |
|
} |
|
%providernames = &proctoring_providernames(); |
|
my $maxnum = scalar(keys(%ordered)); |
|
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}; |
|
} |
|
my $datatable; |
|
my $css_class; |
|
if (keys(%ordered)) { |
|
my @items = sort { $a <=> $b } keys(%ordered); |
|
for (my $i=0; $i<@items; $i++) { |
|
$css_class = $itemcount%2?' class="LC_odd_row"':''; |
|
my $provider = $ordered{$items[$i]}; |
|
my $optionsty = 'none'; |
|
my ($available,$version,$lifetime,$imgsrc,$userincdom,$showroles, |
|
%checkedfields,%rolemaps,%inuse,%crsconfig,%current); |
|
if (ref($settings) eq 'HASH') { |
|
if (ref($settings->{$provider}) eq 'HASH') { |
|
%current = %{$settings->{$provider}}; |
|
if ($current{'available'}) { |
|
$optionsty = 'block'; |
|
$available = 1; |
|
} |
|
if ($current{'lifetime'} =~ /^\d+$/) { |
|
$lifetime = $current{'lifetime'}; |
|
} |
|
if ($current{'version'} =~ /^\d+\.\d+$/) { |
|
$version = $current{'version'}; |
|
} |
|
if ($current{'image'} ne '') { |
|
$imgsrc = '<img src="'.$current{'image'}.'" alt="'.&mt('Proctoring service icon').'" />'; |
|
} |
|
if (ref($current{'fields'}) eq 'ARRAY') { |
|
map { $checkedfields{$_} = 1; } @{$current{'fields'}}; |
|
} |
|
$userincdom = $current{'incdom'}; |
|
if (ref($current{'roles'}) eq 'HASH') { |
|
%rolemaps = %{$current{'roles'}}; |
|
$checkedfields{'roles'} = 1; |
|
} |
|
if (ref($current{'defaults'}) eq 'ARRAY') { |
|
foreach my $val (@{$current{'defaults'}}) { |
|
if (grep(/^\Q$val\E$/,@{$defaults{$provider}})) { |
|
$inuse{$val} = 1; |
|
} else { |
|
foreach my $poss (keys(%{$extended{$provider}})) { |
|
if (ref($extended{$provider}{$poss}) eq 'ARRAY') { |
|
if (grep(/^\Q$val\E$/,@{$extended{$provider}{$poss}})) { |
|
$inuse{$poss} = $val; |
|
last; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} elsif (ref($current{'defaults'}) eq 'HASH') { |
|
foreach my $key (keys(%{$current{'defaults'}})) { |
|
my $currval = $current{'defaults'}{$key}; |
|
if (grep(/^\Q$key\E$/,@{$defaults{$provider}})) { |
|
$inuse{$key} = 1; |
|
} else { |
|
my $match; |
|
foreach my $poss (keys(%{$extended{$provider}})) { |
|
if (ref($extended{$provider}{$poss}) eq 'ARRAY') { |
|
if (grep(/^\Q$key\E$/,@{$extended{$provider}{$poss}})) { |
|
$inuse{$poss} = $key; |
|
last; |
|
} |
|
} elsif (ref($extended{$provider}{$poss}) eq 'HASH') { |
|
foreach my $inner (sort(keys(%{$extended{$provider}{$poss}}))) { |
|
if (ref($extended{$provider}{$poss}{$inner}) eq 'ARRAY') { |
|
if (grep(/^\Q$currval\E$/,@{$extended{$provider}{$poss}{$inner}})) { |
|
$currentdef{$inner} = $currval; |
|
$match = 1; |
|
last; |
|
} |
|
} elsif ($inner eq $key) { |
|
$currentdef{$key} = $currval; |
|
$match = 1; |
|
last; |
|
} |
|
} |
|
} |
|
last if ($match); |
|
} |
|
} |
|
} |
|
} |
|
if (ref($current{'crsconf'}) eq 'ARRAY') { |
|
map { $crsconfig{$_} = 1; } @{$current{'crsconf'}}; |
|
} |
|
} |
|
} |
|
my %lt = &proctoring_titles($provider); |
|
my %fieldtitles = &proctoring_fieldtitles($provider); |
|
my $onclickavailable = ' onclick="toggleProctoring(this.form,'."'$provider'".');"'; |
|
my %checkedavailable = ( |
|
yes => '', |
|
no => ' checked="checked"', |
|
); |
|
if ($available) { |
|
$checkedavailable{'yes'} = $checkedavailable{'no'}; |
|
$checkedavailable{'no'} = ''; |
|
} |
|
my $chgstr = ' onchange="javascript:reorderProctoring(this.form,'."'proctoring_pos_".$provider."'".');"'; |
|
$datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">' |
|
.'<select name="proctoring_pos_'.$provider.'"'.$chgstr.'>'; |
|
for (my $k=0; $k<$maxnum; $k++) { |
|
my $vpos = $k+1; |
|
my $selstr; |
|
if ($k == $i) { |
|
$selstr = ' selected="selected" '; |
|
} |
|
$datatable .= '<option value="'.$k.'"'.$selstr.'>'.$vpos.'</option>'; |
|
} |
|
if ($version eq '') { |
|
if ($provider eq 'proctorio') { |
|
$version = '1.0'; |
|
} elsif ($provider eq 'examity') { |
|
$version = '1.1'; |
|
} |
|
} |
|
if ($lifetime eq '') { |
|
$lifetime = '300'; |
|
} |
|
$datatable .= |
|
'</select>'.(' 'x2).'<b>'.$providernames{$provider}.'</b></span><br />'. |
|
'<span class="LC_nobreak">'.$lt{'avai'}.' '. |
|
'<label><input type="radio" name="proctoring_available_'.$provider.'" value="1"'.$onclickavailable.$checkedavailable{yes}.' />'.&mt('Yes').'</label> '."\n". |
|
'<label><input type="radio" name="proctoring_available_'.$provider.'" value="0"'.$onclickavailable.$checkedavailable{no}.' />'.&mt('No').'</label></span>'."\n". |
|
'</td>'. |
|
'<td colspan="2">'. |
|
'<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'base'}.'</legend>'. |
|
'<span class="LC_nobreak">'.$lt{'version'}.':<select name="proctoring_'.$provider.'_version">'. |
|
'<option value="'.$version.'" selected="selected">'.$version.'</option></select></span> '."\n". |
|
(' 'x2). |
|
'<span class="LC_nobreak">'.$lt{'sigmethod'}.':<select name="proctoring_'.$provider.'_sigmethod">'. |
|
'<option value="HMAC-SHA1" selected="selected">HMAC-SHA1</option>'. |
|
'<option value="HMAC-SHA256">HMAC-SHA256</option></select></span>'. |
|
(' 'x2). |
|
'<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="5" name="proctoring_'.$provider.'_lifetime" value="'.$lifetime.'" /></span> '."\n". |
|
'<br />'. |
|
'<span class="LC_nobreak">'.$lt{'url'}.':<input type="text" size="40" name="proctoring_'.$provider.'_url" value="'.$current{'url'}.'" /></span> '."\n". |
|
'<br />'. |
|
'<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="proctoring_'.$provider.'_key" value="'.$current{'key'}.'" /></span> '."\n". |
|
(' 'x2). |
|
'<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="proctoring_'.$provider.'_secret" value="'.$current{'secret'}.'" />'. |
|
'<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.proctoring_'.$provider.'_secret.type='."'text'".' } else { this.form.proctoring_'.$provider.'_secret.type='."'password'".' }" />'.$lt{'visible'}.'</label></span><br />'."\n"; |
|
$datatable .= '<span class="LC_nobreak">'.$lt{'icon'}.': '; |
|
if ($imgsrc) { |
|
$datatable .= $imgsrc. |
|
'<label><input type="checkbox" name="proctoring_image_del"'. |
|
' value="'.$provider.'" />'.&mt('Delete?').'</label></span> '. |
|
'<span class="LC_nobreak"> '.&mt('Replace:'); |
|
} |
|
$datatable .= ' '; |
|
if ($switchserver) { |
|
$datatable .= &mt('Upload to library server: [_1]',$switchserver); |
|
} else { |
|
$datatable .= '<input type="file" name="proctoring_image_'.$provider.'" value="" />'; |
|
} |
|
unless ($imgsrc) { |
|
$datatable .= '<br />('.&mt('if larger than 21x21 pixels, image will be scaled').')'; |
|
} |
|
$datatable .= '</fieldset>'."\n"; |
|
if (ref($requserfields{$provider}) eq 'ARRAY') { |
|
if (@{$requserfields{$provider}} > 0) { |
|
$datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'requ'}.'</legend>'; |
|
foreach my $field (@{$requserfields{$provider}}) { |
|
$datatable .= '<span class="LC_nobreak">'. |
|
'<label><input type="checkbox" name="proctoring_reqd_'.$provider.'" value="'.$field.'" checked="checked" disabled="disabled" />'. |
|
$lt{$field}.'</label>'; |
|
if ($field eq 'user') { |
|
my $seluserdom = ''; |
|
my $unseluserdom = ' selected="selected"'; |
|
if ($userincdom) { |
|
$seluserdom = $unseluserdom; |
|
$unseluserdom = ''; |
|
} |
|
$datatable .= ': '. |
|
'<select name="proctoring_userincdom_'.$provider.'">'. |
|
'<option value="0"'.$unseluserdom.'>'.$lt{'username'}.'</option>'. |
|
'<option value="1"'.$seluserdom.'>'.$lt{'uname:dom'}.'</option>'. |
|
'</select> '; |
|
} else { |
|
$datatable .= ' '; |
|
if ($field eq 'roles') { |
|
$showroles = 1; |
|
} |
|
} |
|
$datatable .= '</span> '; |
|
} |
|
} |
|
$datatable .= '</fieldset>'."\n"; |
|
} |
|
if (ref($optuserfields{$provider}) eq 'ARRAY') { |
|
if (@{$optuserfields{$provider}} > 0) { |
|
$datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'optu'}.'</legend>'; |
|
foreach my $field (@{$optuserfields{$provider}}) { |
|
my $checked; |
|
if ($checkedfields{$field}) { |
|
$checked = ' checked="checked"'; |
|
} |
|
$datatable .= '<span class="LC_nobreak">'. |
|
'<label><input type="checkbox" name="proctoring_optional_'.$provider.'" value="'.$field.'"'.$checked.' />'.$lt{$field}.'</label></span> '; |
|
} |
|
$datatable .= '</fieldset>'."\n"; |
|
} |
|
} |
|
if (ref($defaults{$provider}) eq 'ARRAY') { |
|
if (@{$defaults{$provider}}) { |
|
my (%options,@selectboxes); |
|
if (ref($extended{$provider}) eq 'HASH') { |
|
%options = %{$extended{$provider}}; |
|
} |
|
$datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'"><legend>'.$lt{'defa'}.'</legend>'; |
|
my ($rem,$numinrow,$dropdowns); |
|
if ($provider eq 'proctorio') { |
|
$datatable .= '<table>'; |
|
$numinrow = 4; |
|
} |
|
my $i = 0; |
|
foreach my $field (@{$defaults{$provider}}) { |
|
my $checked; |
|
if ($inuse{$field}) { |
|
$checked = ' checked="checked"'; |
|
} |
|
if ($provider eq 'examity') { |
|
if ($field eq 'display') { |
|
$datatable .= '<span class="LC_nobreak">'.&mt('Display target:'); |
|
foreach my $option ('iframe','tab','window') { |
|
my $checkdisp; |
|
if ($currentdef{'target'} eq $option) { |
|
$checkdisp = ' checked="checked"'; |
|
} |
|
$datatable .= '<label><input type="radio" name="proctoring_target_'.$provider.'" value="'.$option.'"'.$checkdisp.' />'. |
|
$fieldtitles{$option}.'</label>'.(' 'x2); |
|
} |
|
$datatable .= (' 'x4); |
|
foreach my $dimen ('width','height') { |
|
$datatable .= '<label>'.$fieldtitles{$dimen}.' '. |
|
'<input type="text" name="proctoring_'.$dimen.'_'.$provider.'" size="5" '. |
|
'value="'.$currentdef{$dimen}.'" /></label>'. |
|
(' 'x2); |
|
} |
|
$datatable .= '</span><br />'. |
|
'<div class="LC_left_float">'.$fieldtitles{'linktext'}.'<br />'. |
|
'<input type="text" name="proctoring_linktext_'.$provider.'" '. |
|
'size="25" value="'.$currentdef{'linktext'}.'" /></div>'. |
|
'<div class="LC_left_float">'.$fieldtitles{'explanation'}.'<br />'. |
|
'<textarea name="proctoring_explanation_'.$provider.'" rows="5" cols="40">'. |
|
$currentdef{'explanation'}. |
|
'</textarea></div><div style=""></div><br />'; |
|
} |
|
} else { |
|
if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) { |
|
my ($output,$selnone); |
|
unless ($checked) { |
|
$selnone = ' selected="selected"'; |
|
} |
|
$output .= '<span class="LC_nobreak">'.$fieldtitles{$field}.': '. |
|
'<select name="proctoring_defaults_'.$field.'_'.$provider.'">'. |
|
'<option value=""'.$selnone.'>'.&mt('Not in use').'</option>'; |
|
foreach my $option (@{$options{$field}}) { |
|
my $sel; |
|
if ($inuse{$field} eq $option) { |
|
$sel = ' selected="selected"'; |
|
} |
|
$output .= '<option value="'.$option.'"'.$sel.'>'.$fieldtitles{$option}.'</option>'; |
|
} |
|
$output .= '</select></span>'; |
|
push(@selectboxes,$output); |
|
} else { |
|
$rem = $i%($numinrow); |
|
if ($rem == 0) { |
|
if ($i > 0) { |
|
$datatable .= '</tr>'; |
|
} |
|
$datatable .= '<tr>'; |
|
} |
|
$datatable .= '<td class="LC_left_item">'. |
|
'<span class="LC_nobreak">'. |
|
'<label><input type="checkbox" name="proctoring_defaults_'.$provider.'" value="'.$field.'"'.$checked.' />'. |
|
$fieldtitles{$field}.'</label></span></td>'; |
|
$i++; |
|
} |
|
} |
|
} |
|
if ($provider eq 'proctorio') { |
|
if ($numinrow) { |
|
$rem = $i%$numinrow; |
|
} |
|
my $colsleft = $numinrow - $rem; |
|
if ($colsleft > 1) { |
|
$datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'; |
|
} else { |
|
$datatable .= '<td class="LC_left_item">'; |
|
} |
|
$datatable .= ' '. |
|
'</td></tr></table>'; |
|
if (@selectboxes) { |
|
$datatable .= '<hr /><table>'; |
|
$numinrow = 2; |
|
for (my $i=0; $i<@selectboxes; $i++) { |
|
$rem = $i%($numinrow); |
|
if ($rem == 0) { |
|
if ($i > 0) { |
|
$datatable .= '</tr>'; |
|
} |
|
$datatable .= '<tr>'; |
|
} |
|
$datatable .= '<td class="LC_left_item">'. |
|
$selectboxes[$i].'</td>'; |
|
} |
|
if ($numinrow) { |
|
$rem = $i%$numinrow; |
|
} |
|
$colsleft = $numinrow - $rem; |
|
if ($colsleft > 1) { |
|
$datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'; |
|
} else { |
|
$datatable .= '<td class="LC_left_item">'; |
|
} |
|
$datatable .= ' '. |
|
'</td></tr></table>'; |
|
} |
|
} |
|
$datatable .= '</fieldset>'; |
|
} |
|
if (ref($crsconf{$provider}) eq 'ARRAY') { |
|
$datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'. |
|
'<legend>'.&mt('Configurable in course').'</legend>'; |
|
my ($rem,$numinrow); |
|
if ($provider eq 'proctorio') { |
|
$datatable .= '<table>'; |
|
$numinrow = 4; |
|
} |
|
my $i = 0; |
|
foreach my $item (@{$crsconf{$provider}}) { |
|
my $name; |
|
if ($provider eq 'examity') { |
|
$name = $lt{'crs'.$item}; |
|
} elsif ($provider eq 'proctorio') { |
|
$name = $fieldtitles{$item}; |
|
$rem = $i%($numinrow); |
|
if ($rem == 0) { |
|
if ($i > 0) { |
|
$datatable .= '</tr>'; |
|
} |
|
$datatable .= '<tr>'; |
|
} |
|
$datatable .= '<td class="LC_left_item>'; |
|
} |
|
my $checked; |
|
if ($crsconfig{$item}) { |
|
$checked = ' checked="checked"'; |
|
} |
|
$datatable .= '<span class="LC_nobreak"><label>'. |
|
'<input type="checkbox" name="proctoring_crsconf_'.$provider.'" value="'.$item.'"'.$checked.' />'. |
|
$name.'</label></span>'; |
|
if ($provider eq 'examity') { |
|
$datatable .= ' '; |
|
} |
|
$datatable .= "\n"; |
|
$i++; |
|
} |
|
if ($provider eq 'proctorio') { |
|
if ($numinrow) { |
|
$rem = $i%$numinrow; |
|
} |
|
my $colsleft = $numinrow - $rem; |
|
if ($colsleft > 1) { |
|
$datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'; |
|
} else { |
|
$datatable .= '<td class="LC_left_item">'; |
|
} |
|
$datatable .= ' '. |
|
'</td></tr></table>'; |
|
} |
|
$datatable .= '</fieldset>'; |
|
} |
|
if ($showroles) { |
|
$datatable .= '<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'. |
|
'<legend>'.&mt('Role mapping').'</legend><table><tr>'; |
|
foreach my $role (@courseroles) { |
|
my ($selected,$selectnone); |
|
if (!$rolemaps{$role}) { |
|
$selectnone = ' selected="selected"'; |
|
} |
|
$datatable .= '<td style="text-align: center">'. |
|
&Apache::lonnet::plaintext($role,'Course').'<br />'. |
|
'<select name="proctoring_roles_'.$role.'_'.$provider.'">'. |
|
'<option value=""'.$selectnone.'>'.&mt('Select').'</option>'; |
|
foreach my $ltirole (@ltiroles) { |
|
unless ($selectnone) { |
|
if ($rolemaps{$role} eq $ltirole) { |
|
$selected = ' selected="selected"'; |
|
} else { |
|
$selected = ''; |
|
} |
|
} |
|
$datatable .= '<option value="'.$ltirole.'"'.$selected.'>'.$ltirole.'</option>'; |
|
} |
|
$datatable .= '</select></td>'; |
|
} |
|
$datatable .= '</tr></table></fieldset>'. |
|
'<fieldset class="proctoring_'.$provider.'" style="display:'.$optionsty.'">'. |
|
'<legend>'.&mt('Custom items sent on launch').'</legend>'. |
|
'<table><tr><th>'.&mt('Action').'</th><th>'.&mt('Name').'</th><th>'.&mt('Value').'</th></tr>'. |
|
'<tr><td></td><td>lms</td>'. |
|
'<td><input type="text" name="proctoring_customval_lms_'.$provider.'"'. |
|
' value="Loncapa" disabled="disabled"/></td></tr>'; |
|
if ((ref($settings) eq 'HASH') && (ref($settings->{$provider}) eq 'HASH') && |
|
(ref($settings->{$provider}->{'custom'}) eq 'HASH')) { |
|
my %custom = %{$settings->{$provider}->{'custom'}}; |
|
if (keys(%custom) > 0) { |
|
foreach my $key (sort(keys(%custom))) { |
|
next if ($key eq 'lms'); |
|
$datatable .= '<tr><td><span class="LC_nobreak">'. |
|
'<label><input type="checkbox" name="proctoring_customdel_'.$provider.'" value="'. |
|
$key.'" />'.&mt('Delete').'</label></span></td><td>'.$key.'</td>'. |
|
'<td><input type="text" name="proctoring_customval_'.$key.'_'.$provider.'"'. |
|
' value="'.$custom{$key}.'" /></td></tr>'; |
|
} |
|
} |
|
} |
|
$datatable .= '<tr><td><span class="LC_nobreak">'. |
|
'<label><input type="checkbox" name="proctoring_customadd" value="'.$provider.'" />'. |
|
&mt('Add more').'</label></span></td><td><input type="text" name="proctoring_custom_name_'.$provider.'" />'. |
|
'</td><td><input type="text" name="proctoring_custom_value_'.$provider.'" /></td></tr>'. |
|
'</table></fieldset></td></tr>'."\n"; |
|
} |
|
$datatable .= '</td></tr>'; |
|
} |
|
$itemcount ++; |
|
} |
|
} |
|
return $datatable; |
|
} |
|
|
|
sub proctoring_data { |
|
my $requserfields = { |
|
proctorio => ['user'], |
|
examity => ['roles','user'], |
|
}; |
|
my $optuserfields = { |
|
proctorio => ['fullname'], |
|
examity => ['fullname','firstname','lastname','email'], |
|
}; |
|
my $defaults = { |
|
proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic', |
|
'recordroomstart','verifyvideo','verifyaudio','verifydesktop', |
|
'verifyid','verifysignature','fullscreen','clipboard','tabslinks', |
|
'closetabs','onescreen','print','downloads','cache','rightclick', |
|
'reentry','calculator','whiteboard'], |
|
examity => ['display'], |
|
}; |
|
my $extended = { |
|
proctorio => { |
|
verifyid => ['verifyidauto','verifyidlive'], |
|
fullscreen => ['fullscreenlenient','fullscreenmoderate','fullscreensever'], |
|
tabslinks => ['notabs','linksonly'], |
|
reentry => ['noreentry','agentreentry'], |
|
calculator => ['calculatorbasic','calculatorsci'], |
|
}, |
|
examity => { |
|
display => { |
|
target => ['iframe','tab','window'], |
|
width => '', |
|
height => '', |
|
linktext => '', |
|
explanation => '', |
|
}, |
|
}, |
|
}; |
|
my $crsconf = { |
|
proctorio => ['recordvideo','recordaudio','recordscreen','recordwebtraffic', |
|
'recordroomstart','verifyvideo','verifyaudio','verifydesktop', |
|
'verifyid','verifysignature','fullscreen','clipboard','tabslinks', |
|
'closetabs','onescreen','print','downloads','cache','rightclick', |
|
'reentry','calculator','whiteboard'], |
|
examity => ['label','title','target','linktext','explanation','append'], |
|
}; |
|
my $courseroles = ['cc','in','ta','ep','st']; |
|
my $ltiroles = ['Instructor','ContentDeveloper','TeachingAssistant','Learner']; |
|
return ($requserfields,$optuserfields,$defaults,$extended,$crsconf,$courseroles,$ltiroles); |
|
} |
|
|
|
sub proctoring_titles { |
|
my ($item) = @_; |
|
my (%common_lt,%custom_lt); |
|
%common_lt = &Apache::lonlocal::texthash ( |
|
'avai' => 'Available?', |
|
'base' => 'Basic Settings', |
|
'requ' => 'User data required to be sent on launch', |
|
'optu' => 'User data optionally sent on launch', |
|
'udsl' => 'User data sent on launch', |
|
'defa' => 'Defaults for items configurable in course', |
|
'sigmethod' => 'Signature Method', |
|
'key' => 'Key', |
|
'lifetime' => 'Nonce lifetime (s)', |
|
'secret' => 'Secret', |
|
'icon' => 'Icon', |
|
'fullname' => 'Full Name', |
|
'visible' => 'Visible input', |
|
'username' => 'username', |
|
'user' => 'User', |
|
); |
|
if ($item eq 'proctorio') { |
|
%custom_lt = &Apache::lonlocal::texthash ( |
|
'version' => 'OAuth version', |
|
'url' => 'API URL', |
|
'uname:dom' => 'username-domain', |
|
); |
|
} elsif ($item eq 'examity') { |
|
%custom_lt = &Apache::lonlocal::texthash ( |
|
'version' => 'LTI Version', |
|
'url' => 'URL', |
|
'uname:dom' => 'username:domain', |
|
'msgtype' => 'Message Type', |
|
'firstname' => 'First Name', |
|
'lastname' => 'Last Name', |
|
'email' => 'E-mail', |
|
'roles' => 'Role', |
|
'crstarget' => 'Display target', |
|
'crslabel' => 'Course label', |
|
'crstitle' => 'Course title', |
|
'crslinktext' => 'Link Text', |
|
'crsexplanation' => 'Explanation', |
|
'crsappend' => 'Provider URL', |
|
); |
|
} |
|
my %lt = (%common_lt,%custom_lt); |
|
return %lt; |
|
} |
|
|
|
sub proctoring_fieldtitles { |
|
my ($item) = @_; |
|
if ($item eq 'proctorio') { |
|
return &Apache::lonlocal::texthash ( |
|
'recordvideo' => 'Record video', |
|
'recordaudio' => 'Record audio', |
|
'recordscreen' => 'Record screen', |
|
'recordwebtraffic' => 'Record web traffic', |
|
'recordroomstart' => 'Record room scan', |
|
'verifyvideo' => 'Verify webcam', |
|
'verifyaudio' => 'Verify microphone', |
|
'verifydesktop' => 'Verify desktop recording', |
|
'verifyid' => 'Photo ID verification', |
|
'verifysignature' => 'Require signature', |
|
'fullscreen' => 'Fullscreen', |
|
'clipboard' => 'Disable copy/paste', |
|
'tabslinks' => 'New tabs/windows', |
|
'closetabs' => 'Close other tabs', |
|
'onescreen' => 'Limit to single screen', |
|
'print' => 'Disable Printing', |
|
'downloads' => 'Disable Downloads', |
|
'cache' => 'Empty cache after exam', |
|
'rightclick' => 'Disable right click', |
|
'reentry' => 'Re-entry to exam', |
|
'calculator' => 'Onscreen calculator', |
|
'whiteboard' => 'Onscreen whiteboard', |
|
'verifyidauto' => 'Automated verification', |
|
'verifyidlive' => 'Live agent verification', |
|
'fullscreenlenient' => 'Forced, but can navigate away for up to 30s', |
|
'fullscreenmoderate' => 'Forced, but can navigate away for up to 15s', |
|
'fullscreensever' => 'Forced, navigation away ends exam', |
|
'notabs' => 'Disaallowed', |
|
'linksonly' => 'Allowed from links in exam', |
|
'noreentry' => 'Disallowed', |
|
'agentreentry' => 'Agent required for re-entry', |
|
'calculatorbasic' => 'Basic', |
|
'calculatorsci' => 'Scientific', |
|
); |
|
} elsif ($item eq 'examity') { |
|
return &Apache::lonlocal::texthash ( |
|
'target' => 'Display target', |
|
'window' => 'Window', |
|
'tab' => 'Tab', |
|
'iframe' => 'iFrame', |
|
'height' => 'Height (pixels)', |
|
'width' => 'Width (pixels)', |
|
'linktext' => 'Default Link Text', |
|
'explanation' => 'Default Explanation', |
|
'append' => 'Provider URL', |
|
); |
|
} |
|
} |
|
|
|
sub proctoring_providernames { |
|
return ( |
|
proctorio => 'Proctorio', |
|
examity => 'Examity', |
|
); |
|
} |
|
|
sub print_lti { |
sub print_lti { |
my ($dom,$settings,$rowtotal) = @_; |
my ($dom,$settings,$rowtotal) = @_; |
my $itemcount = 1; |
my $itemcount = 1; |
Line 5137 sub lti_options {
|
Line 5894 sub lti_options {
|
$output .= '</span></div>'. |
$output .= '</span></div>'. |
'<div class="LC_floatleft" style="display:'.$userfieldsty.';" id="lti_userfield_'.$num.'">'. |
'<div class="LC_floatleft" style="display:'.$userfieldsty.';" id="lti_userfield_'.$num.'">'. |
'<input type="text" name="lti_customuser_'.$num.'" '. |
'<input type="text" name="lti_customuser_'.$num.'" '. |
'value="'.$userfield.'" /></div></fieldset>'. |
'value="'.$userfield.'" /></div></fieldset>'. |
'<fieldset class="ltioption_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Mapping course roles').'</legend><table><tr>'; |
'<fieldset class="ltioption_'.$num.'" style="display:'.$optionsty.'"><legend>'.&mt('Mapping course roles').'</legend><table><tr>'; |
foreach my $ltirole (@lticourseroles) { |
foreach my $ltirole (@lticourseroles) { |
my ($selected,$selectnone); |
my ($selected,$selectnone); |
Line 12427 sub modify_ltitools {
|
Line 13184 sub modify_ltitools {
|
} |
} |
} |
} |
if (!$numconfig) { |
if (!$numconfig) { |
$resulttext .= &mt('None'); |
$resulttext .= ' '.&mt('None'); |
} |
} |
$resulttext .= '</li>'; |
$resulttext .= '</li>'; |
foreach my $item ('passback','roster') { |
foreach my $item ('passback','roster') { |
Line 12606 sub get_ltitools_id {
|
Line 13363 sub get_ltitools_id {
|
return ($id,$error); |
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 .= '<li><span class="LC_error">'.$error.'</span></li>'; |
|
} |
|
} elsif (exists($current{'image'})) { |
|
$confhash{$provider}{'image'} = $current{'image'}; |
|
} |
|
if (ref($requserfields{$provider}) eq 'ARRAY') { |
|
if (@{$requserfields{$provider}} > 0) { |
|
if (grep(/^user$/,@{$requserfields{$provider}})) { |
|
if ($env{'form.proctoring_userincdom_'.$provider}) { |
|
$confhash{$provider}{'incdom'} = 1; |
|
} |
|
unless ($current{'incdom'} eq $confhash{$provider}{'incdom'}) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
if (grep(/^roles$/,@{$requserfields{$provider}})) { |
|
$showroles = 1; |
|
} |
|
} |
|
} |
|
$confhash{$provider}{'fields'} = []; |
|
if (ref($optuserfields{$provider}) eq 'ARRAY') { |
|
if (@{$optuserfields{$provider}} > 0) { |
|
my @optfields = &Apache::loncommon::get_env_multiple('form.proctoring_optional_'.$provider); |
|
foreach my $field (@{$optuserfields{$provider}}) { |
|
if (grep(/^\Q$field\E$/,@optfields)) { |
|
push(@{$confhash{$provider}{'fields'}},$field); |
|
} |
|
} |
|
} |
|
if (ref($current{'fields'}) eq 'ARRAY') { |
|
unless ($changes{$provider}) { |
|
my @new = sort(@{$confhash{$provider}{'fields'}}); |
|
my @old = sort(@{$current{'fields'}}); |
|
my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old); |
|
if (@diffs) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} elsif (@{$confhash{$provider}{'fields'}}) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
if (ref($defaults{$provider}) eq 'ARRAY') { |
|
if (@{$defaults{$provider}} > 0) { |
|
my %options; |
|
if (ref($extended{$provider}) eq 'HASH') { |
|
%options = %{$extended{$provider}}; |
|
} |
|
my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_defaults_'.$provider); |
|
foreach my $field (@{$defaults{$provider}}) { |
|
if ((exists($options{$field})) && (ref($options{$field}) eq 'ARRAY')) { |
|
my $poss = $env{'form.proctoring_defaults_'.$field.'_'.$provider}; |
|
if (grep(/^\Q$poss\E$/,@{$options{$field}})) { |
|
push(@{$confhash{$provider}{'defaults'}},$poss); |
|
} |
|
} elsif ((exists($options{$field})) && (ref($options{$field}) eq 'HASH')) { |
|
foreach my $inner (keys(%{$options{$field}})) { |
|
if (ref($options{$field}{$inner}) eq 'ARRAY') { |
|
my $poss = $env{'form.proctoring_'.$inner.'_'.$provider}; |
|
if (grep(/^\Q$poss\E$/,@{$options{$field}{$inner}})) { |
|
$confhash{$provider}{'defaults'}{$inner} = $poss; |
|
} |
|
} else { |
|
$confhash{$provider}{'defaults'}{$inner} = $env{'form.proctoring_'.$inner.'_'.$provider}; |
|
} |
|
} |
|
} else { |
|
if (grep(/^\Q$field\E$/,@checked)) { |
|
push(@{$confhash{$provider}{'defaults'}},$field); |
|
} |
|
} |
|
} |
|
if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') { |
|
if (ref($current{'defaults'}) eq 'ARRAY') { |
|
unless ($changes{$provider}) { |
|
my @new = sort(@{$confhash{$provider}{'defaults'}}); |
|
my @old = sort(@{$current{'defaults'}}); |
|
my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old); |
|
if (@diffs) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} elsif (ref($current{'defaults'}) eq 'ARRAY') { |
|
if (@{$current{'defaults'}}) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') { |
|
if (ref($current{'defaults'}) eq 'HASH') { |
|
unless ($changes{$provider}) { |
|
foreach my $key (keys(%{$confhash{$provider}{'defaults'}})) { |
|
unless ($confhash{$provider}{'defaults'}{$key} eq $current{'defaults'}{$key}) { |
|
$changes{$provider} = 1; |
|
last; |
|
} |
|
} |
|
} |
|
unless ($changes{$provider}) { |
|
foreach my $key (keys(%{$current{'defaults'}})) { |
|
unless ($current{'defaults'}{$key} eq $confhash{$provider}{'defaults'}{$key}) { |
|
$changes{$provider} = 1; |
|
last; |
|
} |
|
} |
|
} |
|
} elsif (keys(%{$confhash{$provider}{'defaults'}})) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
} |
|
if (ref($crsconf{$provider}) eq 'ARRAY') { |
|
if (@{$crsconf{$provider}} > 0) { |
|
$confhash{$provider}{'crsconf'} = []; |
|
my @checked = &Apache::loncommon::get_env_multiple('form.proctoring_crsconf_'.$provider); |
|
foreach my $crsfield (@{$crsconf{$provider}}) { |
|
if (grep(/^\Q$crsfield\E$/,@checked)) { |
|
push(@{$confhash{$provider}{'crsconf'}},$crsfield); |
|
} |
|
} |
|
if (ref($current{'crsconf'}) eq 'ARRAY') { |
|
unless ($changes{$provider}) { |
|
my @new = sort(@{$confhash{$provider}{'crsconf'}}); |
|
my @old = sort(@{$current{'crsconf'}}); |
|
my @diffs = &Apache::loncommon::compare_arrays(\@new,\@old); |
|
if (@diffs) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} elsif (@{$confhash{$provider}{'crsconf'}}) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
if ($showroles) { |
|
$confhash{$provider}{'roles'} = {}; |
|
foreach my $role (@courseroles) { |
|
my $poss = $env{'form.proctoring_roles_'.$role.'_'.$provider}; |
|
if (grep(/^\Q$poss\E$/,@ltiroles)) { |
|
$confhash{$provider}{'roles'}{$role} = $poss; |
|
} |
|
} |
|
unless ($changes{$provider}) { |
|
if (ref($current{'roles'}) eq 'HASH') { |
|
foreach my $role (keys(%{$current{'roles'}})) { |
|
unless ($current{'roles'}{$role} eq $confhash{$provider}{'roles'}{$role}) { |
|
$changes{$provider} = 1; |
|
last |
|
} |
|
} |
|
unless ($changes{$provider}) { |
|
foreach my $role (keys(%{$confhash{$provider}{'roles'}})) { |
|
unless ($confhash{$provider}{'roles'}{$role} eq $current{'roles'}{$role}) { |
|
$changes{$provider} = 1; |
|
last; |
|
} |
|
} |
|
} |
|
} elsif (keys(%{$confhash{$provider}{'roles'}})) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
if (ref($current{'custom'}) eq 'HASH') { |
|
my @customdels = &Apache::loncommon::get_env_multiple('form.proctoring_customdel_'.$provider); |
|
foreach my $key (keys(%{$current{'custom'}})) { |
|
if (grep(/^\Q$key\E$/,@customdels)) { |
|
$changes{$provider} = 1; |
|
} else { |
|
$confhash{$provider}{'custom'}{$key} = $env{'form.proctoring_customval_'.$key.'_'.$provider}; |
|
if ($confhash{$provider}{'custom'}{$key} ne $current{'custom'}{$key}) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
} |
|
if ($customadds{$provider}) { |
|
my $name = $env{'form.proctoring_custom_name_'.$provider}; |
|
$name =~ s/(`)/'/g; |
|
$name =~ s/^\s+//; |
|
$name =~ s/\s+$//; |
|
my $value = $env{'form.proctoring_custom_value_'.$provider}; |
|
$value =~ s/(`)/'/g; |
|
$value =~ s/^\s+//; |
|
$value =~ s/\s+$//; |
|
if ($name ne '') { |
|
$confhash{$provider}{'custom'}{$name} = $value; |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
} |
|
if (@allpos > 0) { |
|
my $idx = 0; |
|
foreach my $provider (@allpos) { |
|
if ($provider ne '') { |
|
$confhash{$provider}{'order'} = $idx; |
|
unless ($changes{$provider}) { |
|
if (ref($domconfig{$action}) eq 'HASH') { |
|
if (ref($domconfig{$action}{$provider}) eq 'HASH') { |
|
if ($domconfig{$action}{$provider}{'order'} ne $idx) { |
|
$changes{$provider} = 1; |
|
} |
|
} |
|
} |
|
} |
|
$idx ++; |
|
} |
|
} |
|
} |
|
my %proc_hash = ( |
|
$action => { %confhash } |
|
); |
|
my $putresult = &Apache::lonnet::put_dom('configuration',\%proc_hash, |
|
$dom); |
|
if ($putresult eq 'ok') { |
|
my %proc_enchash = ( |
|
$action => { %encconfhash } |
|
); |
|
&Apache::lonnet::put_dom('encconfig',\%proc_enchash,$dom); |
|
if (keys(%changes) > 0) { |
|
my $cachetime = 24*60*60; |
|
my %procall = %confhash; |
|
foreach my $provider (keys(%procall)) { |
|
if (ref($encconfhash{$provider}) eq 'HASH') { |
|
foreach my $key ('key','secret') { |
|
$procall{$provider}{$key} = $encconfhash{$provider}{$key}; |
|
} |
|
} |
|
} |
|
&Apache::lonnet::do_cache_new('proctoring',$dom,\%procall,$cachetime); |
|
if (ref($lastactref) eq 'HASH') { |
|
$lastactref->{'proctoring'} = 1; |
|
} |
|
$resulttext = &mt('Configuration for Provider(s) with changes:').'<ul>'; |
|
my %bynum; |
|
foreach my $provider (sort(keys(%changes))) { |
|
my $position = $confhash{$provider}{'order'}; |
|
$bynum{$position} = $provider; |
|
} |
|
foreach my $pos (sort { $a <=> $b } keys(%bynum)) { |
|
my $provider = $bynum{$pos}; |
|
my %lt = &proctoring_titles($provider); |
|
my %fieldtitles = &proctoring_fieldtitles($provider); |
|
if (!$confhash{$provider}{'available'}) { |
|
$resulttext .= '<li>'.&mt('Proctoring integration unavailable for: [_1]','<b>'.$providernames{$provider}.'</b>').'</li>'; |
|
} else { |
|
$resulttext .= '<li>'.&mt('Proctoring integration available for: [_1]','<b>'.$providernames{$provider}.'</b>'); |
|
if ($confhash{$provider}{'image'}) { |
|
$resulttext .= ' '. |
|
'<img src="'.$confhash{$provider}{'image'}.'"'. |
|
' alt="'.&mt('Proctoring icon').'" />'; |
|
} |
|
$resulttext .= '<ul>'; |
|
my $position = $pos + 1; |
|
$resulttext .= '<li>'.&mt('Order: [_1]',$position).'</li>'; |
|
foreach my $key ('version','sigmethod','url','lifetime') { |
|
if ($confhash{$provider}{$key} ne '') { |
|
$resulttext .= '<li>'.$lt{$key}.': '.$confhash{$provider}{$key}.'</li>'; |
|
} |
|
} |
|
if ($encconfhash{$provider}{'key'} ne '') { |
|
$resulttext .= '<li>'.$lt{'key'}.': '.$encconfhash{$provider}{'key'}.'</li>'; |
|
} |
|
if ($encconfhash{$provider}{'secret'} ne '') { |
|
$resulttext .= '<li>'.$lt{'secret'}.': '; |
|
my $num = length($encconfhash{$provider}{'secret'}); |
|
$resulttext .= ('*'x$num).'</li>'; |
|
} |
|
my (@fields,$showroles); |
|
if (ref($requserfields{$provider}) eq 'ARRAY') { |
|
push(@fields,@{$requserfields{$provider}}); |
|
} |
|
if (ref($confhash{$provider}{'fields'}) eq 'ARRAY') { |
|
push(@fields,@{$confhash{$provider}{'fields'}}); |
|
} elsif (ref($confhash{$provider}{'fields'}) eq 'HASH') { |
|
push(@fields,(keys(%{$confhash{$provider}{'fields'}}))); |
|
} |
|
if (@fields) { |
|
if (grep(/^roles$/,@fields)) { |
|
$showroles = 1; |
|
} |
|
$resulttext .= '<li>'.$lt{'udsl'}.': "'. |
|
join('", "', map { $lt{$_}; } @fields).'"</li>'; |
|
} |
|
if (ref($requserfields{$provider}) eq 'ARRAY') { |
|
if (grep(/^user$/,@{$requserfields{$provider}})) { |
|
if ($confhash{$provider}{'incdom'}) { |
|
$resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'uname:dom'}).'</li>'; |
|
} else { |
|
$resulttext .= '<li>'.&mt('[_1] sent as [_2]',$lt{'user'},$lt{'username'}).'</li>'; |
|
} |
|
} |
|
} |
|
if (ref($confhash{$provider}{'defaults'}) eq 'ARRAY') { |
|
if (@{$confhash{$provider}{'defaults'}} > 0) { |
|
$resulttext .= '<li>'.$lt{'defa'}; |
|
foreach my $field (@{$confhash{$provider}{'defaults'}}) { |
|
$resulttext .= ' "'.$fieldtitles{$field}.'",'; |
|
} |
|
$resulttext =~ s/,$//; |
|
$resulttext .= '</li>'; |
|
} |
|
} elsif (ref($confhash{$provider}{'defaults'}) eq 'HASH') { |
|
if (keys(%{$confhash{$provider}{'defaults'}})) { |
|
$resulttext .= '<li>'.$lt{'defa'}.': <ul>'; |
|
foreach my $key (sort(keys(%{$confhash{$provider}{'defaults'}}))) { |
|
if ($confhash{$provider}{'defaults'}{$key} ne '') { |
|
$resulttext .= '<li>'.$fieldtitles{$key}.' = '.$confhash{$provider}{'defaults'}{$key}.'</li>'; |
|
} |
|
} |
|
$resulttext .= '</ul></li>'; |
|
} |
|
} |
|
if (ref($crsconf{$provider}) eq 'ARRAY') { |
|
if (@{$crsconf{$provider}} > 0) { |
|
$resulttext .= '<li>'.&mt('Configurable in course:'); |
|
my $numconfig = 0; |
|
if (ref($confhash{$provider}{'crsconf'}) eq 'ARRAY') { |
|
if (@{$confhash{$provider}{'crsconf'}} > 0) { |
|
foreach my $field (@{$confhash{$provider}{'crsconf'}}) { |
|
$numconfig ++; |
|
if ($provider eq 'examity') { |
|
$resulttext .= ' "'.$lt{'crs'.$field}.'",'; |
|
} else { |
|
$resulttext .= ' "'.$fieldtitles{$field}.'",'; |
|
} |
|
} |
|
$resulttext =~ s/,$//; |
|
} |
|
} |
|
if (!$numconfig) { |
|
$resulttext .= ' '.&mt('None'); |
|
} |
|
$resulttext .= '</li>'; |
|
} |
|
} |
|
if ($showroles) { |
|
if (ref($confhash{$provider}{'roles'}) eq 'HASH') { |
|
my $rolemaps; |
|
foreach my $role (@courseroles) { |
|
if ($confhash{$provider}{'roles'}{$role}) { |
|
$rolemaps .= (' 'x2).&Apache::lonnet::plaintext($role,'Course').'='. |
|
$confhash{$provider}{'roles'}{$role}.','; |
|
} |
|
} |
|
if ($rolemaps) { |
|
$rolemaps =~ s/,$//; |
|
$resulttext .= '<li>'.&mt('Role mapping:').$rolemaps.'</li>'; |
|
} |
|
} |
|
} |
|
if (ref($confhash{$provider}{'custom'}) eq 'HASH') { |
|
my $customlist; |
|
if (keys(%{$confhash{$provider}{'custom'}})) { |
|
foreach my $key (sort(keys(%{$confhash{$provider}{'custom'}}))) { |
|
$customlist .= $key.'='.$confhash{$provider}{'custom'}{$key}.', '; |
|
} |
|
$customlist =~ s/,$//; |
|
} |
|
if ($customlist) { |
|
$resulttext .= '<li>'.&mt('Custom items').': '.$customlist.'</li>'; |
|
} |
|
} |
|
$resulttext .= '</ul></li>'; |
|
} |
|
} |
|
$resulttext .= '</ul>'; |
|
} else { |
|
$resulttext = &mt('No changes made.'); |
|
} |
|
} else { |
|
$errors .= '<li><span class="LC_error">'.&mt('Failed to save changes').'</span></li>'; |
|
} |
|
if ($errors) { |
|
$resulttext .= &mt('The following errors occurred: ').'<ul>'. |
|
$errors.'</ul>'; |
|
} |
|
return $resulttext; |
|
} |
|
|
|
sub process_proctoring_image { |
|
my ($r,$dom,$confname,$caller,$provider,$configuserok,$switchserver,$author_ok) = @_; |
|
my $filename = $env{'form.'.$caller.'.filename'}; |
|
my ($error,$url); |
|
my ($width,$height) = (21,21); |
|
if ($configuserok eq 'ok') { |
|
if ($switchserver) { |
|
$error = &mt('Upload of Remote Proctoring Provider icon is not permitted to this server: [_1]', |
|
$switchserver); |
|
} elsif ($author_ok eq 'ok') { |
|
my ($result,$imageurl,$madethumb) = |
|
&publishlogo($r,'upload',$caller,$dom,$confname, |
|
"proctoring/$provider/icon",$width,$height); |
|
if ($result eq 'ok') { |
|
if ($madethumb) { |
|
my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$}); |
|
my $imagethumb = "$path/tn-".$imagefile; |
|
$url = $imagethumb; |
|
} else { |
|
$url = $imageurl; |
|
} |
|
} else { |
|
$error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result); |
|
} |
|
} else { |
|
$error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok); |
|
} |
|
} else { |
|
$error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok); |
|
} |
|
return ($url,$error); |
|
} |
|
|
sub modify_lti { |
sub modify_lti { |
my ($r,$dom,$action,$lastactref,%domconfig) = @_; |
my ($r,$dom,$action,$lastactref,%domconfig) = @_; |
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); |
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); |
Line 19589 function balancerChange(balnum,baltotal,
|
Line 20876 function balancerChange(balnum,baltotal,
|
END |
END |
} |
} |
|
|
|
|
sub new_spares_js { |
sub new_spares_js { |
my @sparestypes = ('primary','default'); |
my @sparestypes = ('primary','default'); |
my $types = join("','",@sparestypes); |
my $types = join("','",@sparestypes); |
Line 19662 function updateNewSpares(formname,lonhos
|
Line 20950 function updateNewSpares(formname,lonhos
|
function checkNewSpares(lonhost,type) { |
function checkNewSpares(lonhost,type) { |
var newSpare = document.getElementById('newspare_'+type+'_'+lonhost); |
var newSpare = document.getElementById('newspare_'+type+'_'+lonhost); |
var chosen = newSpare.options[newSpare.selectedIndex].value; |
var chosen = newSpare.options[newSpare.selectedIndex].value; |
if (chosen != '') { |
if (chosen != '') { |
var othertype; |
var othertype; |
var othernewSpare; |
var othernewSpare; |
if (type == 'primary') { |
if (type == 'primary') { |
Line 19796 function toggleDisplay(domForm,caller) {
|
Line 21084 function toggleDisplay(domForm,caller) {
|
var dispval = 'block'; |
var dispval = 'block'; |
var selfcreateRegExp = /^cancreate_emailverified/; |
var selfcreateRegExp = /^cancreate_emailverified/; |
if (caller == 'emailoptions') { |
if (caller == 'emailoptions') { |
optionsElement = domForm.cancreate_email; |
optionsElement = domForm.cancreate_email; |
} |
} |
if (caller == 'studentsubmission') { |
if (caller == 'studentsubmission') { |
optionsElement = domForm.postsubmit; |
optionsElement = domForm.postsubmit; |