###############################################################################
# LogInOut.pl                                                                 #
###############################################################################
# YaBB: Yet another Bulletin Board                                            #
# Open-Source Community Software for Webmasters                               #
# Version:        YaBB 2.2                                                    #
# Packaged:       November 8, 2007                                            #
# Distributed by: http://www.yabbforum.com                                    #
# =========================================================================== #
# Copyright (c) 2000-2007 YaBB (www.yabbforum.com) - All Rights Reserved.     #
# Software by:  The YaBB Development Team                                     #
#               with assistance from the YaBB community.                      #
# Sponsored by: Xnull Internet Media, Inc. - http://www.ximinc.com            #
#               Your source for web hosting, web design, and domains.         #
###############################################################################

$loginoutplver = 'YaBB 2.2 $Revision: 1.22 $';
if ($action eq 'detailedversion') { return 1; }

if ($regcheck) {
	require "$sourcedir/Decoder.pl";
}
&LoadLanguage('LogInOut');

$regstyle = '';

sub Login {
	my $shared_login;
	$sharedLogin_title = $loginout_txt{'34'};
	$shared_login = &sharedLogin;
	$yymain .= $shared_login;
	$yytitle = $loginout_txt{'34'};
	&template;
	exit;
}

sub Login2 {
	&fatal_error("no_username") if ($FORM{'username'} eq "");
	&fatal_error("no_password") if ($FORM{'passwrd'}  eq "");
	$username = $FORM{'username'};
	&fatal_error("invalid_character","$loginout_txt{'35'} $loginout_txt{'241'}")	if ($username !~ /^[\s0-9A-Za-z#%+,-\.:=?@^_]+$/);
	&fatal_error("only_numbers_allowed")						if ($FORM{'cookielength'} !~ /^[0-9]+$/);
#	$FORM{'username'} =~ s/\s/_/g;
	## Check if login ID is not and email address or screenname ##
	if (!-e "$memberdir/$username.vars"){
		$test_id = &MemberIndex("who_is", "$username");
		if ($test_id ne ""){ $username = $test_id} else {&fatal_error("bad_credentials"); }
	}
	if (-e "$memberdir/$username.pre" && -e "$memberdir/$username.vars") { unlink "$memberdir/$username.pre"; }
	if (-e "$memberdir/$username.pre" && ($regtype == 1 || $regtype == 2)) { &fatal_error('not_activated'); }


	# Need to do this to get correct case of username,
	# for case insensitive systems. Can cause weird issues otherwise
	$caseright = 0;
	&ManageMemberlist("load");
	while (($curmemb, $value) = each(%memberlist)) {
		if ($username =~ m/\A\Q$curmemb\E\Z/) { $caseright = 1; last; }
	}
	undef %memberlist;
	if(!$caseright) {
		$username = "Guest";
		&fatal_error("bad_credentials");
	}

	if (-e ("$memberdir/$username.dat") || -e ("$memberdir/$username.vars")) {
		&LoadUser($username);
		my $spass     = ${$uid.$username}{'password'};
		my $cryptpass = &encode_password("$FORM{'passwrd'}");

		# convert non encrypted password to MD5 crypted one
		if ($spass eq $FORM{'passwrd'} && $spass ne $cryptpass) {

			# only encrypt the password if it's not already MD5 encrypted
			# MD5 hashes in YaBB are always 22 chars long (base64)
			if (length(${$uid.$username}{'password'}) != 22) {
				${$uid.$username}{'password'} = $cryptpass;
				&UserAccount($username, "update");
				$spass = $cryptpass;
			}
		}
		if ($spass ne $cryptpass) {
			$username = "Guest";
			&fatal_error("bad_credentials");
		} else {
			$realname     = ${$uid.$username}{'realname'};
			$realemail    = ${$uid.$username}{'email'};
			$iamadmin     = ${$uid.$username}{'position'} eq 'Administrator' ? 1 : 0;
			$iamgmod      = ${$uid.$username}{'position'} eq 'Global Moderator' ? 1 : 0;
			$sessionvalid = 1;
		}
	} else {
		$username = "Guest";
		&fatal_error("bad_credentials");
	}
	$iamguest = $username eq 'Guest' ? 1 : 0;
	if ($FORM{'cookielength'} == 1) { $ck{'len'} = 'Sunday, 17-Jan-2038 00:00:00 GMT'; }
	elsif ($FORM{'cookielength'} == 2) { $ck{'len'} = ''; }
	else { $ck{'len'} = "\+$FORM{'cookielength'}m"; }
	$password = &encode_password("$FORM{'passwrd'}");
	${$uid.$username}{'session'} = &encode_password($user_ip);
	chomp ${$uid.$username}{'session'};
	&UserAccount($username, "update", "lastonline");
	&UpdateCookie("write", "$username", "$password", "${$uid.$username}{'session'}", "/", "$ck{'len'}");

	if ($maintenance && !$iamadmin) { $username = 'Guest'; &fatal_error("admin_login_only"); }
	&LoadIMs;
	&banning;
	&WriteLog;
	$yySetLocation = qq~$scripturl~;
	&redirectexit;
}

sub Logout {
	$yySetLocation = qq~$scripturl~;
	if ($username eq 'Guest') { &redirectexit;	}
	# Write log
	fopen(LOG, "$vardir/log.txt");
	my @entries = <LOG>;
	fclose(LOG);
	fopen(LOG, ">$vardir/log.txt", 1);
	$field = $username;
	foreach $curentry (@entries) {
		$curentry =~ s/\n//g;
		($name, $value) = split(/\|/, $curentry);
		if ($name ne $field) { print LOG "$curentry\n"; }
	}
	fclose(LOG);
	&UserCheck($username, 'onlinealert');
	# has member got pm alert switched on?
	if((!$enable_PMcontrols && $enable_PMpostAlert) || ($enable_PMcontrols && $usercheck{'onlinealert'} eq "on") || (!$enable_PMcontrols && $enable_PMpostAlert && $usercheck{'onlinealert'} eq "on") )	{
		# so, need to check any alerts timestamped between last online and now.
		# if found, they need converting to smtp and sending instead.
		&UserCheck($username, 'lastonline');
		$timeNow = int(time);
		## open and read back .msg file to catch any 'a' flagged - alert - pms, 
		## only those dropped in since last recorded online.
		## since member is logging off, the presumption is the gap between last view and
		## 'now' haven't been seen, so need converting to email 
		fopen(USERMSG, "$memberdir/$username.msg");
		@userMessages = <USERMSG>;
		fclose(USERMSG);
		$myLang = qq~${$username}{'language'}~;
		require "$sourcedir/Post.pl";
		&LoadNotifyMessages($myLang);
		fopen(USERMSG, ">$memberdir/$username.msg");
		foreach my $userMessage (@userMessages) {
			## check each inbox message back to the lastonline time
#messageid|(from)user|(touser(s))|(ccuser(s))|(bccuser(s))|
#		subject|date|message|(parentmid)|reply#|ip|messagestatus|
##            flags|storefolder|attachment
		
			chomp $userMessage;
			$yymain .= qq~messageline ($userMessage)~;
			($messageid, $fromuser, $touser, $tocc, $tobcc, $subject, $messdate, $message, $parentmid, $reply, $ip, $messagestatus, $flags, $folder, $att) = split('\|',$userMessage );
			## one we've hit the time, jump out and finish
			## else, check that its an 'alert' 
#			my $midlol = $messageid-$usercheck{'lastonline'};
#$yymain .= qq~<p>messageid($messageid)(int($messageid)) lastonline(int($usercheck{'lastonline'})) mid-lol($midlol)</p> ~;	
			if(int($messageid) < int($usercheck{'lastonline'}))	{
				print USERMSG qq~$userMessage\n~;
				}
			elsif($messagestatus =~ /n/)	{ # n = notify
				#(undef, $curmail, undef) = split(/\|/, $memberinf{$username},3);
				my $timeNow = int(time);
				$myLangLine = ${$username}{'language'}{'136'};
				&sendmail(${$username}{'email'}, $notifysubjects{$myLangLine}, $message);
				
				$message .= qq~<br />\[edit\]$forwardedpm\[/edit\]~;
				$messagestatus =~ s/n//;
				print USERMSG qq~$messageid|$fromuser|$touser|$tocc|$tobcc|$subject|$messdate|$message|$parentmid|$reply|$ip|$messagestatus|$flags|$folder|$att\n~;
			} 
		}
		fclose(USERMSG);
	}
	if ($action ne "profile2") { &UserAccount($username, "update", "lastonline"); }
	&UpdateCookie("delete");

	$username           = 'Guest';
	$iamguest           = '1';
	$iamadmin           = '';
	$iamgmod            = '';
	$password           = '';
	@settings           = ();
	@immessages         = ();
	$yyim               = "";
	$realname           = '';
	$realemail          = '';
	$ENV{'HTTP_COOKIE'} = '';
	$yyuname            = "";
	if (!$guestaccess) { $yySetLocation = qq~$scripturl?action=login~; }
	&redirectexit;
}

sub sharedLogin {
	if ($action eq 'login' || $maintenance) {
		$border = qq~
		<div class="bordercolor" style="width: 100%; margin-bottom: 8px; margin-left: auto; margin-right: auto;">
	~;
		$border_with_title = qq~
		<div class="bordercolor" style="width: 700px; margin-bottom: 8px; margin-left: auto; margin-right: auto;">
	~;
		$border_bottom = qq~</div>~;
	}

	if    ($Cookie_Length == 1)    { $clsel1    = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 2)    { $clsel2    = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 60)   { $clsel60   = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 180)  { $clsel180  = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 360)  { $clsel360  = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 720)  { $clsel720  = " selected=\"selected\" "; }
	elsif ($Cookie_Length == 1440) { $clsel1440 = " selected=\"selected\" "; }
	if ($sharedLogin_title ne "") {
		$sharedlog .= qq~
		$border_with_title
		<table cellpadding="4" cellspacing="1" border="0" width="100%" align="center">
		<tr><td class="titlebg" colspan="2"><b>$sharedLogin_title</b></td></tr>
		~;
		if ($sharedLogin_text ne "") {
			$sharedlog .= qq~
			<tr><td class="windowbg" colspan="2" align="left">$sharedLogin_text</td></tr>
			~;
		}
		$sharedlog .= qq~
		<tr><td class="windowbg2" colspan="2" valign="middle">
		~;
	} else {
		$sharedlog .= qq~
		$border
		<table class="bordercolor" align="center" cellpadding="0" cellspacing="0" border="0" width="100%">
		<tr><td class="tabtitle" colspan="2" valign="middle" align="center" height="25"><span class="ie6alpha">$loginout_txt{'34'}</span></td></tr>
		<tr>
		<td class="windowbg" width="5%" valign="middle" align="center"><img src="$imagesdir/login.gif" border="0" alt="" /></td>
		<td class="windowbg2" valign="middle">
		~;
	}
	$sharedlog .= qq~
        <form action="$scripturl?action=login2" method="post">
		<div style="clear: both; padding-top: 4px; margin-left: auto; margin-right: auto; width: 600px;">
			<span style="float: left; width: 50%; text-align: left; margin-bottom: 5px;">
				$loginout_txt{'35'} $maintxt{'377'} $loginout_txt{'33'}: <br />
				<input type="text" name="username" size="30" maxlength="30" style="width: 285px;" tabindex="1"$regstyle />
			</span>
			<span style="float: left; width: 25%; text-align: left; margin-bottom: 5px;">
				$loginout_txt{'36'}:<br />
				<input type="password" name="passwrd" size="15" maxlength="30" style="width: 110px;" tabindex="2" />
			</span>
			<span style="float: left; width: 25%; text-align: left; margin-bottom: 5px;">
				$loginout_txt{'497'}:<br />
				<select name="cookielength" style="width: 117px;" tabindex="3">
				<option value="2"$clsel2>$loginout_txt{'497d'}</option>
				<option value="1"$clsel1>$loginout_txt{'497c'}</option>
				<option value="60"$clsel60>1 $loginout_txt{'497a'}</option>
				<option value="180"$clsel180>3 $loginout_txt{'497b'}</option>
				<option value="360"$clsel360>6 $loginout_txt{'497b'}</option>
				<option value="720"$clsel720>12 $loginout_txt{'497b'}</option>
				<option value="1440"$clsel1440>24 $loginout_txt{'497b'}</option>
				</select>
			</span>
		</div>
		<div style="clear: both; margin-top: 5px; margin-left: auto; margin-right: auto; width: 370px;">
			<span style="float: left; width: 49%; margin-bottom: 5px;">
				<input type="submit" value="$loginout_txt{'34'}" tabindex="5" accesskey="l" style="float: left; width: 175px;" class="button" />
			</span>
			<span style="float: left; width: 49%; margin-bottom: 5px;">
				<input type="button" value="$loginout_txt{'315'}" style="float: right; width: 175px;" onclick="location.href='$scripturl?action=reminder'" class="button" />
			</span>
        	<br /><br />
		</div>
        </form>
       </td>
      </tr>
	</table>
	$border_bottom
~;

	$sharedLogin_title = '';
	$sharedLogin_text = '';
	return $sharedlog;
}

sub Reminder {
	$yymain .= qq~<br /><br />
<form action="$scripturl?action=reminder2" method="post">
<table border="0" width="400" cellspacing="1" cellpadding="3" align="center" class="bordercolor">
	<tr>
	<td class="titlebg">
	<span class="text1"><b>$mbname $loginout_txt{'36'} $loginout_txt{'194'}</b></span>
	</td>
	</tr><tr>
	<td class="windowbg">
	<span class="text1"><b> $loginout_txt{'35'} $maintxt{'377'} $loginout_txt{'33'}: </b></span>
	<input type="text" name="user"$regstyle />
	</td>
	</tr>
~;

	if ($regcheck) {
		&validation_code;
		$yymain .= qq~
	<tr>
	<td class="windowbg">
	<span class="text1"><b>$floodtxt{'1'}: </b></span>
	$showcheck
	<br /><span class="small">$floodtxt{'casewarning'}</span>
	</td>
	</tr><tr>
	<td class="windowbg">
	<span class="text1"><b>$floodtxt{'3'}: </b></span>
	<span class="text1"><input type="text" maxlength="30" name="verification" id="verification" size="20" /></span>
	</td>
	</tr>
~;
	}
	$yymain .= qq~
	<tr>
	<td align="center" class="windowbg">
	<input type="submit" value="$loginout_txt{'339'}" class="button" />
	</td>
	</tr>
</table>
</form>
<br /><br />
~;
	$yytitle = "$loginout_txt{'669'}";
	&template;
	exit;
}

sub Reminder2 {
	# generate random ID for password reset.
	my $randid = &keygen(8,"A");

	if ($regcheck) {
		&validation_check($FORM{'verification'});
	}

	my $user = $FORM{'user'};
	$user =~ s/\s/_/g;

	if (!-e "$memberdir/$user.vars"){
		$test_id = &MemberIndex("who_is", $user);
		if($test_id) {$user = $test_id;}
		else {&fatal_error("bad_credentials");}
	}
#	&ManageMemberinfo("load");
#	while (($curuser, $value) = each(%memberinf)) {
#		($curname, $curmail, undef, undef) = split(/\|/, $value);
#		if ($user eq $curuser) {
#			$userfound = 1;
#			$sentto = $curuser;
#			last;
#		} elsif ($user eq $curmail) {
#			$user      = $curuser;
#			$userfound = 1;
#			$sentto = $curmail;
#			last;
#		}
#	}
#	&fatal_error("bad_credentials") if (!$userfound);

	# Fix to make it load in their own language
	&LoadUser($user);
	$username = $user;
	&WhatLanguage;
	&LoadLanguage('LogInOut');
	&LoadLanguage('Email');
	undef $username;

	$userfound = 0;

	if (-e "$memberdir/forgotten.passes") {
		require "$memberdir/forgotten.passes";
	}
	if (exists $pass{$user}) { delete $pass{$user}; }
	$pass{"$user"} = $randid;

	fopen(FILE, ">$memberdir/forgotten.passes") || &fatal_error("cannot_open","$memberdir/forgotten.passes", 1);
	while (($key, $value) = each(%pass)) {
		print FILE qq~\$pass{"$key"} = '$value';\n~;
	}
	print FILE "1;";
	fclose(FILE);

	$subject = "$loginout_txt{'36'} $mbname: ${$uid.$user}{'realname'}";
	if($do_scramble_id){$cryptusername = &cloak($user);} else {$cryptusername = $user; }
	require "$sourcedir/Mailer.pl";
	&LoadLanguage('Email');
	my $message = &template_email($passwordreminderemail, {'displayname' => ${$uid.$user}{'realname'}, 'cryptusername' => $cryptusername, 'remindercode' => $randid});
	&sendmail(${$uid.$user}{'email'}, $subject, $message);

	$yymain .= qq~<br /><br />
<table border="0" width="400" cellspacing="1" cellpadding="3" align="center" class="bordercolor">
	<tr>
	<td class="titlebg">
	<span class="text1"><b>$mbname $loginout_txt{'36'} $loginout_txt{'194'}</b></span>
	</td>
	</tr><tr>
 	<td class="windowbg" align="center">
	<b>$loginout_txt{'192'} $FORM{'user'}</b></td>
      </tr>
</table>
<br /><center><a href="javascript:history.back(-2)">$loginout_txt{'193'}</a></center><br />
~;
	$yytitle = "$loginout_txt{'669'}";
	&template;
	exit;
}

sub Reminder3 {
	$id   = $INFO{'ID'};
	if($do_scramble_id){$user = &decloak($INFO{'user'});} else { $user = $INFO{'user'};}

	if ($id !~ /[a-zA-Z0-9]+/) { &fatal_error("invalid_character","ID $loginout_txt{'241'}"); }
	if ($user !~ /\A[0-9A-Za-z#%+-\.@^_]+\Z/) { &fatal_error("invalid_character","User $loginout_txt{'241'}"); }

	# generate a new random password as the old one is one-way encrypted.
	@chararray = qw(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
	my $newpassword;
	for (my $i; $i < 8; $i++) {
		$newpassword .= $chararray[int(rand(61))];
	}

	# load old userdata
	&LoadUser($user);

	# update forgotten passwords database
	require "$memberdir/forgotten.passes";
	if ($pass{$user} ne $id) { &fatal_error("wrong_id"); }
	delete $pass{$user};
	fopen(FORGOTTEN, ">$memberdir/forgotten.passes") || &fatal_error("cannot_open","$memberdir/forgotten.passes", 1);
	while (($key, $value) = each(%pass)) {
		print FORGOTTEN qq~\$pass{"$key"} = '$value';\n~;
	}
	print FORGOTTEN "\n1;";
	fclose(FORGOTTEN);

	# add newly generated password to user data
	${$uid.$user}{'password'} = &encode_password($newpassword);
	&UserAccount($user, "update");

	$sharedLogin_title = qq~$mbname $loginout_txt{'36'} $loginout_txt{'194'}~;
	$sharedLogin_text = qq~$loginout_txt{'835'}~;
	$sharedLogin_text .= qq~ <input type="text" name="newpass" value="$newpassword" readonly="readonly" style="font-weight: bold;" />~;

	&sharedLogin;
	$yymain .= qq~
		<div class="bordercolor" style="width: 650px; margin-bottom: 8px; margin-left: auto; margin-right: auto;">
		$sharedlog
		</div>
	~;

	$yytitle = "$loginout_txt{'836'}";
	&template;
	exit;
}

1;
