--- loncom/interface/lonpreferences.pm 2019/04/30 12:56:23 1.232 +++ loncom/interface/lonpreferences.pm 2025/03/07 02:13:40 1.248 @@ -1,7 +1,7 @@ # The LearningOnline Network # Preferences # -# $Id: lonpreferences.pm,v 1.232 2019/04/30 12:56:23 raeburn Exp $ +# $Id: lonpreferences.pm,v 1.248 2025/03/07 02:13:40 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 # @@ -103,16 +103,17 @@ sub languagechanger { { href => '/adm/preferences?action=changelanguages', text => 'Change Language'}); $r->print(Apache::loncommon::start_page('Content Display Settings')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Language')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Language'). + '
'); my %userenv = &Apache::lonnet::get('environment',['languages']); my $language=$userenv{'languages'}; $r->print( '
'."\n". ''. - '
'.&mt('Preferred language').': '. - &Apache::loncommon::select_language('language',$language,1).''."\n". - '
' + '
'."\n". + '
' ); } @@ -192,8 +193,8 @@ sub texenginechanger {

-$lt{'preftxt'}: $selectionbox -
+

@@ -275,7 +276,8 @@ sub rolesprefchanger { { href => '/adm/preferences?action=changerolespref', text => $brtext}); $r->print(Apache::loncommon::start_page('Content Display Settings')); - $r->print(Apache::lonhtmlcommon::breadcrumbs($brtitle)); + $r->print(Apache::lonhtmlcommon::breadcrumbs($brtitle). + '
'); my $hotlist_flag=$userenv{'recentroles'}; my $hotlist_n=$userenv{'recentrolesn'}; my ($checkedon,$checkedoff); @@ -294,49 +296,49 @@ sub rolesprefchanger { } # Get list of recent roles and display with checkbox in front - my $roles_check_list = ''; - my $role_key=''; + my $roles_check_list; if ($env{'environment.recentroles'}) { my %recent_roles = &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'}); my %frozen_roles = &Apache::lonhtmlcommon::get_recent_frozen('roles',$env{'environment.recentrolesn'}); - + my %role_text = &rolespref_get_role_text([keys(%recent_roles)]); my @sorted_roles = sort {$role_text{$a} cmp $role_text{$b}} keys(%role_text); - $roles_check_list .= - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(). - "".&mt('Freeze '.$role)."". - "".&mt($role)."". - &Apache::loncommon::end_data_table_header_row(). - "\n"; - my $count; - foreach $role_key (@sorted_roles) { - my $checked = ""; - my $value = $recent_roles{$role_key}; - if ($frozen_roles{$role_key}) { - $checked = ' checked="checked"'; - } - $count++; - $roles_check_list .= - &Apache::loncommon::start_data_table_row(). - ''. - "". - "". - &Apache::loncommon::end_data_table_row(). "\n"; + if (@sorted_roles) { + $roles_check_list = + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + "".&mt('Freeze '.$role)."". + "".&mt($role)."". + &Apache::loncommon::end_data_table_header_row()."\n"; + my $count = 0; + foreach my $role_key (@sorted_roles) { + my $checked = ""; + my $value = $recent_roles{$role_key}; + if ($frozen_roles{$role_key}) { + $checked = ' checked="checked"'; + } + $count++; + $roles_check_list .= + &Apache::loncommon::start_data_table_row(). + ''. + "". + "". + &Apache::loncommon::end_data_table_row(). "\n"; + } + $roles_check_list .= &Apache::loncommon::end_data_table."\n"; } - $roles_check_list .= "\n"; } my $actionurl = '/adm/preferences'; if ($env{'form.returnurl'} eq '/adm/roles') { $actionurl = '/adm/roles'; } - $r->print('

'.&mt('Recent Roles Hotlist').'

'); + $r->print('

'.&mt('Recent Roles Hotlist').'

'); unless ($checkedon) { $r->print(&mt('LON-CAPA users with several '.$lc_role.'s may wish to enable the Hotlist.').'
'); } @@ -344,7 +346,7 @@ sub rolesprefchanger {
-

'.&mt('Hotlist options').'

+

'.&mt('Hotlist options').'

'. &mt('When enabled, the Hotlist keeps track of the last N '.$lc_role.'s visited.').'
'. &mt('Those N '.$lc_role.'s are then shown in a table at the top of the '.$lc_role.'s page.').'

'. @@ -363,9 +365,9 @@ $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('Freeze Roles').'

'.&mt('The table below can be used to [_1]freeze[_2] '.$lc_role.'s in the Hotlist.','','').'
'. &mt('Those '.$lc_role.'s marked frozen will not be removed from the list, even if not recently used.').'

@@ -378,7 +380,7 @@ $options.' $r->print('
-'); +
'); } sub rolespref_get_role_text { @@ -491,24 +493,22 @@ sub screennamechanger { text => 'Change Screen Name'}); $r->print(Apache::loncommon::start_page('Personal Data')); $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Screen Name')); - $r->print('

' - .&mt('Change the name that is displayed in your posts.') - .'

' - ); + $r->print('
'); + my $caption = &mt('Name displayed in posts you make').':'; $r->print('
' - .'' - .&Apache::lonhtmlcommon::start_pick_box() - .&Apache::lonhtmlcommon::row_title(&mt('Screenname').' '.&mt('(shown if you post anonymously)')) - .'' + .'

' + .&Apache::lonhtmlcommon::start_pick_box(undef,undef,$caption,'LC_caption_prefs') + .&Apache::lonhtmlcommon::row_title(' '.&mt('(shown if you post anonymously)')) + .'' .&Apache::lonhtmlcommon::row_closure() - .&Apache::lonhtmlcommon::row_title(&mt('Nickname').' '.&mt('(shown if you post non-anonymously)')) - .'' + .&Apache::lonhtmlcommon::row_title(' '.&mt('(shown if you post non-anonymously)')) + .'' .&Apache::lonhtmlcommon::row_closure() - .&Apache::lonhtmlcommon::row_title() + .&Apache::lonhtmlcommon::row_title(''.&mt('Submit').':','','','',1) .'' .&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box() - .'

' + .'

' ); } @@ -556,7 +556,8 @@ sub iconchanger { { href => '/adm/preferences?action=changeicons', text => 'Change Menu Display'}); $r->print(Apache::loncommon::start_page('Page Display Settings')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Menu Display')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Menu Display'). + '
'); my $user = $env{'user.name'}; my $domain = $env{'user.domain'}; @@ -591,14 +592,19 @@ sub iconchanger { '
    '. $iconic_preview. '
'; + my $title = &mt('Use of icons and text'); $r->print(< +
$title $iconic_preview
$iconsonly_preview
+
+

- +

+
ENDSCREEN } @@ -627,7 +633,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 +642,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); @@ -657,7 +663,8 @@ sub clickerchanger { { href => '/adm/preferences?action=changeclicker', text => 'Register Clicker'}); $r->print(Apache::loncommon::start_page('Other')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Register Clicker')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Register Clicker'). + '
'); my $user = $env{'user.name'}; my $domain = $env{'user.domain'}; my %userenv = &Apache::lonnet::get @@ -668,14 +675,17 @@ sub clickerchanger { my $change=&mt('Save'); my $helplink=&Apache::loncommon::help_open_topic('Clicker_Registration',&mt('Locating your clicker ID')); $r->print(<
-
+

+

+
ENDSCREEN } @@ -848,14 +858,24 @@ sub msgforwardchanger { notv => 'is not a valid e-mail address', toen => "To enter multiple addresses, enter one address at a time, click 'Change' and then add the next one", prme => 'Back', + acti => 'Action', + type => 'Types of message for which notification is sent', + nota => 'Notification address', + exce => 'Excerpt retains HTML tags in message', + modi => 'Modify', + dele => 'Delete', + addn => 'Add new address', + yes => 'Yes', + no => 'No', ); $lt{'foad_exmpl'} = &mt('e.g. [_1]userA:domain1,userB:domain2,...[_2]','',''); $lt{'mnot_exmpl'} = &mt('e.g. [_1]joe@doe.com[_2]','',''); Apache::lonhtmlcommon::add_breadcrumb( { href => '/adm/preferences?action=changemsgforward', - text => 'Messages & Notifications'}); + text => 'Messages & Notifications'}); $r->print(Apache::loncommon::start_page('Messages & Notifications')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Messages & Notifications')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Messages & Notifications'). + '
'); my $forwardingHelp = &Apache::loncommon::help_open_topic("Prefs_Forwarding"); my $notificationHelp = &Apache::loncommon::help_open_topic("Prefs_Notification"); my $criticalMessageHelp = &Apache::loncommon::help_open_topic("Course_Critical_Message"); @@ -864,6 +884,7 @@ sub msgforwardchanger { my $validatescript = &Apache::lonhtmlcommon::javascript_valid_email(); my $jscript = qq| |; $r->print(<$lt{'fwdm'} $forwardingHelp +

$lt{'fwdm'} $forwardingHelp

-$lt{'foad'} ($lt{'foad_exmpl'}): - -

-

$lt{'noti'} $notificationHelp

-$lt{'mnot'} ($lt{'mnot_exmpl'}):
+ ($lt{'foad_exmpl'}): + +

+

$lt{'noti'} $notificationHelp

+$lt{'mnot'} ($lt{'mnot_exmpl'}):
ENDMSG - my @sortforwards = sort (keys(%allnot)); + my @sortnotify = sort (keys(%allnot)); my $output = &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). - ' '. - ''.&mt('Action').''. - ''.&mt('Notification address').''. - &mt('Types of message for which notification is sent'). + '#'. + ''.$lt{'acti'}.''. + ''.$lt{'nota'}.''. + $lt{'type'}. $criticalMessageHelp.''. - &mt('Excerpt retains HTML tags in message').''. + $lt{'exce'}.''. &Apache::loncommon::end_data_table_header_row(); my $num = 0; my $counter = 1; - foreach my $item (@sortforwards) { - $output .= &Apache::loncommon::start_data_table_row(). + foreach my $item (@sortnotify) { + $output .= &Apache::loncommon::start_data_table_row('LC_prefs_row'). ''.$counter.''. '   '. + $lt{'modi'}.' '.(' ' x2). ''. - ''; + ')" aria-labelledby="LC_email_notify" />'; my %chk; if (defined($allnot{$item}{'crit'})) { if (defined($allnot{$item}{'reg'})) { @@ -966,13 +989,15 @@ ENDMSG } else { $chk{'reg'} = 'checked="checked" '; } + $output .= '
'.$lt{'type'}.''; foreach my $type ('all','crit','reg') { $output .= ''.(' ' x4); + $lt{$type}.' '.(' ' x2); } + $output .= '
'; my $htmlon = ''; my $htmloff = ''; if (grep/^\Q$item\E/,@allow_html) { @@ -980,14 +1005,16 @@ ENDMSG } else { $htmloff = 'checked="checked" '; } - $output .= ' '.(' ' x2). ''. + $lt{'no'}.''. &Apache::loncommon::end_data_table_row(); $num ++; $counter ++; @@ -997,24 +1024,27 @@ ENDMSG crit => '', reg => '', ); - $output .= &Apache::loncommon::start_data_table_row(). + $output .= &Apache::loncommon::start_data_table_row('LC_prefs_row'). ''.$counter.''. ''. - ''; + '" value="1" />'.$lt{'addn'}.''. + ''; + $output .= '
'.$lt{'type'}.''; foreach my $type ('all','crit','reg') { $output .= ''.(' ' x4); + $lt{$type}.' '.(' ' x2); } - $output .= ''.(' ' x3). + $output .= '
'. + '
'.$lt{'exce'}.''. + ' '.(' ' x2). ''. + $lt{'no'}.'
'. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); $num ++; @@ -1024,7 +1054,7 @@ ENDMSG -
+
|); } @@ -1158,7 +1188,8 @@ sub colorschanger { { href => '/adm/preferences?action=changecolors', text => 'Change Colors'}); $r->print(Apache::loncommon::start_page('Page Display Settings')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Colors')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Colors'). + '
'); # figure out colors my $function=&Apache::loncommon::get_users_function(); my $domain=&Apache::loncommon::determinedomain(); @@ -1172,13 +1203,18 @@ sub colorschanger { 'vlink' => 'Visited Link Color', 'alink' => 'Active Link Color', ); - my $start_data_table = &Apache::loncommon::start_data_table(); + my $start_data_table = &Apache::loncommon::start_data_table(). + &Apache::loncommon::data_table_caption(&mt('Colors for LON-CAPA pages')). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Page Element').''.&mt('Color').''. + &Apache::loncommon::end_data_table_header_row(); my $chtable=''; foreach my $item (sort(keys(%colortypes))) { my $curcol=&Apache::loncommon::designparm($function.'.'.$item,$domain); $chtable.=&Apache::loncommon::start_data_table_row(). - ''.$colortypes{$item}.''.$colortypes{$item}.''. + ''. &Apache::loncommon::end_data_table_row()."\n"; } @@ -1189,7 +1225,8 @@ sub colorschanger { my $resetbuttondesc = &mt('Reset All Colors to Default'); my $colorchooser=&Apache::lonhtmlcommon::color_picker(); $r->print(' '); $r->print(< +
$start_data_table @@ -1209,7 +1247,7 @@ $end_data_table

-
+
ENDCOL } @@ -1265,19 +1303,15 @@ 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'}); unless ($caller eq 'reset_by_email') { $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; + $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Password'). + '
'); } if ((!defined($caller)) || ($caller eq 'preferences')) { $user = $env{'user.name'}; @@ -1285,6 +1319,12 @@ sub passwordchanger { 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 +1341,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( '

' @@ -1326,13 +1372,18 @@ sub passwordchanger { $r->print( '

' .&mt('Page requested in unexpected context') - .'

' + .'

' ); return; } my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain); # Check for authentication types that allow changing of the password. - return if ($currentauth !~ /^(unix|internal):/); + if ($currentauth !~ /^(unix|internal):/) { + unless ($caller eq 'reset_by_email') { + $r->print('
'); + } + return; + } # # Generate keys my ($lkey_cpass ,$ukey_cpass ) = &Apache::loncommon::des_keys(); @@ -1360,28 +1411,124 @@ 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(< +

ENDFORM $r->print(&server_form($logtoken,$caller,$mailtoken,$extrafields)); $r->print(&client_form($caller,\%hexkey,$currentpass,$domain,$extrafields)); - + unless ($caller eq 'reset_by_email') { + $r->print(''); + } # return; } sub jscript_send { - my ($caller,$extrafields) = @_; + my ($caller,$domain,$currentauth,$extrafields) = @_; + my ($min,$max,$rulestr,$numrules); + $min = $Apache::lonnet::passwdmin; + my %js_lt = &Apache::lonlocal::texthash( + uc => '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| |; } @@ -1444,7 +1592,7 @@ sub client_form { .&Apache::lonhtmlcommon::row_closure(); } if ((ref($extrafields) eq 'HASH') && ($extrafields->{'username'})) { - $output .= &Apache::lonhtmlcommon::row_title( + $output .= &Apache::lonhtmlcommon::row_title( '') .'' .&Apache::lonhtmlcommon::row_closure() @@ -1456,16 +1604,16 @@ sub client_form { } else { $output .= &Apache::lonhtmlcommon::row_title( '') - .'' + .'' .&Apache::lonhtmlcommon::row_closure(); } $output .= &Apache::lonhtmlcommon::row_title( '') - .'' + .'' .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title( '') - .'' + .'' .&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box(); if ($caller eq 'reset_by_email') { @@ -1480,7 +1628,6 @@ sub client_form { -

|; return $output; } @@ -1522,14 +1669,8 @@ sub server_form { } sub verify_and_change_password { - my ($r,$caller,$mailtoken,$ended) = @_; - my ($user,$domain,$homeserver); - my ($blocked,$blocktext) = - &Apache::loncommon::blocking_status('passwd'); - if ($blocked) { - $r->print('

'.$blocktext.'

'); - return; - } + my ($r,$caller,$mailtoken,$timelimit,$extrafields,$ended) = @_; + my ($user,$domain,$homeserver,$clientip); if ($caller eq 'reset_by_email') { $user = $env{'form.uname'}; $domain = $env{'form.udom'}; @@ -1538,20 +1679,31 @@ sub verify_and_change_password { if ($homeserver eq 'no_host') { &passwordchanger($r,"

\n". &mt("Invalid username and/or domain")."\n

", - $caller,$mailtoken); - return 1; + $caller,$mailtoken,$timelimit,$extrafields); + return 'no_host'; } } else { &passwordchanger($r,"

\n". &mt("Username and domain were blank")."\n

", - $caller,$mailtoken); - return 1; + $caller,$mailtoken,$timelimit,$extrafields); + return 'missingdata'; } } else { $user = $env{'user.name'}; $domain = $env{'user.domain'}; $homeserver = $env{'user.home'}; } + $clientip = &Apache::lonnet::get_requestor_ip($r); + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('passwd',$clientip,$user,$domain); + if ($blocked) { + $r->print('

'.$blocktext.'

'); + if ($caller eq 'reset_by_email') { + return 'blocked'; + } else { + return; + } + } my $currentauth=&Apache::lonnet::queryauthenticate($user,$domain); # Check for authentication types that allow changing of the password. if ($currentauth !~ /^(unix|internal):/) { @@ -1559,8 +1711,8 @@ sub verify_and_change_password { &passwordchanger($r,"

\n". &mt("Authentication type for this user can not be changed by this mechanism"). "\n

", - $caller,$mailtoken); - return 1; + $caller,$mailtoken,$timelimit,$extrafields); + return 'otherauth'; } else { return; } @@ -1576,8 +1728,12 @@ sub verify_and_change_password { defined($newpass2) ){ &passwordchanger($r,"

\n". &mt("One or more password fields were blank"). - "\n

",$caller,$mailtoken); - return; + "\n

",$caller,$mailtoken,$timelimit,$extrafields); + if ($caller eq 'reset_by_email') { + return 'missingdata'; + } else { + return; + } } # Get the keys my $lonhost = $r->dir_config('lonHostID'); @@ -1595,7 +1751,11 @@ sub verify_and_change_password {

ENDERROR # Probably should log an error here - return 1; + if ($caller eq 'reset_by_email') { + return 'internalerror'; + } else { + return; + } } my ($ckey,$n1key,$n2key)=split(/&/,$tmpinfo); # @@ -1609,101 +1769,52 @@ ENDERROR &passwordchanger($r, ''. &mt('Could not verify current authentication.').' '. - &mt('Please try again.').'',$caller,$mailtoken); - return 1; + &mt('Please try again.').'',$caller,$mailtoken,$timelimit,$extrafields); + return 'emptydata'; } if ($currentpass ne $data{'temppasswd'}) { &passwordchanger($r, ''. &mt('Could not verify current authentication.').' '. - &mt('Please try again.').'',$caller,$mailtoken); - return 1; + &mt('Please try again.').'',$caller,$mailtoken,$timelimit,$extrafields); + return 'missingtemp'; } } if ($newpass1 ne $newpass2) { &passwordchanger($r, ''. &mt('The new passwords you entered do not match.').' '. - &mt('Please try again.').'',$caller,$mailtoken); - return 1; + &mt('Please try again.').'',$caller,$mailtoken,$timelimit,$extrafields); + if ($caller eq 'reset_by_email') { + return 'mismatch'; + } else { + return; + } } if ($currentauth eq 'unix:') { if (length($newpass1) < 7) { &passwordchanger($r, ''. &mt('Passwords must be a minimum of 7 characters long.').' '. - &mt('Please try again.').'',$caller,$mailtoken); - return 1; - } - } else { - my %passwdconf = &Apache::lonnet::get_passwdconf($domain); - my ($min,$max,@chars,@brokerule); - if (ref($passwdconf{'chars'}) eq 'ARRAY') { - if ($passwdconf{'min'} =~ /^\d+$/) { - $min = $passwdconf{'min'}; - } - if ($passwdconf{'max'} =~ /^\d+$/) { - $max = $passwdconf{'max'}; - } - @chars = @{$passwdconf{'chars'}}; - } else { - $min = 7; - } - if (($min) && (length($newpass1) < $min)) { - push(@brokerule,'min'); - } - if (($max) && (length($newpass1) > $max)) { - push(@brokerule,'max'); - } - if (@chars) { - my %rules; - map { $rules{$_} = 1; } @chars; - if ($rules{'uc'}) { - unless ($newpass1 =~ /[A-Z]/) { - push(@brokerule,'uc'); - } - } - if ($rules{'lc'}) { - unless ($newpass1 =~ /a-z/) { - push(@brokerule,'lc'); - } - } - if ($rules{'num'}) { - unless ($newpass1 =~ /\d/) { - push(@brokerule,'num'); - } - } - if ($rules{'spec'}) { - unless ($newpass1 =~ /[!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/) { - push(@brokerule,'spec'); - } + &mt('Please try again.').'',$caller,$mailtoken,$timelimit,$extrafields); + if ($caller eq 'reset_by_email') { + return 'length'; + } else { + return; } } - if (@brokerule) { - 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', - ); - $rulenames{'uc'} .= ': ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $rulenames{'lc'} .= ': abcdefghijklmnopqrstuvwxyz'; - $rulenames{'num'} .= ': 0123456789'; - $rulenames{'spec'} .= ': !"\#$%&\'()*+,-./:;<=>?@[\]^_\`{|}~'; - $rulenames{'min'} = &mt('Minimum password length: [_1]',$min); - $rulenames{'max'} = &mt('Maximum password length: [_1]',$max); - my $warning = &mt('Password did not satisfy the following:').''; + } else { + my $warning = &Apache::loncommon::check_passwd_rules($domain,$newpass1); + if ($warning) { &passwordchanger($r,''. $warning. &mt('Please try again.').'', - $caller,$mailtoken); - return 1; + $caller,$mailtoken,$timelimit,$extrafields); + if ($caller eq 'reset_by_email') { + return 'rules'; + } else { + return; + } } } # @@ -1723,8 +1834,12 @@ ENDERROR ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_\`abcdefghijklmnopqrstuvwxyz{|}~ ENDERROR - &passwordchanger($r,$errormessage,$caller,$mailtoken); - return 1; + &passwordchanger($r,$errormessage,$caller,$mailtoken,$timelimit,$extrafields); + if ($caller eq 'reset_by_email') { + return 'badchars'; + } else { + return; + } } # # Change the password (finally) @@ -1747,7 +1862,7 @@ ENDERROR # error error: run in circles, scream and shout if ($caller eq 'reset_by_email') { if (!$result) { - return 1; + return 'error'; } else { return $result; } @@ -1779,7 +1894,8 @@ sub discussionchanger { { href => '/adm/preferences?action=changediscussions', text => 'Change Discussion Preferences'}); $r->print(Apache::loncommon::start_page('Change Discussion Preferences')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Discussion Preferences')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Discussion Preferences'). + '
'); my $user = $env{'user.name'}; my $domain = $env{'user.domain'}; my %userenv = &Apache::lonnet::get @@ -1847,15 +1963,15 @@ END $r->print('

'.$lt{'thde'}.'

'); - $r->print(&Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row()); $r->print(<<"END"); - $lt{'pref'} $lt{'curr'} $lt{'actn'}? - END - $r->print(&Apache::loncommon::start_data_table_row()); + $r->print(&Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_row()); $r->print(<<"END"); $lt{'disa'} $lt{$discdisp} @@ -1867,14 +1983,13 @@ END $lt{'npmr'} $lt{$discmark} - END $r->print(&Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table()); $r->print('
' .'' - .'' + .'
' ); } @@ -2009,9 +2124,117 @@ sub author_space_settings { my $domain = $env{'user.domain'}; my %author_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au','ca','aa']); if (keys(%author_roles) > 0) { - $r->print(Apache::loncommon::start_page('Authoring Space Settings')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Authoring Space Settings')); - my %userenv = &Apache::lonnet::get('environment',['nocodemirror']); + my ($showdomdefs,$js,$args,@items); + my $returnurl = &HTML::Entities::encode($env{'form.returnurl'},'"<>&\''); + if (&expanded_authoring_settings()) { + @items = ('nocodemirror'); + if (&daxe_permitted(\%author_roles)) { + push(@items,'daxecollapse'); + } + push(@items,('copyright','sourceavail')); + $showdomdefs = 1; + $js = &toggle_options_js(); + my $onload; + foreach my $item (@items) { + $onload .= "javascript:toggleOptions(document.prefs,'$item','user_$item');" + } + $args = { 'add_entries' => { 'onload' => $onload } }; + } + $r->print(Apache::loncommon::start_page('Authoring Space Settings',$js,$args)); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Authoring Space Settings')); + if ($showdomdefs) { + my %userenv = &Apache::lonnet::get('environment',\@items); + my %domdefs = &Apache::lonnet::get_domain_defaults($domain); + my %staticdefaults = ( + 'nocodemirror' => '0', + 'daxecollapse' => '0', + 'copyright' => 'default', + 'sourceavail' => 'closed', + ); + my %lt = &authoring_settings_text(); + my %titles = &authoring_settings_titles(); + $r->print("

$lt{'auss'}

". + '
'."\n". + '

'."\n". + ''."\n". + ''."\n"); + foreach my $item (@items) { + my ($domdef,$checkeddom,$checkeduser,$domdefdisplay,$divsty,$userelem); + $checkeddom = ' checked="checked"'; + $divsty = 'display:none'; + if (exists($domdefs{$item})) { + $domdef = $domdefs{$item}; + } else { + $domdef = $staticdefaults{$item}; + } + if ($item eq 'copyright') { + $domdefdisplay = &Apache::loncommon::copyrightdescription($domdef); + $userelem = &selectbox('userchoice_'.$item,$userenv{$item},'', + \&Apache::loncommon::copyrightdescription, + (grep !/^priv|custom$/,(&Apache::loncommon::copyrightids))); + } elsif ($item eq 'sourceavail') { + $domdefdisplay = &Apache::loncommon::source_copyrightdescription($domdef); + $userelem = &selectbox('userchoice_'.$item,$userenv{$item},'', + \&Apache::loncommon::source_copyrightdescription, + (&Apache::loncommon::source_copyrightids)); + } elsif (($item eq 'nocodemirror') || ($item eq 'daxecollapse')) { + if ($domdef) { + if ($item eq 'daxecollapse') { + $domdefdisplay = $lt{'coll'}; + } else { + $domdefdisplay = $lt{'yes'}; + } + } else { + if ($item eq 'daxecollapse') { + $domdefdisplay = $lt{'expa'}; + } else { + $domdefdisplay = $lt{'no'}; + } + } + my (%checked,%text); + $checked{'no'} = ' checked="checked"'; + if ($userenv{$item} eq 'yes') { + $checked{'yes'} = $checked{'no'}; + $checked{'no'} = ''; + } + if ($item eq 'daxecollapse') { + %text = ( + yes => $lt{'coll'}, + no => $lt{'expa'}, + ); + } else { + %text = ( + yes => $lt{'yes'}, + no => $lt{'no'}, + ); + } + $userelem = ''; + foreach my $choice ('yes','no') { + $userelem .= '   '; + } + $userelem .= ''; + } + if ($userenv{$item} ne '') { + $checkeduser = $checkeddom; + $checkeddom = ''; + $divsty = 'display:inline-block'; + } + $r->print(<<"END"); +

$titles{$item}

+

$lt{'curd'}: $domdefdisplay

+

+    +

+
+$lt{'ousv'} +$userelem +


+END + } + $r->print(''. + '
'."\n"); + } else { my $constchecked=''; if ($env{'environment.nocodemirror'}) { $constchecked=' checked="checked"'; @@ -2019,7 +2242,6 @@ sub author_space_settings { my $text=&mt('By default, CodeMirror an editor with advanced functionality for editing code is activated for authors.'); my $cmoff=&mt('Deactivate CodeMirror. This can improve performance on slow computers and accessibility.'); my $change=&mt('Save'); - my $returnurl = &HTML::Entities::encode($env{'form.returnurl'},'"<>&\''); $r->print(< @@ -2029,6 +2251,7 @@ sub author_space_settings { ENDSCREEN + } } } @@ -2038,6 +2261,8 @@ sub change_authoring_settings { my $domain = $env{'user.domain'}; my %author_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au','ca','aa']); if (keys(%author_roles) > 0) { + my $message; + if (!&expanded_authoring_settings()) { my %ausettings=('environment.nocodemirror' => ''); if ($env{'form.cmoff'}) { $ausettings{'environment.nocodemirror'}='yes'; } &Apache::lonnet::put('environment',\%ausettings); @@ -2048,25 +2273,195 @@ sub change_authoring_settings { } else { $status=&mt('off'); } - my $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]',''.&mt('Deactivate CodeMirror in Authoring Space').'',''.$status.'')); + $message=&Apache::lonhtmlcommon::confirm_success(&mt('Set [_1] to [_2]',''.&mt('Deactivate CodeMirror in Authoring Space').'',''.$status.'')); $message=&Apache::loncommon::confirmwrapper($message); - if ($env{'form.returnurl'}) { - &do_redirect($r,$env{'form.returnurl'},$message); + } else { + my @items = ('nocodemirror'); + if (&daxe_permitted(\%author_roles)) { + push(@items,'daxecollapse'); + } + push(@items,('copyright','sourceavail')); + my %oldsettings = &Apache::lonnet::get('environment',\@items); + my %domdefs = &Apache::lonnet::get_domain_defaults($domain); + my %lt = &authoring_settings_text(); + my %titles = &authoring_settings_titles(); + my ($result,%newsettings,%changes,@delete,@unchanged,@delerrors,@adderrors); + foreach my $item (@items) { + if ($env{'form.'.$item} eq 'dom') { + if ($oldsettings{$item} eq '') { + push(@unchanged,$item); + } else { + push(@delete,$item); + } + } elsif ($env{'form.'.$item} eq 'user') { + my $newval = $env{'form.userchoice_'.$item}; + my @possibles; + if (($item eq 'nocodemirror') || ($item eq 'daxecollapse')) { + if ($newval =~ /^yes|no$/) { + $newsettings{$item} = $newval; + } + } elsif ($item eq 'copyright') { + @possibles = (grep !/^priv|custom$/,(&Apache::loncommon::copyrightids)); + if (grep(/^\Q$newval\E$/,@possibles)) { + $newsettings{$item} = $newval; + } + } elsif ($item eq 'sourceavail') { + @possibles = (&Apache::loncommon::source_copyrightids); + if (grep(/^\Q$newval\E$/,@possibles)) { + $newsettings{$item} = $newval; + } + } + if ($oldsettings{$item} eq $newsettings{$item}) { + push(@unchanged,$item); + } else { + $changes{$item} = $newsettings{$item}; + } + } + } + if (@delete) { + if (&Apache::lonnet::del('environment',\@delete) eq 'ok') { + foreach my $key (@delete) { + &Apache::lonnet::delenv('environment.'.$key); + } + } else { + @delerrors = @delete; + } + } + if (keys(%changes)) { + if (&Apache::lonnet::put('environment',\%changes) eq 'ok') { + my %newenvhash; + map {$newenvhash{'environment.'.$_} = $changes{$_}; } (keys(%changes)); + &Apache::lonnet::appenv(\%newenvhash); + } else { + foreach my $item (@items) { + if (exists($changes{$item})) { + push(@adderrors,$item); + } + } + } + } + if (@adderrors) { + $result = &mt('An error occurred when saving user-specific settings for').': '. + join(', ', map { $titles{$_} } @adderrors); + $message = &Apache::loncommon::confirmwrapper(&Apache::lonhtmlcommon::confirm_success($result,1)); + } elsif (keys(%changes)) { + $result = &mt('User-specific settings saved:').'
    '; + foreach my $item (@items) { + next unless (exists($changes{$item})); + my $value = $changes{$item}; + if ($item eq 'nocodemirror') { + $value = $lt{$changes{$item}}; + } elsif ($item eq 'daxecollapse') { + if ($value eq 'yes') { + $value = $lt{'coll'}; + } else { + $value = $lt{'expa'}; + } + } elsif ($item eq 'copyright') { + $value = &Apache::loncommon::copyrightdescription($changes{$item}); + } elsif ($item eq 'sourceavail') { + $value = &Apache::loncommon::source_copyrightdescription($changes{$item}); + } + $result .= '
  • '. + &mt('[_1] set to [_2]', + $titles{$item}, + ''.$value.''). + '
  • '; + } + $result .= '
'; + $message = &Apache::loncommon::confirmwrapper(&Apache::lonhtmlcommon::confirm_success($result)); + } + if (@delerrors) { + $result = &mt('An error occurred when deleting user-specific settings for').':
  • '. + join('
  • ', map { $titles{$_} } @delerrors).'
'; + $message .= &Apache::loncommon::confirmwrapper(&Apache::lonhtmlcommon::confirm_success($result,1)); + } elsif (@delete) { + $result = &mt('Set use of domain default for').':
  • '. + join('
  • ', map { $titles{$_} } @delete).'
'; + $message .= &Apache::loncommon::confirmwrapper(&Apache::lonhtmlcommon::confirm_success($result)); + } + if (@unchanged) { + $result = &mt('No changes made for').':
  • '. + join('
  • ', map { $titles{$_} } @unchanged).'
'; + $message .= &Apache::loncommon::confirmwrapper(&Apache::lonhtmlcommon::confirm_success($result)); + } + } + if ($env{'form.returnurl'}) { + &do_redirect($r,$env{'form.returnurl'},$message); + } else { + &print_main_menu($r,$message); + } + } +} + +sub authoring_settings_text { + return &Apache::lonlocal::texthash( + 'auss' => 'Authoring Space Settings', + 'used' => 'Use domain default', + 'usyo' => 'Use your own user-specific setting', + 'curd' => 'Current domain default is', + 'ousv' => 'Own user-specific value', + 'save' => 'Save', + 'yes' => 'Deactivated', + 'no' => 'Activated', + 'expa' => 'Start Expanded', + 'coll' => 'Start Collapsed', + ); +} + +sub authoring_settings_titles { + return &Apache::lonlocal::texthash( + 'nocodemirror' => 'CodeMirror for EditXML editor', + 'daxecollapse' => 'Daxe editor: collapsible standard LON-CAPA menus', + 'copyright' => 'Default Copyright/Distribution in new metadata file', + 'sourceavail' => 'Default Source Available in new metadata file', + ); +} + +sub expanded_authoring_settings { + my $reqdmajor = 2; + my $reqdminor = 12; + my $loncaparev = &Apache::lonnet::get_server_loncaparev($env{'user.domain'},$env{'user.home'}); + my ($major,$minor) = ($loncaparev =~ /^\'?(\d+)\.(\d+)\.[\w.\-]+\'?$/); + unless (($major eq '' && $minor eq '') || + ($reqdmajor > $major) || (($reqdmajor == $major) && ($reqdminor > $minor))) { + return 1; + } + return; +} + +sub daxe_permitted { + my ($aurolesref) = @_; + my $hasdaxe; + if (ref($aurolesref) eq 'HASH') { + my %editors; + foreach my $key (keys(%{$aurolesref})) { + if ($key =~ /^:$LONCAPA::match_domain:au$/) { + if (exists($env{'environment.editors'})) { + if (grep(/^daxe$/,split(/,/,$env{'environment.editors'}))) { + $hasdaxe = 1; + last; + } + } } else { - &print_main_menu($r,$message); + my ($auname,$audom) = ($key =~ /^($LONCAPA::match_username):($LONCAPA::match_domain):(ca|aa)$/); + if (exists($env{"environment.internal.editors./$audom/$auname"})) { + if (grep(/^daxe$/,split(/,/,$env{"environment.internal.editors./$audom/$auname"}))) { + $hasdaxe = 1; + last; + } + } } + } } + return $hasdaxe; } sub lockednameschanger { my $r = shift; - &Apache::lonhtmlcommon::add_breadcrumb( - { href => '/adm/preferences?action=changelockednames', - text => 'Automatic name changes'}); - $r->print(Apache::loncommon::start_page('Automatic name changes')); - $r->print(Apache::lonhtmlcommon::breadcrumbs('Allow/disallow name updates')); my %userenv = &Apache::lonnet::get('environment',['lockedname']); my $lockedname=''; + my $ended; if (&can_toggle_namelocking()) { if ($userenv{'lockedname'}) { $lockedname = ' checked="checked"'; @@ -2084,6 +2479,11 @@ sub lockednameschanger { } } if (keys(%updateable)) { + &Apache::lonhtmlcommon::add_breadcrumb( + { href => '/adm/preferences?action=changelockednames', + text => 'Automatic name changes'}); + $r->print(Apache::loncommon::start_page('Automatic name changes')); + $r->print(Apache::lonhtmlcommon::breadcrumbs('Allow/disallow name updates')); my %longnames = &Apache::lonlocal::texthash ( firstname => 'First Name', middlename => 'Middle Name', @@ -2110,11 +2510,14 @@ ENDSCREEN } else { my $message = &mt('Based on your institutional affiliation no name information is automatically updated for your LON-CAPA account.'); &print_main_menu($r,$message); + $ended = 1; } } else { my $message = &mt('You are not permitted to set a user preference for automatic name updates for your LON-CAPA account.'); &print_main_menu($r,$message); + $ended = 1; } + return $ended; } sub verify_and_change_lockednames { @@ -2145,6 +2548,94 @@ sub verify_and_change_lockednames { &print_main_menu($r,$message); } +sub timezonechanger { + my $r = shift; + my $uname = $env{'user.name'}; + my $udom = $env{'user.domain'}; + if (&Apache::lonnet::usertools_access($uname,$udom,'timezone')) { + my $js = &toggle_options_js(); + my %loaditems = ( + onload => "javascript:toggleOptions(document.prefs,'settimezone','LC_timezone_selector');", + ); + 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( + tztu => 'Time Zone in use', + 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:toggleOptions(this.form,'."'settimezone','LC_timezone_selector'".');"'; + my $selector = &Apache::loncommon::select_timezone('timezone',$timezone,undef,1); + $r->print(<<"END"); +
+ +
$lt{'tztu'} + +
+ +
  +$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 @@ -2159,6 +2650,11 @@ 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 %author_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au']); +my %author_coauthor_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au','ca','aa']); my @menu= ({ categorytitle=>'Personal Data', items =>[ @@ -2167,6 +2663,7 @@ my @menu= permission => $permissions{'aboutme'}, #help => 'Prefs_About_Me', icon => 'system-users.png', + alttext => 'About Me Icon', linktitle => 'Edit information about yourself that should be displayed on your public profile.' }, { linktext => 'Screen Name', @@ -2174,6 +2671,7 @@ my @menu= permission => 'F', #help => 'Prefs_Screen_Name_Nickname', icon => 'preferences-desktop-font.png', + alttext => 'Nickname Icon', linktitle => 'Change the name that is displayed in your posts.' }, ] @@ -2185,6 +2683,7 @@ my @menu= permission => 'F', #help => 'Prefs_Language', icon => 'preferences-desktop-locale.png', + alttext => 'Language Icon', linktitle => 'Choose the default language for this user.' }, { linktext => $role.' Page', @@ -2192,6 +2691,7 @@ my @menu= permission => 'F', #help => '', icon => 'role_hotlist.png', + alttext => 'Switch Role Icon', linktitle => 'Configure the roles hotlist.' }, { linktext => 'Math display settings', @@ -2199,8 +2699,18 @@ my @menu= permission => 'F', #help => '', icon => 'dismath.png', + alttext => 'Math Icon', linktitle => 'Change how math is displayed.' }, + { + linktext => 'Time Zone', + url => '/adm/preferences?action=changetimezone', + permission => $permissions{'timezone'}, + #help => '', + icon => 'timezone.png', + alttext => 'Clock Icon', + linktitle => 'Set your time zone.', + } ] }, { categorytitle=>'Page Display Settings', @@ -2210,6 +2720,7 @@ my @menu= permission => 'F', #help => 'Change_Colors', icon => 'preferences-desktop-theme.png', + alttext => 'Colors Icon', linktitle => 'Change LON-CAPA default colors.' }, { linktext => 'Menu Display', @@ -2217,6 +2728,7 @@ my @menu= permission => 'F', #help => '', icon => 'preferences-system-windows.png', + alttext => 'Menus Icon', linktitle => 'Change whether the menus are displayed with icons or icons and text.' } ] @@ -2228,6 +2740,7 @@ my @menu= permission => 'F', #help => 'Prefs_Messages', icon => 'mail-reply-all.png', + alttext => 'Notifications Icon', linktitle => 'Change messageforwarding or notifications settings.' }, { linktext => 'Discussion Display', @@ -2235,10 +2748,40 @@ my @menu= permission => 'F', #help => 'Change_Discussion_Display', icon => 'chat.png', + alttext => 'Discussions Icon', linktitle => 'Set display preferences for discussion posts for both discussion boards and individual resources in all your courses.' }, ] }, + ); +if (keys(%author_coauthor_roles) > 0) { + push(@menu, + { categorytitle=>'Authoring Settings', + items => [ + { + linktext => 'Authoring Space Configuration', + url => '/adm/preferences?action=authorsettings', + permission => 'F', + icon => 'codemirror.png', + alttext => 'Coding Icon', + linktitle => 'Settings for your authoring space.', + }, + ] + }, + ); + if (keys(%author_roles) > 0) { + push(@{ $menu[4]->{items} }, { + linktext => 'Restrict Domain Coordinator Access', + url => '/adm/preferences?action=changedomcoord', + permission => 'F', + #help => '', + icon => 'system-lock-screen.png', + alttext => 'Lock Icon', + linktitle => 'Restrict domain coordinator access.', + }); + } +} +push(@menu, { categorytitle=>'Other', items =>[ { linktext => 'Register Response Devices ("Clickers")', @@ -2246,19 +2789,21 @@ my @menu= permission => 'F', #help => '', icon => 'network-workgroup.png', + alttext => 'Clicker Icon', linktitle => 'Register your clicker.' }, ] }, - ); +); if ($currentauth =~ /^(unix|internal):/) { -push(@{ $menu[0]->{items} }, { + push(@{ $menu[0]->{items} }, { linktext => 'Password', url => '/adm/preferences?action=changepass', permission => 'F', #help => 'Change_Password', icon => 'emblem-readonly.png', + alttext => 'Secure Icon', linktitle => 'Change your password.', }); } @@ -2270,62 +2815,42 @@ push(@{ $menu[0]->{items} }, { permission => 'F', #help => '', icon => 'system-lock-screen.png', + alttext => 'Screen Lock Icon', linktitle => 'Allow/disallow propagation of name changes from institutional directory service', }); } - my %author_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au']); - if (keys(%author_roles) > 0) { -push(@{ $menu[4]->{items} }, { - linktext => 'Restrict Domain Coordinator Access', - url => '/adm/preferences?action=changedomcoord', - permission => 'F', - #help => '', - icon => 'system-lock-screen.png', - linktitle => 'Restrict domain coordinator access.', - }); - } - if (&Apache::lonnet::allowed('whn',$env{'request.course.id'}) || &Apache::lonnet::allowed('whn',$env{'request.course.id'}.'/' .$env{'request.course.sec'})) { -push(@{ $menu[4]->{items} }, { +push(@{ $menu[-1]->{items} }, { linktext => 'Course Initialization', url => '/adm/preferences?action=changecourseinit', permission => 'F', #help => '', icon => 'course_ini.png', + alttext => 'Course Launch Icon', linktitle => 'Set the default page to be displayed when you select a course role.', }); } - my %author_coauthor_roles = &Apache::lonnet::get_my_roles($user,$domain,'userroles','',['au','ca','aa']); - if (keys(%author_coauthor_roles) > 0) { - push(@{ $menu[4]->{items} }, { - linktext => 'Authoring Space Configuration', - url => '/adm/preferences?action=authorsettings', - permission => 'F', - icon => 'codemirror.png', - linktitle => 'Settings for your authoring space.', - }); - } - if (&can_toggle_debug()) { -push(@{ $menu[4]->{items} }, { +push(@{ $menu[-1]->{items} }, { linktext => 'Toggle Debug Messages (Currently '.($env{'user.debug'} ? 'on)' : 'off)'), url => '/adm/preferences?action=debugtoggle', permission => 'F', #help => '', icon => 'blog.png', + alttext => 'Debugging Icon', linktitle => 'Toggle Debug Messages.', }); } $r->print(&Apache::loncommon::start_page('My Space')); $r->print(Apache::lonhtmlcommon::breadcrumbs('Change Preferences')); - $r->print($message); - $r->print(Apache::lonhtmlcommon::generate_menu(@menu)); + $r->print('
'."\n".$message); + $r->print(Apache::lonhtmlcommon::generate_menu(@menu)."\n".'
'); $r->print(Apache::loncommon::end_page()); } @@ -2367,7 +2892,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, @@ -2379,7 +2904,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'){ @@ -2455,10 +2980,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 @@ -2540,13 +3069,66 @@ sub updateable_userinfo { sub do_redirect { my ($r,$url,$msg) = @_; $r->print( - &Apache::loncommon::start_page('Switching Server ...',undef, - {'redirect' => [0.5,$url]}). + &Apache::loncommon::start_page('Loading ...',undef, + {'redirect' => [2,$url]}). '
'."\n". "$msg\n". &Apache::loncommon::end_page()); return; } +sub toggle_options_js { + return <<"ENDSCRIPT"; + +ENDSCRIPT +} + +sub selectbox { + my ($name,$value,$readonly,$functionref,@idlist)=@_; + my $selout = ''; + return $selout; +} + 1; __END__