blob: 6b6ec0c68e89f9277c0cc14dd3f8a19818e0ee54 [file] [log] [blame]
Derek Allardd2df9bc2007-04-15 17:41:17 +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 Rick Ellis
9 * @copyright Copyright (c) 2006, EllisLab, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.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 Rick Ellis
25 * @link http://www.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 log_message('debug', "Validation Class Initialized");
50 }
51
52 // --------------------------------------------------------------------
53
54 /**
55 * Set Fields
56 *
57 * This function takes an array of field names as input
58 * and generates class variables with the same name, which will
59 * either be blank or contain the $_POST value corresponding to it
60 *
61 * @access public
62 * @param string
63 * @param string
64 * @return void
65 */
66 function set_fields($data = '', $field = '')
67 {
68 if ($data == '')
69 {
70 if (count($this->_fields) == 0)
71 {
72 return FALSE;
73 }
74 }
75 else
76 {
77 if ( ! is_array($data))
78 {
79 $data = array($data => $field);
80 }
81
82 if (count($data) > 0)
83 {
84 $this->_fields = $data;
85 }
86 }
87
88 foreach($this->_fields as $key => $val)
89 {
90 $this->$key = ( ! isset($_POST[$key]) OR is_array($_POST[$key])) ? '' : $this->prep_for_form($_POST[$key]);
91
92 $error = $key.'_error';
93 if ( ! isset($this->$error))
94 {
95 $this->$error = '';
96 }
97 }
98 }
99
100 // --------------------------------------------------------------------
101
102 /**
103 * Set Rules
104 *
105 * This function takes an array of field names and validation
106 * rules as input ad simply stores is for use later.
107 *
108 * @access public
109 * @param mixed
110 * @param string
111 * @return void
112 */
113 function set_rules($data, $rules = '')
114 {
115 if ( ! is_array($data))
116 {
117 if ($rules == '')
118 return;
119
120 $data[$data] = $rules;
121 }
122
123 foreach ($data as $key => $val)
124 {
125 $this->_rules[$key] = $val;
126 }
127 }
128
129 // --------------------------------------------------------------------
130
131 /**
132 * Set Error Message
133 *
134 * Lets users set their own error messages on the fly. Note: The key
135 * name has to match the function name that it corresponds to.
136 *
137 * @access public
138 * @param string
139 * @param string
140 * @return string
141 */
142 function set_message($lang, $val = '')
143 {
144 if ( ! is_array($lang))
145 {
146 $lang = array($lang => $val);
147 }
148
149 $this->_error_messages = array_merge($this->_error_messages, $lang);
150 }
151
152 // --------------------------------------------------------------------
153
154 /**
155 * Set The Error Delimiter
156 *
157 * Permits a prefix/suffix to be added to each error message
158 *
159 * @access public
160 * @param string
161 * @param string
162 * @return void
163 */
164 function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
165 {
166 $this->_error_prefix = $prefix;
167 $this->_error_suffix = $suffix;
168 }
169
170 // --------------------------------------------------------------------
171
172 /**
173 * Run the Validator
174 *
175 * This function does all the work.
176 *
177 * @access public
178 * @return bool
179 */
180 function run()
181 {
182 // Do we even have any data to process? Mm?
183 if (count($_POST) == 0 OR count($this->_rules) == 0)
184 {
185 return FALSE;
186 }
187
188 // Load the language file containing error messages
189 $this->CI->lang->load('validation');
190
191 // Cycle through the rules and test for errors
192 foreach ($this->_rules as $field => $rules)
193 {
194 //Explode out the rules!
195 $ex = explode('|', $rules);
196
Rick Ellisa1b05a12007-04-27 21:20:38 +0000197 // Is the field required? If not, if the field is blank we'll move on to the next test
Derek Allardd2df9bc2007-04-15 17:41:17 +0000198 if ( ! in_array('required', $ex, TRUE) AND strpos($rules, 'callback_') === FALSE)
199 {
200 if ( ! isset($_POST[$field]) OR $_POST[$field] == '')
201 {
202 continue;
203 }
204 }
205
206 /*
207 * Are we dealing with an "isset" rule?
208 *
209 * Before going further, we'll see if one of the rules
210 * is to check whether the item is set (typically this
211 * applies only to checkboxes). If so, we'll
212 * test for it here since there's not reason to go
213 * further
214 */
215 if ( ! isset($_POST[$field]))
216 {
217 if (in_array('isset', $ex, TRUE) OR in_array('required', $ex))
218 {
219 if ( ! isset($this->_error_messages['isset']))
220 {
221 if (FALSE === ($line = $this->CI->lang->line('isset')))
222 {
223 $line = 'The field was not set';
224 }
225 }
226 else
227 {
228 $line = $this->_error_messages['isset'];
229 }
230
231 $field = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
232 $this->_error_array[] = sprintf($line, $field);
233 }
234
235 continue;
236 }
237
238 /*
239 * Set the current field
240 *
241 * The various prepping functions need to know the
242 * current field name so they can do this:
243 *
244 * $_POST[$this->_current_field] == 'bla bla';
245 */
246 $this->_current_field = $field;
247
248 // Cycle through the rules!
249 foreach ($ex As $rule)
250 {
251 // Is the rule a callback?
252 $callback = FALSE;
253 if (substr($rule, 0, 9) == 'callback_')
254 {
255 $rule = substr($rule, 9);
256 $callback = TRUE;
257 }
258
259 // Strip the parameter (if exists) from the rule
260 // Rules can contain a parameter: max_length[5]
261 $param = FALSE;
262 if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
263 {
264 $rule = $match[1];
265 $param = $match[2];
266 }
267
268 // Call the function that corresponds to the rule
269 if ($callback === TRUE)
270 {
271 if ( ! method_exists($this->CI, $rule))
272 {
273 continue;
274 }
275
276 $result = $this->CI->$rule($_POST[$field], $param);
277
278 // If the field isn't required and we just processed a callback we'll move on...
279 if ( ! in_array('required', $ex, TRUE) AND $result !== FALSE)
280 {
281 continue 2;
282 }
283
284 }
285 else
286 {
287 if ( ! method_exists($this, $rule))
288 {
289 /*
290 * Run the native PHP function if called for
291 *
292 * If our own wrapper function doesn't exist we see
293 * if a native PHP function does. Users can use
294 * any native PHP function call that has one param.
295 */
296 if (function_exists($rule))
297 {
298 $_POST[$field] = $rule($_POST[$field]);
299 $this->$field = $_POST[$field];
300 }
301
302 continue;
303 }
304
305 $result = $this->$rule($_POST[$field], $param);
306 }
307
308 // Did the rule test negatively? If so, grab the error.
309 if ($result === FALSE)
310 {
311 if ( ! isset($this->_error_messages[$rule]))
312 {
313 if (FALSE === ($line = $this->CI->lang->line($rule)))
314 {
315 $line = 'Unable to access an error message corresponding to your field name.';
316 }
317 }
318 else
319 {
320 $line = $this->_error_messages[$rule];;
321 }
322
323 // Build the error message
324 $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
325 $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
326 $message = sprintf($line, $mfield, $mparam);
327
328 // Set the error variable. Example: $this->username_error
329 $error = $field.'_error';
330 $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
331
332 // Add the error to the error array
333 $this->_error_array[] = $message;
334 continue 2;
335 }
336 }
337
338 }
339
340 $total_errors = count($this->_error_array);
341
342 /*
343 * Recompile the class variables
344 *
345 * If any prepping functions were called the $_POST data
346 * might now be different then the corresponding class
347 * variables so we'll set them anew.
348 */
349 if ($total_errors > 0)
350 {
351 $this->_safe_form_data = TRUE;
352 }
353
354 $this->set_fields();
355
356 // Did we end up with any errors?
357 if ($total_errors == 0)
358 {
359 return TRUE;
360 }
361
362 // Generate the error string
363 foreach ($this->_error_array as $val)
364 {
365 $this->error_string .= $this->_error_prefix.$val.$this->_error_suffix."\n";
366 }
367
368 return FALSE;
369 }
370
371 // --------------------------------------------------------------------
372
373 /**
374 * Required
375 *
376 * @access public
377 * @param string
378 * @return bool
379 */
380 function required($str)
381 {
382 if ( ! is_array($str))
383 {
384 return (trim($str) == '') ? FALSE : TRUE;
385 }
386 else
387 {
388 return ( ! empty($str));
389 }
390 }
391
392 // --------------------------------------------------------------------
393
394 /**
395 * Match one field to another
396 *
397 * @access public
398 * @param string
399 * @return bool
400 */
401 function matches($str, $field)
402 {
403 if ( ! isset($_POST[$field]))
404 {
405 return FALSE;
406 }
407
408 return ($str !== $_POST[$field]) ? FALSE : TRUE;
409 }
410
411 // --------------------------------------------------------------------
412
413 /**
414 * Minimum Length
415 *
416 * @access public
417 * @param string
418 * @return bool
419 */
420 function min_length($str, $val)
421 {
Rick Ellis001e2562007-06-13 22:01:30 +0000422 if (preg_match("/[^0-9]/", $val))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000423 {
424 return FALSE;
425 }
426
427 return (strlen($str) < $val) ? FALSE : TRUE;
428 }
429
430 // --------------------------------------------------------------------
431
432 /**
433 * Max Length
434 *
435 * @access public
436 * @param string
437 * @return bool
438 */
439 function max_length($str, $val)
440 {
Rick Ellis001e2562007-06-13 22:01:30 +0000441 if (preg_match("/[^0-9]/", $val))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000442 {
443 return FALSE;
444 }
445
446 return (strlen($str) > $val) ? FALSE : TRUE;
447 }
448
449 // --------------------------------------------------------------------
450
451 /**
452 * Exact Length
453 *
454 * @access public
455 * @param string
456 * @return bool
457 */
458 function exact_length($str, $val)
459 {
Rick Ellis001e2562007-06-13 22:01:30 +0000460 if (preg_match("/[^0-9]/", $val))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000461 {
462 return FALSE;
463 }
464
465 return (strlen($str) != $val) ? FALSE : TRUE;
466 }
467
468 // --------------------------------------------------------------------
469
470 /**
471 * Valid Email
472 *
473 * @access public
474 * @param string
475 * @return bool
476 */
477 function valid_email($str)
478 {
479 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
480 }
481
482 // --------------------------------------------------------------------
483
484 /**
485 * Validate IP Address
486 *
487 * @access public
488 * @param string
489 * @return string
490 */
491 function valid_ip($ip)
492 {
Rick Ellisa4051172007-06-11 05:08:11 +0000493 return $this->CI->valid_ip($ip);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000494 }
495
496 // --------------------------------------------------------------------
497
498 /**
499 * Alpha
500 *
501 * @access public
502 * @param string
503 * @return bool
504 */
505 function alpha($str)
506 {
Rick Ellis1adf1db2007-06-11 04:46:57 +0000507 return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000508 }
509
510 // --------------------------------------------------------------------
511
512 /**
513 * Alpha-numeric
514 *
515 * @access public
516 * @param string
517 * @return bool
518 */
519 function alpha_numeric($str)
520 {
Rick Ellis8de97ff2007-06-11 04:38:47 +0000521 return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000522 }
523
524 // --------------------------------------------------------------------
525
526 /**
527 * Alpha-numeric with underscores and dashes
528 *
529 * @access public
530 * @param string
531 * @return bool
532 */
533 function alpha_dash($str)
534 {
535 return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
536 }
537
538 // --------------------------------------------------------------------
539
540 /**
541 * Numeric
542 *
543 * @access public
544 * @param int
545 * @return bool
546 */
547 function numeric($str)
548 {
549 return ( ! ereg("^[0-9\.]+$", $str)) ? FALSE : TRUE;
550 }
551
552 // --------------------------------------------------------------------
553
554 /**
555 * Is Numeric
556 *
557 * @access public
558 * @param string
559 * @return bool
560 */
561 function is_numeric($str)
562 {
563 return ( ! is_numeric($str)) ? FALSE : TRUE;
564 }
565
566 // --------------------------------------------------------------------
567
568 /**
569 * Set Select
570 *
571 * Enables pull-down lists to be set to the value the user
572 * selected in the event of an error
573 *
574 * @access public
575 * @param string
576 * @param string
577 * @return string
578 */
579 function set_select($field = '', $value = '')
580 {
581 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
582 {
583 return '';
584 }
585
586 if ($_POST[$field] == $value)
587 {
588 return ' selected="selected"';
589 }
590 }
591
592 // --------------------------------------------------------------------
593
594 /**
595 * Set Radio
596 *
597 * Enables radio buttons to be set to the value the user
598 * selected in the event of an error
599 *
600 * @access public
601 * @param string
602 * @param string
603 * @return string
604 */
605 function set_radio($field = '', $value = '')
606 {
607 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
608 {
609 return '';
610 }
611
612 if ($_POST[$field] == $value)
613 {
614 return ' checked="checked"';
615 }
616 }
617
618 // --------------------------------------------------------------------
619
620 /**
621 * Set Checkbox
622 *
623 * Enables checkboxes to be set to the value the user
624 * selected in the event of an error
625 *
626 * @access public
627 * @param string
628 * @param string
629 * @return string
630 */
631 function set_checkbox($field = '', $value = '')
632 {
633 if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
634 {
635 return '';
636 }
637
638 if ($_POST[$field] == $value)
639 {
640 return ' checked="checked"';
641 }
642 }
643
644 // --------------------------------------------------------------------
645
646 /**
647 * Prep data for form
648 *
649 * This function allows HTML to be safely shown in a form.
650 * Special characters are converted.
651 *
652 * @access public
653 * @param string
654 * @return string
655 */
656 function prep_for_form($str = '')
657 {
658 if ($this->_safe_form_data == FALSE OR $str == '')
659 {
660 return $str;
661 }
662
663 return str_replace(array("'", '"', '<', '>'), array("&#39;", "&quot;", '&lt;', '&gt;'), stripslashes($str));
664 }
665
666 // --------------------------------------------------------------------
667
668 /**
669 * Prep URL
670 *
671 * @access public
672 * @param string
673 * @return string
674 */
675 function prep_url($str = '')
676 {
677 if ($str == 'http://' OR $str == '')
678 {
679 $_POST[$this->_current_field] = '';
680 return;
681 }
682
683 if (substr($str, 0, 7) != 'http://' && substr($str, 0, 8) != 'https://')
684 {
685 $str = 'http://'.$str;
686 }
687
688 $_POST[$this->_current_field] = $str;
689 }
690
691 // --------------------------------------------------------------------
692
693 /**
694 * Strip Image Tags
695 *
696 * @access public
697 * @param string
698 * @return string
699 */
700 function strip_image_tags($str)
701 {
702 $_POST[$this->_current_field] = $this->input->strip_image_tags($str);
703 }
704
705 // --------------------------------------------------------------------
706
707 /**
708 * XSS Clean
709 *
710 * @access public
711 * @param string
712 * @return string
713 */
714 function xss_clean($str)
715 {
716 $_POST[$this->_current_field] = $this->CI->input->xss_clean($str);
717 }
718
719 // --------------------------------------------------------------------
720
721 /**
722 * Convert PHP tags to entities
723 *
724 * @access public
725 * @param string
726 * @return string
727 */
728 function encode_php_tags($str)
729 {
730 $_POST[$this->_current_field] = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
731 }
732
733}
734// END Validation Class
adminb0dd10f2006-08-25 17:25:49 +0000735?>