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

Last change on this file since 415 was 415, checked in by anonymous, 11 years ago

Disabled MX record check for email validation. Updated PEdit to work better with AcceptPathInfo? enabled.

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