blob: 4baf78b91b0f2dc4c1207383226d5d51c81849f6 [file] [log] [blame]
Derek Allard2067d1a2008-11-13 22:59:24 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
9 * @copyright Copyright (c) 2008, EllisLab, Inc.
10 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Validation Class
20 *
21 * @package CodeIgniter
22 * @subpackage Libraries
23 * @category Validation
24 * @author ExpressionEngine Dev Team
25 * @link http://codeigniter.com/user_guide/libraries/validation.html
26 */
27class CI_Validation {
28
29 var $CI;
30 var $error_string = '';
31 var $_error_array = array();
32 var $_rules = array();
33 var $_fields = array();
34 var $_error_messages = array();
35 var $_current_field = '';
36 var $_safe_form_data = FALSE;
37 var $_error_prefix = '<p>';
38 var $_error_suffix = '</p>';
39
40
41
42 /**
43 * Constructor
44 *
45 */
46 function CI_Validation()
47 {
48 $this->CI =& get_instance();
49
50 if (function_exists('mb_internal_encoding'))
51 {
52 mb_internal_encoding($this->CI->config->item('charset'));
53 }
54
55 log_message('debug', "Validation Class Initialized");
56 }
57
58 // --------------------------------------------------------------------
59
60 /**
61 * Set Fields
62 *
63 * This function takes an array of field names as input
64 * and generates class variables with the same name, which will
65 * either be blank or contain the $_POST value corresponding to it
66 *
67 * @access public
68 * @param string
69 * @param string
70 * @return void
71 */
72 function set_fields($data = '', $field = '')
73 {
74 if ($data == '')
75 {
76 if (count($this->_fields) == 0)
77 {
78 return FALSE;
79 }
80 }
81 else
82 {
83 if ( ! is_array($data))
84 {
85 $data = array($data => $field);
86 }
87
88 if (count($data) > 0)
89 {
90 $this->_fields = $data;
91 }
92 }
93
94 foreach($this->_fields as $key => $val)
95 {
96 $this->$key = ( ! isset($_POST[$key])) ? '' : $this->prep_for_form($_POST[$key]);
97
98 $error = $key.'_error';
99 if ( ! isset($this->$error))
100 {
101 $this->$error = '';
102 }
103 }
104 }
105
106 // --------------------------------------------------------------------
107
108 /**
109 * Set Rules
110 *
111 * This function takes an array of field names and validation
112 * rules as input ad simply stores is for use later.
113 *
114 * @access public
115 * @param mixed
116 * @param string
117 * @return void
118 */
119 function set_rules($data, $rules = '')
120 {
121 if ( ! is_array($data))
122 {
123 if ($rules == '')
124 return;
125
126 $data = array($data => $rules);
127 }
128
129 foreach ($data as $key => $val)
130 {
131 $this->_rules[$key] = $val;
132 }
133 }
134
135 // --------------------------------------------------------------------
136
137 /**
138 * Set Error Message
139 *
140 * Lets users set their own error messages on the fly. Note: The key
141 * name has to match the function name that it corresponds to.
142 *
143 * @access public
144 * @param string
145 * @param string
146 * @return string
147 */
148 function set_message($lang, $val = '')
149 {
150 if ( ! is_array($lang))
151 {
152 $lang = array($lang => $val);
153 }
154
155 $this->_error_messages = array_merge($this->_error_messages, $lang);
156 }
157
158 // --------------------------------------------------------------------
159
160 /**
161 * Set The Error Delimiter
162 *
163 * Permits a prefix/suffix to be added to each error message
164 *
165 * @access public
166 * @param string
167 * @param string
168 * @return void
169 */
170 function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
171 {
172 $this->_error_prefix = $prefix;
173 $this->_error_suffix = $suffix;
174 }
175
176 // --------------------------------------------------------------------
177
178 /**
179 * Run the Validator
180 *
181 * This function does all the work.
182 *
183 * @access public
184 * @return bool
185 */
186 function run()
187 {
188 // Do we even have any data to process? Mm?
189 if (count($_POST) == 0 OR count($this->_rules) == 0)
190 {
191 return FALSE;
192 }
193
194 // Load the language file containing error messages
195 $this->CI->lang->load('validation');
196
197 // Cycle through the rules and test for errors
198 foreach ($this->_rules as $field => $rules)
199 {
200 //Explode out the rules!
201 $ex = explode('|', $rules);
202
203 // Is the field required? If not, if the field is blank we'll move on to the next test
204 if ( ! in_array('required', $ex, TRUE))
205 {
206 if ( ! isset($_POST[$field]) OR $_POST[$field] == '')
207 {
208 continue;
209 }
210 }
211
212 /*
213 * Are we dealing with an "isset" rule?
214 *
215 * Before going further, we'll see if one of the rules
216 * is to check whether the item is set (typically this
217 * applies only to checkboxes). If so, we'll
218 * test for it here since there's not reason to go
219 * further
220 */
221 if ( ! isset($_POST[$field]))
222 {
223 if (in_array('isset', $ex, TRUE) OR in_array('required', $ex))
224 {
225 if ( ! isset($this->_error_messages['isset']))
226 {
227 if (FALSE === ($line = $this->CI->lang->line('isset')))
228 {
229 $line = 'The field was not set';
230 }
231 }
232 else
233 {
234 $line = $this->_error_messages['isset'];
235 }
236
237 // Build the error message
238 $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
239 $message = sprintf($line, $mfield);
240
241 // Set the error variable. Example: $this->username_error
242 $error = $field.'_error';
243 $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
244 $this->_error_array[] = $message;
245 }
246
247 continue;
248 }
249
250 /*
251 * Set the current field
252 *
253 * The various prepping functions need to know the
254 * current field name so they can do this:
255 *
256 * $_POST[$this->_current_field] == 'bla bla';
257 */
258 $this->_current_field = $field;
259
260 // Cycle through the rules!
261 foreach ($ex As $rule)
262 {
263 // Is the rule a callback?
264 $callback = FALSE;
265 if (substr($rule, 0, 9) == 'callback_')
266 {
267 $rule = substr($rule, 9);
268 $callback = TRUE;
269 }
270
271 // Strip the parameter (if exists) from the rule
272 // Rules can contain a parameter: max_length[5]
273 $param = FALSE;
274 if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
275 {
276 $rule = $match[1];
277 $param = $match[2];
278 }
279
280 // Call the function that corresponds to the rule
281 if ($callback === TRUE)
282 {
283 if ( ! method_exists($this->CI, $rule))
284 {
285 continue;
286 }
287
288 $result = $this->CI->$rule($_POST[$field], $param);
289
290 // If the field isn't required and we just processed a callback we'll move on...
291 if ( ! in_array('required', $ex, TRUE) AND $result !== FALSE)
292 {
293 continue 2;
294 }
295
296 }
297 else
298 {
299 if ( ! method_exists($this, $rule))
300 {
301 /*
302 * Run the native PHP function if called for
303 *
304 * If our own wrapper function doesn't exist we see
305 * if a native PHP function does. Users can use
306 * any native PHP function call that has one param.
307 */
308 if (function_exists($rule))
309 {
310 $_POST[$field] = $rule($_POST[$field]);
311 $this->$field = $_POST[$field];
312 }
313
314 continue;
315 }
316
317 $result = $this->$rule($_POST[$field], $param);
318 }
319
320 // Did the rule test negatively? If so, grab the error.
321 if ($result === FALSE)
322 {
323 if ( ! isset($this->_error_messages[$rule]))
324 {
325 if (FALSE === ($line = $this->CI->lang->line($rule)))
326 {
327 $line = 'Unable to access an error message corresponding to your field name.';
328 }
329 }
330 else
331 {
332 $line = $this->_error_messages[$rule];
333 }
334
335 // Build the error message
336 $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
337 $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
338 $message = sprintf($line, $mfield, $mparam);
339
340 // Set the error variable. Example: $this->username_error
341 $error = $field.'_error';
342 $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
343
344 // Add the error to the error array
345 $this->_error_array[] = $message;
346 continue 2;
347 }
348 }
349
350 }
351
352 $total_errors = count($this->_error_array);
353
354 /*
355 * Recompile the class variables
356 *
357 * If any prepping functions were called the $_POST data
358 * might now be different then the corresponding class
359 * variables so we'll set them anew.
360 */
361 if ($total_errors > 0)
362 {
363 $this->_safe_form_data = TRUE;
364 }
365
366 $this->set_fields();
367
368 // Did we end up with any errors?
369 if ($total_errors == 0)
370 {
371 return TRUE;
372 }
373
374 // Generate the error string
375 foreach ($this->_error_array as $val)
376 {
377 $this->error_string .= $this->_error_prefix.$val.$this->_error_suffix."\n";
378 }
379
380 return FALSE;
381 }
382
383 // --------------------------------------------------------------------
384
385 /**
386 * Required
387 *
388 * @access public
389 * @param string
390 * @return bool
391 */
392 function required($str)
393 {
394 if ( ! is_array($str))
395 {
396 return (trim($str) == '') ? FALSE : TRUE;
397 }
398 else
399 {
400 return ( ! empty($str));
401 }
402 }
403
404 // --------------------------------------------------------------------
405
406 /**
407 * Match one field to another
408 *
409 * @access public
410 * @param string
411 * @param field
412 * @return bool
413 */
414 function matches($str, $field)
415 {
416 if ( ! isset($_POST[$field]))
417 {
418 return FALSE;
419 }
420
421 return ($str !== $_POST[$field]) ? FALSE : TRUE;
422 }
423
424 // --------------------------------------------------------------------
425
426 /**
427 * Minimum Length
428 *
429 * @access public
430 * @param string
431 * @param value
432 * @return bool
433 */
434 function min_length($str, $val)
435 {
436 if (preg_match("/[^0-9]/", $val))
437 {
438 return FALSE;
439 }
440
441 if (function_exists('mb_strlen'))
442 {
443 return (mb_strlen($str) < $val) ? FALSE : TRUE;
444 }
445
446 return (strlen($str) < $val) ? FALSE : TRUE;
447 }
448
449 // --------------------------------------------------------------------
450
451 /**
452 * Max Length
453 *
454 * @access public
455 * @param string
456 * @param value
457 * @return bool
458 */
459 function max_length($str, $val)
460 {
461 if (preg_match("/[^0-9]/", $val))
462 {
463 return FALSE;
464 }
465
466 if (function_exists('mb_strlen'))
467 {
468 return (mb_strlen($str) > $val) ? FALSE : TRUE;
469 }
470
471 return (strlen($str) > $val) ? FALSE : TRUE;
472 }
473
474 // --------------------------------------------------------------------
475
476 /**
477 * Exact Length
478 *
479 * @access public
480 * @param string
481 * @param value
482 * @return bool
483 */
484 function exact_length($str, $val)
485 {
486 if (preg_match("/[^0-9]/", $val))
487 {
488 return FALSE;
489 }
490
491 if (function_exists('mb_strlen'))
492 {
493 return (mb_strlen($str) != $val) ? FALSE : TRUE;
494 }
495
496 return (strlen($str) != $val) ? FALSE : TRUE;
497 }
498
499 // --------------------------------------------------------------------
500
501 /**
502 * Valid Email
503 *
504 * @access public
505 * @param string
506 * @return bool
507 */
508 function valid_email($str)
509 {
510 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
511 }
512
513 // --------------------------------------------------------------------
514
515 /**
516 * Valid Emails
517 *
518 * @access public
519 * @param string
520 * @return bool
521 */
522 function valid_emails($str)
523 {
524 if (strpos($str, ',') === FALSE)
525 {
526 return $this->valid_email(trim($str));
527 }
528
529 foreach(explode(',', $str) as $email)
530 {
531 if (trim($email) != '' && $this->valid_email(trim($email)) === FALSE)
532 {
533 return FALSE;
534 }
535 }
536
537 return TRUE;
538 }
539
540 // --------------------------------------------------------------------
541
542 /**
543 * Validate IP Address
544 *
545 * @access public
546 * @param string
547 * @return string
548 */
549 function valid_ip($ip)
550 {
551 return $this->CI->input->valid_ip($ip);
552 }
553
554 // --------------------------------------------------------------------
555
556 /**
557 * Alpha
558 *
559 * @access public
560 * @param string
561 * @return bool
562 */
563 function alpha($str)
564 {
565 return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
566 }
567
568 // --------------------------------------------------------------------
569
570 /**
571 * Alpha-numeric
572 *
573 * @access public
574 * @param string
575 * @return bool
576 */
577 function alpha_numeric($str)
578 {
579 return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
580 }
581
582 // --------------------------------------------------------------------
583
584 /**
585 * Alpha-numeric with underscores and dashes
586 *
587 * @access public
588 * @param string
589 * @return bool
590 */
591 function alpha_dash($str)
592 {
593 return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
594 }
595
596 // --------------------------------------------------------------------
597
598 /**
599 * Numeric
600 *
601 * @access public
602 * @param string
603 * @return bool
604 */
605 function numeric($str)
606 {
607 return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
608
609 }
610
611 // --------------------------------------------------------------------
612
613 /**
614 * Is Numeric
615 *
616 * @access public
617 * @param string
618 * @return bool
619 */
620 function is_numeric($str)
621 {
622 return ( ! is_numeric($str)) ? FALSE : TRUE;
623 }
624
625 // --------------------------------------------------------------------
626
627 /**
628 * Integer
629 *
630 * @access public
631 * @param string
632 * @return bool
633 */
634 function integer($str)
635 {
636 return (bool)preg_match( '/^[\-+]?[0-9]+$/', $str);
637 }
638
639 // --------------------------------------------------------------------
640
641 /**
642 * Is a Natural number (0,1,2,3, etc.)
643 *
644 * @access public
645 * @param string
646 * @return bool
647 */
648 function is_natural($str)
649 {
650 return (bool)preg_match( '/^[0-9]+$/', $str);
651 }
652
653 // --------------------------------------------------------------------
654
655 /**
656 * Is a Natural number, but not a zero (1,2,3, etc.)
657 *
658 * @access public
659 * @param string
660 * @return bool
661 */
662 function is_natural_no_zero($str)
663 {
664 if ( ! preg_match( '/^[0-9]+$/', $str))
665 {
666 return FALSE;
667 }
668
669 if ($str == 0)
670 {
671 return FALSE;
672 }
673
674 return TRUE;
675 }
676
677 // --------------------------------------------------------------------
678
679 /**
680 * Valid Base64
681 *
682 * Tests a string for characters outside of the Base64 alphabet
683 * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
684 *
685 * @access public
686 * @param string
687 * @return bool
688 */
689 function valid_base64($str)
690 {
691 return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
692 }
693
694 // --------------------------------------------------------------------
695
696 /**
697 * Set Select
698 *
699 * Enables pull-down lists to be set to the value the user
700 * selected in the event of an error
701 *
702 * @access public
703 * @param string
704 * @param string
705 * @return string
706 */
707 function set_select($field = '', $value = '')
708 {
709 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
710 {
711 return '';
712 }
713
714 if ($_POST[$field] == $value)
715 {
716 return ' selected="selected"';
717 }
718 }
719
720 // --------------------------------------------------------------------
721
722 /**
723 * Set Radio
724 *
725 * Enables radio buttons to be set to the value the user
726 * selected in the event of an error
727 *
728 * @access public
729 * @param string
730 * @param string
731 * @return string
732 */
733 function set_radio($field = '', $value = '')
734 {
735 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
736 {
737 return '';
738 }
739
740 if ($_POST[$field] == $value)
741 {
742 return ' checked="checked"';
743 }
744 }
745
746 // --------------------------------------------------------------------
747
748 /**
749 * Set Checkbox
750 *
751 * Enables checkboxes to be set to the value the user
752 * selected in the event of an error
753 *
754 * @access public
755 * @param string
756 * @param string
757 * @return string
758 */
759 function set_checkbox($field = '', $value = '')
760 {
761 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
762 {
763 return '';
764 }
765
766 if ($_POST[$field] == $value)
767 {
768 return ' checked="checked"';
769 }
770 }
771
772 // --------------------------------------------------------------------
773
774 /**
775 * Prep data for form
776 *
777 * This function allows HTML to be safely shown in a form.
778 * Special characters are converted.
779 *
780 * @access public
781 * @param string
782 * @return string
783 */
784 function prep_for_form($data = '')
785 {
786 if (is_array($data))
787 {
788 foreach ($data as $key => $val)
789 {
790 $data[$key] = $this->prep_for_form($val);
791 }
792
793 return $data;
794 }
795
796 if ($this->_safe_form_data == FALSE OR $data == '')
797 {
798 return $data;
799 }
800
801 return str_replace(array("'", '"', '<', '>'), array("&#39;", "&quot;", '&lt;', '&gt;'), stripslashes($data));
802 }
803
804 // --------------------------------------------------------------------
805
806 /**
807 * Prep URL
808 *
809 * @access public
810 * @param string
811 * @return string
812 */
813 function prep_url($str = '')
814 {
815 if ($str == 'http://' OR $str == '')
816 {
817 $_POST[$this->_current_field] = '';
818 return;
819 }
820
821 if (substr($str, 0, 7) != 'http://' && substr($str, 0, 8) != 'https://')
822 {
823 $str = 'http://'.$str;
824 }
825
826 $_POST[$this->_current_field] = $str;
827 }
828
829 // --------------------------------------------------------------------
830
831 /**
832 * Strip Image Tags
833 *
834 * @access public
835 * @param string
836 * @return string
837 */
838 function strip_image_tags($str)
839 {
840 $_POST[$this->_current_field] = $this->CI->input->strip_image_tags($str);
841 }
842
843 // --------------------------------------------------------------------
844
845 /**
846 * XSS Clean
847 *
848 * @access public
849 * @param string
850 * @return string
851 */
852 function xss_clean($str)
853 {
854 $_POST[$this->_current_field] = $this->CI->input->xss_clean($str);
855 }
856
857 // --------------------------------------------------------------------
858
859 /**
860 * Convert PHP tags to entities
861 *
862 * @access public
863 * @param string
864 * @return string
865 */
866 function encode_php_tags($str)
867 {
868 $_POST[$this->_current_field] = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
869 }
870
871}
872// END Validation Class
873
874/* End of file Validation.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000875/* Location: ./system/libraries/Validation.php */