--- loncom/interface/lonpreferences.pm 2019/05/05 23:19:47 1.233 +++ loncom/interface/lonpreferences.pm 2022/09/08 01:41:13 1.241 @@ -1,7 +1,7 @@ # The LearningOnline Network # Preferences # -# $Id: lonpreferences.pm,v 1.233 2019/05/05 23:19:47 raeburn Exp $ +# $Id: lonpreferences.pm,v 1.241 2022/09/08 01:41:13 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,7 +31,6 @@ package Apache::lonpreferences; use strict; -use LONCAPA; use Apache::Constants qw(:common); use Apache::File; use Apache::loncommon(); @@ -40,6 +39,7 @@ use Apache::lonlocal; use Apache::lonnet; use LONCAPA::lonauthcgi(); use LONCAPA(); +use DateTime::TimeZone(); ################################################################ # Handler subroutines # @@ -363,7 +363,7 @@ $options.' &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::end_pick_box().' '); - if ($roles_check_list) { + if ($roles_check_list) { $r->print('

'.&mt('Freeze Roles').'

'.&mt('The table below can be used to [_1]freeze[_2] '.$lc_role.'s in the Hotlist.','','').'
'. @@ -627,7 +627,7 @@ sub icon_options { } sub icon_previews { - my %icon_text = ( + my %icon_text = &Apache::lonlocal::texthash ( annotate => 'Notes', wishlist => 'Stored Links', catalog => 'Info', @@ -636,12 +636,12 @@ sub icon_previews { printout => 'Print', ); my %inlinetools = ( - printout => "s&8&3&prt.png&$icon_text{'printout'}&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document", - wishlist => "s&9&1&wishlist-link.png&$icon_text{'wishlist'}&wishlistlink[_2]&set_wishlistlink()&Save a link for this resource in your personal Stored Links repository", - evaluate => "s&8&1&eval.png&$icon_text{'evaluate'}&this[_1]&gopost('/adm/evaluate',currentURL,1)&Provide my evaluation of this resource", - feedback => "s&8&2&fdbk.png&$icon_text{'feedback'}&discuss[_1]&gopost('/adm/feedback',currentURL,1)&Provide feedback messages or contribute to the course discussion about this resource", - annotate => "s&9&3&anot.png&$icon_text{'annotate'}&tations[_1]&annotate()&Make notes and annotations about this resource", - catalog => "s&6&3&catalog.png&$icon_text{'catalog'}&info[_1]&catalog_info()&Show Metadata", + printout => "s&8&3&prt.png&$icon_text{'printout'}&printout[_1]&gopost('/adm/printout',currentURL)&".&mt('Prepare a printable document'), + wishlist => "s&9&1&wishlist-link.png&$icon_text{'wishlist'}&wishlistlink[_2]&set_wishlistlink()&".&mt('Save a link for this resource in your personal Stored Links repository'), + evaluate => "s&8&1&eval.png&$icon_text{'evaluate'}&this[_1]&gopost('/adm/evaluate',currentURL,1)&".&mt('Provide my evaluation of this resource'), + feedback => "s&8&2&fdbk.png&$icon_text{'feedback'}&discuss[_1]&gopost('/adm/feedback',currentURL,1)&".&mt('Provide feedback messages or contribute to the course discussion about this resource'), + annotate => "s&9&3&anot.png&$icon_text{'annotate'}&tations[_1]&annotate()&".&mt('Make notes and annotations about this resource'), + catalog => "s&6&3&catalog.png&$icon_text{'catalog'}&info[_1]&catalog_info()&".&mt('Show Metadata'), ); my @toolsorder = qw(annotate wishlist evaluate feedback printout catalog); return (\%inlinetools,\@toolsorder); @@ -1265,7 +1265,8 @@ sub passwordchanger { # This function is a bit of a mess.... # Passwords are encrypted using londes.js (DES encryption) $errormessage = ($errormessage || ''); - my ($user,$domain,$currentpass); + my ($user,$domain,$currentpass,$clientip); + $clientip = &Apache::lonnet::get_requestor_ip($r); &Apache::lonhtmlcommon::add_breadcrumb( { href => '/adm/preferences?action=changepass', text => 'Change Password'}); @@ -1273,18 +1274,18 @@ sub passwordchanger { $r->print(Apache::loncommon::start_page('Personal Data')); $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Password')); } - my ($blocked,$blocktext) = - &Apache::loncommon::blocking_status('passwd'); - if ($blocked) { - $r->print('

'.$blocktext.'

'); - return; - } if ((!defined($caller)) || ($caller eq 'preferences')) { $user = $env{'user.name'}; $domain = $env{'user.domain'}; if (!defined($caller)) { $caller = 'preferences'; } + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('passwd',$clientip); + if ($blocked) { + $r->print('

'.$blocktext.'

'); + return; + } } elsif ($caller eq 'reset_by_email') { my %data = &Apache::lonnet::tmpget($mailtoken); if (keys(%data) == 0) { @@ -1301,6 +1302,12 @@ sub passwordchanger { $user = $data{'username'}; $domain = $data{'domain'}; $currentpass = $data{'temppasswd'}; + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('passwd',$clientip,$user,$domain); + if ($blocked) { + $r->print('

'.$blocktext.'

'); + return; + } } else { $r->print( '

' @@ -1360,7 +1367,7 @@ sub passwordchanger { my $jsh=Apache::File->new($include."/londes.js"); $r->print(<$jsh>); } - $r->print(&jscript_send($caller,$extrafields)); + $r->print(&jscript_send($caller,$domain,$currentauth,$extrafields)); $r->print(< 'New password needs at least one upper case letter', + lc => 'New password needs at least one lower case letter', + num => 'New password needs at least one number', + spec => 'New password needs at least one non-alphanumeric', + blank1 => 'Empty Password field', + blank2 => 'Empty Confirm Password field', + mismatch => 'Contents of Password and Confirm Password fields must match', + fail => 'Please fix the following:', + ); + &js_escape(\%js_lt); + if ($currentauth eq 'internal:') { + if ($domain ne '') { + my %passwdconf = &Apache::lonnet::get_passwdconf($domain); + if (keys(%passwdconf)) { + if ($passwdconf{min}) { + $min = $passwdconf{min}; + } + if ($passwdconf{max}) { + $max = $passwdconf{max}; + $js_lt{'long'} = &js_escape(&mt('Maximum password length: [_1]',$max)); + } + if (ref($passwdconf{chars}) eq 'ARRAY') { + if (@{$passwdconf{chars}}) { + $rulestr = join('","',@{$passwdconf{chars}}); + $numrules = scalar(@{$passwdconf{chars}}); + } + } + } + } + } + $js_lt{'short'} = &js_escape(&mt('Minimum password length: [_1]',$min)); + + my $passwdcheck = <<"ENDJS"; + var errors = new Array(); + var min = parseInt("$min") || 0; + var currauth = "$currentauth"; + if (this.document.client.elements.newpass_1.value == '') { + errors.push("$js_lt{'blank1'}"); + } + if (this.document.client.elements.newpass_2.value == '') { + errors.push("$js_lt{'blank2'}"); + } + if (errors.length == 0) { + if (this.document.client.elements.newpass_1.value != this.document.client.elements.newpass_2.value) { + errors.push("$js_lt{'mismatch'}"); + } + var posspass = this.document.client.elements.newpass_1.value; + if (min > 0) { + if (posspass.length < min) { + errors.push("$js_lt{'short'}"); + } + } + if (currauth == 'internal:') { + var max = parseInt("$max") || 0; + if (max > 0) { + if (posspass.length > max) { + errors.push("$js_lt{'long'}"); + } + } + var numrules = parseInt("$numrules") || 0; + if (numrules > 0) { + var rules = new Array("$rulestr"); + for (var i=0; i\\/?]/; + if (!posspass.match(pattern)) { + errors.push("$js_lt{'spec'}"); + } + } + } + } + } + } + if (errors.length > 0) { + alert("$js_lt{'fail'}"+"\\n\\n"+errors.join("\\n")); + return; + } +ENDJS my $output = qq| +ENDSCRIPT + my %loaditems = ( + onload => 'javascript:toggleTZdisplay(document.prefs);', + ); + my $args = { 'add_entries' => \%loaditems }; + &Apache::lonhtmlcommon::add_breadcrumb( + { href => '/adm/preferences?action=', + text => 'Set Your Time Zone'}); + $r->print(Apache::loncommon::start_page('Set Your Time Zone',$js,$args)); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Set Your Time Zone')); + my %userenv = &Apache::lonnet::get('environment',['timezone']); + my $timezone = $userenv{'timezone'}; + my %lt = &Apache::lonlocal::texthash( + lctz => 'Use Time Zone set by LON-CAPA', + owntz => 'Use Time Zone set by you', + save => 'Save', + ); + my (%checked,$tzsty); + if ($userenv{'timezone'} ne '') { + $checked{'owntz'} = ' checked="checked"'; + $tzsty = 'inline-block'; + } else { + $checked{'lctz'} = ' checked="checked"'; + $tzsty = 'none'; + } + my $onclick = ' onclick="javascript:toggleTZdisplay(this.form);"'; + my $selector = &Apache::loncommon::select_timezone('timezone',$timezone,undef,1); + $r->print(<<"END"); +

+ + +     +
  +$selector +


+ +
+END + } + return; +} + +sub verify_and_change_timezone { + my $r = shift; + my $currtimezone = $env{'environment.timezone'}; + my $newtimezone; + if ($env{'form.settimezone'}) { + $newtimezone = $env{'form.timezone'}; + if (DateTime::TimeZone->is_valid_name($env{'form.timezone'})) { + $newtimezone = $env{'form.timezone'}; + } + } + my $message=''; + if ($newtimezone) { + if ($newtimezone eq $currtimezone) { + $message = &mt('Time Zone settings unchanged'); + } else { + &Apache::lonnet::put('environment',{'timezone' => $newtimezone}); + &Apache::lonnet::appenv({'environment.timezone' => $newtimezone}); + $message=&Apache::lonhtmlcommon::confirm_success( + &mt('Set [_1] to [_2]', + ''.&mt('Your Time Zone').'', + '"'.$newtimezone.'".')). + '
'; + } + } elsif ($currtimezone) { + &Apache::lonnet::del('environment',['timezone']); + &Apache::lonnet::delenv('environment.timezone'); + $message=&Apache::lonhtmlcommon::confirm_success(&mt('Time Zone now set by LON-CAPA')); + } else { + $message = &mt('Time Zone settings unchanged'); + } + $message=&Apache::loncommon::confirmwrapper($message); + &print_main_menu($r,$message); + return; +} + sub print_main_menu { my ($r, $message) = @_; # Determine current authentication method @@ -2098,6 +2346,9 @@ my %permissions; if (&Apache::lonnet::usertools_access($user,$domain,'aboutme')) { $permissions{'aboutme'} = 'F'; } +if (&Apache::lonnet::usertools_access($user,$domain,'timezone')) { + $permissions{'timezone'} = 'F'; +} my @menu= ({ categorytitle=>'Personal Data', items =>[ @@ -2140,6 +2391,14 @@ my @menu= icon => 'dismath.png', linktitle => 'Change how math is displayed.' }, + { + linktext => 'Time Zone', + url => '/adm/preferences?action=changetimezone', + permission => $permissions{'timezone'}, + #help => '', + icon => 'timezone.png', + linktitle => 'Set your time zone.', + } ] }, { categorytitle=>'Page Display Settings', @@ -2306,7 +2565,7 @@ sub handler { } else { $brlink ='/adm/preferences'; $brtxt = 'Set User Preferences'; - $brhelp = 'Prefs_About_Me,Prefs_Language,Prefs_Screen_Name_Nickname,Change_Colors,Change_Password,Prefs_Messages,Change_Discussion_Display'; + $brhelp = 'Prefs_About_Me,Prefs_Language,Prefs_Screen_Name_Nickname,Change_Colors,Change_Password,Prefs_Messages,Change_Discussion_Display'; } Apache::lonhtmlcommon::add_breadcrumb ({href => $brlink, @@ -2318,7 +2577,7 @@ sub handler { }elsif($env{'form.action'} eq 'changepass'){ &passwordchanger($r); }elsif($env{'form.action'} eq 'verify_and_change_pass'){ - &verify_and_change_password($r,'preferences','',\$ended); + &verify_and_change_password($r,'preferences','','','',\$ended); }elsif($env{'form.action'} eq 'changescreenname'){ &screennamechanger($r); }elsif($env{'form.action'} eq 'verify_and_change_screenname'){ @@ -2394,10 +2653,14 @@ sub handler { &print_main_menu($r); $ended = 1; } elsif ($env{'form.action'} eq 'changelockednames') { - &lockednameschanger($r); + $ended = &lockednameschanger($r); } elsif ($env{'form.action'} eq 'verify_and_change_lockednames') { &verify_and_change_lockednames($r); $ended = 1; + } elsif ($env{'form.action'} eq 'changetimezone') { + &timezonechanger($r); + } elsif ($env{'form.action'} eq 'verify_and_change_timezone') { + &verify_and_change_timezone($r); } # Properly end the HTML page of all preference pages