$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"; $ret .= LJ::html_hidden(mode => 'codesubmit', ssl => $FORM{'ssl'}); $ret .= ""; $v = LJ::ehtml($code); $ret .= " "; $ret .= $error_msg->('code', '
'); $ret .= " standout?>"; $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'} standout?>"; } $ret .= " "href='$LJ::SITEROOT/community/create.bml'" }) . " p?>" unless %errors; $ret .= "
\n"; $ret .= LJ::html_hidden(mode => 'submit', code => $code, ssl => $FORM{'ssl'}); $ret .= "
    "; ### username $v = LJ::ehtml($FORM{'user'}); $ret .= "
  1. $ML{'.username.box.head'}
    "; $ret .= $error_msg->('username', '

    ', '

    '); $ret .= "
    " . BML::ml(".username.text_1", {'sitename' => $LJ::SITENAME, 'lc_sitename' => lc($LJ::SITENAME) }) . "
    "; $ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style=""' }); $ret .= " ($ML{'.username.maxchars'})
    \n"; $ret .= "
    $ML{'.username.charsallowed_1'}
    " if (!%errors || exists $errors{'username'}); $ret .= "
  2. "; ### email address $v = LJ::ehtml($FORM{'email'}); $ret .= "
  3. $ML{'.email.input.head'}
    "; $ret .= $error_msg->('email', '

    ', '

    '); $ret .= "
    " . BML::ml('.email.text_1', { aopts => "target='_new' href='$LJ::SITEROOT/legal/privacy.bml'", }) . "
    "; $ret .= LJ::html_text({'name' => 'email', 'size' => 40, 'maxlength' => 50, 'value' => $v,}); $ret .= "
  4. "; # Password $ret .= "
  5. $ML{'.password.input.head1'}
    \n"; $ret .= $error_msg->('password', '

    ', '

    '); $ret .= "
    $ML{'.password.secure'}
    " if exists $errors{'password'}; $ret .= "
    $ML{'.password.text'}
    \n
    "; my $pass_value = $errors{'password'} ? "" : $POST{'password1'}; $ret .= LJ::html_text({'name' => 'password1', 'size' => 30, 'maxlength' => 31, 'type' => "password", value => $pass_value, }); $ret .= "
    $ML{'.password.input.head2'}
    \n
    "; $ret .= LJ::html_text({'name' => 'password2', 'size' => 30, 'maxlength' => 31, 'type' => "password", value => $pass_value, }); $ret .= "
    \n"; unless ($LJ::NO_PASSWORD_CHECK) { $ret .= BML::ml('.password.secure_1', { aopts => "target='_new' href='$LJ::HELPURL{secure_password}'"}); $ret .= "
      "; $ret .= "
    • $ML{'.password.secure.pt1'}
    • \n"; $ret .= "
    • $ML{'.password.secure.pt2'}
    • \n"; $ret .= "
    • $ML{'.password.secure.pt3'}
    • \n"; $ret .= "
    • $ML{'.password.secure.pt4'}
    • \n
    \n"; } $ret .= "
  6. "; if (@LJ::INITIAL_OPTIONAL_FRIENDS) { $ret .= "
  7. $ML{'.initialfriends.heading'}
    "; $ret .= "
    $ML{'.initialfriends'}
    "; $ret .= "
    "; foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) { my $selected = LJ::did_post() ? $POST{"initial_optional_friend_$friend"} : (grep { $_ eq $friend } @LJ::INITIAL_OPTOUT_FRIENDS); $ret .= LJ::html_check({'name' => "initial_optional_friend_$friend", 'value' => 1, 'selected' => $selected, 'id' => "optfriend_$friend", }); $ret .= "
    "; } $ret .= "
  8. "; } # Was this person invited by another user? If so, # then show interface to add inviter as friend as # well as 10ish communities they are a member of my $ifrom = LJ::did_post() ? $POST{from} : $GET{from}; my $inviter; $inviter = LJ::load_user($ifrom) if $ifrom; if ($inviter) { $ret .= "
  9. Your friend " . LJ::ljuser($inviter) . " welcomes you to "; $ret .= "$LJ::SITENAMESHORT
    "; $ret .= "
    "; $ret .= LJ::html_hidden('from', $inviter->{user}); $ret .= LJ::html_check({ name => "inviter_friend_$inviter->{user}", value => 1, selected => LJ::did_post() ? $POST{"inviter_friend_$inviter->{user}"} : 1, id => "inviter_$inviter->{user}", }); $ret .= "
    "; my %comms; unless ($POST{inviter_joins}) { # Load their friendofs to determine community membership my @ids = LJ::get_friendofs($inviter); my %fro; LJ::load_userids_multiple([ map { $_ => \$fro{$_} } @ids ]); foreach my $ulocal (values %fro) { next unless $ulocal->{'statusvis'} eq 'V'; next unless $ulocal->{'journaltype'} eq 'C'; # TODO: This is bad if they belong to a lot of communities, # is a db query to global each call my $ci = LJ::get_community_row($ulocal); next if $ci->{'membership'} eq 'closed'; # Add to %comms $ulocal->{istatus} = 'normal'; $comms{$ulocal->{userid}} = $ulocal; } # Get usage information about comms if (%comms) { my $ids = join(',', map { $_->{userid} } values %comms); my $dbr = LJ::get_db_reader; my $sth = $dbr->prepare("SELECT UNIX_TIMESTAMP(timeupdate), UNIX_TIMESTAMP(timecreate), userid ". "FROM userusage WHERE userid IN($ids)"); $sth->execute; while (my @row = $sth->fetchrow_array) { ($comms{$row[2]}->{'timeupdate'}, $comms{$row[2]}->{'timecreate'}) = ($row[0], $row[1]); } } # Prune the list by time last updated and make sure to # display comms created in the past 10 days or where # the inviter is a maint or mod my $over30 = 0; my $now = time(); foreach my $comm (sort {$b->{timeupdate} <=> $a->{timeupdate}} values %comms) { if ($now - $comm->{timecreate} <= 86400*10) { $comm->{istatus} = 'new'; next; } my $maintainers = LJ::load_rel_user_cache($comm->{userid}, 'A') || []; my $moderators = LJ::load_rel_user_cache($comm->{userid}, 'M') || []; foreach (@$maintainers, @$moderators) { if ($_ == $inviter->{userid}) { $comm->{istatus} = 'mm'; next; } } if ($over30) { delete $comms{$comm->{userid}}; next; } else { if (time() - $comm->{timeupdate} > 86400*30) { delete $comms{$comm->{userid}}; $over30 = 1; } } } # If we still have more than 20 comms, delete any with less than # five members if (scalar keys %comms > 20) { foreach my $comm (values %comms) { next unless $comm->{istatus} eq 'normal'; my $ids = LJ::get_friends($comm); if (scalar values %$ids < 5) { delete $comms{$comm->{userid}}; } } } } if (LJ::did_post()) { foreach (split(',', $POST{inviter_joins})) { my $cj = LJ::load_userid($_); $comms{$_} = $cj if $cj; } } if (%comms) { $ret .= "
    Select which of your friend's communities you'd like to join:
    "; my $i = 0; foreach my $comm (sort { $a->{user} cmp $b->{user} } values %comms) { last if $i >= 20; $ret .= LJ::html_check({ name => "inviter_join_$comm->{userid}", value => 1, selected => LJ::did_post() ? $POST{"inviter_join_$comm->{user}"} : 0, id => "inviter_$comm->{user}", }); my $le = $comm->{istatus} eq 'mm' ? ' *' : ''; $ret .= "
    "; push @joins, $comm->{userid}; $i++; } $ret .= LJ::html_hidden('inviter_joins', join(',', @joins)); $ret .= ""; } $ret .= "
  10. "; } if ($LJ::COPPA_CHECK) { $ret .= "
  11. $ML{'.birthday.head'}
    "; $ret .= "
    $errors{'bday'}
    " if exists $errors{'bday'}; $ret .= "
    "; $ret .= BML::ml('.birthday.question_3', {'aopts' => "target='_new' href='$LJ::SITEROOT/legal/privacy.bml'"}); $ret .= "
    "; $ret .= ""; $ret .= "
    $ML{'.birthday.birthdate'}"; $ret .= LJ::html_datetime({ name => 'bday', notime => 1, default => sprintf("%04d-%02d-%02d", $POST{bday_yyyy}, $POST{bday_mm}, $POST{bday_dd}) }); $ret .= "
  12. "; $ret .= "
    $ML{'.birthday.warning'}
    "; } LJ::run_hooks("create.bml_opts", { post => \%POST, get => \%GET, ret => \$ret, }); if ($LJ::TOS_CHECK) { $ret .= "
  13. $ML{'.tos.heading'}
    "; $ret .= LJ::tosagree_widget($POST{agree_tos}, $errors->{agree_tos}); $ret .= "
  14. "; } if ($LJ::DEBUG{'allow_cluster_select'}) { $ret .= "
  15. $ML{'.clusterselect.head'}
    "; $ret .= "
    $ML{'.clusterselect.text'}
    "; $ret .= LJ::html_select({ 'name' => 'cluster_id' }, "0", "$BML{'.clusterselect.nocluster'}", map { $_, BML::ml(".clusterselect.clusternum", {'number' => $_}) } @LJ::CLUSTERS); $ret .= "
    $ML{'.clusterselect.cluster'}
    "; $ret .= "
  16. "; } if ($LJ::HUMAN_CHECK{create}) { my ($captcha_chal, $captcha_sess); my $answer = $POST{answer}; undef $answer if $errors{'captcha'} || $wants_audio; $captcha_chal = $POST{captcha_chal}; undef $captcha_chal if $errors{'captcha'}; $captcha_chal = $captcha_chal || LJ::challenge_generate(900); $captcha_sess = LJ::get_challenge_attributes($captcha_chal); my $try = 0; if ($form->{captcha_chal}) { my $dbcm = LJ::get_cluster_reader(); $try = $dbcm->selectrow_array('SELECT trynum FROM captcha_session ' . 'WHERE sess=?', undef, $captcha_sess); } $ret .= "
  17. $ML{'.captcha.prove'}
    "; # Visual challenge unless ( $wants_audio || $POST{audio_chal} ) { $ret .= "
    $ML{'.captcha.desc'}
    "; if ($capid && $anum) { # previously entered correctly $ret .= ""; } else { $ret .= ""; } } # Audio challenge else { $ret .= "
    $ML{'.captcha.audiodesc'}
    "; if ($capid && $anum) { $ret .= "$ML{'.captcha.play'}"; } else { $ret .= "$ML{'.captcha.play'}"; } $ret .= LJ::html_hidden(audio_chal => 1); } $ret .= "

    $ML{'.captcha.answer'}"; $ret .= LJ::html_text({ name => 'answer', size => 15, value => $answer }); $ret .= LJ::html_hidden(captcha_chal => $captcha_chal); $ret .= $error_msg->('captcha', '

    ', '

    '); $ret .= "
  18. "; } $ret .= "
"; $ret .= "
"; $ret .= ""; $ret .= "
"; $ret .= "
"; return $ret; } return "$ML{'error.unknownmode'}: $mode"; _code?> <=body page?> link: htdocs/legal/privacy.bml post: htdocs/create.bml, htdocs/manage/profile/index.bml file: htdocs/inc/account-codes hook: post_create _c?>