PHP Classes

File: validation.class.php

Recommend this page to a friend!
  Classes of Jeff Williams  >  Easy PHP Validation  >  validation.class.php  >  Download  
File: validation.class.php
Role: Class source
Content type: text/plain
Description: Class File
Class: Easy PHP Validation
Validate and fetch request and other value types.
Author: By
Last change: Fixes and generateRandomString now uses a cryptographically secure random integer
Date: 9 months ago
Size: 50,058 bytes
 

Contents

Class file image Download
<?php /** * This class encapsulates various validation functionality. * * PHP developers should always validate data on the server side to prevent * vulnerabilities and bugs. JavaScript alone is not adequate data validation * because it can easily be bypassed or turned off altogether. * * Feb 20, 2007 - Initial Release * Feb 28, 2007 - Vitaliy Bogdanets contributed regular expressions * Mar 12, 2007 - Restructured/renamed class, made static, added functionality * Mar 27, 2007 - Added GetBooleanValue method * Jun 19, 2007 - Added functionality and bug fix for getBooleanValue * Jun 29, 2007 - Changed checkMinimumLength to isTooShort and fixed help * Aug 18, 2010 - Added getRequestValue, getCurrentPageURL, and getCurrentPageName methods * Apr 04, 2018 - Added trim and minor code updates * Apr 22, 2018 - Added various useful formatting and validation functions * Apr 30, 2018 - Added credit card validation and other string/integer functions * May 23, 2018 - Added compareValues and containsValues that use arrays * May 28, 2018 - Added beginsWith, formatTitleCase, truncate, counts, plus fixes * Feb 17, 2022 - Fixes and generateRandomString uses cryptographically secure random int * * @version 4.01 * @author Jeff L. Williams */ class Valid { /** * Determines if a string begins with another string * * @param string $string The subject of the search * @param string $find The string to look for * @param boolean $caseSensitive Case sensitive? * @return boolean TRUE if yes and FALSE if not */ public static function beginsWith($string, $find, $caseSensitive = true) { if (strlen($find) == 0) { return true; } else { $substring = substr($string, 0, strlen($find)); if ($caseSensitive) { return ($substring === $find); } else { return (strtoupper($substring) === strtoupper($find)); } } } /** * Converts the case of all keys in a multidimensional array to upper or lower * * @param array $array The array to modify * @param integer $case [OPTIONAL] Use either CASE_UPPER or CASE_LOWER (default) * @return array The array with keys changed */ public static function changeArrayKeyCaseRecursive($array, $case = CASE_LOWER) { return array_map(function ($item) use ($case) { if (is_array($item)) { $item = self::changeArrayKeyCaseRecursive($item, $case); } return $item; }, array_change_key_case($array, $case)); } /** * Returns a character at a given position * * @param string $string The subject of the search * @param string $position The position of the character * @return string The character at the specified position */ public static function charAt($string, $position) { if ($position < 0 || strlen($string) <= $position) { return ''; } else { return $string[$position]; } } /** * Checks to see if an IP address is in a range using wildcards. * Use * or % for any value. Use ? for a single digit. Use #/# or #-# for ranges. * * @example $in_range = CheckIpRange('123.4.56.78', '1*.1/4.50-60.?8'); * * @param string $ip The IP address to check * @param string $range The range using wildcards (can also be a single address) * @return boolean TRUE if a match, otherwise FALSE */ public static function checkIPRange($ip, $range) { // Split the parts of the IP address into an array $ip_parts = explode('.', $ip); $range_parts = explode('.', $range); // Loop through the 4 parts for ($i = 0; $i < 4; $i++) { // Convert each section of the IP into a number $ip_part = intval($ip_parts[$i]); // Is this a range using #/# or #-# or #:#? if (strpos($range_parts[$i], '/') !== false || strpos($range_parts[$i], '-') !== false || strpos($range_parts[$i], ':') !== false) { // We only want to deal with / $range_parts[$i] = str_replace('-', '/', str_replace(':', '/', $range_parts[$i])); // Get the left and right side of the range list($left, $right) = explode('/', $range_parts[$i], 2); // If the number is out of range... if ($ip_part < $left || $ip_part > $right) { return false; } // Does this contain a wildcard like * or 1% } elseif (strpos($range_parts[$i], '*') !== false || strpos($range_parts[$i], '%') !== false || strpos($range_parts[$i], '?') !== false) { // Turn this into a regular expression $regex = '/^' . str_replace(array('*', '%'), array_fill(0, 2, '.+'), $range_parts[$i]) . '$/'; $regex = str_replace('?', '.', $regex); if (!preg_match($regex, $ip_part)) { return false; } // Just compare the number } else { // If the 2 sides don't match if ("$ip_part" !== $range_parts[$i]) { return false; } } } return true; } /** * Checks the length of a value * * @param string $value The value to check * @param integer $maxLength The maximum allowable length of the value * @param integer $minLength [OPTIONAL] The minimum allowable length * @return boolean TRUE if the requirements are met, FALSE if not */ public static function checkLength($value, $maxLength, $minLength = 0) { if (!(strlen($value) > $maxLength) && !(strlen($value) < $minLength)) { return true; } else { return false; } } /** * Checks to make sure a folder path ends in a slash and add only if needed * * @param string $value The value to check * @return string Returns a path with a trailing slash */ public static function checkPathEndingSlash($path) { $is_unix = (strpos($path, '\\') === 0) ? false : true; $last_char = substr($path, strlen($path) - 1, 1); if ($last_char != '/' && $last_char != '\\') { $path .= ($is_unix) ? '/' : '\\'; } return $path; } /** * Compares two values for equality * * @param string $value1 First value to compare * @param string $value2 Second value to compare * @param boolean $caseSensitive [OPTIONAL] TRUE if compare is case sensitive * @return boolean TRUE if the values are equal and FALSE if not */ public static function compare($value1, $value2, $caseSensitive = false) { if ($caseSensitive) { return ($value1 == $value2 ? true : false); } else { if (strtoupper($value1) == strtoupper($value2)) { return true; } else { return false; } } } /** * Determines if a string matches any item in a list of strings * * @example $match = compareValues('Blue', true, 'red', 'green', 'blue'); * @example $match = compareValues('blue', false, array('red', 'blue')); * * @param string $string The string to match * @param boolean $ignoreCase TRUE if this is a case insensitive match * @param array $find Either an array or list of one or more extra parameters * @return boolean TRUE if found and FALSE if not */ public static function compareValues($string, $caseSensitive, $find) { // If no find array was used then use a list of parameters... if (!is_array($find)) { // If there are enough parameters to search with... if (func_num_args() > 2) { // Create the new $find_array variable using a list of parameters $find_array = func_get_args(); // Remove the first two parameters array_shift($find_array); array_shift($find_array); } else { // Not enough parameters either // Create an empty array $find_array = array(); } } else { // An array was specified to search with... // Set the array to the one passed in $find_array = $find; } if ($caseSensitive) { // Do a case-sensitive search return in_array($string, $find_array); } else { // Do a case-insensitive search return in_array(strtolower($string), array_map('strtolower', $find_array)); } } /** * Determines if a string contains another * * @param string $string The subject of the search * @param string $find The string to look for * @param boolean $caseSensitive Case sensitive? * @return boolean TRUE if yes and FALSE if not */ public static function contains($string, $find, $caseSensitive = true) { if (strlen($find) == 0) { return true; } else { if ($caseSensitive) { return (strpos($string, $find) !== false); } else { return (strpos(strtoupper($string), strtoupper($find)) !== false); } } } /** * Determines if a list of partial matches can be found in a string * * @example $match = containsValues('RED', true, 'ed', 'ee', 'ue'); * @example $match = containsValues('blue', false, array('ed', 'ee', 'ue')); * * @param string $string The string to search * @param boolean $ignoreCase TRUE if this is a case insensitive match * @param array $find Either an array or list of one or more extra parameters * @return boolean TRUE if found and FALSE if not */ public static function containsValues($string, $caseSensitive, $find) { // If no find array was used then use a list of parameters... if (!is_array($find)) { // If there are enough parameters to search with... if (func_num_args() > 2) { // Create the new $find_array variable using a list of parameters $find_array = func_get_args(); // Remove the first two parameters array_shift($find_array); array_shift($find_array); } else { // Not enough parameters either // Create an empty array $find_array = array(); } } else { // An array was specified to search with... // Set the array to the one passed in $find_array = $find; } // Set the default values $return = false; // Loop through the array foreach ($find_array as $value) { // Case sensitive search if ($caseSensitive) { if (strpos($string, $value) !== false) { $return = true; } } else { // Case insensitive search if (strpos(strtoupper($string), strtoupper($value)) !== false) { $return = true; } } } // Return the outcome return $return; } /** * Count the number of characters in a string * * @param string $string The string to process * @return integer Returns the count as a number */ public static function countCharacters($string) { return strlen($string); } /** * Count the number of paragraphs (line breaks) in a string * * @param string $string The string to process * @return integer Returns the count as a number */ public static function countParagraphs($string) { return preg_match_all('/([^\r\n]*[^ \r\n]+[^\r\n]*((\r|\n|\r\n)[^\r\n]*[^ \r\n]+[^\r\n]*)*)/m', $string); } /** * Count the number of sentences in a string * * @param string $string The string to process * @return integer Returns the count as a number */ public static function countSentences($string) { return preg_match_all('/[^\s](\.|\!|\?)(?!\w)/', $string); } /** * Count the number of words in a string * * @param string $string The string to process * @return integer Returns the count as a number */ public static function countWords($string) { return str_word_count($string); } /** * HTML Encode a string value or array of values * to stop any cross-site scripting attacks * (STATIC method - use Template::encodeHTML) * * @param string/array $value The value(s) to encode * @param string [OPTIONAL] $encoding The type of encoding * @param string [OPTIONAL] $dateFormat Default date format for date values * @return string/array HTML encoded value(s) */ public static function encodeHTML($value, $encoding = 'UTF-8', $dateFormat = 'm/d/Y') { if (is_array($value)) { $return = array(); foreach ($value as $key => $data) { $return[$key] = self::encodeHTML($data, $encoding, $dateFormat); } } else { if (is_string($value)) { $return = htmlentities(trim($value), ENT_QUOTES | ENT_HTML5, $encoding); } elseif (is_bool($value)) { $return = ($value) ? 'true' : 'false'; } elseif (is_numeric($value)) { $return = htmlentities("$value", ENT_QUOTES | ENT_HTML5, $encoding); } elseif ($value instanceof DateTime) { $return = htmlentities($value->format($dateFormat), ENT_QUOTES | ENT_HTML5, $encoding); } elseif (empty($value)) { $return = ''; } else { $return = $value; } } return $return; } /** * URL Encode a string value or array of values * (STATIC method - use Template::encodeURL) * * @param string/array $value The value(s) to encode * @param boolean [OPTIONAL] $raw TRUE for RFC 3986; FALSE use + for spaces * @param string [OPTIONAL] $dateFormat Default date format for date values * @return string/array HTML encoded value(s) */ public static function encodeURL($value, $raw = false, $dateFormat = 'Y-m-d') { if (is_array($value)) { $return = array(); foreach ($value as $key => $data) { $return[$key] = self::encodeURL($data, $encoding, $dateFormat); } } else { if (is_string($value)) { if ($raw) { $return = rawurlencode(trim($value)); } else { $return = urlencode(trim($value)); } } elseif (is_bool($value)) { $return = ($value) ? 'yes' : 'no'; } elseif (is_numeric($value)) { if ($raw) { $return = rawurlencode($value); } else { $return = urlencode($value); } } elseif ($value instanceof DateTime) { if ($raw) { $return = rawurlencode($value->format($dateFormat)); } else { $return = urlencode($value->format($dateFormat)); } } elseif (empty($value)) { return ''; } else { $return = $value; } } return $return; } /** * Determines if a string ends with another string * * @param string $string The subject of the search * @param string $find The string to look for * @param boolean $caseSensitive Case sensitive? * @return boolean TRUE if yes and FALSE if not */ public static function endsWith($string, $find, $caseSensitive = true) { if (strlen($find) == 0) { return true; } else { if ($caseSensitive) { return (substr($string, -strlen($find)) === $find); } else { return (strtoupper(substr($string, -strlen($find))) === strtoupper($find)); } } } /** * Formats a phone number * * @param string $numbers An unformatted value * @return string Returns the formatted value */ public static function formatPhoneNumber($numbers) { $numbers = self::stripNonNumeric($numbers); if (!$numbers) { return $numbers; } else { $regex = '/^1?(?:[- .])?(\d{3})(?:[- .])?(\d{3})(?:[- .])?(\d{4})$/'; $format = '($1) $2-$3'; return preg_replace($regex, $format, $numbers); } } /** * Formats a social security number * * @param string $numbers An unformatted value * @return string Returns the formatted value */ public static function formatSSN($numbers) { $numbers = self::stripNonNumeric($numbers); $ssn = ''; if (strlen($numbers) > 3) { $ssn = substr($numbers, 0, 3) . '-' . substr($numbers, 3, 2); } else { $ssn = $numbers; } if (strlen($numbers) > 5) { $ssn .= '-' . substr($numbers, 5, 4); } return $ssn; } /** * Formats text to be proper title case like news article titles * * @param string $title The string to capitalize * @return string The formatted string */ public static function formatTitleCase($title) { // Our array of 'small words' which shouldn't be capitalized if // they aren't the first word $smallwordsarray = array( 'a','an','and','as','at','but','by','en','for','if','in','nor','of','on','or','per','the','to'); // Split the string into separate words $words = explode(' ', $title); foreach ($words as $key => $word) { // If this word is the first and not one of our small words, capitalize it if ($key == 0 or !in_array($word, $smallwordsarray)) { $words[$key] = ucwords($word); } } // Join the words back into a string return implode(' ', $words); } /** * Formats a zip code * * @param string $numbers An unformatted value * @return string Returns the formatted value */ public static function formatZipCode($numbers) { $numbers = self::stripNonNumeric($numbers); if (strlen($numbers) > 5) { return substr($numbers, 0, 5) . '-' . substr($numbers, 5, 4); } else { return $numbers; } } /** * Combine first, middle, and last names without extra spaces in-between * * @param string $first First name * @param string $middle Middle name or initial * @param string $last Last Name * @return string The full name */ public static function fullName($first, $middle, $last) { If (strlen(trim($middle)) == 1) { $middle = trim($middle) . '.'; } $full = trim($first . ' ' . $middle . ' ' . $last); return self::stripExcessWhitespace($full); } /** * Generate a random string of specified length from a set of specified characters * * @param integer $size Default size is 30 characters. * @param string $chars The characters to use for randomization. * @return string Returns the random generated string */ public static function generateRandomString($size = 30, $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') { $randomString = ''; for ($i = 0; $i < $size; $i++) { $index = random_int(0, strlen($characters) - 1); $randomString .= $characters[$index]; } return $randomString; } /** * Safely returns an array element with a specified data type * without generating any warning if an element doesn't exist * * @param array $array The array to use * @param string $key The array key to use * @param string $datatype [OPTIONAL] The datatype to return * @return mixed The return value */ public static function getArrayElementValue($array, $key, $datatype = '') { $return = null; if (isset($array[$key])) { $return = convertDataType($array[$key], $datatype, false); } return $return; } /** * Converts any value of any datatype into boolean (true or false) * * @param any $value Value to analyze for TRUE or FALSE * @param any $includeTrueValue [OPTIONAL] return TRUE if the value equals this * @param any $includeFalseValue [OPTIONAL] return FALSE if the value equals this * @return boolean Returns TRUE or FALSE */ public static function getBooleanValue($value, $includeTrueValue = null, $includeFalseValue = null) { if (!(is_null($includeTrueValue)) && $value == $includeTrueValue) { return true; } elseif (!(is_null($includeFalseValue)) && $value == $includeFalseValue) { return false; } else { if (is_array($value)) { return empty($value); } elseif (gettype($value) == 'boolean') { if ($value == true) { return true; } else { return false; } } elseif (is_numeric($value)) { if ($value > 0) { return true; } else { return false; } } else { $cleaned = strtoupper(self::trim($value)); if ($cleaned == 'ON') { return true; } elseif ($cleaned == 'SELECTED' || $cleaned == 'CHECKED') { return true; } elseif ($cleaned == 'YES' || $cleaned == 'Y') { return true; } elseif ($cleaned == 'TRUE' || $cleaned == 'T') { return true; } else { return false; } } } } /** * Get the IP address of the current client (must be used on a server). * $_SERVER['REMOTE_ADDR'] sometimes does not returns the correct ip address * of the visitor. This can be occur due to reasons like the user is behind a * proxy, your apache server is behind a reverse proxy (e.g. varnish), etc. * * @return string Returns the IP address of the visitor */ public static function getClientIPAddress() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ipaddress = $_SERVER['HTTP_CLIENT_IP']; } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR']; } else if (!empty($_SERVER['HTTP_X_FORWARDED'])) { $ipaddress = $_SERVER['HTTP_X_FORWARDED']; } else if (!empty($_SERVER['HTTP_FORWARDED_FOR'])) { $ipaddress = $_SERVER['HTTP_FORWARDED_FOR']; } else if (!empty($_SERVER['HTTP_FORWARDED'])) { $ipaddress = $_SERVER['HTTP_FORWARDED']; } else if (!empty($_SERVER['REMOTE_ADDR'])) { $ipaddress = $_SERVER['REMOTE_ADDR']; } else { $ipaddress = 'UNKNOWN'; } return $ipaddress; } /** * Get the value for a cookie by the cookie name * * @param string $name The name of the cookie * @param string $default [OPTIONAL] A default if the value is empty * @return string The cookie value */ public static function getCookieValue($name, $default = '') { if (isset($_COOKIE[$name])) { return self::trim($_COOKIE[$name]); } else { return $default; } } /** * Validates a credit card and returns what type of card it is * * @param string $cardnumber The credit card number with or without dashes/spaces * @return string/boolean Returns the card type if valid, otherwise FALSE */ public static function getCreditCardType($cardnumber) { // Strip all non-numeric input $number = preg_replace('/[^0-9]/i', '', $cardnumber); // Set our regex for each card type $cardtypes = array( 'visa' => '/^4[0-9]{12}(?:[0-9]{3})?$/', 'mastercard' => '/^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/', 'amex' => '/^3[47][0-9]{13}$/', 'discover' => '/^6(?:011|5[0-9]{2})[0-9]{12}$/', 'jcb' => '/^(?:2131|1800|35\d{3})\d{11}$/', 'maestro' => '/^(?:5[0678]\d\d|6304|6390|67\d\d)\d{8,15}$/', 'solo' => '/^((?:6334|6767)\d{12}(?:\d\d)?\d?)$/', 'switch' => '/^(?:(?:(?:4903|4905|4911|4936|6333|6759)\d{12})|(?:(?:564182|633110)\d{10})(\d\d)?\d?)$/', 'dinersclub' => '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/' ); // Set the default type if none found $type = false; // Loop through the card types foreach ($cardtypes as $cardtype => $regex) { // If a match is found... if (preg_match($regex, $number)) { // Save the type of card $type = $cardtype; // No need to keep processing regex break; } } // Return the result return $type; } /** * Returns the name of the current page (i.e. sample.php) * * @return string The page name */ public static function getCurrentPageName($lowercase = false, $extension = true) { if ($extension) { $return = pathinfo($_SERVER['PHP_SELF'], PATHINFO_BASENAME); } else { $return = pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME); } return ($lowercase ? strtolower($return) : $return); } /** * Returns the name of the current URL (i.e. https://example.com/dir/sample.php) * * @return string The URL path */ public static function getCurrentPageURL($lowercase = false) { $pageURL = self::getCurrentSite() . $_SERVER['REQUEST_URI']; return ($lowercase ? strtolower($pageURL) : $pageURL); } /** * Returns the name of the current URL (i.e. https://example.com * * @return string The URL path */ public static function getCurrentSite($lowercase = false) { $url = 'http'; if (isset($_SERVER['HTTPS'])) { if ($_SERVER['HTTPS'] == 'on') { $url .= 's'; } } $url .= '://'; if ($_SERVER['SERVER_PORT'] != '80' && $_SERVER['SERVER_PORT'] != '443') { $url .= $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT']; } else { $url .= $_SERVER['SERVER_NAME']; } return ($lowercase ? strtolower($url) : $url); } /** * Returns the value if one exists, otherwise returns a default value * (This also works on NULL values) * * @param string $name The value to check * @param string $default A default if the value is empty * @return string Returns the original value unless this value is * empty - in which the default is returned */ public static function getDefaultOnEmpty($value, $default) { if (self::hasValue($value)) { return $value; } else { return $default; } } /** * Returns a value that is safe to use for a file or folder name * (Warning: this will strip extensions like .ext) * * @param string $name The value to convert * @param boolean $lowercase Determines if the return value will be lowercase * @param integer $maxlength Determines if max length of the return value * @param string $delimiter The character used to separate words * @return string Returns a string that is safe for a file system */ public static function getFileSystemSafeString($string, $lowercase = true, $maxlength = 100, $delimiter = '_') { // Strip any HTML or PHP tags $string = trim(strip_tags($string)); // Remove apostrophes $string = preg_replace("/[?']/", '', $string); // We only want letters and numbers $string = preg_replace('/[^a-zA-Z0-9]+/', $delimiter, $string); // Strip out any non-words $string = preg_replace('#\W+#', $delimiter, $string); // Get rid of duplicate delimiters $string = preg_replace('/[' . $delimiter . ']+/', $delimiter, $string); // Convert to lowercase if necessary if ($lowercase) $string = strtolower($string); // Return the maximum allowed characters and do not begin/end with delimiters return trim(substr($string, 0, $maxlength), $delimiter); } /** * Converts a string into a floating point value * * example echo getFloatValue('$1,234,567.89'); * * @param string $string String to modify * @return string Modified string */ public static function getFloatValue($string) { $value = preg_replace('/[^0-9.]/i', '', $string); if (is_numeric($value)) { return floatval($value); } else { return 0; } } /** * Get a GET value by a form element name * * @param string $name The name of the GET data * @param string $default [OPTIONAL] A default if the value is empty * @return string The value of the form element */ public static function getFormGet($name, $default = '') { return this::getFormValue($name, $default, INPUT_GET); } /** * Get a POST value by a form element name * * @param string $name The name of the POST data * @param string $default [OPTIONAL] A default if the value is empty * @return string The value of the form element */ public static function getFormPost($name, $default = '') { return this::getFormValue($name, $default, INPUT_POST); } /** * Get a POST or GET value by a form element name * * @param string $name The name of the POST or GET data * @param string $default [OPTIONAL] A default if the value is empty * @param string $method [OPTIONAL] INPUT_GET, INPUT_POST, or INPUT_REQUEST for both * @return string The value of the form element */ public static function getFormValue($name, $default = '', $method = INPUT_REQUEST) { if ($method != INPUT_GET && isset($_POST[$name])) { return self::trim($_POST[$name]); } else { if ($method != INPUT_POST && isset($_GET[$name])) { return self::trim($_GET[$name]); } else { return $default; } } } /** * Checks an array to see if required keys exist and returns missing keys * * @param array $array The array to check * @param array $required_keys An array holding a list of required keys * @param boolean [OPTIONAL] $keys_uppercase If CASE_UPPER or CASE_LOWER, * the $required_keys parameter will be converted to uppercase or lowercase * @return array An array containing any missing fields * Empty array() if no keys were found missing * False if not an array */ public static function getMissingArrayKeys($array, $required_keys, $keys_case = false) { $keys = array(); if (!is_array($array) || !is_array($required_keys)) { $keys = false; } else { foreach ($required_keys as $key) { if ($keys_case == CASE_UPPER) { if (!array_key_exists(strtoupper($key), $array)) { $keys[] = $key; } } elseif ($keys_case == CASE_LOWER) { if (!array_key_exists(strtolower($key), $array)) { $keys[] = $key; } } else { if (!array_key_exists($key, $array)) { $keys[] = $key; } } } } return $keys; } /** * Get the value for a request * * @param string $name The name of the request item * @param string $default [OPTIONAL] A default if the value is empty * @return string The request value */ public static function getRequestValue($name, $default = '') { if (isset($_REQUEST[$name])) { return self::trim($_REQUEST[$name]); } else { return $default; } } /** * Get the value for a session by the session name * * @param string $name The name of the session * @param string $default [OPTIONAL] A default if the value is empty * @return string The session value */ public static function getSessionValue($name, $default = '') { if (isset($_SESSION[$name])) { return self::trim($_SESSION[$name]); } else { return $default; } } /** * Get an array of unique characters used in a string. * (Also works with multibyte characters) * * @param string $string String to modify * @param boolean $returnAsArray True if results should be returned as array * @return string/array Modified string */ public static function getUniqueChars($string, $returnAsArray = true) { $unique = array_unique(preg_split('/(?<!^)(?!$)/u', $string)); if (!$returnAsArray) { $unique = implode('', $unique); } return $unique; } /** * Get a POST, GET, Cookie, or Session value by name * (in that order - if one doesn't exist, the next is tried) * * @param string $name The name of the POST, GET, Session, or Cookie * @param string $default [OPTIONAL] A default if the value is empty * @return string The value from that element */ public static function getValue($name, $default = '') { if (isset($_REQUEST[$name])) { return self::trim($_REQUEST[$name]); } else { if (isset($_SESSION[$name])) { return self::trim($_SESSION[$name]); } else { return $default; } } } /** * Checks an array to see if required keys exist * * @param array $array The array to check * @param array $required_keys An array holding a list of required keys * @param boolean [OPTIONAL] $keys_uppercase If CASE_UPPER or CASE_LOWER, * the $required_keys parameter will be converted to uppercase or lowercase * @return boolean TRUE if all keys are found, otherwise FALSE */ public static function hasArrayKeys($array, $required_keys, $keys_case = false) { $valid = true; if (!is_array($array)) { $valid = false; } else { foreach ($required_keys as $key) { if ($keys_case == CASE_UPPER) { if (!array_key_exists(strtoupper($key), $array)) { $valid = false; } } elseif ($keys_case == CASE_LOWER) { if (!array_key_exists(strtolower($key), $array)) { $valid = false; } } else { if (!array_key_exists($key, $array)) { $valid = false; } } } } return $valid; } /** * Create a hash checksum for any number of different types of variables * * @example echo hashAny('test', true, false, -100, array('a' => 1, 'b' => 'c')); * * @param mixed $mixed Any number of parameters (order will change the return value) * @return string A unique string of 64 characters representing the input parameters */ public static function hashAny($mixed) { // (SHA-256 was chosen over MD5 to reduce the very remote possibility of collisions // and virtually eliminate the chance of reverse engineering the hash) return hash('sha256', print_r(func_get_args(), true)); } /** * Checks to see if a variable contains a value * * @param string $value The value to check * @return boolean TRUE if a value exists, FALSE if empty */ public static function hasValue($value) { return !(self::isEmpty($value)); } /** * Determines if a string is alpha only * * @param string $value The value to check for alpha (letters) only * @param string $allow Any additional allowable characters * @return boolean */ public static function isAlpha($value, $allow = '') { if (preg_match('/^[a-zA-Z' . $allow . ']+$/', $value)) { return true; } else { return false; } } /** * Determines if a string is alpha-numeric * * @param string $value The value to check * @return boolean TRUE if there are letters and numbers, FALSE if other */ public static function isAlphaNumeric($value) { if (preg_match('/^[A-Za-z0-9 ]+$/', $value)) { return true; } else { return false; } } /** * Checks for a valid email address * * @param string $email The value to validate as an email address * @return boolean TRUE if it is a valid email address, FALSE if not */ public static function isEmail($email) { $pattern = '/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/'; if (preg_match($pattern, $email)) { return true; } else { return false; } } /** * Checks to see if a variable contains no value (not even a zero) * * @param string $value The value to check * @return boolean TRUE if a value exists, FALSE if empty */ public static function isEmpty($value) { if (!isset($value)) { return true; } elseif (is_null($value)) { return true; } elseif (is_string($value) && strlen($value) == 0) { return true; } elseif (is_array($value) && count($value) == 0) { return true; } else { return false; } } /** * Checks to see if a variable is a floating point number * * @param float $number The value to check * @return boolean TRUE if the value is a number, FALSE if not */ public static function isFloat($number) { if (is_float($number)) { return true; } else { $pattern = '/^[-+]?(((\\\\d+)\\\\.?(\\\\d+)?)|\\\\.\\\\d+)([eE]?[+-]?\\\\d+)?$/'; return (!is_bool($number) && (is_float($number) || preg_match($pattern, trim($number)))); } } /** * Checks for a valid internet URL * * @param string $value The value to check * @return boolean TRUE if the value is a valid URL, FALSE if not */ public static function isInternetURL($value) { if (preg_match('/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?$/i', $value)) { return true; } else { return false; } } /** * Checks for a valid IP Address * * @param string $value The value to check * @return boolean TRUE if the value is an IP address, FALSE if not */ public static function isIPAddress($value) { $pattern = '/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' . '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' . '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' . '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i'; if (preg_match($pattern, $value)) { return true; } else { return false; } } /** * Checks to see if a variable is a number * * @param integer $number The value to check * @return boolean TRUE if the value is a number, FALSE if not */ public static function isNumber($number) { if (preg_match('/^\-?\+?[0-9e1-9]+$/', $number)) { return true; } else { return false; } } /** * Checks for a valid US phone number * * @param string $value The value to inspect * @return boolean TRUE if the value is a phone number or FALSE if not */ public static function isPhoneNumber($value) { if (preg_match( '/^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|' . '[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|' . '[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?' . '([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?' . '([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/i', $value)) { return true; } else { return false; } } /** * Checks to see if a variable is a social security number * * @param integer $ssn The value to check * @param integer $strict If true, there are additional checks * @return boolean TRUE if the value is a social security number, FALSE if not */ public static function isSSN($ssn, $strict = false) { if (preg_match('/^\d{3}\-?\d{2}\-?\d{4}$/', $ssn)) { if ($strict) { // None of the digit groups can be all zeros. // Area number 666 is unassigned. // Numbers from 987-65-4320 to 987-65-4329 are reserved for use in advertisements. // Many SSNs have been invalidated by use in advertising. // Numbers above 772 are currently unassigned. $regex = '/^((000|666)\-?\d{2}\-?\d{4}|\d{3}\-?00\-?\d{4}|\d{3}\-?' . '\d{2}\-?0000|987\-?65\-?432\d{1}|042\-?10\-?3580|062\-?36\-?' . '0749|078\-?05\-?1120|095\-?07\-?3645|128\-?03\-?6045|135\-?01\-?' . '6629|141\-?18\-?6941|165\-?(16|18|20|22|24)\-?7999|189\-?09\-?' . '2294|212\-?09\-?(7694|9999|219\-?09\-?9999|306\-?30\-?' . '2348|308\-?12\-?5070|468\-?28\-?8779|549\-?24\-?1889)$/'; if (preg_match($regex, $ssn) || substr($ssn, 0, 3) > 772) { return false; } else { return true; } } else { return true; } } else { return false; } } /** * Checks for a two character state abbreviation * * @param string $value The value to inspect * @return boolean TRUE if the value is a 2 letter state abbreviation * FALSE if the value is anything else */ public static function isStateAbbreviation($value) { if (preg_match('/^[A-Z][A-Z]$/i', $value)) { return true; } else { return false; } } /** * Check to see if a string length is too long * * @param string $value The string value to check * @param integer $maximumLength The maximum allowed length * @return boolean TRUE if the length is too long * FALSE if the length is acceptable */ public static function isTooLong($value, $maximumLength) { if (strlen($value) > $maximumLength) { return true; } else { return false; } } /** * Check to see if a string length is too short * * @param string $value The string value to check * @param integer $maximumLength The minimum allowed length * @return boolean TRUE if the length is too short * FALSE if the length is acceptable */ public static function isTooShort($value, $minimumLength) { if (strlen($value) < $minimumLength) { return true; } else { return false; } } /** * Checks to see if a variable is an unsigned number * * @param integer $number The value to inspect * @return boolean TRUE if the value is a number without a sign * and FALSE if a sign exists */ public static function isUnsignedNumber($number) { if (preg_match('/^\+?[0-9]+$/', $number)) { return true; } else { return false; } } /** * Checks a credit card number to see if it is valid using the Luhn checksum * * @param string $cardnumber The credit card number with or without dashes/spaces * @return boolean TRUE if card checksum passes and FALSE if otherwise */ public static function isValidCreditCardNumber($cardnumber) { // Strip all non-numeric input $number = preg_replace('/[^0-9]/i', '', $cardnumber); $length = strlen($number); // Reverse the order of the number $revNumber = strrev($number); // Loop through and calculate the Luhn checksum $sum = ''; for ($i = 0; $i < $length; $i++) { $sum .= $i & 1 ? $revNumber[$i] * 2 : $revNumber[$i]; } // Return the result as a boolean return array_sum(str_split($sum)) % 10 === 0; } /** * Checks to see if a variable is a valid JSON string * * @param string $string The value to check * @return boolean TRUE if the value is JSON, FALSE if not */ public static function isValidJSON($string) { @json_decode($string); return (json_last_error() == JSON_ERROR_NONE); } /** * Checks to see if a string contains valid XML * * @param string $string The value to check * @return boolean TRUE if the value is XML, FALSE if not */ public static function isValidXML($string) { libxml_use_internal_errors(true); $doc = false; $doc = @simplexml_load_string($string); if ($doc !== false) { $errors = false; } else { // $errors = libxml_get_errors(); $errors = true; } libxml_clear_errors(); return (!$errors); } /** * Checks to see if a value contains a 5 or 9 digit zip code * * @param string $value The value to inspect * @return boolean TRUE if zip code, otherwise FALSE */ public static function isZipCode($value) { $numbers = self::stripNonNumeric($value); if (strlen($numbers) == 5 || strlen($numbers) == 9) { $formatted = self::formatZipCode($numbers); if ($value == $numbers || $value == $formatted) { return true; } else { return false; } } else { return false; } } /** * Returns the left part of a string * * @param string $string The string to be divided * @param int $length The number of characters to return * @return string The extracted string */ public static function left($string, $length) { return substr($string, 0, $length); } /** * Adds th, st, nd, rd, th to the end of a number * * @param integer $number A number * @return string A string with the modified number */ public static function ordinal($number) { $test_c = abs($number) % 10; $ext = ((abs($number) % 100 < 21 && abs($number) % 100 > 4) ? 'th' : (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1) ? 'th' : 'st' : 'nd' : 'rd' : 'th')); return $number . $ext; } /** * Replace the last occurrence of a string. * * @param string $search String to search for * @param string $replace String to replace with * @param string $subject String to operate on * @return string Replaces text */ public static function replaceLast($search, $replace, $subject) { $lenOfSearch = strlen($search); $posOfSearch = strrpos($subject, $search); return substr_replace($subject, $replace, $posOfSearch, $lenOfSearch); } /** * Returns the right part of a string * * @param string $string The string to be divided * @param int $length The number of characters to return * @return string The extracted string */ public static function right($string, $length) { if ($length < 1) { return ''; } else { return substr($string, -$length); } } /** * Removes any dangerous javascript, HTML, or CSS code in a string * * @param String $input String to be sanitized * @return String Sanitized string */ public static function sanitize($input) { $search = array( '@<script[^>]*?>.*?</script>@si', // Strip out javascript '@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags '@<style[^>]*?>.*?</style>@siU', // Strip style tags properly '@<![\s\S]*?--[ \t\n\r]*>@' // Strip multi-line comments ); return preg_replace($search, '', $input); } /** * Determines if a string starts with another string * * @param string $string The subject of the search * @param string $find The string to look for * @param boolean $caseSensitive Case sensitive? * @return boolean TRUE if yes and FALSE if not */ public static function startsWith($string, $find, $caseSensitive = true) { $length = strlen($find); if ($caseSensitive) { return !strncmp($string, $find, $length); } else { return !strncmp(strtoupper($string), strtoupper($find), $length); } } /** * Transform two or more spaces into just one space. * * @param string $string String to modify * @return string Modified string */ public static function stripExcessWhitespace($string) { return preg_replace('/ +/', ' ', $string); } /** * Remove all characters except letters. * * @param string $string String to modify * @return string Modified string */ public static function stripNonAlpha($string) { return preg_replace('/[^a-z]/i', '', $string); } /** * Remove all characters except letters, hyphens, and spaces. * (Most commonly used for names) * * @param string $string String to modify * @return string Modified string */ public static function stripNonAlphaHyphenSpaces($string) { return preg_replace('/[^a-z\- ]/i', '', $string); } /** * Remove all characters except letters and numbers. * * @param string $string String to modify * @return string Modified string */ public static function stripNonAlphaNumeric($string) { return preg_replace('/[^a-z0-9]/i', '', $string); } /** * Remove all characters except letters, numbers, hyphens, and spaces. * (Most commonly used for city names) * * @param string $string String to modify * @return string Modified string */ public static function stripNonAlphaNumericHyphenSpaces($string) { return preg_replace('/[^a-z0-9\- ]/i', '', $string); } /** * Remove all characters except letters, numbers, and spaces. * * @param string $string String to modify * @return string Modified string */ public static function stripNonAlphaNumericSpaces($string) { return preg_replace('/[^a-z0-9 ]/i', '', $string); } /** * Remove all characters except numbers. * * @param string $string String to modify * @return string Modified string */ public static function stripNonNumeric($string) { return preg_replace('/[^0-9]/', '', $string); } /** * Trims a value if it is a string * * @param unknown_type $value The value to trim * @param string $mask The characters used for trim * @return unknown_type The value passed in; if a string, then it is trimmed */ public static function trim($value, $mask = ' ') { if (is_string($value)) { return trim($value, $mask); } elseif (is_null($value)) { return ''; } else { return $value; } } /** * Removes the decimal point in a float without rounding up or down * * example echo truncate('This is too long', 10, '...'); * * @param string $string The string to truncate * @param int $length The number of max character * @return string The truncated string */ public static function truncate($string, $length, $dots = '') { if (strlen($string) > $length) { return substr($string, 0, $length - strlen($dots)) . $dots; } else { return $string; } } /** * Removes the decimal point in a float without rounding up or down * * example echo truncateDecimal(1234.5678); * * @param float $float Floating point decimal number * @param int $precision [OPTIONAL] The number of decimal points to keep * @return float The truncated floating point number */ public static function truncateDecimal($float, $precision = 0) { $pow = pow(10, $precision); $precise = (int) ($float * $pow); return (float) ($precise / $pow); } /** * Check to see if a password is string and meets basic requirements * * @param string $password Password * @param string $confirm Confirmed password * @param string $email Username * @param string $username Email * @param boolean $forceUpperLower True if password must contain both a * lower and uppercase character * @return string Contains an HTML list of problems or FALSE if valid */ public static function validatePassword($password, $confirm, $email = '', $username = '', $forceUpperLower = false, $returnArray = false) { // Create a variable to contain potential problems $problem = ''; if ($password != $confirm) { $problem .= 'Password and confirm password fields did not match.' . "<br>\n"; } if (strlen($password) < 8) { $problem .= 'Password must be at least 8 characters long.' . "<br>\n"; } if ($email) { if (strpos(strtoupper($password), strtoupper($email)) !== false || strpos(strtoupper($password), strtoupper(strrev($email))) !== false) { $problem .= 'Password cannot contain the email address.' . "<br>\n"; } } if ($username) { if (strpos(strtoupper($password), strtoupper($username)) !== false || strpos(strtoupper($password), strtoupper(strrev($username))) !== false) { $problem .= 'Password cannot contain the username (or reversed username).' . "<br>\n"; } } if (!preg_match('#[0-9]+#', $password)) { $problem .= 'Password must contain at least one number.' . "<br>\n"; } if ($forceUpperLower) { if (!preg_match('#[a-z]+#', $password)) { $problem .= 'Password must contain at least one lowercase letter.' . "<br>\n"; } if (!preg_match('#[A-Z]+#', $password)) { $problem .= 'Password must contain at least one uppercase letter.' . "<br>\n"; } } else { if (!preg_match('#[a-zA-Z]+#', $password)) { $problem .= 'Password must contain at least one letter.' . "<br>\n"; } } // Fix the return result if (strlen($problem) == 0) { $problem = false; } elseif ($returnArray) { $problem = explode("<br>\n", trim($problem, "<br>\n")); } else { // $problem = trim($problem, "<br>\n"); } return $problem; } } ?>