par
naholyr » 04 nov. 2007, 18:10
Je vais zapper le débat, mais je tenais quand-même à dire que perso je ne connais pas la doc par cœur. Je sais pas vous mais à chaque fois que j'utilise in_array(), array_walk(), array_map(), strpos(), etc… je vais vérifier l'ordre des paramètres (merci l'homogénéité de PHP…).
Cela dit, et j'espère que ça ne fera pas débat parce que ça c'est vraiment la base de la sécurité (comprendre l'ultra-minimum) si vous n'utilisez pas PDO et aucun système d'abstraction, il faut toujours au moins passer par un système permettant de protéger vos requêtes.
Voici la fonction que je file à mes collègues qui travaillent un peu à l'arrache (php4, pas d'abstraction, bref du site jetable) histoire de sécuriser un minimum les sites. C'est un peu merdique mais ça a le mérite de marcher et de ne pas nécessiter un manuel d'utilisation de 12 pages.
/**
* @var mixed $var
* @return string Conversion de $var en expression utilisable dans une requête
**/
function var2sql($var) {
if (is_string($var)) {
return '"' . mysql_real_escape_string($var) . '"';
} elseif (is_numeric($var)) {
return $var;
} elseif (is_array($var)) {
return '(' . implode(',', array_map('var2sql', $var)) . ')';
} else {
return strval($var);
}
}
/**
* Retourne le résultat d'une requête
* @var string $sql Requête
* @var array $params Tableau de paramètres à insérer dans la requête, les mots-clé
* #{clé} seront remplacé par $params[clé] protégé.
* @var boolean $expand_select Si la requête est un SELECT et que ce paramètre
* est à true, alors la fonction renverra le tableau des résultats (tableaux associatifs)
* @return resource|array Résultat de la requête
**/
function query($sql, $params, $expand_select = true) {
foreach ($params as $key => $param) {
$sql = str_replace('#{' . $key '}', var2sql($param)
}
$result = mysql_query($sql);
if ($expand_select && strtoupper(substr(ltrim($sql), 0, 6)) == 'SELECT') {
$items = array();
while ($item = mysql_fetch_assoc($result)) {
$items[] = $item;
}
return $items;
} else {
return $result;
}
}
Cela permet non seulement d'avoir un peu de sérénité (tout ce qui est passé dans $params est automatiquement échappé au besoin) et aussi de simplifier grandement l'écriture des requêtes (les tableaux sont automatiquement transformés, les chaines ont leurs guillemets ajoutés).
Exemple :
// Trouver un utilisateur sur certains critères
$params = array(
'ids' => array(1, 2, 3), // Son ID est parmi ceux-là
'nom' => 'Bob%', // Nom d'utilisateur commence par Bob
'age_min' = 13, // Age minimum
);
$result = query('SELECT * FROM users WHERE nom LIKE #{nom} AND id IN #{ids} AND age >= #{age_min}', $params);
Je vais zapper le débat, mais je tenais quand-même à dire que perso je ne connais pas la doc par cœur. Je sais pas vous mais à chaque fois que j'utilise in_array(), array_walk(), array_map(), strpos(), etc… je vais vérifier l'ordre des paramètres (merci l'homogénéité de PHP…).
Cela dit, et j'espère que ça ne fera pas débat parce que ça c'est vraiment la base de la sécurité (comprendre l'ultra-minimum) si vous n'utilisez pas PDO et aucun système d'abstraction, il faut toujours au moins passer par un système permettant de protéger vos requêtes.
Voici la fonction que je file à mes collègues qui travaillent un peu à l'arrache (php4, pas d'abstraction, bref du site jetable) histoire de sécuriser un minimum les sites. C'est un peu merdique mais ça a le mérite de marcher et de ne pas nécessiter un manuel d'utilisation de 12 pages.
[php]/**
* @var mixed $var
* @return string Conversion de $var en expression utilisable dans une requête
**/
function var2sql($var) {
if (is_string($var)) {
return '"' . mysql_real_escape_string($var) . '"';
} elseif (is_numeric($var)) {
return $var;
} elseif (is_array($var)) {
return '(' . implode(',', array_map('var2sql', $var)) . ')';
} else {
return strval($var);
}
}
/**
* Retourne le résultat d'une requête
* @var string $sql Requête
* @var array $params Tableau de paramètres à insérer dans la requête, les mots-clé
* #{clé} seront remplacé par $params[clé] protégé.
* @var boolean $expand_select Si la requête est un SELECT et que ce paramètre
* est à true, alors la fonction renverra le tableau des résultats (tableaux associatifs)
* @return resource|array Résultat de la requête
**/
function query($sql, $params, $expand_select = true) {
foreach ($params as $key => $param) {
$sql = str_replace('#{' . $key '}', var2sql($param)
}
$result = mysql_query($sql);
if ($expand_select && strtoupper(substr(ltrim($sql), 0, 6)) == 'SELECT') {
$items = array();
while ($item = mysql_fetch_assoc($result)) {
$items[] = $item;
}
return $items;
} else {
return $result;
}
}[/php]
Cela permet non seulement d'avoir un peu de sérénité (tout ce qui est passé dans $params est automatiquement échappé au besoin) et aussi de simplifier grandement l'écriture des requêtes (les tableaux sont automatiquement transformés, les chaines ont leurs guillemets ajoutés).
Exemple :
[php]// Trouver un utilisateur sur certains critères
$params = array(
'ids' => array(1, 2, 3), // Son ID est parmi ceux-là
'nom' => 'Bob%', // Nom d'utilisateur commence par Bob
'age_min' = 13, // Age minimum
);
$result = query('SELECT * FROM users WHERE nom LIKE #{nom} AND id IN #{ids} AND age >= #{age_min}', $params);[/php]