Annotation of loncom/interface/resetpw.pm, revision 1.53

1.1       raeburn     1: # The LearningOnline Network
                      2: # Allow access to password changing via a token sent to user's e-mail. 
                      3: #
1.53    ! raeburn     4: # $Id: resetpw.pm,v 1.52 2025/02/14 19:01:11 raeburn Exp $
1.14      bisitz      5: #
1.1       raeburn     6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: #
1.21      raeburn    29: 
                     30: =pod
                     31: 
                     32: =head1 NAME
                     33: 
1.22      raeburn    34: Apache::resetpw: reset user password.
1.21      raeburn    35: 
                     36: =head1 SYNOPSIS
                     37: 
                     38: Handles resetting of forgotten passwords.
                     39: 
                     40: This is part of the LearningOnline Network with CAPA project
                     41: described at http://www.lon-capa.org.
                     42:  
                     43: =head1 OVERVIEW
                     44: 
                     45: A user with an e-mail address associated with his/her LON-CAPA username
1.22      raeburn    46: can reset a forgotten password, using a link sent to the e-mail address
1.21      raeburn    47: if the authentication type for the account is "internal".
                     48: 
                     49: =cut
                     50: 
1.1       raeburn    51: package Apache::resetpw;
                     52: 
                     53: use strict;
                     54: use Apache::Constants qw(:common);
                     55: use Apache::lonacc;
                     56: use Apache::lonnet;
                     57: use Apache::loncommon;
1.44      raeburn    58: use Apache::lonpreferences;
1.1       raeburn    59: use Apache::lonlocal;
                     60: use LONCAPA;
1.38      raeburn    61: use HTML::Entities;
1.1       raeburn    62: 
                     63: sub handler {
                     64:     my $r = shift;
                     65:     &Apache::loncommon::content_type($r,'text/html');
                     66:     $r->send_http_header;
                     67:     if ($r->header_only) {
                     68:         return OK;
                     69:     }
                     70:     my $contact_name = &mt('LON-CAPA helpdesk');
1.27      raeburn    71:     my $origmail =  $r->dir_config('lonSupportEMail');
1.1       raeburn    72:     my $server = $r->dir_config('lonHostID');
1.19      raeburn    73:     my $defdom = &Apache::lonnet::default_login_domain();
1.27      raeburn    74:     my $contacts =
                     75:         &Apache::loncommon::build_recipient_list(undef,'helpdeskmail',
                     76:                                                  $defdom,$origmail);
                     77:     my ($contact_email) = split(',',$contacts);
1.26      raeburn    78:     my $handle = &Apache::lonnet::check_for_valid_session($r);
                     79:     my $lonidsdir=$r->dir_config('lonIDsDir');
                     80:     if ($handle ne '') {
                     81:         if ($handle=~/^publicuser\_/) {
                     82:             unlink($r->dir_config('lonIDsDir')."/$handle.id");
                     83:         } else {
                     84:             &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle);
                     85:         }
                     86:     }
1.1       raeburn    87:     &Apache::lonacc::get_posted_cgi($r);
                     88:     &Apache::lonlocal::get_language_handle($r);
                     89:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['token']);
                     90:     
                     91:     my @emailtypes = ('permanentemail','critnotification','notification');
1.38      raeburn    92:     my $uname = $env{'form.uname'};
                     93:     $uname =~ s/^\s+|\s+$//g;
                     94:     $uname = &LONCAPA::clean_username($uname);
                     95:     my $udom = &LONCAPA::clean_domain($env{'form.udom'});
1.44      raeburn    96:     my ($domdesc,$otherinst,$lookup);
1.38      raeburn    97:     if ($udom) {
                     98:         $domdesc = &Apache::lonnet::domain($udom,'description');
                     99:         if ($domdesc) {
1.40      raeburn   100:             $otherinst = 1;
                    101:             my @ids=&Apache::lonnet::current_machine_ids();
1.38      raeburn   102:             my %servers = &Apache::lonnet::internet_dom_servers($udom);
1.44      raeburn   103:             foreach my $hostid (keys(%servers)) {
                    104:                 if (grep(/^\Q$hostid\E$/,@ids)) {
1.40      raeburn   105:                     $otherinst = 0;
                    106:                     last;
                    107:                 }
1.38      raeburn   108:             }
                    109:         }
                    110:     }
1.44      raeburn   111:     my $dom_in_effect = $defdom;
                    112:     if (($udom ne '') && ($domdesc ne '')) {
                    113:         unless ($otherinst) {
                    114:             $dom_in_effect = $udom;
                    115:         }
                    116:     }
                    117:     my %passwdconf = &Apache::lonnet::get_passwdconf($dom_in_effect);
1.50      raeburn   118:     my $clientip = &Apache::lonnet::get_requestor_ip($r);
1.1       raeburn   119:     my $token = $env{'form.token'};
1.44      raeburn   120:     my $useremail = $env{'form.useremail'};
                    121:     if (($udom ne '') && (!$otherinst) && (!$token)) {
                    122:         if ($uname ne '') {
                    123:             my $uhome = &Apache::lonnet::homeserver($uname,$udom);
                    124:             if ($uhome eq 'no_host') {
                    125:                 my %srch = (srchby     => 'uname_ci',
                    126:                             srchdomain => $udom,
                    127:                             srchterm   => $uname,
                    128:                             srchtype   => 'exact');
                    129:                 my %srch_results = &Apache::lonnet::usersearch(\%srch);
                    130:                 if (keys(%srch_results) > 1) {
                    131:                     $lookup = 'nonunique';
                    132:                     if ($useremail =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) {
                    133:                         foreach my $key (keys(%srch_results)) {
                    134:                             if (ref($srch_results{$key}) eq 'HASH') {
                    135:                                 if ($srch_results{$key}{permanentemail} =~ /^\Q$useremail\E$/i) {
                    136:                                     ($uname) = split(/:/,$key);
                    137:                                     undef($lookup);
                    138:                                     last;
                    139:                                 }
                    140:                             }
                    141:                         }
                    142:                     }
                    143:                 } elsif (keys(%srch_results) == 1) {
                    144:                     my $match = (keys(%srch_results))[0];
                    145:                     ($uname) = split(/:/,$match);
                    146:                 } else {
                    147:                     $lookup = 'nomatch';
                    148:                 }
                    149:             }
                    150:         }
                    151:         if (($lookup eq 'nomatch') || ($uname eq '')) {
                    152:             if (($useremail =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) &&
                    153:                 ($passwdconf{'resetprelink'} eq 'either')) {
                    154:                 my %srch = (srchby     => 'email',
                    155:                             srchdomain => $udom,
                    156:                             srchterm   => $useremail,
                    157:                             srchtype   => 'exact');
                    158:                 my %srch_results = &Apache::lonnet::usersearch(\%srch);
                    159:                 if (keys(%srch_results) > 1) {
                    160:                     $lookup = 'nonunique';
                    161:                 } elsif (keys(%srch_results) == 1) {
                    162:                     my $match = (keys(%srch_results))[0];
                    163:                     ($uname) = split(/:/,$match);
                    164:                     undef($lookup);
                    165:                 } else {
                    166:                     $lookup = 'nomatch';
                    167:                 }
                    168:             }
                    169:         }
                    170:     }
1.26      raeburn   171:     my $brcrum = [];
                    172:     if ($token) {
                    173:         push (@{$brcrum},
                    174:             {href => '/adm/resetpw',
                    175:              text => 'Update Password'});
                    176:     } else {
                    177:         push (@{$brcrum},
                    178:             {href => '/adm/resetpw',
                    179:              text => 'Account Information'});
                    180:         if ($uname && $udom) {
                    181:             push (@{$brcrum},
                    182:                 {href => '/adm/resetpw',
                    183:                  text => 'Result'});
                    184:         }
                    185:     }
1.33      bisitz    186:     my $args = {bread_crumbs => $brcrum};
1.38      raeburn   187:     my $js;
                    188:     unless ($token || $otherinst || ($uname && $udom)) {
                    189:         my (@intdoms,@instdoms);
                    190:         my $internet_names = &Apache::lonnet::get_internet_names($server);
                    191:         if (ref($internet_names) eq 'ARRAY') {
                    192:             @intdoms = @{$internet_names};
                    193:         }
                    194:         if (@intdoms) {
                    195:             my %iphost = &Apache::lonnet::get_iphost();
                    196:             foreach my $ip (keys(%iphost)) {
                    197:                 if (ref($iphost{$ip}) eq 'ARRAY') {
                    198:                     foreach my $id (@{$iphost{$ip}}) {
                    199:                         my $location = &Apache::lonnet::internet_dom($id);
                    200:                         if ($location) {
                    201:                             if (grep(/^\Q$location\E$/,@intdoms)) {
                    202:                                 my $dom = &Apache::lonnet::host_domain($id);
                    203:                                 unless (grep(/^\Q$dom\E/,@instdoms)) {
                    204:                                     push(@instdoms,$dom);
                    205:                                 }
                    206:                             }
                    207:                         }
                    208:                     }
                    209:                 }
                    210:             }
                    211:         }
                    212:         my $instdomstr;
                    213:         if (@instdoms > 0) {
                    214:             $instdomstr = "'".join("','",@instdoms)."'";
                    215:         }
                    216:         my %js_lt = &Apache::lonlocal::texthash(
                    217:             thdo  => 'The domain you have selected is for another institution.',
                    218:             yowi  => 'You will be switched to the Forgot Password utility at that institution.',
                    219:             unam  => 'You must enter a username.',
1.44      raeburn   220:             mail  => 'You must enter an e-mail address.',
                    221:             eith  => 'Enter a username and/or an e-mail address.',
1.38      raeburn   222:         );
                    223:         &js_escape(\%js_lt);
                    224:         $js = <<"END";
                    225: function verifyDomain(caller,form) {
                    226:     var redirect = 1; 
                    227:     var instdoms = new Array($instdomstr);
                    228:     if (instdoms.length > 0) {
                    229:         for (var i=0; i<instdoms.length; i++) {
                    230:             if (caller.options[caller.selectedIndex].value == instdoms[i]) {
                    231:                 redirect = 0;
                    232:                 break;
                    233:             }
                    234:         }
                    235:     }
1.44      raeburn   236:     if (redirect == 0) {
                    237:         if (caller.options[caller.selectedIndex].value != '$dom_in_effect') {
                    238:             document.forgotpw.uname.value = '';
                    239:             document.forgotpw.useremail.value = '';
                    240:             form.submit();
                    241:         }
                    242:     }
1.38      raeburn   243:     if (redirect == 1) {
                    244:         if (confirm('$js_lt{thdo}\\n$js_lt{yowi}')) {
                    245:             form.submit();
1.44      raeburn   246:         } else {
                    247:             for (var i=0; i<caller.options.length; i++) { 
                    248:                 if (caller.option[i].value == '$dom_in_effect') {
                    249:                     caller.selectedIndex = i;
                    250:                     break;
                    251:                 }
                    252:             }
1.38      raeburn   253:         }
                    254:     }
                    255:     return;
                    256: }
                    257: 
1.44      raeburn   258: END
                    259:         if ($passwdconf{resetprelink} eq 'either') {
                    260:             $js .= <<"END";
                    261: function validInfo() {
                    262:     if ((document.forgotpw.uname.value == '') &&
                    263:         (document.forgotpw.useremail.value == '')) {
                    264:         alert("$js_lt{'eith'}");
                    265:         return false;
                    266:     }
                    267:     return true;
                    268: }
                    269: END
                    270:         } else {
                    271:             $js .= <<"END";
                    272: 
1.38      raeburn   273: function validInfo() {
                    274:     if (document.forgotpw.uname.value == '') {
                    275:         alert("$js_lt{'unam'}");
                    276:         return false;
                    277:     }
                    278:     if (document.forgotpw.useremail.value == '') {
                    279:         alert("$js_lt{'mail'}");
                    280:         return false;
                    281:     }
                    282:     return true;
                    283: }
                    284: END
1.44      raeburn   285:         }
                    286:     }
                    287:     $js = &Apache::lonhtmlcommon::scripttag($js);
                    288:     if (($passwdconf{'captcha'} eq 'recaptcha') && ($passwdconf{'recaptchaversion'} >=2)) {
                    289:         $js.= "\n".'<script src="https://www.google.com/recaptcha/api.js"></script>'."\n";
1.38      raeburn   290:     }
                    291:     my $header = &Apache::loncommon::start_page('Reset password',$js,$args).
1.53    ! raeburn   292:                  '<div class="LC_landmark" role="banner">'.
        !           293:                  '<h2 class="LC_heading_2">'.&mt('Reset forgotten LON-CAPA password').'</h2></div>';
1.1       raeburn   294:     my $output;
                    295:     if ($token) {
1.53    ! raeburn   296:         $r->print($header.'<div class="LC_landmark" role="main">');
1.50      raeburn   297:         &reset_passwd($r,$token,$contact_name,$contact_email,$clientip,\%passwdconf);
1.53    ! raeburn   298:         $r->print('</div>'.&Apache::loncommon::end_page());
1.39      raeburn   299:         return OK;
1.38      raeburn   300:     } elsif ($udom) {
                    301:         if (!$domdesc) {
                    302:             $output = &invalid_state('baddomain',$domdesc,
                    303:                                      $contact_name,$contact_email); 
                    304:         } elsif ($otherinst) {
1.49      raeburn   305:             ($header,$output) = &homeserver_redirect($r,$uname,$udom,$domdesc,$brcrum);
1.44      raeburn   306:         } elsif (($uname) || ($useremail)) {
                    307:             my $earlyout;
                    308:             unless ($passwdconf{'captcha'} eq 'unused') {
                    309:                 my ($captcha_chk,$captcha_error) =
1.46      raeburn   310:                     &Apache::loncommon::captcha_response('passwords',$server,$dom_in_effect);
1.44      raeburn   311:                 if ($captcha_chk != 1) {
                    312:                     my $error = 'captcha'; 
                    313:                     if ($passwdconf{'captcha'} eq 'recaptcha') {
                    314:                         $error = 'recaptcha';
                    315:                     }
                    316:                     $output = &invalid_state($error,$domdesc,
1.37      raeburn   317:                                              $contact_name,$contact_email);
1.44      raeburn   318:                     $earlyout = 1;
                    319:                 }
                    320:             }
                    321:             unless ($earlyout) {
                    322:                 if ($lookup) {
                    323:                     $output = &invalid_state($lookup,$domdesc,
                    324:                                              $contact_name,$contact_email);
                    325:                     $earlyout = 1;
                    326:                 }
                    327:             }
                    328:             unless ($earlyout) {
                    329:                 my $authtype = &Apache::lonnet::queryauthenticate($uname,$udom);
                    330:                 if ($authtype =~ /^internal/) {
                    331:                     my ($blocked,$blocktext) =
1.51      raeburn   332:                         &Apache::loncommon::blocking_status('passwd',$clientip,$uname,$udom);
1.44      raeburn   333:                     if ($blocked) {
                    334:                         $output = '<p class="LC_warning">'.$blocktext.'</p>'
                    335:                                   .&display_actions($contact_email,$domdesc);
                    336:                     } elsif (($passwdconf{'resetprelink'} ne 'either') && 
                    337:                              ($useremail !~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/)) {
                    338:                         $output = &invalid_state('baduseremail',$domdesc,
                    339:                                                  $contact_name,$contact_email);
                    340:                     } else {
                    341:                         my %userinfo = 
                    342: 	                    &Apache::lonnet::get('environment',\@emailtypes,
                    343: 					         $udom,$uname);
                    344:                         my @allemails;
                    345:                         foreach my $type (@emailtypes) {
                    346:                             if (ref($passwdconf{resetemail}) eq 'ARRAY') {
                    347:                                 if ($type eq 'permanentemail') {
                    348:                                     next unless (grep(/^permanent$/,@{$passwdconf{resetemail}}));
                    349:                                 } elsif ($type eq 'critnotification') {
                    350:                                     next unless (grep(/^critical$/,@{$passwdconf{resetemail}}));
                    351:                                 } elsif ($type eq 'notification') {
                    352:                                     next unless (grep(/^notify$/,@{$passwdconf{resetemail}}));
                    353:                                 }
                    354:                             }
                    355:                             my $email = $userinfo{$type};
                    356:                             my @items;
                    357:                             if ($email =~ /,/) {
                    358:                                 @items = split(',',$userinfo{$type});
                    359:                             } else {
                    360:                                 @items = ($email);
                    361:                             }
                    362:                             foreach my $item (@items) {
                    363:                                 if ($item =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) {
1.46      raeburn   364:                                     unless (grep(/^\Q$item\E$/i,@allemails)) {
1.44      raeburn   365:                                         push(@allemails,$item);
                    366:                                     }
                    367:                                 }
                    368:                             }
1.38      raeburn   369:                         }
1.44      raeburn   370:                         if (@allemails > 0) {
                    371:                             my ($sendto,$warning,$timelimit);
                    372:                             my $timelimit = 2;
                    373:                             if ($passwdconf{'resetlink'} =~ /^\d+(|\.\d*)$/) {
                    374:                                 $timelimit = $passwdconf{'resetlink'};
                    375:                             }
                    376:                             if ($passwdconf{'resetprelink'} eq 'either') {
                    377:                                 if ($useremail ne '') {
                    378:                                     if (grep(/^\Q$useremail\E$/i,@allemails)) {
                    379:                                         $sendto = $useremail;
                    380:                                     } else {
                    381:                                         $warning = &mt('The e-mail address you entered did not match the expected e-mail address.');
                    382:                                     }
                    383:                                 } elsif (@allemails > 1) {
                    384:                                     $warning = &mt('More than one e-mail address is associated with your username, and one has been selected to receive the message sent by LON-CAPA.');
                    385:                                 }
                    386:                                 unless ($sendto) {
                    387:                                     $sendto = $allemails[0];
                    388:                                 }
                    389:                             } else {
                    390:                                 if (grep(/^\Q$useremail\E$/i,@allemails)) {
                    391:                                     $sendto = $useremail;
                    392:                                 } else {
                    393:                                     $output = &invalid_state('mismatch',$domdesc,
                    394:                                                              $contact_name,
                    395:                                                              $contact_email);
1.38      raeburn   396:                                 }
1.18      raeburn   397:                             }
1.44      raeburn   398:                             if ($sendto) {
                    399:                                 $output = &send_token($uname,$udom,$sendto,$server,
                    400:                                                       $domdesc,$contact_name,
                    401:                                                       $contact_email,$timelimit,$warning);
                    402:                             }
1.38      raeburn   403:                         } else {
1.44      raeburn   404:                             $output = &invalid_state('missing',$domdesc,
                    405:                                                      $contact_name,$contact_email);
1.38      raeburn   406:                         }
1.3       raeburn   407:                     }
1.44      raeburn   408:                 } elsif ($authtype =~ /^(krb|unix|local)/) {
                    409:                     $output = &invalid_state('authentication',$domdesc,
                    410:                                          $contact_name,$contact_email);
                    411:                 } else {
                    412:                     $output = &invalid_state('invalid',$domdesc,
                    413:                                              $contact_name,$contact_email);
1.1       raeburn   414:                 }
                    415:             }
                    416:         } else {
1.44      raeburn   417:             $output = &get_uname($server,$dom_in_effect,\%passwdconf);
1.1       raeburn   418:         }
                    419:     } else {
1.44      raeburn   420:         $output = &get_uname($server,$defdom,\%passwdconf);
1.1       raeburn   421:     }
1.53    ! raeburn   422:     $r->print($header.'<div class="LC_landmark" role="main">'.$output.'</div>');
1.1       raeburn   423:     $r->print(&Apache::loncommon::end_page());
                    424:     return OK;
                    425: }
                    426: 
                    427: sub get_uname {
1.44      raeburn   428:     my ($server,$defdom,$passwdconf) = @_;
                    429:     return unless (ref($passwdconf) eq 'HASH');
1.1       raeburn   430:     my %lt = &Apache::lonlocal::texthash(
1.44      raeburn   431:             unam => 'LON-CAPA username',
                    432:             udom => 'LON-CAPA domain',
                    433:             uemail => 'E-mail address in LON-CAPA',
                    434:             vali   => 'Validation',
                    435:             proc => 'Proceed');
                    436:     my $msg;
                    437:     unless ($passwdconf->{'resetremove'}) {
                    438:         $msg = '<p>'.&mt('If you use the same account for other campus services besides LON-CAPA, (e.g., e-mail, course registration, etc.), a separate centrally managed mechanism likely exists to reset a password. However, if your account is used for just LON-CAPA access you will probably be able to reset a password from this page.').'</p>';
                    439:     }
                    440:     if ($passwdconf->{'resetcustom'} eq "/res/$defdom/$defdom-domainconfig/customtext/resetpw/resetpw.html") {
                    441:         my $contents = &Apache::lonnet::getfile(&Apache::lonnet::filelocation('',$passwdconf->{'resetcustom'}));
                    442:         unless ($contents eq '-1') {
                    443:             $msg .= $contents;
                    444:         }
                    445:     }
1.52      raeburn   446:     $msg .= '<p>'.&mt('Three conditions must be met:').'</p>'
1.8       bisitz    447:            .'<ul><li>'.&mt('An e-mail address must have previously been associated with your LON-CAPA username.').'</li>'
                    448:            .'<li>'.&mt('You must be able to access e-mail sent to that address.').'</li>'
                    449:            .'<li>'.&mt('Your LON-CAPA account must be of a type for which LON-CAPA can reset a password.')
1.52      raeburn   450:            .'</ul>';
1.38      raeburn   451:     my $onchange = 'javascript:verifyDomain(this,this.form);';
                    452:     $msg .= '<form name="forgotpw" method="post" action="/adm/resetpw" onsubmit="return validInfo();">'.
1.44      raeburn   453:             &Apache::lonhtmlcommon::start_pick_box().
1.53    ! raeburn   454:             &Apache::lonhtmlcommon::row_title('<label for="udom">'.$lt{'udom'}).'</label>').
        !           455:             &Apache::loncommon::select_dom_form($defdom,'udom',undef,undef,$onchange,'','','','udom').
1.26      raeburn   456:             &Apache::lonhtmlcommon::row_closure(1).
1.53    ! raeburn   457:             &Apache::lonhtmlcommon::row_title('<label for="uname">'.$lt{'unam'}.'</label>').
1.44      raeburn   458:             '<input type="text" name="uname" size="20" autocapitalize="off" autocorrect="off" />'.
                    459:             &Apache::lonhtmlcommon::row_closure(1).
1.53    ! raeburn   460:             &Apache::lonhtmlcommon::row_title('<label for="useremail">'.$lt{'uemail'}.'</label>').
1.44      raeburn   461:             '<input type="text" name="useremail" size="30" autocapitalize="off" autocorrect="off" />'.
                    462:             &Apache::lonhtmlcommon::row_closure(1);
                    463:     unless ($passwdconf->{'captcha'} eq 'notused') {
                    464:         my ($captcha_form,$captcha_error,$captcha,$recaptcha_version) =
                    465:             &Apache::loncommon::captcha_display('passwords',$server,$defdom);
                    466:         if ($captcha_form) {
                    467:             $msg .= &Apache::lonhtmlcommon::row_title($lt{'vali'}).
                    468:                     $captcha_form."\n".
                    469:                     &Apache::lonhtmlcommon::row_closure(1);
                    470:         }
                    471:     }
                    472:     $msg .= &Apache::lonhtmlcommon::end_pick_box().
1.26      raeburn   473:             '<br /><br /><input type="submit" name="resetter" value="'.$lt{'proc'}.'" /></form>';
1.1       raeburn   474:     return $msg;
                    475: }
                    476: 
                    477: sub send_token {
                    478:     my ($uname,$udom,$email,$server,$domdesc,$contact_name,
1.44      raeburn   479:         $contact_email,$timelimit,$warning) = @_;
1.29      bisitz    480:     my $msg =
                    481:         '<p class="LC_info">'
                    482:        .&mt('Thank you for your request to reset the password for your LON-CAPA account.')
                    483:        .'</p>';
1.1       raeburn   484: 
                    485:     my $now = time;
                    486:     my $temppasswd = &create_passwd();
1.48      raeburn   487:     my $ip = &Apache::lonnet::get_requestor_ip(); 
                    488:     my %info = ('ip'         => $ip,
1.2       albertel  489: 		'time'       => $now,
                    490: 		'domain'     => $udom,
                    491: 		'username'   => $uname,
                    492: 		'email'      => $email,
                    493: 		'temppasswd' => $temppasswd);
1.1       raeburn   494: 
1.3       raeburn   495:     my $token = &Apache::lonnet::tmpput(\%info,$server,'resetpw');
                    496:     if ($token !~ /^error/ && $token ne 'no_such_host') {
1.2       albertel  497:         my $esc_token = &escape($token);
1.15      raeburn   498:         my $showtime = &Apache::lonlocal::locallocaltime(time);
                    499:         my $reseturl = &Apache::lonnet::absolute_url().'/adm/resetpw?token='.$esc_token;
1.26      raeburn   500:         my $mailmsg = &mt('A request was submitted on [_1] for reset of the password for your LON-CAPA account.',$showtime)." \n".&mt('To complete this process please open a web browser and enter the following URL in the address/location box: [_1]',"\n\n".$reseturl);
1.1       raeburn   501:         my $result = &send_mail($domdesc,$email,$mailmsg,$contact_name,
                    502:                                 $contact_email);
                    503:         if ($result eq 'ok') {
1.34      bisitz    504:             $msg .=
                    505:                 &mt('An e-mail sent to the e-mail address associated with your LON-CAPA account includes the web address for the link you should use to complete the reset process.')
                    506:                .'<br /><br />'
1.44      raeburn   507:                .&mt('The link included in the message will be valid for the next [_1][quant,_2,hour][_3].','<b>',$timelimit,'</b>');
1.1       raeburn   508:         } else {
1.28      bisitz    509:             $msg .=
1.29      bisitz    510:                 '<p class="LC_error">'
                    511:                .&mt('An error occurred when sending a message to the e-mail address'
                    512:                    .' associated with your LON-CAPA account.')
                    513:                .'</p>'
                    514:                .&display_actions($contact_email,$domdesc);
1.1       raeburn   515:         }
                    516:     } else {
1.28      bisitz    517:         $msg .=
1.29      bisitz    518:             '<p class="LC_error">'
                    519:            .&mt('An error occurred creating a token required for the'
                    520:                .' password reset process.')
                    521:            .'</p>'
                    522:            .&display_actions($contact_email,$domdesc);
1.1       raeburn   523:     }
                    524:     return $msg;
                    525: }
                    526: 
                    527: sub send_mail {
                    528:     my ($domdesc,$email,$mailmsg,$contact_name,$contact_email) = @_;
                    529:     my $outcome;
                    530:     my $requestmail = "To: $email\n".
                    531:                       "From: $contact_name <$contact_email>\n".
                    532:                       "Subject: ".&mt('Your LON-CAPA account')."\n".
1.25      bisitz    533:                       "Content-type: text/plain\;charset=UTF-8\n".
1.1       raeburn   534:                       "\n\n".$mailmsg."\n\n".
                    535:                       &mt('[_1] LON-CAPA support team',$domdesc)."\n".
                    536:                       "$contact_email\n";
                    537:     if (open(MAIL, "|/usr/lib/sendmail -oi -t -odb")) {
                    538:         print MAIL $requestmail;
                    539:         close(MAIL);
                    540:         $outcome = 'ok';
                    541:     } else {
                    542:         $outcome = 'fail';
                    543:     }
                    544:     return $outcome;
                    545: }
                    546: 
                    547: sub invalid_state {
                    548:     my ($error,$domdesc,$contact_name,$contact_email) = @_;
                    549:     my $msg;
                    550:     if ($error eq 'invalid') {
1.29      bisitz    551:         $msg =
                    552:             '<p class="LC_warning">'
                    553:             .&mt('The username you provided was not verified as a valid username'
                    554:                 .' in the LON-CAPA system for the [_1] domain.','<i>'.$domdesc.'</i>')
                    555:               .'</p>';
                    556:         $msg .= &display_actions($contact_email,$domdesc);
1.1       raeburn   557:     } else {
1.44      raeburn   558:         if ($error eq 'captcha') {
                    559:             $msg = &mt('Validation of the code you entered failed');
                    560:         } elsif ($error eq 'recaptcha') {
                    561:             $msg = &mt('Validation of human, not robot, failed'); 
                    562:         } elsif ($error eq 'nonunique') {
                    563:             $msg = &mt('More than one username was identified from the information you provided; try providing both a username and e-mail address');
                    564:         } elsif ($error eq 'nomatch') {
                    565:             $msg = &mt('A valid user could not be identified from the username and/or e-mail address you provided');
                    566:         } elsif ($error eq 'baduseremail') {
1.3       raeburn   567:             $msg = &mt('The e-mail address you provided does not appear to be a valid address.');
                    568:         } elsif ($error eq 'mismatch') {
                    569:             $msg = &mt('The e-mail address you provided does not match the address recorded in the LON-CAPA system for the username and domain you provided.');  
                    570:         } elsif ($error eq 'missing') {
1.1       raeburn   571:             $msg = &mt('A valid e-mail address was not located in the LON-CAPA system for the username and domain you provided.');
                    572:         } elsif ($error eq 'authentication') {
                    573:             $msg = &mt('The username you provided uses an authentication type which can not be reset directly via LON-CAPA.');
1.38      raeburn   574:         } elsif ($error eq 'baddomain') {
                    575:             $msg = &mt('The domain you provided was not verified as a valid domain in the LON-CAPA system.');
1.1       raeburn   576:         }
1.29      bisitz    577:         $msg = '<p class="LC_warning">'.$msg.'</p>'
                    578:               .&display_actions($contact_email,$domdesc);
1.1       raeburn   579:     }
                    580:     return $msg;
                    581: }
                    582: 
1.38      raeburn   583: sub homeserver_redirect {
1.49      raeburn   584:     my ($r,$uname,$udom,$domdesc,$brcrum) = @_;
1.42      raeburn   585:     my $uhome;
1.43      raeburn   586:     if (($uname ne '') && ($udom ne '')) {
1.42      raeburn   587:         $uhome = &Apache::lonnet::homeserver($uname,$udom);
                    588:     }
                    589:     if (($uhome eq 'no_host') || ($uhome eq '')) {
1.38      raeburn   590:         $uhome = &Apache::lonnet::domain($udom,'primary');
                    591:     }
1.42      raeburn   592:     my $hostname = &Apache::lonnet::hostname($uhome);
1.38      raeburn   593:     my $protocol = $Apache::lonnet::protocol{$uhome};
                    594:     $protocol = 'http' if ($protocol ne 'https');
1.49      raeburn   595:     my $alias = &Apache::lonnet::use_proxy_alias($r,$uhome);
                    596:     $hostname = $alias if ($alias ne '');
1.42      raeburn   597:     my $url = $protocol.'://'.$hostname.'/adm/resetpw';
1.38      raeburn   598:     # Breadcrumbs
                    599:     my $start_page = &Apache::loncommon::start_page('Switching Server',undef,
                    600:                                                     {'redirect' => [0,$url],
                    601:                                                      'bread_crumbs' => $brcrum,});
                    602:     my $output = '<p>'.&mt('This LON-CAPA server belongs to a different domain.').' '.
                    603:                        &mt('You are being switched to your domain ([_1]), to use the "Forgot Password" tool.',$domdesc).
                    604:                  '</p>';
                    605:     return ($start_page,$output);
                    606: }
                    607: 
1.1       raeburn   608: sub reset_passwd {
1.50      raeburn   609:     my ($r,$token,$contact_name,$contact_email,$clientip,$passwdconf) = @_;
1.44      raeburn   610:     return unless (ref($passwdconf) eq 'HASH');
1.1       raeburn   611:     my %data = &Apache::lonnet::tmpget($token);
                    612:     my $now = time;
                    613:     if (keys(%data) == 0) {
1.39      raeburn   614:         $r->print(&mt('Sorry, the URL you provided to complete the reset of your password was invalid. Either the token included in the URL has been deleted or the URL you provided was invalid. Please submit a [_1]new request[_2] for a password reset, and follow the link to the new URL included in the e-mail that will be sent to you, to allow you to enter a new password.'
                    615:                   ,'<a href="/adm/resetpw">','</a>')
                    616:         );
                    617:         return;
1.1       raeburn   618:     }
                    619:     if (($data{'time'} =~ /^\d+$/) && 
                    620:         ($data{'username'} ne '') && 
                    621:         ($data{'domain'} ne '') && 
1.3       raeburn   622:         ($data{'email'}  =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) && 
1.1       raeburn   623:         ($data{'temppasswd'} =~/^\w+$/)) {
1.44      raeburn   624:         my $timelimit = 7200;
                    625:         if ($passwdconf->{resetlink} =~ /^\d+(|\.\d*)$/) {
                    626:             $timelimit = 3600 * $passwdconf->{resetlink};
                    627:         }
1.9       raeburn   628:         my $reqtime = &Apache::lonlocal::locallocaltime($data{'time'});
1.37      raeburn   629:         my ($blocked,$blocktext) =
1.50      raeburn   630:             &Apache::loncommon::blocking_status('passwd',$clientip,$data{'username'},$data{'domain'});
1.37      raeburn   631:         if ($blocked) {
1.39      raeburn   632:             $r->print('<p class="LC_warning">'.$blocktext.'</p>');
                    633:             return;
1.44      raeburn   634:         } elsif ($now - $data{'time'} < $timelimit) {
                    635:             my ($needscase,%formfields) = &reset_requires($data{'username'},$data{'domain'},
                    636:                                                           $passwdconf);
1.1       raeburn   637:             if ($env{'form.action'} eq 'verify_and_change_pass') {
1.44      raeburn   638:                 my $invalidinfo;
                    639:                 if ($formfields{'username'}) {
                    640:                     $env{'form.uname'} =~ s/^\s+|\s+$//g;
                    641:                     $env{'form.udom'} =~ s/^\s+|\s+$//g;
                    642:                     if ($needscase) {
                    643:                         unless (($env{'form.uname'} eq $data{'username'}) && ($env{'form.udom'} eq $data{'domain'})) {
                    644:                             $invalidinfo = "||$env{'form.uname'}|| ||$env{'form.udom'}|| ";
                    645:                         }
                    646:                     } else {
1.47      raeburn   647:                         if ((lc($env{'form.uname'}) eq lc($data{'username'})) && (lc($env{'form.udom'}) eq lc($data{'domain'}))) {
                    648:                             $env{'form.uname'} = $data{'username'};
                    649:                         } else {
1.44      raeburn   650:                             $invalidinfo = "||$env{'form.uname'}|| ||$env{'form.udom'}|| ";
                    651:                         }
                    652:                     }
                    653:                 } else {
                    654:                     $env{'form.uname'} = $data{'username'};
                    655:                     $env{'form.udom'} = $data{'domain'};
                    656:                 }
                    657:                 if ($formfields{'email'}) {
                    658:                     $env{'form.email'} =~ s/^\s+|\s+$//g;
                    659:                     if ($needscase) {
                    660:                         unless ($env{'form.email'} eq $data{'email'}) {
                    661:                             $invalidinfo .= "||$env{'form.email'}||";
                    662:                         }
                    663:                     } else {
                    664:                         unless (lc($env{'form.email'}) eq lc($data{'email'})) {
                    665:                             $invalidinfo = "||$env{'form.email'}||";
                    666:                         }
                    667:                     }
                    668:                 }
                    669:                 if ($invalidinfo) {
                    670:                     &Apache::lonnet::logthis("Forgot Password -- token data: ||$data{'username'}|| ||$data{'domain'}|| ||$data{'email'}|| differs from form: $invalidinfo");
1.47      raeburn   671:                     my $retry;
                    672:                     $r->print(
                    673:                               '<p class="LC_warning">'
                    674:                              .&mt('A problem occurred when attempting to reset'
                    675:                              .' the password for your account.').'</p>');
                    676:                     if (($formfields{'username'}) && ($formfields{'email'})) {
                    677:                         if ($needscase) {
                    678:                             $r->print('<p>'
                    679:                                      .&mt('Please verify you entered the correct username and e-mail address, '
                    680:                                      .'including the correct lower and/or upper case letters')
                    681:                                      .'</p>');
                    682:                         } else {
                    683:                             $r->print('<p>'
                    684:                                      .&mt('Please verify you entered the correct username and e-mail address.')
                    685:                                      .'</p>');
                    686:                         }
                    687:                         $retry = 1;
                    688:                     } elsif ($formfields{'username'}) {
                    689:                         if ($needscase) {
                    690:                             $r->print('<p>'
                    691:                                      .&mt('Please verify you entered the correct username, '
                    692:                                      .'including the correct lower and/or upper case letters')
                    693:                                      .'</p>');
                    694:                         } else {
                    695:                             $r->print('<p>'
                    696:                                      .&mt('Please verify you entered the correct username.')
                    697:                                      .'</p>');
                    698:                         }
                    699:                         $retry = 1;
                    700:                     } elsif ($formfields{'email'}) {
                    701:                         if ($needscase) {
                    702:                             $r->print('<p>'
                    703:                                      .&mt('Please verify you entered the correct e-mail address, '
                    704:                                      .'including the correct lower and/or upper case letters')
                    705:                                      .'</p>');
                    706:                         } else {
                    707:                             $r->print('<p>'
                    708:                                      .&mt('Please verify you entered the correct e-mail address.')
                    709:                                      .'</p>');
                    710:                         }
                    711:                         $retry = 1;
                    712:                     }
                    713:                     if ($retry) {
                    714:                          &Apache::lonpreferences::passwordchanger($r,'','reset_by_email',$token,$timelimit,\%formfields);
                    715:                     } else {
                    716:                         $r->print(&generic_failure_msg($contact_name,$contact_email));
                    717:                     }
1.44      raeburn   718:                     unless ($formfields{'username'}) {
                    719:                         delete($env{'form.uname'});
                    720:                         delete($env{'form.udom'});
                    721:                     }
1.39      raeburn   722:                     return;
1.22      raeburn   723:                 }
1.44      raeburn   724:                 my $change_failed =
1.47      raeburn   725: 		    &Apache::lonpreferences::verify_and_change_password($r,'reset_by_email',$token,$timelimit,\%formfields);
1.1       raeburn   726:                 if (!$change_failed) {
                    727:                     my $delete = &Apache::lonnet::tmpdel($token);
1.9       raeburn   728:                     my $now = &Apache::lonlocal::locallocaltime(time);
1.1       raeburn   729:                     my $domdesc = 
1.6       albertel  730: 			&Apache::lonnet::domain($data{'domain'},'description');
1.48      raeburn   731:                     my $ip = &Apache::lonnet::get_requestor_ip();
                    732:                     my $mailmsg = &mt('The password for your LON-CAPA account in the [_1] domain was changed [_2] from IP address: [_3].  If you did not perform this change or authorize it, please contact the [_4] ([_5]).',$domdesc,$now,$ip,$contact_name,$contact_email)."\n";
1.1       raeburn   733:                     my $result = &send_mail($domdesc,$data{'email'},$mailmsg,
                    734:                                             $contact_name,$contact_email);
1.33      bisitz    735:                     my $confirm_msg;
1.1       raeburn   736:                     if ($result eq 'ok') {
1.33      bisitz    737:                         $confirm_msg =
                    738:                             &Apache::lonhtmlcommon::confirm_success(
                    739:                                 &mt('An e-mail confirming setting of the password'
                    740:                                    .' for your LON-CAPA account has been sent to [_1].'
                    741:                                     ,'<span class="LC_filename">'.$data{'email'}.'</span>'));
1.1       raeburn   742:                     } else {
1.33      bisitz    743:                         $confirm_msg =
                    744:                             &Apache::lonhtmlcommon::confirm_success(
                    745:                                 &mt('An error occurred when sending e-mail to [_1]'
                    746:                                    .' confirming setting of your new password.'
                    747:                                     ,'<span class="LC_filename">'.$data{'email'}.'</span>'),1);
1.1       raeburn   748:                     }
1.39      raeburn   749:                     $r->print(
1.33      bisitz    750:                         &Apache::loncommon::confirmwrapper($confirm_msg)
                    751:                        .&Apache::lonhtmlcommon::actionbox([
1.39      raeburn   752:                             '<a href="/adm/login">'.&mt('Go to the login page').'</a>'])
                    753:                     );
1.20      raeburn   754:                 } elsif ($change_failed eq 'invalid_client') {
                    755:                     my $homeserver = &Apache::lonnet::homeserver($data{'username'},$data{'domain'});
                    756:                     if ($homeserver eq 'no_host') {
1.39      raeburn   757:                         $r->print(&generic_failure_msg($contact_name,$contact_email));
1.20      raeburn   758:                     } else {
1.42      raeburn   759:                         my $hostname = &Apache::lonnet::hostname($homeserver);
1.20      raeburn   760:                         my $protocol = $Apache::lonnet::protocol{$homeserver};
                    761:                         $protocol = 'http' if ($protocol ne 'https');
1.49      raeburn   762:                         my $alias = &Apache::lonnet::use_proxy_alias($r,$homeserver);
                    763:                         $hostname = $alias if ($alias ne '');
1.42      raeburn   764:                         my $url = $protocol.'://'.$hostname.'/adm/resetpw';
1.20      raeburn   765:                         my ($opentag,$closetag);
                    766:                         if ($url) {
                    767:                            $opentag = '<a href="'.$url.'">';
                    768:                            $closetag = '</a>';
                    769:                         }
1.39      raeburn   770:                         $r->print(
1.28      bisitz    771:                             '<p class="LC_warning">'
                    772:                            .&mt('A problem occurred when attempting to reset'
                    773:                                .' the password for your account.'
                    774:                                .' Please try again from your [_1]home server[_2].'
                    775:                                 ,$opentag,$closetag)
1.39      raeburn   776:                            .'</p>'
                    777:                         );
1.20      raeburn   778:                     }
1.45      raeburn   779:                 } elsif (($change_failed eq 'prioruse') && ($passwdconf->{'numsaved'})) {
                    780:                     my $domdesc =
                    781:                         &Apache::lonnet::domain($data{'domain'},'description');
                    782:                     $r->print(
                    783:                           '<p class="LC_warning">'
                    784:                          .&mt('Please enter a password that you have not used recently.')
                    785:                          .'</p>'
1.46      raeburn   786:                          .&display_actions($contact_email,$domdesc,$token)
1.45      raeburn   787:                     );
1.47      raeburn   788:                 } elsif (($change_failed eq 'internalerror') || ($change_failed eq 'missingtemp') ||
                    789:                          ($change_failed eq 'error')) {
1.39      raeburn   790:                     $r->print(&generic_failure_msg($contact_name,$contact_email));
1.1       raeburn   791:                 }
1.44      raeburn   792:                 unless ($formfields{'username'}) {
                    793:                     delete($env{'form.uname'});
                    794:                     delete($env{'form.udom'});
                    795:                 }
1.1       raeburn   796:             } else {
1.13      schafran  797:                 $r->print(&mt('The token included in an e-mail sent to you [_1] has been verified, so you may now proceed to reset the password for your LON-CAPA account.',$reqtime).'<br /><br />');
1.44      raeburn   798:                 if (keys(%formfields)) {
                    799:                     if (($formfields{'username'}) && ($formfields{'email'})) {
                    800:                         $r->print(&mt('Please enter the username and domain of the LON-CAPA account, and the associated e-mail address, for which you are setting a password.'));
                    801:                     } elsif ($formfields{'username'}) {
                    802:                         $r->print(&mt('Please enter the username and domain of the LON-CAPA account for which you are setting a password.'));
                    803:                     } elsif ($formfields{'email'}) {
                    804:                         $r->print(&mt('Please enter the e-mail address associated with the LON-CAPA account for which you are setting a password.'));
                    805:                     }
                    806:                     if ($needscase) {
                    807:                         $r->print(' '.&mt('User data entered must match LON-CAPA account information (including case).'));
                    808:                     }
1.47      raeburn   809:                     $r->print('<br />');
                    810:                 }
                    811:                 my ($min,$max,$minrule,$maxrule);
                    812:                 if ($passwdconf->{min}) {
                    813:                     $min = $passwdconf->{min};
                    814:                 } else {
                    815:                     $min = $Apache::lonnet::passwdmin;
                    816:                 }
                    817:                 if ($min) {
                    818:                     $minrule = &mt('Minimum password length: [_1]',$min);
                    819:                 }
                    820:                 if ($passwdconf->{max}) {
                    821:                     $max = $passwdconf->{max};
                    822:                     $maxrule = &mt('Maximum password length: [_1]',$max);
1.44      raeburn   823:                 }
                    824:                 if (ref($passwdconf->{chars}) eq 'ARRAY') {
                    825:                     my %rules;
                    826:                     map { $rules{$_} = 1; } @{$passwdconf->{chars}};
                    827:                     my %rulenames = &Apache::lonlocal::texthash(
                    828:                                                      uc => 'At least one upper case letter',
                    829:                                                      lc => 'At least one lower case letter',
                    830:                                                      num => 'At least one number',
                    831:                                                      spec => 'At least one non-alphanumeric',
                    832:                                                    );
                    833:                     $r->print(&mt('The new password must satisfy the following:').'<ul>');
                    834:                     foreach my $poss ('uc','lc','num','spec') {
                    835:                         if ($rules{$poss}) {
                    836:                             $r->print('<li>'.$rulenames{$poss}.'</li>');
                    837:                         }
                    838:                     }
1.47      raeburn   839:                     if ($min) {
                    840:                         $r->print('<li>'.$minrule.'</li>');
                    841:                     }
                    842:                     if ($max) {
                    843:                         $r->print('<li>'.$maxrule.'</li>');
                    844:                     }
1.44      raeburn   845:                     $r->print('</ul>');
                    846:                 } else {
1.47      raeburn   847:                     if ($min && $max) {
                    848:                         $r->print(&mt('The new password must satisfy the following:').'<ul>'."\n".
                    849:                                   '<li>'.$minrule.'</li>'."\n".
                    850:                                   '<li>'.$maxrule.'</li>'."\n".
                    851:                                   '</ul>'."\n");
                    852:                     } elsif ($min) {
                    853:                         $r->print($minrule.'<br />');
                    854:                     } elsif ($max) {
                    855:                         $r->print($maxrule.'<br />');
                    856:                     }
1.44      raeburn   857:                 }
                    858:                 $r->print(&mt('Your new password will be sent to the LON-CAPA server in an encrypted form.').'<br />');
                    859:                 &Apache::lonpreferences::passwordchanger($r,'','reset_by_email',$token,$timelimit,\%formfields);
1.1       raeburn   860:             }
                    861:         } else {
1.39      raeburn   862:             $r->print(
1.28      bisitz    863:                 '<p class="LC_warning">'
1.47      raeburn   864:                .&mt('Sorry, the token generated when you requested a password reset has expired.').'<br />'
                    865:                .&mt('Please submit a [_1]new request[_2], and follow the link to the web page included in the new e-mail that will be sent to you, to allow you to enter a new password.'
1.28      bisitz    866:                     ,'<a href="/adm/resetpw">','</a>')
1.39      raeburn   867:                .'</p>'
                    868:             );
1.1       raeburn   869:         }
                    870:     } else {
1.39      raeburn   871:         $r->print(
1.28      bisitz    872:             '<p class="LC_warning">'
                    873:            .&mt('Sorry, the URL generated when you requested reset of your password contained incomplete information. Please submit a [_1]new request[_2] for a password reset, and use the new URL that will be sent to your e-mail account to complete the process.'
                    874:                 ,'<a href="/adm/resetpw">','</a>')
1.39      raeburn   875:            .'</p>'
                    876:         );
1.1       raeburn   877:     }
1.39      raeburn   878:     return;
1.1       raeburn   879: }
                    880: 
1.20      raeburn   881: sub generic_failure_msg {
                    882:     my ($contact_name,$contact_email) = @_;
1.28      bisitz    883:     return
1.29      bisitz    884:         '<p class="LC_error">'
                    885:        .&mt('A problem occurred when attempting to reset the password for your account.')
                    886:        .'<br />'
1.36      raeburn   887:        .&mt('Please contact the [_1] ([_2]) for assistance.',
1.28      bisitz    888:               $contact_name,'<a href="mailto:'.$contact_email.'">'.$contact_email.'</a>')
                    889:        .'</p>';
1.20      raeburn   890: }
                    891: 
1.1       raeburn   892: sub create_passwd {
                    893:     my $passwd = '';
1.2       albertel  894:     my @letts = ("a".."z");
1.1       raeburn   895:     for (my $i=0; $i<8; $i++) {
1.2       albertel  896:         my $lettnum = int(rand(2));
1.1       raeburn   897:         my $item = '';
                    898:         if ($lettnum) {
1.2       albertel  899:             $item = $letts[int(rand(26))];
                    900:             my $uppercase = int(rand(2));
1.1       raeburn   901:             if ($uppercase) {
                    902:                 $item =~ tr/a-z/A-Z/;
                    903:             }
                    904:         } else {
1.2       albertel  905:             $item = int(rand(10));
1.1       raeburn   906:         }
                    907:         $passwd .= $item;
                    908:     }
                    909:     return ($passwd);
                    910: }
                    911: 
1.29      bisitz    912: sub display_actions {
1.46      raeburn   913:     my ($contact_email,$domdesc,$token) = @_;
                    914:     my $url = '/adm/resetpw';
                    915:     if ($token) {
                    916:         $url .= '?token='.&escape($token);
                    917:     }
1.29      bisitz    918:     my @msg = (&mt('[_1]Go back[_2] and try again',
1.46      raeburn   919:                    '<a href="'.$url.'">','</a>'));
1.29      bisitz    920:     my $msg2 = '';
                    921:     if ($contact_email ne '') {
1.30      raeburn   922:         my $escuri = &HTML::Entities::encode('/adm/resetpw','&<>"');
                    923:         push(@msg, &mt('Contact the [_1]LON-CAPA helpdesk[_2] for the institution: [_3]',
                    924:                        '<a href="/adm/helpdesk?origurl='.$escuri.'">',
                    925:                        '</a>','<i>'.$domdesc.'</i>'));
                    926:     } else {
                    927:         $msg2 =
                    928:             '<p>'
                    929:            .&mt('You may wish to send an e-mail to the'
                    930:            .' server administrator: [_1] for the [_2] domain.',
1.31      raeburn   931:                 '<i>'.$Apache::lonnet::perlvar{'AdmEMail'}.'</i>',
1.30      raeburn   932:                 '<i>'.$domdesc.'</i>')
                    933:            .'</p>';
                    934:     }
1.29      bisitz    935:     return &Apache::lonhtmlcommon::actionbox(\@msg).$msg2;
1.44      raeburn   936: }
1.29      bisitz    937: 
1.44      raeburn   938: sub reset_requires {
                    939:     my ($username,$domain,$passwdconf) = @_;
                    940:     my (%fields,$needscase);
                    941:     return ($needscase,%fields) unless (ref($passwdconf) eq 'HASH');
                    942:     my (%postlink,%resetcase);
                    943:     if (ref($passwdconf->{resetpostlink}) eq 'HASH') {
                    944:         %postlink = %{$passwdconf->{resetpostlink}};
                    945:     }
                    946:     if (ref($passwdconf->{resetcase}) eq 'ARRAY') {
                    947:         map { $resetcase{$_} = 1; } (@{$passwdconf->{resetcase}});
                    948:     } else {
                    949:         $needscase = 1;
                    950:     }
                    951:     my %userenv =
                    952:         &Apache::lonnet::get('environment',['inststatus'],$domain,$username);
                    953:     my @inststatuses;
                    954:     if ($userenv{'inststatus'} ne '') {
                    955:         @inststatuses = split(/:/,$userenv{'inststatus'});
                    956:     } else {
                    957:         @inststatuses = ('default');
                    958:     }
                    959:     foreach my $status (@inststatuses) {
                    960:         if (ref($postlink{$status}) eq 'ARRAY') {
                    961:             map { $fields{$_} = 1; } (@{$postlink{$status}});
                    962:         } else {
                    963:             map { $fields{$_} = 1; } ('username','email');
                    964:         }
                    965:         if ($resetcase{$status}) {
                    966:             $needscase = 1;
                    967:         }
                    968:     }
                    969:     return ($needscase,%fields);
1.29      bisitz    970: }
                    971: 
1.1       raeburn   972: 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>