<?page
title=><?_ml .title _ml?>
head=><?_code return LJ::robot_meta_tags(); _code?>
body<=
<?_code

 use strict;

 my $body;

 if ($LJ::SERVER_DOWN) {
     $body = LJ::server_down_html();
     return $body;
 }


# Only logged user can change its own password

 my $remote = LJ::get_remote();
 return  LJ::bad_input($ML{'error.noremote'})
     unless $remote;

 my $authas = $GET{'authas'} || $remote->{'user'};
 my $memoryu = LJ::get_authas_user($authas);
 return  LJ::bad_input($ML{'error.invalidauth'})
     unless $memoryu;



 if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") {
     return BML::redirect("$LJ::SSLROOT/changepassword.bml");
 }

 my $crumb = $LJ::IS_SSL ? 'securechangepass' : 'changepass';
 LJ::set_active_crumb($crumb);

 my $update_form = sub {
     my $ret;

     # else, show the form to change:
     $ret .= "<form action='changepassword.bml' method='post'>\n";
     $ret .= LJ::html_hidden(mode => 'submit',
                              ssl => $GET{'ssl'});

     $ret .= "<?h1 $ML{'.changepassword.header'} h1?>\n";
     $ret .= "<?p $ML{'.changepassword.instructions'} p?>\n";

     my $remote = LJ::get_remote();

     # Warn them if logged in and not validated
     if (!LJ::did_post() && $remote && $remote->{'status'} ne 'A') {
         $ret .= "<?warningbar <b>$ML{'label.warning'}</b> $ML{'.error.notvalidated'} warningbar?>";
         $ret .= "<br />";
     }
 
     $ret .= "<?standout\n";
     $ret .= "$ML{'Username'}: $authas <br />\n<br />\n";

     # we make the field for the new password *longer* than the max length
     # for a password - that way we can tell if someone is trying to use an
     # excessively long password, instead of silently truncating it.

     $ret .= "$ML{'.oldpassword'}<br />\n";
     $ret .= "<input type='password' name='password' size='30' maxlength='30' /><br />\n";
     $ret .= "$ML{'.newpassword'}<br />\n";
     $ret .= "<input type='password' name='newpass1' size='30' maxlength='31' /><br />\n";
     $ret .= "$ML{'.newpasswordagain'}<br />\n";
     $ret .= "<input type='password' name='newpass2' size='30' maxlength='31' /><br />\n";
     $ret .= "standout?>\n";

     $ret .= "<?h1 $ML{'Proceed'} h1?>\n";
     $ret .= "<?p $ML{'.proceed.instructions'} p?>\n";

     $ret .= "<?standout\n";
     $ret .= "<input type='submit' value='$ML{'.btn.proceed'}' />\n";
     $ret .= "standout?>\n";
     $ret .= "</form>\n";
     return $ret;
 };

 unless (LJ::did_post()) {
     $body .= $update_form->();
 } elsif ($POST{'mode'} eq 'submit') {
     my $user = $authas; #LJ::canonical_username($POST{'user'});
     my $password = $POST{'password'};
     my $newpass1 = LJ::trim($POST{'newpass1'});
     my $newpass2 = LJ::trim($POST{'newpass2'});

     my $remote = LJ::get_remote();
     my $u = LJ::load_user($user);

     my @errors = ();
     if ($user eq "test") { push @errors, $ML{'.error.changetestaccount'}; }
     unless ($user) {
         push @errors, $ML{'.error.mustenterusername'}; 
     } else {
         unless (defined $u) {
             push @errors, BML::ml('.error.invaliduser', {'user' => $user} );
         } else {
             if (LJ::login_ip_banned($u)) {
                 push @errors, $ML{'error.ipbanned'};
             } elsif ($u->{'password'} eq "" || $u->{'password'} ne $password) {
                 push @errors, $ML{'.error.badoldpassword'};
                 LJ::handle_bad_login($u);
             }
         }
     }
     if ($newpass1 ne $newpass2) {
         push @errors, $ML{'.error.badnewpassword'};
     } else {
         if ($newpass1 eq "") {
             push @errors, $ML{'.error.blankpassword'};
         } elsif (length $newpass1 > 30) {
             push @errors, $ML{'.error.characterlimit'};
         } else {
             
             my @checkpass = LJ::run_hooks("bad_password", 
                                           { 'user' => $u->{'user'}, 'password' => $newpass1,
                                             'name' => $u->{'name'}, 'email' => $u->{'email'} });
             if (@checkpass && $checkpass[0]->[0]) {
                 push @errors, BML::ml('.error.badcheck', {'error' => $checkpass[0]->[0]});
             }
         }
     }

     # don't allow changes if email address is not validated
     unless ($u->{'status'} eq 'A') {
         push @errors, $ML{'.error.notvalidated'};
     }

     unless (LJ::is_ascii($newpass1)) {
         push @errors, $ML{'.error.nonascii'};
     }
     
     if (@errors) {
       $body .= LJ::error_list(@errors);
       $body .= $update_form->();
       return $body;
     }

     ## make note of changed password
     my $dbh = LJ::get_db_writer();
     my $oldval = Digest::MD5::md5_hex($u->{'password'} . "change");
     LJ::infohistory_add($u, 'password', $oldval);
     
     LJ::update_user($u, { password => $POST{'newpass1'} });

     # Kill all sessions, forcing user to relogin
     $u->kill_all_sessions;
     
     LJ::send_mail({
         'to' => $u->{'email'},
         'from' => $LJ::ADMIN_EMAIL,
         'fromname' => $LJ::SITENAME,
         'charset' => 'utf-8',
         'subject' => $ML{'.email.subject'},
         'body' => BML::ml('.email.body', {'sitename'=>$LJ::SITENAME, 'siteroot'=>$LJ::SITEROOT})});
     
     $body = "<?h1 $ML{'Success'} h1?><?p $ML{'.success.text'} p?>";
     
     # if they were logged in, tell them to relogin
     $body .= "<?p " . BML::ml('.relogin', { 'aopts' => "href='/login.bml'" }) . " p?>" if $remote;

     LJ::run_hooks("post_changepassword", {
         "u" => $u,
         "newpassword" => $POST{'newpass1'},
         "oldpassword" => $u->{'password'},
     });
 }

 return $body;
_code?>
<=body
page?><?_c <LJDEP>
post: htdocs/changepassword.bml
lib: Digest::MD5
hook: post_changepassword
</LJDEP> _c?>
