Newsgroup: it.comp.www.php
Titolo: Domanda banale su MySQL e PHP

Salve a tutti. Forse la mia è una FAQ banale ma non riesco a trovare
una risposta, pur avendo googlato un bel po', dove mi riconosca nel
problema.
Il problema è questo: ho realizzato un sito per un'associazione che
prevede la possibilità per ciascun socio di modificarsi le proprie
pagine.
In locale funziona tutto bene, in remoto la query fallisce quando uso
i caratteri "soliti" (cioè apici, doppi apici e slash). Qualcuno ha
qualche suggerimento?
Grazie a tutti.
Ciao,
BadAnimal

 qualche suggerimento?
magic_quotes impostato su uno dei due?
Controlla che il php.ini (e la versione di php) locale sia uguale a quello
del server.
Se possibile, non usare magic_quotes e nemmeno addslashes, ma direttamente
mysql_real_escape_string su ogni parametro.
Bye.

 mysql_real_escape_string su ogni parametro.
Al di la che è più facile programmare impostando i parametri di controllo
da script (così sono io che decido cosa e come fare una certa operazione),
c'è un motivo per preferire mysql_real_escape_string a magic_quotes
impostato nel PHP.ini? Parlo a livello di sicurezza contro le sql
injectione e via discorrendo.
Ciao Stefano

 injectione e via discorrendo.
Principalmente che diversi DB hanno diverse convenzioni.
Alcuni fanno l'escape dell'apice con \' altri con '' per esempio.
Con mysql_real_escape_string (per MySQL, naturlamente) e funzioni
analoghe, risolvi il problema ed eviti anche le subquery.
La "strada del futuro", IMHO, e` PDO, dove scrivi
$pdo = new PDO("mysql:....");
$st = $pdo->prepare("select * from utenti where password = :password");
$res = $st->execute(array(":password"=>$_POST["password"]));
e si arrangia lui a fare tutto l'escaping in base al DB che stai usando.
Bye.

 e si arrangia lui a fare tutto l'escaping in base al DB che stai usando.
Aggiungo solo all'ottima nota di Alessandro, che, qualora il server non 
metta a disposizione PDO, si può sempre creare un wrapper con il quale 
fare la stessa cosa, e non è nemmeno un'impresa difficile. :-)
--
rob4you

 del server.
Le versioni di PHP sono diverse: 4.3.10 quella in locale e 4.4.4
quella di aruba.
Grazie mille per la risposta e la velocità.
Ciao,
BadAnimal

 analoghe, risolvi il problema ed eviti anche le subquery.
Quindi è solo un problema di convenzioni e maggiore correttezza nella
programmazione nel caso si volesse cambiare database. Dal punto di vista
della sicurezza è lo stesso.
Lo dico perchè ormai per un progetto ho fatto così e non mi va (almeno per
il momento) di sbattermi a modificare decine e decine di query.
Era il primo, adesso ogni inserimento è lo faccio tramite una funzione che
in base al settaggio del server imposta i paremetri adatti e in un futuro
pdo basterà cambiare la funzione e tutte le query saranno seguiranno le
nuove regole.
Ciao Stefano

 quella di aruba.
Non dovrebbe cambiare molto. Ma visto che sul server hai una versione piu`
recente, se puoi aggiorna anche in locale, in modo da usare le nuove
caratteristiche del linguaggio.
Bye.

 raddoppia.
Quello che non capisco, e che poi mi ha portato a scrivere su questo
newsgroup, è che se l'escaping venisse raddoppiato io dovrei vedere \'
anzichè '.
Invece la query fallisce. Ho provato a impostare il parametro su OFF
creando un file di nome .htaccess che ho messo nella directory
principale del sito e che ha come testo "php_flag magic_quotes_gpc
Off" (senza virgolette). Non è cambiato nulla e la query continua a
fallire.
Grazie per l'aiuto.
Ciao,
BadAnimal

 fallire.
Posta codice (un pezzo significativo) ed errore.
Bye.

 Posta codice (un pezzo significativo) ed errore.
$testo  = htmlentities($_POST['testo']);
		if (ereg("&amp;#[0-9]{4,5};",$testo)){$testo =
str_replace("&amp;#","&#",$testo);}
		if (ereg("&lt;strong&gt;",$testo)){$testo =
str_replace("&lt;strong&gt;","<strong>",$testo);}
		if (ereg("&lt;/strong&gt;",$testo)){$testo = str_replace("&lt;/
strong&gt;","</strong>",$testo);}
		if (ereg("'",$testo)){$testo = str_replace("'","\'",$testo);}
		$testo = nl2br($testo);
		$testo = trim($testo);
$alt4 = ($_POST['alt4']);
		if (ereg("&amp;#[0-9]{4,5};",$alt4)){$alt4 =
str_replace("&amp;#","&#",$alt4);}
		if (ereg("'",$alt4)){$alt4 = str_replace("'","\'",$alt4);}
		$alt4 = nl2br($alt4);
		$alt4 = trim($alt4);
$sql = "UPDATE it SET lmtitolo = '$lmtitolo', lmtesto ='$lmtesto',
testo='$testo', sconticc='$sconticc', sconticv='$sconticv',
	servizicc='$servizicc', servizicv='$servizicv', auto='$auto',
treno='$treno', aereo='$aereo',
	alt1='$alt1', alt2='$alt2', alt3='$alt3', alt4='$alt4' WHERE
id='$id'";
	$ris = MySQL_query($sql) or die ("Query fallita");
MySQL_close();
Tutti gli altri ($lmtitolo, $lmtesto, $sconticc, ecc.) sono identici a
$alt4 che ho postato.
L'errore, banalmente, è quel "query fallita" che ho messo come "die"
se l'interrogazione non va a buon fine.
Grazie ancora.
Ciao,
BadAnimal

 se l'interrogazione non va a buon fine.
anziché usare un errore generico, scrivi:
die(mysql_errno().": ".mysql_error());
così vediamo più correttamente che succede.
--
rob4you

 die(mysql_errno().": ".mysql_error());
1064: You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'olio extra-vergine prodotti da Sturaro sono la migliore testimon
Se metto un backslash prima dell'apice l'errore resta identico, se
invece tolgo l'apice (e scrivo, erroneamente, "lolio extra-vergine")
il messaggio si ripresenta nel punto successivo dove c'è un apice.
Grazie per la disponibilità mostrata sinora.
Ciao,
BadAnimal

 il messaggio si ripresenta nel punto successivo dove c'è un apice.
Chiaramente è un problema di escaping.
Usare addslashes così com'è "rischioso" proprio perché se hai 
"magic_quotes_gpc" a ON ti viene raddoppiato l'escaping.
Controlla anche l'impostazione di "magic_quotes_sybase".
Se comunque vuoi continuare a usare addslashes piuttosto che 
mysql_real_escape_string (che ti è stata consigliata già, e anche il 
manuale stesso la consiglia), sul manuale è riportata una versione 
"migliorata" dell'addslashes, che tiene conto del magic_quotes:
function real_addslashes($string) {
   if (!get_magic_quotes_gpc()) {
      return addslashes($string);
   } else {
      return $string;
   }
}
--
rob4you

 "migliorata" dell'addslashes, che tiene conto del magic_quotes:
Ma adesso magic_quotes_rpc l'ho messo a OFF con un file .htaccess
Cosa faccio? Lo lascio a OFF, metto a ON mysql_real_escape_string e
tolgo il comando "if (ereg("'",$testo)){$testo = str_replace("'","\'",
$testo);}"?
Grazie mille per l'aiuto.
Ciao,
BadAnimal

 Ma adesso magic_quotes_rpc l'ho messo a OFF con un file .htaccess
Sei sicuro che il server l'abbia interpretato?
Se fai un phpinfo() in quella directory il magic_quotes e` on o off?
Bye.

 $testo);}"?
Quest'ultimo str_replace non è il modo più corretto di operare :-)
Le soluzioni sono appunto due:
- o usi la funzione addslashes (o meglio quella que ti ho postato io: 
real_addslashes) per fare l'escaping degli apici,
- o meglio ancora usi la funzione specifica del db (in mysql è appunto 
mysql_real_escape_string).
Inoltre, un modo migliore per converitire i tag html con le loro 
rappresentazioni in entità, è l'uso della funzione htmlspecialchars (di 
cui ti invito a dare una lettura sul manuale). Se vuoi poi convertire 
tutti i caratteri nelle loro entità, allora puoi usare htmlentities.
Entrambe queste funzioni hanno un parametro opzionale intero (il 
quote_style) con il quale specifichi che fare degli apici doppi o 
singoli (cioè se convertire anche essi o meno).
Leggendo il tuo codice, non ho capito del resto perché prima fai la 
conversione in entità, e poi riconverti il tag <strong>.
Che obiettivo vuoi raggiungere in concreto?
--
rob4you

 Che obiettivo vuoi raggiungere in concreto?
Preferisco htmlentities a htmlspecialchars semplicemente perchè
preferisco &agrave; ad à.
Il tag <strong> è l'unico che voglio rimanga. Lo scopo del database è
quello di permettere a tutti i soci di un'associazione di modificarsi
le loro pagine autonomamente. Non possono inserire HTML, l'unica cosa
concessa è enfatizzare parti di testo col grassetto (per questo ho
lasciato il tag <strong> ma se noti solo per uno dei parametri,
$testo. Per tutti gli altri no.)
Grazie davvero per l'aiuto che mi state dando.
Ciao,
Nicola
PS: continuo a leggervi e a rispondere ai vostri preziosissimi
suggerimenti ma in concreto fino a venerdì non potrò mettere le mani
(salvo forse piccolissime modifiche) al codice.

 Se fai un phpinfo() in quella directory il magic_quotes e` on o off?
Purtroppo sino a venerdì non posso mettere le mani al sito e vedere
quello che chiedi. In effetti non sono per niente sicuro. Volevo
comunque ringraziarti per la disponibilità che mi stai dando col tuo
prezioso aiuto.
Ciao,
BadAnimal

 Il tag <strong> è l'unico che voglio rimanga. 
Ah capito. A questo punto potresti pure usare la funzione 
strip_tags($testo,'<strong>') e con una riga sei a cavallo. :-)
--
rob4you

 strip_tags($testo,'<strong>') e con una riga sei a cavallo. :-)
Perfetto. Grazie. Posso abusare della tua gentilezza ancora?
$alt4 = ($_POST['alt4']);
if (ereg("&amp;#[0-9]{4,5};",$alt4)){$alt4 =
         str_replace("&amp;#","&#",$alt4);}
if (ereg("'",$alt4)){$alt4 = str_replace("'","\'",$alt4);}
$alt4 = nl2br($alt4);
$alt4 = trim($alt4);
Questi comandi li devo ripetere per ogni variabile (e come avrai visto
sono diverse).
Ho provato a creare una funzione, che dovrebbe essere abbastanza
banale, ma non ci sono riuscito.
Grazie davvero di tutto.
Ciao,
BadAnimal

 $alt4 = trim($alt4);
Restano queste due righe che puoi scrivere anche così:
$alt4 = trim(nl2br($_POST['alt4']));
Se propri ovuo creare una funzione...beh, a questo punto è banale. :-)
--
rob4you

 così. :-)
Sono sempre BadAnimal ;)
Intanto, con un po' di ritardo ti ringrazio per la spiegazione
dettagliata.
Ho provato così
$testo =
mysql_real_escape_string(nl2br(trim(htmlentities($_POST["testo"]))));
e la query non fallisce però vengono visualizzati i backslash. Sembra
ci sia qualcosa che li raddoppia ma non capisco il perchè.
Riuscite, ancora una volta, ad aiutarmi?
Grazie mille.
Ciao,
BadAnimal

 ci sia qualcosa che li raddoppia ma non capisco il perchè.
Tra l'altro, se li tolgo, la query funziona (però non mi funziona più
il nl2br ma non penso sia una cosa difficile da risolvere).
Ciao,
BadAnimal