source: trunk/lib/Validator.inc.php @ 266

Last change on this file since 266 was 266, checked in by quinn, 17 years ago

Bugfixes found during strangecode site upgrade.

File size: 10.1 KB
Line 
1<?php
2/**
3 * Validator.inc.php
4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 *
6 * The Validator class provides a methods for validating input against different criteria.
7 * All functions return true if the input passes the test.
8 *
9 * @author    Quinn Comendant <quinn@strangecode.com>
10 * @version   1.0
11 */
12
13// Known credit card types.
14define('CC_TYPE_VISA', 1);
15define('CC_TYPE_MASTERCARD', 2);
16define('CC_TYPE_AMEX', 3);
17define('CC_TYPE_DISCOVER', 4);
18define('CC_TYPE_DINERS', 5);
19define('CC_TYPE_JCB', 6);
20
21// validateEmail return types.
22define('VALIDATE_EMAIL_REGEX_FAIL', 1);
23define('VALIDATE_EMAIL_LENGTH_FAIL', 2);
24define('VALIDATE_EMAIL_MX_FAIL', 3);
25define('VALIDATE_EMAIL_SUCCESS', 4);
26
27class Validator {
28
29    /**
30     * Ensures a value is empty.
31     *
32     * @param  string $val The input data to validate.
33     * @return bool   true if form is not empty, false otherwise.
34     */
35    function notEmpty($val)
36    {
37        return '' != trim((string)$val);
38    }
39
40    /**
41     * Ensures a value is blank.
42     *
43     * @param  string $val The input data to validate.
44     * @return bool   true if form is empty, false otherwise.
45     */
46    function isEmpty($val)
47    {
48        return '' == trim((string)$val);
49    }
50
51    /**
52     * Check whether input is a string.
53     *
54     * @param  string $val The input data to validate.
55     * @return bool   true if form is a string, false otherwise.
56     */
57    function isString($val)
58    {
59        return '' == trim((string)$val) || is_string($val);
60    }
61
62    /**
63     * Check whether input is a number. Allows negative numbers.
64     *
65     * @param  string $val The input data to validate.
66     * @return bool   True if no errors found, false otherwise.
67     */
68    function isNumber($val)
69    {
70        return '' == trim((string)$val) || is_numeric($val);
71    }
72
73    /**
74     * addError if input is NOT an integer. Don't just use is_int() because the
75     * data coming from the user is *really* a string.
76     *
77     * @param  string $val The input data to validate.
78     * @return bool   true if value is an integer
79     */
80    function isInteger($val, $negative_ok=false)
81    {
82        $pattern = $negative_ok ? '/^-?[[:digit:]]+$/' : '/^[[:digit:]]+$/';
83        return '' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val));
84    }
85
86    /**
87     * Check whether input is a float. Don't just use is_float() because the
88     * data coming from the user is *really* a string. Integers will also
89     * pass this test.
90     *
91     * @param  string $val The input data to validate.
92     * @return bool   true if value is a float
93     */
94    function isFloat($val, $negative_ok=false)
95    {
96        $pattern = $negative_ok ? '/^-?[[:digit:]]*(?:\.?[[:digit:]]+)$/' : '/^[[:digit:]]*(?:\.?[[:digit:]]+)$/';
97        return '' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val));
98    }
99
100    /**
101     * Check whether input is an array.
102     *
103     * @param  string $val The input data to validate.
104     * @return bool   true if value is a float
105     */
106    function isArray($val)
107    {
108        return (is_string($val) && '' == trim((string)$val)) || is_array($val);
109    }
110
111    /**
112     * Check whether input matches the specified perl regular expression
113     * pattern.
114     *
115     * @param  string $val The input data to validate.
116     * @param  int    $regex            PREG that the string must match
117     * @param  bool   $valid_on_match   Set to false to be valid if match, or true
118     *                                  to be valid on no match
119     * @return bool   true if value passes regex test
120     */
121    function checkRegex($val, $regex, $valid_on_match=true)
122    {
123        return $valid_on_match ? preg_match($regex, $val) : !preg_match($regex, $val);
124    }
125
126    /**
127     * Tests if the string length is between specified values. Whitespace excluded for min.
128     *
129     * @param  string $val The input data to validate.
130     * @param  int    $min       minimum length of string, inclusive
131     * @param  int    $max       maximum length of string, inclusive
132     * @return bool   true if string length is within given boundaries
133     */
134    function stringLength($val, $min, $max)
135    {
136        return mb_strlen(trim((string)$val)) >= $min && mb_strlen($val) <= $max;
137    }
138
139    /**
140     * Check whether input is within a valid numeric range.
141     *
142     * @param  string $val The input data to validate.
143     * @param  int    $min       minimum value of number, inclusive
144     * @param  int    $max       maximum value of number, inclusive
145     * @return bool   True if no errors found, false otherwise.
146     */
147    function numericRange($val, $min, $max)
148    {
149        return '' == trim((string)$val) || (is_numeric($val) && $val >= $min && $val <= $max);
150    }
151
152    /**
153     * Validates an email address based on the recommendations in RFC 3696.
154     * Is more loose than restrictive, to allow the many valid variants of
155     * email addresses while catching the most common mistakes.
156     * http://www.faqs.org/rfcs/rfc822.html
157     * http://www.faqs.org/rfcs/rfc2822.html
158     * http://www.faqs.org/rfcs/rfc3696.html
159     * http://www.faqs.org/rfcs/rfc1035.html
160     *
161     * @access  public
162     * @param   string  $val  The input data to validate..
163     * @return  bool    Validity of address.
164     * @author  Quinn Comendant <quinn@strangecode.com>
165     */
166    function validateEmail($val)
167    {
168        require_once 'codebase/lib/Email.inc.php';
169        $e = new Email();
170
171        // Test email address format.
172        if (!preg_match($e->getParam('regex'), $val, $e_parts)) {
173            return VALIDATE_EMAIL_REGEX_FAIL;
174        }
175       
176        // We have a match! Here are the captured subpatterns, on which further tests are run.
177        // The part before the @.
178        $local = $e_parts[2];
179
180        // The part after the @.
181        // If domain is an IP [XXX.XXX.XXX.XXX] strip off the brackets.
182        $domain = $e_parts[3]{0} == '[' ? mb_substr($e_parts[3], 1, -1) : $e_parts[3];
183
184        // Test length.
185        if (mb_strlen($local) > 64 || mb_strlen($domain) > 191) {
186            return VALIDATE_EMAIL_LENGTH_FAIL;
187        }
188
189        // Check domain exists: It's a domain if ip2long fails; Checkdnsrr ensures a MX record exists; Gethostbyname() ensures the domain exists.
190        // Compare ip2long twice for php4 backwards compat.
191        if ((ip2long($domain) == '-1' || ip2long($domain) === false) && function_exists('checkdnsrr') && !checkdnsrr($domain . '.', 'MX') && gethostbyname($domain) == $domain) {
192            return VALIDATE_EMAIL_MX_FAIL;
193        }
194
195        return VALIDATE_EMAIL_SUCCESS;
196    }
197
198    /**
199     * Verifies that date can be processed by the strtotime function.
200     *
201     * @param  string  $val The input data to validate.
202     * @return bool    True if no errors found, false otherwise.
203     */
204    function validateStrDate($val)
205    {
206        $app =& App::getInstance();
207       
208        $timestamp = strtotime($val);
209        // Return values change between php4 and php5.
210        if ('' != trim($val) && ($timestamp === -1 || $timestamp === false)) {
211            return false;
212        } else {
213            return true;
214        }
215    }
216
217
218    /**
219     * Verifies credit card number.
220     *
221     * @param  string  $val   The input data to validate..
222     * @param  string  $cc_num      Card number to verify.
223     * @param  string  $cc_type     Optional, card type to do specific checks.
224     * @return bool    True if no errors found, false otherwise.
225     */
226     function validateCCNumber($val, $cc_type=null)
227     {
228         // Get rid of any non-digits
229         $cc_num = preg_replace('/[^\d]/', '', $val);
230
231         // Perform card-specific checks, if applicable
232         switch ($cc_type) {
233             case CC_TYPE_VISA :
234                 $regex = '/^4\d{15}$|^4\d{12}$/';
235                 break;
236             case CC_TYPE_MASTERCARD :
237                 $regex = '/^5[1-5]\d{14}$/';
238                 break;
239             case CC_TYPE_AMEX :
240                 $regex = '/^3[47]\d{13}$/';
241                 break;
242             case CC_TYPE_DISCOVER :
243                 $regex = '/^6011\d{12}$/';
244                 break;
245             case CC_TYPE_DINERS :
246                 $regex = '/^30[0-5]\d{11}$|^3[68]\d{12}$/';
247                 break;
248             case CC_TYPE_JCB :
249                 $regex = '/^3\d{15}$|^2131|1800\d{11}$/';
250                 break;
251             default :
252                 $regex = '';
253                 break;
254         }
255         
256         if ('' != $regex && !preg_match($regex, $cc_num)) {
257             // Invalid format.
258             return false;
259         }
260
261         // The Luhn formula works right to left, so reverse the number.
262         $cc_num = strrev($cc_num);
263
264         $luhn_total = 0;
265
266         $num = mb_strlen($cc_num);
267         for ($i=0; $i<$num; $i++) {
268             // Get each digit.
269             $digit = mb_substr($cc_num, $i, 1);
270
271             //  If it's an odd digit, double it.
272             if ($i / 2 != floor($i / 2)) {
273                 $digit *= 2;
274             }
275
276             //  If the result is two digits, add them.
277             if (mb_strlen($digit) == 2) {
278                 $digit = mb_substr($digit, 0, 1) + mb_substr($digit, 1, 1);
279             }
280
281             //  Add the current digit to the $luhn_total.
282             $luhn_total += $digit;
283         }
284
285         // If the Total is evenly divisible by 10, it's cool!
286         return $luhn_total % 10 == 0;
287     }
288
289    /**
290     * Check whether a file was selected for uploading. If file is missing, it's an error.
291     *
292     * @param  string $form_name The input data to validate.
293     * @return bool   True if no errors found, false otherwise.
294     */
295    function fileUploaded($form_name)
296    {
297        if (!isset($_FILES[$form_name]['name']) || empty($_FILES[$form_name]['name'])) {
298            return false;
299        }
300       
301        if (is_array($_FILES[$form_name]['name'])) {
302            foreach($_FILES[$form_name]['name'] as $f) {
303                if ('' == $f) {
304                    return false;
305                }
306            }
307        } else {
308            if ('' == $_FILES[$form_name]['name']) {
309                return false;
310            }
311        }
312       
313        return true;
314    }
315
316} // THE END
317
318?>
Note: See TracBrowser for help on using the repository browser.