1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: App::uses('Multibyte', 'I18n');
17: App::uses('File', 'Utility');
18: App::uses('CakeNumber', 'Utility');
19:
20:
21: if (!function_exists('mb_strlen')) {
22: class_exists('Multibyte');
23: }
24:
25: 26: 27: 28: 29: 30: 31:
32: class Validation {
33:
34: 35: 36: 37: 38:
39: protected static $_pattern = array(
40: 'hostname' => '(?:[_\p{L}0-9][-_\p{L}0-9]*\.)*(?:[\p{L}0-9][-\p{L}0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,})'
41: );
42:
43: 44: 45: 46: 47: 48:
49: public static $errors = array();
50:
51: 52: 53: 54: 55: 56: 57: 58:
59: public static function notEmpty($check) {
60: trigger_error('Validation::notEmpty() is deprecated. Use Validation::notBlank() instead.', E_USER_DEPRECATED);
61: return static::notBlank($check);
62: }
63:
64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
75: public static function notBlank($check) {
76: if (!is_scalar($check)) {
77: return false;
78: }
79: if (empty($check) && (string)$check !== '0') {
80: return false;
81: }
82: return static::_check($check, '/[^\s]+/m');
83: }
84:
85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95:
96: public static function alphaNumeric($check) {
97: if (empty($check) && $check != '0') {
98: return false;
99: }
100: return static::_check($check, '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/Du');
101: }
102:
103: 104: 105: 106: 107: 108: 109: 110: 111: 112:
113: public static function lengthBetween($check, $min, $max) {
114: $length = mb_strlen($check);
115: return ($length >= $min && $length <= $max);
116: }
117:
118: 119: 120: 121: 122: 123: 124: 125: 126: 127:
128: public static function between($check, $min, $max) {
129: return static::lengthBetween($check, $min, $max);
130: }
131:
132: 133: 134: 135: 136: 137: 138: 139: 140: 141:
142: public static function blank($check) {
143: return !static::_check($check, '/[^\\s]/');
144: }
145:
146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159:
160: public static function cc($check, $type = 'fast', $deep = false, $regex = null) {
161: if (!is_scalar($check)) {
162: return false;
163: }
164:
165: $check = str_replace(array('-', ' '), '', $check);
166: if (mb_strlen($check) < 13) {
167: return false;
168: }
169:
170: if ($regex !== null) {
171: if (static::_check($check, $regex)) {
172: return static::luhn($check, $deep);
173: }
174: }
175: $cards = array(
176: 'all' => array(
177: 'amex' => '/^3[4|7]\\d{13}$/',
178: 'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
179: 'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
180: 'disc' => '/^(?:6011|650\\d)\\d{12}$/',
181: 'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
182: 'enroute' => '/^2(?:014|149)\\d{11}$/',
183: 'jcb' => '/^(3\\d{4}|2100|1800)\\d{11}$/',
184: 'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
185: 'mc' => '/^(5[1-5]\\d{14})|(2(?:22[1-9]|2[3-9][0-9]|[3-6][0-9]{2}|7[0-1][0-9]|720)\\d{12})$/',
186: 'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
187: 'switch' =>
188: '/^(?: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})?)$/',
189: 'visa' => '/^4\\d{12}(\\d{3})?$/',
190: 'voyager' => '/^8699[0-9]{11}$/'
191: ),
192: 'fast' =>
193: '/^(?: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})$/'
194: );
195:
196: if (is_array($type)) {
197: foreach ($type as $value) {
198: $regex = $cards['all'][strtolower($value)];
199:
200: if (static::_check($check, $regex)) {
201: return static::luhn($check, $deep);
202: }
203: }
204: } elseif ($type === 'all') {
205: foreach ($cards['all'] as $value) {
206: $regex = $value;
207:
208: if (static::_check($check, $regex)) {
209: return static::luhn($check, $deep);
210: }
211: }
212: } else {
213: $regex = $cards['fast'];
214:
215: if (static::_check($check, $regex)) {
216: return static::luhn($check, $deep);
217: }
218: }
219: return false;
220: }
221:
222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232:
233: public static function comparison($check1, $operator = null, $check2 = null) {
234: if ((float)$check1 != $check1) {
235: return false;
236: }
237: $operator = str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', strtolower($operator));
238:
239: switch ($operator) {
240: case 'isgreater':
241: case '>':
242: if ($check1 > $check2) {
243: return true;
244: }
245: break;
246: case 'isless':
247: case '<':
248: if ($check1 < $check2) {
249: return true;
250: }
251: break;
252: case 'greaterorequal':
253: case '>=':
254: if ($check1 >= $check2) {
255: return true;
256: }
257: break;
258: case 'lessorequal':
259: case '<=':
260: if ($check1 <= $check2) {
261: return true;
262: }
263: break;
264: case 'equalto':
265: case '==':
266: if ($check1 == $check2) {
267: return true;
268: }
269: break;
270: case 'notequal':
271: case '!=':
272: if ($check1 != $check2) {
273: return true;
274: }
275: break;
276: default:
277: static::$errors[] = __d('cake_dev', 'You must define the $operator parameter for %s', 'Validation::comparison()');
278: }
279: return false;
280: }
281:
282: 283: 284: 285: 286: 287: 288: 289:
290: public static function custom($check, $regex = null) {
291: if (!is_scalar($check)) {
292: return false;
293: }
294: if ($regex === null) {
295: static::$errors[] = __d('cake_dev', 'You must define a regular expression for %s', 'Validation::custom()');
296: return false;
297: }
298: return static::_check($check, $regex);
299: }
300:
301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324:
325: public static function date($check, $format = 'ymd', $regex = null) {
326: if ($regex !== null) {
327: return static::_check($check, $regex);
328: }
329: $month = '(0[123456789]|10|11|12)';
330: $separator = '([- /.])';
331: $fourDigitYear = '(([1][8-9][0-9][0-9])|([2][0-9][0-9][0-9]))';
332: $twoDigitYear = '([0-9]{2})';
333: $year = '(?:' . $fourDigitYear . '|' . $twoDigitYear . ')';
334:
335: $regex['dmy'] = '%^(?:(?:31(\\/|-|\\.|\\x20)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)' .
336: $separator . '(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29' .
337: $separator . '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])' .
338: $separator . '(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
339:
340: $regex['mdy'] = '%^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.|\\x20)31)\\1|(?:(?:0?[13-9]|1[0-2])' .
341: $separator . '(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2' . $separator . '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]))' .
342: $separator . '(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$%';
343:
344: $regex['ymd'] = '%^(?:(?:(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))' .
345: $separator . '(?:0?2\\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\\d)?\\d{2})' .
346: $separator . '(?:(?:(?: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]))))$%';
347:
348: $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})$/';
349:
350: $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)?|(Sep)(tember)?|(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}))$/';
351:
352: $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)?)' .
353: $separator . '((1[6-9]|[2-9]\\d)\\d{2})$%';
354:
355: $regex['my'] = '%^(' . $month . $separator . $year . ')$%';
356: $regex['ym'] = '%^(' . $year . $separator . $month . ')$%';
357: $regex['y'] = '%^(' . $fourDigitYear . ')$%';
358:
359: $format = (is_array($format)) ? array_values($format) : array($format);
360: foreach ($format as $key) {
361: if (static::_check($check, $regex[$key]) === true) {
362: return true;
363: }
364: }
365: return false;
366: }
367:
368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379:
380: public static function datetime($check, $dateFormat = 'ymd', $regex = null) {
381: $valid = false;
382: $parts = explode(' ', $check);
383: if (!empty($parts) && count($parts) > 1) {
384: $time = array_pop($parts);
385: $date = implode(' ', $parts);
386: $valid = static::date($date, $dateFormat, $regex) && static::time($time);
387: }
388: return $valid;
389: }
390:
391: 392: 393: 394: 395: 396: 397: 398:
399: public static function time($check) {
400: return static::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2} ?([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%');
401: }
402:
403: 404: 405: 406: 407: 408:
409: public static function boolean($check) {
410: $booleanList = array(0, 1, '0', '1', true, false);
411: return in_array($check, $booleanList, true);
412: }
413:
414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427:
428: public static function decimal($check, $places = null, $regex = null) {
429: if ($regex === null) {
430: $lnum = '[0-9]+';
431: $dnum = "[0-9]*[\.]{$lnum}";
432: $sign = '[+-]?';
433: $exp = "(?:[eE]{$sign}{$lnum})?";
434:
435: if ($places === null) {
436: $regex = "/^{$sign}(?:{$lnum}|{$dnum}){$exp}$/";
437:
438: } elseif ($places === true) {
439: if (is_float($check) && floor($check) === $check) {
440: $check = sprintf("%.1f", $check);
441: }
442: $regex = "/^{$sign}{$dnum}{$exp}$/";
443:
444: } elseif (is_numeric($places)) {
445: $places = '[0-9]{' . $places . '}';
446: $dnum = "(?:[0-9]*[\.]{$places}|{$lnum}[\.]{$places})";
447: $regex = "/^{$sign}{$dnum}{$exp}$/";
448: }
449: }
450:
451:
452: $data = localeconv();
453: $check = str_replace($data['thousands_sep'], '', $check);
454: $check = str_replace($data['decimal_point'], '.', $check);
455:
456: return static::_check($check, $regex);
457: }
458:
459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469:
470: public static function email($check, $deep = false, $regex = null) {
471: if ($regex === null) {
472: $regex = '/^[\p{L}0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[\p{L}0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . static::$_pattern['hostname'] . '$/ui';
473: }
474: $return = static::_check($check, $regex);
475: if ($deep === false || $deep === null) {
476: return $return;
477: }
478:
479: if ($return === true && preg_match('/@(' . static::$_pattern['hostname'] . ')$/i', $check, $regs)) {
480: if (function_exists('getmxrr') && getmxrr($regs[1], $mxhosts)) {
481: return true;
482: }
483: if (function_exists('checkdnsrr') && checkdnsrr($regs[1], 'MX')) {
484: return true;
485: }
486: return is_array(gethostbynamel($regs[1]));
487: }
488: return false;
489: }
490:
491: 492: 493: 494: 495: 496: 497:
498: public static function equalTo($check, $comparedTo) {
499: return ($check === $comparedTo);
500: }
501:
502: 503: 504: 505: 506: 507: 508:
509: public static function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
510: if (is_array($check)) {
511: return static::extension(array_shift($check), $extensions);
512: }
513: $extension = strtolower(pathinfo($check, PATHINFO_EXTENSION));
514: foreach ($extensions as $value) {
515: if ($extension === strtolower($value)) {
516: return true;
517: }
518: }
519: return false;
520: }
521:
522: 523: 524: 525: 526: 527: 528:
529: public static function ip($check, $type = 'both') {
530: $type = strtolower($type);
531: $flags = 0;
532: if ($type === 'ipv4') {
533: $flags = FILTER_FLAG_IPV4;
534: }
535: if ($type === 'ipv6') {
536: $flags = FILTER_FLAG_IPV6;
537: }
538: return (bool)filter_var($check, FILTER_VALIDATE_IP, array('flags' => $flags));
539: }
540:
541: 542: 543: 544: 545: 546: 547:
548: public static function minLength($check, $min) {
549: return mb_strlen($check) >= $min;
550: }
551:
552: 553: 554: 555: 556: 557: 558:
559: public static function maxLength($check, $max) {
560: return mb_strlen($check) <= $max;
561: }
562:
563: 564: 565: 566: 567: 568: 569:
570: public static function money($check, $symbolPosition = 'left') {
571: $money = '(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{1,2})?';
572: if ($symbolPosition === 'right') {
573: $regex = '/^' . $money . '(?<!\x{00a2})\p{Sc}?$/u';
574: } else {
575: $regex = '/^(?!\x{00a2})\p{Sc}?' . $money . '$/u';
576: }
577: return static::_check($check, $regex);
578: }
579:
580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593:
594: public static function multiple($check, $options = array(), $caseInsensitive = false) {
595: $defaults = array('in' => null, 'max' => null, 'min' => null);
596: $options += $defaults;
597:
598: $check = array_filter((array)$check, 'strlen');
599: if (empty($check)) {
600: return false;
601: }
602: if ($options['max'] && count($check) > $options['max']) {
603: return false;
604: }
605: if ($options['min'] && count($check) < $options['min']) {
606: return false;
607: }
608: if ($options['in'] && is_array($options['in'])) {
609: if ($caseInsensitive) {
610: $options['in'] = array_map('mb_strtolower', $options['in']);
611: }
612: foreach ($check as $val) {
613: $strict = !is_numeric($val);
614: if ($caseInsensitive) {
615: $val = mb_strtolower($val);
616: }
617: if (!in_array((string)$val, $options['in'], $strict)) {
618: return false;
619: }
620: }
621: }
622: return true;
623: }
624:
625: 626: 627: 628: 629: 630:
631: public static function numeric($check) {
632: return is_numeric($check);
633: }
634:
635: 636: 637: 638: 639: 640: 641: 642:
643: public static function naturalNumber($check, $allowZero = false) {
644: $regex = $allowZero ? '/^(?:0|[1-9][0-9]*)$/' : '/^[1-9][0-9]*$/';
645: return static::_check($check, $regex);
646: }
647:
648: 649: 650: 651: 652: 653: 654: 655:
656: public static function phone($check, $regex = null, $country = 'all') {
657: if ($regex === null) {
658: switch ($country) {
659: case 'us':
660: case 'ca':
661: case 'can':
662: case 'all':
663:
664:
665: $regex = '/^(?:(?:\+?1\s*(?:[.-]\s*)?)?';
666:
667:
668: $areaCode = '(?![2-9]11)(?!555)([2-9][0-8][0-9])';
669: $regex .= '(?:\(\s*' . $areaCode . '\s*\)|' . $areaCode . ')';
670: $regex .= '\s*(?:[.-]\s*)?)';
671:
672:
673: $regex .= '(?!(555(?:\s*(?:[.\-\s]\s*))(01([0-9][0-9])|1212)))';
674: $regex .= '(?!(555(01([0-9][0-9])|1212)))';
675: $regex .= '([2-9]1[02-9]|[2-9][02-9]1|[2-9][0-9]{2})\s*(?:[.-]\s*)';
676:
677:
678: $regex .= '?([0-9]{4})';
679: $regex .= '(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/';
680: break;
681: }
682: }
683: if (empty($regex)) {
684: return static::_pass('phone', $check, $country);
685: }
686: return static::_check($check, $regex);
687: }
688:
689: 690: 691: 692: 693: 694: 695: 696:
697: public static function postal($check, $regex = null, $country = 'us') {
698: if ($regex === null) {
699: switch ($country) {
700: case 'uk':
701: $regex = '/\\A\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b\\z/i';
702: break;
703: case 'ca':
704: $district = '[ABCEGHJKLMNPRSTVYX]';
705: $letters = '[ABCEGHJKLMNPRSTVWXYZ]';
706: $regex = "/\\A\\b{$district}[0-9]{$letters} [0-9]{$letters}[0-9]\\b\\z/i";
707: break;
708: case 'it':
709: case 'de':
710: $regex = '/^[0-9]{5}$/i';
711: break;
712: case 'be':
713: $regex = '/^[1-9]{1}[0-9]{3}$/i';
714: break;
715: case 'us':
716: $regex = '/\\A\\b[0-9]{5}(?:-[0-9]{4})?\\b\\z/i';
717: break;
718: }
719: }
720: if (empty($regex)) {
721: return static::_pass('postal', $check, $country);
722: }
723: return static::_check($check, $regex);
724: }
725:
726: 727: 728: 729: 730: 731: 732: 733: 734: 735:
736: public static function range($check, $lower = null, $upper = null) {
737: if (!is_numeric($check)) {
738: return false;
739: }
740: if ((float)$check != $check) {
741: return false;
742: }
743: if (isset($lower) && isset($upper)) {
744: return ($check > $lower && $check < $upper);
745: }
746: return is_finite($check);
747: }
748:
749: 750: 751: 752: 753: 754: 755: 756: 757:
758: public static function ssn($check, $regex = null, $country = null) {
759: if ($regex === null) {
760: switch ($country) {
761: case 'dk':
762: $regex = '/\\A\\b[0-9]{6}-[0-9]{4}\\b\\z/i';
763: break;
764: case 'nl':
765: $regex = '/\\A\\b[0-9]{9}\\b\\z/i';
766: break;
767: case 'us':
768: $regex = '/\\A\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b\\z/i';
769: break;
770: }
771: }
772: if (empty($regex)) {
773: return static::_pass('ssn', $check, $country);
774: }
775: return static::_check($check, $regex);
776: }
777:
778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794:
795: public static function url($check, $strict = false) {
796: static::_populateIp();
797: $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~[]') . '\/0-9\p{L}\p{N}]|(%[0-9a-f]{2}))';
798: $regex = '/^(?:(?:https?|ftps?|sftp|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') .
799: '(?:' . static::$_pattern['IPv4'] . '|\[' . static::$_pattern['IPv6'] . '\]|' . static::$_pattern['hostname'] . ')(?::[1-9][0-9]{0,4})?' .
800: '(?:\/?|\/' . $validChars . '*)?' .
801: '(?:\?' . $validChars . '*)?' .
802: '(?:#' . $validChars . '*)?$/iu';
803: return static::_check($check, $regex);
804: }
805:
806: 807: 808: 809: 810: 811: 812: 813:
814: public static function inList($check, $list, $caseInsensitive = false) {
815: if ($caseInsensitive) {
816: $list = array_map('mb_strtolower', $list);
817: $check = mb_strtolower($check);
818: } else {
819: $list = array_map('strval', $list);
820: }
821: return in_array((string)$check, $list, true);
822: }
823:
824: 825: 826: 827: 828: 829: 830: 831: 832:
833: public static function userDefined($check, $object, $method, $args = null) {
834: return call_user_func_array(array($object, $method), array($check, $args));
835: }
836:
837: 838: 839: 840: 841: 842:
843: public static function uuid($check) {
844: $regex = '/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[0-5][a-fA-F0-9]{3}-[089aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$/';
845: return static::_check($check, $regex);
846: }
847:
848: 849: 850: 851: 852: 853: 854: 855: 856: 857:
858: protected static function _pass($method, $check, $classPrefix) {
859: $className = ucwords($classPrefix) . 'Validation';
860: if (!class_exists($className)) {
861: trigger_error(__d('cake_dev', 'Could not find %s class, unable to complete validation.', $className), E_USER_WARNING);
862: return false;
863: }
864: if (!method_exists($className, $method)) {
865: trigger_error(__d('cake_dev', 'Method %s does not exist on %s unable to complete validation.', $method, $className), E_USER_WARNING);
866: return false;
867: }
868: $check = (array)$check;
869: return call_user_func_array(array($className, $method), $check);
870: }
871:
872: 873: 874: 875: 876: 877: 878:
879: protected static function _check($check, $regex) {
880: if (is_string($regex) && is_scalar($check) && preg_match($regex, $check)) {
881: return true;
882: }
883: return false;
884: }
885:
886: 887: 888: 889: 890: 891: 892: 893:
894: public static function luhn($check, $deep = false) {
895: if (!is_scalar($check)) {
896: return false;
897: }
898: if ($deep !== true) {
899: return true;
900: }
901: if ((int)$check === 0) {
902: return false;
903: }
904: $sum = 0;
905: $length = strlen($check);
906:
907: for ($position = 1 - ($length % 2); $position < $length; $position += 2) {
908: $sum += $check[$position];
909: }
910:
911: for ($position = ($length % 2); $position < $length; $position += 2) {
912: $number = $check[$position] * 2;
913: $sum += ($number < 10) ? $number : $number - 9;
914: }
915:
916: return ($sum % 10 === 0);
917: }
918:
919: 920: 921: 922: 923: 924: 925: 926:
927: public static function mimeType($check, $mimeTypes = array()) {
928: if (is_array($check) && isset($check['tmp_name'])) {
929: $check = $check['tmp_name'];
930: }
931:
932: $File = new File($check);
933: $mime = $File->mime();
934:
935: if ($mime === false) {
936: throw new CakeException(__d('cake_dev', 'Can not determine the mimetype.'));
937: }
938:
939: if (is_string($mimeTypes)) {
940: return static::_check($mime, $mimeTypes);
941: }
942:
943: foreach ($mimeTypes as $key => $val) {
944: $mimeTypes[$key] = strtolower($val);
945: }
946: return in_array($mime, $mimeTypes);
947: }
948:
949: 950: 951: 952: 953: 954: 955: 956:
957: public static function fileSize($check, $operator = null, $size = null) {
958: if (is_array($check) && isset($check['tmp_name'])) {
959: $check = $check['tmp_name'];
960: }
961:
962: if (is_string($size)) {
963: $size = CakeNumber::fromReadableSize($size);
964: }
965: $filesize = filesize($check);
966:
967: return static::comparison($filesize, $operator, $size);
968: }
969:
970: 971: 972: 973: 974: 975: 976: 977:
978: public static function uploadError($check, $allowNoFile = false) {
979: if (is_array($check) && isset($check['error'])) {
980: $check = $check['error'];
981: }
982: if ($allowNoFile) {
983: return in_array((int)$check, array(UPLOAD_ERR_OK, UPLOAD_ERR_NO_FILE), true);
984: }
985:
986: return (int)$check === UPLOAD_ERR_OK;
987: }
988:
989: 990: 991: 992: 993: 994: 995: 996: 997: 998: 999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008:
1009: public static function uploadedFile($file, $options = array()) {
1010: $options += array(
1011: 'minSize' => null,
1012: 'maxSize' => null,
1013: 'types' => null,
1014: 'optional' => false,
1015: );
1016: if (!is_array($file)) {
1017: return false;
1018: }
1019: $keys = array('error', 'name', 'size', 'tmp_name', 'type');
1020: ksort($file);
1021: if (array_keys($file) != $keys) {
1022: return false;
1023: }
1024: if (!static::uploadError($file, $options['optional'])) {
1025: return false;
1026: }
1027: if ($options['optional'] && (int)$file['error'] === UPLOAD_ERR_NO_FILE) {
1028: return true;
1029: }
1030: if (isset($options['minSize']) && !static::fileSize($file, '>=', $options['minSize'])) {
1031: return false;
1032: }
1033: if (isset($options['maxSize']) && !static::fileSize($file, '<=', $options['maxSize'])) {
1034: return false;
1035: }
1036: if (isset($options['types']) && !static::mimeType($file, $options['types'])) {
1037: return false;
1038: }
1039: return static::_isUploadedFile($file['tmp_name']);
1040: }
1041:
1042: 1043: 1044: 1045: 1046: 1047:
1048: protected static function _isUploadedFile($path) {
1049: return is_uploaded_file($path);
1050: }
1051:
1052: 1053: 1054: 1055: 1056:
1057: protected static function _populateIp() {
1058: if (!isset(static::$_pattern['IPv6'])) {
1059: $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
1060: $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
1061: $pattern .= '|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})';
1062: $pattern .= '(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)';
1063: $pattern .= '{4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1064: $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}';
1065: $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
1066: $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
1067: $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
1068: $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
1069: $pattern .= '{0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)';
1070: $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
1071: $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
1072: $pattern .= '{1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?';
1073:
1074: static::$_pattern['IPv6'] = $pattern;
1075: }
1076: if (!isset(static::$_pattern['IPv4'])) {
1077: $pattern = '(?:(?: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])';
1078: static::$_pattern['IPv4'] = $pattern;
1079: }
1080: }
1081:
1082: 1083: 1084: 1085: 1086:
1087: protected static function _reset() {
1088: static::$errors = array();
1089: }
1090:
1091: }
1092: