This month I look at another of the PEAR packages I find extremely useful – Validate. Poor validation is a key weakness many scripts are guilty of, enabling security exploits. The Validate package can be used to validate any data, and is especially useful for validating user input. It can be used to validate:
* numbers (whether they fall into a certain range, or are decimal or not)
* emails (domain, syntax and RFC822)
* strings (whether they’re numeric or not, upper and lower case
* dates (within a specific range)
* urls
* custom data
There are also related packages that apply specific validation rules according to geographic location. Currently these include: AT (Austria), BE (Belgium), CH (Switzerland), DK (Denmark), ES (Spain), FR (France), PL (Poland), ZA (South Africa). Similarly, there are packages that validate by application domain (such as Validate_Finance, or Validate_ISPN). I don’t cover these packages in this article, though once you’ve grasped the basics of the main Validate package, using these won’t present much of a challenge.
Installing PEAR:Validate
The requirements are not odious. Currently, with 0.6.3 the latest release, you need a PHP Version at least as recent as 4.2.0, and the PEAR:Date package is an optional requirement.
If you’re not sure whether the Validate package is running on your system, you can check if you have it with:
$ pear list
Installed packages:
===================
Package Version State
Archive_Tar 1.1 stable
Console_Getopt 1.2 stable
DB 1.6.2 stable
HTTP 1.2.2 stable
Mail 1.1.3 stable
Net_SMTP 1.2.6 stable
Net_Socket 1.0.1 stable
PEAR 1.3.2 stable
XML_Parser 1.0.1 stable
XML_RPC 1.1.0 stable
This is a default list of installed packages, and you’ll see it doesn’t include the Validate package. Download it if necessary from the PEAR repository, and install:
pear install Validate-0.6.3.tgz
Optional dependencies:
package `Date’ is recommended to utilize some features.
install ok: Validate 0.6.3
Starting off: validating email
Let’s start with a simple script that validates the format of an email.
validate.php
<?php
require_once ‘Validate.php’;
$email = $_REQUEST[’email’];
$validate = new Validate();
if ($validate->email(“$email”)) {
echo “Valid email”;
}
else {
echo “Invalid email”;
}
?>
You can test the results. Calling the script using something like http://yourserver.co.za/validate.php?email=blah will display Invalid email, while calling it with something like http://yourserver.co.za/[email protected] will display Valid email.
Short and sweet! The great thing is that you no longer need to worry about writing the regex to validate something like an email yourself. Numerous authors of books and articles have come up with their own versions, not all entirely reliable. Here, you’re relying on the authors of the Validate class, and even though the package is officially still beta, this many eyes into the process it’s reliable. Here’s the full function used by the Validate package:
function email($email, $options = null)
{
$check_domain = false;
$use_rfc822 = false;
if (is_bool($options)) {
$check_domain = $options;
} elseif (is_array($options)) {
extract($options);
}
// the base regexp for address
$regex = ‘&^(?: # recipient:
(“s*(?:[^”fnrtvbs]+s*)+”)| #1 quoted name
([-w!#$%&’*+~/^`|{}]+(?:.[-w!#$%&’*+~/^`|{}]+)*)) #2 OR dot-atom
@((([)? #3 domain, 4 as IPv4, 5 optionally bracketed
(?:(?:(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9])).){3}
(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))))(?(5)])|
((?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?.)*[a-z](?:[-a-z0-9]*[a-z0-9])?)) #6 domain as hostname
$ξ’;
if ($use_rfc822? Validate::__emailRFC822($email, $options) :
preg_match($regex, $email)) {
if ($check_domain && function_exists(‘checkdnsrr’)) {
list (, $domain) = explode(‘@’, $email);
if (checkdnsrr($domain, ‘MX’) || checkdnsrr($domain, ‘A’)) {
return true;
}
return false;
}
return true;
}
return false;
}