Validation.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2008, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * Validation Class
00020  *
00021  * @package             CodeIgniter
00022  * @subpackage  Libraries
00023  * @category    Validation
00024  * @author              ExpressionEngine Dev Team
00025  * @link                http://codeigniter.com/user_guide/libraries/validation.html
00026  */
00027 class CI_Validation {
00028         
00029         var $CI;
00030         var $error_string               = '';
00031         var $_error_array               = array();
00032         var $_rules                             = array();
00033         var $_fields                    = array();
00034         var $_error_messages    = array();
00035         var $_current_field     = '';
00036         var $_safe_form_data    = FALSE;
00037         var $_error_prefix              = '<p>';
00038         var $_error_suffix              = '</p>';
00039 
00040         
00041 
00042         /**
00043          * Constructor
00044          *
00045          */     
00046         function CI_Validation()
00047         {       
00048                 $this->CI =& get_instance();
00049                 
00050                 if (function_exists('mb_internal_encoding'))
00051                 {
00052                         mb_internal_encoding($this->CI->config->item('charset'));
00053                 }
00054                 
00055                 log_message('debug', "Validation Class Initialized");
00056         }
00057         
00058         // --------------------------------------------------------------------
00059         
00060         /**
00061          * Set Fields
00062          *
00063          * This function takes an array of field names as input
00064          * and generates class variables with the same name, which will
00065          * either be blank or contain the $_POST value corresponding to it
00066          *
00067          * @access      public
00068          * @param       string
00069          * @param       string
00070          * @return      void
00071          */
00072         function set_fields($data = '', $field = '')
00073         {       
00074                 if ($data == '')
00075                 {
00076                         if (count($this->_fields) == 0)
00077                         {
00078                                 return FALSE;
00079                         }
00080                 }
00081                 else
00082                 {
00083                         if ( ! is_array($data))
00084                         {
00085                                 $data = array($data => $field);
00086                         }
00087                         
00088                         if (count($data) > 0)
00089                         {
00090                                 $this->_fields = $data;
00091                         }
00092                 }               
00093                         
00094                 foreach($this->_fields as $key => $val)
00095                 {
00096                         $this->$key = ( ! isset($_POST[$key])) ? '' : $this->prep_for_form($_POST[$key]);
00097                         
00098                         $error = $key.'_error';
00099                         if ( ! isset($this->$error))
00100                         {
00101                                 $this->$error = '';
00102                         }
00103                 }               
00104         }
00105         
00106         // --------------------------------------------------------------------
00107         
00108         /**
00109          * Set Rules
00110          *
00111          * This function takes an array of field names and validation
00112          * rules as input ad simply stores is for use later.
00113          *
00114          * @access      public
00115          * @param       mixed
00116          * @param       string
00117          * @return      void
00118          */
00119         function set_rules($data, $rules = '')
00120         {
00121                 if ( ! is_array($data))
00122                 {
00123                         if ($rules == '')
00124                                 return;
00125                                 
00126                         $data = array($data => $rules);
00127                 }
00128         
00129                 foreach ($data as $key => $val)
00130                 {
00131                         $this->_rules[$key] = $val;
00132                 }
00133         }
00134         
00135         // --------------------------------------------------------------------
00136         
00137         /**
00138          * Set Error Message
00139          *
00140          * Lets users set their own error messages on the fly.  Note:  The key
00141          * name has to match the  function name that it corresponds to.
00142          *
00143          * @access      public
00144          * @param       string
00145          * @param       string
00146          * @return      string
00147          */
00148         function set_message($lang, $val = '')
00149         {
00150                 if ( ! is_array($lang))
00151                 {
00152                         $lang = array($lang => $val);
00153                 }
00154         
00155                 $this->_error_messages = array_merge($this->_error_messages, $lang);
00156         }
00157         
00158         // --------------------------------------------------------------------
00159         
00160         /**
00161          * Set The Error Delimiter
00162          *
00163          * Permits a prefix/suffix to be added to each error message
00164          *
00165          * @access      public
00166          * @param       string
00167          * @param       string
00168          * @return      void
00169          */     
00170         function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
00171         {
00172                 $this->_error_prefix = $prefix;
00173                 $this->_error_suffix = $suffix;
00174         }
00175         
00176         // --------------------------------------------------------------------
00177         
00178         /**
00179          * Run the Validator
00180          *
00181          * This function does all the work.
00182          *
00183          * @access      public
00184          * @return      bool
00185          */             
00186         function run()
00187         {
00188                 // Do we even have any data to process?  Mm?
00189                 if (count($_POST) == 0 OR count($this->_rules) == 0)
00190                 {
00191                         return FALSE;
00192                 }
00193         
00194                 // Load the language file containing error messages
00195                 $this->CI->lang->load('validation');
00196                                                         
00197                 // Cycle through the rules and test for errors
00198                 foreach ($this->_rules as $field => $rules)
00199                 {
00200                         //Explode out the rules!
00201                         $ex = explode('|', $rules);
00202 
00203                         // Is the field required?  If not, if the field is blank  we'll move on to the next test
00204                         if ( ! in_array('required', $ex, TRUE))
00205                         {
00206                                 if ( ! isset($_POST[$field]) OR $_POST[$field] == '')
00207                                 {
00208                                         continue;
00209                                 }
00210                         }
00211                         
00212                         /*
00213                          * Are we dealing with an "isset" rule?
00214                          *
00215                          * Before going further, we'll see if one of the rules
00216                          * is to check whether the item is set (typically this
00217                          * applies only to checkboxes).  If so, we'll
00218                          * test for it here since there's not reason to go
00219                          * further
00220                          */
00221                         if ( ! isset($_POST[$field]))
00222                         {                       
00223                                 if (in_array('isset', $ex, TRUE) OR in_array('required', $ex))
00224                                 {
00225                                         if ( ! isset($this->_error_messages['isset']))
00226                                         {
00227                                                 if (FALSE === ($line = $this->CI->lang->line('isset')))
00228                                                 {
00229                                                         $line = 'The field was not set';
00230                                                 }                                                       
00231                                         }
00232                                         else
00233                                         {
00234                                                 $line = $this->_error_messages['isset'];
00235                                         }
00236                                         
00237                                         // Build the error message
00238                                         $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
00239                                         $message = sprintf($line, $mfield);
00240 
00241                                         // Set the error variable.  Example: $this->username_error
00242                                         $error = $field.'_error';
00243                                         $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
00244                                         $this->_error_array[] = $message;
00245                                 }
00246                                                 
00247                                 continue;
00248                         }
00249         
00250                         /*
00251                          * Set the current field
00252                          *
00253                          * The various prepping functions need to know the
00254                          * current field name so they can do this:
00255                          *
00256                          * $_POST[$this->_current_field] == 'bla bla';
00257                          */
00258                         $this->_current_field = $field;
00259 
00260                         // Cycle through the rules!
00261                         foreach ($ex As $rule)
00262                         {
00263                                 // Is the rule a callback?                      
00264                                 $callback = FALSE;
00265                                 if (substr($rule, 0, 9) == 'callback_')
00266                                 {
00267                                         $rule = substr($rule, 9);
00268                                         $callback = TRUE;
00269                                 }
00270                                 
00271                                 // Strip the parameter (if exists) from the rule
00272                                 // Rules can contain a parameter: max_length[5]
00273                                 $param = FALSE;
00274                                 if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
00275                                 {
00276                                         $rule   = $match[1];
00277                                         $param  = $match[2];
00278                                 }
00279                                 
00280                                 // Call the function that corresponds to the rule
00281                                 if ($callback === TRUE)
00282                                 {
00283                                         if ( ! method_exists($this->CI, $rule))
00284                                         {               
00285                                                 continue;
00286                                         }
00287                                         
00288                                         $result = $this->CI->$rule($_POST[$field], $param);     
00289                                         
00290                                         // If the field isn't required and we just processed a callback we'll move on...
00291                                         if ( ! in_array('required', $ex, TRUE) AND $result !== FALSE)
00292                                         {
00293                                                 continue 2;
00294                                         }
00295                                         
00296                                 }
00297                                 else
00298                                 {                               
00299                                         if ( ! method_exists($this, $rule))
00300                                         {
00301                                                 /*
00302                                                  * Run the native PHP function if called for
00303                                                  *
00304                                                  * If our own wrapper function doesn't exist we see
00305                                                  * if a native PHP function does. Users can use
00306                                                  * any native PHP function call that has one param.
00307                                                  */
00308                                                 if (function_exists($rule))
00309                                                 {
00310                                                         $_POST[$field] = $rule($_POST[$field]);
00311                                                         $this->$field = $_POST[$field];
00312                                                 }
00313                                                                                         
00314                                                 continue;
00315                                         }
00316                                         
00317                                         $result = $this->$rule($_POST[$field], $param);
00318                                 }
00319                                                                 
00320                                 // Did the rule test negatively?  If so, grab the error.
00321                                 if ($result === FALSE)
00322                                 {
00323                                         if ( ! isset($this->_error_messages[$rule]))
00324                                         {
00325                                                 if (FALSE === ($line = $this->CI->lang->line($rule)))
00326                                                 {
00327                                                         $line = 'Unable to access an error message corresponding to your field name.';
00328                                                 }                                               
00329                                         }
00330                                         else
00331                                         {
00332                                                 $line = $this->_error_messages[$rule];
00333                                         }                               
00334 
00335                                         // Build the error message
00336                                         $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
00337                                         $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
00338                                         $message = sprintf($line, $mfield, $mparam);
00339                                         
00340                                         // Set the error variable.  Example: $this->username_error
00341                                         $error = $field.'_error';
00342                                         $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
00343 
00344                                         // Add the error to the error array
00345                                         $this->_error_array[] = $message;                               
00346                                         continue 2;
00347                                 }                               
00348                         }
00349                         
00350                 }
00351                 
00352                 $total_errors = count($this->_error_array);
00353 
00354                 /*
00355                  * Recompile the class variables
00356                  *
00357                  * If any prepping functions were called the $_POST data
00358                  * might now be different then the corresponding class
00359                  * variables so we'll set them anew.
00360                  */     
00361                 if ($total_errors > 0)
00362                 {
00363                         $this->_safe_form_data = TRUE;
00364                 }
00365                 
00366                 $this->set_fields();
00367 
00368                 // Did we end up with any errors?
00369                 if ($total_errors == 0)
00370                 {
00371                         return TRUE;
00372                 }
00373                 
00374                 // Generate the error string
00375                 foreach ($this->_error_array as $val)
00376                 {
00377                         $this->error_string .= $this->_error_prefix.$val.$this->_error_suffix."\n";
00378                 }
00379 
00380                 return FALSE;
00381         }
00382         
00383         // --------------------------------------------------------------------
00384         
00385         /**
00386          * Required
00387          *
00388          * @access      public
00389          * @param       string
00390          * @return      bool
00391          */
00392         function required($str)
00393         {
00394                 if ( ! is_array($str))
00395                 {
00396                         return (trim($str) == '') ? FALSE : TRUE;
00397                 }
00398                 else
00399                 {
00400                         return ( ! empty($str));
00401                 }
00402         }
00403         
00404         // --------------------------------------------------------------------
00405         
00406         /**
00407          * Match one field to another
00408          *
00409          * @access      public
00410          * @param       string
00411          * @param       field
00412          * @return      bool
00413          */
00414         function matches($str, $field)
00415         {
00416                 if ( ! isset($_POST[$field]))
00417                 {
00418                         return FALSE;
00419                 }
00420                 
00421                 return ($str !== $_POST[$field]) ? FALSE : TRUE;
00422         }
00423         
00424         // --------------------------------------------------------------------
00425         
00426         /**
00427          * Minimum Length
00428          *
00429          * @access      public
00430          * @param       string
00431          * @param       value
00432          * @return      bool
00433          */     
00434         function min_length($str, $val)
00435         {
00436                 if (preg_match("/[^0-9]/", $val))
00437                 {
00438                         return FALSE;
00439                 }
00440 
00441                 if (function_exists('mb_strlen'))
00442                 {
00443                         return (mb_strlen($str) < $val) ? FALSE : TRUE;         
00444                 }
00445 
00446                 return (strlen($str) < $val) ? FALSE : TRUE;
00447         }
00448         
00449         // --------------------------------------------------------------------
00450         
00451         /**
00452          * Max Length
00453          *
00454          * @access      public
00455          * @param       string
00456          * @param       value
00457          * @return      bool
00458          */     
00459         function max_length($str, $val)
00460         {
00461                 if (preg_match("/[^0-9]/", $val))
00462                 {
00463                         return FALSE;
00464                 }
00465                 
00466                 if (function_exists('mb_strlen'))
00467                 {
00468                         return (mb_strlen($str) > $val) ? FALSE : TRUE;         
00469                 }
00470 
00471                 return (strlen($str) > $val) ? FALSE : TRUE;
00472         }
00473         
00474         // --------------------------------------------------------------------
00475         
00476         /**
00477          * Exact Length
00478          *
00479          * @access      public
00480          * @param       string
00481          * @param       value
00482          * @return      bool
00483          */     
00484         function exact_length($str, $val)
00485         {
00486                 if (preg_match("/[^0-9]/", $val))
00487                 {
00488                         return FALSE;
00489                 }
00490         
00491                 if (function_exists('mb_strlen'))
00492                 {
00493                         return (mb_strlen($str) != $val) ? FALSE : TRUE;                
00494                 }
00495 
00496                 return (strlen($str) != $val) ? FALSE : TRUE;
00497         }
00498         
00499         // --------------------------------------------------------------------
00500         
00501         /**
00502          * Valid Email
00503          *
00504          * @access      public
00505          * @param       string
00506          * @return      bool
00507          */     
00508         function valid_email($str)
00509         {
00510                 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
00511         }
00512 
00513         // --------------------------------------------------------------------
00514         
00515         /**
00516          * Valid Emails
00517          *
00518          * @access      public
00519          * @param       string
00520          * @return      bool
00521          */     
00522         function valid_emails($str)
00523         {
00524                 if (strpos($str, ',') === FALSE)
00525                 {
00526                         return $this->valid_email(trim($str));
00527                 }
00528                 
00529                 foreach(explode(',', $str) as $email)
00530                 {
00531                         if (trim($email) != '' && $this->valid_email(trim($email)) === FALSE)
00532                         {
00533                                 return FALSE;
00534                         }
00535                 }
00536                 
00537                 return TRUE;
00538         }
00539 
00540         // --------------------------------------------------------------------
00541         
00542         /**
00543          * Validate IP Address
00544          *
00545          * @access      public
00546          * @param       string
00547          * @return      string
00548          */
00549         function valid_ip($ip)
00550         {
00551                 return $this->CI->input->valid_ip($ip);
00552         }
00553 
00554         // --------------------------------------------------------------------
00555         
00556         /**
00557          * Alpha
00558          *
00559          * @access      public
00560          * @param       string
00561          * @return      bool
00562          */             
00563         function alpha($str)
00564         {
00565                 return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
00566         }
00567         
00568         // --------------------------------------------------------------------
00569         
00570         /**
00571          * Alpha-numeric
00572          *
00573          * @access      public
00574          * @param       string
00575          * @return      bool
00576          */     
00577         function alpha_numeric($str)
00578         {
00579                 return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
00580         }
00581         
00582         // --------------------------------------------------------------------
00583         
00584         /**
00585          * Alpha-numeric with underscores and dashes
00586          *
00587          * @access      public
00588          * @param       string
00589          * @return      bool
00590          */     
00591         function alpha_dash($str)
00592         {
00593                 return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
00594         }
00595         
00596         // --------------------------------------------------------------------
00597         
00598         /**
00599          * Numeric
00600          *
00601          * @access      public
00602          * @param       string
00603          * @return      bool
00604          */     
00605         function numeric($str)
00606         {
00607                 return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
00608 
00609         }
00610 
00611         // --------------------------------------------------------------------
00612 
00613         /**
00614          * Is Numeric
00615          *
00616          * @access      public
00617          * @param       string
00618          * @return      bool
00619          */
00620         function is_numeric($str)
00621         {
00622                 return ( ! is_numeric($str)) ? FALSE : TRUE;
00623         } 
00624 
00625         // --------------------------------------------------------------------
00626         
00627         /**
00628          * Integer
00629          *
00630          * @access      public
00631          * @param       string
00632          * @return      bool
00633          */     
00634         function integer($str)
00635         {
00636                 return (bool)preg_match( '/^[\-+]?[0-9]+$/', $str);
00637         }
00638 
00639         // --------------------------------------------------------------------
00640 
00641         /**
00642          * Is a Natural number  (0,1,2,3, etc.)
00643          *
00644          * @access      public
00645          * @param       string
00646          * @return      bool
00647          */
00648         function is_natural($str)
00649         {   
00650                 return (bool)preg_match( '/^[0-9]+$/', $str);
00651         }
00652 
00653         // --------------------------------------------------------------------
00654 
00655         /**
00656          * Is a Natural number, but not a zero  (1,2,3, etc.)
00657          *
00658          * @access      public
00659          * @param       string
00660          * @return      bool
00661          */
00662         function is_natural_no_zero($str)
00663         {   
00664                 if ( ! preg_match( '/^[0-9]+$/', $str))
00665                 {
00666                         return FALSE;
00667                 }
00668         
00669                 if ($str == 0)
00670                 {
00671                         return FALSE;
00672                 }
00673 
00674                 return TRUE;
00675         }
00676 
00677         // --------------------------------------------------------------------
00678         
00679         /**
00680          * Valid Base64
00681          *
00682          * Tests a string for characters outside of the Base64 alphabet
00683          * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
00684          *
00685          * @access      public
00686          * @param       string
00687          * @return      bool
00688          */
00689         function valid_base64($str)
00690         {
00691                 return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
00692         }
00693 
00694         // --------------------------------------------------------------------
00695         
00696         /**
00697          * Set Select
00698          *
00699          * Enables pull-down lists to be set to the value the user
00700          * selected in the event of an error
00701          *
00702          * @access      public
00703          * @param       string
00704          * @param       string
00705          * @return      string
00706          */     
00707         function set_select($field = '', $value = '')
00708         {
00709                 if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
00710                 {
00711                         return '';
00712                 }
00713                         
00714                 if ($_POST[$field] == $value)
00715                 {
00716                         return ' selected="selected"';
00717                 }
00718         }
00719         
00720         // --------------------------------------------------------------------
00721         
00722         /**
00723          * Set Radio
00724          *
00725          * Enables radio buttons to be set to the value the user
00726          * selected in the event of an error
00727          *
00728          * @access      public
00729          * @param       string
00730          * @param       string
00731          * @return      string
00732          */     
00733         function set_radio($field = '', $value = '')
00734         {
00735                 if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
00736                 {
00737                         return '';
00738                 }
00739                         
00740                 if ($_POST[$field] == $value)
00741                 {
00742                         return ' checked="checked"';
00743                 }
00744         }
00745         
00746         // --------------------------------------------------------------------
00747         
00748         /**
00749          * Set Checkbox
00750          *
00751          * Enables checkboxes to be set to the value the user
00752          * selected in the event of an error
00753          *
00754          * @access      public
00755          * @param       string
00756          * @param       string
00757          * @return      string
00758          */     
00759         function set_checkbox($field = '', $value = '')
00760         {
00761                 if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
00762                 {
00763                         return '';
00764                 }
00765                         
00766                 if ($_POST[$field] == $value)
00767                 {
00768                         return ' checked="checked"';
00769                 }
00770         }
00771         
00772         // --------------------------------------------------------------------
00773         
00774         /**
00775          * Prep data for form
00776          *
00777          * This function allows HTML to be safely shown in a form.
00778          * Special characters are converted.
00779          *
00780          * @access      public
00781          * @param       string
00782          * @return      string
00783          */
00784         function prep_for_form($data = '')
00785         {
00786                 if (is_array($data))
00787                 {
00788                         foreach ($data as $key => $val)
00789                         {
00790                                 $data[$key] = $this->prep_for_form($val);
00791                         }
00792                         
00793                         return $data;
00794                 }
00795                 
00796                 if ($this->_safe_form_data == FALSE OR $data == '')
00797                 {
00798                         return $data;
00799                 }
00800 
00801                 return str_replace(array("'", '"', '<', '>'), array("&#39;", "&quot;", '&lt;', '&gt;'), stripslashes($data));
00802         }
00803         
00804         // --------------------------------------------------------------------
00805         
00806         /**
00807          * Prep URL
00808          *
00809          * @access      public
00810          * @param       string
00811          * @return      string
00812          */     
00813         function prep_url($str = '')
00814         {
00815                 if ($str == 'http://' OR $str == '')
00816                 {
00817                         $_POST[$this->_current_field] = '';
00818                         return;
00819                 }
00820                 
00821                 if (substr($str, 0, 7) != 'http://' && substr($str, 0, 8) != 'https://')
00822                 {
00823                         $str = 'http://'.$str;
00824                 }
00825                 
00826                 $_POST[$this->_current_field] = $str;
00827         }
00828         
00829         // --------------------------------------------------------------------
00830         
00831         /**
00832          * Strip Image Tags
00833          *
00834          * @access      public
00835          * @param       string
00836          * @return      string
00837          */     
00838         function strip_image_tags($str)
00839         {
00840                 $_POST[$this->_current_field] = $this->CI->input->strip_image_tags($str);
00841         }
00842         
00843         // --------------------------------------------------------------------
00844         
00845         /**
00846          * XSS Clean
00847          *
00848          * @access      public
00849          * @param       string
00850          * @return      string
00851          */     
00852         function xss_clean($str)
00853         {
00854                 $_POST[$this->_current_field] = $this->CI->input->xss_clean($str);
00855         }
00856         
00857         // --------------------------------------------------------------------
00858         
00859         /**
00860          * Convert PHP tags to entities
00861          *
00862          * @access      public
00863          * @param       string
00864          * @return      string
00865          */     
00866         function encode_php_tags($str)
00867         {
00868                 $_POST[$this->_current_field] = str_replace(array('<?php', '<?PHP', '<?', '?>'),  array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
00869         }
00870 
00871 }
00872 // END Validation Class
00873 
00874 /* End of file Validation.php */
00875 /* Location: ./system/libraries/Validation.php */