Fonction de nettoyage de variables avec une installation de php basique

Contenu du snippet

Bonjour à tous,

Ayant longuement cherché sur le web, je n'ai pas trouvé de solution de nettoyage des variables simple d'emploi en PHP.

Bien sûr il y a des solutions, mais elles nécéssitent toutes l'installation de certaines extensions de PHP qui sont rarement disponibles en hébergement mutualisé.

J'ai donc créé cette fonction "checkVar()" avec les moyens du bord, c'est-à-dire une installation PHP de base.

Cette fonction est EXPERIMENTALE et évidemment totalement libre de tous droits.

Je ne suis pas un cador en programmation et encore moins en sécurité, c'est pourquoi je la soumet ici à vos critiques aussi bien sur le fond (utilité, pertinence) que sur la forme (réalisation probablement imparfaite) car peut-être ensemble arriverons-nous à en faire quelque chose de fiable.

-

Mini-documentation:

$target: "html" si vous souhaitez afficher le résultat sur une page, ou "sql" si vous souhaitez le concaténer dans une commande SQL

$untrusted_value: valeur saisie par l'utilisateur à vérifier, typiquement en provenance d'un $_POST ou d'un $_GET.

$awaited_type: type de valeur attendu. Valeurs possible: "boolean", "int", "float", "hex", "string", "date", "hour", "url", "email".

$min, $max: limites mini et maxi. Si le type de valeur attendu est numérique (int, float, hex), il s'agit de sa valeur intrinsèque. Si le type de valeur attendu est chaîne se caractère (string, date, url, email), la limite s'applique à la longueur de la chaîne.

$default_value: Valeur renvoyée par défaut par la fonction si le test échoue.

$label: Désignation de la valeur analysée. Utile dans les messages d'erreur.

$array_return: 1 = retourner un rapport d'analyse sous forme de tableau, 0 = retourner simplement la valeur après analyse.

Description du tableau de rapport d'analyse
"ok" => 1 | 0 (indique si le test a réussi ou échoué)
"value" => retour de valeur après analyse ($default_value si le test a échoué)
"error" => Description de l'erreur si le test a échoué.

$die_on_fail: si l'analyse a échoué, 0 = retourner la valeur par défaut, 1 = stopper le script (à utiliser dans les cas critiques où si la valeur est hors limite il s'agit obligatoirement d'une tentative malveillante).

Source / Exemple :


function checkVar($target, $untrusted_value, $awaited_type, $min, $max, $default_value, $label, $array_return, $die_on_fail) {

	$value_accepted = true; $error = ""; $date_format = "d/m/Y"; // $date_format is only for date type validation

	// 1. filters value according to target (web page or database)
	// converts to correct charset, removes unwanted values, encodes special chars
	// does nothing if not $target = ""
	$untrusted_value = filterValue($target, $untrusted_value);

	// 2. checks var content against awaited type
	if($awaited_type != "") {
		$value_accepted = validateType($untrusted_value, $awaited_type, $target, $date_format); // $date_format is only for date type validation
		if(!$value_accepted) { $error .= "bad type, " . $awaited_type . " awaited."; }
	} else {
		// sets var type if not specified, for next check against bounds
		if(is_numeric($untrusted_value)) { $awaited_type = "float"; } else { $awaited_type = "string"; }
	}

	// 3. checks var content against bounds
	if($value_accepted) {

		// numeric : checks var content against values bounds
		if($awaited_type == "int" || $awaited_type == "float" || $awaited_type == "hex") {
			$value_accepted = validateValue($untrusted_value, $min, $max);
			if(!$value_accepted) { $error .= "bad value, " . $min . " to " . $max . " accepted."; }
		}

		// string : checks var content against length bounds
		if($awaited_type == "string" || $awaited_type == "date" || $awaited_type == "url" || $awaited_type == "email") {
			$value_accepted = validateLength($untrusted_value, $min, $max);
			if(!$value_accepted) { $error .= "bad length, " . $min . " to " . $max . " chars awaited."; }
			}
		}

		if($value_accepted) {

			switch($array_return) {

			case 0: // returns a single value without feedback
			return $untrusted_value; break;

			case 1: // returns an array with filtered value or default value with error feedback if validation fails (useful for form validation)
			return array("ok"=>true, "value"=>$untrusted_value, "error"=>"");
		}

	} else {

		if($die_on_fail) {
			exit("Fatal error :: bad var value detected" ,1);
			if($debug_mode == "on") { echo "<br>'" . $label . "' " . $error; }
		}

		switch($array_return) {

			case 0: // returns a single value without feedback
			return $default_value; break;

			case 1: // returns an array with filtered value or default value with error feedback if validation fails (useful for form validation)
			return array("ok"=>false, "value"=>$default_value, "error"=>"'" . $label . "' " . $error);
		}
	}
}

function filterValue($target, $value) {

	switch($target) {
		case "": return $value; break;
		case "sql": $db_connection = mysql_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD); return mysql_real_escape_string($value, $db_connection); break; // mysql connexion is mandatory for mysql_real_escape_string use
		case "html": return htmlentities($value, ENT_QUOTES, "UTF-8"); // change UTF-8 if you're using another page code
	}
}

function validateType($value, $type, $target, $date_format) {

	switch($type) {
		case "boolean": return is_bool($value); break;
		case "int": return ctype_digit($value); break;
		case "float": return is_float($value); break;
		case "hex": return ctype_xdigit($value); break;
		case "string": return validateString($target, $value); break;
		case "date": return dateFormat($value, $date_format, ""); break;
		case "hour": return validateHour($value); break;
		case "url": return validateUrl($value); break;
		case "email": return validateEmail($value); break;
		default: return false;
	}
}

function validateString($target, $string) { // [] () / . ? ! _ - &aa[aaaa]; &000;

	if($string == "") { return true; }

	switch($target) {
		case "html": $pattern = "#^([A-Za-z0-9\.\?\!\[\]\(\)\s'/_-]|&[a-z]{2,6};|&\#[0-9]{3,3};){1,}$#"; break;
		case "sql": $pattern = "#^([ÉÈÊËÜÛÎÔÄÏÖÄÅÇA-Zéèëêüûçîôâïöäåaa-z0-9\.\?\!\[\]\(\)\s'/_-]|&[a-z]{2,6};|&\#[0-9]{3,3};){1,}$#"; break;
		case "": $pattern = "#^([A-Za-z0-9\.\?\!\[\]\(\)\s'/_-]){1,}$#"; break;
		default: return false;
	}
	
	return preg_match($pattern, $string) ? $string : false;
}

function validateHour($hour) {
	$pattern = "#^[0-2]{1,1}[0-9]{1,1}:[0-2]{1,1}[0-9]{1,1}$#";
	return preg_match($pattern, $hour) ? $hour : false;
}

function validateUrl($url) {
	$pattern = "#^(http://)?((www|3w|w3)\.)?[A-Za-z0-9_-]+(\.[A-Za-z]{2,4})+([^/\.]/[A-Za-z0-9_-]{0,})*(\.[A-Za-z0-9]{1,})?$#";
	return preg_match($pattern, $url) ? $url : false;
}

function validateEmail($email) {
	$pattern = "#^[A-Za-z0-9._-]+@[a-z0-9._-]{2,}\.[A-Za-z]{2,4}$#";
	return preg_match($pattern, $email) ? $email : false;
}

function validateValue($value, $min, $max) {
	return (($min == "" || $value >= $min) && ($max == "" || $value <= $max));
}

function validateLength($value, $min, $max) {
	return (($min == "" || strlen($value) >= $min) && ($max == "" || strlen($value) <= $max));
}

function dateFormat($d_date, $s_input_format, $s_output_format) {

	// checks if $d_date sticks to $s_input_format
	// checks if $d_date is a valid date
	// returns $d_date converted to $s_output_format or true if $s_output_format is an empty string

	$return = false;

	// parse date format
	$a_year_formats = array("Y","y");
	$a_month_formats = array("m","M","n");
	$a_day_formats = array("d","j");
	$a_separator_formats = array("/",".","-");

	$a_format = array();

	for($n=0;$n<=strlen($s_input_format)-1;$n++) {

		$letter = substr($s_input_format, $n, 1);

		if(in_array($letter, $a_day_formats)) {
			$a_format["day"] = $letter;
		} elseif(in_array($letter, $a_month_formats)) {
			$a_format["month"] = $letter;
		} elseif(in_array($letter, $a_year_formats)) {
			$a_format["year"] = $letter;
		} elseif(in_array($letter, $a_separator_formats)) {
			$a_format["separator"] = $letter;
		}
	}

	if(count($a_format) == 4) { // year, month, day and separator found

		$year = ""; $month = ""; $day = "";

		// explodes date according to parsed format
		$a_date = explode($a_format["separator"], $d_date);

		foreach($a_date as $i_index=>$s_value) {
			$$a_format[$i_index]["date_part"] = $s_value; // $day = 30 | $month = 12 | $year = 2009
		}

		if(checkdate($month, $day, $year)) {

			if($s_output_format == "") {
				$return = true;
			} else {
				$return = date($s_output_format, strtotime($year . "-" . $month . "-" . $day));
			}
		}
	}

	return $return;
}

Conclusion :


J'attends vos commentaires, venez nombreux !

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.