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