Newsgroup: it.comp.www.php
Titolo: PHP Security (articolo)

Il mio piccolo contributo alla security del PHP nella speranza che
un giorno venga riconosciuto come sistema adatto per le applicazioni
"importanti".
L'articolo formattato per benino in HTML si trova qui:
http://www.icosaedro.it/articoli/php-security.html
Qui sotto c'e' la versione in puro testo.
Suggerimenti e critiche sono utili e necessari.
Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  
www.icosaedro.it
PHP Security
============
In breve
L'articolo PHP Analisi Critica si concentrava sugli aspetti di safety, 
cioè sul come scrivere programmi privi di difetti logici. Questo articolo 
analizza invece la questione della security, cioè come scrivere programmi 
che resistono agli attacchi in un ambiente ostile come il WEB. Il PHP è 
abbastanza versatile da offrire al programmatore infiniti modi per 
spararsi nei piedi, per cui la security si esprime meglio in consigli sul 
"come fare" piuttosto che nel "come non fare". In questo senso questo 
articolo non ha ragione di esistere ma piuttosto ha lo scopo di mettere in 
guardia contro le trappole più comuni.
Indice
------
    Il PHP è veramente poco sicuro?
    Installazione e configurazione del php.ini
    Validazione dell'input
    Uso dei database
    Varie
    Riferimenti
    Argomenti correlati
Il PHP è veramente poco sicuro?
-------------------------------
Recentemente c'è stato un dibattito su BUGTRAQ (la famosa mailing list 
dove vengono segnalati i problemi di sicurezza dei sistemi software) a 
riguardo della sicurezza del PHP, sia come linguaggio, sia come sistema di 
sviluppo dei siti WEB attivi, sia più in generale sui prodotti sviluppati 
in PHP. Il titolo di questo thread è piuttosto significativo: "PHP 
security (or the lack thereof)". Sono emersi alcuni punti che mi sembrano 
interessanti.
Documentazione carente sugli aspetti della security. 
na...@hotmail.com
 
osserva che il PHP viene presentato agli sviluppatori come strumento che 
"permette di sviluppare rapidamente i siti WEB dinamici" 
(
www.php.net/manual/en/faq.general.php
) e quindi un breve tutorial 
(
www.php.net/manual/en/tutorial.php
) dovrebbe bastare a preparare il 
programmatore ad affrontare l'ambiente ostile della rete. Ciò che invece 
spesso manca al neofita della programmazione WEB sono le basi della 
programmazione, le nozioni sui protocolli di rete e una seria introduzione 
alle tecniche di sicurezza, tutti argomenti sui quali la documentazione 
ufficiale del PHP è piuttosto carente. Il neofita si convince così che la 
programmazione WEB sia facile e si lancia allo sbaraglio producendo 
applicazioni piene di vulnerabilità delle quali non è consapevole.
Applicativi WEB poco affidabili. Il successo del PHP come sistema rapido 
per lo sviluppo WEB si misura anche con la grande quantità di prodotti di 
terze parti disponibili in rete, spesso gratuitamente. Si tratta per lo 
più di sistemi per la gestione dei contenuti dei siti WEB, per la gestione 
di blog/forum/news/chat, e per il commercio elettronico. Questi pacchetti 
sono tanto curati nella presentazione grafica quanto lacunosi sugli 
aspetti della security. Ecco perché su prodotti come PhpBB, PHP-Nuke, 
Mambo e Joomla sono così frequenti le segnalazioni di vulnerabilità, ed 
ecco perché i soliti problemi di "SQL-injection", "cross-site scripting" e 
il famoso "register globals" si ripetono puntualmente. In definitiva, 
afferma ancora 
na...@hotmail.com
, in questo caso non si tratta di un 
problema di documentazione, ma di un problema della comunità del PHP che 
non sembra in grado di selezionare ed emendare i suoi prodotti in modo da 
renderli più maturi e solidi sotto l'aspetto della security.
PHP paga il prezzo della sua stessa popolarità. Ronald Chmara osserva che 
oggigiorno ormai PHP si trova installato su una grande quantità di sistemi 
server WEB: il 43% dei server dichiarano di usare PHP, mentre solo il 3.7% 
dichiarano di usare una tecnologia basata su Java. Riguardo invece alle 
vulnerabilità che interessano i due sistemi e i prodotti sviluppati con 
essi, Ronald trova 1181 segnalazioni afferibili al PHP e solo 152 
afferibili al secondo sistema; dobbiamo considerare anche il fatto che il 
sistema più diffuso diventa anche quello meglio conosciuto e quindi più 
attaccato, per cui Ronald suggerisce piuttosto di confrontare il rapporto 
tra la diffusione del sistema e il numero di vulnerabilità segnalate. Si 
scopre allora che i sistemi basati sul PHP risultano più solidi sotto il 
profilo della security, avendo un rapporto diffusione/vulnerabilità più 
elevato (0.036 contro 0.024). Ci dobbiamo consolare? Certo che no: 
evidentemente, conclude Ronald, il PHP è troppo facile da usare e quindi 
viene adottato da troppi sviluppatori senza esperienza che finiscono per 
produrre cattivo codice, cioè programmi funzionanti in condizioni normali, 
ma incapaci di resistere agli attacchi più banali. E qui la responsabilità 
di nuovo investe la comunità del PHP, che dovrebbe selezionare e poi 
sostenere solo i progetti che lo meritano. Insomma, ridurre la quantità 
per migliorare la qualità.
Percezione del PHP come di un sistema per pasticcioni e improvvisati. E' 
questo il modo sbrigativo con il quale i più liquidano la natura del PHP. 
Questa è una concezione che tente ad autoalimentarsi, complice il fatto 
che il PHP ha una bassa barriera di ingresso e quindi viene spesso 
adottato da neofiti per applicazioni di modesta complessità, mentre le 
applicazioni più avanzate rimangono appannaggio degli sviluppatori esperti 
che usano altri sistemi. Secondo me questa percezione è errata e deve 
cambiare, soprattutto nella mentalità di chi ne fa uso. Nulla vieta di 
usare il PHP per applicazioni complesse e sofisticate, è una questione di 
metodo, non di strumento. Il PHP è "liberista", ma ciò non deve coincidere 
con il "pressapochismo": il programmatore non si deve accontentare di un 
programma "che funziona", deve pretendere che sia anche sicuro, ordinato e 
formalmente corretto.
Fatte queste premesse politiche, passiamo agli aspetti più strettamente 
tecnici della security in ambito PHP.
Installazione e configurazione del php.ini
------------------------------------------
Aggiornare PHP all'ultima versione disponibile. La frequenza con la quale 
il PHP viene aggiornato è piuttosto elevata, diciamo che ogni due o tre 
settimana esce una nuova versione che corregge qualche vulnerabilità. 
Spesso le vulnerabilità in questione sono di poco conto perché si 
manifestano solo con particolari combinazioni di configurazioni e di 
codice. E' comunque sempre meglio rimanere aggiornati all'ultima versione 
di PHP disponibile. Notare che la versione 4 del PHP non viene più 
sviluppata, ma è ancora largamente utilizzata, per cui viene ancora 
aggiornata con regolarità anch'essa. Sono disponibili pacchetti 
precompilati del PHP, spesso molto comodi perché non richiedono la 
compilazione: in questo caso fare attenzione che la versione del PHP sia 
la più recente, in caso contrario procedere nel modo "normale".
In ambienti multi-utente usare la versione CGI con SUEXEC. I sistemi 
operativi multiutente permettono di disciplinare l'accesso alle risorse in 
base all'utente cui appartiene il processo in esecuzione. Anche 
l'interprete PHP è un processo, e quindi anche il PHP risente di questo 
meccanismo. Purtroppo spesso il server WEB viene configurato per l'uso 
"monoutente", cioè tutti i programmi WEB vengono eseguiti con la stessa 
identità e ogni processo ha gli stessi diritti. Questo apre numerose falle 
di sicurezza quando il sistema diventa multiutente. Apache, uno dei WEB 
server più utilizzati, ha una interessante funzionalità detta SUEXEC che 
permette di eseguire i programmi WEB con l'identità dell'utente a cui 
appartiene il file; questo però esige che il PHP venga utilizzato nella 
forma CGI. Nella sezione dedicata al WEB server Apache viene spiegato come 
configurare il SUEXEC e come compilare il PHP con il supporto CGI [v. link
sulla pagina HTML].
Non mettere l'interprete PHP CGI richiamabile dalla DocumentRoot. 
L'interprete PHP dovrebbe sempre stare in una directory distinta da quella 
del WEB server, in modo che non sia mai richiamabile direttamente dal WEB.
error_reporting = E_ALL | E_STRICT
Questa opzione del php.ini abilita la segnalazione di tutti i problemi che 
l'interprete incontra, incluse variabili usate ma non inizializzate. 
L'opzione E_STRICT è solo per PHP5.
display_errors = Off
display_startup_errors = Off
log_errors = On
track_errors = On
warn_plus_overloading = On
E' bene salvare tutti gli errori nel log del server WEB. L'utente, invece, 
non dovrebbe mai ricevere i messaggi di errore perché rivelano troppe 
informazioni sul funzionamento del programma e facilitano l'attacco. 
Durante il debugging basta guardare il log con un comando come "tail -f 
/var/log/apache/error.log" che mostra gli errori man mano che vengono 
generati. Se non si ha accesso diretto al log non rimane che abilitare il 
display_errors, ricordando però di disattivarlo al termine della fase di 
debugging. Il file di log degli errori deve comunque essere esaminato con 
regolarità durante tutto il tempo di funzionamento dell'applicativo WEB.
register_globals = Off
Quando register_globals è attivo, il PHP istanzia delle variabili globali 
per ogni parametro della request HTTP; ogni variabile ha il nome del 
parametro stesso. Ad esempio, se l'utente invia la richiesta 
http://miosito/prova.php?i=3
 il PHP assegna la variabile globale $i = 
"3";. E' vero che questo torna comodo, ma diventa pericoloso quando il 
programmatore sfrutta le variabili non inizializzate convinto che abbiano 
un valore default 0 oppure la stringa vuota. Questo, oltre ad essere una 
pessima pratica di programmazione, espone a un grave pericolo quando i 
register_globals sono abilitati. Disabilitare i register_globals è quindi 
sempre una buona idea. Praticamente ogni giorno vengono segnalati problemi 
di security in applicazioni che invece fanno uso di questa funzionalità, 
perciò partiamo con il piede giusto ed eliminiamo anche le applicazioni 
che ne fanno uso.
allow_url_fopen = Off
Di solito i programmi non necessitano di questa funzionalità, meglio 
disabilitarla.
Validazione dell'input
----------------------
Tutto quello che proviene dal browser potrebbe essere artefatto. I 
parametri vengono inviati dal browser al programma sul server via 
richiesta GET o via richiesta POST. In entrambi i casi i valori ritornati 
possono essere del tutto arbitrari:
    * Parametri attesi potrebbero mancare mentre altri parametri inattesi 
potrebbero essere presenti.
    * Non possiamo fare affidamento sui campi nascosti dei FORM perché il 
loro valore è falsificabile esattamente come per gli altri parametri. 
Pertanto se usiamo i campi nascosti per salvare informazioni di stato, 
dovremo poi fare molta attenzione nel validare questi valori.
    * Non possiamo fare affidamento sui valori dei control di tipo radio, 
check button o menu a tendina: anche questi sono falsificabili. Spesso le 
applicazioni usano il valore di questi control per specificare la chiave 
primaria del record da mostrare o da cancellare: se l'utente falsifica 
questo valore può accedere arbitrariamente alle informazioni del nostro DB 
o cancellarle del tutto!
    * Valori attesi di tipo numerico potrebbero essere stringhe o 
viceversa. Se aspettiamo un numero, non è detto che questo numero sia 
positivo e non è detto che abbia un valore ragionevole.
    * I parametri potrebbero essere di lunghezza arbitraria: l'attributo 
maxlength=20 presente nei control dei FORM non garantisce affatto che la 
lunghezza massima della stringa sia di 20 caratteri.
    * Non si può fare affidamento sul fatto che l'encoding delle stringhe 
sia quello atteso. Le stringhe potrebbero contenere byte arbitrari non 
definiti dal charset previsto.
    * I parametri $_GET[] $_POST[] $_REQUEST[] sono di norma stringhe, ma 
possono anche essere array. Vedremo degli esempi più avanti. 
Nella pratica dobbiamo pensare che il contenuto degli array $_GET[] e 
$_POST[] sia del tutto arbitrario. Per meglio chiarire il contenuto di 
questi array, esploriamo la casistica. Nei prossimi esempi supporremo che 
il programma sul server sia in attesa di un certo parametro n di tipo 
numerico, oppure di un parametro s di tipo stringa e vediamo come PHP 
istanzia l'array $_GET[] quando la pagina viene richiamata con vari URL e 
diverse combinazioni dei parametri della query:
http://miosito/prova.php
    Nessun parametro di query. Siccome il parametro 'n' manca, 
l'espressione $_GET['n'] produce il messaggio di errore PHP Notice: 
Undefined index: n in /path/miosito/prova.php on line 7. Se il parametro è 
obbligatorio questo messaggio è opportuno e ci mette in guardia che 
qualcuno sta attentando al nostro programma.
    Il fatto curioso è che se assegnamo il valore di $_GET['n'] a una 
variabile direttamente, l'assegnamento fallisce e la variabile risulta non 
settata:
$n = $_GET['n'];  # ==> Notice: Undefined index:  n in ...
if( ! isset($n) )
    echo "valore di n indefinito!";  # stampa questo!
    Per evitare inconvenienti nel codice che segue ed evitare ripetute 
segnalazioni, conviene eseguire il cast a (int) che assicura che la 
variabile venga comunque assegnata anche se il parametro della query 
manca. In definitiva, ecco il codice da usare quando il parametro n è 
obbligatorio:
$n = (int) $_GET['n'];
    In questo caso se il parametro della query manca, $n assume il valore 
0. Se invece il parametro è opzionale dovremo verificare se il parametro 
esiste ed eventualmente usare un valore default quando manca. In 
definitiva, questo è il codice da usare quando il parametro n è opzionale:
if( isset($_GET['n']) )
    $n = (int) $_GET['n'];
else
    $n = -1; # oppure altro valore default
http://miosito/prova.php?n=123
    Parametro di query "verosimile", anche se non è detto che il valore 
"123" sia poi lecito. In questo caso $_GET['n'] è la stringa "123". Notare 
che si tratta proprio di una stringa, non di un numero intero. Negli 
esempi di prima il typecast (int) assicura che la variabile $n sia 
effettivamente un numero intero. 
http://miosito/prova.php?n[]=1&n[]=2&n[]=3
    Quando il nome dei parametri della query contiene le parentesi 
quadrate, il PHP costruisce un array. In questo caso $_GET['n'] è l'array 
di stringhe array("1", "2", "3"). Nel nostro caso il parametro n è atteso 
essere un numero intero: il typecast (int) convertirà l'array nel numero 0 
(zero). 
http://miosito/prova.php?n[]=1&n[]=2&n[][]=3&n[][][]=4
    Il PHP permette anche di costruire array di array. In questo caso 
$_GET['n'] è un array di stringhe frastagliato array("1", "2", array("3"), 
array( array("4") ) ). Notare che i primi due elementi dell'array sono 
stringhe, il terzo è un array di una stringa, e il quarto è un array di un 
array di una stringa. 
Il PHP permette anche di specificare l'indice degli elementi dell'array, 
sicchè non è prevedibile l'indice degli elementi né il loro ordinamento. 
Ne consegue che se siamo realmente in attesa di un array, dovremmo 
esplorarne gli elementi usando un ciclo foreach() e non un ciclo for().
Vediamo un breve decalogo per la validazione dell'input. Qui faremo gli 
esempi con il metodo GET del protocollo HTTP, ma le stesse cose si 
ripetono per il POST:
Numeri interi. Eseguire un typecast a numero intero e poi controllare che 
il range sia quello previsto. Ad esempio:
if( isset($_GET['n']) ){
    $n = (int) $_GET['n'];
    if( $n < N_MIN )
        $n = N_MIN;
    else if( $n > N_MAX )
        $n = N_MAX;
} else {
    $n = N_DEF;
}
Il PHP consente di mescolare variabili di tipi diversi dentro alle 
espressioni, e converte automaticamente il tipo di una variabile nel tipo 
atteso. La conversione avviene ogni volta che la variabile viene usata, 
con evidente spreco di tempo. Eseguire il typecast a intero non solo 
semplifica il controllo, ma rende anche più veloce il programma.
Numeri a virgola mobile. E' raro che un'applicazione WEB richieda l'uso di 
numeri in precisione double. Anche qui vale il suggerimento di convertire 
il valore con un typecast (double).
Stringhe. Applicare il typecast (string), verificare la lunghezza massima, 
eliminare i codici ASCII di controllo e verificare l'encoding. Supponiamo 
ad esempio che il FORM di una pagina HTML codificata UTF-8 abbia un campo 
di testo a linea singola con un attributo maxlength=50 che fissa la 
lunghezza massima come numero di caratteri UTF-8. Ecco il codice per 
l'acquisizione della stringa; supponiamo che il valore default nel caso il 
parametro manchi sia la stringa vuota:
$s = (string) $_GET['s'];
# Rimuovi codici ASCII 0-32,127:
$s = preg_replace("/[\\000-\\037\\177]/", "", $s);
# Forza codifica UTF-8:
$s = mb_convert_encoding($s, 'UTF-8', 'UTF-8');
# Impone lunghezza massima per VARCHAR(50):
if( strlen($s) > 50 )
	$s = mb_strcut($s, 0, 50, 'UTF-8');
In questo esempio il database prevede un campo stringa VARCHAR(50) in 
codifica UTF-8. Notare che il DB deve essere a conoscenza che questa 
stringa è effettivamente UTF-8, infatti l'UTF-8 può usare fino a 6 byte 
per ogni carattere, per cui la lunghezza della stringa potrebbe arrivare 
anche a 6*50 byte.
Date e importi monetari. Ad esempio "12/03/2006" oppure "1'234,50 Eur" 
sono degli input che potremmo dover interpretare in qualche modo. Siccome 
il PHP non ha dei tipi adatti per rappresentare questi dati, dovremo 
tenerli come stringhe. Eseguire il solito typecast a (string), rimuovere i 
caratteri ASCII di controllo e validare con una espressione regolare con 
ereg() o preg_match(). NOTA: la documentazione ufficiale avverte di non 
usare ereg() perché non è "binary safe", cioè perché considera la stringa 
terminata quando compare il byte zero "\000"; nel nostro caso il problema 
non esiste, dato che abbiamo già rimosso i caratteri di controllo. Per 
quanto riguarda gli importi monetari, vedi anche Calcoli monetari con 
numeri frazionari in PHP [v. link nella pagina HTML].
Convertire sempre l'input dell'utente nel tipo di dato adatto. I numeri 
devono essere numeri, e le stringhe devono essere stringhe.
Campi hidden. Sono falsificabili dal client, mancare del tutto o essere 
arbitrariamente lunghi. Non si può fare alcun affidamento sui valori 
recuperati da un campo hidden di un FORM. Soluzioni: 1) verificare che il 
valore ritornato sia lecito; 2) corredare il valore a un codice di 
controllo MAC (message authentication code); 3) rinunciare all'uso dei 
campi hidden e salvare le informazioni sul server nella sessione 
dell'utente.
Diffidare degli operatori di uguaglianza debole quando si confrontano 
stringhe. Gli operatori di confronto == <= >= e != sono deboli nel senso 
che il PHP esegue delle conversioni automatiche a numero quando almeno uno 
degli operatori inizia con una cifra. Usare invece gli operatori di 
uguaglianza stretta === e !== e la funzione strcmp().
L'istruzione switch() fa il confronto con l'operatore di uguaglianza 
debole. Pertanto meglio evitare di coinvolgere l'input dell'utente in uno 
switch(); usare piuttosto una catena di if()... else if()... else... con 
=== per i confronti:
$action = (string) $_GET['action'];
if( $action === '1' || $action === '2' )
    doAction( (int) $action );
else if( $action === 'none' )
    doAction(0);
else
    trigger_error("invalid action parameter `$action'", E_USER_WARNING);
Uso dei database
----------------
Il famoso problema dell'SQL-injection è dovuto ai campi del FORM non 
validati oppure non sottoposti al filtro di escaping dei caratteri 
speciali. In questo caso l'attaccante può inviare al nostro database dei 
comandi arbitrari, con le conseguenze immaginabili. Questo paragrafo l'ho 
copiato direttamente dal sito PHP:
SQL escaping. Quote each non numeric user supplied value that is passed to 
the database with the database-specific string escape function (e.g. 
mysql_escape_string(), pg_escape_string(), sql_escape_string(), etc.). If 
a database-specific string escape mechanism is not available, the 
addslashes() and str_replace() functions may be useful (depending on 
database type).
Varie
-----
Evitare i comandi di shell. In generale esistono alternative pulite e 
sicure all'uso dello shell. Se non si può proprio farne a meno, ricordare 
che spesso le funzioni come system() passthru() popen() richiedono dei 
parametri per cui si deve usare sempre escapeshellcmd(). Spesso certi 
comandi interpretano in modo speciale certi parametri; ad esempio in Unix 
il carattere "-" precede le opzioni e quindi i parametri validi non 
possono iniziare con questo carattere, altrimenti verrebbero interpretati 
come opzioni e non come parametri. Molti comandi di GNU/Linux hanno una 
opzione speciale "--": tutto quello che segue questa opzione viene sempre 
interpretato come parametro. Esempio:
system("mv -- " . escapeshellcmd($a) . " " . escapeshellcmd($b));
Questo accorgimento da solo non salva dai disastri se $a e $b non sono 
correttamente sanificati.
Non usare require* e include* con parametri forniti dal browser. Il 
prototipo di tutti i disastri è
include $_REQUEST['file'];
Non usare la funzione eval(). Punto.
Non silenziare gli errori. Abusare dell'operatore "@" per aggirare le 
segnalazioni di errore si ritorce contro il programmatore stesso, che si 
ritrova poi ad eseguire il debugging "al buio" e non si accorge degli input 
malevoli che possono creare problemi al programma. Si possono silenziare 
gli errori solo se il programma li gestisce esplicitamente. Esempio:
# Leggi i dati aggiornati -- puo' fallire:
$f = @fopen("dati-nuovi.txt", "r");
if( $f === FALSE ){
    trigger_error("fopen(dati-nuovi.txt, r): $php_errormsg",
        E_USER_WARNING);
    # Ripiego leggendo i dati vecchi:
    $f = fopen("dati-vecchi.txt", "r");
    if( $f === FALSE )
        die("dati non disponibili, ne' vecchi ne' nuovi");
}
Notare che il secondo fopen() non è silenziato e quindi in caso di errore 
produce di per sè un messaggio completo di nome file e motivo dell'errore; 
quindi il die() finale non ha bisogno di fornire altri dettagli.
Applicare gli operatori di incremento/decremento solo a variabili di tipo 
intero. Incrementare una stringa si può ma in generale non produce 
l'effetto voluto: viene infatti applicata un'arcana funzionalità ereditata 
dal Perl tale per cui si generano stringhe sempre più lunghe. Provare 
questo:
$i = "a";
for($j=0; $j < 1000; $j++)
    echo $i++, "<br>\n";
Riferimenti
[omissi]
Argomenti correlati
[omessi]
EOT

 Suggerimenti e critiche sono utili e necessari.
ho dato un'occhiata veloce, posso dirti che non condivo lo stile di
scrittura del codice che usi: sarebbe meglio, in una guida del genere,
usare del codice piu' pulito possibile (ad esempio non omettere le
graffe)

 (ad esempio non omettere le graffe)
esiste un codice più *pulito* di quello senza graffe? 8-|
io addirittura odio quei linguaggi che necessariamente vogliono le
parentesi anche se il blocco di istruzioni è composto di un'unica
istruzione. :-)
Ciao,
Tristan

 regolarità durante tutto il tempo di funzionamento dell'applicativo WEB.
   non puoi parlare di sicurezza se non fai neanche un accenno alla gestiore degli errori
(email, file etc. etc.)

istruzione. :-)
Personalmente metto sempre le graffe, quando hai a che fare con pagine
di codice molto lunghe le graffe ti aiutano molto a leggere il codice.
Francesco Mazzi
Webmaster di AltroPC.it - 
http://www.altropc.it
 
Staff di E-Xoopport - 
http://www.e-xoopport.it

 di codice molto lunghe le graffe ti aiutano molto a leggere il codice.
mai scritto o letto un sorgente Python? :)
un codice ben indentato non ha bisogno di due inutili caratteri in più
per essere più leggibile, secondo me.
io in php/c/c++ le uso (a volte anche quando non sarebbero necessarie)
solo in caso di troppi cicli nidificati.
if (1)
	while (1)
		print 'Ciao<br />';
Tristan :)

 esiste un codice più *pulito* di quello senza graffe? 8-|
si', quello con le graffe. se il linguaggio prevede le graffe non
usarle in alcune istruzioni porta ad un codice sporco, proprio perche'
mischi due notazioni diverse: alcune istruzioni con e alcune senza.
c'e' poi da considerare oltre la leggibilita' anche la possibilita' che
hanno alcuni editor di rilevare automaticamente blocchi di espressione
basandosi sull'apertura e la chiusura delle graffe.
cmq per php esistono regole di scrittura di codice standard:
http://pear.php.net/manual/en/standards.php
basta seguire queste.

 graffe)
La questione stilistica e' un po' fuori dell'argomento security, ma
ne ho parlato nell'altro articolo dedicato alla safety (ed e' un po'
fuori argomento anche li') dove ho proposto anche altre modifiche alla
sintassi con lo scopo di migliorare la leggibilita'. Io preferirei una
sintassi che non richiede parentesi o, ancora meglio, una sintassi che
prevede una sola forma per le istruzioni strutturate, cioe' o cosi'
if EXPR then
    bla bla bla
end
oppure cosi'
if EXPR {
    bla bla bla
}
L'imposizione del Phyton sulla indentazione delle istruzioni mi da'
un po' fastidio e la scarterei.


 degli errori (email, file etc. etc.)
Buon punto. Solo per mail() credo che ci vorrebbe un articolo intero a
parte, se non addirittura un libro... o almeno indicare un package come
PHPMailer come interfaccia a questa funzione di basso livello. Anche
per la gestione di file e socket (bloccanti, non bloccanti, protocolli,
...) magari un'opera in cinque volumi. Ridurre il tutto a una ricetta
di poche regole restando nel tema della security, e' una bella impresa.


 
http://pear.php.net/manual/en/standards.php
"Standard" e' una parola grossa, diciamo che si tratta della "convenzione"
adottata dal progetto PEAR, anche se condivisibile in molti aspetti.
Con una eccezione: espandere i TAB in spazi e' un errore, allunga il
codice e rende difficile cambiare la larghezza dell'indentazione a
seconda delle preferenze del programmatore (chi vuole 8, chi vuole 4,
...). Tutti i text editor seri permettono di gestire l'impostazione
della larghezza del TAB.  Si fa un gran parlare di separare la logica
dall'implementazione, e poi il cadiamo sul banale TAB di un file di
testo: il numero di TAB e' la logica, il numero di spazi con il quale
viene rappresentato in video o in stampa e' la rappresentazione.


Umberto Salsi ha scritto:

   non ho detto di scrivere un opera in cinque volumi ma almeno
invitare chi legge a dare un'occhiata alla gestione degli errori
creando un proprio handler
   il tuo "non rimane che abilitare il display_errors" fa intendere che non
esistono alternative, e' un po' troppo "assoluto"

 per essere più leggibile, secondo me.
Secondo me si`.
Io uso PHP per tutto quello che riguarda il web, e Python per tutto
quello che non lo riguarda, e se potessi usare le graffe anche in
Python, lo farei.
In PHP posso fare qualcosa tipo
if (questo-e-quello) {
  esegui varie cose
} // if questo-e-quello
In python devo fare roba tipo
if questo-e-quello:
  esegui varie cose
# if questo-e-quello
Che mi costringe a lasciare righe vuote per non confondere i commenti
successivi. Oltre a sembrare un pezzo di codice commentato perche`
vecchio.
E` la cosa che mi piace meno di python, seguita dalla mancanza del $ sui
nomi delle variabili, che quindi possono confondersi con nomi di
funzioni e non vengono colorati bene dagli IDE. Esattamente le stesse
due cose che i programmatori python, di solito, criticano ai
programmatori PHP, ma al contrario :)
Di PHP non mi piace la mancanza di namespace negli include, ma qui
divaghiamo. :)
Bye.
-- 
Alessandro Pellizzari

 # if questo-e-quello
Suvvia, hai la stessa struttura e risparmi diversi caratteri. Io
preferisco la seconda:
if cond
	block
# endif cond
Non mi sembra questo il caso più utile per le parentesi graffe: quelle
servono in caso di costrutti nidificati in cui ad esempio un 'else'
potrebbe riferirsi (almeno all'occhio umano) ad un 'if' piuttosto che ad
un altro: in python il problema è risolto con l'indentazione, in
c/c++/php bisogna stare attenti a non perdere di vista l'ottica del
compilatore, ed è in questo senso che le parentesi graffe sono utili e
anzi spesso necessarie.
Ciao,
Tristan

 basta seguire queste.
In passato hanno già provato ad abituarmi a tab di 8 caratteri, a
scrivere cose come:
function foo () 
{
	return true;
}
cioè con la parentesi graffa di apertura nella riga sotto quella con la
definizione, e altre cose del genere: ora rifuggo da qualsiasi documento
che voglia imporsi come standard sullo stile di programmazione altrui
(quello lì, come dice Umberto, è solo lo standard di Pear, e la nota sul
tab è precisa ed incontestabile secondo me: inoltre, sulle parentesi ne
raccomanda solo l'uso, e ci mancherebbe che un documento del genere non
le raccomandasse).
Ciao,
Tristan

 è un obbrobrio dal punto di vista estetico.
pienamente d'accordo ma preferisco scrivere:
if ( raise_error() ) {
      die('Errore');
} else {
      echo 'ok';
}
che:
if ( raise_error() )
      die('Errore');
else
      echo 'ok';
trovo le graffe indispensabili ma poi " de gustibus ..."