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

# Copyright
# =========
# 
# Copyright (c) 2006 Benjamin C. Wilson & Criss Ittermann. 
# This software is released under GPL
# under the same terms as PmWiki.
/*
 Description
 ===========

 AuthUserDBase is a database tie-in for PmWiki's AuthUser.
 The 2.0 versions utilize the ADOdb database abstraction layer,
 and have options for standalone use for authentication from
 its own database

 Requirements
 =====

 To use this version requires ADOdb and adodb-connect.php
 as described at 
 http://www.pmwiki.org/wiki/Cookbook/DatabaseStandard

 It also requires a database of some type, that is supported by ADOdb.
 
 Usage
 =====

 To use this for borrowing user authentication from an existing database,
 the following steps must be taken.
 
 1) see Requirements (above)

 2) Add $AUDBaseTable configuration values to config.php BEFORE calling authuser_dbase.php: 
 
	// if you don't need to change the default settings, you may leave them out
	
	$AUDBaseTable['database'] => 'users';
	$AUDBaseTable['user_table'] => 'pmwiki_users';
	$AUDBaseTable['user_field'] => 'username';
	$AUDBaseTable['pw_field']   => 'password';
	
	// normally "md5" or "sha1".  
	// May also be admin-defined function; use the name of the function,
	// and define the function in config.php
	$AUDBaseTable['encrypt_f'] => 'md5';
	
	// these are required for stand-alone use only
	$AUDBaseTable['standalone'] => false; // set to true for stand-alone use
	$AUDBaseTable['email'] => 'email';
	$AUDBaseTable['validate_code'] => 'validatecode';
	$AUDBaseTable['validate_field'] => 'validatefield';
	$AUDBaseTable['date_joined'] => 'signupdate';
	
	// not used at the moment
	$AUDBaseTable['lang'] => 'en';


   3. Include this file via the site configuration
    include_once("$FarmD/cookbook/authuser_dbase.php");

   4. Edit Site.AuthUser and add the following on its own line:
       " AUD: required for AuthUserDatabase"
   5. Have users in the authentication table.
   
   6. Make sure to include authuser.php *after* everything is set up
     for authuser_dbase
     // Must come after the other items!
	include_once('scripts/authuser.php');


**************************



Stand-alone usage



********************
SQL Installation
********************

Add table to a database.  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

Adapt as needed for your own database.  This database set-up is the default.


********************
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=AUD_SA value=addnew:)
(:input hidden name=aud_returnUrl value={$PageUrl} :)

|| Username:||(:input text aud_username size=20:) ||
|| Password:||(:input password aud_password size=20:) ||
|| Repeat Password:||(:input password aud_dupepassword:) ||
|| Email:||(:input text name=aud_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=AUD_SA value=reregister:)
(:input hidden name=aud_returnUrl value={$PageUrl} :)

|| Username:||(:input text name=aud_username size=20:) ||
|| Email:||(:input text name=aud_email size=20:) ||
|| New Password:||(:input password aud_newpassword:)||
|| Repeat Password:||(:input password aud_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=AUD_SA value=update:)
(:input hidden name=aud_returnUrl value={$PageUrl} :)

|| Username:||(:input text name=aud_username size=20:) ||
|| Current Password:||(:input text name=aud_oldpassword size=20:) ||
|| New Password:||(:input text name=aud_newpassword size=20:) (optional) ||
|| Repeat New Password:||(:input password aud_dupepassword:) ||
|| New Email:||(:input text name=aud_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
 ===============

 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
 v.2.0 Nov 05, 2006 by Crisses (xes) - update to ADOdb use, 
   and integrated stand-alone options
   
 prior xes_authuser_dbase.php fork history:
   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
   0.1.2 2006-10-5 Security Fix
   merged back into authuser_dbase.php
   

 To Do Items
 ===============
 - database errors
 -- in multiple languages?
 - fix internationalization for email body?
 - consider adding username to validation links
 - optional email notification for new user sign-up
 - password/username length specifications

****************************
DO NOT ALTER BELOW THIS LINE
You should be able to change

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

// new connection standards - defaults
SDVA($AUDBaseTable, array(
	'database' => 'users',
	  'user_table' => 'pmwiki_users',
	  'user_field' => 'username',
	  'pw_field'   => 'password',
	  'encrypt_f' => 'md5',
	  'lang' => 'en',
	  'standalone' => false,
	  'email' => 'email',
	  'validate_code' => 'validatecode',
	  'validate_field' => 'validatefield',
	  'date_joined' => 'signupdate'
));

SDV($AuthUserFunctions['AUD'], 'AuthUserDatabase');

function AuthUserDatabase($pagename, $id, $pw, $pwlist) {
    global $AUDBaseTable;

    #-----------------------------------
    # Encryption - allows admin-created function for encryption algorhythm
    $pw = $AUDBaseTable['encrypt_f']($pw);

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $vf = $AUDBaseTable['validate_field'];
	$id = AUD_Safe($id);
	$pw = AUD_Safe($pw);
    $ask = "SELECT * FROM $t WHERE $u=$id AND $p=$pw";
    if ($AUDBaseTable['standalone']) { $ask .= " AND $vf=1";}
    if (AUD_Query($AUDBaseTable['database'], $ask)){
    	return true;
    } else {
	   if ($AUDBaseTable['standalone']) { AUD_SA_FormExit('login_not_valid'); } else {AUD_SA_FormExit('user_not_valid'); }
   		return false;
    }
}

// returns true if query has matches
function AUD_Query($dbase, $query) {
	global $DB;
	$out = ADOdbConnect($dbase);
  	if ($out !== TRUE) die($out);
	$result = $DB[$dbase]->Execute($query);
	if ($result === false) die("failed");
	$return = false;
	if (($result->RecordCount() > 0) || ($DB[$dbase]->Affected_Rows() > 0)) {$return = true;} else {$return = false;}
    return $return;
}

// Replaces user-entered values and makes sure they're safe from SQL injection
function AUD_Safe($value){
	global $AUDBaseTable, $DB;
	$out = ADOdbConnect($AUDBaseTable['database']);
  	if ($out !== TRUE) die($out);

	if (get_magic_quotes_gpc()) $value = trim(stripslashes($value)); 
	$value = $DB[$AUDBaseTable['database']]->qstr($value);
	return($value);
}



/*********************** Stand-Alone Code ***********************/


SDV($AUD_SA_ValidationCodeLength, 15);

SDV($AUD_SA_Msgs, 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; color:red;'>$[No user with that name and password found.  Please register or try again].</a></p>",
		
		"login_not_valid" => "<p style='font-weight:strong; color:red;'>$[No validated user with that name and password found.  Please validate your account, 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",
		
		"standalone_error" => "<p style='font-weight:strong'>$[There is an error in your configuration settings, or in your form.  To use AuthUserDBase with the standalone feature, you must set \$AUDBaseTable's standalone setting to <b>true</b>.]</p>",

		"validation_done" => "<p style='font-weight:strong'>$[Thank you for validating.]</p>" )
);

/*********************************/
// Stand-alone database management
/*********************************/

//Program Logic

// logic only runs for AUD_SA actions
if (isset($_REQUEST['AUD_SA'])) {
	if (!$AUDBaseTable['standalone']) {
		AUD_SA_FormExit('standalone_error');
		return false;
	}
	global $AUDBaseTable, $DB;
	$out = ADOdbConnect($AUDBaseTable['database']);
  	if ($out !== TRUE) die($out);
	
	switch ($_REQUEST['AUD_SA']) {
		case "addnew":
			AUD_SA_ProcessAddnew();
		break;
		case "update":
			AUD_SA_ProcessUpdate();
		break;
		case "validate":
			AUD_SA_ProcessValidate();
		break;
		case "reregister":
			if ($_POST['AUD_SA'] == "reregister") {
				AUD_SA_ProcessReRegister();
			} else {
				AUD_SA_CompleteReRegister();
			}
		break;
		default:
			AUD_SA_FormExit('form_error');
			return false;
		break;
	}
}

// Handle the re-validation email from user request to fix passwords
function AUD_SA_CompleteReRegister(){
    global $AUDBaseTable;

	// validate "audcode" as 32 hexidecimal characters in length
	$password_valid = preg_match('/^[A-Fa-f0-9]{32}$/', $_GET['audcode']);
	if (!$password_valid) {		
		AUD_SA_FormExit('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'];
	$un = AUD_Safe($_GET['username']);
    $vc = AUD_Safe($_GET['valcode']);
    $ac = AUD_Safe($_GET['audcode']);
    // check username & validation code.  
	$ask = "SELECT * FROM $t WHERE $u=$un AND $v=$vc";
	$answer = AUD_Query($AUDBaseTable['database'], $ask);
	
	if ($answer === true) {
		//If valid, then update table with password.
		$ask = "UPDATE $t SET $v=NULL, $vf='1', $p=$ac WHERE $u=$un";
		$answer = AUD_Query($AUDBaseTable['database'], $ask);
		
		if ($answer) {
			AUD_SA_FormExit('validation_done');
		} else {
			AUD_SA_FormExit('validation_error');
		}
	}
}

// Handle the user request to fix their password
function AUD_SA_ProcessReRegister () {
    global $AUDBaseTable;
    #-----------------------------------
    # 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'];
    $un = AUD_Safe($_POST['aud_username']);
    $em = AUD_Safe($_POST[aud_email]);

	// validate all user-entered data

	// entered passwords must match
	if (($_POST['aud_newpassword'] != '') && (!AUD_SA_ComparePasswords($_POST['aud_newpassword'], $_POST['aud_dupepassword']))) return false;

	// validate user - username & email must match account
	$ask = "SELECT * from $t where $u=$un AND $e=$em";
	$answer = AUD_Query($AUDBaseTable['database'], $ask);
	if (!$answer) {
		AUD_SA_FormExit('user_not_found');
		return false;
	} 
	
	// generate new validation code
	$vcode = AUD_SA_ValidateCode();

	// update database with validation code
	$ask = "UPDATE $t SET $v='$vcode' WHERE $u=$un";
	$answer = AUD_Query($AUDBaseTable['database'], $ask);

	// Send email
	if ($answer > 0) {
		AUD_SA_EmailCode ($_POST['aud_username'], $_POST['aud_email'], $vcode, 1) ;
		AUD_SA_FormExit('email_sent');
	}
}

// process user information changes - update email &/or password
function AUD_SA_ProcessUpdate () {
    global $AUDBaseTable;
    // Form validation
    
    // Check that there's sufficient info to process the update
    if (($_POST['aud_username'] == '') || ($_POST['aud_oldpassword'] == '') || ( ($_POST['aud_newpassword'] == '') && ($_POST['aud_newemail'] == '') ) ) {
    	AUD_SA_FormExit('update_invalid');
    	return false;
    }
    
   	// entered passwords must match
	if (($_POST['aud_newpassword'] != '') && (!AUD_SA_ComparePasswords($_POST['aud_newpassword'], $_POST['aud_dupepassword']))) return false;

	// Make sure user IS validated if updating record.	
	if (!AUD_SA_IsValidated(AUD_Safe($_POST['aud_username']))) {
		AUD_SA_FormExit('user_not_validated');
		return false;
	} 

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

	// entered new passwords must match
	if (($_POST['aud_newpassword'] != '') && (!AUD_SA_ComparePasswords($_POST['aud_newpassword'], $_POST['aud_dupepassword']))) return false;

    #-----------------------------------
    # Query Preparation
    $u = $AUDBaseTable['user_field'];
    $p = $AUDBaseTable['pw_field'];
    $t = $AUDBaseTable['user_table'];
    $e = $AUDBaseTable['email'];
    $d = $AUDBaseTable['date_joined'];
    $ne = AUD_Safe($_POST['aud_newemail']);
    $un = AUD_Safe($_POST['aud_username']);
    
    // create the update query
	$ask = "UPDATE $t SET ";
	if ($_POST['aud_newpassword'] != "") {
		// encrypt password using the format set by user or default
		$crypt = $AUDBaseTable['encrypt_f']($_POST['aud_newpassword']);
		$ask .= "$p = '$crypt' " ;
	}
	if (($_POST['aud_newemail'] != "") && ($_POST['aud_newpassword'] != "") ) {$ask .= ", ";}
	
	if ($_POST['aud_newemail'] != "") { $ask .= "$e = $ne " ;}
	
	$ask .= "WHERE $u=$un";
	$answer = AUD_Query($AUDBaseTable['database'], $ask);
	
	// userfeedback
	if ($answer == 1) {
		AUD_SA_FormExit('updates_done');
		return true;
	} else {
		AUD_SA_FormExit('form_error');
		return false;
	}
}


// This function adds a new user to the database
function AUD_SA_ProcessAddNew () {
    global $AUDBaseTable, $DB;

	// Check this --> need to make sure user IS not(!) validated if adding a record.	
	if (AUD_SA_IsValidated(AUD_Safe($_POST['aud_username']))) {AUD_SA_FormExit('addnew_loggedin'); return false;} 
	
	// entered passwords must match
	if ($_POST['aud_password'] != '') {
		$p_answer = AUD_SA_ComparePasswords($_POST['aud_password'], $_POST['aud_dupepassword']);
		if (!$p_answer) {
			return false;
		} 
	} else { AUD_SA_FormExit('password_mismatch');
			return false;
	}

	// Validate Email Address
	if (!AUD_SA_ValidateEmail($_POST['aud_email'])) { AUD_SA_FormExit('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'];
    $em = AUD_Safe($_POST['aud_email']);
    $un = AUD_Safe($_POST['aud_username']);

	// check whether requested email address exists
	$ask = "SELECT * FROM $t WHERE $e=$em";
	$eanswer = AUD_Query($AUDBaseTable['database'], $ask);
	// if email exists, send error to browser
	if ($eanswer) { AUD_SA_FormExit ('email_taken'); }

	// check whether requested username exists
	$ask = "SELECT * FROM $t WHERE $u=$un";
	$uanswer = AUD_Query($AUDBaseTable['database'], $ask);
	// if username exists, send error to browser, ask for new username
	if ($uanswer) { AUD_SA_FormExit ('username_taken'); }

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

		// generate a random validation code
		$vcode = AUD_SA_ValidateCode($AUD_SA_ValidationCodeLength);
		
		// encrypt password using the encryption format
		$crypt = $AUDBaseTable['encrypt_f']($_POST['aud_password']);
		// Add new user to database with validation code
		$now = $DB[$AUDBaseTable['database']]->DBdate(time());
		$ask = "INSERT INTO $t ($u, $e, $p, $v, $d) VALUES ($un, $em, '$crypt', '$vcode', $now )";
		
		// run query
		$answer = AUD_Query($AUDBaseTable['database'], $ask);
		// Send out email with validation code
		
		// can check $answer, send email, and send message to browser
		if ($answer) {
			AUD_SA_EmailCode($_POST['aud_username'], $_POST['aud_email'], $vcode);
			AUD_SA_FormExit('email_sent');
		};
	}
}

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

	// create validation URL

	if ($revalidate == 0) {
		$url = $ScriptUrl . "?n=$pagename&aud_username=$username&AUD_SA=validate&valcode=$vcode";
	} else {
		$crypt = $AUDBaseTable['encrypt_f']($_POST['aud_newpassword']);
		$uencuser = urlencode($username);
		$url = $ScriptUrl . "?n=$pagename&AUD_SA=reregister&username=$uencuser&valcode=$vcode&audcode=$crypt";
	}
	
	$body = $username . ": \n\n$AUD_SA_Msgs[email_msg]\n" . $url;
	//may want to add a from line later
	$from = "";

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

//Should check for valid email addresses including ones with abnormal but valid characters
function AUD_SA_ValidateEmail ($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 AUD_SA_IsValidated ($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 from $t where $u = $username";
	$answer = AUD_Query($AUDBaseTable['database'], $ask);
	return $answer;
}

// Process a request to validate the user - from link in email using GET values
function AUD_SA_ProcessValidate () {	
	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'];
		$vc = AUD_Safe($_GET['valcode']);
	
	$ask = "SELECT * FROM $t WHERE $v =$vc";
	$count = AUD_Query($AUDBaseTable['database'], $ask);
	if ($count) {
		$ask = "UPDATE $t SET $v=NULL, $vf=1 WHERE $v =$vc";
		$answer = AUD_Query($AUDBaseTable['database'], $ask);
	
		if ($answer) {
			AUD_SA_FormExit('validation_done');
		} else {
			AUD_SA_FormExit('validation_error');
		}
	}
}

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

// Create random alphanumeric code
function AUD_SA_ValidateCode ($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;
}

// case-sensitive string comparison -> compare passwords given in dupe password forms
function AUD_SA_ComparePasswords($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) {
		AUD_SA_FormExit('password_mismatch');
		return false;
	}
	return true;
}