--- loncom/interface/domainprefs.pm 2018/11/18 22:50:52 1.341
+++ loncom/interface/domainprefs.pm 2020/02/07 20:42:50 1.370
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.341 2018/11/18 22:50:52 raeburn Exp $
+# $Id: domainprefs.pm,v 1.370 2020/02/07 20:42:50 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -219,7 +219,7 @@ sub handler {
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor','selfenrollment','inststatus',
- 'ltitools','ssl','trust','lti'],$dom);
+ 'ltitools','ssl','trust','lti','privacy','passwords'],$dom);
my %encconfig =
&Apache::lonnet::get_dom('encconfig',['ltitools','lti'],$dom);
if (ref($domconfig{'ltitools'}) eq 'HASH') {
@@ -246,8 +246,8 @@ sub handler {
}
}
}
- my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
- 'autoupdate','autocreate','directorysrch','contacts',
+ my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll',
+ 'autoupdate','autocreate','directorysrch','contacts','privacy',
'usercreation','selfcreation','usermodification','scantron',
'requestcourses','requestauthor','coursecategories',
'serverstatuses','helpsettings','coursedefaults',
@@ -291,13 +291,25 @@ sub handler {
help => 'Domain_Configuration_LangTZAuth',
header => [{col1 => 'Setting',
col2 => 'Value'},
- {col1 => 'Internal Authentication',
- col2 => 'Value'},
{col1 => 'Institutional user types',
col2 => 'Name displayed'}],
print => \&print_defaults,
modify => \&modify_defaults,
},
+ 'passwords' =>
+ { text => 'Passwords (Internal authentication)',
+ help => 'Domain_Configuration_Passwords',
+ header => [{col1 => 'Resetting Forgotten Password',
+ col2 => 'Settings'},
+ {col1 => 'Encryption of Stored Passwords (Internal Auth)',
+ col2 => 'Settings'},
+ {col1 => 'Rules for LON-CAPA Passwords',
+ col2 => 'Settings'},
+ {col1 => 'Course Owner Changing Student Passwords',
+ col2 => 'Settings'}],
+ print => \&print_passwords,
+ modify => \&modify_passwords,
+ },
'quotas' =>
{ text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
help => 'Domain_Configuration_Quotas',
@@ -394,11 +406,12 @@ sub handler {
modify => \&modify_usermodification,
},
'scantron' =>
- { text => 'Bubblesheet format file',
+ { text => 'Bubblesheet format',
help => 'Domain_Configuration_Scantron_Format',
- header => [ {col1 => 'Item',
- col2 => '',
- }],
+ header => [ {col1 => 'Bubblesheet format file',
+ col2 => ''},
+ {col1 => 'Bubblesheet data upload formats',
+ col2 => 'Settings'}],
print => \&print_scantron,
modify => \&modify_scantron,
},
@@ -484,10 +497,16 @@ sub handler {
modify => \&modify_selfenrollment,
},
'privacy' =>
- {text => 'User Privacy',
+ {text => 'Availability of User Information',
help => 'Domain_Configuration_User_Privacy',
- header => [{col1 => 'Setting',
- col2 => 'Value',}],
+ header => [{col1 => 'Role assigned in different domain',
+ col2 => 'Approval options'},
+ {col1 => 'Role assigned in different domain to user of type',
+ col2 => 'User information available in that domain'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by privileged user'},
+ {col1 => "Role assigned in user's domain",
+ col2 => 'Information viewable by unprivileged user'}],
print => \&print_privacy,
modify => \&modify_privacy,
},
@@ -627,6 +646,9 @@ END
if (grep(/^contacts$/,@actions)) {
$js .= &contacts_javascript();
}
+ if (grep(/^scantron$/,@actions)) {
+ $js .= &scantron_javascript();
+ }
&Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js);
} else {
# check if domconfig user exists for the domain.
@@ -755,6 +777,10 @@ sub process_changes {
$output = &modify_trust($dom,$lastactref,%domconfig);
} elsif ($action eq 'lti') {
$output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'privacy') {
+ $output = &modify_privacy($dom,%domconfig);
+ } elsif ($action eq 'passwords') {
+ $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
}
return $output;
}
@@ -767,6 +793,8 @@ sub print_config_box {
$output = &coursecategories_javascript($settings);
} elsif ($action eq 'defaults') {
$output = &defaults_javascript($settings);
+ } elsif ($action eq 'passwords') {
+ $output = &passwords_javascript();
} elsif ($action eq 'helpsettings') {
my (%privs,%levelscurrent);
my %full=();
@@ -803,6 +831,7 @@ sub print_config_box {
if ($numheaders > 1) {
my $colspan = '';
my $rightcolspan = '';
+ my $leftnobr = '';
if (($action eq 'rolecolors') || ($action eq 'defaults') ||
($action eq 'directorysrch') ||
(($action eq 'login') && ($numheaders < 4))) {
@@ -811,12 +840,15 @@ sub print_config_box {
if ($action eq 'usersessions') {
$rightcolspan = ' colspan="3"';
}
+ if ($action eq 'passwords') {
+ $leftnobr = ' LC_nobreak';
+ }
$output .= '
- '.&mt($item->{'header'}->[0]->{'col1'}).'
+ '.&mt($item->{'header'}->[0]->{'col1'}).'
'.&mt($item->{'header'}->[0]->{'col2'}).'
';
$rowtotal ++;
@@ -824,10 +856,14 @@ sub print_config_box {
($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
- ($action eq 'contacts')) {
+ ($action eq 'contacts') || ($action eq 'privacy')) {
$output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'coursecategories') {
$output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
+ } elsif ($action eq 'scantron') {
+ $output .= $item->{'print'}->($r,'top',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'login') {
if ($numheaders == 4) {
$colspan = ' colspan="2"';
@@ -855,12 +891,16 @@ sub print_config_box {
if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
($action eq 'usersessions') || ($action eq 'coursecategories') ||
- ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
+ ($action eq 'trust') || ($action eq 'contacts') ||
+ ($action eq 'privacy') || ($action eq 'passwords')) {
+ my $leftnobr = ' LC_nobreak';
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
$colspan = ' colspan="2"';
} elsif ($action eq 'trust') {
$output .= $item->{'print'}->('shared',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);
} else {
$output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
}
@@ -906,8 +946,13 @@ sub print_config_box {
'."\n";
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
- } elsif ($action eq 'contacts') {
- $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal).'
+ } elsif (($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'passwords')) {
+ if ($action eq 'passwords') {
+ $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal);
+ } else {
+ $output .= $item->{'print'}->('lower',$dom,$settings,\$rowtotal);
+ }
+ $output .= '
@@ -916,9 +961,14 @@ sub print_config_box {
- '.&mt($item->{'header'}->[3]->{'col1'}).'
- '.&mt($item->{'header'}->[3]->{'col2'}).' '.
- $item->{'print'}->('bottom',$dom,$settings,\$rowtotal).'
+ '.&mt($item->{'header'}->[3]->{'col1'}).'
+ '.&mt($item->{'header'}->[3]->{'col2'}).' '."\n";
+ if ($action eq 'passwords') {
+ $output .= $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal);
+ } else {
+ $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+ }
+ $output .= '
@@ -932,6 +982,8 @@ sub print_config_box {
($action eq 'defaults') || ($action eq 'directorysrch') ||
($action eq 'helpsettings')) {
$output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'scantron') {
+ $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'ssl') {
$output .= $item->{'print'}->('connto',$dom,$settings,\$rowtotal).'
@@ -1113,8 +1165,6 @@ sub print_config_box {
($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
($action eq 'ltitools') || ($action eq 'lti')) {
$output .= $item->{'print'}->($dom,$settings,\$rowtotal);
- } elsif ($action eq 'scantron') {
- $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
}
}
$output .= '
@@ -2836,17 +2886,44 @@ sub lti_toggle_js {
// {$item}) eq 'HASH') {
$key = $settings->{$item}->{'key'};
$secret = $settings->{$item}->{'secret'};
$lifetime = $settings->{$item}->{'lifetime'};
$consumer = $settings->{$item}->{'consumer'};
+ $requser = $settings->{$item}->{'requser'};
$current = $settings->{$item};
}
+ my $onclickrequser = ' onclick="toggleLTI(this.form,'."'requser','$i'".');"';
+ my %checkedrequser = (
+ yes => ' checked="checked"',
+ no => '',
+ );
+ if (!$requser) {
+ $checkedrequser{'no'} = $checkedrequser{'yes'};
+ $checkedrequser{'yes'} = '';
+ }
my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_".$item."'".');"';
$datatable .= ''
.'';
@@ -4792,13 +4880,17 @@ sub print_lti {
''.
''.&mt('Required settings').' '.
''.$lt{'consumer'}.
- ': '.
+ ': '.
(' 'x2).
''.$lt{'version'}.':'.
'1.1 '.
(' 'x2).
''.$lt{'lifetime'}.': '.
+ 'value="'.$lifetime.'" size="3" />'.
+ (' 'x2).
+ ''.$lt{'requser'}.':'.
+ ' '.&mt('Yes').' '."\n".
+ ' '.&mt('No').' '."\n".
' '.
''.$lt{'key'}.
': '.
@@ -4829,12 +4921,16 @@ sub print_lti {
''.
''.&mt('Required settings').' '.
''.$lt{'consumer'}.
- ': '."\n".
+ ': '."\n".
(' 'x2).
''.$lt{'version'}.':'.
'1.1 '."\n".
(' 'x2).
- ''.$lt{'lifetime'}.': '."\n".
+ ''.$lt{'lifetime'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'requser'}.':'.
+ ' '.&mt('Yes').' '."\n".
+ ' '.&mt('No').' '."\n".
' '.
''.$lt{'key'}.': '."\n".
(' 'x2).
@@ -4853,22 +4949,23 @@ sub lti_names {
'url' => 'URL',
'key' => 'Key',
'lifetime' => 'Nonce lifetime (s)',
- 'consumer' => 'LTI Consumer',
+ 'consumer' => 'Consumer',
'secret' => 'Secret',
+ 'requser' => "User's identity sent",
'email' => 'Email address',
'sourcedid' => 'User ID',
'other' => 'Other',
'passback' => 'Can return grades to Consumer:',
'roster' => 'Can retrieve roster from Consumer:',
'topmenu' => 'Display LON-CAPA page header',
- 'inlinemenu'=> 'Display LON-CAPA inline menu',
+ 'inlinemenu'=> 'Display LON-CAPA inline menu',
);
return %lt;
}
sub lti_options {
my ($num,$current,$itemcount,%lt) = @_;
- my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield);
+ my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield,$callback);
$checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
$checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
$checked{'makecrs'}{'N'} = ' checked="checked"';
@@ -4886,7 +4983,9 @@ sub lti_options {
my $crsfieldsty = 'none';
my $crssecfieldsty = 'none';
my $secsrcfieldsty = 'none';
+ my $callbacksty = 'none';
my $passbacksty = 'none';
+ my $optionsty = 'block';
my $lcauthparm;
my $lcauthparmstyle = 'display:none';
my $lcauthparmtext;
@@ -4895,6 +4994,9 @@ sub lti_options {
my %menutitles = <imenu_titles();
if (ref($current) eq 'HASH') {
+ if (!$current->{'requser'}) {
+ $optionsty = 'none';
+ }
if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
$checked{'mapuser'}{'sourcedid'} = '';
if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
@@ -4920,7 +5022,7 @@ sub lti_options {
$checked{'mapcrstype'}{$type} = ' checked="checked"';
}
}
- if ($current->{'makecrs'}) {
+ if ($current->{'makecrs'}) {
$checked{'makecrs'}{'Y'} = ' checked="checked"';
}
if (ref($current->{'makeuser'}) eq 'ARRAY') {
@@ -4961,6 +5063,13 @@ sub lti_options {
} else {
$checked{'crssec'}{'N'} = ' checked="checked"';
}
+ if ($current->{'callback'} ne '') {
+ $callback = $current->{'callback'};
+ $checked{'callback'}{'Y'} = ' checked="checked"';
+ $callbacksty = 'inline-block';
+ } else {
+ $checked{'callback'}{'N'} = ' checked="checked"';
+ }
if ($current->{'topmenu'}) {
$checked{'topmenu'}{'Y'} = ' checked="checked"';
} else {
@@ -4986,6 +5095,7 @@ sub lti_options {
} else {
$checked{'makecrs'}{'N'} = ' checked="checked"';
$checked{'crssec'}{'N'} = ' checked="checked"';
+ $checked{'callback'}{'N'} = ' checked="checked"';
$checked{'topmenu'}{'N'} = ' checked="checked"';
$checked{'inlinemenu'}{'Y'} = ' checked="checked"';
$checked{'menuitem'}{'grades'} = ' checked="checked"';
@@ -5014,10 +5124,11 @@ sub lti_options {
my $onclickuser = ' onclick="toggleLTI(this.form,'."'user','$num'".');"';
my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
+ my $onclickcallback = ' onclick="toggleLTI(this.form,'."'callback','$num'".');"';
my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
my $onclicklcauth = ' onclick="toggleLTI(this.form,'."'lcauth','$num'".')"';
my $onclickmenu = ' onclick="toggleLTI(this.form,'."'lcmenu','$num'".');"';
- my $output = ''.&mt('Mapping users').' '.
+ my $output = ''.&mt('Mapping users').' '.
''.&mt('LON-CAPA username').': ';
foreach my $option ('sourcedid','email','other') {
$output .= ' '.
'
'.
- ''.&mt('Mapping course roles').' '.
- ''.&mt('Mapping courses').' '.
+ ''.&mt('Mapping courses').' '.
''.
+ '
'.
+ ''.&mt('Callback on logout').': '.
+ ' '.&mt('No').' '.(' 'x2).
+ ' '.&mt('Yes').'
'.
+ ''.
+ ''.&mt('Parameter').': '.
+ ' '.
+ '
'.
+ ''.&mt('Course defaults (Course Coordinator can override)').' '.
''.$lt{'topmenu'}.': '.
' '.&mt('No').' '.(' 'x2).
@@ -5219,7 +5340,6 @@ sub print_coursedefaults {
mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver',
);
my %staticdefaults = (
- texengine => 'MathJax',
anonsurvey_threshold => 10,
uploadquota => 500,
postsubmit => 60,
@@ -5233,7 +5353,7 @@ sub print_coursedefaults {
'canclone' => 'none',
);
@toggles = ('canuse_pdfforms','uselcmath','usejsme');
- my $deftex = $staticdefaults{'texengine'};
+ my $deftex = $Apache::lonnet::deftex;
if (ref($settings) eq 'HASH') {
if ($settings->{'texengine'}) {
if ($settings->{'texengine'} =~ /^(MathJax|mimetex|tth)$/) {
@@ -5717,6 +5837,577 @@ sub print_validation_rows {
return $datatable;
}
+sub print_privacy {
+ my ($position,$dom,$settings,$rowtotal) = @_;
+ my ($datatable,$css_class,$numinrow,@items,%names,$othertitle,$usertypes,$types);
+ my $itemcount = 0;
+ unless ($position eq 'top') {
+ @items = ('domain','author','course','community');
+ %names = &Apache::lonlocal::texthash (
+ domain => 'Assigned domain role(s)',
+ author => 'Assigned co-author role(s)',
+ course => 'Assigned course role(s)',
+ community => 'Assigned community role',
+ );
+ $numinrow = 4;
+ ($othertitle,$usertypes,$types) =
+ &Apache::loncommon::sorted_inst_types($dom);
+ }
+ if (($position eq 'top') || ($position eq 'middle')) {
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ if ($position eq 'top') {
+ my %curr;
+ my @options = ('none','user','domain','auto');
+ my %titles = &Apache::lonlocal::texthash (
+ none => 'Not allowed',
+ user => 'User authorizes',
+ domain => 'DC authorizes',
+ auto => 'Unrestricted',
+ instdom => 'Other domain shares institution/provider',
+ extdom => 'Other domain has different institution/provider',
+ );
+ my %names = &Apache::lonlocal::texthash (
+ domain => 'Domain role',
+ author => 'Co-author role',
+ course => 'Course role',
+ community => 'Community role',
+ );
+ my $primary_id = &Apache::lonnet::domain($dom,'primary');
+ my $intdom = &Apache::lonnet::internet_dom($primary_id);
+ foreach my $domtype ('instdom','extdom') {
+ my (%checked,$skip);
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{$domtype}.' '.
+ '';
+ if ($domtype eq 'instdom') {
+ unless (@instdoms > 1) {
+ $datatable .= &mt('Nothing to set, as no domains besides [_1] are hosted by [_2]',$dom,$intdom);
+ $skip = 1;
+ }
+ } elsif ($domtype eq 'extdom') {
+ if (keys(%by_location) == 0) {
+ $datatable .= &mt('Nothing to set, as no other hosts besides [_1]',$intdom);
+ $skip = 1;
+ }
+ }
+ unless ($skip) {
+ foreach my $roletype ('domain','author','course','community') {
+ $checked{'auto'} = ' checked="checked"';
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{approval}) eq 'HASH') {
+ if (ref($settings->{approval}->{$domtype}) eq 'HASH') {
+ if ($settings->{approval}->{$domtype}->{$roletype}=~ /^(none|user|domain)$/) {
+ $checked{$1} = ' checked="checked"';
+ $checked{'auto'} = '';
+ }
+ }
+ }
+ }
+ $datatable .= ''.$names{$roletype}.' ';
+ foreach my $option (@options) {
+ $datatable .= ''.
+ ' '.$titles{$option}.
+ ' ';
+ }
+ $datatable .= ' ';
+ }
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ } elsif ($position eq 'middle') {
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ $datatable .= &modifiable_userdata_row('privacy','othdom_'.$item,$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$usertypes->{$item});
+ $itemcount ++;
+ }
+ }
+ $datatable .= &modifiable_userdata_row('privacy','othdom_default',$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$othertitle);
+ $itemcount ++;
+ } else {
+ my (@insttypes,%insttitles);
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ @insttypes = @{$types};
+ %insttitles = %{$usertypes};
+ }
+ foreach my $item (@insttypes,'default') {
+ my $title;
+ if ($item eq 'default') {
+ $title = $othertitle;
+ } else {
+ $title = $insttitles{$item};
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.
+ ''.$title.' '.
+ ''.
+ &mt('Nothing to set here, as there are no other domains').
+ ' ';
+ $itemcount ++;
+ }
+ }
+ }
+ } else {
+ my $prefix;
+ if ($position eq 'lower') {
+ $prefix = 'priv';
+ } else {
+ $prefix = 'unpriv';
+ }
+ foreach my $item (@items) {
+ $datatable .= &modifiable_userdata_row('privacy',$prefix.'_'.$item,$settings,
+ $numinrow,$itemcount,'','','','','',
+ '',$names{$item});
+ $itemcount ++;
+ }
+ }
+ if (ref($rowtotal)) {
+ $$rowtotal += $itemcount;
+ }
+ return $datatable;
+}
+
+sub print_passwords {
+ my ($position,$dom,$confname,$settings,$rowtotal) = @_;
+ my ($datatable,$css_class);
+ my $itemcount = 0;
+ my %titles = &Apache::lonlocal::texthash (
+ captcha => '"Forgot Password" CAPTCHA validation',
+ link => 'Reset link expiration (hours)',
+ case => 'Case-sensitive usernames/e-mail',
+ prelink => 'Information required (form 1)',
+ postlink => 'Information required (form 2)',
+ emailsrc => 'LON-CAPA e-mail address type(s)',
+ customtext => 'Domain specific text (HTML)',
+ intauth_cost => 'Encryption cost for bcrypt (positive integer)',
+ intauth_check => 'Check bcrypt cost if authenticated',
+ intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
+ permanent => 'Permanent e-mail address',
+ critical => 'Critical notification address',
+ notify => 'Notification address',
+ min => 'Minimum password length',
+ max => 'Maximum password length',
+ chars => 'Required characters',
+ expire => 'Password expiration (days)',
+ numsaved => 'Number of previous passwords to save and disallow reuse',
+ );
+ if ($position eq 'top') {
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my $shownlinklife = 2;
+ my $prelink = 'both';
+ my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {
+ $shownlinklife = $settings->{resetlink};
+ }
+ if (ref($settings->{resetcase}) eq 'ARRAY') {
+ map { $casesens{$_} = 1; } (@{$settings->{resetcase}});
+ }
+ if ($settings->{resetprelink} =~ /^(both|either)$/) {
+ $prelink = $settings->{resetprelink};
+ }
+ if (ref($settings->{resetpostlink}) eq 'HASH') {
+ %postlink = %{$settings->{resetpostlink}};
+ }
+ if (ref($settings->{resetemail}) eq 'ARRAY') {
+ map { $emailsrc{$_} = 1; } (@{$settings->{resetemail}});
+ }
+ if ($settings->{resetremove}) {
+ $nostdtext = 1;
+ }
+ if ($settings->{resetcustom}) {
+ $customurl = $settings->{resetcustom};
+ }
+ } else {
+ if (ref($types) eq 'ARRAY') {
+ foreach my $item (@{$types}) {
+ $casesens{$item} = 1;
+ $postlink{$item} = ['username','email'];
+ }
+ }
+ $casesens{'default'} = 1;
+ $postlink{'default'} = ['username','email'];
+ $prelink = 'both';
+ %emailsrc = (
+ permanent => 1,
+ critical => 1,
+ notify => 1,
+ );
+ }
+ $datatable = &captcha_choice('passwords',$settings,$$rowtotal);
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'link'}.' '.
+ ''.
+ ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'case'}.' '.
+ '';
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ my $checkedcase;
+ if ($casesens{$item}) {
+ $checkedcase = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$usertypes->{$item}.' '.
+ ' ';
+ }
+ }
+ my $checkedcase;
+ if ($casesens{'default'}) {
+ $checkedcase = ' checked="checked"';
+ }
+ $datatable .= ' '.
+ $othertitle.' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my %checkedpre = (
+ both => ' checked="checked"',
+ either => '',
+ );
+ if ($prelink eq 'either') {
+ $checkedpre{either} = ' checked="checked"';
+ $checkedpre{both} = '';
+ }
+ $datatable .= ''.$titles{'prelink'}.' '.
+ ''.
+ ' '.
+ &mt('Both username and e-mail address').' '.
+ ''.
+ ' '.
+ &mt('Either username or e-mail address').' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'postlink'}.' '.
+ '';
+ my %postlinked;
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ undef(%postlinked);
+ $datatable .= ''.
+ ''.$usertypes->{$item}.' ';
+ if (ref($postlink{$item}) eq 'ARRAY') {
+ map { $postlinked{$_} = 1; } (@{$postlink{$item}});
+ }
+ foreach my $field ('email','username') {
+ my $checked;
+ if ($postlinked{$field}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$field.' '.
+ ' ';
+ }
+ $datatable .= ' ';
+ }
+ }
+ if (ref($postlink{'default'}) eq 'ARRAY') {
+ map { $postlinked{$_} = 1; } (@{$postlink{'default'}});
+ }
+ $datatable .= ''.
+ ''.$othertitle.' ';
+ foreach my $field ('email','username') {
+ my $checked;
+ if ($postlinked{$field}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$field.' '.
+ ' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'emailsrc'}.' '.
+ '';
+ foreach my $type ('permanent','critical','notify') {
+ my $checkedemail;
+ if ($emailsrc{$type}) {
+ $checkedemail = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$titles{$type}.' '.
+ ' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $switchserver = &check_switchserver($dom,$confname);
+ my ($showstd,$noshowstd);
+ if ($nostdtext) {
+ $noshowstd = ' checked="checked"';
+ } else {
+ $showstd = ' checked="checked"';
+ }
+ $datatable .= ''.$titles{'customtext'}.' '.
+ ''.
+ &mt('Retain standard text:').
+ ' '.
+ &mt('Yes').' '.' '.
+ ' '.
+ &mt('No').' '.
+ ''.
+ &mt('(If you use the same account ... reset a password from this page.)').' '.
+ &mt('Include custom text:');
+ if ($customurl) {
+ my $link = &Apache::loncommon::modal_link($customurl,&mt('custom text'),600,500,
+ undef,undef,undef,undef,'background-color:#ffffff');
+ $datatable .= ' '.$link.
+ ' '.&mt('Delete?').' '.
+ ' '.&mt('Replace:').' ';
+ }
+ if ($switchserver) {
+ $datatable .= ' '.&mt('Upload to library server: [_1]',$switchserver).' ';
+ } else {
+ $datatable .=' '.
+ ' ';
+ }
+ $datatable .= ' ';
+ } elsif ($position eq 'middle') {
+ my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);
+ my @items = ('intauth_cost','intauth_check','intauth_switch');
+ my %defaults;
+ if (ref($domconf{'defaults'}) eq 'HASH') {
+ %defaults = %{$domconf{'defaults'}};
+ if ($defaults{'intauth_cost'} !~ /^\d+$/) {
+ $defaults{'intauth_cost'} = 10;
+ }
+ if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_check'} = 0;
+ }
+ if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_switch'} = 0;
+ }
+ } else {
+ %defaults = (
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ }
+ foreach my $item (@items) {
+ if ($itemcount%2) {
+ $css_class = '';
+ } else {
+ $css_class = ' class="LC_odd_row" ';
+ }
+ $datatable .= ''.
+ ''.$titles{$item}.
+ ' ';
+ if ($item eq 'intauth_switch') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ $datatable .= '';
+ } elsif ($item eq 'intauth_check') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ $datatable .= '';
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ } elsif ($position eq 'lower') {
+ my ($min,$max,%chars,$expire,$numsaved);
+ $min = $Apache::lonnet::passwdmin;
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{min}) {
+ $min = $settings->{min};
+ }
+ if ($settings->{max}) {
+ $max = $settings->{max};
+ }
+ if (ref($settings->{chars}) eq 'ARRAY') {
+ map { $chars{$_} = 1; } (@{$settings->{chars}});
+ }
+ if ($settings->{expire}) {
+ $expire = $settings->{expire};
+ }
+ if ($settings->{numsaved}) {
+ $numsaved = $settings->{numsaved};
+ }
+ }
+ my %rulenames = &Apache::lonlocal::texthash(
+ uc => 'At least one upper case letter',
+ lc => 'At least one lower case letter',
+ num => 'At least one number',
+ spec => 'At least one non-alphanumeric',
+ );
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'min'}.' '.
+ ''.
+ ' '.
+ ' '.&mt('(Enter an integer: 7 or larger)').' '.
+ ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'max'}.' '.
+ ''.
+ ' '.
+ ' '.&mt('(Leave blank for no maximum)').' '.
+ ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'chars'}.' '.
+ ''.&mt('(Leave unchecked if not required)').
+ ' ';
+ my $numinrow = 2;
+ my @possrules = ('uc','lc','num','spec');
+ $datatable .= ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'expire'}.' '.
+ ''.
+ ' '.
+ ' '.&mt('(Leave blank for no expiration)').' '.
+ ' ';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.$titles{'numsaved'}.' '.
+ ''.
+ ' '.
+ ' '.&mt('(Leave blank to not save previous passwords)').' '.
+ ' ';
+ } else {
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my %ownerchg = (
+ by => {},
+ for => {},
+ );
+ my %ownertitles = &Apache::lonlocal::texthash (
+ by => 'Course owner status(es) allowed',
+ for => 'Student status(es) allowed',
+ );
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{crsownerchg}) eq 'HASH') {
+ if (ref($settings->{crsownerchg}{'by'}) eq 'ARRAY') {
+ map { $ownerchg{by}{$_} = 1; } (@{$settings->{crsownerchg}{'by'}});
+ }
+ if (ref($settings->{crsownerchg}{'for'}) eq 'ARRAY') {
+ map { $ownerchg{for}{$_} = 1; } (@{$settings->{crsownerchg}{'for'}});
+ }
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''.
+ ''.
+ &mt('Requirements').''.
+ ''.&mt("Course 'type' is not a Community or Placement Test").' '.
+ ''.&mt('User is Course Coordinator and also course owner').' '.
+ ''.&mt("Student's only active roles are student role(s) in course(s) owned by this user").' '.
+ ''.&mt('User, course, and student share same domain').' '.
+ ' '.
+ ' '.
+ '';
+ foreach my $item ('by','for') {
+ $datatable .= ''.
+ ''.$ownertitles{$item}.' ';
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $type (@{$types}) {
+ my $checked;
+ if ($ownerchg{$item}{$type}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.$usertypes->{$type}.' '.
+ ' ';
+ }
+ }
+ my $checked;
+ if ($ownerchg{$item}{'default'}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ' '.
+ $othertitle.' ';
+ }
+ $datatable .= ' ';
+ }
+ return $datatable;
+}
+
sub print_usersessions {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,$itemcount,%checked,%choices);
@@ -6339,13 +7030,13 @@ sub print_loadbalancing {
my $numinrow = 1;
my $datatable;
my %servers = &Apache::lonnet::internet_dom_servers($dom);
- my (%currbalancer,%currtargets,%currrules,%existing);
+ my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
if (ref($settings) eq 'HASH') {
%existing = %{$settings};
}
if ((keys(%servers) > 1) || (keys(%existing) > 0)) {
&get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
- \%currtargets,\%currrules);
+ \%currtargets,\%currrules,\%currcookies);
} else {
return;
}
@@ -6422,6 +7113,9 @@ sub print_loadbalancing {
my %hostherechecked = (
no => ' checked="checked"',
);
+ my %balcookiechecked = (
+ no => ' checked="checked"',
+ );
foreach my $sparetype (@sparestypes) {
my $targettable;
for (my $i=0; $i<$numspares; $i++) {
@@ -6477,6 +7171,11 @@ sub print_loadbalancing {
}
}
}
+ if ($currcookies{$lonhost}) {
+ %balcookiechecked = (
+ yes => ' checked="checked"',
+ );
+ }
$datatable .= &mt('Hosting on balancer itself').' '.
' '.&mt('No').' ';
@@ -6485,7 +7184,12 @@ sub print_loadbalancing {
'value="'.$sparetype.'"'.$hostherechecked{$sparetype}.' />'.$typetitles{$sparetype}.
' ';
}
- $datatable .= ' '.
+ $datatable .= &mt('Use balancer cookie').' '.
+ ' '.&mt('Yes').' '.
+ ' '.&mt('No').' '.
+ ''.
&loadbalancing_rules($dom,$intdom,$currrules{$lonhost},
$othertitle,$usertypes,$types,\%servers,
\%currbalancer,$lonhost,
@@ -6499,10 +7203,11 @@ sub print_loadbalancing {
}
sub get_loadbalancers_config {
- my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_;
+ my ($servers,$existing,$currbalancer,$currtargets,$currrules,$currcookies) = @_;
return unless ((ref($servers) eq 'HASH') &&
(ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') &&
- (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH'));
+ (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH') &&
+ (ref($currcookies) eq 'HASH'));
if (keys(%{$existing}) > 0) {
my $oldlonhost;
foreach my $key (sort(keys(%{$existing}))) {
@@ -6521,6 +7226,9 @@ sub get_loadbalancers_config {
$currbalancer->{$key} = 1;
$currtargets->{$key} = $existing->{$key}{'targets'};
$currrules->{$key} = $existing->{$key}{'rules'};
+ if ($existing->{$key}{'cookie'}) {
+ $currcookies->{$key} = 1;
+ }
}
}
} else {
@@ -6716,6 +7424,7 @@ sub contact_titles {
'requestsmail' => 'E-mail from course requests requiring approval',
'updatesmail' => 'E-mail from nightly check of LON-CAPA module integrity/updates',
'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
+ 'hostipmail' => 'E-mail from nightly check of hostname/IP network changes',
'errorthreshold' => 'Error/warning threshold for status e-mail',
'errorsysmail' => 'Error threshold for e-mail to core group',
'errorweights' => 'Weights used to compute error count',
@@ -7457,10 +8166,14 @@ sub captcha_choice {
$vertext,$currver);
my %lt = &captcha_phrases();
$keyentry = 'hidden';
+ my $colspan=2;
if ($context eq 'cancreate') {
$rowname = &mt('CAPTCHA validation');
} elsif ($context eq 'login') {
$rowname = &mt('"Contact helpdesk" CAPTCHA validation');
+ } elsif ($context eq 'passwords') {
+ $rowname = &mt('"Forgot Password" CAPTCHA validation');
+ $colspan=1;
}
if (ref($settings) eq 'HASH') {
if ($settings->{'captcha'}) {
@@ -7500,7 +8213,7 @@ sub captcha_choice {
$css_class .= ' style="'.$rowstyle.'"';
}
my $output = ''.
- ''.$rowname.' '."\n".
+ ' '.$rowname.' '."\n".
''."\n";
foreach my $option ('original','recaptcha','notused') {
$output .= ' '.
- ''.$titles->{$item}.
- ' ';
- if ($item eq 'intauth_switch') {
- my @options = (0,1,2);
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes',
- 2 => 'Yes, and copy existing passwd file to passwd.bak file',
- );
- $datatable .= '';
- } elsif ($item eq 'intauth_check') {
- my @options = (0,1,2);
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
- 2 => 'Yes, disallow login if stored cost is less than domain default',
- );
- $datatable .= '';
- } else {
- $datatable .= ' ';
- }
- $datatable .= ' ';
- $rownum ++;
- }
} else {
my %defaults;
if (ref($settings) eq 'HASH') {
@@ -7910,6 +8544,58 @@ sub defaults_titles {
return (\%titles);
}
+sub print_scantron {
+ my ($r,$position,$dom,$confname,$settings,$rowtotal) = @_;
+ if ($position eq 'top') {
+ return &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
+ } else {
+ return &print_scantronconfig($dom,$settings,\$rowtotal);
+ }
+}
+
+sub scantron_javascript {
+ return <<"ENDSCRIPT";
+
+
+
+ENDSCRIPT
+
+}
+
sub print_scantronformat {
my ($r,$dom,$confname,$settings,$rowtotal) = @_;
my $itemcount = 1;
@@ -7936,8 +8622,8 @@ sub print_scantronformat {
if ($configuserok eq 'ok') {
if ($author_ok eq 'ok') {
my %legacyfile = (
- default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
- custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
+ default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab',
+ custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab',
);
my %md5chk;
foreach my $type (keys(%legacyfile)) {
@@ -7946,7 +8632,7 @@ sub print_scantronformat {
}
if ($md5chk{'default'} ne $md5chk{'custom'}) {
foreach my $type (keys(%legacyfile)) {
- ($scantronurls{$type},my $error) =
+ ($scantronurls{$type},my $error) =
&legacy_scantronformat($r,$dom,$confname,
$type,$legacyfile{$type},
$scantronurls{$type},
@@ -7957,13 +8643,13 @@ sub print_scantronformat {
}
if (keys(%error) == 0) {
$is_custom = 1;
- $confhash{'scantron'}{'scantronformat'} =
+ $confhash{'scantron'}{'scantronformat'} =
$scantronurls{'custom'};
- my $putresult =
+ my $putresult =
&Apache::lonnet::put_dom('configuration',
\%confhash,$dom);
if ($putresult ne 'ok') {
- $error{'custom'} =
+ $error{'custom'} =
''.
&mt('An error occurred updating the domain configuration: [_1]',$putresult).' ';
}
@@ -8083,6 +8769,129 @@ sub legacy_scantronformat {
return ($url,$error);
}
+sub print_scantronconfig {
+ my ($dom,$settings,$rowtotal) = @_;
+ my $itemcount = 2;
+ my $is_checked = ' checked="checked"';
+ my %optionson = (
+ hdr => ' checked="checked"',
+ pad => ' checked="checked"',
+ rem => ' checked="checked"',
+ );
+ my %optionsoff = (
+ hdr => '',
+ pad => '',
+ rem => '',
+ );
+ my $currcsvsty = 'none';
+ my ($datatable,%csvfields,%checked,%onclick,%csvoptions);
+ my @fields = &scantroncsv_fields();
+ my %titles = &scantronconfig_titles();
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{config}) eq 'HASH') {
+ if ($settings->{config}->{dat}) {
+ $checked{'dat'} = $is_checked;
+ }
+ if (ref($settings->{config}->{csv}) eq 'HASH') {
+ if (ref($settings->{config}->{csv}->{fields}) eq 'HASH') {
+ %csvfields = %{$settings->{config}->{csv}->{fields}};
+ if (keys(%csvfields) > 0) {
+ $checked{'csv'} = $is_checked;
+ $currcsvsty = 'block';
+ }
+ }
+ if (ref($settings->{config}->{csv}->{options}) eq 'HASH') {
+ %csvoptions = %{$settings->{config}->{csv}->{options}};
+ foreach my $option (keys(%optionson)) {
+ unless ($csvoptions{$option}) {
+ $optionsoff{$option} = $optionson{$option};
+ $optionson{$option} = '';
+ }
+ }
+ }
+ }
+ } else {
+ $checked{'dat'} = $is_checked;
+ }
+ } else {
+ $checked{'dat'} = $is_checked;
+ }
+ $onclick{'csv'} = ' onclick="toggleScantron(this.form);"';
+ my $css_class = $itemcount%2? ' class="LC_odd_row"':'';
+ $datatable = ''.&mt('Supported formats').' '.
+ '';
+ foreach my $item ('dat','csv') {
+ my $id;
+ if ($item eq 'csv') {
+ $id = 'id="scantronconfcsv" ';
+ }
+ $datatable .= ' '.
+ $titles{$item}.' '.(' 'x3);
+ if ($item eq 'csv') {
+ $datatable .= ''.
+ ''.&mt('CSV Column Mapping').' '.
+ ''.&mt('Field').' '.&mt('Location').' '."\n";
+ foreach my $col (@fields) {
+ my $selnone;
+ if ($csvfields{$col} eq '') {
+ $selnone = ' selected="selected"';
+ }
+ $datatable .= ''.$titles{$col}.' '.
+ ''.
+ ' ';
+ for (my $i=0; $i<20; $i++) {
+ my $shown = $i+1;
+ my $sel;
+ unless ($selnone) {
+ if (exists($csvfields{$col})) {
+ if ($csvfields{$col} == $i) {
+ $sel = ' selected="selected"';
+ }
+ }
+ }
+ $datatable .= ''.$shown.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
'.
+ ''.
+ ''.&mt('CSV Options').' ';
+ foreach my $option ('hdr','pad','rem') {
+ $datatable .= ''.$titles{$option}.':'.
+ ' '.
+ &mt('Yes').' '.(' 'x2)."\n".
+ ' '.&mt('No').' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ }
+ $datatable .= ' ';
+ $$rowtotal ++;
+ return $datatable;
+}
+
+sub scantronconfig_titles {
+ return &Apache::lonlocal::texthash(
+ dat => 'Standard format (.dat)',
+ csv => 'Comma separated values (.csv)',
+ hdr => 'Remove first line in file (contains column titles)',
+ pad => 'Prepend 0s to PaperID',
+ rem => 'Remove leading spaces (except Question Response columns)',
+ CODE => 'CODE',
+ ID => 'Student ID',
+ PaperID => 'Paper ID',
+ FirstName => 'First Name',
+ LastName => 'Last Name',
+ FirstQuestion => 'First Question Response',
+ Section => 'Section',
+ );
+}
+
+sub scantroncsv_fields {
+ return ('PaperID','LastName','FirstName','ID','Section','CODE','FirstQuestion');
+}
+
sub print_coursecategories {
my ($position,$dom,$hdritem,$settings,$rowtotal) = @_;
my $datatable;
@@ -8431,35 +9240,7 @@ sub serverstatus_pages {
sub defaults_javascript {
my ($settings) = @_;
- my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
- my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
- &js_escape(\$intauthcheck);
- &js_escape(\$intauthcost);
- my $intauthjs = <<"ENDSCRIPT";
-
-function warnIntAuth(field) {
- if (field.name == 'intauth_check') {
- if (field.value == '2') {
- alert('$intauthcheck');
- }
- }
- if (field.name == 'intauth_cost') {
- field.value.replace(/\s/g,'');
- if (field.value != '') {
- var regexdigit=/^\\d+\$/;
- if (!regexdigit.test(field.value)) {
- alert('$intauthcost');
- }
- }
- }
- return;
-}
-
-ENDSCRIPT
-
- if (ref($settings) ne 'HASH') {
- return &Apache::lonhtmlcommon::scripttag($intauthjs);
- }
+ return unless (ref($settings) eq 'HASH');
if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
my $maxnum = scalar(@{$settings->{'inststatusorder'}});
if ($maxnum eq '') {
@@ -8513,15 +9294,100 @@ $jstext
return;
}
-$intauthjs
-
// ]]>
ENDSCRIPT
+ }
+ return;
+}
+
+sub passwords_javascript {
+ my %intalert = &Apache::lonlocal::texthash (
+ authcheck => 'Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.',
+ authcost => 'Warning: bcrypt encryption cost for internal authentication must be an integer.',
+ passmin => 'Warning: minimum password length must be a positive integer greater than 6.',
+ passmax => 'Warning: maximum password length must be a positive integer (or blank).',
+ passexp => 'Warning: days before password expiration must be a positive integer (or blank).',
+ passnum => 'Warning: number of previous passwords to save must be a positive integer (or blank).',
+ );
+ &js_escape(\%intalert);
+ my $defmin = $Apache::lonnet::passwdmin;
+ my $intauthjs = <<"ENDSCRIPT";
+
+function warnIntAuth(field) {
+ if (field.name == 'intauth_check') {
+ if (field.value == '2') {
+ alert('$intalert{authcheck}');
+ }
+ }
+ if (field.name == 'intauth_cost') {
+ field.value.replace(/\s/g,'');
+ if (field.value != '') {
+ var regexdigit=/^\\d+\$/;
+ if (!regexdigit.test(field.value)) {
+ alert('$intalert{authcost}');
+ }
+ }
+ }
+ return;
+}
+
+function warnIntPass(field) {
+ field.value.replace(/^\s+/,'');
+ field.value.replace(/\s+\$/,'');
+ var regexdigit=/^\\d+\$/;
+ if (field.name == 'passwords_min') {
+ if (field.value == '') {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ } else {
+ if (!regexdigit.test(field.value)) {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ }
+ var minval = parseInt(field.value,10);
+ if (minval < $defmin) {
+ alert('$intalert{passmin}');
+ field.value = '$defmin';
+ }
+ }
} else {
- return &Apache::lonhtmlcommon::scripttag($intauthjs);
+ if (field.value == '0') {
+ field.value = '';
+ }
+ if (field.value != '') {
+ if (field.name == 'passwords_expire') {
+ var regexpposnum=/^\\d+(|\\.\\d*)\$/;
+ if (!regexpposnum.test(field.value)) {
+ alert('$intalert{passexp}');
+ field.value = '';
+ } else {
+ var expval = parseFloat(field.value);
+ if (expval == 0) {
+ alert('$intalert{passexp}');
+ field.value = '';
+ }
+ }
+ } else {
+ if (!regexdigit.test(field.value)) {
+ if (field.name == 'passwords_max') {
+ alert('$intalert{passmax}');
+ } else {
+ if (field.name == 'passwords_numsaved') {
+ alert('$intalert{passnum}');
+ }
+ }
+ field.value = '';
+ }
+ }
+ }
}
+ return;
+}
+
+ENDSCRIPT
+ return &Apache::lonhtmlcommon::scripttag($intauthjs);
}
sub coursecategories_javascript {
@@ -8767,7 +9633,7 @@ sub build_category_rows {
sub modifiable_userdata_row {
my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref,
- $rowid,$customcss,$rowstyle) = @_;
+ $rowid,$customcss,$rowstyle,$itemdesc) = @_;
my ($role,$rolename,$statustype);
$role = $item;
if ($context eq 'cancreate') {
@@ -8790,6 +9656,8 @@ sub modifiable_userdata_row {
}
} elsif ($context eq 'lti') {
$rolename = &mt('Institutional data used (if available)');
+ } elsif ($context eq 'privacy') {
+ $rolename = $itemdesc;
} else {
if ($role eq 'cr') {
$rolename = &mt('Custom role');
@@ -8839,6 +9707,13 @@ sub modifiable_userdata_row {
if (ref($settings) eq 'HASH') {
$hashref = $settings->{'instdata'};
}
+ } elsif ($context eq 'privacy') {
+ my ($key,$inner) = split(/_/,$role);
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$key}) eq 'HASH') {
+ $hashref = $settings->{$key}->{$inner};
+ }
+ }
} elsif (ref($settings->{$context}) eq 'HASH') {
if (ref($settings->{$context}->{$role}) eq 'HASH') {
$hashref = $settings->{'lti_instdata'};
@@ -8876,7 +9751,25 @@ sub modifiable_userdata_row {
my $check = ' ';
unless ($role eq 'emailusername') {
if (exists($checks{$fields[$i]})) {
- $check = $checks{$fields[$i]}
+ $check = $checks{$fields[$i]};
+ } elsif ($context eq 'privacy') {
+ if ($role =~ /^priv_(domain|course)$/) {
+ if (ref($settings) ne 'HASH') {
+ $check = ' checked="checked" ';
+ }
+ } elsif ($role =~ /^priv_(author|community)$/) {
+ if (ref($settings) ne 'HASH') {
+ unless ($fields[$i] eq 'id') {
+ $check = ' checked="checked" ';
+ }
+ }
+ } elsif ($role =~ /^(unpriv|othdom)_/) {
+ if (ref($settings) ne 'HASH') {
+ if (($fields[$i] eq 'lastname') || ($fields[$i] eq 'firstname')) {
+ $check = ' checked="checked" ';
+ }
+ }
+ }
} elsif ($context ne 'lti') {
if ($role eq 'st') {
if (ref($settings) ne 'HASH') {
@@ -8905,6 +9798,8 @@ sub modifiable_userdata_row {
} else {
if ($context eq 'lti') {
$prefix = 'lti';
+ } elsif ($context eq 'privacy') {
+ $prefix = 'privacy';
}
$output .= ''.
' 0) {
+ if ($domconfig{$action}{$itemid}{'passback'} eq $confhash{$itemid}{'passback'}) {
+ if ($domconfig{$action}{$itemid}{'passbackformat'} ne $confhash{$itemid}{'passbackformat'}) {
$changes{$itemid} = 1;
}
- } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{$field}} > 0) {
- $changes{$itemid} = 1;
- }
- }
+ }
}
- }
- unless ($changes{$itemid}) {
- if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
- if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
- if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
- $confhash{$itemid}{'maproles'}{$ltirole}) {
+ foreach my $field ('makeuser','mapcrstype','selfenroll','instdata','lcmenu') {
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
+ if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
+ $confhash{$itemid}{$field});
+ if (@diffs) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{$field}} > 0) {
$changes{$itemid} = 1;
- last;
}
}
- unless ($changes{$itemid}) {
- foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
- if ($confhash{$itemid}{'maproles'}{$ltirole} ne
- $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ }
+ }
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
+ if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
+ $confhash{$itemid}{'maproles'}{$ltirole}) {
$changes{$itemid} = 1;
last;
}
}
- }
- } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
- $changes{$itemid} = 1;
- }
- } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- unless ($changes{$itemid}) {
- if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
+ unless ($changes{$itemid}) {
+ foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
+ if ($confhash{$itemid}{'maproles'}{$ltirole} ne
+ $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ $changes{$itemid} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
$changes{$itemid} = 1;
}
+ } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ unless ($changes{$itemid}) {
+ if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
+ $changes{$itemid} = 1;
+ }
+ }
}
}
}
@@ -12024,122 +12928,129 @@ sub modify_lti {
my $num = length($encconfig{$itemid}{'secret'});
$resulttext .= ('*'x$num).'';
}
- if ($confhash{$itemid}{'mapuser'}) {
- my $shownmapuser;
- if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
- $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
- } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
- $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
- } else {
- $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
- }
- $resulttext .= ''.&mt('LON-CAPA username').': '.$shownmapuser.' ';
- }
- if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
- my $rolemaps;
- foreach my $role (@ltiroles) {
- if ($confhash{$itemid}{'maproles'}{$role}) {
- $rolemaps .= (' 'x2).$role.'='.
- &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
- 'Course').',';
+ if ($confhash{$itemid}{'requser'}) {
+ if ($confhash{$itemid}{'mapuser'}) {
+ my $shownmapuser;
+ if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
+ $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
+ } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
+ $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
+ } else {
+ $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
}
+ $resulttext .= ''.&mt('LON-CAPA username').': '.$shownmapuser.' ';
}
- if ($rolemaps) {
- $rolemaps =~ s/,$//;
- $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
- }
- }
- if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'makeuser'}} > 0) {
- $resulttext .= ''.&mt('Following roles may create user accounts: [_1]',
- join(', ',@{$confhash{$itemid}{'makeuser'}})).' ';
- if ($confhash{$itemid}{'lcauth'} eq 'lti') {
- $resulttext .= &mt('New users will only be able to authenticate via LTI').' ';
- } else {
- $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
- $confhash{$itemid}{'lcauth'});
- if ($confhash{$itemid}{'lcauth'} eq 'internal') {
- $resulttext .= '; '.&mt('a randomly generated password will be created');
- } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
- if ($confhash{$itemid}{'lcauthparm'} ne '') {
- $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
- }
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ my $rolemaps;
+ foreach my $role (@ltiroles) {
+ if ($confhash{$itemid}{'maproles'}{$role}) {
+ $rolemaps .= (' 'x2).$role.'='.
+ &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
+ 'Course').',';
+ }
+ }
+ if ($rolemaps) {
+ $rolemaps =~ s/,$//;
+ $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
+ }
+ }
+ if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'makeuser'}} > 0) {
+ $resulttext .= ''.&mt('Following roles may create user accounts: [_1]',
+ join(', ',@{$confhash{$itemid}{'makeuser'}})).' ';
+ if ($confhash{$itemid}{'lcauth'} eq 'lti') {
+ $resulttext .= &mt('New users will only be able to authenticate via LTI').' ';
} else {
- $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
+ $resulttext .= &mt('New users will be assigned LON-CAPA authentication: [_1]',
+ $confhash{$itemid}{'lcauth'});
+ if ($confhash{$itemid}{'lcauth'} eq 'internal') {
+ $resulttext .= '; '.&mt('a randomly generated password will be created');
+ } elsif ($confhash{$itemid}{'lcauth'} eq 'localauth') {
+ if ($confhash{$itemid}{'lcauthparm'} ne '') {
+ $resulttext .= ' '.&mt('with argument: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
+ } else {
+ $resulttext .= '; '.&mt('Kerberos domain: [_1]',$confhash{$itemid}{'lcauthparm'});
+ }
}
+ $resulttext .= '';
+ } else {
+ $resulttext .= ''.&mt('User account creation not permitted.').' ';
}
- $resulttext .= '';
- } else {
- $resulttext .= ''.&mt('User account creation not permitted.').' ';
}
- }
- if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'instdata'}} > 0) {
- $resulttext .= ''.&mt('Institutional data will be used when creating a new user for: [_1]',
- join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).' ';
- } else {
- $resulttext .= ''.&mt('No institutional data used when creating a new user.').' ';
+ if (ref($confhash{$itemid}{'instdata'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'instdata'}} > 0) {
+ $resulttext .= ''.&mt('Institutional data will be used when creating a new user for: [_1]',
+ join(', ',map { $fieldtitles{$_}; } @{$confhash{$itemid}{'instdata'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('No institutional data used when creating a new user.').' ';
+ }
}
- }
- if ($confhash{$itemid}{'mapcrs'}) {
- $resulttext .= ''.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.' ';
- }
- if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
- $resulttext .= ''.&mt('Mapping for the following LON-CAPA course types: [_1]',
- join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
- ' ';
+ if ($confhash{$itemid}{'mapcrs'}) {
+ $resulttext .= ''.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.' ';
+ }
+ if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
+ $resulttext .= ''.&mt('Mapping for the following LON-CAPA course types: [_1]',
+ join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('No mapping to LON-CAPA courses').' ';
+ }
+ }
+ if ($confhash{$itemid}{'makecrs'}) {
+ $resulttext .= ''.&mt('Instructor may create course (if absent).').' ';
} else {
- $resulttext .= ''.&mt('No mapping to LON-CAPA courses').' ';
+ $resulttext .= ''.&mt('Instructor may not create course (if absent).').' ';
}
- }
- if ($confhash{$itemid}{'makecrs'}) {
- $resulttext .= ''.&mt('Instructor may create course (if absent).').' ';
- } else {
- $resulttext .= ''.&mt('Instructor may not create course (if absent).').' ';
- }
- if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
- $resulttext .= ''.&mt('Self-enrollment for following roles: [_1]',
- join(', ',@{$confhash{$itemid}{'selfenroll'}})).
- ' ';
+ if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
+ $resulttext .= ''.&mt('Self-enrollment for following roles: [_1]',
+ join(', ',@{$confhash{$itemid}{'selfenroll'}})).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('Self-enrollment not permitted').' ';
+ }
+ }
+ if ($confhash{$itemid}{'section'}) {
+ if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
+ $resulttext .= ''.&mt('User section from standard field:').
+ ' (course_section_sourcedid)'.' ';
+ } else {
+ $resulttext .= ''.&mt('User section from:').' '.
+ $confhash{$itemid}{'section'}.' ';
+ }
} else {
- $resulttext .= ''.&mt('Self-enrollment not permitted').' ';
+ $resulttext .= ''.&mt('No section assignment').' ';
}
- }
- if ($confhash{$itemid}{'section'}) {
- if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
- $resulttext .= ''.&mt('User section from standard field:').
- ' (course_section_sourcedid)'.' ';
+ if ($confhash{$itemid}{'callback'}) {
+ $resulttext .= ''.&mt('Callback setting').': '.$confhash{$itemid}{'callback'}.' ';
} else {
- $resulttext .= ''.&mt('User section from:').' '.
- $confhash{$itemid}{'section'}.' ';
+ $resulttext .= ''.&mt('No callback to logout LON-CAPA session when user logs out of Comsumer');
}
- } else {
- $resulttext .= ' '.&mt('No section assignment').' ';
- }
- foreach my $item ('passback','roster','topmenu','inlinemenu') {
- $resulttext .= ''.$lt{$item}.': ';
- if ($confhash{$itemid}{$item}) {
- $resulttext .= &mt('Yes');
- if ($item eq 'passback') {
- if ($confhash{$itemid}{'passbackformat'} eq '1.0') {
- $resulttext .= ' ('.&mt('Outcomes Extension (1.0)').')';
- } elsif ($confhash{$itemid}{'passbackformat'} eq '1.1') {
- $resulttext .= ' ('.&mt('Outcomes Service (1.1)').')';
+ foreach my $item ('passback','roster','topmenu','inlinemenu') {
+ $resulttext .= ' '.$lt{$item}.': ';
+ if ($confhash{$itemid}{$item}) {
+ $resulttext .= &mt('Yes');
+ if ($item eq 'passback') {
+ if ($confhash{$itemid}{'passbackformat'} eq '1.0') {
+ $resulttext .= ' ('.&mt('Outcomes Extension (1.0)').')';
+ } elsif ($confhash{$itemid}{'passbackformat'} eq '1.1') {
+ $resulttext .= ' ('.&mt('Outcomes Service (1.1)').')';
+ }
}
+ } else {
+ $resulttext .= &mt('No');
}
- } else {
- $resulttext .= &mt('No');
+ $resulttext .= ' ';
}
- $resulttext .= '';
- }
- if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
- if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
- $resulttext .= ''.&mt('Menu items:').' '.
- join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).' ';
- } else {
- $resulttext .= ''.&mt('No menu items displayed in header or online menu').' ';
+ if (ref($confhash{$itemid}{'lcmenu'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'lcmenu'}} > 0) {
+ $resulttext .= ''.&mt('Menu items:').' '.
+ join(', ', map { $menutitles{$_}; } (@{$confhash{$itemid}{'lcmenu'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('No menu items displayed in header or online menu').' ';
+ }
}
}
$resulttext .= '';
@@ -12787,7 +13698,7 @@ sub modify_contacts {
my (%others,%to,%bcc,%includestr,%includeloc);
my @contacts = ('supportemail','adminemail');
my @mailings = ('errormail','packagesmail','helpdeskmail','otherdomsmail',
- 'lonstatusmail','requestsmail','updatesmail','idconflictsmail');
+ 'lonstatusmail','requestsmail','updatesmail','idconflictsmail','hostipmail');
my @toggles = ('reporterrors','reportupdates','reportstatus');
my @lonstatus = ('threshold','sysmail','weights','excluded');
my ($fields,$fieldtitles,$fieldoptions,$possoptions) = &helpform_fields();
@@ -13076,6 +13987,7 @@ sub modify_contacts {
$default{'lonstatusmail'} = 'adminemail';
$default{'requestsmail'} = 'adminemail';
$default{'updatesmail'} = 'adminemail';
+ $default{'hostipmail'} = 'adminemail';
foreach my $item (@contacts) {
if ($to{$item} ne $default{$item}) {
$changes{$item} = 1;
@@ -13365,6 +14277,778 @@ sub modify_contacts {
return $resulttext;
}
+sub modify_privacy {
+ my ($dom,%domconfig) = @_;
+ my ($resulttext,%current,%changes);
+ if (ref($domconfig{'privacy'}) eq 'HASH') {
+ %current = %{$domconfig{'privacy'}};
+ }
+ my @fields = ('lastname','firstname','middlename','generation','permanentemail','id');
+ my @items = ('domain','author','course','community');
+ my %names = &Apache::lonlocal::texthash (
+ domain => 'Assigned domain role(s)',
+ author => 'Assigned co-author role(s)',
+ course => 'Assigned course role(s)',
+ community => 'Assigned community role',
+ );
+ my %roles = &Apache::lonlocal::texthash (
+ domain => 'Domain role',
+ author => 'Co-author role',
+ course => 'Course role',
+ community => 'Community role',
+ );
+ my %titles = &Apache::lonlocal::texthash (
+ approval => 'Approval for role in different domain',
+ othdom => 'User information available in other domain',
+ priv => 'Information viewable by privileged user in same domain',
+ unpriv => 'Information viewable by unprivileged user in same domain',
+ instdom => 'Other domain shares institution/provider',
+ extdom => 'Other domain has different institution/provider',
+ none => 'Not allowed',
+ user => 'User authorizes',
+ domain => 'Domain Coordinator authorizes',
+ auto => 'Unrestricted',
+ );
+ my %fieldnames = &Apache::lonlocal::texthash (
+ id => 'Student/Employee ID',
+ permanentemail => 'E-mail address',
+ lastname => 'Last Name',
+ firstname => 'First Name',
+ middlename => 'Middle Name',
+ generation => 'Generation',
+ );
+ my ($othertitle,$usertypes,$types) =
+ &Apache::loncommon::sorted_inst_types($dom);
+ my (%by_ip,%by_location,@intdoms,@instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+
+ my %privacyhash = (
+ 'approval' => {
+ instdom => {},
+ extdom => {},
+ },
+ 'othdom' => {},
+ 'priv' => {},
+ 'unpriv' => {},
+ );
+ foreach my $item (@items) {
+ if (@instdoms > 1) {
+ if ($env{'form.privacy_approval_instdom'.$item} =~ /^(none|user|domain|auto)$/) {
+ $privacyhash{'approval'}{'instdom'}{$item} = $env{'form.privacy_approval_instdom_'.$item};
+ }
+ if (ref($current{'approval'}) eq 'HASH') {
+ if (ref($current{'approval'}{'instdom'}) eq 'HASH') {
+ unless ($privacyhash{'approval'}{'instdom'}{$item} eq $current{'approval'}{'instdom'}{$item}) {
+ $changes{'approval'} = 1;
+ }
+ }
+ } elsif ($privacyhash{'approval'}{'instdom'}{$item} ne 'auto') {
+ $changes{'approval'} = 1;
+ }
+ }
+ if (keys(%by_location) > 0) {
+ if ($env{'form.privacy_approval_extdom_'.$item} =~ /^(none|user|domain|auto)$/) {
+ $privacyhash{'approval'}{'extdom'}{$item} = $env{'form.privacy_approval_extdom_'.$item};
+ }
+ if (ref($current{'approval'}) eq 'HASH') {
+ if (ref($current{'approval'}{'extdom'}) eq 'HASH') {
+ unless ($privacyhash{'approval'}{'extdom'}{$item} eq $current{'approval'}{'extdom'}{$item}) {
+ $changes{'approval'} = 1;
+ }
+ }
+ } elsif ($privacyhash{'approval'}{'extdom'}{$item} ne 'auto') {
+ $changes{'approval'} = 1;
+ }
+ }
+ foreach my $status ('priv','unpriv') {
+ my @possibles = sort(&Apache::loncommon::get_env_multiple('form.privacy_'.$status.'_'.$item));
+ my @newvalues;
+ foreach my $field (@possibles) {
+ if (grep(/^\Q$field\E$/,@fields)) {
+ $privacyhash{$status}{$item}{$field} = 1;
+ push(@newvalues,$field);
+ }
+ }
+ @newvalues = sort(@newvalues);
+ if (ref($current{$status}) eq 'HASH') {
+ if (ref($current{$status}{$item}) eq 'HASH') {
+ my @currvalues = sort(keys(%{$current{$status}{$item}}));
+ my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
+ if (@diffs > 0) {
+ $changes{$status} = 1;
+ }
+ }
+ } else {
+ my @stdfields;
+ foreach my $field (@fields) {
+ if ($field eq 'id') {
+ next if ($status eq 'unpriv');
+ next if (($status eq 'priv') && ($item eq 'community'));
+ }
+ push(@stdfields,$field);
+ }
+ my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
+ if (@diffs > 0) {
+ $changes{$status} = 1;
+ }
+ }
+ }
+ }
+ if ((@instdoms > 1) || (keys(%by_location) > 0)) {
+ my @statuses;
+ if (ref($types) eq 'ARRAY') {
+ @statuses = @{$types};
+ }
+ foreach my $type (@statuses,'default') {
+ my @possfields = &Apache::loncommon::get_env_multiple('form.privacy_othdom_'.$type);
+ my @newvalues;
+ foreach my $field (sort(@possfields)) {
+ if (grep(/^\Q$field\E$/,@fields)) {
+ $privacyhash{'othdom'}{$type}{$field} = 1;
+ push(@newvalues,$field);
+ }
+ }
+ @newvalues = sort(@newvalues);
+ if (ref($current{'othdom'}) eq 'HASH') {
+ if (ref($current{'othdom'}{$type}) eq 'HASH') {
+ my @currvalues = sort(keys(%{$current{'othdom'}{$type}}));
+ my @diffs = &Apache::loncommon::compare_arrays(\@currvalues,\@newvalues);
+ if (@diffs > 0) {
+ $changes{'othdom'} = 1;
+ }
+ }
+ } else {
+ my @stdfields = ('lastname','firstname','middlename','generation','permanentemail');
+ my @diffs = &Apache::loncommon::compare_arrays(\@stdfields,\@newvalues);
+ if (@diffs > 0) {
+ $changes{'othdom'} = 1;
+ }
+ }
+ }
+ }
+ my %confighash = (
+ privacy => \%privacyhash,
+ );
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
+ if ($putresult eq 'ok') {
+ if (keys(%changes) > 0) {
+ $resulttext = &mt('Changes made: ').'';
+ foreach my $key ('approval','othdom','priv','unpriv') {
+ if ($changes{$key}) {
+ $resulttext .= ''.$titles{$key}.':';
+ if ($key eq 'approval') {
+ if (keys(%{$privacyhash{$key}{instdom}})) {
+ $resulttext .= ''.$titles{'instdom'}.'';
+ foreach my $item (@items) {
+ $resulttext .= ''.$roles{$item}.': '.$titles{$privacyhash{$key}{instdom}{$item}}.' ';
+ }
+ $resulttext .= ' ';
+ }
+ if (keys(%{$privacyhash{$key}{extdom}})) {
+ $resulttext .= ''.$titles{'extdom'}.'';
+ foreach my $item (@items) {
+ $resulttext .= ''.$roles{$item}.': '.$titles{$privacyhash{$key}{extdom}{$item}}.' ';
+ }
+ $resulttext .= ' ';
+ }
+ } elsif ($key eq 'othdom') {
+ my @statuses;
+ if (ref($types) eq 'ARRAY') {
+ @statuses = @{$types};
+ }
+ if (ref($privacyhash{$key}) eq 'HASH') {
+ foreach my $status (@statuses,'default') {
+ if ($status eq 'default') {
+ $resulttext .= ''.$othertitle.': ';
+ } elsif (ref($usertypes) eq 'HASH') {
+ $resulttext .= ' '.$usertypes->{$status}.': ';
+ } else {
+ next;
+ }
+ if (ref($privacyhash{$key}{$status}) eq 'HASH') {
+ if (keys(%{$privacyhash{$key}{$status}})) {
+ $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$status}}))));
+ } else {
+ $resulttext .= &mt('none');
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ } else {
+ foreach my $item (@items) {
+ if (ref($privacyhash{$key}{$item}) eq 'HASH') {
+ $resulttext .= ''.$names{$item}.': ';
+ if (keys(%{$privacyhash{$key}{$item}})) {
+ $resulttext .= join(', ', map { $fieldnames{$_}; } (sort(keys(%{$privacyhash{$key}{$item}}))));
+ } else {
+ $resulttext .= &mt('none');
+ }
+ $resulttext .= ' ';
+ }
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ } else {
+ $resulttext = &mt('No changes made to user information settings');
+ }
+ } else {
+ $resulttext = ''.
+ &mt('An error occurred: [_1]',$putresult).' ';
+ }
+ return $resulttext;
+}
+
+sub modify_passwords {
+ my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
+ my ($resulttext,%current,%changes,%newvalues,@oktypes,$errors,
+ $updatedefaults,$updateconf);
+ my $customfn = 'resetpw.html';
+ if (ref($domconfig{'passwords'}) eq 'HASH') {
+ %current = %{$domconfig{'passwords'}};
+ }
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ if (ref($types) eq 'ARRAY') {
+ @oktypes = @{$types};
+ }
+ push(@oktypes,'default');
+
+ my %titles = &Apache::lonlocal::texthash (
+ intauth_cost => 'Encryption cost for bcrypt (positive integer)',
+ intauth_check => 'Check bcrypt cost if authenticated',
+ intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
+ permanent => 'Permanent e-mail address',
+ critical => 'Critical notification address',
+ notify => 'Notification address',
+ min => 'Minimum password length',
+ max => 'Maximum password length',
+ chars => 'Required characters',
+ expire => 'Password expiration (days)',
+ numsaved => 'Number of previous passwords to save',
+ reset => 'Resetting Forgotten Password',
+ intauth => 'Encryption of Stored Passwords (Internal Auth)',
+ rules => 'Rules for LON-CAPA Passwords',
+ crsownerchg => 'Course Owner Changing Student Passwords',
+ username => 'Username',
+ email => 'E-mail address',
+ );
+
+#
+# Retrieve current domain configuration for internal authentication from $domconfig{'defaults'}.
+#
+ my (%curr_defaults,%save_defaults);
+ if (ref($domconfig{'defaults'}) eq 'HASH') {
+ foreach my $key (keys(%{$domconfig{'defaults'}})) {
+ if ($key =~ /^intauth_(cost|check|switch)$/) {
+ $curr_defaults{$key} = $domconfig{'defaults'}{$key};
+ } else {
+ $save_defaults{$key} = $domconfig{'defaults'}{$key};
+ }
+ }
+ }
+ my %staticdefaults = (
+ 'resetlink' => 2,
+ 'resetcase' => \@oktypes,
+ 'resetprelink' => 'both',
+ 'resetemail' => ['critical','notify','permanent'],
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ $staticdefaults{'min'} = $Apache::lonnet::passwdmin;
+ foreach my $type (@oktypes) {
+ $staticdefaults{'resetpostlink'}{$type} = ['email','username'];
+ }
+ my $linklife = $env{'form.passwords_link'};
+ $linklife =~ s/^\s+|\s+$//g;
+ if (($linklife =~ /^\d+(|\.\d*)$/) && ($linklife > 0)) {
+ $newvalues{'resetlink'} = $linklife;
+ if ($current{'resetlink'}) {
+ if ($current{'resetlink'} ne $linklife) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!ref($domconfig{passwords}) eq 'HASH') {
+ if ($staticdefaults{'resetlink'} ne $linklife) {
+ $changes{'reset'} = 1;
+ }
+ }
+ } elsif ($current{'resetlink'}) {
+ $changes{'reset'} = 1;
+ }
+ my @casesens;
+ my @posscase = &Apache::loncommon::get_env_multiple('form.passwords_case_sensitive');
+ foreach my $case (sort(@posscase)) {
+ if (grep(/^\Q$case\E$/,@oktypes)) {
+ push(@casesens,$case);
+ }
+ }
+ $newvalues{'resetcase'} = \@casesens;
+ if (ref($current{'resetcase'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetcase'},\@casesens);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!ref($domconfig{passwords}) eq 'HASH') {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetcase'},\@casesens);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ if ($env{'form.passwords_prelink'} =~ /^(both|either)$/) {
+ $newvalues{'resetprelink'} = $env{'form.passwords_prelink'};
+ if (exists($current{'resetprelink'})) {
+ if ($current{'resetprelink'} ne $newvalues{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!ref($domconfig{passwords}) eq 'HASH') {
+ if ($staticdefaults{'resetprelink'} ne $newvalues{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ }
+ } elsif ($current{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ foreach my $type (@oktypes) {
+ my @possplink = &Apache::loncommon::get_env_multiple('form.passwords_postlink_'.$type);
+ my @postlink;
+ foreach my $item (sort(@possplink)) {
+ if ($item =~ /^(email|username)$/) {
+ push(@postlink,$item);
+ }
+ }
+ $newvalues{'resetpostlink'}{$type} = \@postlink;
+ unless ($changes{'reset'}) {
+ if (ref($current{'resetpostlink'}) eq 'HASH') {
+ if (ref($current{'resetpostlink'}{$type}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetpostlink'}{$type},\@postlink);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } else {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!ref($domconfig{passwords}) eq 'HASH') {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetpostlink'}{$type},\@postlink);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ }
+ }
+ my @possemailsrc = &Apache::loncommon::get_env_multiple('form.passwords_emailsrc');
+ my @resetemail;
+ foreach my $item (sort(@possemailsrc)) {
+ if ($item =~ /^(permanent|critical|notify)$/) {
+ push(@resetemail,$item);
+ }
+ }
+ $newvalues{'resetemail'} = \@resetemail;
+ unless ($changes{'reset'}) {
+ if (ref($current{'resetemail'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetemail'},\@resetemail);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!ref($domconfig{passwords}) eq 'HASH') {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetemail'},\@resetemail);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ }
+ if ($env{'form.passwords_stdtext'} == 0) {
+ $newvalues{'resetremove'} = 1;
+ unless ($current{'resetremove'}) {
+ $changes{'reset'} = 1;
+ }
+ } elsif ($current{'resetremove'}) {
+ $changes{'reset'} = 1;
+ }
+ if ($env{'form.passwords_customfile.filename'} ne '') {
+ my $servadm = $r->dir_config('lonAdmEMail');
+ my ($configuserok,$author_ok,$switchserver) =
+ &config_check($dom,$confname,$servadm);
+ my $error;
+ if ($configuserok eq 'ok') {
+ if ($switchserver) {
+ $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);
+ } else {
+ if ($author_ok eq 'ok') {
+ my ($result,$customurl) =
+ &publishlogo($r,'upload','passwords_customfile',$dom,
+ $confname,'customtext/resetpw','','',$customfn);
+ if ($result eq 'ok') {
+ $newvalues{'resetcustom'} = $customurl;
+ $changes{'reset'} = 1;
+ } else {
+ $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customfn,$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].",$customfn,$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].",$customfn,$confname,$dom,$configuserok);
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= ''.$error.' ';
+ }
+ } elsif ($current{'resetcustom'}) {
+ if ($env{'form.passwords_custom_del'}) {
+ $changes{'reset'} = 1;
+ } else {
+ $newvalues{'resetcustom'} = $current{'resetcustom'};
+ }
+ }
+ $env{'form.intauth_cost'} =~ s/^\s+|\s+$//g;
+ if (($env{'form.intauth_cost'} ne '') && ($env{'form.intauth_cost'} =~ /^\d+$/)) {
+ $save_defaults{'intauth_cost'} = $env{'form.intauth_cost'};
+ if ($save_defaults{'intauth_cost'} ne $curr_defaults{'intauth_cost'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_cost'} = $curr_defaults{'intauth_cost'};
+ }
+ if ($env{'form.intauth_check'} =~ /^(0|1|2)$/) {
+ $save_defaults{'intauth_check'} = $env{'form.intauth_check'};
+ if ($save_defaults{'intauth_check'} ne $curr_defaults{'intauth_check'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
+ }
+ if ($env{'form.intauth_switch'} =~ /^(0|1|2)$/) {
+ $save_defaults{'intauth_switch'} = $env{'form.intauth_switch'};
+ if ($save_defaults{'intauth_switch'} ne $curr_defaults{'intauth_switch'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
+ }
+ foreach my $item ('cost','check','switch') {
+ if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {
+ $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};
+ $updatedefaults = 1;
+ }
+ }
+ foreach my $rule ('min','max','expire','numsaved') {
+ $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;
+ my $ruleok;
+ if ($rule eq 'expire') {
+ if (($env{'form.passwords_'.$rule} =~ /^\d+(|\.\d*)$/) &&
+ ($env{'form.passwords_'.$rule} ne '0')) {
+ $ruleok = 1;
+ }
+ } elsif ($rule eq 'min') {
+ if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {
+ if ($env{'form.passwords_'.$rule} >= $Apache::lonnet::passwdmin) {
+ $ruleok = 1;
+ }
+ }
+ } elsif (($env{'form.passwords_'.$rule} =~ /^\d+$/) &&
+ ($env{'form.passwords_'.$rule} ne '0')) {
+ $ruleok = 1;
+ }
+ if ($ruleok) {
+ $newvalues{$rule} = $env{'form.passwords_'.$rule};
+ if (exists($current{$rule})) {
+ if ($newvalues{$rule} ne $current{$rule}) {
+ $changes{'rules'} = 1;
+ }
+ } elsif ($rule eq 'min') {
+ if ($staticdefaults{$rule} ne $newvalues{$rule}) {
+ $changes{'rules'} = 1;
+ }
+ } else {
+ $changes{'rules'} = 1;
+ }
+ } elsif (exists($current{$rule})) {
+ $changes{'rules'} = 1;
+ }
+ }
+ my @posschars = &Apache::loncommon::get_env_multiple('form.passwords_chars');
+ my @chars;
+ foreach my $item (sort(@posschars)) {
+ if ($item =~ /^(uc|lc|num|spec)$/) {
+ push(@chars,$item);
+ }
+ }
+ $newvalues{'chars'} = \@chars;
+ unless ($changes{'rules'}) {
+ if (ref($current{'chars'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'chars'},\@chars);
+ if (@diffs > 0) {
+ $changes{'rules'} = 1;
+ }
+ } else {
+ if (@chars > 0) {
+ $changes{'rules'} = 1;
+ }
+ }
+ }
+ my %crsownerchg = (
+ by => [],
+ for => [],
+ );
+ foreach my $item ('by','for') {
+ my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);
+ foreach my $type (sort(@posstypes)) {
+ if (grep(/^\Q$type\E$/,@oktypes)) {
+ push(@{$crsownerchg{$item}},$type);
+ }
+ }
+ }
+ $newvalues{'crsownerchg'} = \%crsownerchg;
+ if (ref($current{'crsownerchg'}) eq 'HASH') {
+ foreach my $item ('by','for') {
+ if (ref($current{'crsownerchg'}{$item}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'crsownerchg'}{$item},$crsownerchg{$item});
+ if (@diffs > 0) {
+ $changes{'crsownerchg'} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (!(ref($domconfig{passwords}) eq 'HASH')) {
+ foreach my $item ('by','for') {
+ if (@{$crsownerchg{$item}} > 0) {
+ $changes{'crsownerchg'} = 1;
+ last;
+ }
+ }
+ }
+
+ my %confighash = (
+ defaults => \%save_defaults,
+ passwords => \%newvalues,
+ );
+ &process_captcha('passwords',\%changes,$confighash{'passwords'},$domconfig{'passwords'});
+
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
+ if ($putresult eq 'ok') {
+ if (keys(%changes) > 0) {
+ $resulttext = &mt('Changes made: ').'';
+ foreach my $key ('reset','intauth','rules','crsownerchg') {
+ if ($changes{$key}) {
+ unless ($key eq 'intauth') {
+ $updateconf = 1;
+ }
+ $resulttext .= ''.$titles{$key}.':';
+ if ($key eq 'reset') {
+ if ($confighash{'passwords'}{'captcha'} eq 'original') {
+ $resulttext .= ''.&mt('CAPTCHA validation set to use: original CAPTCHA').' ';
+ } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {
+ $resulttext .= ''.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.
+ &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).' ';
+ if (ref($confighash{'passwords'}{'recaptchakeys'}) eq 'HASH') {
+ $resulttext .= &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'public'}).''.
+ &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchakeys'}{'private'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('No CAPTCHA validation').' ';
+ }
+ if ($confighash{'passwords'}{'resetlink'}) {
+ $resulttext .= ''.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).' ';
+ } else {
+ $resulttext .= ''.&mt('No reset link expiration set.').' '.
+ &mt('Will default to 2 hours').' ';
+ }
+ if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetcase'}} == 0) {
+ $resulttext .= ''.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').' ';
+ } else {
+ my $casesens;
+ foreach my $type (@{$confighash{'passwords'}{'resetcase'}}) {
+ if ($type eq 'default') {
+ $casesens .= $othertitle.', ';
+ } elsif ($usertypes->{$type} ne '') {
+ $casesens .= $usertypes->{$type}.', ';
+ }
+ }
+ $casesens =~ s/\Q, \E$//;
+ $resulttext .= ''.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('Case-sensitivity not set for "Forgot Password" web form').' '.&mt('Will default to case-sensitive for username and/or e-mail address for all').' ';
+ }
+ if ($confighash{'passwords'}{'resetprelink'} eq 'either') {
+ $resulttext .= ''.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').' ';
+ } else {
+ $resulttext .= ''.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').' ';
+ }
+ if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {
+ my $output;
+ if (ref($types) eq 'ARRAY') {
+ foreach my $type (@{$types}) {
+ if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetpostlink'}{$type}} == 0) {
+ $output .= $usertypes->{$type}.' -- '.&mt('none');
+ } else {
+ $output .= $usertypes->{$type}.' -- '.
+ join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{$type}})).'; ';
+ }
+ }
+ }
+ }
+ if (ref($confighash{'passwords'}{'resetpostlink'}{'default'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {
+ $output .= $othertitle.' -- '.&mt('none');
+ } else {
+ $output .= $othertitle.' -- '.
+ join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));
+ }
+ }
+ if ($output) {
+ $resulttext .= ''.&mt('Information required for new password form (by user type) set to: [_1]',$output).' ';
+ } else {
+ $resulttext .= ''.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').' ';
+ }
+ if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetemail'}} > 0) {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('E-mail address(es) in LON-CAPA usedfor verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).' ';
+ }
+ if ($confighash{'passwords'}{'resetremove'}) {
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" web form not shown').' ';
+ } else {
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" web form is shown').' ';
+ }
+ if ($confighash{'passwords'}{'resetcustom'}) {
+ my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},
+ &mt('custom text'),600,500,undef,undef,
+ undef,undef,'background-color:#ffffff');
+ $resulttext .= ''.&mt('Preamble to "Forgot Password" form includes: [_1]',$customlink).' ';
+ } else {
+ $resulttext .= ''.&mt('No custom text included in preamble to "Forgot Password" form').' ';
+ }
+ } elsif ($key eq 'intauth') {
+ foreach my $item ('cost','switch','check') {
+ my $value = $save_defaults{$key.'_'.$item};
+ if ($item eq 'switch') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
+ } elsif ($item eq 'check') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
+ }
+ $resulttext .= ''.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).' ';
+ }
+ } elsif ($key eq 'rules') {
+ foreach my $rule ('min','max','expire','numsaved') {
+ if ($confighash{'passwords'}{$rule} eq '') {
+ if ($rule eq 'min') {
+ $resulttext .= ''.&mt('[_1] not set.',$titles{$rule});
+ ' '.&mt('Default of [_1] will be used',
+ $Apache::lonnet::passwdmin).' ';
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{$rule}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).' ';
+ }
+ }
+ if (ref($confighash{'passwords'}{'chars'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'chars'}} > 0) {
+ my %rulenames = &Apache::lonlocal::texthash(
+ uc => 'At least one upper case letter',
+ lc => 'At least one lower case letter',
+ num => 'At least one number',
+ spec => 'At least one non-alphanumeric',
+ );
+ my $needed = ''.
+ join(' ',map {$rulenames{$_} } @{$confighash{'passwords'}{'chars'}}).
+ ' ';
+ $resulttext .= ''.&mt('[_1] set to: [_2]',$titles{'chars'},$needed).' ';
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{'chars'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('[_1] set to none',$titles{'chars'}).' ';
+ }
+ } elsif ($key eq 'crsownerchg') {
+ if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {
+ if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||
+ (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {
+ $resulttext .= ''.&mt('Course owner may not change student passwords.').' ';
+ } else {
+ my %crsownerstr;
+ foreach my $item ('by','for') {
+ if (ref($confighash{'passwords'}{'crsownerchg'}{$item}) eq 'ARRAY') {
+ foreach my $type (@{$confighash{'passwords'}{'crsownerchg'}{$item}}) {
+ if ($type eq 'default') {
+ $crsownerstr{$item} .= $othertitle.', ';
+ } elsif ($usertypes->{$type} ne '') {
+ $crsownerstr{$item} .= $usertypes->{$type}.', ';
+ }
+ }
+ $crsownerstr{$item} =~ s/\Q, \E$//;
+ }
+ }
+ $resulttext .= ''.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',
+ $crsownerstr{'by'},$crsownerstr{'for'}).' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('Course owner may not change student passwords.').' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ $resulttext .= ' ';
+ } else {
+ $resulttext = &mt('No changes made to password settings');
+ }
+ my $cachetime = 24*60*60;
+ if ($updatedefaults) {
+ &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'domdefaults'} = 1;
+ }
+ }
+ if ($updateconf) {
+ &Apache::lonnet::do_cache_new('passwdconf',$dom,$confighash{'passwords'},$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'passwdconf'} = 1;
+ }
+ }
+ } else {
+ $resulttext = ''.
+ &mt('An error occurred: [_1]',$putresult).' ';
+ }
+ if ($errors) {
+ $resulttext .= ''.&mt('The following errors occurred: ').'
';
+ }
+ return $resulttext;
+}
+
sub modify_usercreation {
my ($dom,%domconfig) = @_;
my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
@@ -14178,7 +15862,7 @@ sub modify_selfcreation {
$chgtext .= &mt('For self-created accounts verified by e-mail address, username is set as follows:').
'';
foreach my $status (@statuses) {
- if ($type eq 'default') {
+ if ($status eq 'default') {
$chgtext .= ''.$othertitle.' -- '.$options{$cancreate{'emailverified'}{$status}}.' ';
} else {
$chgtext .= ''.$usertypes{$status}.' -- '.$options{$cancreate{'emailverified'}{$status}}.' ';
@@ -14447,19 +16131,25 @@ sub modify_selfcreation {
}
sub process_captcha {
- my ($container,$changes,$newsettings,$current) = @_;
- return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH') || (ref($current) eq 'HASH'));
+ my ($container,$changes,$newsettings,$currsettings) = @_;
+ return unless ((ref($changes) eq 'HASH') && (ref($newsettings) eq 'HASH'));
$newsettings->{'captcha'} = $env{'form.'.$container.'_captcha'};
unless ($newsettings->{'captcha'} eq 'recaptcha' || $newsettings->{'captcha'} eq 'notused') {
$newsettings->{'captcha'} = 'original';
}
- if ($current->{'captcha'} ne $newsettings->{'captcha'}) {
+ my %current;
+ if (ref($currsettings) eq 'HASH') {
+ %current = %{$currsettings};
+ }
+ if ($current{'captcha'} ne $newsettings->{'captcha'}) {
if ($container eq 'cancreate') {
if (ref($changes->{'cancreate'}) eq 'ARRAY') {
push(@{$changes->{'cancreate'}},'captcha');
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['captcha'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'captcha'} = 1;
}
@@ -14481,9 +16171,9 @@ sub process_captcha {
}
$newsettings->{'recaptchaversion'} = $newversion;
}
- if (ref($current->{'recaptchakeys'}) eq 'HASH') {
- $currpub = $current->{'recaptchakeys'}{'public'};
- $currpriv = $current->{'recaptchakeys'}{'private'};
+ if (ref($current{'recaptchakeys'}) eq 'HASH') {
+ $currpub = $current{'recaptchakeys'}{'public'};
+ $currpriv = $current{'recaptchakeys'}{'private'};
unless ($newsettings->{'captcha'} eq 'recaptcha') {
$newsettings->{'recaptchakeys'} = {
public => '',
@@ -14491,8 +16181,8 @@ sub process_captcha {
}
}
}
- if ($current->{'captcha'} eq 'recaptcha') {
- $currversion = $current->{'recaptchaversion'};
+ if ($current{'captcha'} eq 'recaptcha') {
+ $currversion = $current{'recaptchaversion'};
if ($currversion ne '2') {
$currversion = 1;
}
@@ -14504,6 +16194,8 @@ sub process_captcha {
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['recaptchaversion'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'recaptchaversion'} = 1;
}
@@ -14515,6 +16207,8 @@ sub process_captcha {
} elsif (!defined($changes->{'cancreate'})) {
$changes->{'cancreate'} = ['recaptchakeys'];
}
+ } elsif ($container eq 'passwords') {
+ $changes->{'reset'} = 1;
} else {
$changes->{'recaptchakeys'} = 1;
}
@@ -14630,7 +16324,7 @@ sub modify_defaults {
my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors);
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
- 'portal_def','intauth_cost','intauth_check','intauth_switch');
+ 'portal_def');
my @authtypes = ('internal','krb4','krb5','localauth','lti');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
@@ -14672,24 +16366,6 @@ sub modify_defaults {
push(@errors,$item);
}
}
- } elsif ($item eq 'intauth_cost') {
- if ($newvalues{$item} ne '') {
- if ($newvalues{$item} =~ /\D/) {
- push(@errors,$item);
- }
- }
- } elsif ($item eq 'intauth_check') {
- if ($newvalues{$item} ne '') {
- unless ($newvalues{$item} =~ /^(0|1|2)$/) {
- push(@errors,$item);
- }
- }
- } elsif ($item eq 'intauth_switch') {
- if ($newvalues{$item} ne '') {
- unless ($newvalues{$item} =~ /^(0|1|2)$/) {
- push(@errors,$item);
- }
- }
}
if (grep(/^\Q$item\E$/,@errors)) {
$newvalues{$item} = $domdefaults{$item};
@@ -14698,6 +16374,18 @@ sub modify_defaults {
}
$domdefaults{$item} = $newvalues{$item};
}
+ my %staticdefaults = (
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ foreach my $item ('intauth_cost','intauth_check','intauth_switch') {
+ if (exists($domdefaults{$item})) {
+ $newvalues{$item} = $domdefaults{$item};
+ } else {
+ $newvalues{$item} = $staticdefaults{$item};
+ }
+ }
my %defaults_hash = (
defaults => \%newvalues,
);
@@ -14826,28 +16514,6 @@ sub modify_defaults {
lti => 'lti',
);
$value = $authnames{$shortauth{$value}};
- } elsif ($item eq 'intauth_switch') {
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes',
- 2 => 'Yes, and copy existing passwd file to passwd.bak file',
- );
- if ($value =~ /^(0|1|2)$/) {
- $value = $optiondesc{$value};
- } else {
- $value = &mt('none -- defaults to No');
- }
- } elsif ($item eq 'intauth_check') {
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
- 2 => 'Yes, disallow login if stored cost is less than domain default',
- );
- if ($value =~ /^(0|1|2)$/) {
- $value = $optiondesc{$value};
- } else {
- $value = &mt('none -- defaults to No');
- }
}
$resulttext .= ''.&mt('[_1] set to "[_2]"',$title->{$item},$value).' ';
$mailmsgtext .= "$title->{$item} set to $value\n";
@@ -14896,7 +16562,7 @@ sub modify_scantron {
my $custom = 'custom.tab';
my $default = 'default.tab';
my $servadm = $r->dir_config('lonAdmEMail');
- my ($configuserok,$author_ok,$switchserver) =
+ my ($configuserok,$author_ok,$switchserver) =
&config_check($dom,$confname,$servadm);
if ($env{'form.scantronformat.filename'} ne '') {
my $error;
@@ -14931,6 +16597,67 @@ sub modify_scantron {
if ($env{'form.scantronformat_del'}) {
$confhash{'scantron'}{'scantronformat'} = '';
$changes{'scantronformat'} = 1;
+ } else {
+ $confhash{'scantron'}{'scantronformat'} = $domconfig{'scantron'}{'scantronformat'};
+ }
+ }
+ }
+ my @options = ('hdr','pad','rem');
+ my @fields = &scantroncsv_fields();
+ my %titles = &scantronconfig_titles();
+ my @formats = &Apache::loncommon::get_env_multiple('form.scantronconfig');
+ my ($newdat,$currdat,%newcol,%currcol);
+ if (grep(/^dat$/,@formats)) {
+ $confhash{'scantron'}{config}{dat} = 1;
+ $newdat = 1;
+ } else {
+ $newdat = 0;
+ }
+ if (grep(/^csv$/,@formats)) {
+ my %bynum;
+ foreach my $field (@fields) {
+ if ($env{'form.scantronconfig_csv_'.$field} =~ /^(\d+)$/) {
+ my $posscol = $1;
+ if (($posscol < 20) && (!$bynum{$posscol})) {
+ $confhash{'scantron'}{config}{csv}{fields}{$field} = $posscol;
+ $bynum{$posscol} = $field;
+ $newcol{$field} = $posscol;
+ }
+ }
+ }
+ if (keys(%newcol)) {
+ foreach my $option (@options) {
+ if ($env{'form.scantroncsv_'.$option}) {
+ $confhash{'scantron'}{config}{csv}{options}{$option} = 1;
+ }
+ }
+ }
+ }
+ $currdat = 1;
+ if (ref($domconfig{'scantron'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
+ unless (exists($domconfig{'scantron'}{'config'}{'dat'})) {
+ $currdat = 0;
+ }
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ %currcol = %{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}};
+ }
+ }
+ }
+ }
+ if ($currdat != $newdat) {
+ $changes{'config'} = 1;
+ } else {
+ foreach my $field (@fields) {
+ if ($currcol{$field} ne '') {
+ if ($currcol{$field} ne $newcol{$field}) {
+ $changes{'config'} = 1;
+ last;
+ }
+ } elsif ($newcol{$field} ne '') {
+ $changes{'config'} = 1;
+ last;
}
}
}
@@ -14941,22 +16668,57 @@ sub modify_scantron {
if (keys(%changes) > 0) {
if (ref($confhash{'scantron'}) eq 'HASH') {
$resulttext = &mt('Changes made:').'';
- if ($confhash{'scantron'}{'scantronformat'} eq '') {
- $resulttext .= ''.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).' ';
- } else {
- $resulttext .= ''.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).' ';
+ if ($changes{'scantronformat'}) {
+ if ($confhash{'scantron'}{'scantronformat'} eq '') {
+ $resulttext .= ''.&mt('[_1] bubblesheet format file removed; [_2] file will be used for courses in this domain.',$custom,$default).' ';
+ } else {
+ $resulttext .= ''.&mt('Custom bubblesheet format file ([_1]) uploaded for use with courses in this domain.',$custom).' ';
+ }
+ }
+ if ($changes{'config'}) {
+ if (ref($confhash{'scantron'}{'config'}) eq 'HASH') {
+ if ($confhash{'scantron'}{'config'}{'dat'}) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .dat format').' ';
+ }
+ if (ref($confhash{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($confhash{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'fields'}})) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .csv format, with following fields/column numbers supported:').'';
+ foreach my $field (@fields) {
+ if ($confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} ne '') {
+ my $showcol = $confhash{'scantron'}{'config'}{'csv'}{'fields'}{$field} + 1;
+ $resulttext .= ''.$titles{$field}.': '.$showcol.' ';
+ }
+ }
+ $resulttext .= ' ';
+ if (ref($confhash{'scantron'}{'config'}{'csv'}{'options'}) eq 'HASH') {
+ if (keys(%{$confhash{'scantron'}{'config'}{'csv'}{'options'}})) {
+ $resulttext .= ''.&mt('Bubblesheet data upload formats includes .csv format, with following options:').'';
+ foreach my $option (@options) {
+ if ($confhash{'scantron'}{'config'}{'csv'}{'options'}{$option} ne '') {
+ $resulttext .= ''.$titles{$option}.' ';
+ }
+ }
+ $resulttext .= ' ';
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $resulttext .= ''.&mt('No bubblesheet data upload formats set -- will default to assuming .dat format').' ';
+ }
}
$resulttext .= ' ';
} else {
$resulttext = &mt('Changes made to bubblesheet format file.');
}
- $resulttext .= ' ';
&Apache::loncommon::devalidate_domconfig_cache($dom);
if (ref($lastactref) eq 'HASH') {
$lastactref->{'domainconfig'} = 1;
}
} else {
- $resulttext = &mt('No changes made to bubblesheet format file');
+ $resulttext = &mt('No changes made to bubblesheet format settings');
}
} else {
$resulttext = ''.
@@ -14966,8 +16728,8 @@ sub modify_scantron {
$resulttext = &mt('No changes made to bubblesheet format file');
}
if ($errors) {
- $resulttext .= &mt('The following errors occurred: ').'';
+ $resulttext .= ''.&mt('The following errors occurred: ').'
';
}
return $resulttext;
}
@@ -15242,6 +17004,10 @@ sub modify_coursecategories {
}
$resulttext .= ' ';
}
+ &Apache::lonnet::do_cache_new('cats',$dom,$cathash,3600);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'cats'} = 1;
+ }
}
$resulttext .= '';
if ($changes{'unauth'} || $changes{'auth'}) {
@@ -15788,7 +17554,6 @@ sub modify_coursedefaults {
$defaultshash{'coursedefaults'}{$setting}{$type} = $newdef;
}
if ($currdef ne $newdef) {
- my $staticdef;
if ($item eq 'anonsurvey_threshold') {
unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) {
$changes{$item} = 1;
@@ -15804,11 +17569,12 @@ sub modify_coursedefaults {
my $texengine;
if ($env{'form.texengine'} =~ /^(MathJax|mimetex|tth)$/) {
$texengine = $env{'form.texengine'};
- if ($defaultshash{'coursedefaults'}{'texengine'} eq '') {
- unless ($texengine eq 'MathJax') {
+ my $currdef = $domconfig{'coursedefaults'}{'texengine'};
+ if ($currdef eq '') {
+ unless ($texengine eq $Apache::lonnet::deftex) {
$changes{'texengine'} = 1;
}
- } elsif ($defaultshash{'coursedefaults'}{'texengine'} ne $texengine) {
+ } elsif ($currdef ne $texengine) {
$changes{'texengine'} = 1;
}
}
@@ -16625,14 +18391,18 @@ sub modify_usersessions {
} else {
foreach my $type (@{$types{$prefix}}) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{'usersessions'}) eq 'HASH') {
if (ref($defaultshash{'usersessions'}{$prefix})) {
if ($type eq 'version') {
$newvalue = $defaultshash{'usersessions'}{$prefix}{$type};
- } elsif (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
- if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
- $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
+ } else {
+ if (ref($defaultshash{'usersessions'}{$prefix}{$type}) eq 'ARRAY') {
+ if (@{$defaultshash{'usersessions'}{$prefix}{$type}} > 0) {
+ $newvalue = join(', ',@{$defaultshash{'usersessions'}{$prefix}{$type}});
+ }
+ } else {
+ $notinuse = 1;
}
}
}
@@ -16640,12 +18410,14 @@ sub modify_usersessions {
if ($newvalue eq '') {
if ($type eq 'version') {
$resulttext .= ''.&mt('[_1] set to: off',$lt{$type}).' ';
+ } elsif ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$lt{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: none',$lt{$type}).' ';
}
} else {
if ($type eq 'version') {
- $newvalue .= ' '.&mt('(or later)');
+ $newvalue .= ' '.&mt('(or later)');
}
$resulttext .= ''.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).' ';
}
@@ -16833,18 +18605,24 @@ sub modify_ssl {
$resulttext .= ''.$titles{$prefix}.'';
foreach my $type (@{$types{$prefix}}) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{$action}) eq 'HASH') {
if (ref($defaultshash{$action}{$prefix})) {
if (($prefix eq 'connto') || ($prefix eq 'connfrom')) {
$newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
- } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
- if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
- $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+ } else {
+ if (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
+ if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
+ $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+ }
+ } else {
+ $notinuse = 1;
}
}
}
- if ($newvalue eq '') {
+ if ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$titles{$type}).' ';
+ } elsif ($newvalue eq '') {
$resulttext .= ''.&mt('[_1] set to: none',$titles{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).' ';
@@ -16958,17 +18736,21 @@ sub modify_trust {
$resulttext .= ''.$lt{$prefix}.'';
foreach my $type (@types) {
if (defined($changes{$prefix}{$type})) {
- my $newvalue;
+ my ($newvalue,$notinuse);
if (ref($defaultshash{'trust'}) eq 'HASH') {
if (ref($defaultshash{'trust'}{$prefix})) {
if (ref($defaultshash{'trust'}{$prefix}{$type}) eq 'ARRAY') {
if (@{$defaultshash{'trust'}{$prefix}{$type}} > 0) {
$newvalue = join(', ',@{$defaultshash{'trust'}{$prefix}{$type}});
}
+ } else {
+ $notinuse = 1;
}
}
}
- if ($newvalue eq '') {
+ if ($notinuse) {
+ $resulttext .= ''.&mt('[_1] set to: not in use',$lt{$type}).' ';
+ } elsif ($newvalue eq '') {
$resulttext .= ''.&mt('[_1] set to: none',$lt{$type}).' ';
} else {
$resulttext .= ''.&mt('[_1] set to: [_2].',$lt{$type},$newvalue).' ';
@@ -17003,12 +18785,12 @@ sub modify_loadbalancing {
my @sparestypes = ('primary','default');
my %typetitles = &sparestype_titles();
my $resulttext;
- my (%currbalancer,%currtargets,%currrules,%existing);
+ my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
}
&get_loadbalancers_config(\%servers,\%existing,\%currbalancer,
- \%currtargets,\%currrules);
+ \%currtargets,\%currrules,\%currcookies);
my ($saveloadbalancing,%defaultshash,%changes);
my ($alltypes,$othertypes,$titles) =
&loadbalancing_titles($dom,$intdom,$usertypes,$types);
@@ -17060,6 +18842,18 @@ sub modify_loadbalancing {
}
$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto;
}
+ if ($env{'form.loadbalancing_cookie_'.$i}) {
+ $defaultshash{'loadbalancing'}{$balancer}{'cookie'} = 1;
+ if (exists($currbalancer{$balancer})) {
+ unless ($currcookies{$balancer}) {
+ $changes{'curr'}{$balancer}{'cookie'} = 1;
+ }
+ }
+ } elsif (exists($currbalancer{$balancer})) {
+ if ($currcookies{$balancer}) {
+ $changes{'curr'}{$balancer}{'cookie'} = 1;
+ }
+ }
if (ref($currtargets{$balancer}) eq 'HASH') {
foreach my $sparetype (@sparestypes) {
if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') {
@@ -17213,6 +19007,10 @@ sub modify_loadbalancing {
}
}
}
+ if ($changes{'curr'}{$balancer}{'cookie'}) {
+ $resulttext .= ''.&mt('Load Balancer: [_1] -- cookie use enabled',
+ $balancer).' ';
+ }
if (keys(%toupdate)) {
my %thismachine;
my $updatedhere;
@@ -17442,12 +19240,12 @@ sub lonbalance_targets_js {
}
push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external');
$allinsttypes = join("','",@alltypes);
- my (%currbalancer,%currtargets,%currrules,%existing);
+ my (%currbalancer,%currtargets,%currrules,%existing,%currcookies);
if (ref($settings) eq 'HASH') {
%existing = %{$settings};
}
&get_loadbalancers_config($servers,\%existing,\%currbalancer,
- \%currtargets,\%currrules);
+ \%currtargets,\%currrules,\%currcookies);
my $balancers = join("','",sort(keys(%currbalancer)));
return <<"END";
@@ -17989,7 +19787,8 @@ sub devalidate_remote_domconfs {
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %thismachine;
map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
- my @posscached = ('domainconfig','domdefaults','ltitools','usersessions','directorysrch');
+ my @posscached = ('domainconfig','domdefaults','ltitools','usersessions',
+ 'directorysrch','passwdconf','cats');
if (keys(%servers)) {
foreach my $server (keys(%servers)) {
next if ($thismachine{$server});