PHP ou comment supprimer des valeurs à l'aide d'un formulaire

J’ai réalisé un annuaire vachement basique (chui un n00b en php) on l’on peut insérer les donnée dans la table via un formulaire mais comment je peux faire pour pouvoir supprimer ou modifier ces données via aussi un formulaire ?
Ce message a été édité par morpheus35 le 04/02/2004

Générallement tu passe pas par un formulaire pour effacer une entrée dans la base, mais plutot par un lien. genre mapage.php?action=efface&id=25

Bien sur, c’est dans le cas ou tu a eu la bonne idée d’inclure un id (identifiant unique qui permet de repérer chaque enregistrement de ta table individuellement).

la requete SQL qui va avec ressemblerait à :

$query = "DELETE FROM matable WHERE id = $id";
Dans le cas ou tu n'a pas d'id, faut que tu choisisse une colonne qui est unique. Ou un ensemble de colonnes unique. Mais après c'est le bordel à expliquer avec le peu d'explications que tu donne

Pour la modification, c’est tout con, tu sélectionne une des entrées à modifier, tu fait une requete qui recupere toutes ces infos dans la base de donnée, et qui le met dans le formulaire

au retour de l'envoi du formulaire tu met les champs à jour dans la base (je conseille de les mettre tous à jour, y compris ceux qui n'ont pas changé, ca fait moins de taf, et les questions de vitesse n'entrent pas en ligne de compte).
$query = "UPDATE matable SET nom='$nom', auteur='$auteur' WHERE id=$id";[/quote]Il existe au moins 10.000 autres facons de gérer ce genre de chose, mais celle là est assez acessible. Jette un oeuil sur phpfrance.com si vraiment tu galere, il doit y avoir de bons exemples. [i]Ce message a été édité par bishop le 05/02/2004[/i]

Allez on va completer un peu le post de Bishop parce que j’ai que ca a faire au lieu de dormir :

  • Récuperer un champ passé en GET sur l’url (machin.php?id=2&bidule=3 par exemple), ca se fait avec le tableau superglobal $_GET maintenant ! Et pareil pour un form en POST, c’est dans $_POST (et les sessions dans $_SESSION, et les cookies dans $_COOKIE, c’est bo.)
    Parce que $id et $bidule ne seront définies que si php est configuré en mode register_globals dans le php.ini, ce qui est OFF par défaut désormais, et totalement PAS SAFE à utiliser (bah oui, vous utilisez une variable bidule dans votre script, et un rigolo la passe en GET via mapage.php?bidule=nouvellevaleur, et hop. Pour info je m’etais fait passé pour Caféine comme ça sur l’ancienne version de Cafzone. youpi.)
    Donc ca donnerait :
    $query = ‘DELETE FROM matable WHERE id=’ . $_GET[‘id’];
    (et j’utilise des ’ et pas des " pour dire à php “c’est pas la peine de traiter cette chaine pour remplacer les variables et les caractères spéciaux”, c’est toujours un micronième de seconde de gagné sur le parsing)

  • Un moyen pratique de faire juste un echo / print php dans du html, c’est <?= (c’est dans la doc, au tout début, les pages pour noobs qu’on ne lit pas )
    donc on peut faire :
    <input type=“text” name=“auteur” value="<?=$auteur?>"
    Ce message a été édité par MisterP le 05/02/2004

[quote]$query = ‘DELETE FROM matable WHERE id=’ . $_GET[‘id’];[/quote]Et il serait aussi bien vu de verifier que id ne contient qu’un entier pour s’eviter des “legers” problemes de sql injection ou id vaut “13; DELETE FROM Users;” et autres joies du genre pour te faire exectuer deux commandes en une… les joies de pas etre “strongly typed”, ca a des bons gros avantages, mais pas que…

Meme que j’ai vu aujourd’hui que qqch comme 61% des sites web peuvent etre victimes de script injections, pas loins de 45% de sql injection, 27% cookies poisoning et autres chiffres proprements effrayants… Si vous voulez pas etre dans le tas…

A consulter obligatoirement
Ce message a été édité par GloP le 05/02/2004

Je profite de la légère déviation de ce thread sur la sécurité des varibles fournie par l’utilisateur pour vous demander si cette façon de procéder est 100% safe (et efficace)

if(isset($HTTP_POST_VARS['HFilter'])){  $filter = addslashes($HTTP_POST_VARS['HFilter']); //elle peut etre dans la champ post (form)  $_SESSION['filter']=$filter; }else{  if(isset($HTTP_GET_VARS['HFilter'])){ $filter = addslashes($HTTP_GET_VARS['HFilter']); //elle peut etre dans la champ get (lien) $_SESSION['filter']=$filter;  }else{ if (isset($_SESSION['filter'])){  $filter = $_SESSION['filter']; // ou dans la session }else{  $filter = "total"; // le filtre par défaut. }  } }[/quote]En clair : Je regarde si une variable est dans le champ Post, puis Get, puis Session. Si elle est dans le champ Get ou Post le l'enregistre dans la Session. Si la variable n'est nulle-part, le prend une valleur par défaut (qui n'est pas enregistrée dans la session)

Edit : La session est gérée par le serveur (pas de cookie)
Ce message a été édité par Kane–sama le 05/02/2004

[quote]Edit : La session est gérée par le serveur (pas de cookie)[/quote]La session est toujours geree cote serveur, par contre j’aimerais bien savoir comment tu fais une session sans cookie La seule solution pour tracker les sessions hors cookie c’est la reecriture d’URL et ca fait longtemps que plus personne fait ca, a part des gros masos tares ou pour des devices en WAP tout pourris qui gerent pas les cookies. Les requetes en HTTP sont independantes les unes des autres, tu peux pas identifier qqn base sur son IP parceque t’as des proxy web qui en ont plein et te camouflent des miliers de users, donc pour “relier” toutes les requetes HTTP a un seul et meme identifiant qui te permet de stocker des infos sur le serveur “par user” (une session) il te faut un ID unique a assigner a chaque utilisateur a sa premiere requete : un cookie (yeah) dans les headers de la requete ou un identifiant unique dans chacune des requetes elle memes de l’utilisateur (beurk) GET ou POST. Tu perds cet identifiant, pour le serveur c’est un nouvel utilisateur…

(précisons juste que les cookies de sessions et les cookies “tout courts” ne sont pas gérés de la même manière (au moins dans IE))

[quote](précisons juste que les cookies de sessions et les cookies “tout courts” ne sont pas gérés de la même manière (au moins dans IE))[/quote]Oui enfin il faut aussi dire qu’un cookie “de session” peut etre utilise pour plein d’autre chose que gerer une session sur le serveur. Ca a d’ailleurs un sens completement different. Une session avec son cookie de session, peut expirer avant que le cookie de session ne disparaisse du cote client. Pour le client un cookie “de session“ vit tant que le process du browser est vivant. Alors que du cote serveur une session identifiee par son cookie peut exister plus longtemps que la derniere requete du client, et apres que le cookie de session n’existe plus nulle part chez le client. Enfin c’est pas pareil quoi

Sur le client: cookie “de session” ou cookie de “type session“ pour pas melanger: cookie qui sera efface des que le browser sera ferme, ou le process tue. Ce cookie peut contenir n’importe quoi qu’un cookie autre peut contenir. Le fait qu’il soit “de session“ n’a une influence que sur sa duree de vie. L’autre type de cookie c’est le cookie “persistant“ qui est stocke sur le disque dur.
Sur le serveur: session: ensemble de donnees, associees a un client unique donne identifie par un nombre/identifiant unique qui est stocke dans un cookie dit “de session”, qui sera stocke comme un cockie de “type session” chez le client.
Ce message a été édité par GloP le 05/02/2004

[quote] La seule solution pour tracker les sessions hors cookie c’est la reecriture d’URL et ca fait longtemps que plus personne fait ca, a part des gros masos tares

Ben merci ! Avec le short que tu viens de me tailler je suis habillé pour l’été moi …
Plus sérieusement j’utilisa la ré-écriture d’url (qui est automatique avec php) parceque que mon responsable (et pricipal utilisateur du soft, un compteur d’impression) est un gros parano des cookies (no comment…) et les desactives.
voila voila …

Edit : Il n’y a qu’une poigné d’utilisateurs du service, donc je peut stocker tout ça dans le rep /tmp du serveur sans aucun problème.

Ha , sinon, une question : justement la ré-écriture d’url m’empêche de passer le HTML validator du W3C car l’url est (a peut près) écrite comme ça :

machin.php?varalacon=truc&sID=465456464

au lieu de :

machin.php?varalacon=truc&sID=465456464

Bon, il doit y avoir une option dans la config de php etje n’ai pas pris le temps de regarder mais ça serait bien de pouvoir valider mes pages correctement.

Arg, je fais encore dévier le thread désolé morpheus35, promis c’est mon dernier post dans ce thread (sauf si je me fais encore traité de taré

Ce message a été édité par Kane–sama le 05/02/2004
Ce message a été édité par Kane–sama le 05/02/2004

[quote]Arg, je fais encore dévier le thread désolé morpheus35, promis c’est mon dernier post dans ce thread (sauf si je me fais encore traité de taré )[/quote]Vi mais c’est pas ta faute hehe  Si t’aime ca t’es maso mais le gros tare c’est ton patron (si je peux me permettre) qui est un gros parano, avoue que c’est quand meme pas la mort si t’es un minimum rationel un cookie et que la reecriture d’URL c’est quand meme hypra moche et chiant a gerer. Bon c’est vrai que pour la plupart des cas triviaux c’est auto mais, hors parano, dans la plupart des cas ou tu es oblige de le faire, meme si c’est auto, y a des contraintes super chiantes qui font que c’est RELOUD. Par exemple dans un POST, c’est pas cense etre legal de mettre des params dans l’URL, et si tu fais du WAP par exemple, et bien beaucoup de telephonne ignorent les parametres mis dans l’url si tu fais un POST, et j’ai encore jamais vu un truc “auto” etre capable de mettre l’id de session dans un post/get automatiquement selon le type de requete.

Genre sur 80% des telephonnes qui supportent pas les cookies, si tu fais
POST /Machin.php?sId=xxxxx
var1=toto;var2=tata (contenu du post quoi)

ben pour lui c’est comme si sId existait pas… super la joie a gerer…

; The separator used in PHP generated URLs to separate arguments.
; Default is “&”.
arg_separator.output = “&”

dans php.ini

simple question quelle est la fonction pour tester cela rapidement.

sinon, le param magic_quote_runtime n’est-il pas en mesure de contrer ce genre d’exploit automatiquement?

[quote]sinon, le param magic_quote_runtime n’est-il pas en mesure de contrer ce genre d’exploit automatiquement?[/quote]Non.

[quote]magic_quotes_runtime boolean

If magic_quotes_runtime is enabled, most functions that return data from any sort of external source including databases and text files will have quotes escaped with a backslash. If magic_quotes_sybase is also on, a single-quote is escaped with a single-quote instead of a backslash.[/quote]Donc non, remplacer un “3” par “3; DELETE * FROM Users”, il y a pas un seule quote a echaper avec un backslash et pourtant c’est du sql injection. Et en plus c’est “most” functions, donc pas toutes.
Ce message a été édité par GloP le 05/02/2004

Sans vouloir faire peur au "newbee" [img]style_emoticons/<#EMO_DIR#>/wink.gif[/img] , c'est bien là qu'on voit comment il est facile de faire du code unsafe en php. Le probleme du vérifier que c'est un entier, et beaucoup d'autres problemes du même ordre, viennent du fait du non-typage de ce language à script (erk). Sinon, pour ce qui est des cookies, il y a malheuresement 2 choses a constater :  - D'une part, des users paranos.  - D'autre part, des sites qui ne savent pas rendre leurs cookies "de session", ce qui pose problème lorsque des users paranos bloques les cookies qui ne sont pas de session.[/quote]

Merci pour l’aide les mecs, ca tourne bien bien maintenant (bon comme c’est un truc simple ca doit être bourré de failles de sécurité, mais bon ca à la limite je m’en fou

[quote]; The separator used in PHP generated URLs to separate arguments.
; Default is “&”.
arg_separator.output = “&”

dans php.ini[/quote]Merci !

Au fait, le SQL injection c’est pas si facile que ça, car par défaut (avec les version récentes d’apache, les autres je ne sais pas) on ne peut faire qu’une seul requête SQL à la fois. Il faut donc que le hacker (cracker) fasse passer sa commande avant la bonne commande.

[quote]
Au fait, le SQL injection c’est pas si facile que ça, car par défaut (avec les version récentes d’apache, les autres je ne sais pas) on ne peut faire qu’une seul requête SQL à la fois. Il faut donc que le hacker (cracker) fasse passer sa commande avant la bonne commande.
Tout à fait exa, pour la lib MySQL en tous cas, la fonction mysql_query() n’execute qu’une seule commande, et théoriquement celle-ci ne doit même pas contenir de ; final. Donc le coup de passer une commande supplémentaire après un ; c’est zob, j’ai déjà essayé

Enfin, si on veut vraiment vérifier qu’on parle bien d’un id numérique, il existe la fonction bool is_numeric(mixed $variable)  (ou is_int(), is_float() et is_whateveryouwant() ) 

Le php EST typé implicitement, suffit de faire un cast ou un check et basta, hein.

[quote]
if(isset($HTTP_POST_VARS[‘HFilter’])){
 $filter = addslashes($HTTP_POST_VARS[‘HFilter’]); //elle peut etre dans la champ post (form)
 $_SESSION[‘filter’]=$filter;

Ici, l'interet du addslashes() est redondant, vu que le contenu du $HTTP_POST_VARS (qui est deprecated et devrait être $_POST, donc...) est déjà escapé si tu avais le magic_quotes sur on, ce qui, avouons le, est quand même plutôt pratique et bien souvent le cas. Mettre des addslashes() et des stripslashes() partout, c'est MAL. Je l'ai suffisamment fait pour me rendre compte de l'enorme bêtise que c'est par la suite, quand tu vois des se multiplier partout ! Il faut juste s'en servir quand c'est utile

Ce message a été édité par MisterP le 06/02/2004

Ben c’est facile de gruger quand meme dans ces cas la.
Si t’as un truc qui fait :

SELECT CAtegoryName WHERE CategoryAuthorId=$id

qui retourne toute les categories avec un certain auteur par exemple.

Tu remplaces $id par 0 UNION SELECT pwd FROM Users 
et ben paf, au lieu de t’afficher les categories il va t’afficher les mot de passe de tout le monde (au pire son hash mais c’est deja pas cool). Que tu escape le quote ou pas… C’est un exemple bidon mais ca se trouve souvent.

En plus autre chose, c’est que meme avec une seule commande et le magic_quote on, je suis pas persuade que les valeurs qui viennent de la DB elle meme soient “magic_quotees” aussi. Il suffit que quelqu’un re-utilise une valeur qu’il a chope de la DB sans faire attention et poum.

Genre je m’inscrit sur un site avec le nom

admin’–

Bon, le mec malin sur le serveur, il se dit “moi j’echape tout ce qui me vient de dehors”.
Paf il insere proprement dans la base de donnee admin’–. Le quote a ete echape et tout, la commande a marche, pas de soucis.

Maintenant ademettons qu’il y a une interface pour changer son mot de passe par ex…

Le truc verifie l’ancien mot de passe, puis met a jour ledit mdp.
Donc…

  1. Verification de l’ancien mot de passe
    le_user = select * from users where nom=$_POST[”username”] and passwd=$_POST[”oldpasswd”]

bon, la aussi pas de risque, tout est bien echape et tout ce qui vient de $_POST a bien ete echappe proprement.

Bon, maintenant raisonnement de base alacon: tout ce qui est dans la DB est safe puisque tout a ete filtre avec des magic_Quote avant d’y rentrer.

Maintenant le piege, le gars il fait.

  1. UPDATE Users SET passwd=$_POST[”newpasswd”] WHERE USERNAME=le_user[”UserName”]

poum il vient de se faire baiser la gueule et de changer le mdp de l’admin.

C’est un exemple a la con vite fait, ou c’est pas super “normal“ que le mec ait reutilise une valeur dans la DB plutot que de reutiliser la variable du post. Mais c’est simple a piger comme ca, il y a des cas bien plus malin qui marchent meme avec l’echapage des chaine auto.

Enfin tout ca pour dire que magic_quote et une seule requete, ca protege des cas les plus evidents a la portee de tout farceur de 12 ans Pour le reste c’est un peu plus complexe sans les outils qu’il faut.

euh encore une dernière question, pour supprimer une valeur en fonction de plusieurs conditions (j’ai mis un id mais je préfèrerait supprimer à partir des données)
enfin bref mon bleme c’est que avec cette ligne la ca fonctionne trés bien :

$sql = "DELETE FROM matable where nom = '$nom'";
mais si je veux insérer une 2e condition comme la :
$sql = "DELETE FROM matable where nom = '$nom'& prenom = '$prenom'";[/quote]ben ca merde, selon le séparateur, des fois cela m'affiche une erreur, des fois pas mais jamais rien n'est supprimé.

Quel séparateur est d’usage dans ce cas ?

EDIT : masquage des noms de tables parceque je suis pas ranaux
Ce message a été édité par morpheus35 le 14/02/2004

AND