Changeset 550


Ignore:
Timestamp:
Nov 24, 2015 5:38:54 PM (8 years ago)
Author:
anonymous
Message:

Escaped quotes from email from names.
Changed logMsg string truncation method and added version to email log msg.
Better variable testing in carry queries.
Spelling errors.
Added runtime cache to Currency.
Added logging to form validation.
More robust form validation.
Added json serialization methond to Version.

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/docs/examples/contact_form/contact.php

    r479 r550  
    44 * For details visit the project site: <http://trac.strangecode.com/codebase/>
    55 * Copyright 2001-2012 Strangecode, LLC
    6  * 
     6 *
    77 * This file is part of The Strangecode Codebase.
    88 *
     
    1111 * Free Software Foundation, either version 3 of the License, or (at your option)
    1212 * any later version.
    13  * 
     13 *
    1414 * The Strangecode Codebase is distributed in the hope that it will be useful, but
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1616 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    1717 * details.
    18  * 
     18 *
    1919 * You should have received a copy of the GNU General Public License along with
    2020 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
     
    5959        $email = new Email(array(
    6060            'to' => $email_to,
    61             'from' => sprintf('%s <%s>', getFormData('name'), getFormData('email')),
     61            'from' => sprintf('"%s" <%s>', addcslashes(getFormData('name'), '"'), getFormData('email')),
    6262            'subject' => 'Contact form email',
    6363        ));
     
    110110    $fv->notEmpty('name', sprintf(_("%s cannot be blank."), _("Name")));
    111111    $fv->stringLength('name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Name"), 0, 255));
    112    
     112
    113113    $fv->notEmpty('email', sprintf(_("%s cannot be blank."), _("Email")));
    114114    $fv->stringLength('email', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Email"), 0, 255));
    115115    $fv->validateEmail('email');
    116    
     116
    117117    $fv->notEmpty('message', sprintf(_("%s cannot be blank."), _("Message")));
    118118    $fv->stringLength('message', 0, 32000, sprintf(_("%s must be %d-to-%d characters in length."), _("Message"), 0, 32000));
  • trunk/docs/version.txt

    r541 r550  
    1 2.2.0-3
     12.2.0-4
  • trunk/lib/App.inc.php

    r547 r550  
    4242class App
    4343{
    44 
    4544    // Minimum version of PHP required for this version of the Codebase.
    4645    const CODEBASE_MIN_PHP_VERSION = '5.3.0';
     
    753752
    754753        // Serialize multi-line messages.
    755         $message = preg_replace('/\s+/m', ' ', $message);
     754        $message = preg_replace('/\s+/m', ' ', trim($message));
    756755
    757756        // Store this event under a unique key, counting each time it occurs so that it only gets reported a limited number of times.
     
    807806            'file:line' => "$file : $line",
    808807            'url'       => mb_substr(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '', 0, 1024),
    809             'message'   => $message
     808            'message'   => mb_substr($message, 0, 1024),
    810809        );
    811810        // Here's a shortened version of event data.
     
    819818        if (false !== $this->getParam('log_file_priority') && $priority <= $this->getParam('log_file_priority')) {
    820819            $event_str = '[' . join('] [', $event_short) . ']';
    821             error_log(mb_substr($event_str, 0, 1024) . "\n", 3, $this->getParam('log_directory') . '/' . $this->getParam('log_filename'));
     820            error_log("$event_str\n", 3, $this->getParam('log_directory') . '/' . $this->getParam('log_filename'));
    822821        }
    823822
     
    826825            $hostname = (isset($_SERVER['HTTP_HOST']) && '' != $_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n');
    827826            $subject = sprintf('[%s %s] %s', $hostname, $event['type'], mb_substr($event['message'], 0, 64));
    828             $email_msg = sprintf("A %s log event occurred on %s\n\n", $event['type'], $hostname);
     827            $email_msg = sprintf("A log event of type '%s' occurred on %s\n\n", $event['type'], $hostname);
    829828            $headers = 'From: ' . $this->getParam('site_email');
    830829            foreach ($event as $k=>$v) {
    831                 $email_msg .= sprintf("%-11s%s\n", $k, $v);
    832             }
     830                $email_msg .= sprintf("%-16s %s\n", $k, $v);
     831            }
     832            $email_msg .= sprintf("%-16s %s\n", 'codebase version', $this->getParam('codebase_version'));
     833            $email_msg .= sprintf("%-16s %s\n", 'site version', $this->getParam('site_version'));
    833834            mb_send_mail($this->getParam('log_to_email_address'), $subject, $email_msg, $headers);
    834835        }
     
    916917        foreach ($query_key as $k) {
    917918            // If not already set, and there is a non-empty value provided in the request...
    918             if (!isset($this->_carry_queries[$k]) && false !== getFormData($k, $default)) {
     919            if (isset($k) && '' != $k && !isset($this->_carry_queries[$k]) && false !== getFormData($k, $default)) {
    919920                // Copy the value of the specified query argument into the _carry_queries array.
    920921                $this->_carry_queries[$k] = getFormData($k, $default);
     
    990991        $one_time_carry_queries = array();
    991992        if (!is_null($carry_args)) {
    992             if (is_array($carry_args) && !empty($carry_args)) {
    993                 foreach ($carry_args as $key=>$arg) {
    994                     // Get query from appropriate source.
    995                     if (false === $arg) {
    996                         $do_carry_queries = false;
    997                     } else if (false !== getFormData($arg, false)) {
    998                         $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available.
    999                     } else if (!is_numeric($key) && '' != $arg) {
    1000                         $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data).
     993            if (is_array($carry_args)) {
     994                if (!empty($carry_args)) {
     995                    foreach ($carry_args as $key=>$arg) {
     996                        // Get query from appropriate source.
     997                        if (false === $arg) {
     998                            $do_carry_queries = false;
     999                        } else if (false !== getFormData($arg, false)) {
     1000                            $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available.
     1001                        } else if (!is_numeric($key) && '' != $arg) {
     1002                            $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data).
     1003                        }
    10011004                    }
    10021005                }
     
    11101113        $one_time_carry_queries = array();
    11111114        if (!is_null($carry_args)) {
    1112             if (is_array($carry_args) && !empty($carry_args)) {
    1113                 foreach ($carry_args as $key=>$arg) {
    1114                     // Get query from appropriate source.
    1115                     if (false === $arg) {
    1116                         $do_carry_queries = false;
    1117                     } else if (false !== getFormData($arg, false)) {
    1118                         $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available.
    1119                     } else if (!is_numeric($key) && '' != $arg) {
    1120                         $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data).
     1115            if (is_array($carry_args)) {
     1116                if (!empty($carry_args)) {
     1117                    foreach ($carry_args as $key=>$arg) {
     1118                        // Get query from appropriate source.
     1119                        if (false === $arg) {
     1120                            $do_carry_queries = false;
     1121                        } else if (false !== getFormData($arg, false)) {
     1122                            $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available.
     1123                        } else if (!is_numeric($key) && '' != $arg) {
     1124                            $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data).
     1125                        }
    11211126                    }
    11221127                }
     
    11361141                if (is_array($val)) {
    11371142                    foreach ($val as $subval) {
    1138                         printf('<input type="hidden" name="%s[]" value="%s" />', $key, $subval);
     1143                        if ('' != $key && '' != $subval) {
     1144                            printf('<input type="hidden" name="%s[]" value="%s" />', $key, $subval);
     1145                        }
    11391146                    }
    1140                 } else {
     1147                } else if ('' != $key && '' != $val) {
    11411148                    printf('<input type="hidden" name="%s" value="%s" />', $key, $val);
    11421149                }
  • trunk/lib/Auth_SQL.inc.php

    r541 r550  
    3232class Auth_SQL
    3333{
    34 
    3534    // Available hash types for class Auth_SQL.
    3635    const ENCRYPT_PLAINTEXT = 1;
     
    7069
    7170        // The type of hash to use for passwords stored in the db_table. Use one of the Auth_SQL::ENCRYPT_* types specified above.
    72         // Hardened password hashes rely on the same key/salt being used to compare hashs.
     71        // Hardened password hashes rely on the same key/salt being used to compare hashes.
    7372        // Be aware that when using one of the hardened types the App signing_key or $more_salt below cannot change!
    7473        'hash_type' => self::ENCRYPT_MD5,
     
    176175            }
    177176
    178             // The minimal columns for a table compatable with the Auth_SQL class.
     177            // The minimal columns for a table compatible with the Auth_SQL class.
    179178            $db->query("CREATE TABLE IF NOT EXISTS " . $db->escapeString($this->getParam('db_table')) . " (
    180179                " . $this->getParam('db_primary_key') . " MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
     
    475474                switch ($user_data['blocked_reason']) {
    476475                    case 'account abuse' :
    477                         $app->raiseMsg(sprintf(_("This account has been blocked due to possible account abuse. Please contact us to reactivate."), null), MSG_WARNING, __FILE__, __LINE__);
     476                        $app->raiseMsg(sprintf(_("This account has been blocked due to possible account abuse. Please contact an administrator to reactivate."), null), MSG_WARNING, __FILE__, __LINE__);
    478477                        break;
    479478                    default :
     
    507506                if ($this->get('abuse_warning_level') < $this->_params['login_abuse_warnings']) {
    508507                    // Warn the user with a password reset.
    509                     $this->resetPassword(null, _("This is a security precaution. We have detected this account has been accessed from multiple computers simultaneously. It is against policy to share login information with others. If further account abuse is detected this account will be blocked."));
     508                    $this->resetPassword(null, _("This is a security precaution. We have detected this account has been accessed from multiple computers simultaneously. It is against policy to share credentials with others. If further account abuse is detected this account will be blocked."));
    510509                    $app->raiseMsg(_("Your password has been reset as a security precaution. Please check your email for more information."), MSG_NOTICE, __FILE__, __LINE__);
    511510                    $app->logMsg(sprintf('Account abuse detected for user_id %s (%s) from IP %s', $this->get('user_id'), $this->get('username'), $this->get('remote_ip')), LOG_WARNING, __FILE__, __LINE__);
     
    652651            if (strtotime($_SESSION['_auth_sql'][$this->_ns]['last_access_datetime']) > (time() - 43200)) {
    653652                // Only raise message if last session is less than 12 hours old.
    654                 $app->raiseMsg(_("Your session has expired. You need to log-in again."), MSG_NOTICE, __FILE__, __LINE__);
     653                $app->raiseMsg(sprintf(_("For your safety we logged you out after being idle for %s. Please log in again."), humanTime($this->_params['idle_timeout'], 'hour', '%01.0f')), MSG_NOTICE, __FILE__, __LINE__);
    655654            }
    656655
     
    10441043            $email = new Email(array(
    10451044                'to' => $user_data['email'],
    1046                 'from' => sprintf('%s <%s>', $app->getParam('site_name'), $app->getParam('site_email')),
     1045                'from' => sprintf('"%s" <%s>', addcslashes($app->getParam('site_name'), '"'), $app->getParam('site_email')),
    10471046                'subject' => sprintf('%s password change', $app->getParam('site_name'))
    10481047            ));
  • trunk/lib/Currency.inc.php

    r502 r550  
    4040class Currency
    4141{
    42 
    4342    // Configuration parameters for this object.
    4443    protected $_params = array(
     
    4948        'api_key' => '', // Used only by xurrency API.
    5049    );
     50
     51    // Static runtime cache of values.
     52    private static $rates = array();
    5153
    5254    /**
     
    143145        $app =& App::getInstance();
    144146
     147        // If we've looked-up this rate during this run, return it from the runtime cache.
     148        $rate_key = sprintf('%s-to-%s', $base, $target);
     149        if (isset(self::$rates[$rate_key])) {
     150            $app->logMsg(sprintf('Found %s in runtime cache: %s', $rate_key, self::$rates[$rate_key]), LOG_DEBUG, __FILE__, __LINE__);
     151            return self::$rates[$rate_key];
     152        }
     153
    145154        $cache_file_path = sprintf('%s/%s-to-%s', $this->getParam('cache_dir'), $base, $target);
     155        if (!is_dir(dirname($cache_file_path))) {
     156            mkdir(dirname($cache_file_path));
     157        }
    146158        $cache_file_mtime = @filemtime($cache_file_path);
    147159        if (!$this->getParam('cache_result') || !$cache_file_mtime || $cache_file_mtime < time() - $this->getParam('cache_age')) {
     
    172184        }
    173185        $app->logMsg(sprintf('Found currency exchange rate: %s-to-%s = %s', $base, $target, $value), LOG_DEBUG, __FILE__, __LINE__);
     186
     187        // Store the value in the runtime cache.
     188        self::$rates[$rate_key] = trim($value);
     189
    174190        return trim($value);
    175191    }
     
    239255                return (float) $aCurrencies[$parameters['base']][$parameters['target']];
    240256            } else {
    241                 $app->logMsg(sprintf('API %s does not have base %s or target %s', $this->getParam('api'), $parameters['base'], $parameters['target']), LOG_WARNING, __FILE__, __LINE__);
     257                $app->logMsg(sprintf('API %s does not have base %s or target %s', $this->getParam('api'), $parameters['base'], $parameters['target']), LOG_ALERT, __FILE__, __LINE__);
    242258                return false;
    243259            }
    244260
    245261        default :
    246             trigger_error('Unknown API: ' . $this->getParam('api'), E_USER_ERROR);
    247             die;
    248             break;
     262            $app->logMsg(sprintf('Unknown currency API: %s', $this->getParam('api')), LOG_ERR, __FILE__, __LINE__);
     263            return false;
    249264        }
    250265    }
  • trunk/lib/DB.inc.php

    r547 r550  
    374374     * @param  string $table                The name of the table to search.
    375375     * @param  array  $columns              An array of column names.
    376      * @param  bool   $strict               Exact schema match, or are additional fields in the table okay?
     376     * @param  bool   $strict               Exact schema match. If TRUE, test if *only* the given columns exist. If FALSE, test if given columns exist (possibly amongst others).
    377377     * @param  bool   $use_cached_results   Get fresh table info (in case DB changed).
    378378     * @return bool                         true if column(s) exist.
  • trunk/lib/Email.inc.php

    r502 r550  
    3434$email = new Email(array(
    3535    'to' => array($frm['email'], 'q@lovemachine.local'),
    36     'from' => sprintf('%s <%s>', $app->getParam('site_name'), $app->getParam('site_email')),
     36    'from' => sprintf('"%s" <%s>', addcslashes($app->getParam('site_name'), '"'), $app->getParam('site_email')),
    3737    'subject' => 'Your account has been activated',
    3838));
  • trunk/lib/FormValidator.inc.php

    r534 r550  
    3737$fv = new FormValidator();
    3838
    39 $fv->empty('field_name', sprintf(_("%s cannot be blank."), _("Field name")));
    40 $fv->stringLength('field_name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Field name"), 0, 255));
    41 $fv->isInteger('field_name', sprintf(_("%s must be an integer."), _("Field name")));
    42 $fv->checkRegex('field_name', '/^\d{4}$|^$/', true, sprintf(_("%s must be in MMYY format."), _("Field name")));
    43 $fv->numericRange('field_name', 0, 65535, sprintf(_("%s must be a number between %d and %d."), _("Field name"), 0, 65535));
    44 $fv->validatePhone('field_name');
    45 $fv->validateEmail('field_name');
    46 $fv->validateStrDate('field_name', sprintf(_("%s must be a valid date in YYYY-MM-DD format."), _("Field name")));
     39$fv->empty('field_name', sprintf(_("%s cannot be blank."), _("Field name")), MSG_ERR, __FILE__, __LINE__);
     40$fv->stringLength('field_name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Field name"), 0, 255), MSG_ERR, __FILE__, __LINE__);
     41$fv->isInteger('field_name', sprintf(_("%s must be an integer."), _("Field name")), MSG_ERR, __FILE__, __LINE__);
     42$fv->checkRegex('field_name', '/^\d{4}$|^$/', true, sprintf(_("%s must be in MMYY format."), _("Field name")), MSG_ERR, __FILE__, __LINE__);
     43$fv->numericRange('field_name', 0, 65535, sprintf(_("%s must be a number between %d and %d."), _("Field name"), 0, 65535), MSG_ERR, __FILE__, __LINE__);
     44$fv->validatePhone('field_name', MSG_ERR, __FILE__, __LINE__);
     45$fv->validateEmail('field_name', MSG_ERR, __FILE__, __LINE__);
     46$fv->validateStrDate('field_name', sprintf(_("%s must be a valid date in YYYY-MM-DD format."), _("Field name")), MSG_ERR, __FILE__, __LINE__);
    4747if (is_null($var)) {
    48     $fv->addError('field_name', sprintf(_("%s is invalid."), _("Field name")));
     48    $fv->addError('field_name', sprintf(_("%s is invalid."), _("Field name")), MSG_ERR, __FILE__, __LINE__);
    4949}
    5050if ($fv->anyErrors()) {
     
    7373
    7474    /**
    75      * FormValidator constructor.
    76      *
    77      * @access public
    78      * @param array $params Configuration parameters for this object.
    79      */
     75    * FormValidator constructor.
     76    *
     77    * @access public
     78    * @param array $params Configuration parameters for this object.
     79    */
    8080    public function __construct($params=array())
    8181    {
     
    8585
    8686    /**
    87      * Set (or overwrite existing) parameters by passing an array of new parameters.
    88      *
    89      * @access public
    90      * @param  array    $params     Array of parameters (key => val pairs).
    91      */
     87    * Set (or overwrite existing) parameters by passing an array of new parameters.
     88    *
     89    * @access public
     90    * @param  array    $params     Array of parameters (key => val pairs).
     91    */
    9292    public function setParam($params)
    9393    {
     
    103103
    104104    /**
    105      * Return the value of a parameter, if it exists.
    106      *
    107      * @access public
    108      * @param string $param        Which parameter to return.
    109      * @return mixed               Configured parameter value.
    110      */
     105    * Return the value of a parameter, if it exists.
     106    *
     107    * @access public
     108    * @param string $param        Which parameter to return.
     109    * @param  const  $type  A LOG_* constant (see App->logMsg())
     110    * @param  const  $file  Filename to log (usually __FILE__)
     111    * @param  const  $line  Line number to log (usually __LINE__)
     112    * @return mixed               Configured parameter value.
     113    */
    111114    public function getParam($param)
    112115    {
     
    122125
    123126    /**
    124      * Return the current list of errors.
    125      *
    126      * @return array    an array of errors in the following arrangement:
    127      *                  keys: the name of the variable with an error
    128      *                  vals: the message to display for that error
    129      */
     127    * Return the current list of errors.
     128    *
     129    * @param  const  $type  A LOG_* constant (see App->logMsg())
     130    * @param  const  $file  Filename to log (usually __FILE__)
     131    * @param  const  $line  Line number to log (usually __LINE__)
     132    * @return array    an array of errors in the following arrangement:
     133    *                  keys: the name of the variable with an error
     134    *                  vals: the message to display for that error
     135    */
    130136    public function getErrorList()
    131137    {
     
    134140
    135141    /**
    136      * Add an error to the errors stack.
    137      *
    138      * @param   string $form_name   The name of the incoming form variable.
    139      * @param   string $msg         The error message for that form.
    140      * @param   int    $type        The type of message: MSG_NOTICE,
    141      *                              MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
    142      * @param   string $file        __FILE__.
    143      * @param   string $line        __LINE__.
    144      */
     142    * Add an error to the errors stack.
     143    *
     144    * @param   string $form_name   The name of the incoming form variable.
     145    * @param   string $msg         The error message for that form.
     146    * @param   int    $type        The type of message: MSG_NOTICE,
     147    *                              MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
     148    * @param   string $file        __FILE__.
     149    * @param   string $line        __LINE__.
     150    */
    145151    public function addError($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
    146152    {
     
    155161
    156162    /**
    157      * Check whether any errors have been triggered.
    158      *
    159      * @param  string $form_name the name of the incoming form variable
    160      *
    161      * @return bool   true if any errors were found, or if found for
    162      *                a variable of $form_name, false otherwise
    163      */
     163    * Check whether any errors have been triggered.
     164    *
     165    * @param  string $form_name the name of the incoming form variable
     166    * @param  const  $type  A LOG_* constant (see App->logMsg())
     167    * @param  const  $file  Filename to log (usually __FILE__)
     168    * @param  const  $line  Line number to log (usually __LINE__)
     169    * @return bool   true if any errors were found, or if found for
     170    *                a variable of $form_name, false otherwise
     171    */
    164172    public function anyErrors($form_name=null)
    165173    {
     
    177185
    178186    /**
    179      * Reset the error list.
    180      */
     187    * Reset the error list.
     188    */
    181189    public function resetErrorList()
    182190    {
     
    185193
    186194    /**
    187      * Prints the HTML for displaying error messages.
    188      *
    189      * @param   string  $above    Additional message to print above error messages (e.g. "Oops!").
    190      * @param   string  $below    Additional message to print below error messages (e.g. "Please fix and resubmit").
    191      * @param   string  $print_gotohash_js  Print a line of javascript that scrolls the browser window down to view any error messages.
    192      * @param   string  $hash     The #hashtag to scroll to.
    193      * @access  public
    194      * @author  Quinn Comendant <quinn@strangecode.com>
    195      * @since   15 Jul 2005 01:39:14
    196      */
     195    * Prints the HTML for displaying error messages.
     196    *
     197    * @param   string  $above    Additional message to print above error messages (e.g. "Oops!").
     198    * @param   string  $below    Additional message to print below error messages (e.g. "Please fix and resubmit").
     199    * @param   string  $print_gotohash_js  Print a line of javascript that scrolls the browser window down to view any error messages.
     200    * @param   string  $hash     The #hashtag to scroll to.
     201    * @access  public
     202    * @author  Quinn Comendant <quinn@strangecode.com>
     203    * @since   15 Jul 2005 01:39:14
     204    */
    197205    public function printErrorMessages($above='', $below='', $print_gotohash_js=false, $hash='sc-msg-formvalidator')
    198206    {
    199207        $app =& App::getInstance();
    200208        if ($this->anyErrors()) {
    201             ?><div class="sc-msg" id="sc-msg-formvalidator"><?php
     209            // data-gotohash="
" is to be used by sites that refuse inline JS (via CSP) but needs to be referenced from an external JS.
     210            ?><div class="sc-msg" id="sc-msg-formvalidator" data-gotohash="<?php echo oTxt($hash); ?>"><?php
    202211            if ('' != $above) {
    203212                ?><div class="sc-above"><?php echo oTxt($above); ?></div><?php
     
    245254
    246255    /**
    247      * If this form has an error, print an error marker like "<<".
    248      *
    249      * @param  string $form_name the name of the incoming form variable
    250      * @param  string $marker    A string to print if there is an error. if
    251      *                           not provided, use default.
    252      */
     256    * If this form has an error, print an error marker like "<<".
     257    *
     258    * @param  string $form_name the name of the incoming form variable
     259    * @param  string $marker    A string to print if there is an error. if
     260    *                           not provided, use default.
     261    */
    253262    public function err($form_name, $marker=null)
    254263    {
     
    280289
    281290    /**
    282      * Ensure the length of string is non-zero.
    283      *
    284      * @param  string $form_name the name of the incoming form variable
    285      * @param  string $msg       the message to display on error
    286      *
    287      * @return bool   true if form is not empty, false otherwise.
    288      */
    289     public function notEmpty($form_name, $msg='')
    290     {
    291         if (!Validator::isEmpty(getFormData($form_name))) {
    292             return true;
    293         } else {
    294             $this->addError($form_name, $msg);
     291    * Ensure the length of string is non-zero.
     292    *
     293    * @param  string $form_name the name of the incoming form variable
     294    * @param  string $msg       the message to display on error
     295    * @param  const  $type  A LOG_* constant (see App->logMsg())
     296    * @param  const  $file  Filename to log (usually __FILE__)
     297    * @param  const  $line  Line number to log (usually __LINE__)
     298    * @return bool   true if form is not empty, false otherwise.
     299    */
     300    public function notEmpty($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     301    {
     302        if (Validator::notEmpty(getFormData($form_name), LOG_NOTICE, $file, $line)) {
     303            return true;
     304        } else {
     305            $this->addError($form_name, $msg, $type, $file, $line);
    295306            return false;
    296307        }
     
    298309
    299310    /*
    300     * We were using the isEmpty method *wrong* all these years and should have been using notEmpty.
    301     * But the fact is the only use is to ensure a value is not empty, so this function simply becomes
    302     * an alias of the one-true notEmpty() function.
     311    * We were using the isEmpty method *wrong* for years and should have been using notEmpty becuase it is more grammatically correct.
     312    * Because the only use is to ensure a value is not empty, we're simply going to alias this method to notEmpty().
    303313    * @since    03 Jun 2006 22:56:46
    304314    */
    305     public function isEmpty($form_name, $msg='')
    306     {
    307         return $this->notEmpty($form_name, $msg);
    308     }
    309 
    310     /**
    311      * Check whether input is a string.
    312      *
    313      * @param  string $form_name the name of the incoming form variable
    314      * @param  string $msg       the message to display on error
    315      *
    316      * @return bool   true if form is a string, false otherwise.
    317      */
    318     public function isString($form_name, $msg='')
    319     {
    320         if (Validator::isString(getFormData($form_name))) {
    321             return true;
    322         } else {
    323             $this->addError($form_name, $msg);
    324             return false;
    325         }
    326     }
    327 
    328     /**
    329      * Check whether input is a number. Allows negative numbers.
    330      *
    331      * @param  string $form_name the name of the incoming form variable
    332      * @param  string $msg       the message to display on error
    333      *
    334      * @return bool   true if no errors found, false otherwise
    335      */
    336     public function isNumber($form_name, $msg='')
    337     {
    338         if (Validator::isNumber(getFormData($form_name))) {
    339             return true;
    340         } else {
    341             $this->addError($form_name, $msg);
    342             return false;
    343         }
    344     }
    345 
    346     /**
    347      * addError if input is NOT an integer. Don't just use is_int() because the
    348      * data coming from the user is *really* a string.
    349      *
    350      * @param  string $form_name the name of the incoming form variable
    351      * @param  string $msg       the message to display on error
    352      *
    353      * @return bool   true if value is an integer
    354      */
    355     public function isInteger($form_name, $msg='', $negative_ok=false)
    356     {
    357         if (Validator::isInteger(getFormData($form_name), $negative_ok)) {
    358             return true;
    359         } else {
    360             $this->addError($form_name, $msg);
    361             return false;
    362         }
    363     }
    364 
    365     /**
    366      * Check whether input is a float. Don't just use is_float() because the
    367      * data coming from the user is *really* a string. Integers will also
    368      * pass this test.
    369      *
    370      * @param  string $form_name the name of the incoming form variable
    371      * @param  string $msg       the message to display on error
    372      *
    373      * @return bool   true if value is a float
    374      */
    375     public function isFloat($form_name, $msg='', $negative_ok=false)
    376     {
    377         if (Validator::isFloat(getFormData($form_name), $negative_ok)) {
    378             return true;
    379         } else {
    380             $this->addError($form_name, $msg);
    381             return false;
    382         }
    383     }
    384 
    385     /**
    386      * Check whether input is a Decimal or Fixed type. Check values to be stored in mysql decimal, numeric, num, or fixed types.
    387      * Note: some integers and floats will also pass this test.
    388      * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
    389      *
    390      * @param  string $form_name the name of the incoming form variable
    391      * @param  string $msg       the message to display on error
    392      * @param  string $val The input data to validate.
    393      * @param  bool $negative_ok  If the value can be unsigned.
    394      * @param  int  $max    Total max number of digits.
    395      * @param  int  $dec    Total max number of digits after the decimal place.
    396      * @return bool   true if value is a float
    397      */
    398     public function isDecimal($form_name, $msg='', $negative_ok=false, $max=10, $dec=2)
    399     {
    400         if (Validator::isDecimal(getFormData($form_name), $negative_ok, $max, $dec)) {
    401             return true;
    402         } else {
    403             $this->addError($form_name, $msg);
    404             return false;
    405         }
    406     }
    407 
    408     /**
    409      * Check whether input is an array.
    410      *
    411      * @param  string $form_name the name of the incoming form variable
    412      * @param  string $msg       the message to display on error
    413      *
    414      * @return bool   true if value is a float
    415      */
    416     public function isArray($form_name, $msg='')
    417     {
    418         if (Validator::isArray(getFormData($form_name))) {
    419             return true;
    420         } else {
    421             $this->addError($form_name, $msg);
    422             return false;
    423         }
    424     }
    425 
    426     /**
    427      * Check whether input matches the specified perl regular expression
    428      * pattern.
    429      *
    430      * @param  string $form_name        The name of the incoming form variable
    431      * @param  int    $regex            Perl regex that the string must match
    432      * @param  bool   $valid_on_match   Set to true to be valid if match, or false to be valid if the match fails.
    433      * @param  string $msg              The message to display on error
    434      *
    435      * @return bool   true if value passes regex test
    436      */
    437     public function checkRegex($form_name, $regex, $valid_on_match=true, $msg='')
    438     {
    439         if (Validator::checkRegex(getFormData($form_name), $regex, $valid_on_match)) {
    440             return true;
    441         } else {
    442             $this->addError($form_name, $msg);
    443             return false;
    444         }
    445     }
    446 
    447     /**
    448      * Tests if the string length is between specified values. Whitespace excluded for min.
    449      *
    450      * @param  string $form_name the name of the incoming form variable
    451      * @param  int    $min       minimum length of string, inclusive
    452      * @param  int    $max       maximum length of string, inclusive
    453      * @param  string $msg       the message to display on error
    454      *
    455      * @return bool   true if string length is within given boundaries
    456      */
    457     public function stringLength($form_name, $min, $max, $msg='')
    458     {
    459         if (Validator::stringLength(getFormData($form_name), $min, $max)) {
    460             return true;
    461         } else {
    462             $this->addError($form_name, $msg);
    463             return false;
    464         }
    465     }
    466 
    467     /**
    468      * Check whether input is within a valid numeric range.
    469      *
    470      * @param  string $form_name the name of the incoming form variable
    471      * @param  int    $min       minimum value of number, inclusive
    472      * @param  int    $max       maximum value of number, inclusive
    473      * @param  string $msg       the message to display on error
    474      *
    475      * @return bool   true if no errors found, false otherwise
    476      */
    477     public function numericRange($form_name, $min, $max, $msg='')
    478     {
    479         if (Validator::numericRange(getFormData($form_name), $min, $max)) {
    480             return true;
    481         } else {
    482             $this->addError($form_name, $msg);
    483             return false;
    484         }
    485     }
    486 
    487     /**
    488      * Validates an email address based on the recommendations in RFC 3696.
    489      * Is more loose than restrictive, to allow the many valid variants of
    490      * email addresses while catching the most common mistakes.
    491      * http://www.faqs.org/rfcs/rfc822.html
    492      * http://www.faqs.org/rfcs/rfc2822.html
    493      * http://www.faqs.org/rfcs/rfc3696.html
    494      * http://www.faqs.org/rfcs/rfc1035.html
    495      *
    496      * @access  public
    497      * @param   string  $form_name  The name of the incoming form variable.
    498      * @return  bool    Validity of address.
    499      * @author  Quinn Comendant <quinn@strangecode.com>
    500      */
    501     public function validateEmail($form_name, $strict=false)
     315    public function isEmpty($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     316    {
     317        return $this->notEmpty($form_name, $msg, $type, $file, $line);
     318    }
     319
     320    /**
     321    * Check whether input is a string.
     322    *
     323    * @param  string $form_name the name of the incoming form variable
     324    * @param  string $msg       the message to display on error
     325    * @param  const  $type  A LOG_* constant (see App->logMsg())
     326    * @param  const  $file  Filename to log (usually __FILE__)
     327    * @param  const  $line  Line number to log (usually __LINE__)
     328    * @return bool   true if form is a string, false otherwise.
     329    */
     330    public function isString($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     331    {
     332        if (Validator::isString(getFormData($form_name), LOG_NOTICE, $file, $line)) {
     333            return true;
     334        } else {
     335            $this->addError($form_name, $msg, $type, $file, $line);
     336            return false;
     337        }
     338    }
     339
     340    /**
     341    * Check whether input is a number. Allows negative numbers.
     342    *
     343    * @param  string $form_name the name of the incoming form variable
     344    * @param  string $msg       the message to display on error
     345    * @param  const  $type  A LOG_* constant (see App->logMsg())
     346    * @param  const  $file  Filename to log (usually __FILE__)
     347    * @param  const  $line  Line number to log (usually __LINE__)
     348    * @return bool   true if no errors found, false otherwise
     349    */
     350    public function isNumber($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     351    {
     352        if (Validator::isNumber(getFormData($form_name), LOG_NOTICE, $file, $line)) {
     353            return true;
     354        } else {
     355            $this->addError($form_name, $msg, $type, $file, $line);
     356            return false;
     357        }
     358    }
     359
     360    /**
     361    * addError if input is NOT an integer. Don't just use is_int() because the
     362    * data coming from the user is *really* a string.
     363    *
     364    * @param  string $form_name the name of the incoming form variable
     365    * @param  string $msg       the message to display on error
     366    * @param  const  $type  A LOG_* constant (see App->logMsg())
     367    * @param  const  $file  Filename to log (usually __FILE__)
     368    * @param  const  $line  Line number to log (usually __LINE__)
     369    * @return bool   true if value is an integer
     370    */
     371    public function isInteger($form_name, $msg='', $negative_ok=false, $type=MSG_ERR, $file=null, $line=null)
     372    {
     373        if (Validator::isInteger(getFormData($form_name), $negative_ok, LOG_NOTICE, $file, $line)) {
     374            return true;
     375        } else {
     376            $this->addError($form_name, $msg, $type, $file, $line);
     377            return false;
     378        }
     379    }
     380
     381    /**
     382    * Check whether input is a float. Don't just use is_float() because the
     383    * data coming from the user is *really* a string. Integers will also
     384    * pass this test.
     385    *
     386    * @param  string $form_name the name of the incoming form variable
     387    * @param  string $msg       the message to display on error
     388    * @param  const  $type  A LOG_* constant (see App->logMsg())
     389    * @param  const  $file  Filename to log (usually __FILE__)
     390    * @param  const  $line  Line number to log (usually __LINE__)
     391    * @return bool   true if value is a float
     392    */
     393    public function isFloat($form_name, $msg='', $negative_ok=false, $type=MSG_ERR, $file=null, $line=null)
     394    {
     395        if (Validator::isFloat(getFormData($form_name), $negative_ok, LOG_NOTICE, $file, $line)) {
     396            return true;
     397        } else {
     398            $this->addError($form_name, $msg, $type, $file, $line);
     399            return false;
     400        }
     401    }
     402
     403    /**
     404    * Check whether input is a Decimal or Fixed type. Use to check values to be stored in mysql decimal, numeric, num, or fixed types.
     405    * The arguments $max and $dec should match M and D of the column definition "DECIMAL(M,D)".
     406    * Note: some integers and floats will also pass this test.
     407    * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
     408    *
     409    * @param  string    $form_name      The name of the incoming form variable
     410    * @param  int       $max            Total max number of digits.
     411    * @param  int       $dec            Total max number of digits after the decimal place.
     412    * @param  string    $msg            The message to display on error
     413    * @param  bool      $negative_ok    If the value can be unsigned.
     414    * @param  const  $type  A LOG_* constant (see App->logMsg())
     415    * @param  const  $file  Filename to log (usually __FILE__)
     416    * @param  const  $line  Line number to log (usually __LINE__)
     417    * @return bool                      True if value is a decimal, false otherwise.
     418    */
     419    public function isDecimal($form_name, $max=10, $dec=2, $negative_ok=false, $msg='', $type=MSG_ERR, $file=null, $line=null)
     420    {
     421        if (Validator::isDecimal(getFormData($form_name), $max, $dec, $negative_ok, LOG_NOTICE, $file, $line)) {
     422            return true;
     423        } else {
     424            // Set the example to a sequence of Ns with $max number of digits and a faction part length of $dec.
     425            $msg = str_replace('{EX}', sprintf('%s.%s', str_repeat('N', $max - $dec), str_repeat('N', $dec)), $msg);
     426            $this->addError($form_name, $msg, $type, $file, $line);
     427            return false;
     428        }
     429    }
     430
     431    /**
     432    * Check whether input is an array.
     433    *
     434    * @param  string $form_name the name of the incoming form variable
     435    * @param  string $msg       the message to display on error
     436    * @param  const  $type  A LOG_* constant (see App->logMsg())
     437    * @param  const  $file  Filename to log (usually __FILE__)
     438    * @param  const  $line  Line number to log (usually __LINE__)
     439    * @return bool   true if value is an array
     440    */
     441    public function isArray($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     442    {
     443        if (Validator::isArray(getFormData($form_name), LOG_NOTICE, $file, $line)) {
     444            return true;
     445        } else {
     446            $this->addError($form_name, $msg, $type, $file, $line);
     447            return false;
     448        }
     449    }
     450
     451    /**
     452    * Check whether input matches the specified perl regular expression
     453    * pattern.
     454    *
     455    * @param  string $form_name        The name of the incoming form variable
     456    * @param  int    $regex            Perl regex that the string must match
     457    * @param  bool   $valid_on_match   Set to true to be valid if match, or false to be valid if the match fails.
     458    * @param  string $msg              The message to display on error
     459    * @param  const  $type  A LOG_* constant (see App->logMsg())
     460    * @param  const  $file  Filename to log (usually __FILE__)
     461    * @param  const  $line  Line number to log (usually __LINE__)
     462    * @return bool   true if value passes regex test (or false if $valid_on_match=false)
     463    */
     464    public function checkRegex($form_name, $regex, $valid_on_match=true, $msg='', $type=MSG_ERR, $file=null, $line=null)
     465    {
     466        if (Validator::checkRegex(getFormData($form_name), $regex, $valid_on_match, LOG_NOTICE, $file, $line)) {
     467            return true;
     468        } else {
     469            $this->addError($form_name, $msg, $type, $file, $line);
     470            return false;
     471        }
     472    }
     473
     474    /**
     475    * Tests if the string length is between specified values. Whitespace excluded for min.
     476    *
     477    * @param  string $form_name the name of the incoming form variable
     478    * @param  int    $min       minimum length of string, inclusive
     479    * @param  int    $max       maximum length of string, inclusive
     480    * @param  string $msg       the message to display on error
     481    * @param  const  $type  A LOG_* constant (see App->logMsg())
     482    * @param  const  $file  Filename to log (usually __FILE__)
     483    * @param  const  $line  Line number to log (usually __LINE__)
     484    * @return bool   true if string length is within given boundaries
     485    */
     486    public function stringLength($form_name, $min, $max, $msg='', $type=MSG_ERR, $file=null, $line=null)
     487    {
     488        if (Validator::stringLength(getFormData($form_name), $min, $max, LOG_NOTICE, $file, $line)) {
     489            return true;
     490        } else {
     491            $this->addError($form_name, $msg, $type, $file, $line);
     492            return false;
     493        }
     494    }
     495
     496    /**
     497    * Check whether input is within a valid numeric range.
     498    *
     499    * @param  string $form_name the name of the incoming form variable
     500    * @param  int    $min       minimum value of number, inclusive
     501    * @param  int    $max       maximum value of number, inclusive
     502    * @param  string $msg       the message to display on error
     503    * @param  const  $type  A LOG_* constant (see App->logMsg())
     504    * @param  const  $file  Filename to log (usually __FILE__)
     505    * @param  const  $line  Line number to log (usually __LINE__)
     506    * @return bool   true if no errors found, false otherwise
     507    */
     508    public function numericRange($form_name, $min, $max, $msg='', $type=MSG_ERR, $file=null, $line=null)
     509    {
     510        if (Validator::numericRange(getFormData($form_name), $min, $max, LOG_NOTICE, $file, $line)) {
     511            return true;
     512        } else {
     513            $this->addError($form_name, $msg, $type, $file, $line);
     514            return false;
     515        }
     516    }
     517
     518    /**
     519    * Validates an email address based on the recommendations in RFC 3696.
     520    * Is more loose than restrictive, to allow the many valid variants of
     521    * email addresses while catching the most common mistakes.
     522    * http://www.faqs.org/rfcs/rfc822.html
     523    * http://www.faqs.org/rfcs/rfc2822.html
     524    * http://www.faqs.org/rfcs/rfc3696.html
     525    * http://www.faqs.org/rfcs/rfc1035.html
     526    *
     527    * @access  public
     528    * @param   string  $form_name   The name of the incoming form variable.
     529    * @param   bool    $strict      Run strict tests (check if the domain exists and has an MX record assigned)
     530    * @param  const  $type  A LOG_* constant (see App->logMsg())
     531    * @param  const  $file  Filename to log (usually __FILE__)
     532    * @param  const  $line  Line number to log (usually __LINE__)
     533    * @return  bool                 Validity of address.
     534    * @author  Quinn Comendant <quinn@strangecode.com>
     535    */
     536    public function validateEmail($form_name, $strict=false, $type=MSG_ERR, $file=null, $line=null)
    502537    {
    503538        $app =& App::getInstance();
     
    511546
    512547        // Validator::validateEmail() returns a value that relates to the Validate::EMAIL_* constants (defined in Validator.inc.php).
    513         switch (Validator::validateEmail($email, $strict)) {
     548        switch (Validator::validateEmail($email, $strict, LOG_NOTICE, $file, $line)) {
    514549        case Validator::EMAIL_REGEX_FAIL:
    515550            // Failed regex match.
    516             $this->addError($form_name, sprintf(_("The email address <em>%s</em> is formatted incorrectly."), oTxt($email)));
     551            $this->addError($form_name, sprintf(_("The email address <em>%s</em> is formatted incorrectly."), oTxt($email)), $type, $file, $line);
    517552            $app->logMsg(sprintf('The email address %s is not valid.', oTxt($email)), LOG_DEBUG, __FILE__, __LINE__);
    518553            return false;
    519554
    520         case Validator::EMAIL_LENGTH_FAIL :
     555        case Validator::EMAIL_LENGTH_FAIL:
    521556            // Failed length requirements.
    522             $this->addError($form_name, sprintf(_("The email address <em>%s</em> is too long (email addresses must have fewer than 256 characters)."), oTxt($email)));
     557            $this->addError($form_name, sprintf(_("The email address <em>%s</em> is too long (email addresses must have fewer than 256 characters)."), oTxt($email)), $type, $file, $line);
    523558            $app->logMsg(sprintf('The email address %s must contain less than 256 characters.', oTxt($email)), LOG_DEBUG, __FILE__, __LINE__);
    524559            return false;
    525560
    526         case Validator::EMAIL_MX_FAIL :
     561        case Validator::EMAIL_MX_FAIL:
    527562            // Failed MX record test.
    528             $this->addError($form_name, sprintf(_("The email address <em>%s</em> does not have a valid domain name"), oTxt($email)));
    529             $app->logMsg(sprintf('The email address %s does not have a valid domain name.', oTxt($email)), LOG_INFO, __FILE__, __LINE__);
    530             return false;
    531 
    532         case Validator::EMAIL_SUCCESS :
     563            $this->addError($form_name, sprintf(_("The email address <em>%s</em> does not have a valid domain name"), oTxt($email)), $type, $file, $line);
     564            $app->logMsg(sprintf('The email address %s does not have a valid domain name.', oTxt($email)), LOG_NOTICE, __FILE__, __LINE__);
     565            return false;
     566
     567        case Validator::EMAIL_SUCCESS:
    533568        default :
    534569            return true;
     
    537572
    538573    /**
    539      * Check whether input is a valid phone number. Notice: it is now set
    540      * to allow characters like - or () or + so people can type in a phone
    541      * number that looks like: +1 (530) 555-1212
    542      *
    543      * @param  string  $form_name the name of the incoming form variable
    544      *
    545      * @return bool    true if no errors found, false otherwise
    546      */
    547     public function validatePhone($form_name)
     574    * Check whether input is a valid phone number. Notice: it is now set
     575    * to allow characters like - or () or + so people can type in a phone
     576    * number that looks like: +1 (530) 555-1212
     577    *
     578    * @param  string  $form_name the name of the incoming form variable
     579    * @param  const  $type  A LOG_* constant (see App->logMsg())
     580    * @param  const  $file  Filename to log (usually __FILE__)
     581    * @param  const  $line  Line number to log (usually __LINE__)
     582    * @return bool    true if no errors found, false otherwise
     583    */
     584    public function validatePhone($form_name, $type=MSG_ERR, $file=null, $line=null)
    548585    {
    549586        $app =& App::getInstance();
     
    552589
    553590        // Validator::validateEmail() returns a value that relates to the Validate::PHONE_* constants (defined in Validator.inc.php).
    554         switch (Validator::validatePhone($phone)) {
     591        switch (Validator::validatePhone($phone, LOG_NOTICE, $file, $line)) {
    555592        case Validator::PHONE_REGEX_FAIL:
    556593            // Failed regex match.
    557             $this->addError($form_name, sprintf(_("The phone number <em>%s</em> is not valid."), oTxt($phone)));
     594            $this->addError($form_name, sprintf(_("The phone number <em>%s</em> is not valid."), oTxt($phone)), $type, $file, $line);
    558595            $app->logMsg(sprintf('The phone number %s is not valid.', oTxt($phone)), LOG_DEBUG, __FILE__, __LINE__);
    559596            return false;
    560597
    561         case Validator::PHONE_LENGTH_FAIL :
     598        case Validator::PHONE_LENGTH_FAIL:
    562599            // Failed length requirements.
    563             $this->addError($form_name, sprintf(_("The phone number <em>%s</em> is too long (phone number must have fewer than 25 characters)."), oTxt($phone)));
     600            $this->addError($form_name, sprintf(_("The phone number <em>%s</em> is too long (phone number must have fewer than 25 characters)."), oTxt($phone)), $type, $file, $line);
    564601            $app->logMsg(sprintf('The phone number %s must contain less than 256 characters.', oTxt($phone)), LOG_DEBUG, __FILE__, __LINE__);
    565602            return false;
    566603
    567         case Validator::PHONE_SUCCESS :
     604        case Validator::PHONE_SUCCESS:
    568605        default :
    569606            return true;
     
    572609
    573610    /**
    574      * Verifies that date can be processed by the strtotime function.
    575      *
    576      * @param  string  $form_name the name of the incoming form variable
    577      * @param  string  $msg       the message to display on error
    578      *
    579      * @return bool    true if no errors found, false otherwise
    580      */
    581     public function validateStrDate($form_name, $msg='')
     611    * Verifies that date can be processed by the strtotime function.
     612    *
     613    * @param  string  $form_name the name of the incoming form variable
     614    * @param  string  $msg       the message to display on error
     615    * @param  const  $type  A LOG_* constant (see App->logMsg())
     616    * @param  const  $file  Filename to log (usually __FILE__)
     617    * @param  const  $line  Line number to log (usually __LINE__)
     618    * @return bool    true if no errors found, false otherwise
     619    */
     620    public function validateStrDate($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
    582621    {
    583622        $app =& App::getInstance();
    584623
    585         if (Validator::validateStrDate(getFormData($form_name, ''))) {
    586             return true;
    587         } else {
    588             $this->addError($form_name, $msg);
     624        if (Validator::validateStrDate(getFormData($form_name, ''), LOG_NOTICE, $file, $line)) {
     625            return true;
     626        } else {
     627            $this->addError($form_name, $msg, $type, $file, $line);
    589628            $app->logMsg(sprintf('The string date %s is not valid.', getFormData($form_name)), LOG_DEBUG, __FILE__, __LINE__);
    590629            return false;
     
    594633
    595634    /**
    596      * Verifies credit card number using the Luhn (mod 10) algorithm.
    597      * http://en.wikipedia.org/wiki/Luhn_algorithm
    598      *
    599      * @param  string  $form_name   The name of the incoming form variable.
    600      * @param  string  $cc_type     Optional, card type to do specific checks. One of the Validator::CC_TYPE_* constants.
    601      *
    602      * @return bool    true if no errors found, false otherwise
    603      */
    604     public function validateCCNumber($form_name, $cc_type=null)
     635    * Verifies credit card number using the Luhn (mod 10) algorithm.
     636    * http://en.wikipedia.org/wiki/Luhn_algorithm
     637    *
     638    * @param  string  $form_name   The name of the incoming form variable.
     639    * @param  string  $cc_type     Optional, card type to do specific checks. One of the Validator::CC_TYPE_* constants.
     640    * @param  const  $type  A LOG_* constant (see App->logMsg())
     641    * @param  const  $file  Filename to log (usually __FILE__)
     642    * @param  const  $line  Line number to log (usually __LINE__)
     643    * @return bool    true if no errors found, false otherwise
     644    */
     645    public function validateCCNumber($form_name, $cc_type=null, $type=MSG_ERR, $file=null, $line=null)
    605646    {
    606647        $cc_num = getFormData($form_name);
    607648
    608         if (Validator::validateCCNumber($cc_num, $cc_type)) {
    609             return true;
    610         } else {
    611             $this->addError($form_name, sprintf(_("The credit card number you entered is not valid. Please check the number and try again."), $cc_num));
    612             return false;
    613         }
    614     }
    615 
    616     /**
    617      * Check whether a file was selected for uploading. If file is missing, it's an error.
    618      *
    619      * @param  string $form_name the name of the incoming form variable
    620      * @param  string $msg       the message to display on error
    621      *
    622      * @return bool   true if no errors found, false otherwise
    623      */
    624     public function fileUploaded($form_name, $msg='')
    625     {
    626         if (Validator::fileUploaded($form_name)) {
    627             return true;
    628         } else {
    629             $this->addError($form_name, $msg);
    630             return false;
    631         }
    632     }
    633     /**
    634      * Check whether a file was selected for uploading. If file is missing, it's an error.
    635      *
    636      * @param  string $form_name the name of the incoming form variable
    637      * @param  string $msg       the message to display on error
    638      *
    639      * @return bool   true if no errors found, false otherwise
    640      */
    641     public function fileUploadSize($form_name, $msg='')
    642     {
    643         if (Validator::fileUploadSize($form_name)) {
     649        if (Validator::validateCCNumber($cc_num, $cc_type, LOG_NOTICE, $file, $line)) {
     650            return true;
     651        } else {
     652            $this->addError($form_name, sprintf(_("The credit card number you entered is not valid. Please check the number and try again."), $cc_num), $type, $file, $line);
     653            return false;
     654        }
     655    }
     656
     657    /**
     658    * Check whether a file was selected for uploading. If file is missing, it's an error.
     659    *
     660    * @param  string $form_name the name of the incoming form variable
     661    * @param  string $msg       the message to display on error
     662    * @param  const  $type  A LOG_* constant (see App->logMsg())
     663    * @param  const  $file  Filename to log (usually __FILE__)
     664    * @param  const  $line  Line number to log (usually __LINE__)
     665    * @return bool   true if no errors found, false otherwise
     666    */
     667    public function fileUploaded($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     668    {
     669        if (Validator::fileUploaded($form_name, LOG_NOTICE, $file, $line)) {
     670            return true;
     671        } else {
     672            $this->addError($form_name, $msg, $type, $file, $line);
     673            return false;
     674        }
     675    }
     676    /**
     677    * Check whether a file was selected for uploading. If file is missing, it's an error.
     678    *
     679    * @param  string $form_name the name of the incoming form variable
     680    * @param  string $msg       the message to display on error
     681    * @param  const  $type  A LOG_* constant (see App->logMsg())
     682    * @param  const  $file  Filename to log (usually __FILE__)
     683    * @param  const  $line  Line number to log (usually __LINE__)
     684    * @return bool   true if no errors found, false otherwise
     685    */
     686    public function fileUploadSize($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
     687    {
     688        if (Validator::fileUploadSize($form_name, LOG_NOTICE, $file, $line)) {
    644689            return true;
    645690        } else {
    646691            $msg = '' == $msg ? sprintf(_("Maximum filesize exceeded. Got %s, but limit is %s."), humanFileSize($_SERVER['CONTENT_LENGTH']), humanFileSize(phpIniGetBytes('upload_max_filesize'))) : $msg;
    647             $this->addError($form_name, $msg);
     692            $this->addError($form_name, $msg, $type, $file, $line);
    648693            return false;
    649694        }
  • trunk/lib/Validator.inc.php

    r534 r550  
    5454
    5555    /**
    56      * Check if a value is not empty (just the opposite of isEmpty()).
    57      *
    58      * @param  string $val The input data to validate.
    59      * @return bool   true if form is not empty, false otherwise.
    60      */
    61     static public function notEmpty($val)
    62     {
    63         return !self::isEmpty($val);
    64     }
    65 
    66     /**
    67      * Check if a value is empty.
    68      *
    69      * @param  string $val The input data to validate.
    70      * @return bool   true if form is empty, false otherwise.
    71      */
    72     static public function isEmpty($val)
    73     {
     56    * Check if a value is not empty (the opposite of isEmpty()).
     57    *
     58    * @param  string $val The input data to validate.
     59    * @param  const  $type  A LOG_* constant (see App->logMsg())
     60    * @param  string $file  Filename to log (usually __FILE__)
     61    * @param  int    $line  Line number to log (usually __LINE__)
     62    * @return bool   true if form is not empty, false otherwise.
     63    */
     64    static public function notEmpty($val, $type=LOG_NOTICE, $file=null, $line=null)
     65    {
     66        $app =& App::getInstance();
    7467        if (is_array($val)) {
    75             return empty($val);
    76         } else {
    77             return '' == trim((string)$val);
    78         }
    79     }
    80 
    81     /**
    82      * Check whether input is a string.
    83      *
    84      * @param  string $val The input data to validate.
    85      * @return bool   true if form is a string, false otherwise.
    86      */
    87     static public function isString($val)
    88     {
    89         return '' == trim((string)$val) || is_string($val);
    90     }
    91 
    92     /**
    93      * Check whether input is a number. Allows negative numbers.
    94      *
    95      * @param  string $val The input data to validate.
    96      * @return bool   True if no errors found, false otherwise.
    97      */
    98     static public function isNumber($val)
    99     {
    100         return '' == trim((string)$val) || is_numeric($val);
    101     }
    102 
    103     /**
    104      * addError if input is NOT an integer. Don't just use is_int() because the
    105      * data coming from the user is *really* a string.
    106      *
    107      * @param  string $val The input data to validate.
    108      * @return bool   true if value is an integer
    109      */
    110     static public function isInteger($val, $negative_ok=false)
    111     {
     68            if (!empty($val)) {
     69                return true;
     70            } else {
     71                $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     72                return false;
     73            }
     74        } else {
     75            if ('' != trim((string)$val)) {
     76                return true;
     77            } else {
     78                $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     79                return false;
     80            }
     81        }
     82    }
     83
     84    /*
     85    * We were using the isEmpty method *wrong* for years and should have been using notEmpty becuase it is more grammatically correct.
     86    * Because the only use is to ensure a value is not empty, we're simply going to alias this method to notEmpty().
     87    *
     88    * @param  string $val   The input data to validate.
     89    * @param  const  $type  A LOG_* constant (see App->logMsg())
     90    * @param  string $file  Filename to log (usually __FILE__)
     91    * @param  int    $line  Line number to log (usually __LINE__)
     92    * @return bool   true if form is empty, false otherwise.
     93    */
     94    static public function isEmpty($val, $type=LOG_NOTICE, $file=null, $line=null)
     95    {
     96        return !self::notEmpty($val, $type, $file, $line);
     97    }
     98
     99    /**
     100    * Check whether input is a string.
     101    *
     102    * @param  string $val The input data to validate.
     103    * @param  const  $type  A LOG_* constant (see App->logMsg())
     104    * @param  string $file  Filename to log (usually __FILE__)
     105    * @param  int    $line  Line number to log (usually __LINE__)
     106    * @return bool   true if form is a string, false otherwise.
     107    */
     108    static public function isString($val, $type=LOG_NOTICE, $file=null, $line=null)
     109    {
     110        $app =& App::getInstance();
     111        if ('' == trim((string)$val) || is_string($val)) {
     112            return true;
     113        } else {
     114            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     115            return false;
     116        }
     117    }
     118
     119    /**
     120    * Check whether input is a number. Allows negative numbers.
     121    *
     122    * @param  string $val The input data to validate.
     123    * @param  const  $type  A LOG_* constant (see App->logMsg())
     124    * @param  string $file  Filename to log (usually __FILE__)
     125    * @param  int    $line  Line number to log (usually __LINE__)
     126    * @return bool   True if no errors found, false otherwise.
     127    */
     128    static public function isNumber($val, $type=LOG_NOTICE, $file=null, $line=null)
     129    {
     130        $app =& App::getInstance();
     131        if ('' == trim((string)$val) || is_numeric($val)) {
     132            return true;
     133        } else {
     134            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     135            return false;
     136        }
     137    }
     138
     139    /**
     140    * addError if input is NOT an integer. Don't just use is_int() because the
     141    * data coming from the user is *really* a string.
     142    *
     143    * @param  string $val The input data to validate.
     144    * @param  const  $type  A LOG_* constant (see App->logMsg())
     145    * @param  string $file  Filename to log (usually __FILE__)
     146    * @param  int    $line  Line number to log (usually __LINE__)
     147    * @return bool   true if value is an integer
     148    */
     149    static public function isInteger($val, $negative_ok=false, $type=LOG_NOTICE, $file=null, $line=null)
     150    {
     151        $app =& App::getInstance();
    112152        $pattern = $negative_ok ? '/^-?[[:digit:]]+$/' : '/^[[:digit:]]+$/';
    113         return '' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val));
    114     }
    115 
    116     /**
    117      * Check whether input is a float. Don't just use is_float() because the
    118      * data coming from the user is *really* a string. Integers will also
    119      * pass this test.
    120      *
    121      * @param  string $val The input data to validate.
    122      * @param  bool $negative_ok  If the value can be unsigned.
    123      * @return bool   true if value is a float
    124      */
    125     static public function isFloat($val, $negative_ok=false)
    126     {
     153        if ('' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val))) {
     154            return true;
     155        } else {
     156            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     157            return false;
     158        }
     159    }
     160
     161    /**
     162    * Check whether input is a float. Don't just use is_float() because the
     163    * data coming from the user is *really* a string. Integers will also
     164    * pass this test.
     165    *
     166    * @param  string $val The input data to validate.
     167    * @param  bool $negative_ok  If the value can be unsigned.
     168    * @param  const  $type  A LOG_* constant (see App->logMsg())
     169    * @param  string $file  Filename to log (usually __FILE__)
     170    * @param  int    $line  Line number to log (usually __LINE__)
     171    * @return bool   true if value is a float
     172    */
     173    static public function isFloat($val, $negative_ok=false, $type=LOG_NOTICE, $file=null, $line=null)
     174    {
     175        $app =& App::getInstance();
    127176        $pattern = $negative_ok ? '/^-?[[:digit:]]*(?:\.?[[:digit:]]+)$/' : '/^[[:digit:]]*(?:\.?[[:digit:]]+)$/';
    128         return '' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val));
    129     }
    130 
    131     /**
    132      * Check whether input is a Decimal or Fixed type. Check values to be stored in mysql decimal, numeric, num, or fixed types.
    133      * Note: some integers and floats will also pass this test.
    134      * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
    135      *
    136      * @param  string $val The input data to validate.
    137      * @param  bool $negative_ok  If the value can be unsigned.
    138      * @param  int  $max    Total max number of digits (for mysql max is 65).
    139      * @param  int  $dec    Total max number of digits after the decimal place (for mysql max is 30).
    140      * @return bool   true if value is a float
    141      */
    142     static public function isDecimal($val, $negative_ok=false, $max=10, $dec=2)
    143     {
     177        if ('' == trim((string)$val) || (is_numeric($val) && preg_match($pattern, $val))) {
     178            return true;
     179        } else {
     180            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     181            return false;
     182        }
     183    }
     184
     185    /**
     186    * Check whether input is a Decimal or Fixed type. Check values to be stored in mysql decimal, numeric, num, or fixed types.
     187    * Note: some integers and floats will also pass this test.
     188    * https://dev.mysql.com/doc/refman/5.5/en/fixed-point-types.html
     189    *
     190    * @param  string $val The input data to validate.
     191    * @param  bool $negative_ok  If the value can be unsigned.
     192    * @param  int  $max    Total max number of digits (for mysql max is 65).
     193    * @param  int  $dec    Total max number of digits after the decimal place (for mysql max is 30).
     194    * @param  const  $type  A LOG_* constant (see App->logMsg())
     195    * @param  string $file  Filename to log (usually __FILE__)
     196    * @param  int    $line  Line number to log (usually __LINE__)
     197    * @return bool   true if value is a float
     198    */
     199    static public function isDecimal($val, $max=10, $dec=2, $negative_ok=false, $type=LOG_NOTICE, $file=null, $line=null)
     200    {
     201        $app =& App::getInstance();
    144202        if ('' == trim((string)$val)) {
    145203            return true;
    146204        }
    147205        if (!$negative_ok && is_numeric($val) && $val < 0) {
     206            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    148207            return false;
    149208        }
     
    152211        $dec_count = sizeof($num_parts) <= 1 ? 0 : mb_strlen(end($num_parts));
    153212        // Must be numeric, total digits <= $max, dec digits <= $dec.
    154         return is_numeric($val) && mb_strlen(str_replace(['-', '.'], '', $val)) <= $max && $dec_count <= $dec;
    155     }
    156 
    157     /**
    158      * Check whether input is an array.
    159      *
    160      * @param  string $val The input data to validate.
    161      * @return bool   true if value is a float
    162      */
    163     static public function isArray($val)
    164     {
    165         return (is_string($val) && '' == trim((string)$val)) || is_array($val);
    166     }
    167 
    168     /**
    169      * Check whether input matches the specified perl regular expression
    170      * pattern.
    171      *
    172      * @param  string $val The input data to validate.
    173      * @param  int    $regex            PREG that the string must match
    174      * @param  bool   $valid_on_match   Set to true to be valid if match, or false to be valid if the match fails.
    175      * @return bool   true if value passes regex test
    176      */
    177     static public function checkRegex($val, $regex, $valid_on_match=true)
    178     {
    179         return $valid_on_match ? preg_match($regex, $val) : !preg_match($regex, $val);
    180     }
    181 
    182     /**
    183      * Tests if the string length is between specified values. Whitespace excluded for min.
    184      *
    185      * @param  string $val The input data to validate.
    186      * @param  int    $min       minimum length of string, inclusive
    187      * @param  int    $max       maximum length of string, inclusive
    188      * @return bool   true if string length is within given boundaries
    189      */
    190     static public function stringLength($val, $min, $max)
    191     {
    192         return mb_strlen((string)$val) >= $min && mb_strlen((string)$val) <= $max;
    193     }
    194 
    195     /**
    196      * Check whether input is within a valid numeric range.
    197      *
    198      * @param  string $val The input data to validate.
    199      * @param  int    $min       minimum value of number, inclusive
    200      * @param  int    $max       maximum value of number, inclusive
    201      * @return bool   True if no errors found, false otherwise.
    202      */
    203     static public function numericRange($val, $min, $max)
    204     {
    205         return '' == trim((string)$val) || (is_numeric($val) && $val >= $min && $val <= $max);
    206     }
    207 
    208     /**
    209      * Validates an email address based on the recommendations in RFC 3696.
    210      * Is more loose than restrictive, to allow the many valid variants of
    211      * email addresses while catching the most common mistakes.
    212      * http://www.faqs.org/rfcs/rfc822.html
    213      * http://www.faqs.org/rfcs/rfc2822.html
    214      * http://www.faqs.org/rfcs/rfc3696.html
    215      * http://www.faqs.org/rfcs/rfc1035.html
    216      *
    217      * @access  public
    218      * @param   string  $val    The input data to validate..
    219      * @param   bool    $strict Do we run strict tests?
    220      * @return  const           One of the constant values: Validate::EMAIL_SUCCESS|Validate::EMAIL_REGEX_FAIL|Validate::EMAIL_LENGTH_FAIL|Validate::EMAIL_MX_FAIL
    221      * @author  Quinn Comendant <quinn@strangecode.com>
    222      */
    223     static public function validateEmail($val, $strict=false)
    224     {
     213        if (is_numeric($val) && mb_strlen(str_replace(['-', '.'], '', $val)) <= $max && $dec_count <= $dec) {
     214            return true;
     215        } else {
     216            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     217            return false;
     218        }
     219    }
     220
     221    /**
     222    * Check whether input is an array.
     223    *
     224    * @param  string $val The input data to validate.
     225    * @param  const  $type  A LOG_* constant (see App->logMsg())
     226    * @param  string $file  Filename to log (usually __FILE__)
     227    * @param  int    $line  Line number to log (usually __LINE__)
     228    * @return bool   true if value is a float
     229    */
     230    static public function isArray($val, $type=LOG_NOTICE, $file=null, $line=null)
     231    {
     232        $app =& App::getInstance();
     233        if ((is_string($val) && '' == trim((string)$val)) || is_array($val)) {
     234            return true;
     235        } else {
     236            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     237            return false;
     238        }
     239    }
     240
     241    /**
     242    * Check whether input matches the specified perl regular expression
     243    * pattern.
     244    *
     245    * @param  string $val The input data to validate.
     246    * @param  int    $regex            PREG that the string must match
     247    * @param  bool   $valid_on_match   Set to true to be valid if match, or false to be valid if the match fails.
     248    * @param  const  $type  A LOG_* constant (see App->logMsg())
     249    * @param  string $file  Filename to log (usually __FILE__)
     250    * @param  int    $line  Line number to log (usually __LINE__)
     251    * @return bool   true if value passes regex test
     252    */
     253    static public function checkRegex($val, $regex, $valid_on_match=true, $type=LOG_NOTICE, $file=null, $line=null)
     254    {
     255        $app =& App::getInstance();
     256        if ($valid_on_match ? preg_match($regex, $val) : !preg_match($regex, $val)) {
     257            return true;
     258        } else {
     259            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     260            return false;
     261        }
     262    }
     263
     264    /**
     265    * Tests if the string length is between specified values. Whitespace excluded for min.
     266    *
     267    * @param  string $val The input data to validate.
     268    * @param  int    $min       minimum length of string, inclusive
     269    * @param  int    $max       maximum length of string, inclusive
     270    * @param  const  $type  A LOG_* constant (see App->logMsg())
     271    * @param  string $file  Filename to log (usually __FILE__)
     272    * @param  int    $line  Line number to log (usually __LINE__)
     273    * @return bool   true if string length is within given boundaries
     274    */
     275    static public function stringLength($val, $min, $max, $type=LOG_NOTICE, $file=null, $line=null)
     276    {
     277        $app =& App::getInstance();
     278        if (mb_strlen((string)$val) >= $min && mb_strlen((string)$val) <= $max) {
     279            return true;
     280        } else {
     281            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     282            return false;
     283        }
     284    }
     285
     286    /**
     287    * Check whether input is within a valid numeric range.
     288    *
     289    * @param  string $val The input data to validate.
     290    * @param  int    $min       minimum value of number, inclusive
     291    * @param  int    $max       maximum value of number, inclusive
     292    * @param  const  $type  A LOG_* constant (see App->logMsg())
     293    * @param  string $file  Filename to log (usually __FILE__)
     294    * @param  int    $line  Line number to log (usually __LINE__)
     295    * @return bool   True if no errors found, false otherwise.
     296    */
     297    static public function numericRange($val, $min, $max, $type=LOG_NOTICE, $file=null, $line=null)
     298    {
     299        $app =& App::getInstance();
     300        if ('' == trim((string)$val) || (is_numeric($val) && $val >= $min && $val <= $max)) {
     301            return true;
     302        } else {
     303            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     304            return false;
     305        }
     306    }
     307
     308    /**
     309    * Validates an email address based on the recommendations in RFC 3696.
     310    * Is more loose than restrictive, to allow the many valid variants of
     311    * email addresses while catching the most common mistakes.
     312    * http://www.faqs.org/rfcs/rfc822.html
     313    * http://www.faqs.org/rfcs/rfc2822.html
     314    * http://www.faqs.org/rfcs/rfc3696.html
     315    * http://www.faqs.org/rfcs/rfc1035.html
     316    *
     317    * @access  public
     318    * @param   string   $val    The input data to validate..
     319    * @param   bool     $strict Run strict tests (check if the domain exists and has an MX record assigned)
     320    * @param   const    $type  A LOG_* constant (see App->logMsg())
     321    * @param   string   $file  Filename to log (usually __FILE__)
     322    * @param   int      $line  Line number to log (usually __LINE__)
     323    * @return  const           One of the constant values: Validate::EMAIL_SUCCESS|Validate::EMAIL_REGEX_FAIL|Validate::EMAIL_LENGTH_FAIL|Validate::EMAIL_MX_FAIL
     324    * @author  Quinn Comendant <quinn@strangecode.com>
     325    */
     326    static public function validateEmail($val, $strict=false, $type=LOG_NOTICE, $file=null, $line=null)
     327    {
     328        $app =& App::getInstance();
    225329        require_once 'codebase/lib/Email.inc.php';
    226330        $e = new Email();
     
    228332        // Test email address format.
    229333        if (!preg_match($e->getParam('regex'), $val, $e_parts)) {
     334            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    230335            return self::EMAIL_REGEX_FAIL;
    231336        }
     
    241346        // Test length.
    242347        if (mb_strlen($local) > 64 || mb_strlen($domain) > 191) {
     348            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    243349            return self::EMAIL_LENGTH_FAIL;
    244350        }
    245351
    246         // Strict tests below.
    247 
    248         // Check domain exists: It's a domain if ip2long fails; checkdnsrr ensures a MX record exists; gethostbyname() ensures the domain exists.
    249         if ($strict && ip2long($domain) === false && function_exists('checkdnsrr') && !checkdnsrr($domain . '.', 'MX') && gethostbyname($domain) == $domain) {
    250             return self::EMAIL_MX_FAIL;
     352        if ($strict) {
     353            // Strict tests.
     354            if (ip2long($domain) === false && function_exists('checkdnsrr') && !checkdnsrr($domain . '.', 'MX') && gethostbyname($domain) == $domain) {
     355                // Check domain exists: It's a domain if ip2long fails; checkdnsrr ensures a MX record exists; gethostbyname() ensures the domain exists.
     356                $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     357                return self::EMAIL_MX_FAIL;
     358            }
    251359        }
    252360
     
    255363
    256364    /**
    257      * Check whether input is a valid phone number. Notice: it is now set
    258      * to allow characters like - or () or + so people can type in a phone
    259      * number that looks like: +1 (530) 555-1212
    260      *
    261      * @param  string  $form_name the name of the incoming form variable
    262      *
    263      * @return bool    true if no errors found, false otherwise
    264      */
    265     static public function validatePhone($val)
    266     {
    267         if (!self::checkRegex($val, '/^[0-9 +().-]*$/', true)) {
     365    * Check whether input is a valid phone number. Notice: it is now set
     366    * to allow characters like - or () or + so people can type in a phone
     367    * number that looks like: +1 (530) 555-1212
     368    *
     369    * @param  string  $form_name the name of the incoming form variable
     370    *
     371    * @param  const  $type  A LOG_* constant (see App->logMsg())
     372    * @param  string $file  Filename to log (usually __FILE__)
     373    * @param  int    $line  Line number to log (usually __LINE__)
     374    * @return bool    true if no errors found, false otherwise
     375    */
     376    static public function validatePhone($val, $type=LOG_NOTICE, $file=null, $line=null)
     377    {
     378        $app =& App::getInstance();
     379        if (!self::checkRegex($val, '/^[0-9 +().-]*$/', true, $type, $file, $line)) {
     380            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    268381            return self::PHONE_REGEX_FAIL;
    269382        }
    270         if (!self::stringLength($val, 0, 25)) {
     383        if (!self::stringLength($val, 0, 25, $type, $file, $line)) {
     384            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    271385            return self::PHONE_LENGTH_FAIL;
    272386        }
     
    275389
    276390    /**
    277      * Verifies that date can be processed by the strtotime function.
    278      * Empty strings are considered valid. Other values are tested on their return value from strtotime(). Null values will fail.
    279      *
    280      * @param  string  $val The input data to validate.
    281      * @return bool    True if no errors found, false otherwise.
    282      */
    283     static public function validateStrDate($val)
    284     {
     391    * Verifies that date can be processed by the strtotime function.
     392    * Empty strings are considered valid. Other values are tested on their return value from strtotime(). Null values will fail.
     393    *
     394    * @param  string  $val The input data to validate.
     395    * @param  const  $type  A LOG_* constant (see App->logMsg())
     396    * @param  string $file  Filename to log (usually __FILE__)
     397    * @param  int    $line  Line number to log (usually __LINE__)
     398    * @return bool    True if no errors found, false otherwise.
     399    */
     400    static public function validateStrDate($val, $type=LOG_NOTICE, $file=null, $line=null)
     401    {
     402        $app =& App::getInstance();
    285403        if (is_string($val) && '' === trim($val)) {
    286404            // Don't be too bothered about empty strings.
     
    290408        $timestamp = strtotime($val);
    291409        if (!$timestamp || $timestamp < 1) {
     410            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    292411            return false;
    293412        } else {
     
    301420    * @access   public
    302421    * @param    string  $val    String to check.
     422    * @param  const  $type  A LOG_* constant (see App->logMsg())
     423    * @param  string $file  Filename to log (usually __FILE__)
     424    * @param  int    $line  Line number to log (usually __LINE__)
    303425    * @return   bool            True if value is an empty date.
    304426    * @author   Quinn Comendant <quinn@strangecode.com>
     
    306428    * @since    19 May 2015 09:57:27
    307429    */
    308     static public function isEmptyDate($val)
    309     {
     430    static public function isEmptyDate($val, $type=LOG_NOTICE, $file=null, $line=null)
     431    {
     432        $app =& App::getInstance();
    310433        if (empty($val) || '0000-00-00 00:00:00' == $val || '0000-00-00' == $val || '00:00:00' == $val) {
    311434            return true;
    312435        }
     436        $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    313437        return false;
    314438    }
    315439
    316440    /**
    317      * Verifies credit card number using the Luhn (mod 10) algorithm.
    318      * http://en.wikipedia.org/wiki/Luhn_algorithm
    319      *
    320      * @param  string  $val   The input data to validate..
    321      * @param  string  $cc_num      Card number to verify.
    322      * @param  string  $cc_type     Optional, card type to do specific checks.
    323      * @return bool    True if no errors found, false otherwise.
    324      */
    325     static public function validateCCNumber($val, $cc_type=null)
    326     {
     441    * Verifies credit card number using the Luhn (mod 10) algorithm.
     442    * http://en.wikipedia.org/wiki/Luhn_algorithm
     443    *
     444    * @param  string  $val   The input data to validate..
     445    * @param  string  $cc_num      Card number to verify.
     446    * @param  string  $cc_type     Optional, card type to do specific checks.
     447    * @param  const  $type  A LOG_* constant (see App->logMsg())
     448    * @param  string $file  Filename to log (usually __FILE__)
     449    * @param  int    $line  Line number to log (usually __LINE__)
     450    * @return bool    True if no errors found, false otherwise.
     451    */
     452    static public function validateCCNumber($val, $cc_type=null, $type=LOG_NOTICE, $file=null, $line=null)
     453    {
     454        $app =& App::getInstance();
    327455        // Get rid of any non-digits
    328456        $cc_num = preg_replace('/[^\d]/', '', $val);
     
    355483        if ('' != $regex && !preg_match($regex, $cc_num)) {
    356484            // Invalid format.
     485            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    357486            return false;
    358487        }
     
    383512
    384513        // If the Total is evenly divisible by 10, it's cool!
    385         return $luhn_total % 10 == 0;
    386     }
    387 
    388     /**
    389      * Check whether a file was selected for uploading. If file is missing, it's an error.
    390      *
    391      * @param  string $form_name The input data to validate.
    392      * @return bool   True if no errors found, false otherwise.
    393      */
    394     static public function fileUploaded($form_name)
    395     {
     514        if ($luhn_total % 10 == 0) {
     515            return true;
     516        } else {
     517            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
     518            return false;
     519        }
     520    }
     521
     522    /**
     523    * Check whether a file was selected for uploading. If file is missing, it's an error.
     524    *
     525    * @param  string $form_name The input data to validate.
     526    * @param  const  $type  A LOG_* constant (see App->logMsg())
     527    * @param  string $file  Filename to log (usually __FILE__)
     528    * @param  int    $line  Line number to log (usually __LINE__)
     529    * @return bool   True if no errors found, false otherwise.
     530    */
     531    static public function fileUploaded($form_name, $type=LOG_NOTICE, $file=null, $line=null)
     532    {
     533        $app =& App::getInstance();
    396534        if (!isset($_FILES[$form_name]['name']) || empty($_FILES[$form_name]['name'])) {
     535            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, 'no _FILES'), $type, $file, $line);
    397536            return false;
    398537        }
     
    401540            foreach($_FILES[$form_name]['name'] as $f) {
    402541                if ('' == $f) {
     542                    $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($_FILES)), $type, $file, $line);
    403543                    return false;
    404544                }
     
    406546        } else {
    407547            if ('' == $_FILES[$form_name]['name']) {
     548                $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($_FILES)), $type, $file, $line);
    408549                return false;
    409550            }
     
    419560    * @access   public
    420561    * @param    string $form_name The input data to validate.
     562    * @param  const  $type  A LOG_* constant (see App->logMsg())
     563    * @param  string $file  Filename to log (usually __FILE__)
     564    * @param  int    $line  Line number to log (usually __LINE__)
    421565    * @return   bool   True if no errors found, false otherwise.
    422566    * @author   Quinn Comendant <quinn@strangecode.com>
     
    424568    * @since    20 Aug 2014 14:44:23
    425569    */
    426     static public function fileUploadSize($form_name)
    427     {
     570    static public function fileUploadSize($form_name, $type=LOG_NOTICE, $file=null, $line=null)
     571    {
     572        $app =& App::getInstance();
    428573        $upload_max_filesize = phpIniGetBytes('upload_max_filesize');
    429574        if (isset($_SERVER['CONTENT_LENGTH']) && 0 != $upload_max_filesize && $_SERVER['CONTENT_LENGTH'] > $upload_max_filesize) {
     575            $app->logMsg(sprintf('%s (line %s) failed: %s', __METHOD__, __LINE__, getDump($val)), $type, $file, $line);
    430576            return false;
    431577        }
  • trunk/lib/Version.inc.php

    r532 r550  
    5656        // If true, makes an exact comparison of saved vs. live table schemas. If false, just checks that the saved columns are available.
    5757        'db_schema_strict' => true,
     58
     59        // Serialization method.
     60        // Legacy installations will have been using 'phpserialize' but these should migrate to use 'json' to avoid PHP object injection https://www.owasp.org/index.php/PHP_Object_Injection
     61        'serialization_method' => 'phpserialize', // Or 'json'
    5862    );
    5963
     
    161165    public function setParam($params=null)
    162166    {
     167        $app =& App::getInstance();
     168
     169        if (isset($params['serialization_method']) && !in_array($params['serialization_method'], ['phpserialize', 'json'])) {
     170            trigger_error(sprintf('Invalid serialization_method: %s', $params['serialization_method']), E_USER_ERROR);
     171        }
    163172        if (isset($params) && is_array($params)) {
    164173            // Merge new parameters with old overriding only those passed.
     
    220229        // Clean-up old versions.
    221230        $this->deleteOld($record_table, $record_key, $record_val);
     231
     232        // Serialize the DB record.
     233        switch ($this->getParam('serialization_method')) {
     234        case 'phpserialize':
     235            $data = gzcompress(serialize($record), 9);
     236            break;
     237
     238        case 'json':
     239            $data = gzcompress(json_encode($record), 9);
     240            break;
     241        }
    222242
    223243        // Save as new version.
     
    238258                '" . $db->escapeString($record_key) . "',
    239259                '" . $db->escapeString($record_val) . "',
    240                 '" . $db->escapeString(gzcompress(serialize($record), 9)) . "',
     260                '" . $db->escapeString($data) . "',
    241261                '" . $db->escapeString($title) . "',
    242262                '" . $db->escapeString($last_version_number + 1) . "',
     
    266286        // Get version data.
    267287        $qid = $db->query("
    268             SELECT * FROM " . $db->escapeString($this->getParam('db_table')) . "
     288            SELECT *
     289            FROM " . $db->escapeString($this->getParam('db_table')) . "
    269290            WHERE version_id = '" . $db->escapeString($version_id) . "'
    270291        ");
     
    274295            return false;
    275296        }
    276         $data = unserialize(gzuncompress($record['version_data']));
     297
     298        // Unserialize the DB record.
     299        switch ($this->getParam('serialization_method')) {
     300        case 'phpserialize':
     301            $data = unserialize(gzuncompress($record['version_data']));
     302            break;
     303
     304        case 'json':
     305            $data = json_decode(gzuncompress($record['version_data']), true);
     306            break;
     307        }
    277308
    278309        // Ensure saved db columns match current table schema.
     
    342373                // First query for oldest records, selecting enough to bring total number down to min_qty.
    343374                $qid = $db->query("
    344                     SELECT version_id FROM " . $db->escapeString($this->getParam('db_table')) . "
     375                    SELECT version_id
     376                    FROM " . $db->escapeString($this->getParam('db_table')) . "
    345377                    WHERE record_table = '" . $db->escapeString($record_table) . "'
    346378                    AND record_key = '" . $db->escapeString($record_key) . "'
    347379                    AND record_val = '" . $db->escapeString($record_val) . "'
    348380                    ORDER BY version_datetime ASC
    349                     LIMIT " . ($v_count - $this->getParam('min_qty')) . "
     381                    LIMIT " . $db->escapeString($v_count - $this->getParam('min_qty')) . "
    350382                ");
     383                $old_versions = array();
    351384                while (list($old_id) = mysql_fetch_row($qid)) {
    352385                    $old_versions[] = $old_id;
     
    359392                // Delete versions older than min_days, while still keeping min_qty.
    360393                $qid = $db->query("
    361                     SELECT version_id FROM " . $db->escapeString($this->getParam('db_table')) . "
     394                    SELECT version_id
     395                    FROM " . $db->escapeString($this->getParam('db_table')) . "
    362396                    WHERE record_table = '" . $db->escapeString($record_table) . "'
    363397                    AND record_key = '" . $db->escapeString($record_key) . "'
     
    367401                    LIMIT " . ($v_count - $this->getParam('min_qty')) . "
    368402                ");
     403                $old_versions = array();
    369404                while (list($old_id) = mysql_fetch_row($qid)) {
    370405                    $old_versions[] = $old_id;
     
    455490        // Get version data.
    456491        $qid = $db->query("
    457             SELECT * FROM " . $db->escapeString($this->getParam('db_table')) . "
     492            SELECT *
     493            FROM " . $db->escapeString($this->getParam('db_table')) . "
    458494            WHERE version_id = '" . $db->escapeString($version_id) . "'
    459495        ");
    460496        $record = mysql_fetch_assoc($qid);
    461497        if (isset($record['version_data'])) {
    462             return unserialize(gzuncompress($record['version_data']));
     498            // Unserialize the DB record.
     499            switch ($this->getParam('serialization_method')) {
     500            case 'phpserialize':
     501                return unserialize(gzuncompress($record['version_data']));
     502
     503            case 'json':
     504                return json_decode(gzuncompress($record['version_data']));
     505            }
    463506        } else {
    464507            return false;
Note: See TracChangeset for help on using the changeset viewer.