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