$LJ::SITENAMEABBREV}); _code?>
head<=
<=head
body<=
" unless LJ::text_in(\%POST);
my $mode = $POST{'mode'};
my $code = $POST{'code'} || $GET{'code'};
my @getargs;
push @getargs,"from=$GET{from}" if $GET{from};
push @getargs,"user=$GET{user}" if $GET{user};
my $getextra = '?' . join('&', @getargs) if @getargs;
if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") {
return BML::redirect("$LJ::SSLROOT/create.bml$getextra");
}
# with no mode, decide which screen the user sees first, based
# on whether or not this LJ installation lets in free users
if ($mode eq "") {
$mode = $LJ::USE_ACCT_CODES ?
($code ? "codesubmit" : "entercode")
: "getinfo";
}
my $remote = LJ::get_remote();
my %errors;
my $error_msg = sub {
my $key = shift;
my $pre = shift;
my $post = shift;
my $msg = $errors{$key};
return unless $msg;
return "$pre $msg $post";
};
# Flag to indicate they've submitted with 'audio' as the answer to the spambot
# challenge.
my $wants_audio = 0;
# Captcha id
my ($capid, $anum);
# validate a code they've entered and throw them back to entercode
# mode if it's invalid
if ($code && $mode eq "submit" || # account codes turned off, but one specified anyway
$LJ::USE_ACCT_CODES && ($mode eq "codesubmit" || $mode eq "submit")) # account codes required
{
my $error;
my $userid = 0; # acceptable userid for double-click protection
if ($mode eq "submit") {
my $u = LJ::load_user($POST{'user'});
$userid = $u->{'userid'};
}
$errors{'code'} = $error
unless (LJ::acct_code_check($code, \$error, $userid));
if (%errors) {
$mode = "entercode";
} elsif ($mode eq "codesubmit") {
$mode = "getinfo";
}
}
# MODE: entercode - enter an account code to proceed making an account
if ($LJ::USE_ACCT_CODES && $mode eq "entercode")
{
my $ret;
my $v;
$ret .= "
\n";
open (REM, "$LJ::HOME/htdocs/inc/account-codes");
while () {
$ret .= $_;
}
close REM;
return $ret;
}
# MODE: submit - if they've given 'audio' as the answer to the spambot-blocker,
# reset the mode to 'getinfo' and set the audio flag
if ( $LJ::HUMAN_CHECK{create} && $mode eq 'submit' && lc($POST{answer}) eq 'audio' )
{
$mode = 'getinfo';
$wants_audio = 1;
}
# MODE: submit - try to create an account. might change mode
# if there are errors, we'll populate %errors and
# return to "getinfo" mode below
SUBMIT:
while ($mode eq "submit") # using while instead of if so we can 'last' out of it
{
return "$ML{'Error'}: $ML{'.error.postrequired'}" unless LJ::did_post();
my $user = LJ::canonical_username($POST{'user'});
my $email = LJ::trim(lc($POST{'email'}));
# setup global things that can be used to modify the user later
my $is_underage = 0; # turn on if the user should be marked as underage
my $ofage = 0; # turn on to note that the user is over 13 in actuality
# (but is_underage might be on which just means that their
# account is being marked as underage--even if they're old
# enough [unique cookie check])
# reject this email?
return LJ::sysban_block(0, "Create user blocked based on email",
{ 'new_user' => $user, 'email' => $email, 'name' => $user })
if LJ::sysban_check('email', $email);
my $dbh = LJ::get_db_writer();
if (length($user) > 15) {
$errors{'username'} = "$ML{'error.usernamelong'}";
}
if ($POST{'user'} && ! $user) {
$errors{'username'} = "$ML{'error.usernameinvalid'}";
}
unless ($POST{'user'}) {
$errors{'username'} = "$ML{'.error.username.mustenter'}";
}
foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) {
next unless ($user =~ /$re/);
# you can give people sharedjournal priv ahead of time to create
# reserved communities:
next if LJ::check_priv($remote, "sharedjournal", $user);
$errors{'username'} = "$ML{'.error.username.reserved'}";
}
# see if they're confused and entered a valid account code
# for their username (happens often)
if ($LJ::USE_ACCT_CODES && $user =~ /^.....a[ab].....$/) {
# see if the acctcode is valid and unused
my ($acid, $auth) = LJ::acct_code_decode($user);
my $is_valid = $dbh->selectrow_array("SELECT COUNT(*) FROM acctcode ".
"WHERE acid=? AND rcptid=0",
undef, $acid);
$errors{'username'} = "$ML{'.error.username.iscode'}"
if $is_valid;
}
my $u = LJ::load_user($user);
my $second_submit = 0;
# do not create if this account name is purged
if ($u && $u->{'statusvis'} eq "X") {
$errors{'username'} = BML::ml('.error.username.purged',
{'aopts' => 'href="/rename/"'} );
} elsif ($u) {
my $in_use = 1;
if ($u->{'email'} eq $POST{'email'}) {
if (LJ::login_ip_banned($u)) {
# brute-force possible going on
} else {
if ($u->{'password'} eq $POST{'password1'}) {
# okay either they double-clicked the submit button
# or somebody entered an account name that already exists
# with the existing password
$second_submit = 1;
$in_use = 0;
} else {
LJ::handle_bad_login($u);
}
}
}
if ($in_use) {
$errors{'username'} = "$ML{'.error.username.inuse'}";
}
}
$POST{'password1'} = LJ::trim($POST{'password1'});
$POST{'password2'} = LJ::trim($POST{'password2'});
if ($POST{'password1'} ne $POST{'password2'}) {
$errors{'password'} = "$ML{'.error.password.nomatch'}";
} else {
my $checkpass = LJ::run_hook("bad_password",
{
'user' => $user,
'email' => $email,
'password' => $POST{'password1'},
});
if ($checkpass) {
$errors{'password'} = "Bad password: $checkpass";
}
}
if (! $POST{'password1'}) {
$errors{'password'} = "$ML{'.error.password.blank'}";
} elsif (length $POST{'password1'} > 30) {
$errors{'password'} = "$ML{'password.max30'}";
}
unless (LJ::is_ascii($POST{'password1'})) {
$errors{'password'} = "$ML{'.error.password.asciionly'}";
}
### start COPPA_CHECK
# age checking to determine how old they are
if ($LJ::COPPA_CHECK) {
my $uniq;
if ($LJ::UNIQ_COOKIES) {
$uniq = Apache->request->notes('uniq');
if ($uniq) {
my $timeof = $dbh->selectrow_array('SELECT timeof FROM underage WHERE uniq = ?', undef, $uniq);
$is_underage = 1 if $timeof && $timeof > 0;
}
}
my ($year, $mon, $day) = ( $POST{"bday_yyyy"}+0, $POST{"bday_mm"}+0, $POST{"bday_dd"}+0 );
if ($year < 100 && $year > 0) {
$POST{'bday_yyyy'} += 1900;
$year += 1900;
}
# get current time
my ($nday, $nmon, $nyear) = (gmtime())[3, 4, 5];
$nyear += 1900;
$nmon += 1;
# require dates in the 1900s (or beyond)
if ($year && $mon && $day && $year >= 1900 && $year < $nyear) {
# now see how many years back they are
my $ofageyear = $year + 13;
if ($ofageyear > $nyear) {
$is_underage = 1;
} elsif ($ofageyear == $nyear) {
# years match, see if they were born after this month
if ($mon > $nmon) {
$is_underage = 1;
} elsif ($mon == $nmon) {
# now check the day
if ($day > $nday) {
$is_underage = 1;
} else {
$ofage = 1;
}
} else {
$ofage = 1;
}
} else {
$ofage = 1;
}
} else {
$errors{'bday'} = "$ML{'.error.birthday.invalid'}";
}
# note this unique cookie as underage (if we have a unique cookie)
if ($is_underage && $uniq) {
$dbh->do("REPLACE INTO underage (uniq, timeof) VALUES (?, UNIX_TIMESTAMP())", undef, $uniq);
}
}
### end COPPA_CHECK
if ($LJ::TOS_CHECK && ! $POST{'agree_tos'}) {
$errors{'agree_tos'} = $ML{'tos.error'};
}
# check the email address
{
my @email_errors;
LJ::check_email($email, \@email_errors);
if ($LJ::USER_EMAIL and $email =~ /\@\Q$LJ::USER_DOMAIN\E$/i) {
push @email_errors, BML::ml(".error.email.lj_domain",
{domain => $LJ::USER_DOMAIN});
}
$errors{'email'} = join(", ", @email_errors) if @email_errors;
}
# Check the turing test answer if it's turned on
if ($LJ::HUMAN_CHECK{create}) {
($capid, $anum) = LJ::Captcha::session_check_code($POST{captcha_chal}, $POST{answer});
$errors{'captcha'} = $ML{'.captcha.invalid'} unless $capid && $anum;
}
last SUBMIT if %errors;
my $clusterid = ($LJ::DEBUG{'allow_cluster_select'}
? $POST{'cluster_id'}
: LJ::new_account_cluster()) + 0;
die "Cluster 0 not supported" unless $clusterid;
my $userid = $u ? $u->{'userid'}+0 : 0;
# create user and send email as long as the user didn't double-click submit
# (or they tried to re-create a purged account)
unless ($second_submit) {
my $bdate = sprintf("%04d-%02d-%02d", $POST{bday_yyyy}, $POST{bday_mm}, $POST{bday_dd});
my $nu = LJ::User->create_personal(
'user' => $user,
'bdate' => $bdate,
'email' => $email,
'password' => $POST{password1},
'get_ljnews' => $POST{news},
'inviter' => $inviter,
'underage' => $is_underage,
'ofage' => $ofage,
);
return "There was an error creating your account." unless $nu;
# Mark the turing test for deletion
if ($LJ::HUMAN_CHECK{create}) {
LJ::Captcha::expire($capid, $anum, $nu->id);
}
# if we're using account codes on this site, mark the code as used
if ($code) {
my ($acid, $auth) = LJ::acct_code_decode($code);
$dbh->do("UPDATE acctcode SET rcptid=$nu->id WHERE acid=$acid");
if ($dbh->err) { return $dbh->errstr; }
}
foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) {
my $friendid = LJ::get_userid($friend);
LJ::add_friend($nu->id, $friendid) if $friendid and $POST{"initial_optional_friend_$friend"};
}
# Mark the turing test for deletion
if ($LJ::HUMAN_CHECK{create}) {
LJ::Captcha::expire($capid, $anum, $nu->id);
}
# send welcome mail... unless they're underage
unless ($is_underage) {
my $aa = LJ::register_authaction($nu->id, "validateemail", $email);
my $body = BML::ml('email.newacct4.body', {
"sitename" => $LJ::SITENAME,
"regurl" => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}",
"journal_base" => $nu->journal_base,
"username" => $nu->user,
"siteroot" => $LJ::SITEROOT,
"sitenameshort" => $LJ::SITENAMESHORT,
"lostinfourl" => "$LJ::SITEROOT/lostinfo.bml",
"editprofileurl" => "$LJ::SITEROOT/manage/profile/",
"searchinterestsurl" => "$LJ::SITEROOT/interests.bml",
"editpicsurl" => "$LJ::SITEROOT/editpics.bml",
"customizeurl" => "$LJ::SITEROOT/customize/style.bml",
"postentryurl" => "$LJ::SITEROOT/update.bml",
});
LJ::send_mail({
'to' => $email,
'from' => $LJ::ADMIN_EMAIL,
'fromname' => $LJ::SITENAME,
'charset' => 'utf-8',
'subject' => BML::ml('email.newacct.subject', {'sitename' => $LJ::SITENAME}),
'body' => $body,
});
}
# If they were invited then add friend and do joins
# Needed to do this after we load the $nu object
if ($POST{from}) {
my $ivf = LJ::load_user($POST{from});
my $friend = $POST{"inviter_friend_$ivf->{user}"};
LJ::add_friend($nu->id, $ivf->{userid})
if $friend;
my @ijoins;
foreach (split(',', $POST{inviter_joins})) {
# Join the comm and add to friends list
next unless $POST{"inviter_join_$_"};
push @ijoins, $_;
my $ci = LJ::get_community_row($_);
next unless $ci;
if ($ci->{membership} eq 'open') {
LJ::join_community($nu->id, $_, 1);
} else {
my $cu = LJ::load_userid($_);
next unless $cu && $nu;
LJ::comm_join_request($cu, $nu);
LJ::add_friend($nu->id, $cu->{userid});
}
}
# Log who invited them
my $ijoinsstr = join(',', @ijoins);
LJ::statushistory_add($nu->id, $ivf->{userid}, 'create_from_invite',
"Recommended: $POST{inviter_joins}\nJoined: $ijoinsstr");
# Send the inviter an email
my $body = BML::ml('.email.invite.body', {
username => $ivf->{user},
sitename => $LJ::SITENAMESHORT,
infolink => "$LJ::SITEROOT/userinfo.bml?user=$nu->{user}",
invitelink => "$LJ::SITEROOT/friends/invite.bml"
});
LJ::send_mail({
'to' => $ivf->{email},
'from' => $LJ::ADMIN_EMAIL,
'fromname' => $LJ::SITENAME,
'charset' => 'utf-8',
'subject' => BML::ml('.email.invite.subject', {'sitename' => $LJ::SITENAMESHORT}),
'body' => $body,
});
}
if ($LJ::TOS_CHECK) {
my $err = "";
$nu->tosagree_set(\$err)
or return LJ::bad_input($err);
}
$nu->make_login_session;
# local sites may want to override what happens at this point
my $redirect = undef;
my $stop_output;
LJ::run_hooks("create.bml_postsession", {
post => \%POST,
u => $nu,
redirect => \$redirect,
ret => \$ret,
stop_output => \$stop_output,
});
return BML::redirect($redirect) if $redirect;
return $ret if $stop_output;
return BML::redirect("$LJ::SITEROOT/newuser.bml");
}
}
if ($mode eq "getinfo" || %errors)
{
my $ret;
my $v;
if (%errors) {
my @errors_order = ('code', 'username', 'email', 'password', 'agree_tos', 'captcha', 'invalidform');
my %errors_def;
$errors_def{$_} = 1 for @errors_order;
foreach my $key (keys %errors) { push @errors_order, $key unless $errors_def{$key}; }
$ret .= "$ML{'.errors.label'}