validation.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: validation_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Short description for file.
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs
00023  * @since           CakePHP(tm) v 1.2.0.3830
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * Deprecated
00031  */
00032 /**
00033  * Not empty.
00034  */
00035     define('VALID_NOT_EMPTY', '/.+/');
00036 /**
00037  * Numbers [0-9] only.
00038  */
00039     define('VALID_NUMBER', '/^[-+]?\\b[0-9]*\\.?[0-9]+\\b$/');
00040 /**
00041  * A valid email address.
00042  */ 
00043     define('VALID_EMAIL', "/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2,4}|museum|travel)$/i");
00044 /**
00045  * A valid year (1000-2999).
00046  */
00047     define('VALID_YEAR', '/^[12][0-9]{3}$/');
00048 /**
00049  * Offers different validation methods.
00050  *
00051  * Long description for file
00052  *
00053  * @package    cake
00054  * @subpackage cake.cake.libs
00055  * @since      CakePHP v 1.2.0.3830
00056  */
00057 class Validation extends Object {
00058 /**
00059  * Set the the value of methods $check param.
00060  *
00061  * @var string
00062  * @access public
00063  */
00064     var $check = null;
00065 /**
00066  * Set to a valid regular expression in the class methods.
00067  * Can be set from $regex param also
00068  *
00069  * @var string
00070  * @access public
00071  */
00072     var $regex = null;
00073 /**
00074  * Some class methods use a country to determine proper validation.
00075  * This can be passed to methods in the $country param
00076  *
00077  * @var string
00078  * @access public
00079  */
00080     var $country = null;
00081 /**
00082  * Some class methods use a deeper validation when set to true
00083  *
00084  * @var string
00085  * @access public
00086  */
00087     var $deep = null;
00088 /**
00089  * Some class methods use the $type param to determine which validation to perfom in the method
00090  *
00091  * @var string
00092  * @access public
00093  */
00094     var $type = null;
00095 /**
00096  * Holds an array of errors messages set in this class.
00097  * These are used for debugging purposes
00098  *
00099  * @var array
00100  * @access public
00101  */
00102     var $errors = array();
00103 /**
00104  * Gets a reference to the Validation object instance
00105  *
00106  * @return object Validation instance
00107  * @access public
00108  * @static
00109  */
00110     function &getInstance() {
00111         static $instance = array();
00112 
00113         if (!isset($instance[0]) || !$instance[0]) {
00114             $instance[0] =& new Validation();
00115         }
00116         return $instance[0];
00117     }
00118 /**
00119  * Checks that a string contains only integer or letters
00120  *
00121  * Returns true if string contains only integer or letters
00122  *
00123  * $check can be passed as an array:
00124  * array('check' => 'valueToCheck');
00125  *
00126  * @param mixed $check Value to check
00127  * @return boolean Success
00128  * @access public
00129  */
00130     function alphaNumeric($check) {
00131         $_this =& Validation::getInstance();
00132         $_this->__reset();
00133         $_this->check = $check;
00134 
00135         if (is_array($check)) {
00136             $_this->_extract($check);
00137         }
00138 
00139         if (empty($_this->check) && $_this->check != '0') {
00140             return false;
00141         }
00142 
00143         $_this->regex = '/[^\\dA-Z]/i';
00144         if ($_this->_check() === true) {
00145             return false;
00146         } else {
00147             return true;
00148         }
00149     }
00150 /**
00151  * Checks that a string length is within s specified range.
00152  * Spaces are included in the character count.
00153  * Returns true is string matches value min, max, or between min and max,
00154  *
00155  * @param string $check Value to check for length
00156  * @param integer $min Minimum value in range (inclusive)
00157  * @param integer $max Maximum value in range (inclusive)
00158  * @return boolean Success
00159  * @access public
00160  */
00161     function between($check, $min, $max) {
00162         $length = strlen($check);
00163 
00164         if ($length >= $min && $length <= $max) {
00165             return true;
00166         } else {
00167             return false;
00168         }
00169     }
00170 /**
00171  * Returns true if field is left blank -OR- only whitespace characters are present in it's value
00172  * Whitespace characters include Space, Tab, Carriage Return, Newline
00173  *
00174  * $check can be passed as an array:
00175  * array('check' => 'valueToCheck');
00176  *
00177  * @param mixed $check Value to check
00178  * @return boolean Success
00179  * @access public
00180  */
00181     function blank($check) {
00182         $_this =& Validation::getInstance();
00183         $_this->__reset();
00184         $_this->check = $check;
00185 
00186         if (is_array($check)) {
00187             $_this->_extract($check);
00188         }
00189 
00190         $_this->regex = '/[^\\s]/';
00191         if ($_this->_check() === true) {
00192             return false;
00193         } else {
00194             return true;
00195         }
00196     }
00197 /**
00198  * Validation of credit card numbers.
00199  * Returns true if $check is in the proper credit card format.
00200  *
00201  * @param mixed $check credit card number to validate
00202  * @param mixed $type 'all' may be passed as a sting, defaults to fast which checks format of most major credit cards
00203  *                          if an array is used only the values of the array are checked.
00204  *                          Example: array('amex', 'bankcard', 'maestro')
00205  * @param boolean $deep set to true this will check the Luhn algorithm of the credit card.
00206  * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values
00207  * @return boolean Success
00208  * @access public
00209  * @see Validation::_luhn()
00210  */
00211     function cc($check, $type = 'fast', $deep = false, $regex = null) {
00212         $_this =& Validation::getInstance();
00213         $_this->__reset();
00214         $_this->check = $check;
00215         $_this->type = $type;
00216         $_this->deep = $deep;
00217         $_this->regex = $regex;
00218 
00219         if (is_array($check)) {
00220             $_this->_extract($check);
00221         }
00222         $_this->check = str_replace(array('-', ' '), '', $_this->check);
00223 
00224         if (strlen($_this->check) < 13) {
00225             return false;
00226         }
00227 
00228         if (!is_null($_this->regex)) {
00229             if ($_this->_check()) {
00230                 return $_this->_luhn();
00231             }
00232         }
00233         $cards = array('all' => array('amex' => '/^3[4|7]\\d{13}$/',
00234                                     'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
00235                                     'diners'   => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
00236                                     'disc'     => '/^(?:6011|650\\d)\\d{12}$/',
00237                                     'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
00238                                     'enroute'  => '/^2(?:014|149)\\d{11}$/',
00239                                     'jcb'      => '/^(3\\d{4}|2100|1800)\\d{11}$/',
00240                                     'maestro'  => '/^(?:5020|6\\d{3})\\d{12}$/',
00241                                     'mc'       => '/^5[1-5]\\d{14}$/',
00242                                     'solo'     => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
00243                                     'switch'   => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
00244                                     'visa'     => '/^4\\d{12}(\\d{3})?$/',
00245                                     'voyager'  => '/^8699[0-9]{11}$/'),
00246                             'fast'   => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/');
00247 
00248         if (is_array($_this->type)) {
00249             foreach ($_this->type as $key => $value) {
00250                 $card = strtolower($value);
00251                 $_this->regex = $cards['all'][$card];
00252 
00253                 if ($_this->_check()) {
00254                     return $_this->_luhn();
00255                 }
00256             }
00257         } else {
00258             if ($_this->type == 'all') {
00259                 foreach ($cards['all'] as $key => $value) {
00260                     $_this->regex = $value;
00261 
00262                     if ($_this->_check()) {
00263                         return $_this->_luhn();
00264                     }
00265                 }
00266             } else {
00267                 $_this->regex = $cards['fast'];
00268 
00269                 if ($_this->_check()) {
00270                     return $_this->_luhn();
00271                 }
00272             }
00273         }
00274     }
00275 /**
00276  * Used to compare 2 numeric values.
00277  *
00278  * @param mixed $check1 if string is passed for a string must also be passed for $check2
00279  *                          used as an array it must be passed as array('check1' => value, 'operator' => 'value', 'check2' -> value)
00280  * @param string $operator Can be either a word or operand
00281  *                              is greater >, is less <, greater or equal >=
00282  *                              less or equal <=, is less <, equal to ==, not equal !=
00283  * @param integer $check2 only needed if $check1 is a string
00284  * @return bool
00285  * @access public
00286  */
00287     function comparison($check1, $operator = null, $check2 = null) {
00288         $return = false;
00289         if (is_array($check1)) {
00290             extract($check1, EXTR_OVERWRITE);
00291         }
00292         $operator = str_replace(array(" ", "\t", "\n", "\r", "\0", "\x0B"), "", strtolower($operator));
00293 
00294         switch($operator) {
00295             case 'isgreater':
00296             case '>':
00297                 if ($check1 > $check2) {
00298                     $return = true;
00299                 }
00300             break;
00301             case 'isless':
00302             case '<':
00303                 if ($check1 < $check2) {
00304                     $return = true;
00305                 }
00306             break;
00307             case 'greaterorequal':
00308             case '>=':
00309                 if ($check1 >= $check2) {
00310                     $return = true;
00311                 }
00312             break;
00313             case 'lessorequal':
00314             case '<=':
00315                 if ($check1 <= $check2) {
00316                     $return = true;
00317                 }
00318             break;
00319             case 'equalto':
00320             case '==':
00321                 if ($check1 == $check2) {
00322                     $return = true;
00323                 }
00324             break;
00325             case 'notequal':
00326             case '!=':
00327                 if ($check1 != $check2) {
00328                     $return = true;
00329                 }
00330             break;
00331             default:
00332                 $_this =& Validation::getInstance();
00333                 $_this->errors[] = __('You must define the $operator parameter for Validation::comparison()', true);
00334                 $return = false;
00335             break;
00336         }
00337         return $return;
00338     }
00339 /**
00340  * Used when a custom regular expression is needed.
00341  *
00342  * @param mixed $check When used as a string, $regex must also be a valid regular expression.
00343  *                              As and array: array('check' => value, 'regex' => 'valid regular expression')
00344  * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression
00345  * @return boolean Success
00346  * @access public
00347  */
00348     function custom($check, $regex = null) {
00349         $_this =& Validation::getInstance();
00350         $_this->__reset();
00351         $_this->check = $check;
00352         $_this->regex = $regex;
00353         if (is_array($check)) {
00354             $_this->_extract($check);
00355         }
00356         if ($_this->regex === null) {
00357             $_this->errors[] = __('You must define a regular expression for Validation::custom()', true);
00358             return false;
00359         }
00360         return $_this->_check();
00361     }
00362 /**
00363  * Date validation, determines if the string passed is a valid date.
00364  * keys that expect full month, day and year will validate leap years
00365  *
00366  * @param string $check a valid date string
00367  * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc)
00368  *                  Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
00369  *                          mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
00370  *                          ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
00371  *                          dMy 27 December 2006 or 27 Dec 2006
00372  *                          Mdy December 27, 2006 or Dec 27, 2006 comma is optional
00373  *                          My December 2006 or Dec 2006
00374  *                          my 12/2006 or 12/06 separators can be a space, period, dash, forward slash
00375  * @param string $regex If a custom regular expression is used this is the only validation that will occur.
00376  * @return boolean Success
00377  * @access public
00378  */
00379     function date($check, $format = 'ymd', $regex = null) {
00380         $_this =& Validation::getInstance();
00381         $_this->__reset();
00382         $_this->check = $check;
00383         $_this->regex = $regex;
00384 
00385         if (!is_null($_this->regex)) {
00386             return $_this->_check();
00387         }
00388 
00389         $search = array();
00390 
00391         if (is_array($format)) {
00392             foreach ($format as $key => $value) {
00393                 $search[$value] = $value;
00394             }
00395         } else {
00396             $search[$format] = $format;
00397         }
00398         $regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.|\\x20)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/|-|\\.|\\x20)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.|\\x20)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
00399         $regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])(\\/|-|\\.|\\x20)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2(\\/|-|\\.|\\x20)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.|\\x20)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
00400         $regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\\/|-|\\.|\\x20)(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})(\\/|-|\\.|\\x20)(?:(?:(?:0?[13578]|1[02])\\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\\2(?:0?[1-9]|1\\d|2[0-8]))))$%';
00401         $regex['dMy'] = '/^((31(?!\\ (Feb(ruary)?|Apr(il)?|June?|(Sep(?=\\b|t)t?|Nov)(ember)?)))|((30|29)(?!\\ Feb(ruary)?))|(29(?=\\ Feb(ruary)?\\ (((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\\d|2[0-8])\\ (Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)\\ ((1[6-9]|[2-9]\\d)\\d{2})$/';
00402         $regex['Mdy'] = '/^(?:(((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?)\\ 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)\\ (0?[1-9]|([12]\\d)|30))|(Feb(ruary)?\\ (0?[1-9]|1\\d|2[0-8]|(29(?=,?\\ ((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))))\\,?\\ ((1[6-9]|[2-9]\\d)\\d{2}))$/';
00403         $regex['My'] = '%^(Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sep(?=\\b|t)t?|Nov|Dec)(ember)?)[ /]((1[6-9]|[2-9]\\d)\\d{2})$%';
00404         $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
00405 
00406         foreach ($search as $key) {
00407             $_this->regex = $regex[$key];
00408 
00409             if ($_this->_check() === true) {
00410                 return true;
00411             }
00412         }
00413         return false;
00414     }
00415 
00416 /**
00417  * Time validation, determines if the string passed is a valid time.
00418  * Validates time as 24hr (HH:MM) or am/pm ([H]H:MM[a|p]m)
00419  * Does not allow/validate seconds.
00420  *
00421  * @param string $check a valid time string
00422  * @return boolean Success
00423  * @access public
00424  */
00425 
00426     function time($check) {
00427         $_this =& Validation::getInstance();
00428         $_this->__reset();
00429         $_this->check = $check;
00430         $_this->regex = '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%';
00431         return $_this->_check();
00432     }
00433 
00434 /**
00435  * Boolean validation, determines if value passed is a boolean integer or true/false.
00436  *
00437  * @param string $check a valid boolean
00438  * @return boolean Success
00439  * @access public
00440  */
00441     function boolean($check) {
00442         $booleanList = array(0,1,'0','1',true,false);
00443         return in_array($check, $booleanList, true);
00444     }
00445 
00446 /**
00447  * Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
00448  * If no decimal point is found a false will be returned. Both the sign and exponent are optional.
00449  *
00450  * @param integer $check The value the test for decimal
00451  * @param integer $places if set $check value must have exactly $places after the decimal point
00452  * @param string $regex If a custom regular expression is used this is the only validation that will occur.
00453  * @return boolean Success
00454  * @access public
00455  */
00456     function decimal($check, $places = null, $regex = null) {
00457         $_this =& Validation::getInstance();
00458         $_this->__reset();
00459         $_this->regex = $regex;
00460         $_this->check = $check;
00461 
00462         if (!is_null($_this->regex)) {
00463             return $_this->_check();
00464         }
00465 
00466         if (is_null($places)) {
00467             $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
00468             return $_this->_check();
00469         }
00470 
00471         $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{'.$places.'}$/';
00472         return $_this->_check();
00473     }
00474 /**
00475  * Validates for an email address.
00476  *
00477  * @param string $check Value to check
00478  * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host
00479  * @param string $regex Regex to use (if none it will use built in regex)
00480  * @return boolean Success
00481  * @access public
00482  */
00483     function email($check, $deep = false, $regex = null) {
00484         $_this =& Validation::getInstance();
00485         $_this->__reset();
00486         $_this->check = $check;
00487         $_this->regex = $regex;
00488         $_this->deep = $deep;
00489 
00490         if (is_array($check)) {
00491             $_this->_extract($check);
00492         }
00493 
00494         if (is_null($_this->regex)) {
00495             $_this->regex = "/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2,4}|museum|travel)$/i";
00496         }
00497         $return = $_this->_check();
00498 
00499         if ($_this->deep === false || $_this->deep === null) {
00500             return $return;
00501         }
00502 
00503         if ($return === true && preg_match('/@([a-z0-9][a-z0-9\\.\\-]{0,63}\\.([a-z]*))/', $_this->check, $regs)) {
00504             $host = gethostbynamel($regs[1]);
00505             if (is_array($host)) {
00506                 return true;
00507             }
00508         }
00509         return false;
00510     }
00511 /**
00512  * Check that value is exactly $comparedTo.
00513  *
00514  * @param mixed $check Value to check
00515  * @param mixed $comparedTo Value to compare
00516  * @access public
00517  */
00518     function equalTo($check, $comparedTo) {
00519         return ($check === $comparedTo);
00520     }
00521 /**
00522  * Check that value has a valid file extension.
00523  *
00524  * @param mixed $check Value to check
00525  * @param array $extensions file extenstions to allow
00526  * @access public
00527  */
00528     function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
00529         if (is_array($check)) {
00530             foreach ($check as $value) {
00531                 if (Validation::extension($value, $extensions) === false) {
00532                     return false;
00533                 }
00534                 return true;
00535             }
00536         }
00537         $extension = strtolower(array_pop(explode('.', $check)));
00538 
00539         if (in_array($extension, array_map('strtolower', $extensions))) {
00540             return true;
00541         }
00542         return false;
00543     }
00544 /**
00545  * Check that value is a file name
00546  *
00547  * @param mixed $check Value to check
00548  * @access public
00549  */
00550     function file($check) {
00551         // if (is_array($check)) {
00552         //  foreach ($check as $value) {
00553         //      if (!Validation::file($value)) {
00554         //          return false;
00555         //      }
00556         //  }
00557         //  return true;
00558         // }
00559         // 
00560         // return preg_match('/[\w| |_]+\.[\w]+/', $check);
00561     }
00562 /**
00563  * Validation of an IPv4 address.
00564  *
00565  * @param string $check The string to test.
00566  * @return boolean Success
00567  * @access public
00568  */
00569     function ip($check) {
00570         $bytes = explode('.', $check);
00571         if (count($bytes) == 4) {
00572             foreach ($bytes as $byte) {
00573                 if (!(is_numeric($byte) && $byte >= 0 && $byte <= 255)) {
00574                     return false;
00575                 }
00576             }
00577             return true;
00578         }
00579         return false;
00580     }
00581 /**
00582  * Checks whether the length of a string is greater or equal to a minimal length.
00583  *
00584  * @param string $check The string to test
00585  * @param integer $min The minimal string length
00586  * @return boolean Success
00587  * @access public
00588  */
00589     function minLength($check, $min) {
00590         $length = strlen($check);
00591         return ($length >= $min);
00592     }
00593 /**
00594  * Checks whether the length of a string is smaller or equal to a maximal length..
00595  *
00596  * @param string $check The string to test
00597  * @param integer $max The maximal string length
00598  * @return boolean Success
00599  * @access public
00600  */
00601     function maxLength($check, $max) {
00602         $length = strlen($check);
00603         return ($length <= $max);
00604     }
00605 /**
00606  * Checks that a value is a monetary amount.
00607  *
00608  * @param string $check Value to check
00609  * @param string $symbolPosition Where symbol is located (left/right)
00610  * @return boolean Success
00611  * @access public
00612  */
00613     function money($check, $symbolPosition = 'left') {
00614         $_this =& Validation::getInstance();
00615         $_this->check = $check;
00616 
00617         switch ($symbolPosition) {
00618             case 'left':
00619                 $_this->regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';
00620             break;
00621             case 'right':
00622                 $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u';
00623             break;
00624         }
00625         return $_this->_check();
00626     }
00627 /**
00628  * Validate a multiple select.
00629  *
00630  * @param mixed $check Value to check
00631  * @param mixed $type Type of check
00632  * @param string $regex Use custom regular expression
00633  * @access public
00634  * @todo Implement
00635  */
00636     function multiple($check, $type, $regex = null) {
00637         //Validate a select object for a selected index past 0.
00638         //Validate a select against a list of restriced indexes.
00639         //Validate a multiple-select for the quantity selected.
00640     }
00641 /**
00642  * Checks if a value is numeric.
00643  *
00644  * @param string $check Value to check
00645  * @return boolean Succcess
00646  * @access public
00647  */
00648     function numeric($check) {
00649         return is_numeric($check);
00650     }
00651 /**
00652  * Check that a value is a valid phone number.
00653  *
00654  * @param mixed $check Value to check (string or array)
00655  * @param string $regex Regular expression to use
00656  * @param string $country Country code (defaults to 'all')
00657  * @return boolean Success
00658  * @access public
00659  */
00660     function phone($check, $regex = null, $country = 'all') {
00661         $_this =& Validation::getInstance();
00662         if (is_array($check)) {
00663             $_this->_extract($check);
00664         } else {
00665             $_this->check = $check;
00666             $_this->regex = $regex;
00667             $_this->country = $country;
00668         }
00669 
00670         if (is_null($_this->regex)) {
00671             switch ($_this->country) {
00672                 case 'us':
00673                 default:
00674                     $_this->regex  = '/^1?[-. ]?\\(?([0-9]{3})\\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/';
00675                 break;
00676             }
00677         }
00678         return $_this->_check();
00679     }
00680 /**
00681  * Checks that a given value is a valid postal code.
00682  *
00683  * @param mixed $check Value to check
00684  * @param string $regex Regular expression to use
00685  * @param string $country Country to use for formatting
00686  * @return boolean Success
00687  * @access public
00688  */
00689     function postal($check, $regex = null, $country = null) {
00690         $_this =& Validation::getInstance();
00691         if (is_array($check)) {
00692             $_this->_extract($check);
00693         } else {
00694             $_this->check = $check;
00695             $_this->regex = $regex;
00696             $_this->country = $country;
00697         }
00698 
00699         if (is_null($_this->regex)) {
00700             switch ($_this->country) {
00701                 case 'uk':
00702                     $_this->regex  = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
00703                 break;
00704                 case 'ca':
00705                     $_this->regex  = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]\\b\\z/i';
00706                 break;
00707                 case 'it':
00708                 case 'de':
00709                     $_this->regex  = '/^[0-9]{5}$/i';
00710                 break;
00711                 case 'us':
00712                 default:
00713                     $_this->regex  = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
00714                 break;
00715                 case 'be':
00716                     $_this->regex  = '/^[1-9]{1}[0-9]{3}$/i';
00717                 break;
00718             }
00719         }
00720         return $_this->_check();
00721     }
00722 /**
00723  * Validate that a number is in specified range.
00724  * if $lower and $upper are not set, will return true if
00725  * $check is a legal finite on this platform
00726  *
00727  * @param string $check Value to check
00728  * @param integer $lower Lower limit
00729  * @param integer $upper Upper limit
00730  * @access public
00731  */
00732     function range($check, $lower = null, $upper = null ) {
00733         if (!is_numeric($check)) {
00734             return false;
00735         }
00736         if (isset($lower) && isset($upper)) {
00737             if ($lower > $upper) {
00738                 return false;
00739             }
00740             if ($check > $lower && $check < $upper) {
00741                 return true;
00742             }
00743         } elseif (is_finite($check)) {
00744             return true;
00745         }
00746         return false;
00747     }
00748 /**
00749  * Checks that a value is a valid Social Security Number.
00750  *
00751  * @param mixed $check Value to check
00752  * @param string $regex Regular expression to use
00753  * @param string $country Country
00754  * @return boolean Success
00755  * @access public
00756  */
00757     function ssn($check, $regex = null, $country = null) {
00758         $_this =& Validation::getInstance();
00759         if (is_array($check)) {
00760             $_this->_extract($check);
00761         } else {
00762             $_this->check = $check;
00763             $_this->regex = $regex;
00764             $_this->country = $country;
00765         }
00766 
00767         if (is_null($_this->regex)) {
00768             switch ($_this->country) {
00769                 case 'dk':
00770                     $_this->regex  = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
00771                 break;
00772                 case 'nl':
00773                     $_this->regex  = '/\\A\\b[0-9]{9}\\b\\z/i';
00774                 break;
00775                 case 'us':
00776                 default:
00777                     $_this->regex  = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
00778                 break;
00779             }
00780         }
00781         return $_this->_check();
00782     }
00783 /**
00784  * Checks that a value is a valid URL.
00785  *
00786  * @param string $check Value to check
00787  * @return boolean Success
00788  * @access public
00789  */
00790     function url($check) {
00791         $_this =& Validation::getInstance();
00792         $_this->check = $check;
00793         $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\\/\\/)?(?:(?:(?:25[0-5]|2[0-4]\d|(?:(?:1\d)?|[1-9]?)\d)\.){3}(?:25[0-5]|2[0-4]\d|(?:(?:1\d)?|[1-9]?)\d)'
00794                             . '|(?:[0-9a-z]{1}[0-9a-z\\-]*\\.)*(?:[0-9a-z]{1}[0-9a-z\\-]{0,62})\\.(?:[a-z]{2,6}|[a-z]{2}\\.[a-z]{2,6})'
00795                             . '(?::[0-9]{1,4})?)(?:\\/?|\\/[\\w\\-\\.,\'@?^=%&:;\/~\\+#]*[\\w\\-\\@?^=%&\/~\\+#])$/i';
00796         return $_this->_check();
00797     }
00798 /**
00799  * Checks if a value is in a given list.
00800  *
00801  * @param string $check Value to check
00802  * @param array $list List to check against
00803  * @return boolean Succcess
00804  * @access public
00805  */
00806     function inList($check, $list) {
00807         return in_array($check, $list);
00808     }
00809 /**
00810  * Runs an user-defined validation.
00811  *
00812  * @param mixed $check value that will be validated in user-defined methods.
00813  * @param object $object class that holds validation method
00814  * @param string $method class method name for validation to run
00815  * @param array $args arguments to send to method
00816  * @return mixed user-defined class class method returns
00817  * @access public
00818  */
00819     function userDefined($check, $object, $method, $args = null) {
00820         return call_user_func_array(array(&$object, $method), array($check, $args));
00821     }
00822 /**
00823  * Runs a regular expression match.
00824  *
00825  * @return boolean Success of match
00826  * @access protected
00827  */
00828     function _check() {
00829         $_this =& Validation::getInstance();
00830         if (preg_match($_this->regex, $_this->check)) {
00831             $_this->error[] = false;
00832             return true;
00833         } else {
00834             $_this->error[] = true;
00835             return false;
00836         }
00837     }
00838 /**
00839  * Get the values to use when value sent to validation method is
00840  * an array.
00841  *
00842  * @param array $params Parameters sent to validation method
00843  * @access protected
00844  */
00845     function _extract($params) {
00846         $_this =& Validation::getInstance();
00847         extract($params, EXTR_OVERWRITE);
00848 
00849         if (isset($check)) {
00850             $_this->check = $check;
00851         }
00852         if (isset($regex)) {
00853             $_this->regex = $regex;
00854         }
00855         if (isset($country)) {
00856             $_this->country = strtolower($country);
00857         }
00858         if (isset($deep)) {
00859             $_this->deep = $deep;
00860         }
00861         if (isset($type)) {
00862             $_this->type = $type;
00863         }
00864     }
00865 /**
00866  * Luhn algorithm
00867  *
00868  * @see http://en.wikipedia.org/wiki/Luhn_algorithm
00869  * @return boolean Success
00870  * @access protected
00871  */
00872     function _luhn() {
00873         $_this =& Validation::getInstance();
00874         if ($_this->deep === true) {
00875             if ($_this->check == 0) {
00876                 return false;
00877             }
00878             $sum = 0;
00879             $length = strlen($_this->check);
00880 
00881             for ($position = 1 - ($length % 2); $position < $length; $position += 2) {
00882                 $sum += substr($_this->check, $position, 1);
00883             }
00884 
00885             for ($position = ($length % 2); $position < $length; $position += 2) {
00886                 $number = substr($_this->check, $position, 1) * 2;
00887                 if ($number < 10) {
00888                     $sum += $number;
00889                 } else {
00890                     $sum += $number - 9;
00891                 }
00892             }
00893 
00894             if ($sum % 10 != 0) {
00895                 return false;
00896             }
00897         }
00898         return true;
00899     }
00900 /**
00901  * Reset internal variables for another validation run.
00902  *
00903  * @access private
00904  */
00905     function __reset() {
00906         $_this =& Validation::getInstance();
00907         $_this->check = null;
00908         $_this->regex = null;
00909         $_this->country = null;
00910         $_this->deep = null;
00911         $_this->type = null;
00912     }
00913 }
00914 ?>