PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/system/classes/kohana/valid.php

https://bitbucket.org/waqar4at/scrumie
PHP | 518 lines | 248 code | 57 blank | 213 comment | 24 complexity | d57ebb9fb5a7018b09405c5e6b0aa3f2 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Validation rules.
  4. *
  5. * @package Kohana
  6. * @category Security
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2011 Kohana Team
  9. * @license http://kohanaframework.org/license
  10. */
  11. class Kohana_Valid {
  12. /**
  13. * Checks if a field is not empty.
  14. *
  15. * @return boolean
  16. */
  17. public static function not_empty($value)
  18. {
  19. if (is_object($value) AND $value instanceof ArrayObject)
  20. {
  21. // Get the array from the ArrayObject
  22. $value = $value->getArrayCopy();
  23. }
  24. // Value cannot be NULL, FALSE, '', or an empty array
  25. return ! in_array($value, array(NULL, FALSE, '', array()), TRUE);
  26. }
  27. /**
  28. * Checks a field against a regular expression.
  29. *
  30. * @param string value
  31. * @param string regular expression to match (including delimiters)
  32. * @return boolean
  33. */
  34. public static function regex($value, $expression)
  35. {
  36. return (bool) preg_match($expression, (string) $value);
  37. }
  38. /**
  39. * Checks that a field is long enough.
  40. *
  41. * @param string value
  42. * @param integer minimum length required
  43. * @return boolean
  44. */
  45. public static function min_length($value, $length)
  46. {
  47. return UTF8::strlen($value) >= $length;
  48. }
  49. /**
  50. * Checks that a field is short enough.
  51. *
  52. * @param string value
  53. * @param integer maximum length required
  54. * @return boolean
  55. */
  56. public static function max_length($value, $length)
  57. {
  58. return UTF8::strlen($value) <= $length;
  59. }
  60. /**
  61. * Checks that a field is exactly the right length.
  62. *
  63. * @param string value
  64. * @param integer exact length required
  65. * @return boolean
  66. */
  67. public static function exact_length($value, $length)
  68. {
  69. return UTF8::strlen($value) === $length;
  70. }
  71. /**
  72. * Checks that a field is exactly the value required.
  73. *
  74. * @param string value
  75. * @param string required value
  76. * @return boolean
  77. */
  78. public static function equals($value, $required)
  79. {
  80. return ($value === $required);
  81. }
  82. /**
  83. * Check an email address for correct format.
  84. *
  85. * @link http://www.iamcal.com/publish/articles/php/parsing_email/
  86. * @link http://www.w3.org/Protocols/rfc822/
  87. *
  88. * @param string email address
  89. * @param boolean strict RFC compatibility
  90. * @return boolean
  91. */
  92. public static function email($email, $strict = FALSE)
  93. {
  94. if ($strict === TRUE)
  95. {
  96. $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
  97. $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
  98. $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
  99. $pair = '\\x5c[\\x00-\\x7f]';
  100. $domain_literal = "\\x5b($dtext|$pair)*\\x5d";
  101. $quoted_string = "\\x22($qtext|$pair)*\\x22";
  102. $sub_domain = "($atom|$domain_literal)";
  103. $word = "($atom|$quoted_string)";
  104. $domain = "$sub_domain(\\x2e$sub_domain)*";
  105. $local_part = "$word(\\x2e$word)*";
  106. $expression = "/^$local_part\\x40$domain$/D";
  107. }
  108. else
  109. {
  110. $expression = '/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD';
  111. }
  112. return (bool) preg_match($expression, (string) $email);
  113. }
  114. /**
  115. * Validate the domain of an email address by checking if the domain has a
  116. * valid MX record.
  117. *
  118. * @link http://php.net/checkdnsrr not added to Windows until PHP 5.3.0
  119. *
  120. * @param string email address
  121. * @return boolean
  122. */
  123. public static function email_domain($email)
  124. {
  125. // Check if the email domain has a valid MX record
  126. return (bool) checkdnsrr(preg_replace('/^[^@]++@/', '', $email), 'MX');
  127. }
  128. /**
  129. * Validate a URL.
  130. *
  131. * @param string URL
  132. * @return boolean
  133. */
  134. public static function url($url)
  135. {
  136. // Based on http://www.apps.ietf.org/rfc/rfc1738.html#sec-5
  137. if ( ! preg_match(
  138. '~^
  139. # scheme
  140. [-a-z0-9+.]++://
  141. # username:password (optional)
  142. (?:
  143. [-a-z0-9$_.+!*\'(),;?&=%]++ # username
  144. (?::[-a-z0-9$_.+!*\'(),;?&=%]++)? # password (optional)
  145. @
  146. )?
  147. (?:
  148. # ip address
  149. \d{1,3}+(?:\.\d{1,3}+){3}+
  150. | # or
  151. # hostname (captured)
  152. (
  153. (?!-)[-a-z0-9]{1,63}+(?<!-)
  154. (?:\.(?!-)[-a-z0-9]{1,63}+(?<!-)){0,126}+
  155. )
  156. )
  157. # port (optional)
  158. (?::\d{1,5}+)?
  159. # path (optional)
  160. (?:/.*)?
  161. $~iDx', $url, $matches))
  162. return FALSE;
  163. // We matched an IP address
  164. if ( ! isset($matches[1]))
  165. return TRUE;
  166. // Check maximum length of the whole hostname
  167. // http://en.wikipedia.org/wiki/Domain_name#cite_note-0
  168. if (strlen($matches[1]) > 253)
  169. return FALSE;
  170. // An extra check for the top level domain
  171. // It must start with a letter
  172. $tld = ltrim(substr($matches[1], (int) strrpos($matches[1], '.')), '.');
  173. return ctype_alpha($tld[0]);
  174. }
  175. /**
  176. * Validate an IP.
  177. *
  178. * @param string IP address
  179. * @param boolean allow private IP networks
  180. * @return boolean
  181. */
  182. public static function ip($ip, $allow_private = TRUE)
  183. {
  184. // Do not allow reserved addresses
  185. $flags = FILTER_FLAG_NO_RES_RANGE;
  186. if ($allow_private === FALSE)
  187. {
  188. // Do not allow private or reserved addresses
  189. $flags = $flags | FILTER_FLAG_NO_PRIV_RANGE;
  190. }
  191. return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags);
  192. }
  193. /**
  194. * Validates a credit card number, with a Luhn check if possible.
  195. *
  196. * @param integer credit card number
  197. * @param string|array card type, or an array of card types
  198. * @return boolean
  199. * @uses Validate::luhn
  200. */
  201. public static function credit_card($number, $type = NULL)
  202. {
  203. // Remove all non-digit characters from the number
  204. if (($number = preg_replace('/\D+/', '', $number)) === '')
  205. return FALSE;
  206. if ($type == NULL)
  207. {
  208. // Use the default type
  209. $type = 'default';
  210. }
  211. elseif (is_array($type))
  212. {
  213. foreach ($type as $t)
  214. {
  215. // Test each type for validity
  216. if (Valid::credit_card($number, $t))
  217. return TRUE;
  218. }
  219. return FALSE;
  220. }
  221. $cards = Kohana::config('credit_cards');
  222. // Check card type
  223. $type = strtolower($type);
  224. if ( ! isset($cards[$type]))
  225. return FALSE;
  226. // Check card number length
  227. $length = strlen($number);
  228. // Validate the card length by the card type
  229. if ( ! in_array($length, preg_split('/\D+/', $cards[$type]['length'])))
  230. return FALSE;
  231. // Check card number prefix
  232. if ( ! preg_match('/^'.$cards[$type]['prefix'].'/', $number))
  233. return FALSE;
  234. // No Luhn check required
  235. if ($cards[$type]['luhn'] == FALSE)
  236. return TRUE;
  237. return Valid::luhn($number);
  238. }
  239. /**
  240. * Validate a number against the [Luhn](http://en.wikipedia.org/wiki/Luhn_algorithm)
  241. * (mod10) formula.
  242. *
  243. * @param string number to check
  244. * @return boolean
  245. */
  246. public static function luhn($number)
  247. {
  248. // Force the value to be a string as this method uses string functions.
  249. // Converting to an integer may pass PHP_INT_MAX and result in an error!
  250. $number = (string) $number;
  251. if ( ! ctype_digit($number))
  252. {
  253. // Luhn can only be used on numbers!
  254. return FALSE;
  255. }
  256. // Check number length
  257. $length = strlen($number);
  258. // Checksum of the card number
  259. $checksum = 0;
  260. for ($i = $length - 1; $i >= 0; $i -= 2)
  261. {
  262. // Add up every 2nd digit, starting from the right
  263. $checksum += substr($number, $i, 1);
  264. }
  265. for ($i = $length - 2; $i >= 0; $i -= 2)
  266. {
  267. // Add up every 2nd digit doubled, starting from the right
  268. $double = substr($number, $i, 1) * 2;
  269. // Subtract 9 from the double where value is greater than 10
  270. $checksum += ($double >= 10) ? ($double - 9) : $double;
  271. }
  272. // If the checksum is a multiple of 10, the number is valid
  273. return ($checksum % 10 === 0);
  274. }
  275. /**
  276. * Checks if a phone number is valid.
  277. *
  278. * @param string phone number to check
  279. * @return boolean
  280. */
  281. public static function phone($number, $lengths = NULL)
  282. {
  283. if ( ! is_array($lengths))
  284. {
  285. $lengths = array(7,10,11);
  286. }
  287. // Remove all non-digit characters from the number
  288. $number = preg_replace('/\D+/', '', $number);
  289. // Check if the number is within range
  290. return in_array(strlen($number), $lengths);
  291. }
  292. /**
  293. * Tests if a string is a valid date string.
  294. *
  295. * @param string date to check
  296. * @return boolean
  297. */
  298. public static function date($str)
  299. {
  300. return (strtotime($str) !== FALSE);
  301. }
  302. /**
  303. * Checks whether a string consists of alphabetical characters only.
  304. *
  305. * @param string input string
  306. * @param boolean trigger UTF-8 compatibility
  307. * @return boolean
  308. */
  309. public static function alpha($str, $utf8 = FALSE)
  310. {
  311. $str = (string) $str;
  312. if ($utf8 === TRUE)
  313. {
  314. return (bool) preg_match('/^\pL++$/uD', $str);
  315. }
  316. else
  317. {
  318. return ctype_alpha($str);
  319. }
  320. }
  321. /**
  322. * Checks whether a string consists of alphabetical characters and numbers only.
  323. *
  324. * @param string input string
  325. * @param boolean trigger UTF-8 compatibility
  326. * @return boolean
  327. */
  328. public static function alpha_numeric($str, $utf8 = FALSE)
  329. {
  330. if ($utf8 === TRUE)
  331. {
  332. return (bool) preg_match('/^[\pL\pN]++$/uD', $str);
  333. }
  334. else
  335. {
  336. return ctype_alnum($str);
  337. }
  338. }
  339. /**
  340. * Checks whether a string consists of alphabetical characters, numbers, underscores and dashes only.
  341. *
  342. * @param string input string
  343. * @param boolean trigger UTF-8 compatibility
  344. * @return boolean
  345. */
  346. public static function alpha_dash($str, $utf8 = FALSE)
  347. {
  348. if ($utf8 === TRUE)
  349. {
  350. $regex = '/^[-\pL\pN_]++$/uD';
  351. }
  352. else
  353. {
  354. $regex = '/^[-a-z0-9_]++$/iD';
  355. }
  356. return (bool) preg_match($regex, $str);
  357. }
  358. /**
  359. * Checks whether a string consists of digits only (no dots or dashes).
  360. *
  361. * @param string input string
  362. * @param boolean trigger UTF-8 compatibility
  363. * @return boolean
  364. */
  365. public static function digit($str, $utf8 = FALSE)
  366. {
  367. if ($utf8 === TRUE)
  368. {
  369. return (bool) preg_match('/^\pN++$/uD', $str);
  370. }
  371. else
  372. {
  373. return (is_int($str) AND $str >= 0) OR ctype_digit($str);
  374. }
  375. }
  376. /**
  377. * Checks whether a string is a valid number (negative and decimal numbers allowed).
  378. *
  379. * Uses {@link http://www.php.net/manual/en/function.localeconv.php locale conversion}
  380. * to allow decimal point to be locale specific.
  381. *
  382. * @param string input string
  383. * @return boolean
  384. */
  385. public static function numeric($str)
  386. {
  387. // Get the decimal point for the current locale
  388. list($decimal) = array_values(localeconv());
  389. // A lookahead is used to make sure the string contains at least one digit (before or after the decimal point)
  390. return (bool) preg_match('/^-?+(?=.*[0-9])[0-9]*+'.preg_quote($decimal).'?+[0-9]*+$/D', (string) $str);
  391. }
  392. /**
  393. * Tests if a number is within a range.
  394. *
  395. * @param string number to check
  396. * @param integer minimum value
  397. * @param integer maximum value
  398. * @return boolean
  399. */
  400. public static function range($number, $min, $max)
  401. {
  402. return ($number >= $min AND $number <= $max);
  403. }
  404. /**
  405. * Checks if a string is a proper decimal format. Optionally, a specific
  406. * number of digits can be checked too.
  407. *
  408. * @param string number to check
  409. * @param integer number of decimal places
  410. * @param integer number of digits
  411. * @return boolean
  412. */
  413. public static function decimal($str, $places = 2, $digits = NULL)
  414. {
  415. if ($digits > 0)
  416. {
  417. // Specific number of digits
  418. $digits = '{'.( (int) $digits).'}';
  419. }
  420. else
  421. {
  422. // Any number of digits
  423. $digits = '+';
  424. }
  425. // Get the decimal point for the current locale
  426. list($decimal) = array_values(localeconv());
  427. return (bool) preg_match('/^[0-9]'.$digits.preg_quote($decimal).'[0-9]{'.( (int) $places).'}$/D', $str);
  428. }
  429. /**
  430. * Checks if a string is a proper hexadecimal HTML color value. The validation
  431. * is quite flexible as it does not require an initial "#" and also allows for
  432. * the short notation using only three instead of six hexadecimal characters.
  433. *
  434. * @param string input string
  435. * @return boolean
  436. */
  437. public static function color($str)
  438. {
  439. return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $str);
  440. }
  441. /**
  442. * Checks if a field matches the value of another field.
  443. *
  444. * @param array array of values
  445. * @param string field name
  446. * @param string field name to match
  447. * @return boolean
  448. */
  449. public static function matches($array, $field, $match)
  450. {
  451. return ($array[$field] === $array[$match]);
  452. }
  453. } // End Valid