<?php if (! defined ('PmWiki')) exit;

# Copyright
# =========
# 
# Copyright (c) 2006 Benjamin C. Wilson. This software is released under GPL
# under the same terms as PmWiki.
#
# Description
# ===========
#
# AuthUserDBase is a database tie-in for PmWiki's AuthUser.
#
# Usage
# =====
#
# To use this for user authentication, the following steps must be taken.
# 
#    1. Include this file via the site configuration
#    include_once("/path/to/cookbook/authuser_mysql.php-1.0.02.php");
#
#    2. Edit Site.AuthUser and add the following on its own line:
#       " mysql: required for AuthUserDatabase"
#
#    3. Set the following values:
#       a. $AUDBaseEncryption (defaults to md5).
#       b. $AUDBaseDBase (array)
#           i.   $AUDBaseDBase['host'] (defaults to 'localhost')
#           ii.  $AUDBaseDBase['db'] (no default)
#           iii. $AUDBaseDBase['host'] (no default)
#           iv.  $AUDBaseDBase['user'] (username to access database)
#           v.   $AUDBaseDBase['password'] (password to access database)
#       c. $AUDBaseTable (array)
#           i.   $AUDBaseTable['table'] (authentication database table)
#           ii.  $AUDBaseTable['userfield'] (user field in the authentication
#                 table)
#           iii. $AUDBaseTable['pwfield'] (password field in the
#                authentication table)
#
#    4. Have users in the authentication table.
/*
     5. Edit scripts/authuser.php - 
        replace the line
        #    'mysql' => 'AuthUserMySQL',
        with
        'mysql' => 'AuthUserDatabase',
*/ 
#
# Original authuser_dbase.php Release History
# ===============
#
# v.0.1 July, 2005 - Private release
# v.0.2 May 31, 3006 - Semi-public release.
# v.1.0 ---- -, 2006 - Initial public release. 
#   * I am trying to implement multiple-table support
#   * Cleaning up for easier use on various sites. 
# v.1.0.01 July 25, 2006 by akc - fixed 3 typos
# v.1.0.02 Aug 03, 2006 by akc - working at last

/**************************

Edits by Crisses (XES)

Purpose: create a stand-alone PmWiki->MySQL authentication system.  postgresql support may be added back in.

********************
Installation
********************

Add table to a database.  Suggested MySQL, used in this example:

CREATE TABLE `pmwiki_users` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(30) NOT NULL default '',
  `password` varchar(60) default NULL,
  `validatecode` varchar(60) default NULL,
  `signupdate` date default NULL,
  `email` varchar(60) default NULL,
  `validatefield` tinyint(1) default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=24 DEFAULT CHARSET=utf8


Add to config.php:

// Set up database settings before calling scripts
$AUDBaseDBase = array(
	  'host'      => 'localhost',
	  'db'        => 'pmwiki',
	  'user'      => 'pmwiki_dbase_user',
	  'password'  => 'myPmWikiP@ssW0rd'
);

// Must be before the xes_authuser_dbase.php call
$AUDBaseTable = array(
	  'user_table' => 'pmwiki_users',
	  'user_field' => 'username',
	  'email' => 'email',
	  'pw_field'   => 'password',
	  'validate_code' => 'validatecode',
	  'validate_field' => 'validatefield',
	  'date_joined' => 'signupdate',
);

// Must come before authuser.php call
include_once ('cookbook/xes_authuser_dbase.php');

// Must come before authuser.php call
$AuthUserFunctions = array('mysql' => 'AuthUserDatabase');

// Must come after the other items!
include_once('scripts/authuser.php');


Edit Site.AuthUser and add the following line:

mysql: required for AuthUserDatabase


See "Usage" (below) for registration forms.

********************
Usage
********************
create sign-up page in Wiki.  You can split the forms out to multiple pages if desired:

(:messages:)

(:title Account Management Page:)

(:if !authid:)
!!!User Login
(:input form {$PageUrl}:)
(:input hidden action login:)
||     Name:||(:input text authid:)    ||
|| Password:||(:input password authpw:) ||
|| ||(:input submit value="OK" class="inputbutton":) ||
(:input end:)

-----
(:div style='text-align:justify; float:left; valign:top; width:48%; padding-right:2%;padding-bottom:5px;':)
!!!New User Registration
(:input form method=post action={$PageUrl} :)
(:input hidden name=xes_AuthUser value=addnew:)
(:input hidden name=xes_returnUrl value={$PageUrl} :)

|| Username:||(:input text xes_username size=20:) ||
|| Password:||(:input password xes_password size=20:) ||
|| Repeat Password:||(:input password xes_dupepassword:) ||
|| Email:||(:input text name=xes_email value="email" size=20:) ||
|| ||(:input submit name=post value="New" accesskey=g:) ||
(:input end:)
(:divend:)
(:div style='text-align:justify; valign:top; float:left; width:48%; padding-right:2%;padding-bottom:5px;':)
!!! Change Password Request
An email with a new validation code will be sent to you.

(:input form method=post action={$PageUrl} :)
(:input hidden name=xes_AuthUser value=reregister:)
(:input hidden name=xes_returnUrl value={$PageUrl} :)

|| Username:||(:input text name=xes_username size=20:) ||
|| Email:||(:input text name=xes_email size=20:) ||
|| New Password:||(:input password xes_newpassword:)||
|| Repeat Password:||(:input password xes_dupepassword:)||
|| ||(:input submit name=post value="Change" accesskey=g:) ||

(:input end:)

(:divend:)
[[<<]]
----

(:ifend:)

(:if authid:)
You are authenticated as '''{$Author}'''.  [[{$FullName}?action=logout | Logout]]

!!!Update User Information
Change your email address and/or password.
(:input form method=post action={$PageUrl} :)
(:input hidden name=xes_AuthUser value=update:)
(:input hidden name=xes_returnUrl value={$PageUrl} :)

|| Username:||(:input text name=xes_username size=20:) ||
|| Current Password:||(:input text name=xes_oldpassword size=20:) ||
|| New Password:||(:input text name=xes_newpassword size=20:) (optional) ||
|| Repeat New Password:||(:input password xes_dupepassword:) ||
|| New Email:||(:input text name=xes_newemail size=20:) (optional) ||
|| ||(:input submit name=post value="Go" accesskey=g:) ||
(:input end:)

(:ifend:)



Hints & Tips
 - Put the config.php information AFTER setting $WikiTitle so the emails are automatically configured to say your wiki name


********************
Release History
********************
0.1.2 2006-10-5 Security Fix
0.1 2006-09-20 Initial xes_authuser_dbase.php beta release
	- tested only with Triad form
	- postgresql support definitely broken
	- some mysql hacks need cleaning up!!
	- it miraculously works in any case
	- probably needs to be double-checked on security
	- nearly everything loops back to the original page, so everything on one page works best
	
ToDo:
	- Internationalization broken for email body -- needs fixing
	- Consider adding username to the validation link & query -- valcodes COULD be duped	
	- Warn if using PGSQL that it's broken?
	- Eventually add in email notice regarding new user registration to admin option
	- Allow password length, username length, etc. validation
	- cleaner SQL and database transactioning?

**************************/

SDV($AUDBaseEncryption, 'md5');
SDV($AUDBaseDBase, array(
	  'host'      => 'localhost',
	  'db'        => 'pmwiki',
	  'user'      => 'pmwiki_user',
	  'password'  => 'sample',
  )
);
SDV($AUDBaseConditional, '');
SDV($AUDBaseEngine, 'mysql');

// Criss altered table
SDV($AUDBaseTable, array(
	  'user_table' => 'pmwiki_users',
	  'user_field' => 'username',
	  'email' => 'email',
	  'pw_field'   => 'password',
	  'validate_code' => 'validatecode',
	  'validate_field' => 'validatefield',
	  'date_joined' => 'signupdate'	)
);

SDV($xAUDBaseValidationCodeLength, 15);

SDV($xAUDBaseMsgs, array(
		"invalid_register_link" => "$[There has been an error in processing your change request.  Please check the link in your email or contact the site administrator for assistance.]",
		
		"form_error" => "$[There has been an error in form processing.  Please alert the admin.]",
		
		"user_not_found" => "<p style='font-weight:strong'>$[No user with that name and password found.  Please register or try again].</a></p>",
		
		"email_taken" => "<p style='font-weight:strong'>$[That email is already in our database.  If you've forgotten your password, please use the Change Password Request form].</a></p>",
		
		"addnew_loggedin" => "<p style='font-weight:strong'>$[You are already logged in as a valid user.  Please use your current account or log out to create a new account.].</a></p>",
		
		"username_taken" => "<p style='font-weight:strong'>$[That username is already taken.  Please enter another username.]</p>",
		
		"email_invalid" => "<p style='font-weight:strong'>$[Email address appears invalid.  Please check the email address or notify the administrator.]</p>",
		
		"update_invalid" => "<p style='font-weight:strong'>$[Username and current password are required.  You must also include either a new email address or new password.]</p>",
		
		"password_invalid" => "<p style='font-weight:strong'>$[The old password you entered does not match the password we have on file.  Please try again.]</p>",
		
		"user_not_validated" => "<p style='font-weight:strong'>$[I'm sorry, your account isn't validated.  Please change details in your account after you've validated your account.  Please check your email.]</p>",
		
		"validation_error" => "<p style='font-weight:strong'>$[There was a problem validating your account.  Please contact the site administrator.]</p>",
		
		"email_sent" => "$[An email has been sent to you.  Please find the email and click on the validation link.]",
		
		"password_mismatch" => "$[Your password and it's duplicate don't match.  Please-reenter your new password twice.]",
		
		"updates_done" => "$[Your information has been updated.  Thank you.]",

		"email_subject" => "$WikiTitle sign-up validation link",
		
		"email_msg" => "\nThank you for signing up to $WikiTitle.\n\nPlease click on the following link to complete your registration:\n",
		
		"validation_done" => "<p style='font-weight:strong'>$[Thank you for validating.]</p>" )
);

/********************/
// Criss add-ins
/*******************/

//Program Logic


// debug statement
//xes_sms ($_REQUEST) ;

// Debug function
function xes_sms($text,$switch=0){
	global $MessagesFmt;
	if ($switch == true || is_array($text)) {
		$MessagesFmt[] = "<pre>" . print_r($text, true) . "</pre>\n";
	} else {
		$MessagesFmt[] = $text . "<br />\n";
	}
}


// logic only runs for xes_AuthUser actions
if (isset($_REQUEST['xes_AuthUser'])) {

	foreach($_POST as $key=>$value) xAUDBaseslashmysql($_POST[$key]);

	// validate & fix visitor-entered post variables:
	if (($_POST['xes_AuthUser'] == "addnew") && (xAUDBaseFixPosts() === false)) {return false;
	
	} else {
		xAUDBaseFixPosts(0);
	} 
	
		
	switch ($_REQUEST['xes_AuthUser']) {
		case "addnew":
			if ($_POST['xes_AuthUser'] == "addnew") xes_AuthUserProcessAddnew();
		break;
		case "update":
			if ($_POST['xes_AuthUser'] == "update") xes_AuthUserProcessUpdate();
		break;
		case "validate":
			if ($_GET['xes_AuthUser'] == "validate") xes_AuthUserProcessValidate();
		break;
		case "reregister":
			if ($_POST['xes_AuthUser'] == "reregister") {
				xes_AuthUserProcessReRegister();
			} else {
				xes_AuthUserCompleteReRegister();
			}
		break;
		default:
			xes_AuthUserFormExit('form_error');
			return false;

		break;
	}
}


function xes_AuthUserCompleteReRegister(){
    global $AUDBaseTable, $AUDBaseEngine, $AUDBaseEncryption;

	// validate "xcode" as 32 hexidecimal characters in length
	$password_valid = preg_match('/^[A-Fa-f0-9]{32}$/', $_GET['xcode']);
	if (!$password_valid) {		
		xes_AuthUserFormExit('invalid_reregister_link');
		return false;
	} 

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $e = $AUDBaseTable['email'];
    $v = $AUDBaseTable['validate_code'];
	$vf = $AUDBaseTable['validate_field'];
    
    
	// check username & validation code.  
	$ask = "SELECT count(*) as `EXISTS` FROM $t WHERE $u='$_GET[username]' AND $v='$_GET[valcode]'";
	$answer = xes_AuthUserQuery($ask);

	
	if ($answer === true) {
		//If valid, then update table with password.
		$ask = "UPDATE $t SET $v=NULL, $vf='1', $p='$_GET[xcode]' WHERE $u='$_GET[username]'";
		$answer = xes_AuthUserQuery($ask, 2);
		
		if ($answer >= 1) {
			xes_AuthUserFormExit('validation_done');
		} else {
			xes_AuthUserFormExit('validation_error');
		}

	}
}

// case-sensitive string comparison -> compare passwords given?
function xAUDBaseComparePasswords($first, $second) {
	// This function compares two passwords to make sure they're the same, and if not, returns false
	$result = strcmp($first, $second) ;
	if ($result != 0) return false;
	return true;
}

function xes_AuthUserProcessReRegister () {
    global $AUDBaseTable, $AUDBaseEngine, $AUDBaseEncryption;
    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $e = $AUDBaseTable['email'];
    $d = $AUDBaseTable['date_joined'];
    $v = $AUDBaseTable['validate_code'];

	// validate all user-entered data

	// entered passwords must match
	if ($_POST['xes_newpassword'] != '') {
		$p_answer = xAUDBaseComparePasswords($_POST['xes_newpassword'], $_POST['xes_dupepassword']);
		if (!$p_answer) {
			xes_AuthUserFormExit('password_mismatch');
			return false;
		} 
	} 

	// validate user - username & email must match account
	$u_ask = "SELECT count(*) as `EXISTS` from $t where $u='$_POST[xes_username]' AND $e='$_POST[xes_email]'";
	$u_answer = xes_AuthUserQuery($u_ask);
	
	if (!$u_answer) {
		xes_AuthUserFormExit('user_not_found');
		return false;
	} 
	
	// generate new validation code
	$vcode = xes_AuthUserValidateCode();

	// update database with validation code
	$v_ask = "UPDATE $t SET $v='$vcode' WHERE $u='$_POST[xes_username]'";
	$v_answer = xes_AuthUserQuery($v_ask, 2);

	// Send email
	if ($v_answer === 1) {
		xes_AuthUserEmailCode ($_POST['xes_username'], $email, $vcode, 1) ;
		xes_AuthUserFormExit('email_sent');
	}
}

function xes_AuthUserProcessUpdate () {

    global $AUDBaseTable, $AUDBaseEngine;
    
    // Form validation
    
    // Check that there's info to process
    if (($_POST['xes_username'] == '') || ($_POST['xes_oldpassword'] == '') || ( ($_POST['xes_newpassword'] == '') && ($_POST['xes_newemail'] == '') ) ) {
    	xes_AuthUserFormExit('update_invalid');
    	return false;
    }
    
    	// entered passwords must match
	if ($_POST['xes_newpassword'] != '') {
		$p_answer = xAUDBaseComparePasswords($_POST['xes_newpassword'], $_POST['xes_dupepassword']);
		if (!$p_answer) {
			xes_AuthUserFormExit('password_mismatch');
			return false;
		} 
	}

	// Make sure user IS validated if updating record.	
	if (!xes_AuthUserIsValidated($_POST['xes_username'])) {
		xes_AuthUserFormExit('user_not_validated');
		return false;
	} 

	// If we're going to be updating the email address, make sure it's valid
	if ($_POST['xes_newemail'] != '') {
		if (!xAUDBaseValidateEmail($_POST['xes_newemail'])) {
			xes_AuthUserFormExit('email_invalid');
			return false;
		}
	}
	
	// Check user's password etc. using false as placeholders for unused values
	if (!AuthUserDatabase(false, $_POST['xes_username'], $_POST['xes_oldpassword'], false)) {
		xes_AuthUserFormExit('password_invalid');
		return false;		
	}

	if (($_POST['xes_newpassword'] != '') && (!(xAUDBaseComparePasswords($_POST['xes_newpassword'], $_POST['xes_dupepassword'])))) {
		xes_AuthUserFormExit('password_mismatch');
		return false;
	} 

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $e = $AUDBaseTable['email'];
    $d = $AUDBaseTable['date_joined'];
    
    // That should be enough validation -- time to update the records -- devise the update query
	$ask = "UPDATE $t SET ";
	if ($_POST['xes_newpassword'] != "") {
		// encrypt password using the format set by user or default
		global $AUDBaseEncryption;
		$crypt = $AUDBaseEncryption($_POST['xes_newpassword']);
		$ask .= "$p = '$crypt' " ;
	}
	if (($_POST['xes_newemail'] != "") && ($_POST['xes_newpassword'] != "") ) {$ask .= ", ";}
	
	if ($_POST['xes_newemail'] != "") { $ask .= "$e = '$_POST[xes_newemail]' " ;}
	
	$ask .= "WHERE $u='$_POST[xes_username]'";
	
	$answer = xes_AuthUserQuery($ask, 2);
	
	// userfeedback
	if ($answer = 1) {
		xes_AuthUserFormExit('updates_done');
		return true;
	} else {
		xes_AuthUserFormExit('form_error');
		return false;
	}
}


// This function adds a new user to the database
function xes_AuthUserProcessAddNew () {
    global $AUDBaseTable, $AUDBaseEngine, $AUDBaseEncryption;

	// Check this --> need to make sure user IS not(!) validated if adding a record.	
	if (xes_AuthUserIsValidated($_POST['xes_username'])) {xes_AuthUserFormExit('addnew_loggedin'); return false;} 
	
	// entered passwords must match
	if ($_POST['xes_password'] != '') {
		$p_answer = xAUDBaseComparePasswords($_POST['xes_password'], $_POST['xes_dupepassword']);
		if (!$p_answer) {
			xes_AuthUserFormExit('password_mismatch');
			return false;
		} 
	} else { xes_AuthUserFormExit('password_mismatch');
			return false;
	}

	// Validate Email Address
	if (!xAUDBaseValidateEmail($_POST['xes_email'])) { xes_AuthUserFormExit('email_invalid'); return false;}
	
	

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $e = $AUDBaseTable['email'];
    $d = $AUDBaseTable['date_joined'];
    $v = $AUDBaseTable['validate_code'];

	// check whether requested email address exists
	$ask = "SELECT count(*) AS `EXISTS` FROM $t WHERE $e='$_POST[xes_email]'";
	$eanswer = xes_AuthUserQuery ($ask);
	// if email exists, send error to browser
	if ($eanswer > 0) { xes_AuthUserFormExit ('email_taken'); }

	// check whether requested username exists
	$ask = "SELECT count(*) AS `EXISTS` FROM $t WHERE $u='$_POST[xes_username]'";
	$uanswer = xes_AuthUserQuery ($ask);
	// if username exists, send error to browser, ask for new username
	if ($uanswer > 0) { xes_AuthUserFormExit ('username_taken'); }

	// if neither username or email exist, add user		
	if ((!$uanswer) && (!$eanswer)) {
		global $xAUDBaseValidationCodeLength;

		// generate a random validation code
		$vcode = xes_AuthUserValidateCode($xAUDBaseValidationCodeLength);
		
		// encrypt password using the encryption format
		$crypt = $AUDBaseEncryption($_POST['xes_password']);
		// Add new user to database with validation code
		$ask = "INSERT INTO $t ($u, $e, $p, $v, $d) VALUES ('$_POST[xes_username]', '$_POST[xes_email]', '$crypt', '$vcode', NOW() )";
		
		// run query, grab number of rows affected
		$answer = xes_AuthUserQuery($ask, 2);
		// Send out email with validation code
		
		// can check $answer, send email, and send message to browser
		if ($answer == 1) {
			xes_AuthUserEmailCode($_POST['xes_username'], $_POST['xes_email'], $vcode);
			xes_AuthUserFormExit('email_sent');
		};
	}
}

// This function sends out emails, whether for first validation or re-validation
function xes_AuthUserEmailCode ($username, $email, $vcode, $revalidate=0) {
	global $xAUDBaseMsgs, $ScriptUrl, $pagename, $AUDBaseEncryption;

	// create validation URL

	if ($revalidate == 0) {
		$url = $ScriptUrl . "?n=$pagename&xes_username=$username&xes_AuthUser=validate&valcode=$vcode";
	} else {
		$crypt = $AUDBaseEncryption($_POST['xes_newpassword']);
		$uencuser = urlencode($username);
		$url = $ScriptUrl . "?n=$pagename&xes_AuthUser=reregister&username=$uencuser&valcode=$vcode&xcode=$crypt";
	}
	
	$body = $username . ": \n\n$xAUDBaseMsgs[email_msg]\n" . $url;
	//may want to add a from line later
	$from = "";

	return (mail($email, $xAUDBaseMsgs['email_subject'], $body ));
}


// Protecting servers from SQL injections -- or at least trying
// addslashes is not good enough -- strip the slashes and use the database's own method of escaping.
function xAUDBaseFixPosts() {
	global $AUDBaseEngine;
	$slash = "xAUDBaseslash$AUDBaseEngine";
	if (get_magic_quotes_gpc()) {
		foreach ($_POST as $key=>$value) {
			$_POST[$key]= trim(stripslashes($value));
		}
	}
	$_POST['xes_username'] = $slash($_POST['xes_username']);
	$_POST['xes_email'] = $slash($_POST['xes_email']);
	
}

//Uses built-in mysql sql-injection protection mechanisms.  Requires connection to mysql.
function xAUDBaseslashmysql(&$value) {
	global $AUDBaseDBase;
	if (!isset($AUDBaseDBase['connect'])) {AuthUserConnectmysql();};
	$value = mysql_real_escape_string($value,$AUDBaseDBase['connect']);
	return $value;
}

// Note that PGSQL is broken!  This is more a placeholder for the proper function
function xAUDBaseslashpgsql($value) {
	$value = pg_escape_string($value);
}

//Should check for valid email addresses including ones with abnormal but valid characters
function xAUDBaseValidateEmail ($email) {
	// This may look like a rather loose email validator, but if you look at RFPs
	// for real valid email addresses, it's pretty scary what people can put in email
	// addresses and then there's .info, .name, .museum and a bunch of .com.au etc. 
	// and oddest of all is name@[127.0.0.1] type addresses.
	
	$lastdot = strrpos($email, '.'); 
	$amp = strrpos($email, '@'); 
	$length = strlen($email);
	if ( ($lastdot === false) ||
		(!(substr_count($email, '@')==1)) || 
		($amp === 0) ||
		($amp === false) ||
		($length === false) ||
		(($lastdot - $amp) < 3) ||
		(($length - $lastdot) < 3) ) 
	{
			$return = false; 
	} else { 
		$return = true;
	}
	return $return;
}

// Quick check to see if the user has already validated their account
function xes_AuthUserIsValidated ($username) {
	global $AUDBaseTable;
		
		#-----------------------------------
		# Query Preparation
		$u = $AUDBaseTable['user_field'];
		$t = $AUDBaseTable['user_table'];
		$vf = $AUDBaseTable['validate_field'];
	// return true/false on whether a user is validated -- no need to check password, etc.
	$ask = "select $vf as 'EXISTS' from $t where $u = '$username'";
	$answer = xes_AuthUserQuery ($ask);
	return $answer;
}

// Customized query function based on pre-existing authuser_dbase.php's query/function format
// Flags added to influence return values: previous functions only return boolean.
function xes_AuthUserQuery ($ask, $flag=1) {
	global $AUDBaseEngine, $AUDBaseDBase;
	#-----------------------------------
    # Database Switch
     switch($AUDBaseEngine) {
        case 'mysql' : $answer = AuthUserMySQL($ask, $flag); break;
        case 'pgsql' : $answer = AuthUserPgSQL($ask); break;
        default : $answer = AuthUserMySQL($ask); break;
    }
    
    if ($flag == 2) {$answer = mysql_affected_rows($AUDBaseDBase['connect']);}
	return $answer;
}

// Process a request to validate the user - from link in email using GET values
function xes_AuthUserProcessValidate () {	
	global $AUDBaseTable;

	// Note: Consider adding username to the link & query -- valcodes COULD be duped	
		#-----------------------------------
		# Query Preparation
		$u = $AUDBaseTable['user_field'];
		$t = $AUDBaseTable['user_table'];
		$v = $AUDBaseTable['validate_code'];
		$vf = $AUDBaseTable['validate_field'];
	
	$ask = "SELECT count(*) as `EXISTS` FROM $t WHERE $v ='$_GET[valcode]'";
	$count = xes_AuthUserQuery($ask);
	if ($count == 1) {
		$ask = "UPDATE $t SET $v=NULL, $vf=1 WHERE $v ='$_GET[valcode]'";
		$answer = xes_AuthUserQuery($ask, 2);
	
		if ($answer >= 1) {
			xes_AuthUserFormExit('validation_done');
		} else {
			xes_AuthUserFormExit('validation_error');
		}
	}
}

// Process errors and send them to the browser PmWiki-style
function xes_AuthUserFormExit ($type) {
	global $MessagesFmt, $xAUDBaseMsgs;
	$MessagesFmt[] = $xAUDBaseMsgs[$type];
	return true;
}


// Create random alphanumeric code
function xes_AuthUserValidateCode ($length=20) {

	//Borrowed and hacked from Author: Peter Mugane Kionga-Kamau 
	//http://www.pmkmedia.com 
	//code found at http://codewalkers.com/seecode/279.html
	//"Modify at will."
	
	$from = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	
	for ($i=0; $i<$length; $i++) $key .= $from[(mt_rand(0,(strlen($from)-1)))];
	return $key;
}

/***************************************************
// ORIGINAL AuthUserDatabase Functions -- mods noted
****************************************************/

function AuthUserDBaseError($t, $e) {
    $msg = array(
        'query' => "Could not successfully run query (\$ask) from DB: ",
        'dbase' => "Unable to select database \$AUDBaseDBase[db]: ",
        'conn' => "Could not connect: ",
    );
    die($msg[$t] . $e);
}

function AuthUserPgSQL($ask) {
    global $AUDBaseDBase;
    pg_connect(
        "host=$AUDBaseDBase[host] "
        . "dbname=$AUDBaseDBase[db] "
        . "user=$AUDBaseDBase[user] "
        . "password=$AUDBaseDBase[password]"
    )
        or AuthUserDBaseError('conn',pg_last_error());
    $result = pg_fetch_assoc($ask)
        or AuthUserDBaseError('query',mysql_error());
    return ($result['authorized']);
}

function AuthUserConnectmysql() {
    global $AUDBaseDBase;
    
    $AUDBaseDBase['connect'] = mysql_connect(
        $AUDBaseDBase['host'],
        $AUDBaseDBase['user'],
        $AUDBaseDBase['password']
    ) or AuthUserDBaseError('conn',mysql_error());
    @mysql_select_db($AUDBaseDBase['db']) 
        or AuthUserDBaseError('dbase',mysql_error());
}

function AuthUserMySQL($ask, $type=1) {
    global $AUDBaseDBase;
    
    $AUDBaseDBase['connect'] = mysql_connect(
        $AUDBaseDBase['host'],
        $AUDBaseDBase['user'],
        $AUDBaseDBase['password']
    ) or AuthUserDBaseError('conn',mysql_error());
    @mysql_select_db($AUDBaseDBase['db']) 
        or AuthUserDBaseError('dbase',mysql_error());
  	$result = mysql_query($ask) 
        or AuthUserDBaseError('query',mysql_error());
    if($type == 1 && (@mysql_num_rows($result) > 0)) {
		$row = mysql_fetch_array($result);
		return ($row['EXISTS']) ? true : false;
    } elseif (@mysql_num_rows($result) == 0) {
    	return false;
    } elseif (@mysql_insert_id()) {
    	return mysql_insert_id();
    }
}


// Altered by Criss (XES)
function AuthUserDatabase($pagename, $id, $pw, $pwlist) {
    global $AUDBaseTable, $AUDBaseEncryption, $AUDBaseConditional, $AUDBaseEngine;


    #-----------------------------------
    # Encryption Switch
    switch($AUDBaseEncryption) {
        case 'md5' : $pw = md5($pw); break;
        case 'sha1' : $pw = sha1($pw); break;
        default : $pw = md5($pw); break;
    }

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $vf = $AUDBaseTable['validate_field']; // Altered by Criss (XES)
    $w = $AUDBaseConditional;
    $n = $AUDBaseEncryption;
    // Query altered to include checking if user is validated, 
    //     also added explicit variable calls {} due to a debug
    $ask = "SELECT count(*) AS `EXISTS` FROM {$t} WHERE {$u}='{$id}' AND {$p}='{$pw}' AND {$vf}=1 {$w};";
    #-----------------------------------
    # Database Switch
    switch($AUDBaseEngine) {
        case 'mysql' : $answer = AuthUserMySQL($ask); break;
        case 'pgsql' : $answer = AuthUserPgSQL($ask); break;
        default : $answer = AuthUserMySQL($ask); break;
    }
    return ($answer) ? true : false;
    return false;
}


// Original commented out form was part of original authuser_dbase.php


#$AuthForm      =<<<AUTHFORM
#<form name='authform' action='{$_SERVER['REQUEST_URI']}' method='post'>
#<table border='0'>
#<tr>
#<td class='name'>Name:</td><td><input tabindex='1' type='text' name='authid' value=''></td>
#</tr><tr>
#<td class='name'>Password:</td><td><input tabindex='2' type='password' name='authpw' value=''></td>
#</tr><tr>
#<td colspan='2'>
#<input type='submit' value='OK'>
#</td>
#<input type='hidden' name='authaction' value='1'>
#</table>
#<script language='javascript'<!-- document.authform.authid.focus() //--></script>
#</form>
#
#AUTHFORM;
#$AuthPromptFmt = array(&$PageStartFmt, $AuthForm, &$PageEndFmt);