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: Recent bug fixes
Date: 1 month ago
Size: 49,958 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
 *
 * @version 4.0
 * @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 = rand(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;
	}
}
?>

For more information send a message to info at phpclasses dot org.