In this chapter, you’ll find a collection of solutions for helping you with expression evaluation, validation of credit card details, e-mail addresses and text strings, identifying spam,
Trang 1Forms and User Input
Trang 2Even with the growth in Web 2.0 Ajax techniques, most people still interact with web
sites using forms They are a tried and tested means of obtaining user input and are likely to retain an important position for a long time to come
Receiving user input is all well and good—that’s the easy part But turning that input into usable and secure data is another matter In this chapter, you’ll find a collection of solutions for helping you with expression evaluation, validation of credit card details, e-mail addresses and text strings, identifying spam, preventing automated input from
“bots,” and ways of supporting user-supplied text formatting
Evaluate Expression
You might think that offering support for evaluating expressions would be a simple matter
of calling the PHP eval() function with a user supplied input Unfortunately, though, eval() is an extremely powerful function that will interpret any string supplied to it as if it were a PHP program; using it could completely open up your web site to any intruder with
a minimum of PHP knowledge
However, with this plug-in the user input is completely sanitized by stripping out any characters and functions that are not safe, leaving only a selection of 22 mathematical functions and the basic math operators (plus, minus, multiply, and divide), and only then
is the input passed to eval() Figure 6-1 shows a variety of expressions being calculated About the Plug-in
This plug-in accepts a string containing a mathematical expression and returns the result of evaluating it It takes this argument:
• $expr A string containing an expression
Variables, Arrays, and Functions
$f1 Array containing the 22 mathematical function names supported
$f2 Array containing tokens that the function names are temporarily converted to
F IGURE 6-1 This plug-in enables powerful calculator functionality on your web site.
31
Trang 3How It Works
To allow the use of PHP’s build-in eval() function, it is necessary to remove any harmful expressions before passing them to the function To achieve this, the array $f1 contains
22 function names (out of the hundreds supported by PHP) that are considered safe Using the $f2 array, which contains a matching set of tokens, any of the 22 functions found in the argument $expr are converted to a corresponding token This means that any remaining alphabetical characters may form other function names and therefore are stripped out
The preceding is achieved by first converting the string $expr to lowercase using the function strtolower() and then employing str_replace() to replace all occurrences of the allowed function names with their tokens
Next preg_replace() is called to strip out anything remaining that is not required, using the regular expression /[^\d\+\*\/\-\.()! ]/ Okay, I know it looks like I just dropped the keyboard on the floor but this is actually a powerful expression which I’ll now break up for you
The outer / characters denote the start and end of a regular expression
The square brackets, [], state that a match should be made against any single character enclosed within them
The ^ symbol, when immediately following a [ symbol, forces negation, so that the
expression will match anything that is not one of the characters following.
Next comes a sequence of characters, which are all escaped by prefacing them with a \ symbol, because otherwise they would be interpreted as special regular expression operators:
• \d Any digit (0–9)
• \+ An addition symbol
• \* A multiplication symbol
• \/ A division symbol
• \- A subtraction symbol
• \ A decimal point symbol
So, if any symbol is not one of these escaped symbols, it will be considered a match and
the second argument to preg_replace(), '', will replace it with nothing—in other words, the symbol will be removed
Finally, a few other symbols are also allowed through These are the left and right brackets, the comma, the exclamation mark, and a space
You might wonder why the exclamation mark is allowed within a mathematical expression Well, the answer isn’t that the exclamation mark is needed for use in expressions, because it isn’t Instead, it’s there because it forms part of each of the 22 tokens in the array
$f2 Once the mathematical functions have been converted to tokens, the ! symbols remain there so that the tokens can be converted back again after stripping the remaining unwanted characters out, which is done using another call to the str_replace() function I chose the exclamation mark at random and could equally have used any one of many other symbols
After all this processing, the resulting sanitized string is passed to the eval() function, the result of which is returned to the calling statement If you wish to see what the sanitized expression looks like, you can uncomment the line shown in the source code
Trang 4How to Use It
To evaluate a user-supplied expression, just call the function PIPHP_EvaluateExpression(), passing the expression to be calculated, in the following manner, which calculates the area
of a circle with a radius of 4:
echo PIPHP_EvaluateExpression("pi() * pow(4, 2)");
The Plug-in
function PIPHP_EvaluateExpression($expr) {
$f1 = array ('abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cos', 'cosh', 'exp', 'expm1', 'log', 'log10', 'log1p', 'pi', 'pow', 'sin', 'sinh', 'sqrt', 'tan', 'tanh');
$f2 = array ('!01!', '!02!', '!03!', '!04!', '!05!', '!06!', '!07!', '!08!', '!09!', '!10!', '!11!', '!12!', '!13!', '!14!', '!15!', '!16!', '!17!', '!18!', '!19!', '!20!', '!21!', '!22!');
$expr = strtolower($expr);
$expr = str_replace($f1, $f2, $expr);
$expr = preg_replace("/[^\d\+\*\/\-\.(),! ]/", '', $expr);
$expr = str_replace($f2, $f1, $expr);
// Uncomment the line below to see the sanitized expression // echo "$expr<br />\n";
return eval("return $expr;");
}
Validate Credit Card
Sometimes people make mistakes when entering credit card numbers in web forms, or even just make numbers up to see what will happen Using this plug-in you can at least ensure that
a credit card number and expiration date you have been provided with has an acceptable number sequence, a correct checksum, and a valid expiration date
This enables you to only pass on sensible-looking details to your card processing organization, and possibly limit any additional fees that may be charged In Figure 6-2 you can see a made-up card number that has not validated
About the Plug-in This plug-in accepts a credit card number and expiration date and returns TRUE if they validate, otherwise it returns FALSE It takes these arguments:
• $number A string containing a credit card number
• $expiry A credit card expiration date in the form 07/12 or 0712
32
Trang 5Variables, Arrays, and Functions
How It Works
In the 1950s, Hans Peter Luhn, a scientist working at IBM, created the Luhn checksum
algorithm, also known as the modulus 10 or mod 10 algorithm It will detect any single-digit
error, as well as almost all transpositions of adjacent digits in a string of digits This makes it very useful for verifying whether a credit card number has been successfully entered by using the simple method of adding a checksum digit at the number’s end All major credit companies use this system, and so can we
The first thing the plug-in does is remove any non-digit characters from $number; the same is done for the expiration date in $expiry Then, the contents of the first four digits of
$number are placed in the variable $left, the length of $number is placed in $cclen, and
$checksum is initialized to 0
Each card issuer has their own initial sequences of numbers, and card number length can vary between 13 and 16 digits depending on the issuer So, using the contents of $left, the next main section of code looks up the type of card and, based on the result, returns FALSE if $number does not contain the correct number of digits for that card
Once all the known sequences of initial digits have been processed, if no card has yet been matched, then FALSE is returned because $number represents the number for a card type the program is unaware of—most likely it’s a made-up number
Otherwise, the card type has been identified and $number has been found to have the right number of digits, so the next portion of code runs the Luhn algorithm to see whether the sequence of numbers appears valid It does this by checking alternate digits and adding them together in a pre-set manner If the result is exactly divisible by 10, then the sequence
is valid If not, FALSE is returned
Lastly, the expiration date is checked against the date of the last day of the current month, and if the card has expired, FALSE is returned
If all these tests pass, a value of TRUE is returned
F IGURE 6-2 Credit card numbers have a built-in checksum that this plug-in will validate.