Location: PHPKode > projects > Processed Book Open Source > pbos-1.01/signin.php
<?php
/**
 * Support sign-in, sign-up, and password changes.
 *
 * Copyright (C) 2005 Wayne Davison <hide@address.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

require 'lib/main.inc';

switch ($_GET['do']) {
case 'signin':
case 'signup':
case 'newpass':
    user_page($_GET['do']);
    break;
case 'welcome':
case 'passchange':
    welcome_page($_GET['do']);
    break;
default:
    user_page('signin');
    break;
}

function user_page($signup_type)
{
    add_sidebar_divider();
    add_sidebar_image('btn-library', '.');

    start_content($signup_type, 'wide');
    $need_prompt = 1;
    $scr_desc = '&nbsp;';

    $sub = $_POST['sub'];
    if ($sub != '') {
	$scrname = preg_replace('/\s+/', '_', trim($_POST['scrname']));
	$email = trim($_POST['pbemail']);
	$pass1 = $_POST['pass1'];
	$pass2 = $_POST['pass2'];

	open_db();

	if ($signup_type == 'signin') {
	    if ($scrname != '') {
		$qscrname = mysql_real_escape_string($scrname);
		$do = "SELECT UserID, Password FROM Users WHERE Name = '$qscrname' LIMIT 1";
		if (preg_match('/^[-\w.]+@[-\w.]+$/', $scrname))
		    $do = preg_replace('/ Name /', ' Email ', $do, 1);
		$result = mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
		$obj = mysql_fetch_object($result);
		if ($obj && crypt($pass1, $obj->Password) == $obj->Password) {
		    set_auth_cookie("{$obj->UserID}*{$obj->Password}");
		    redir_main();
		    $need_prompt = 0;
		} else {
		    $err_msg = 'Sign-in information is incorrect';
		}
	    }
	} else {
	    if ($signup_type != 'newpass'
	     && !preg_match('#^\w[\w.]{2,}$#i', $scrname))
		$err_msg = 'Your screen name is invalid';
	    elseif (preg_match('/^everyone$/i', $scrname))
		$err_msg = 'You may not use the screen name "Everyone"';
	    elseif ($signup_type != 'newpass'
	     && !preg_match('/^[-\w.]+@[-\w.]+$/', $email))
		$err_msg = 'Your email address is invalid';
	    elseif (strlen($pass1) < 5)
		$err_msg = 'Your password is too short';
	    elseif ($pass1 != $pass2)
		$err_msg = 'The passwords do not match';
	    if ($err_msg == '') {
		$salt = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
		$cpass = crypt($pass1, substr($salt, rand(0,63), 1) . substr($salt, rand(0,63), 1));
		if ($signup_type == 'newpass') {
		    // Change the password of an existing user.
		    $do = "SELECT UserID, Email FROM Users WHERE Name = '$scrname' LIMIT 1";
		    if (preg_match('/^[-\w.]+@[-\w.]+$/', $scrname))
			$do = preg_replace('/ Name /', ' Email ', $do, 1);
		    $result = mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
		    $obj = mysql_fetch_object($result);
		    if ($obj) {
			$do = "UPDATE Users SET NewPass = '$cpass' WHERE UserID = {$obj->UserID}";
			mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
			send_email($obj->UserID, $obj->Email, $cpass, 'passchange');
			$need_prompt = 0;
		    } else {
			$err_msg = 'We could not find your account';
		    }
		} else { // TODO We should do this in a transaction.
		    // Create a new user.
		    $do = "INSERT INTO Users SET Name = '$scrname', Email = '$email',
			Password = '**INVALID', NewPass = '$cpass'";
		    if (mysql_query($do)) {
			$do = "SELECT UserID, NewPass FROM Users WHERE Name = '$scrname' LIMIT 1";
			$result = mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
			$obj = mysql_fetch_object($result);
			if (!$obj || $obj->NewPass != $cpass) {
			    echo '** Internal error! **<p>Possible duplicate user!';
			} else {
			    $uID = $obj->UserID;
			    $book_groups = array();
			    $do = "SELECT GroupID FROM Books";
			    $result = mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
			    while (($row = mysql_fetch_row($result)) !== FALSE)
				$book_groups[] = $row[0];
			    add_new_group($uID, $uID, '', $scrname, 'Private', 0);
			    add_new_group($uID, 0, '', $scrname, 'Public', 0);
			    foreach ($book_groups as $gID)
				add_enabled_group($uID, $gID);
			    send_email($uID, $email, $cpass, 'welcome');
			    $need_prompt = 0;
			}
		    } else {
			if (!preg_match('/Duplicate entry \'(.*)\' for key (\d+)/', mysql_error(), $out))
			    die('INSERT failed: ' . mysql_error() . " (cmd: $do)");
			if ($out[1] == $scrname)
			    $err_msg = 'That screen name is already taken';
			else
			    $err_msg = 'You may only sign-up for a single screen name';
		    }
		}
	    }
	}

	close_db();
    }

    if ($need_prompt) {
	$pass_prompt = 'Password';
	if ($signup_type == 'signin') {
	    $info_text = <<<EOT
Returning users should supply their email address and the associated password
to sign-in.  You will get a browser-cookie that will allow you to begin making
Annotations.
EOT;
	    $pass_desc = '&nbsp;';
	    $lower_form = <<<EOT
<td>&nbsp;</td><td><input type=submit name=sub value="Sign-In"></td><td>&nbsp;</td>
EOT;
	} else {
	    if ($signup_type == 'signup') {
		$button_text = 'Create Account';
		$info_text = <<<EOT
<p>Please provide your email address below, which is also your login name, along
with the password you'd like.&nbsp; Confirmation
email will be set to that email address, with the information you will
need to login for the first time.
<p><font size=2>After filling in the form and clicking "Create Account" below, you
should wait for the email to arrive, and then follow the directions in it to
complete your registration.
EOT;
		$email_prompt = <<<EOT
<td align=right width="20%">Email:</td>
<td width="5%"><input type=text name=pbemail value="$email"></td><td>&nbsp;</td>
</tr><tr>
EOT;
		$scr_desc = '<small>(At least 3 characters; Only period and underscore for punctuaton.)</small>';
	    } else {
		if ($scrname == '') {
		    open_db();
		    list($uID, $scrname) = get_auth_cookie();
		    close_db();
		    if (!$uID)
			$scrname = '';
		}
		$pass_prompt = 'New Password';
		$button_text = 'Change Password';
		$scr_desc = "<small>(Use your email address if you don't remember your screen name.)</small>";
		$info_text = <<<EOT
Use this page to request a new password for an existing account.  An email will
be sent to the indicated email address with the details on what to do to
finalize the change.  <b>The password-change will not take effect until you
(as the assumed recipient at the indicated email address) approve this action.</b>
EOT;
	    }
	    $pass_desc = '<small>(At least 5 characters.)</small>';
	    $lower_form = <<<EOT
<td align=right>Confirm Password:</td>
<td><input type=password name=pass2 value="$pass2"></td><td>&nbsp;</td>
</tr><tr>
$ab<td>&nbsp;</td><td colspan=2><input type=submit name=sub value="$button_text"></td>
EOT;
	}

	if ($err_msg != '')
	    $info_text = "<b style='color:red'>$err_msg.</b>";

	echo <<<EOT
<form name=signform method=post>
<table><tr><td>
<h2 style='border:0'>$title</h2>
<p>$info_text
</td><td>&nbsp;</td></tr></table>

<p><table><tr>
<td align=right width="20%">Screen Name:</td>
<td width="5%"><input type=text name=scrname value="$scrname"></td><td>$scr_desc</td>
</tr><tr>
$email_prompt<td align=right>$pass_prompt:</td>
<td><input type=password name=pass1 value="$pass1"></td><td>$pass_desc</td>
</tr><tr>
$lower_form</tr></table>
</form>
<script>
document.signform.scrname.focus();
</script>
EOT;
	if ($signup_type != 'signin') {
	    echo <<<EOT
<p>If you already have an account, please <a href="signin.php">sign in</a>.
EOT;
	}
	if ($signup_type != 'signup') {
	    echo <<<EOT
<p>If you don't yet have an account, please <a href="signin.php?do=signup">sign up
for one</a>.
EOT;
	}
	if ($signup_type == 'signin') {
	    echo <<<EOT
<p>If you can't remember your password, you can <a href="signin.php?do=newpass">request
a password change</a>.
EOT;
	}
    }

    end_content();
}

function welcome_page($page_type)
{
    $uID = $_GET['u'];
    $cpass = $_GET['x'];
    if (!preg_match(':^\d+;[a-zA-Z0-9./]+$:', join(';', array($uID, $cpass)))) {
	redir_main();
	return;
    }

    open_db();

    $type = $page_type == 'welcome' ? 'sign-up' : 'password-change';

    $do = "SELECT Email, Name, NewPass FROM Users WHERE UserID = $uID LIMIT 1";
    $result = mysql_query($do) or die('SELECT failed: ' . mysql_error() . " (cmd: $do)");
    $obj = mysql_fetch_object($result);
    if (!$obj || $obj->NewPass != $cpass) {
	if ($obj) {
	    $msg = <<<EOT
Your account does not have a pending $type request.
<p>You may wish to do one of the following: <ul>
<li><a href="signin.php?do=newpass">Request a new password</a>.
<li><a href=".">Go to the library</A>.
</ul>

<p>Check the sidebar to see if you're signed in or not.
EOT;
	} else
	    $msg = 'Invalid request';

	list($uID, $scrname) = get_auth_cookie();
    } else {
	$scrname = $obj->Name;
	$do = "UPDATE Users SET Password = '$cpass', NewPass = NULL WHERE UserID = $uID";
	mysql_query($do) or die('UPDATE failed: ' . mysql_error() . " (cmd: $do)");
	set_auth_cookie("$uID*$cpass");
	$msg = <<<EOT
<h2>Welcome!</h2>
<p>You've completed your $type.  To get started, visit
<a href=".">the library</a>.
EOT;
    }

    add_sidebar_divider();
    add_sidebar_image('btn-library', '.');
    if ($uID)
	add_sidebar_image('btn-bookmarks', 'bkmk.php');
    sidebar_signin($uID, $scrname);

    start_content('Welcome', 'wide');

    echo $msg;

    close_db();
    end_content();
}

function send_email($uID, $email, $cpass, $page_type)
{
    global $CGI;

    $url = "$CGI?do=$page_type&x=$cpass&u=$uID";
    $op = $page_type == 'welcome' ? 'Sign-Up' : 'Password Change';
    $op2 = strtolower($op);

    echo <<<EOT
<H2 style='border:0'>Email Sent</h2>

<p>An email is being sent to the email address you provided.
It contains instructions on how to complete your $op2.
EOT;

    $subject = "Completing your ProcessedBook $op";
    $headers = 'From: hide@address.com' . "\r\n"
	     . 'X-Mailer: PHP/' . phpversion();

    $message = <<<EOT
To complete the $op2 that you initiated on our web site, please
visit this link:

    $url

If you did not request this $op2, you may disregard this message.
EOT;

    mail($email, $subject, $message, $headers);
}

?>
Return current item: Processed Book Open Source