366 lines
14 KiB
Plaintext
366 lines
14 KiB
Plaintext
|
<?page
|
||
|
title=><?_ml .title _ml?>
|
||
|
body<=
|
||
|
|
||
|
<?_code
|
||
|
{
|
||
|
use strict;
|
||
|
use vars qw(%FORM);
|
||
|
|
||
|
my $remote = LJ::get_remote();
|
||
|
return LJ::bad_input(BML::ml('.error.login', {'aopts' => 'href="/login.bml?ret=1"'}))
|
||
|
unless $remote;
|
||
|
|
||
|
my $authas = $GET{'authas'} || $remote->{'user'};
|
||
|
my $u = LJ::get_authas_user($authas);
|
||
|
return LJ::bad_input($ML{'error.invalidauth'})
|
||
|
unless $u;
|
||
|
|
||
|
return "<?p $ML{'.error.type'} p?>"
|
||
|
unless $u->{'journaltype'} =~ /[PCS]/;
|
||
|
|
||
|
my %err;
|
||
|
|
||
|
my ($ren, $newuser);
|
||
|
|
||
|
my $ret = '';
|
||
|
|
||
|
# authas switcher form
|
||
|
$ret .= "<form method='get' action='use.bml'>\n";
|
||
|
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||
|
$ret .= "</form>\n\n";
|
||
|
|
||
|
$ret .= BML::ml('.intent', {'aopts0' => 'href="./"', 'aopts1' => 'href="/pay/?item=rename"'});
|
||
|
|
||
|
my $err = sub {
|
||
|
my $area = shift;
|
||
|
return unless defined $err{$area};
|
||
|
$ret .= "<br /><font color='<?hotcolor?>'><b>$err{$area}</b></font>";
|
||
|
};
|
||
|
|
||
|
my $form = sub {
|
||
|
$ret .= "<?hr?><form method='post'>";
|
||
|
$ret .= LJ::html_hidden("userid", $u->{'userid'});
|
||
|
|
||
|
$ret .= "<p>$ML{'.label.username'} <b>$u->{'user'}</b>";
|
||
|
$err->("user");
|
||
|
|
||
|
$ret .= "<p><label for=\"newuser\">$ML{'.label.desired'}</label> ";
|
||
|
$ret .= LJ::html_text({ 'name' => 'newuser',
|
||
|
'value' => $FORM{'newuser'},
|
||
|
'size' => 18, 'maxlength' => 15,
|
||
|
'raw' => 'id="newuser"' });
|
||
|
$err->("newuser");
|
||
|
|
||
|
$ret .= "<p><label for=\"token\">$ML{'.label.token'}</label> ";
|
||
|
$ret .= LJ::html_text({ 'name' => 'token',
|
||
|
'value' => $FORM{'token'},
|
||
|
'size' => 18, 'maxlength' => 16,
|
||
|
'raw' => 'id="token"' });
|
||
|
$err->("token");
|
||
|
|
||
|
# these options don't apply to communities
|
||
|
if ($u->{journaltype} eq 'P') {
|
||
|
$ret .= "<p>$ML{'.options'}<blockquote>";
|
||
|
$ret .= "<p>";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_delfriends',
|
||
|
'type' => 'radio',
|
||
|
'selected' => $FORM{'opt_delfriends'},
|
||
|
'value' => '1',
|
||
|
'raw' => 'id="del_yes"' });
|
||
|
$ret .= " <label for=\"del_yes\">$ML{'.options.delfriends'}</label><br />";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_delfriends',
|
||
|
'type' => 'radio',
|
||
|
'selected' => ! LJ::did_post() || ! $FORM{'opt_delfriends'},
|
||
|
'value' => '0',
|
||
|
'raw' => 'id="del_no"' });
|
||
|
$ret .= " <label for=\"del_no\">$ML{'.options.keepfriends'}</label>";
|
||
|
|
||
|
$ret .= "</p><p>";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_delfriendofs',
|
||
|
'type' => 'radio',
|
||
|
'selected' => $FORM{'opt_delfriendofs'},
|
||
|
'value' => '1',
|
||
|
'raw' => 'id="rem_no"' });
|
||
|
$ret .= " <label for=\"rem_no\">$ML{'.options.removeself'}</label><br />";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_delfriendofs',
|
||
|
'type' => 'radio',
|
||
|
'selected' => ! LJ::did_post() || ! $FORM{'opt_delfriendofs'},
|
||
|
'value' => '0',
|
||
|
'raw' => 'id="rem_yes"' });
|
||
|
$ret .= " <label for=\"rem_yes\">$ML{'.options.keepself'}</label>";
|
||
|
|
||
|
$ret .= "</p><p>";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_redir',
|
||
|
'type' => 'radio',
|
||
|
'selected' => LJ::did_post() && ! $FORM{'opt_redir'},
|
||
|
'value' => '0',
|
||
|
'raw' => 'id="keep_no"' });
|
||
|
$ret .= " <label for=\"keep_no\">" . BML::ml('.options.unlink', {'oldname' => LJ::ljuser($u->{'user'})}) . "</label><br />";
|
||
|
$ret .= LJ::html_check({ 'name' => 'opt_redir',
|
||
|
'type' => 'radio',
|
||
|
'selected' => ! LJ::did_post() || $FORM{'opt_redir'},
|
||
|
'value' => '1',
|
||
|
'raw' => 'id="keep_yes"' });
|
||
|
$ret .= " <label for=\"keep_yes\">" . BML::ml('.options.forward', {'oldname' => LJ::ljuser($u->{'user'})}) . "</label><br />";
|
||
|
}
|
||
|
|
||
|
$ret .= "<p>" . LJ::html_submit($ML{'.label.proceed'}) . "</p>";
|
||
|
|
||
|
$ret .= "</blockquote></p>";
|
||
|
|
||
|
$ret .= "</form>";
|
||
|
return $ret;
|
||
|
};
|
||
|
|
||
|
return $form->() unless LJ::did_post();
|
||
|
|
||
|
my $dbh = LJ::get_db_writer();
|
||
|
|
||
|
unless ($FORM{'userid'} == $u->{'userid'}) {
|
||
|
$err{'user'} = $ML{'.error.differentusername'};
|
||
|
}
|
||
|
$newuser = LJ::canonical_username($FORM{'newuser'});
|
||
|
if (! $newuser) {
|
||
|
$err{'newuser'} = $ML{'.error.username'};
|
||
|
} elsif ($newuser eq $u->{'user'}) {
|
||
|
$err{'newuser'} = $ML{'.error.same'};
|
||
|
}
|
||
|
$ren;
|
||
|
if ($FORM{'token'} =~ /^([0-9a-f]{6,6})(\w{10,10})$/) {
|
||
|
$ren = $dbh->selectrow_hashref("SELECT * FROM renames WHERE renid=? AND token=?",
|
||
|
undef, hex $1, $2);
|
||
|
if (! $ren) {
|
||
|
$err{'token'} = $ML{'.error.token'};
|
||
|
} elsif ($ren->{'rendate'}) {
|
||
|
if ($ren->{'fromuser'} eq $u->{'user'} &&
|
||
|
$ren->{'touser'} eq $newuser) {
|
||
|
return $ML{'.success.usernamerenamed'};
|
||
|
} else {
|
||
|
$err{'token'} = $ML{'.error.usedtoken'};
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
$err{'token'} = $ML{'.error.token'};
|
||
|
}
|
||
|
return $form->() if %err;
|
||
|
|
||
|
my $tou = LJ::load_user($newuser);
|
||
|
my $move_away = 0;
|
||
|
my $exname = undef;
|
||
|
if ($tou) {
|
||
|
# decide if we can move away the existing destination username
|
||
|
|
||
|
if ($tou->{'statusvis'} eq "X") {
|
||
|
# expunged usernames can be moved away. they're already deleted.
|
||
|
$move_away = 1;
|
||
|
} elsif (lc($tou->{'email'}) eq lc($u->{'email'}) &&
|
||
|
$tou->{'statusvis'} eq "V" &&
|
||
|
$tou->{'journaltype'} eq "P") {
|
||
|
if ($tou->{'password'} eq $u->{'password'}) {
|
||
|
if ($tou->{'status'} ne 'A' || $u->{'status'} ne 'A') {
|
||
|
$err{'newuser'} = $ML{'.error.notvalidated'};
|
||
|
} else {
|
||
|
$move_away = 1;
|
||
|
}
|
||
|
} else {
|
||
|
$err{'newuser'} = $ML{'.error.badpass'};
|
||
|
}
|
||
|
} else {
|
||
|
$err{'newuser'} = $ML{'.error.usernametaken'};
|
||
|
}
|
||
|
|
||
|
# if we will be moving the destination username away,
|
||
|
# we need to allocate a name for it
|
||
|
if ($move_away) {
|
||
|
my $tempname = $tou->{'user'};
|
||
|
$tempname = substr($tempname, 0, 9) if length($tempname) > 9;
|
||
|
for (1..10) {
|
||
|
|
||
|
# if it exists, first try the exname found on the
|
||
|
# previous (confirmation) page
|
||
|
if ($_ == 1 && $FORM{'exname'}) {
|
||
|
$exname = $FORM{'exname'};
|
||
|
|
||
|
# otherwise we either didn't have one or it's been
|
||
|
# taken in the meantime?
|
||
|
} else {
|
||
|
$exname = "ex_$tempname" . int(rand(999));
|
||
|
}
|
||
|
|
||
|
# check to see if this exname already exists
|
||
|
unless ($dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE user=?",
|
||
|
undef, $exname)) {
|
||
|
# name doesn't already exist, use this one
|
||
|
last;
|
||
|
}
|
||
|
# name existed, try and get another
|
||
|
|
||
|
if ($_ >= 10) {
|
||
|
return $ML{'.error.allocating'};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return $form->() if %err;
|
||
|
|
||
|
my $confirm = sub {
|
||
|
$ret .= "<?hr?><form method='post'>";
|
||
|
|
||
|
# carry on submitted data in hidden elements
|
||
|
$ret .= LJ::html_hidden("userid" => $u->{'userid'},
|
||
|
"exname" => $exname,
|
||
|
map { $_, $FORM{$_} }
|
||
|
qw(newuser token opt_delfriends opt_delfriendofs
|
||
|
opt_redir));
|
||
|
|
||
|
$ret .= "<?h1 $ML{'.heading.change'} h1?>";
|
||
|
$ret .= "<?p $ML{'.changes'} p?><ul>";
|
||
|
$ret .= "<li>" . BML::ml('.changes.move', {'newuser' => $newuser, 'exname' => $exname}) . "</li>"
|
||
|
if $move_away;
|
||
|
$ret .= "<li>" . BML::ml('.changes.rename', {'newuser' => $newuser, 'oldname' => $u->{'user'}}) . "</li>";
|
||
|
$ret .= "</ul>";
|
||
|
|
||
|
$ret .= "<?h1 $ML{'.heading.sure'} h1?>";
|
||
|
$ret .= "<?p " . BML::ml('.confirm2', {'confirmword' => 'YES'}) . " <blockquote>";
|
||
|
$ret .= LJ::html_text({ 'name' => 'yes', 'size' => 10, 'maxlength' => 3 });
|
||
|
$err->("yes");
|
||
|
$ret .= "</blockquote> $ML{'.confirm.click'} p?>";
|
||
|
|
||
|
$ret .= "<p>" . LJ::html_submit($ML{'.label.rename'}) . "</p>";
|
||
|
$ret .= "</form>";
|
||
|
return $ret;
|
||
|
};
|
||
|
|
||
|
# display confirmation page if "form" is okay and no confirmation sent
|
||
|
return $confirm->() if LJ::did_post && ! exists $FORM{'yes'};
|
||
|
|
||
|
# error check confirmation
|
||
|
unless ($FORM{'yes'} eq "YES") {
|
||
|
$err{'yes'} = $ML{'.error.readit'};
|
||
|
}
|
||
|
return $confirm->() if %err;
|
||
|
|
||
|
my $do_rename = sub {
|
||
|
my ($from, $to) = map { LJ::canonical_username($_) } @_;
|
||
|
return 0 unless $from ne "" && $to ne "";
|
||
|
my $u = LJ::load_user($from);
|
||
|
return 0 unless $u;
|
||
|
foreach my $table (qw(user useridmap overrides style))
|
||
|
{
|
||
|
$dbh->do("UPDATE $table SET user=? WHERE user=?",
|
||
|
undef, $to, $from);
|
||
|
return 0 if $dbh->err;
|
||
|
}
|
||
|
|
||
|
LJ::memcache_kill($u, "userid");
|
||
|
LJ::MemCache::delete("uidof:$from");
|
||
|
LJ::MemCache::delete("uidof:$to");
|
||
|
|
||
|
LJ::infohistory_add($u, 'username', $from);
|
||
|
|
||
|
# tell all web machines to clear their caches for this userid/name mapping
|
||
|
LJ::procnotify_add("rename_user", { 'userid' => $u->{'userid'},
|
||
|
'user' => $u->{'user'} });
|
||
|
return 1;
|
||
|
};
|
||
|
|
||
|
if ($tou && $move_away) {
|
||
|
# time to move this one out of the way we already
|
||
|
# have a valid $exname from above
|
||
|
unless ($exname && $do_rename->($tou->{'user'}, $exname) &&
|
||
|
$dbh->do("INSERT INTO renames (token, payid, userid, fromuser, touser, rendate) " .
|
||
|
"VALUES (?,?,?,?,?,NOW())",
|
||
|
undef, "[moveaway]", 0, $tou->{'userid'}, $tou->{'user'}, $exname))
|
||
|
{
|
||
|
return $ML{'.error.reserved'};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unless ($do_rename->($u->{'user'}, $newuser)) {
|
||
|
return $ML{'.error.unknown'};
|
||
|
}
|
||
|
|
||
|
$dbh->do("UPDATE renames SET userid=?, fromuser=?, touser=?, rendate=NOW() WHERE renid=?",
|
||
|
undef, $u->{'userid'}, $u->{'user'}, $newuser, $ren->{'renid'});
|
||
|
|
||
|
if ($u->{journaltype} eq 'P') {
|
||
|
if ($FORM{'opt_delfriends'}) {
|
||
|
# delete friends
|
||
|
my $friends = LJ::get_friends($u, undef, undef, 'force') || {};
|
||
|
LJ::remove_friend($u, [ keys %$friends ]);
|
||
|
|
||
|
# delete access to post to communities
|
||
|
LJ::clear_rel('*', $u, 'P');
|
||
|
|
||
|
# delete friend-ofs that are communities
|
||
|
# TAG:fr:bml_rename_use:get_member_of
|
||
|
my $users = $dbh->selectcol_arrayref(qq{
|
||
|
SELECT u.userid FROM friends f, user u
|
||
|
WHERE f.friendid=$u->{'userid'} AND
|
||
|
f.userid=u.userid and u.journaltype <> 'P'
|
||
|
});
|
||
|
if ($users && @$users) {
|
||
|
my $in = join(',', @$users);
|
||
|
$dbh->do("DELETE FROM friends WHERE friendid=$u->{'userid'} AND userid IN ($in)");
|
||
|
LJ::memcache_kill($_, "friends") foreach @$users;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($FORM{'opt_delfriendofs'}) {
|
||
|
# delete people (only people) who list this user as a friend
|
||
|
my $users = $dbh->selectcol_arrayref(qq{
|
||
|
SELECT u.userid FROM friends f, user u
|
||
|
WHERE f.friendid=$u->{'userid'} AND
|
||
|
f.userid=u.userid and u.journaltype = 'P'
|
||
|
});
|
||
|
if ($users && @$users) {
|
||
|
my $in = join(',', @$users);
|
||
|
$dbh->do("DELETE FROM friends WHERE friendid=$u->{'userid'} AND userid IN ($in)");
|
||
|
LJ::memcache_kill($_, "friends") foreach @$users;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# delete friend of memcaching, as either path might have done it
|
||
|
LJ::MemCache::delete([ $u->{userid}, "friendofs:$u->{userid}" ]);
|
||
|
}
|
||
|
|
||
|
my $id = LJ::create_account({
|
||
|
'user' => $u->{'user'},
|
||
|
'password' => '',
|
||
|
'name' => '[renamed acct]',
|
||
|
});
|
||
|
|
||
|
my $alias_changed = $dbh->do("UPDATE email_aliases SET alias=? WHERE alias=?",
|
||
|
undef, "$newuser\@$LJ::USER_DOMAIN",
|
||
|
"$u->{'user'}\@$LJ::USER_DOMAIN");
|
||
|
if ($u->{journaltype} ne 'P' || $FORM{'opt_redir'}) {
|
||
|
LJ::update_user($id, { raw => "journaltype='R', statusvis='R', statusvisdate=NOW()" });
|
||
|
LJ::set_userprop($dbh, $id, "renamedto", $newuser);
|
||
|
if ($alias_changed > 0) {
|
||
|
$dbh->do("INSERT INTO email_aliases VALUES (?,?)", undef,
|
||
|
"$u->{'user'}\@$LJ::USER_DOMAIN",
|
||
|
$u->{'email'});
|
||
|
}
|
||
|
} else {
|
||
|
LJ::update_user($id, { journaltype => $u->{journaltype}, raw => "statusvis='D', statusvisdate=NOW()" });
|
||
|
}
|
||
|
|
||
|
$u->kill_session;
|
||
|
|
||
|
# overwrite $ret and give success page
|
||
|
$ret = "<?h1 $ML{'.heading.success'} h1?><ul>";
|
||
|
$ret .= "<li>" . BML::ml('.success.moved', {'newuser' => $newuser, 'exname' => $exname}). "</li>"
|
||
|
if $move_away;
|
||
|
$ret .= "<li>" . BML::ml('.success.renamed', {'newuser' => $newuser, 'olduser' => $u->{'user'}}) . "</li>";
|
||
|
$ret .= "</ul>";
|
||
|
$ret .= "<?p " . BML::ml('.success.login', {'aopts' => 'href="/login.bml"'}) . "p?>"
|
||
|
if $u->{userid} == $remote->{userid};
|
||
|
return $ret;
|
||
|
|
||
|
}
|
||
|
_code?>
|
||
|
|
||
|
<=body
|
||
|
page?>
|