Jump to content

PHP validation script


knobby2k

Recommended Posts

Hi guys,

 

wanted to run this past you lot for a seal of approval before I run with it.

 

I've been searching for a script that would fully validate a registration form; so basically check all fields hold the correct expected data in the correct format and protect against sql injection as well as other misuse. This would then alert the user to their mistakes and allow corrections to be made.

 

I originally went to modify one that I had done in uni but I think I had done it the hard way round as mine was about 1500 lines of code with lots of the code repeated in 'if statements' and also wide open to sql injection.

 

So I stumbled across this little beauty which I've had a play about with and think it can do the job i'm after.

 

Form:

<form name="register" method="post" action="register.php">

<p>*First Name: <input type="text" name="firstname" value="" maxlength="80" />
</p>

<p>*Last Name: <input type="text" name="lastname" value="" maxlength="80" /></p>

<p>Mobile: <input type="text" name="mobile" value="" /></p>

<p>*Email: <input type="text" name="email" value="" /></p>

<p><input type="checkbox" name="t-and-c" id="t-and-c" value="true" /> </p>

<p><strong>* Required</strong></p>

<p><input type="submit" value="Send" /></p>

</form>

 

validating the data page:

<?php
/************************************************************
  Validation Class
  Author: Jason Ashdown
  Updated: 12:12 24/07/2008
  Version 0.2j

--------------------------------------------------------
Change Log:-
v0.2j - Added 'decode' function to form helpers. To help
	 pass UTF-8 characters back to a form from the DB.
v0.2h - Removed 'spaces' from the regexp strings
v0.2g - Email address function is now in compliant
	 with RFC 2822
v0.2f - Added $masks for allErrors to be more
	 user-friendly, updated loop_clean to use
	 htmlspecialchars and supports UTF-8
v0.2e - Fixed allErrors() to include wrappers
v0.2d - Changed "required" to check for empty
	 strings properly
v0.2c - Added "not_equal" and "selected" functions
v0.2b - Tidied comments; fixed email mx check
v0.2a - Added loop_clean (multi-array sanitiser)
V0.2 - Added new helper functions (label, check)
- - -
v0.1 - Initial Release
*************************************************************/

class validateForm
{
var $input = array();
var $error = array();
var $error_wrapper;
var $pass;

// You can call the validated inputs directly from this class
// when you come to inserting them into the db, e.g.
// $form = new validateForm($_POST);
// $form->input['fullname']; etc...

function validateForm($input=array()) // Yes, post the the whole $_POST/$_GET array into the function
{
	$this->input = $input; // Clone form inputs array into here

	$this->pass = true; // Flag changes if theres an error

	// Config
	$this->error_wrapper['start'] = "<br /><span class=\"error\">";
	$this->error_wrapper['end'] = "</span>";

	// Sanitise our arrays
	$this->loop_clean($this->input);
}

//
// We can even perform some security checks here if we wish
//
function loop_clean(&$data)
{
	foreach ($data as $key => $value)
	{
		if ( !is_array($value) )
		{
			// Well formatted string; PHP4 requires "stripslashes" on all input fields
			$data[$key] = trim(htmlspecialchars(strip_tags(stripslashes($value)), ENT_QUOTES, 'UTF-8'));
		}
		else
		{
			$this->loop_clean($value);
			$data[$key] = $value;
		}
	}
}

/************************************/
/* Error Functions                  */
/************************************/

// Set error
function error($item, $desc)
{
	$this->pass = false;
	$this->error[$item] .= $desc." "; // Append multiple error messages
}

// Return the error
function showError($item)
{
	return $this->error_wrapper['start'].trim($this->error[$item]).$this->error_wrapper['end'];
}

function allErrors($masks=array())
{
	foreach ( $this->error as $key => $value )
	{
		// Mask field names with more appropriate User friendly names
		$key = $masks[$key] != '' ? $masks[$key] : $key;
		echo $this->error_wrapper['start']."<b>".ucfirst($key)."</b>: ".trim($value).$this->error_wrapper['end'];
	}
}

/************************************/
/* Debugging                        */
/************************************/

function showInputs()
{
	print_r($this->input);
}

/************************************/
/* Validation Functions             */
/************************************/

function not_equal($string, $field)
{
	if ( is_string($string) )
	{
		if ($string == $this->input[$field])
		{
			$msg = "You must select a different option other than \"$string\"";
			$this->error($field, $msg);
			return false;
		}
		return true;
	}
	return false;
}

function min_length($min=0, $field)
{
	if( strlen($this->input[$field]) < (int) $min )
	{
		$msg = "This field cannot be shorter than $min characters.";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

function max_length($max=0, $field)
{
	if ( strlen($this->input[$field]) > (int) $max )
	{
		$msg = "This field cannot be longer than $max characters.";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

function alpha($field)
{
	if ( !preg_match("/^([a-z])+$/i", $this->input[$field]) )
	{
		$msg = "This field can only contain letters (A-Z). No foreign characters allowed.";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

// Double-barrel names and marital status will require this
function alpha_dotdash($field)
{
	if ( !preg_match("/^([a-z\-\.])+$/i", $this->input[$field]) )
	{
		$msg = "This field can only contain characters (A-Z-.). No foreign characters allowed.";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

// Useful for Addresses or fields that may contain unusual but still valid chars
function alpha_special($field)
{
	if ( !preg_match("/^([a-z0-9\-+\.,_='\"@#])+$/i", $this->input[$field]) )
	{
		$msg = "This field has illegal characters. You can use letters, numbers and (._-+='\"@#).";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

function numeric($field)
{
	if ( !preg_match("/^[\-+]?[0-9]*\.?[0-9]+$/", $this->input[$field]) )
	{
		$msg = "This field must contain only numbers.";
		$this->error($field, $msg);
		return false;
	}
	return true;
	//return is_numeric($this->input[$field]);
}

function alpha_numeric($field)
{
	if( !preg_match("/^([a-z0-9])+$/i", $this->input[$field]) )
	{
		$msg = "This field can only contain letters and numbers.";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

function required($field)
{
	if ( !isset($this->input[$field]) OR $this->input[$field] == '' )
	{
		$this->error($field, 'This field is required.');
		return false;
	}
	elseif ( is_array($this->input[$field]) )
	{
		$this->error($field, 'This is an array and won\'t be passed.');
		return false;
	}
	return true;
}

/************************************/
/* Alias Functions                  */
/************************************/

function fullname($field, $req=true)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	return $this->alpha_dotdash($field);
}

function address($field, $req=true)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	return $this->alpha_special($field);
}

function telephone($field, $req=true)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	if ( $this->numeric($field) AND $this->min_length(11, $field) AND $this->max_length(14, $field) )
	{
		return true;
	}

	return false;
}

function mobile($field, $req=true)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	return $this->telephone($field);
}

function postcode($field, $req=true)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	if ( !preg_match("/^[a-zA-Z]{1,3}[0-9]{1,3} [0-9]{1}[a-zA-Z]{2}$/i", $this->input[$field]) )
	{
		$msg = "Postcode must follow the format of \"XX1 1XX\".";
		$this->error($field, $msg);
		return false;
	}
	return true;
}

function email($field, $req=true, $mx_records=false)
{
	if ( $req == true AND !$this->required($field) )
		return false;

	// Function from: http://www.ilovejackdaniels.com/php/email-address-validation/
	// Complies with the email address specification guidelines: RFC 2822

	// First, we check that there's one @ symbol, and that the lengths are right
	if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $this->input[$field]))
	{
		// Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
		$msg = "Your email address is the wrong length.";
		$this->error($field, $msg);
		return false;
	}

	// Split it into sections to make life easier
	$email_array = explode("@", $this->input[$field]);
	$local_array = explode(".", $email_array[0]);

	for ($i = 0; $i < sizeof($local_array); $i++)
	{
		if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i]))
		{
			$msg = "The first part of your email is malformed.";
			$this->error($field, $msg);
			return false;
		}
	}

	if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) // Check if domain is IP. If not, it should be valid domain name
	{
		$domain_array = explode(".", $email_array[1]);
		if (sizeof($domain_array) < 2)
		{
			$msg = "Your email doesn't have a valid domain.";
			$this->error($field, $msg);
			return false; // Not enough parts to domain
		}

		for ($i = 0; $i < sizeof($domain_array); $i++)
		{
			if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i]))
			{
				$msg = "Your email doesn't have a valid domain.";
				$this->error($field, $msg);
				return false;
			}
		}
	}

	// Check online to see if this is a real email host!
	if ( $mx_records != false )
	{
		$host = $email_array[1]; //The whooole domain

		getmxrr($host, $mxhosts);
		if ( count($mxhosts) < 1 )
		{
			$msg = "There is no email host associated with your email. This probably means its fake.";
			$this->error($field, $msg);
			return false;
		}
	}

	return true;
}

/************************************/
/* Helper Functions                 */
/************************************/

function decode($field)
{
	return html_entity_decode($this->input[$field]);
}

function label($text, $id)
{
	return "<label for=\"$id\">$text</label>";
}

function check($field, $value, $default=false)
{
	if ( $default == true AND empty($this->input[$field]) )
		return 'checked="checked"';

	return $this->input[$field] == $value ? 'checked="checked"' : '';
}

function selected($field, $value, $default=false)
{
	if ( $default == true AND empty($this->input[$field]) )
		return 'selected="selected"';

	return $this->input[$field] == $value ? 'selected="selected"' : '';
}
}

/*
Example:

You can just edit $this->error_wrapper['start'] AND $this->error_wrapper['end'] to make the errors display how you want.
*/

if ( $_SERVER['REQUEST_METHOD'] == 'POST' )
{
$form = new validateForm($_POST);

$form->required('firstname');
$form->required('lastname');
$form->mobile('mobile');
$form->email('email', true); // Validate email AND make it required
$form->required('t-and-c'); // Terms & Conditions

if ( $form->pass == true )
{
	// Insert data into DB ... but a temporary success as confirmation that it has worked
	echo "Success<p>";

	// once data is inserted, go to successful page 
	//header ("location: success.php");
	//exit;
}
}
else
{
$form = new validateForm();

}
?>

<div class="error">
<?php

// Masks are used if you have an unfriendly named field that may cause the user confusion.
// You just specify the names and the fields in the array with the text you want to replace it with.
$masks = array(
't-and-c' => 'Terms & Conditions');

$form->allErrors($masks);
?>
</div>

<form method="post">

<p>*First Name: <input type="text" name="firstname" value="<?php echo $form->input['firstname'];?>" maxlength="80" />
<?php
// Show inidividual errors
echo $form->showError('firstname');
?>
</p>

<p>*Last Name: <input type="text" name="lastname" value="<?php echo $form->input['lastname'];?>" maxlength="80" />
<?php
// OR Specify your own error message
echo $form->showError('lastname');
?>
<p>

<p>Mobile: <input type="text" name="mobile" value="<?php echo $form->input['mobile'];?>" /></p>

<p>*Email: <input type="text" name="email" value="<?php echo $form->input['email'];?>" /></p>

<p><input type="checkbox" name="t-and-c" id="t-and-c" value="true" <?php $form->check('t-and-c', true);?>/> <?php echo $form->label('Terms and Conditions*' ,'t-and-c');?></p>

<p><strong>* Required</strong></p>

<p><input type="submit" value="Send" /></p>

</form>


 

What i'm asking you savvy gits out there is if this is going to protect me and is it doing everything possible to help with the protection. Is there anything you would add to it?

 

Thanks for your help guys

 

 

 

Link to comment
Share on other sites

check all fields hold the correct expected data in the correct format

You can easily check these two yourself.

 

protect against sql injection

Download the FF plug-in "SQL Inject Me" and test your form fields for vulnerabilities.

Link to comment
Share on other sites

check all fields hold the correct expected data in the correct format

You can easily check these two yourself.

 

protect against sql injection

Download the FF plug-in "SQL Inject Me" and test your form fields for vulnerabilities.

 

...unless you have the latest version of Firefox, in which case it won't install...  so you likely can't do this.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.