PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/validation.php

https://github.com/hardsshah/bookmarks
PHP | 928 lines | 475 code | 36 blank | 417 comment | 84 complexity | 1aecce743ea33a0920ac6e44d0e6dc51 MD5 | raw file
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Validation Class. Used for validation of model data
  5. *
  6. * Long description for file
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
  11. * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  12. *
  13. * Licensed under The MIT License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @filesource
  17. * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  18. * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
  19. * @package cake
  20. * @subpackage cake.cake.libs
  21. * @since CakePHP(tm) v 1.2.0.3830
  22. * @version $Revision$
  23. * @modifiedby $LastChangedBy$
  24. * @lastmodified $Date$
  25. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  26. */
  27. /**
  28. * Deprecated
  29. */
  30. /**
  31. * Not empty.
  32. */
  33. define('VALID_NOT_EMPTY', '/.+/');
  34. /**
  35. * Numbers [0-9] only.
  36. */
  37. define('VALID_NUMBER', '/^[-+]?\\b[0-9]*\\.?[0-9]+\\b$/');
  38. /**
  39. * A valid email address.
  40. */
  41. 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");
  42. /**
  43. * A valid year (1000-2999).
  44. */
  45. define('VALID_YEAR', '/^[12][0-9]{3}$/');
  46. /**
  47. * Offers different validation methods.
  48. *
  49. * Long description for file
  50. *
  51. * @package cake
  52. * @subpackage cake.cake.libs
  53. * @since CakePHP v 1.2.0.3830
  54. */
  55. class Validation extends Object {
  56. /**
  57. * Set the the value of methods $check param.
  58. *
  59. * @var string
  60. * @access public
  61. */
  62. var $check = null;
  63. /**
  64. * Set to a valid regular expression in the class methods.
  65. * Can be set from $regex param also
  66. *
  67. * @var string
  68. * @access public
  69. */
  70. var $regex = null;
  71. /**
  72. * Some complex patterns needed in multiple places
  73. *
  74. * @var array
  75. * @access private
  76. */
  77. var $__pattern = array(
  78. 'ip' => '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])',
  79. 'hostname' => '(?:[a-z0-9][-a-z0-9]*\.)*(?:[a-z0-9][-a-z0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,4}|museum|travel)'
  80. );
  81. /**
  82. * Some class methods use a country to determine proper validation.
  83. * This can be passed to methods in the $country param
  84. *
  85. * @var string
  86. * @access public
  87. */
  88. var $country = null;
  89. /**
  90. * Some class methods use a deeper validation when set to true
  91. *
  92. * @var string
  93. * @access public
  94. */
  95. var $deep = null;
  96. /**
  97. * Some class methods use the $type param to determine which validation to perfom in the method
  98. *
  99. * @var string
  100. * @access public
  101. */
  102. var $type = null;
  103. /**
  104. * Holds an array of errors messages set in this class.
  105. * These are used for debugging purposes
  106. *
  107. * @var array
  108. * @access public
  109. */
  110. var $errors = array();
  111. /**
  112. * Gets a reference to the Validation object instance
  113. *
  114. * @return object Validation instance
  115. * @access public
  116. * @static
  117. */
  118. function &getInstance() {
  119. static $instance = array();
  120. if (!$instance) {
  121. $instance[0] =& new Validation();
  122. }
  123. return $instance[0];
  124. }
  125. /**
  126. * Checks that a string contains something other than whitespace
  127. *
  128. * Returns true if string contains something other than whitespace
  129. *
  130. * $check can be passed as an array:
  131. * array('check' => 'valueToCheck');
  132. *
  133. * @param mixed $check Value to check
  134. * @return boolean Success
  135. * @access public
  136. */
  137. function notEmpty($check) {
  138. $_this =& Validation::getInstance();
  139. $_this->__reset();
  140. $_this->check = $check;
  141. if (is_array($check)) {
  142. $_this->_extract($check);
  143. }
  144. if (empty($_this->check) && $_this->check != '0') {
  145. return false;
  146. }
  147. $_this->regex = '/[^\s]+/m';
  148. return $_this->_check();
  149. }
  150. /**
  151. * Checks that a string contains only integer or letters
  152. *
  153. * Returns true if string contains only integer or letters
  154. *
  155. * $check can be passed as an array:
  156. * array('check' => 'valueToCheck');
  157. *
  158. * @param mixed $check Value to check
  159. * @return boolean Success
  160. * @access public
  161. */
  162. function alphaNumeric($check) {
  163. $_this =& Validation::getInstance();
  164. $_this->__reset();
  165. $_this->check = $check;
  166. if (is_array($check)) {
  167. $_this->_extract($check);
  168. }
  169. if (empty($_this->check) && $_this->check != '0') {
  170. return false;
  171. }
  172. $_this->regex = '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu';
  173. return $_this->_check();
  174. }
  175. /**
  176. * Checks that a string length is within s specified range.
  177. * Spaces are included in the character count.
  178. * Returns true is string matches value min, max, or between min and max,
  179. *
  180. * @param string $check Value to check for length
  181. * @param integer $min Minimum value in range (inclusive)
  182. * @param integer $max Maximum value in range (inclusive)
  183. * @return boolean Success
  184. * @access public
  185. */
  186. function between($check, $min, $max) {
  187. $length = strlen($check);
  188. return ($length >= $min && $length <= $max);
  189. }
  190. /**
  191. * Returns true if field is left blank -OR- only whitespace characters are present in it's value
  192. * Whitespace characters include Space, Tab, Carriage Return, Newline
  193. *
  194. * $check can be passed as an array:
  195. * array('check' => 'valueToCheck');
  196. *
  197. * @param mixed $check Value to check
  198. * @return boolean Success
  199. * @access public
  200. */
  201. function blank($check) {
  202. $_this =& Validation::getInstance();
  203. $_this->__reset();
  204. $_this->check = $check;
  205. if (is_array($check)) {
  206. $_this->_extract($check);
  207. }
  208. $_this->regex = '/[^\\s]/';
  209. return !$_this->_check();
  210. }
  211. /**
  212. * Validation of credit card numbers.
  213. * Returns true if $check is in the proper credit card format.
  214. *
  215. * @param mixed $check credit card number to validate
  216. * @param mixed $type 'all' may be passed as a sting, defaults to fast which checks format of most major credit cards
  217. * if an array is used only the values of the array are checked.
  218. * Example: array('amex', 'bankcard', 'maestro')
  219. * @param boolean $deep set to true this will check the Luhn algorithm of the credit card.
  220. * @param string $regex A custom regex can also be passed, this will be used instead of the defined regex values
  221. * @return boolean Success
  222. * @access public
  223. * @see Validation::_luhn()
  224. */
  225. function cc($check, $type = 'fast', $deep = false, $regex = null) {
  226. $_this =& Validation::getInstance();
  227. $_this->__reset();
  228. $_this->check = $check;
  229. $_this->type = $type;
  230. $_this->deep = $deep;
  231. $_this->regex = $regex;
  232. if (is_array($check)) {
  233. $_this->_extract($check);
  234. }
  235. $_this->check = str_replace(array('-', ' '), '', $_this->check);
  236. if (strlen($_this->check) < 13) {
  237. return false;
  238. }
  239. if (!is_null($_this->regex)) {
  240. if ($_this->_check()) {
  241. return $_this->_luhn();
  242. }
  243. }
  244. $cards = array('all' => array('amex' => '/^3[4|7]\\d{13}$/',
  245. 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
  246. 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
  247. 'disc' => '/^(?:6011|650\\d)\\d{12}$/',
  248. 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
  249. 'enroute' => '/^2(?:014|149)\\d{11}$/',
  250. 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/',
  251. 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
  252. 'mc' => '/^5[1-5]\\d{14}$/',
  253. 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
  254. '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})?)$/',
  255. 'visa' => '/^4\\d{12}(\\d{3})?$/',
  256. 'voyager' => '/^8699[0-9]{11}$/'),
  257. '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})$/');
  258. if (is_array($_this->type)) {
  259. foreach ($_this->type as $value) {
  260. $_this->regex = $cards['all'][strtolower($value)];
  261. if ($_this->_check()) {
  262. return $_this->_luhn();
  263. }
  264. }
  265. } elseif ($_this->type == 'all') {
  266. foreach ($cards['all'] as $value) {
  267. $_this->regex = $value;
  268. if ($_this->_check()) {
  269. return $_this->_luhn();
  270. }
  271. }
  272. } else {
  273. $_this->regex = $cards['fast'];
  274. if ($_this->_check()) {
  275. return $_this->_luhn();
  276. }
  277. }
  278. }
  279. /**
  280. * Used to compare 2 numeric values.
  281. *
  282. * @param mixed $check1 if string is passed for a string must also be passed for $check2
  283. * used as an array it must be passed as array('check1' => value, 'operator' => 'value', 'check2' -> value)
  284. * @param string $operator Can be either a word or operand
  285. * is greater >, is less <, greater or equal >=
  286. * less or equal <=, is less <, equal to ==, not equal !=
  287. * @param integer $check2 only needed if $check1 is a string
  288. * @return boolean Success
  289. * @access public
  290. */
  291. function comparison($check1, $operator = null, $check2 = null) {
  292. if (is_array($check1)) {
  293. extract($check1, EXTR_OVERWRITE);
  294. }
  295. $operator = str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', strtolower($operator));
  296. switch ($operator) {
  297. case 'isgreater':
  298. case '>':
  299. if ($check1 > $check2) {
  300. return true;
  301. }
  302. break;
  303. case 'isless':
  304. case '<':
  305. if ($check1 < $check2) {
  306. return true;
  307. }
  308. break;
  309. case 'greaterorequal':
  310. case '>=':
  311. if ($check1 >= $check2) {
  312. return true;
  313. }
  314. break;
  315. case 'lessorequal':
  316. case '<=':
  317. if ($check1 <= $check2) {
  318. return true;
  319. }
  320. break;
  321. case 'equalto':
  322. case '==':
  323. if ($check1 == $check2) {
  324. return true;
  325. }
  326. break;
  327. case 'notequal':
  328. case '!=':
  329. if ($check1 != $check2) {
  330. return true;
  331. }
  332. break;
  333. default:
  334. $_this =& Validation::getInstance();
  335. $_this->errors[] = __('You must define the $operator parameter for Validation::comparison()', true);
  336. break;
  337. }
  338. return false;
  339. }
  340. /**
  341. * Used when a custom regular expression is needed.
  342. *
  343. * @param mixed $check When used as a string, $regex must also be a valid regular expression.
  344. * As and array: array('check' => value, 'regex' => 'valid regular expression')
  345. * @param string $regex If $check is passed as a string, $regex must also be set to valid regular expression
  346. * @return boolean Success
  347. * @access public
  348. */
  349. function custom($check, $regex = null) {
  350. $_this =& Validation::getInstance();
  351. $_this->__reset();
  352. $_this->check = $check;
  353. $_this->regex = $regex;
  354. if (is_array($check)) {
  355. $_this->_extract($check);
  356. }
  357. if ($_this->regex === null) {
  358. $_this->errors[] = __('You must define a regular expression for Validation::custom()', true);
  359. return false;
  360. }
  361. return $_this->_check();
  362. }
  363. /**
  364. * Date validation, determines if the string passed is a valid date.
  365. * keys that expect full month, day and year will validate leap years
  366. *
  367. * @param string $check a valid date string
  368. * @param mixed $format Use a string or an array of the keys below. Arrays should be passed as array('dmy', 'mdy', etc)
  369. * Keys: dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
  370. * mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
  371. * ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
  372. * dMy 27 December 2006 or 27 Dec 2006
  373. * Mdy December 27, 2006 or Dec 27, 2006 comma is optional
  374. * My December 2006 or Dec 2006
  375. * my 12/2006 separators can be a space, period, dash, forward slash
  376. * @param string $regex If a custom regular expression is used this is the only validation that will occur.
  377. * @return boolean Success
  378. * @access public
  379. */
  380. function date($check, $format = 'ymd', $regex = null) {
  381. $_this =& Validation::getInstance();
  382. $_this->__reset();
  383. $_this->check = $check;
  384. $_this->regex = $regex;
  385. if (!is_null($_this->regex)) {
  386. return $_this->_check();
  387. }
  388. $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})$%';
  389. $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})$%';
  390. $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]))))$%';
  391. $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})$/';
  392. $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}))$/';
  393. $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})$%';
  394. $regex['my'] = '%^(((0[123456789]|10|11|12)([- /.])(([1][9][0-9][0-9])|([2][0-9][0-9][0-9]))))$%';
  395. $format = (is_array($format)) ? array_values($format) : array($format);
  396. foreach ($format as $key) {
  397. $_this->regex = $regex[$key];
  398. if ($_this->_check() === true) {
  399. return true;
  400. }
  401. }
  402. return false;
  403. }
  404. /**
  405. * Time validation, determines if the string passed is a valid time.
  406. * Validates time as 24hr (HH:MM) or am/pm ([H]H:MM[a|p]m)
  407. * Does not allow/validate seconds.
  408. *
  409. * @param string $check a valid time string
  410. * @return boolean Success
  411. * @access public
  412. */
  413. function time($check) {
  414. $_this =& Validation::getInstance();
  415. $_this->__reset();
  416. $_this->check = $check;
  417. $_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}$%';
  418. return $_this->_check();
  419. }
  420. /**
  421. * Boolean validation, determines if value passed is a boolean integer or true/false.
  422. *
  423. * @param string $check a valid boolean
  424. * @return boolean Success
  425. * @access public
  426. */
  427. function boolean($check) {
  428. $booleanList = array(0, 1, '0', '1', true, false);
  429. return in_array($check, $booleanList, true);
  430. }
  431. /**
  432. * Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
  433. * If no decimal point is found a false will be returned. Both the sign and exponent are optional.
  434. *
  435. * @param integer $check The value the test for decimal
  436. * @param integer $places if set $check value must have exactly $places after the decimal point
  437. * @param string $regex If a custom regular expression is used this is the only validation that will occur.
  438. * @return boolean Success
  439. * @access public
  440. */
  441. function decimal($check, $places = null, $regex = null) {
  442. $_this =& Validation::getInstance();
  443. $_this->__reset();
  444. $_this->regex = $regex;
  445. $_this->check = $check;
  446. if (is_null($_this->regex)) {
  447. if (is_null($places)) {
  448. $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
  449. } else {
  450. $_this->regex = '/^[-+]?[0-9]*\\.{1}[0-9]{'.$places.'}$/';
  451. }
  452. }
  453. return $_this->_check();
  454. }
  455. /**
  456. * Validates for an email address.
  457. *
  458. * @param string $check Value to check
  459. * @param boolean $deep Perform a deeper validation (if true), by also checking availability of host
  460. * @param string $regex Regex to use (if none it will use built in regex)
  461. * @return boolean Success
  462. * @access public
  463. */
  464. function email($check, $deep = false, $regex = null) {
  465. $_this =& Validation::getInstance();
  466. $_this->__reset();
  467. $_this->check = $check;
  468. $_this->regex = $regex;
  469. $_this->deep = $deep;
  470. if (is_array($check)) {
  471. $_this->_extract($check);
  472. }
  473. if (is_null($_this->regex)) {
  474. $_this->regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . $_this->__pattern['hostname'] . '$/i';
  475. }
  476. $return = $_this->_check();
  477. if ($_this->deep === false || $_this->deep === null) {
  478. return $return;
  479. }
  480. if ($return === true && preg_match('/@(' . $_this->__pattern['hostname'] . ')$/i', $_this->check, $regs)) {
  481. $host = gethostbynamel($regs[1]);
  482. return is_array($host);
  483. }
  484. return false;
  485. }
  486. /**
  487. * Check that value is exactly $comparedTo.
  488. *
  489. * @param mixed $check Value to check
  490. * @param mixed $comparedTo Value to compare
  491. * @return boolean Success
  492. * @access public
  493. */
  494. function equalTo($check, $comparedTo) {
  495. return ($check === $comparedTo);
  496. }
  497. /**
  498. * Check that value has a valid file extension.
  499. *
  500. * @param mixed $check Value to check
  501. * @param array $extensions file extenstions to allow
  502. * @return boolean Success
  503. * @access public
  504. */
  505. function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
  506. if (is_array($check)) {
  507. return Validation::extension(array_shift($check), $extensions);
  508. }
  509. $extension = strtolower(array_pop(explode('.', $check)));
  510. foreach ($extensions as $value) {
  511. if ($extension == strtolower($value)) {
  512. return true;
  513. }
  514. }
  515. return false;
  516. }
  517. /**
  518. * Check that value is a file name
  519. *
  520. * @param mixed $check Value to check
  521. * @access public
  522. * @todo finish implementation
  523. */
  524. function file($check) {
  525. // if (is_array($check)) {
  526. // foreach ($check as $value) {
  527. // if (!Validation::file($value)) {
  528. // return false;
  529. // }
  530. // }
  531. // return true;
  532. // }
  533. //
  534. // return preg_match('/[\w| |_]+\.[\w]+/', $check);
  535. }
  536. /**
  537. * Validation of an IPv4 address.
  538. *
  539. * @param string $check The string to test.
  540. * @return boolean Success
  541. * @access public
  542. */
  543. function ip($check) {
  544. $_this =& Validation::getInstance();
  545. $_this->check = $check;
  546. $_this->regex = '/^' . $_this->__pattern['ip'] . '$/';
  547. return $_this->_check();
  548. }
  549. /**
  550. * Checks whether the length of a string is greater or equal to a minimal length.
  551. *
  552. * @param string $check The string to test
  553. * @param integer $min The minimal string length
  554. * @return boolean Success
  555. * @access public
  556. */
  557. function minLength($check, $min) {
  558. $length = strlen($check);
  559. return ($length >= $min);
  560. }
  561. /**
  562. * Checks whether the length of a string is smaller or equal to a maximal length..
  563. *
  564. * @param string $check The string to test
  565. * @param integer $max The maximal string length
  566. * @return boolean Success
  567. * @access public
  568. */
  569. function maxLength($check, $max) {
  570. $length = strlen($check);
  571. return ($length <= $max);
  572. }
  573. /**
  574. * Checks that a value is a monetary amount.
  575. *
  576. * @param string $check Value to check
  577. * @param string $symbolPosition Where symbol is located (left/right)
  578. * @return boolean Success
  579. * @access public
  580. */
  581. function money($check, $symbolPosition = 'left') {
  582. $_this =& Validation::getInstance();
  583. $_this->check = $check;
  584. if ($symbolPosition == 'right') {
  585. $_this->regex = '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u';
  586. } else {
  587. $_this->regex = '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';
  588. }
  589. return $_this->_check();
  590. }
  591. /**
  592. * Validate a multiple select.
  593. *
  594. * @param mixed $check Value to check
  595. * @param mixed $options Options for the check.
  596. * Valid options
  597. * in => provide a list of choices that selections must be made from
  598. * max => maximun number of non-zero choices that can be made
  599. * min => minimum number of non-zero choices that can be made
  600. * @return boolean Success
  601. * @access public
  602. */
  603. function multiple($check, $options = array()) {
  604. $defaults = array('in' => null, 'max' => null, 'min' => null);
  605. $options = array_merge($defaults, $options);
  606. $check = array_filter((array)$check);
  607. if (empty($check)) {
  608. return false;
  609. }
  610. if ($options['max'] && sizeof($check) > $options['max']) {
  611. return false;
  612. }
  613. if ($options['min'] && sizeof($check) < $options['min']) {
  614. return false;
  615. }
  616. if ($options['in'] && is_array($options['in'])) {
  617. foreach ($check as $val) {
  618. if (!in_array($val, $options['in'])) {
  619. return false;
  620. }
  621. }
  622. }
  623. return true;
  624. }
  625. /**
  626. * Checks if a value is numeric.
  627. *
  628. * @param string $check Value to check
  629. * @return boolean Succcess
  630. * @access public
  631. */
  632. function numeric($check) {
  633. return is_numeric($check);
  634. }
  635. /**
  636. * Check that a value is a valid phone number.
  637. *
  638. * @param mixed $check Value to check (string or array)
  639. * @param string $regex Regular expression to use
  640. * @param string $country Country code (defaults to 'all')
  641. * @return boolean Success
  642. * @access public
  643. */
  644. function phone($check, $regex = null, $country = 'all') {
  645. $_this =& Validation::getInstance();
  646. $_this->check = $check;
  647. $_this->regex = $regex;
  648. $_this->country = $country;
  649. if (is_array($check)) {
  650. $_this->_extract($check);
  651. }
  652. if (is_null($_this->regex)) {
  653. switch ($_this->country) {
  654. case 'us':
  655. // includes all NANPA members. see http://en.wikipedia.org/wiki/North_American_Numbering_Plan#List_of_NANPA_countries_and_territories
  656. default:
  657. $_this->regex = '/^(?:\+?1)?[-. ]?\\(?[2-9][0-8][0-9]\\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/';
  658. break;
  659. }
  660. }
  661. return $_this->_check();
  662. }
  663. /**
  664. * Checks that a given value is a valid postal code.
  665. *
  666. * @param mixed $check Value to check
  667. * @param string $regex Regular expression to use
  668. * @param string $country Country to use for formatting
  669. * @return boolean Success
  670. * @access public
  671. */
  672. function postal($check, $regex = null, $country = null) {
  673. $_this =& Validation::getInstance();
  674. $_this->check = $check;
  675. $_this->regex = $regex;
  676. $_this->country = $country;
  677. if (is_array($check)) {
  678. $_this->_extract($check);
  679. }
  680. if (is_null($_this->regex)) {
  681. switch ($_this->country) {
  682. case 'uk':
  683. $_this->regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
  684. break;
  685. case 'ca':
  686. $_this->regex = '/\\A\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]\\b\\z/i';
  687. break;
  688. case 'it':
  689. case 'de':
  690. $_this->regex = '/^[0-9]{5}$/i';
  691. break;
  692. case 'be':
  693. $_this->regex = '/^[1-9]{1}[0-9]{3}$/i';
  694. break;
  695. case 'us':
  696. default:
  697. $_this->regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
  698. break;
  699. }
  700. }
  701. return $_this->_check();
  702. }
  703. /**
  704. * Validate that a number is in specified range.
  705. * if $lower and $upper are not set, will return true if
  706. * $check is a legal finite on this platform
  707. *
  708. * @param string $check Value to check
  709. * @param integer $lower Lower limit
  710. * @param integer $upper Upper limit
  711. * @return boolean Success
  712. * @access public
  713. */
  714. function range($check, $lower = null, $upper = null ) {
  715. if (!is_numeric($check)) {
  716. return false;
  717. }
  718. if (isset($lower) && isset($upper)) {
  719. return ($check > $lower && $check < $upper);
  720. }
  721. return is_finite($check);
  722. }
  723. /**
  724. * Checks that a value is a valid Social Security Number.
  725. *
  726. * @param mixed $check Value to check
  727. * @param string $regex Regular expression to use
  728. * @param string $country Country
  729. * @return boolean Success
  730. * @access public
  731. */
  732. function ssn($check, $regex = null, $country = null) {
  733. $_this =& Validation::getInstance();
  734. $_this->check = $check;
  735. $_this->regex = $regex;
  736. $_this->country = $country;
  737. if (is_array($check)) {
  738. $_this->_extract($check);
  739. }
  740. if (is_null($_this->regex)) {
  741. switch ($_this->country) {
  742. case 'dk':
  743. $_this->regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
  744. break;
  745. case 'nl':
  746. $_this->regex = '/\\A\\b[0-9]{9}\\b\\z/i';
  747. break;
  748. case 'us':
  749. default:
  750. $_this->regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
  751. break;
  752. }
  753. }
  754. return $_this->_check();
  755. }
  756. /**
  757. * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
  758. *
  759. * The regex checks for the following component parts:
  760. * a valid, optional, scheme
  761. * a valid ip address OR
  762. * a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
  763. * with an optional port number
  764. * an optional valid path
  765. * an optional query string (get parameters)
  766. * an optional fragment (anchor tag)
  767. *
  768. * @param string $check Value to check
  769. * @return boolean Success
  770. * @access public
  771. */
  772. function url($check, $strict = false) {
  773. $_this =& Validation::getInstance();
  774. $_this->check = $check;
  775. $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=') . '\/0-9a-z]|(%[0-9a-f]{2}))';
  776. $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . ife($strict, '', '?') .
  777. '(?:' . $_this->__pattern['ip'] . '|' . $_this->__pattern['hostname'] . ')(?::[1-9][0-9]{0,3})?' .
  778. '(?:\/?|\/' . $validChars . '*)?' .
  779. '(?:\?' . $validChars . '*)?' .
  780. '(?:#' . $validChars . '*)?$/i';
  781. return $_this->_check();
  782. }
  783. /**
  784. * Checks if a value is in a given list.
  785. *
  786. * @param string $check Value to check
  787. * @param array $list List to check against
  788. * @return boolean Succcess
  789. * @access public
  790. */
  791. function inList($check, $list) {
  792. return in_array($check, $list);
  793. }
  794. /**
  795. * Runs an user-defined validation.
  796. *
  797. * @param mixed $check value that will be validated in user-defined methods.
  798. * @param object $object class that holds validation method
  799. * @param string $method class method name for validation to run
  800. * @param array $args arguments to send to method
  801. * @return mixed user-defined class class method returns
  802. * @access public
  803. */
  804. function userDefined($check, $object, $method, $args = null) {
  805. return call_user_func_array(array(&$object, $method), array($check, $args));
  806. }
  807. /**
  808. * Runs a regular expression match.
  809. *
  810. * @return boolean Success of match
  811. * @access protected
  812. */
  813. function _check() {
  814. $_this =& Validation::getInstance();
  815. if (preg_match($_this->regex, $_this->check)) {
  816. $_this->error[] = false;
  817. return true;
  818. } else {
  819. $_this->error[] = true;
  820. return false;
  821. }
  822. }
  823. /**
  824. * Get the values to use when value sent to validation method is
  825. * an array.
  826. *
  827. * @param array $params Parameters sent to validation method
  828. * @return void
  829. * @access protected
  830. */
  831. function _extract($params) {
  832. $_this =& Validation::getInstance();
  833. extract($params, EXTR_OVERWRITE);
  834. if (isset($check)) {
  835. $_this->check = $check;
  836. }
  837. if (isset($regex)) {
  838. $_this->regex = $regex;
  839. }
  840. if (isset($country)) {
  841. $_this->country = strtolower($country);
  842. }
  843. if (isset($deep)) {
  844. $_this->deep = $deep;
  845. }
  846. if (isset($type)) {
  847. $_this->type = $type;
  848. }
  849. }
  850. /**
  851. * Luhn algorithm
  852. *
  853. * @see http://en.wikipedia.org/wiki/Luhn_algorithm
  854. * @return boolean Success
  855. * @access protected
  856. */
  857. function _luhn() {
  858. $_this =& Validation::getInstance();
  859. if ($_this->deep !== true) {
  860. return true;
  861. }
  862. if ($_this->check == 0) {
  863. return false;
  864. }
  865. $sum = 0;
  866. $length = strlen($_this->check);
  867. for ($position = 1 - ($length % 2); $position < $length; $position += 2) {
  868. $sum += $_this->check[$position];
  869. }
  870. for ($position = ($length % 2); $position < $length; $position += 2) {
  871. $number = $_this->check[$position] * 2;
  872. $sum += ($number < 10) ? $number : $number - 9;
  873. }
  874. return ($sum % 10 == 0);
  875. }
  876. /**
  877. * Reset internal variables for another validation run.
  878. *
  879. * @return void
  880. * @access private
  881. */
  882. function __reset() {
  883. $this->check = null;
  884. $this->regex = null;
  885. $this->country = null;
  886. $this->deep = null;
  887. $this->type = null;
  888. $this->error = array();
  889. $this->errors = array();
  890. }
  891. }
  892. ?>