# This code was forked from the LiveJournal project owned and operated # by Live Journal, Inc. The code has been modified and expanded by # Dreamwidth Studios, LLC. These files were originally licensed under # the terms of the license supplied by Live Journal, Inc, which can # currently be found at: # # http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt # # In accordance with the original license, this code and all its # modifications are provided under the GNU General Public License. # A copy of that license can be found in the LICENSE file included as # part of this distribution. package LJ::CreatePage; use strict; use Carp qw(croak); use DW::Auth::Password; sub verify_username { my $class = shift; my $given_username = shift; my %opts = @_; my $post = $opts{post}; my $second_submit_ref = $opts{second_submit_ref}; my $error; $given_username = LJ::trim($given_username); my $user = LJ::canonical_username($given_username); unless ($given_username) { $error = LJ::Lang::ml('widget.createaccount.error.username.mustenter'); } if ( $given_username && !$user ) { $error = LJ::Lang::ml('error.usernameinvalid'); } if ( length $given_username > $LJ::USERNAME_MAXLENGTH ) { $error = LJ::Lang::ml( 'error.usernamelong1', { maxlength => $LJ::USERNAME_MAXLENGTH } ); } my $u = LJ::load_user($user); my $in_use = 0; # because these error messages overwrite each other, do these in a specific order # -- rename to a purged journal # -- username in use, unless it's reserved. # do not create if this account name is purged if ( $u && $u->is_expunged ) { $error = LJ::Lang::ml( 'widget.createaccount.error.username.purged', { aopts => "href='$LJ::SITEROOT/rename/'" } ); } elsif ($u) { $in_use = 1; # only do these checks on POST if ( $post->{email} && $post->{password1} ) { if ( $u->email_raw eq $post->{email} ) { if ( LJ::login_ip_banned($u) ) { # brute-force possibly going on } else { if ( DW::Auth::Password->check( $u, $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_ref = 1 if $second_submit_ref; $in_use = 0; } else { LJ::handle_bad_login($u); } } } } } # don't allow protected usernames $error = LJ::Lang::ml('widget.createaccount.error.username.invalid') if LJ::User->is_protected_username($user); $error = LJ::Lang::ml('widget.createaccount.error.username.inuse') if $in_use; return $error; } sub verify_password { my $class = shift; my %opts = @_; return undef unless LJ::is_enabled('password_check'); my ( $password, $username, $email, $name ); my $u = $opts{u}; if ( LJ::isu($u) ) { $username = $u->user; $email = $u->email_raw; $name = $u->name_raw; } $password = $opts{password} if $opts{password}; $username = $opts{username} if $opts{username}; $email = $opts{email} if $opts{email}; $name = $opts{name} if $opts{name}; # password must exist return LJ::Lang::ml('widget.createaccount.error.password.blank') unless $password; # at least a few characters return LJ::Lang::ml('widget.createaccount.error.password.tooshort') if length $password < $LJ::PASSWORD_MINLENGTH; # no more than X characters return LJ::Lang::ml('widget.createaccount.error.password.toolong') if length $password > $LJ::PASSWORD_MAXLENGTH; # only ascii characters return LJ::Lang::ml('widget.createaccount.error.password.asciionly') unless LJ::is_ascii($password); # not the same as the username or the reversed username if ($username) { return LJ::Lang::ml('widget.createaccount.error.password.likeusername') if lc $password eq lc $username || lc $password eq lc reverse $username; } # not the same as either part of the email address if ($email) { $email =~ /^(.+)@(.+)\./; return LJ::Lang::ml('widget.createaccount.error.password.likeemail') if lc $password eq lc $1 || lc $password eq lc $2; } # not the same as the displayed name or the reversed displayed name if ($name) { return LJ::Lang::ml('widget.createaccount.error.password.likename') if lc $password eq lc $name || lc $password eq lc reverse $name; } # at least 4 unique characters my %unique_chars = map { $_ => 1 } split( //, $password ); return LJ::Lang::ml('widget.createaccount.error.password.needsmoreuniquechars') unless scalar keys %unique_chars >= 4; # contains at least one digit or symbol return LJ::Lang::ml('widget.createaccount.error.password.needsnonletter') if $password =~ /^[A-Za-z]+$/; # isn't similar to a common password my @common_passwords = grep { $_ } split( /\r?\n/, LJ::load_include('common-passwords') ); foreach my $comm_pass ( $LJ::SITENAMESHORT, @common_passwords ) { # you can have a common password in your password if your password is greater in length # than the sum of the common password's length plus the ceiling of half of its length next if length $password > ( ( length $comm_pass ) + POSIX::ceil( ( length $comm_pass ) / 2 ) ); return LJ::Lang::ml('widget.createaccount.error.password.common') if $password =~ /$comm_pass/i; } return undef; } 1;