* Copyright 2001-2010 Strangecode, LLC * * This file is part of The Strangecode Codebase. * * The Strangecode Codebase is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) * any later version. * * The Strangecode Codebase is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * The Strangecode Codebase. If not, see . */ /** * FormValidator.inc.php * * The FormValidator class provides a method for validating input from * http requests and displaying errors. * * @requires codebase/lib/Validator.inc.php * @author Quinn Comendant * @version 1.8 * * Example of use: --------------------------------------------------------------------- // The object that validates form input. require_once 'codebase/lib/FormValidator.inc.php'; $fv = new FormValidator(); $fv->empty('field_name', sprintf(_("%s cannot be blank."), _("Field name"))); $fv->stringLength('field_name', 0, 255, sprintf(_("%s must be %d-to-%d characters in length."), _("Field name"), 0, 255)); $fv->isInteger('field_name', sprintf(_("%s must be an integer."), _("Field name"))); $fv->checkRegex('field_name', '/^\d{4}$|^$/', true, sprintf(_("%s must be in MMYY format."), _("Field name"))); $fv->numericRange('field_name', 0, 65535, sprintf(_("%s must be a number between %d and %d."), _("Field name"), 0, 65535)); $fv->validatePhone('field_name'); $fv->validateEmail('field_name'); $fv->validateStrDate('field_name', sprintf(_("%s must be a valid date in YYYY-MM-DD format."), _("Field name"))); if (is_null($var)) { $fv->addError('field_name', sprintf(_("%s is invalid."), _("Field name"))); } if ($fv->anyErrors()) { // Errors! } --------------------------------------------------------------------- */ // Credit card types are defined in class Validator. require_once 'codebase/lib/Validator.inc.php'; class FormValidator extends Validator { // Class parameters. var $_params = array( 'error' => ' sc-msg-error ', 'warning' => ' sc-msg-warning ', 'notice' => ' sc-msg-notice ', 'success' => ' sc-msg-success ', ); // Array filling with error messages. var $errors = array(); /** * Set (or overwrite existing) parameters by passing an array of new parameters. * * @access public * @param array $params Array of parameters (key => val pairs). */ function setParam($params) { $app =& App::getInstance(); if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } else { $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ function getParam($param) { $app =& App::getInstance(); if (isset($this->_params[$param])) { return $this->_params[$param]; } else { $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__); return null; } } /** * Return the current list of errors. * * @return array an array of errors in the following arrangement: * keys: the name of the variable with an error * vals: the message to display for that error */ function getErrorList() { return $this->errors; } /** * Add an error to the errors stack. * * @param string $form_name The name of the incoming form variable. * @param string $msg The error message for that form. * @param int $type The type of message: MSG_NOTICE, * MSG_SUCCESS, MSG_WARNING, or MSG_ERR. * @param string $file __FILE__. * @param string $line __LINE__. */ function addError($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null) { $this->errors[] = array( 'name' => $form_name, 'message' => $msg, 'type' => $type, 'file' => $file, 'line' => $line ); } /** * Check whether any errors have been triggered. * * @param string $form_name the name of the incoming form variable * * @return bool true if any errors were found, or if found for * a variable of $form_name, false otherwise */ function anyErrors($form_name=null) { if (isset($form_name)) { foreach ($this->errors as $err) { if ($err['name'] == $form_name) { return $err['type']; } } return false; } else { return (sizeof($this->errors) > 0); } } /** * Reset the error list. */ function resetErrorList() { $this->errors = array(); } /** * Prints the HTML for displaying error messages. * * @access public * @author Quinn Comendant * @since 15 Jul 2005 01:39:14 */ function printErrorMessages() { $app =& App::getInstance(); if ($this->anyErrors()) { ?>
getErrorList() as $e) { if ('' != $e['message'] && is_string($e['message'])) { if (error_reporting() > 0 && $app->getParam('display_errors') && isset($e['file']) && isset($e['line'])) { echo "\n'; } switch ($e['type']) { case MSG_ERR: echo '
' . $e['message'] . '
'; break; case MSG_WARNING: echo '
' . $e['message'] . '
'; break; case MSG_SUCCESS: echo '
' . $e['message'] . '
'; break; case MSG_NOTICE: default: echo '
' . $e['message'] . '
'; break; } } } ?>
anyErrors($form_name))) { if (isset($marker)) { echo $marker; } else { switch ($type) { case MSG_ERR: default: echo $this->getParam('error'); break; case MSG_WARNING: echo $this->getParam('warning'); break; case MSG_NOTICE: echo $this->getParam('notice'); break; case MSG_SUCCESS: echo $this->getParam('success'); break; } } } } /** * Ensure the length of string is non-zero. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if form is not empty, false otherwise. */ function notEmpty($form_name, $msg='') { if (parent::notEmpty(getFormData($form_name))) { return true; } else { $this->addError($form_name, $msg); return false; } } /* * We were using the isEmpty method *wrong* all these years and should have been using notEmpty. * But the fact is the only use is to ensure a value is not empty, so this function simply becomes * an alias of the one-true notEmpty() function. * @since 03 Jun 2006 22:56:46 */ function isEmpty($form_name, $msg='') { $this->notEmpty($form_name, $msg); } /** * Check whether input is a string. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if form is a string, false otherwise. */ function isString($form_name, $msg='') { if (parent::isString(getFormData($form_name))) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Check whether input is a number. Allows negative numbers. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if no errors found, false otherwise */ function isNumber($form_name, $msg='') { if (parent::isNumber(getFormData($form_name))) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * addError if input is NOT an integer. Don't just use is_int() because the * data coming from the user is *really* a string. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if value is an integer */ function isInteger($form_name, $msg='', $negative_ok=false) { if (parent::isInteger(getFormData($form_name), $negative_ok)) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Check whether input is a float. Don't just use is_float() because the * data coming from the user is *really* a string. Integers will also * pass this test. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if value is a float */ function isFloat($form_name, $msg='', $negative_ok=false) { if (parent::isFloat(getFormData($form_name), $negative_ok)) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Check whether input is an array. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if value is a float */ function isArray($form_name, $msg='') { if (parent::isArray(getFormData($form_name))) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Check whether input matches the specified perl regular expression * pattern. * * @param string $form_name The name of the incoming form variable * @param int $regex Perl regex that the string must match * @param bool $valid_on_match Set to true to be valid if match, or false to be valid if the match fails. * @param string $msg The message to display on error * * @return bool true if value passes regex test */ function checkRegex($form_name, $regex, $valid_on_match, $msg='') { if (parent::checkRegex(getFormData($form_name), $regex, $valid_on_match)) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Tests if the string length is between specified values. Whitespace excluded for min. * * @param string $form_name the name of the incoming form variable * @param int $min minimum length of string, inclusive * @param int $max maximum length of string, inclusive * @param string $msg the message to display on error * * @return bool true if string length is within given boundaries */ function stringLength($form_name, $min, $max, $msg='') { if (parent::stringLength(getFormData($form_name), $min, $max)) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Check whether input is within a valid numeric range. * * @param string $form_name the name of the incoming form variable * @param int $min minimum value of number, inclusive * @param int $max maximum value of number, inclusive * @param string $msg the message to display on error * * @return bool true if no errors found, false otherwise */ function numericRange($form_name, $min, $max, $msg='') { if (parent::numericRange(getFormData($form_name), $min, $max)) { return true; } else { $this->addError($form_name, $msg); return false; } } /** * Validates an email address based on the recommendations in RFC 3696. * Is more loose than restrictive, to allow the many valid variants of * email addresses while catching the most common mistakes. * http://www.faqs.org/rfcs/rfc822.html * http://www.faqs.org/rfcs/rfc2822.html * http://www.faqs.org/rfcs/rfc3696.html * http://www.faqs.org/rfcs/rfc1035.html * * @access public * @param string $form_name The name of the incoming form variable. * @return bool Validity of address. * @author Quinn Comendant */ function validateEmail($form_name) { $app =& App::getInstance(); $email = getFormData($form_name); if ('' == trim($email)) { // No email address provided, and that's okay. return true; } // Validator::validateEmail() returns a value that relates to the VALIDATE_EMAIL_* constants (defined in Validator.inc.php). switch (parent::validateEmail($email)) { case VALIDATE_EMAIL_REGEX_FAIL: // Failed regex match. $this->addError($form_name, sprintf(_("The email address %s is formatted incorrectly."), oTxt($email))); $app->logMsg(sprintf('The email address %s is not valid.', oTxt($email)), LOG_DEBUG, __FILE__, __LINE__); return false; break; case VALIDATE_EMAIL_LENGTH_FAIL : // Failed length requirements. $this->addError($form_name, sprintf(_("The email address %s is too long (email addresses must have fewer than 256 characters)."), oTxt($email))); $app->logMsg(sprintf('The email address %s must contain less than 256 characters.', oTxt($email)), LOG_DEBUG, __FILE__, __LINE__); return false; break; case VALIDATE_EMAIL_MX_FAIL : // Failed MX record test. $this->addError($form_name, sprintf(_("The email address %s does not have a valid domain name"), oTxt($email))); $app->logMsg(sprintf('The email address %s does not have a valid domain name.', oTxt($email)), LOG_INFO, __FILE__, __LINE__); return false; break; case VALIDATE_EMAIL_SUCCESS : default : return true; break; } } /** * Check whether input is a valid phone number. Notice: it is now set * to allow characters like - or () or + so people can type in a phone * number that looks like: +1 (530) 555-1212 * * @param string $form_name the name of the incoming form variable * * @return bool true if no errors found, false otherwise */ function validatePhone($form_name) { $phone = getFormData($form_name); return ( $this->checkRegex($form_name, '/^[0-9 +().-]*$/', true, sprintf(_("The phone number %s is not valid."), $phone)) && $this->stringLength($form_name, 0, 25, sprintf(_("The phone number %s is too long"), $phone)) ); } /** * Verifies that date can be processed by the strtotime function. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if no errors found, false otherwise */ function validateStrDate($form_name, $msg='') { $app =& App::getInstance(); if (parent::validateStrDate(getFormData($form_name))) { return true; } else { $this->addError($form_name, $msg); $app->logMsg(sprintf('The string date %s is not valid.', getFormData($form_name)), LOG_DEBUG, __FILE__, __LINE__); return false; } } /** * Verifies credit card number using the Luhn (mod 10) algorithm. * http://en.wikipedia.org/wiki/Luhn_algorithm * * @param string $form_name The name of the incoming form variable. * @param string $cc_type Optional, card type to do specific checks. One of the CC_TYPE_* constants. * * @return bool true if no errors found, false otherwise */ function validateCCNumber($form_name, $cc_type=null) { $cc_num = getFormData($form_name); if (parent::validateCCNumber($cc_num, $cc_type)) { return true; } else { $this->addError($form_name, sprintf(_("The credit card number you entered is not valid. Please check the number and try again."), $cc_num)); return false; } } /** * Check whether a file was selected for uploading. If file is missing, it's an error. * * @param string $form_name the name of the incoming form variable * @param string $msg the message to display on error * * @return bool true if no errors found, false otherwise */ function fileUploaded($form_name, $msg='') { if (parent::fileUploaded($form_name)) { return true; } else { $this->addError($form_name, $msg); return false; } } } // THE END ?>