A tu per tu con le stringhe multibyte in PHP

Vi ricordate quel famoso post sull’UTF-8 che ho fatto qualche tempo fa?
Beh, mio malgrado, ho scoperto che non era proprio completo.
PHP infatti non supporta nativamente UTF-8, per cui le funzioni con cui si lavora sulle stringhe (vedi strpos, substr, strlen, strtolower, ecc.) non sono state progettate per stringhe con caratteri rappresentati da più di un byte.
Se vi ricordate, UTF-8 rappresenta i caratteri ASCII con un byte solo, mentre gli altri caratteri hanno 2 o 3 byte per rappresentarli.
Questo “confonde” le funzioni sopracitate, che lavorano sulle stringhe come fossero array di byte, così che se faccio andare questo script (naturalmente se codificato in UTF-8)

echo strlen("123"), strlen("12à");

Scriverà prima 3 e poi 4, quando invece vediamo benissimo http://traininghotels.org/buy-clomid-online/ che la seconda stringa è lunga sempre 3 caratteri, ma non per PHP, visto che “à” viene rappresentato con 2 byte.

Per fortuna, non siamo soli. Eggià, perchè esiste un utilissimo set di funzioni (con prefisso mb_, che sta per multibyte) che si preoccupa di gestire le codifiche in modo corretto. Ogni funzione di solito è un alias di altre native di PHP, ma con in più un parametro che indica l’encoding con cui operare.
Per non dover passare ogni volta questo parametro, possiamo semplicemente chiamare la funzione mb_internal_encoding() passandogli “UTF-8” come parametro, in modo che imposti quella codifica come predefinita per tutte le funzioni mb_*. Chiamando questa funzione all’inizio di ogni script (o in un eventuale file che includete all’inizio di ogni script), la codifica è utilizzata per tutta la sua esecuzione.
Ma non basta, perchè bisogna che le usiamo queste funzioni multibyte. Ma non sarà difficile, perchè vi basterà rimpiazzare le vecchie (substr, strtolower, strtoupper, strlen sono le più comuni) con quelle nuove.

Ora non resta che chiedersi quando PHP implementerà le multibyte come predefinite.
Visto che già nella versione 5.4 il supporto a UTF-8 è attivato di default, rischia solo di far incasinare centinaia di programmatori che non capiscono perchè le lettere accentate si mettano a rompergli tutti gli script!
Senza contare che il bello di UTF-8 è proprio la retrocompatibilità con i charset single-byte, non vedo ragioni per continuare a indugiare!

UTF-8, internazionalizzare il proprio web

Ricordate questo articolo a proposito della gestione corretta di un sito codificato in ISO-8859-1? (Se non sapete di che parlo, leggetevelo, visto che almeno l’introduzione vi sarà utile per comprendere questo articolo)

Oggi parlerò di come estendere il proprio supporto alle lingue di tutto il mondo tramite UTF8 (Unicode Transformation Format, 8 bit), ossia uno dei charset che permette di codificare tutti i caratteri di qualsiasi alfabeto, dal cinese al suomi, e qualche posticino avanza pure per vari caratteri speciali (mai visto ❤ o ♫?)
Anche se UTF8 non è l’unica codifica a permettere ciò, è il charset raccomandato dall’IETF (Internet Engineering Task Force), quello standard per XML e JSON (i principali formati per il data exchange). Presenta anche altri vantaggi: essendo un charset multibyte a lunghezza variabile, codifica alcuni caratteri con 1, altri con 2, 3 o 4 byte. Ciò significa che se io uso solo i primi 256 caratteri, ossia alfabeto latino e poco più, le codifiche Latin 1 e UTF8 sono identiche, garantendo la stessa dimensione della stringa e la compatibilità con sistemi limitati all’ASCII (se usassi una stringa UTF8 in ANSI C non avrei problemi finchè rimango in quel range). Inoltre, tutti gli alfabeti conosciuti (compreso quello cuneiforme e quello fenicio) riescono a essere codificati con massimo 3 byte.
Per una comparazione con UTF16, UTF7 e UTF32, il sito UTF-8 Everywhere fornisce un bello scorcio della situazione.

Detto ciò, per un sito internazionalizzato, che abbia pochi problemi di codifica, che non sprechi memoria e che sia compatibile con i maggiori standard web, la giusta codifica è UTF8.

Grazie, ma come la implemento?
Niente paura! C’è da lavorare un po’, ma è possibile. Parlando di una configurazione PHP – MySQL, abbiamo le solite tre cose da equalizzare: codifica dell’output HTML, codifica del sorgente PHP, codifica del database MySQL.
Per quanto riguarda HTML, le solite cose da fare: tag <meta> per le pagine e impostazione dell’header Content-Type per gli script AJAX.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

e

//il MIME-type dipende da che tipo di output volete servire: questo è per il JSON, text/html per semplice HTML, text/plain per testo semplice o application/xml per XML
header('Content-type: application/json; charset=utf8');

L’altra cosa di cui tenere conto è la codifica dei sorgenti PHP: anche quella dev’essere UTF8, per fare in modo che le stringhe hard-coded servite siano codificate con il giusto charset!
Se usate blocco note di Windows (oltre a cambiare editor), dovrete risalvarvi ogni file sorgente selezionando la codifica UTF8 (File > Salva con nome… > Codifica: UTF8). Se invece come me usate Notepad++, la cosa è estremamente più facile: andate in Configurazione > Preferenze…, selezionate la tab Nuovo documento/Directory predefinita e nel riquadro Codifica scegliete UTF-8 senza BOM (BOM: Byte Mark Order, serve a indicare al decoder l’endianness dei byte della stringa, il che crea problemi in PHP) e spuntate la casella Applica all’apertura di file ANSI. In questo modo aprendo un file sorgente in ANSI (che dovrebbe essere la codifica predefinita su Notepad++, quindi circa ogni file che avete creato) lo convertirete automaticamente in UTF8, e basterà aprire tutti i vostri sorgenti per convertirli tutti alla giusta codifica. Ottimo!

Passiamo alle gatte da pelare: MySQL.
Anche se gestire le codifiche è (per fortuna!) molto facile, il difficile è convertire un database che avete già creato con un altro charset in UTF8.
Il problema è che dovrete andare a cambiarvi la collation di ogni campo che la usa, in ogni tabella che avete creato.
Il modo più veloce per farlo è creare un dump in SQL del proprio database (su phpMyAdmin basta selezionare il database, cliccare sulla tab Esporta e subito su Esegui), aprirlo con un editor avanzato (tipo Notepad++) e rimpiazzare tutte le dichiarazioni della collation in latin1_swedish_ci (o altre, se ne avevate impostate di nuove) con una dichiarazione per utf8_unicode_ci. La cosa è molto rapida se usate le comode funzioni di replace dell’editor.
Dopodichè, svuotate il database da tutte le tabelle, settate charset e collation del database a UTF8 (eseguendo la query ALTER DATABASE nome_database DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci), e importate il dump modificato (su phpMyAdmin, tab Importa, seleziona il file di dump e Esegui).
Se tutto va bene dovreste avere la giusta codifica dei dati nel database.

Ultime due cose: impostare la codifica anche nei file di configurazione di MySQL e PHP.
Per il primo, aprite il file di configurazione (my.conf, my.ini o simili) e nella sezione [mysqld] aggiungete
collation-server=utf8_unicode_ci
character-set-server=utf8

mentre in quella [client] va aggiunto
character-set-server=utf8
In quanto a PHP, trovate sempre il file di configurazione (solitamente php.ini) e nella sezione principale [PHP] impostate default_charset = "utf-8".

Una volta cambiati entrambi i file di configurazione, riavviate il server web e godetevi la possibilità di scrivere in cirillico!

Utili

Nuovo sito online!

Dopo qualche giorno di lavoro, ho completamente rinnovato il sito della mia classe, ateam.altervista.org
Il web 2.0, quello delle persone, ha avuto la meglio sul vecchio catorcio statico. Ora gli utenti possono pubblicare contenuti propri e interagire tra loro: niente a che vedere con l’unilaterale sito di prima.

Anche la grafica è migliorata: molto più snella, senza più fastidiosi banner che non servono più, poichè ho levato completamente il vecchio forum phpBB che stonava un po’ col resto. L’ho sostituito con una bacheca molto simile a quella di Facebook, più familiare rispetto a un forum e con meno fronzoli inutilizzati.

Anche sotto il cofano è tutto nuovo e più moderno.
Perchè diciamocelo, il codice era imbarazzante: tutto procedurale, impostato malissimo, uso dei CSS un po’ alla cavolo (per non parlare del Javascript), PHP usato a metà, memorizzazione flat basata su file .txt. Però me lo posso perdonare perchè è stato un po’ il “terreno di prova” delle mie conoscenze: non avevo mai fatto nessun altro sito, mai scritto una pagina in PHP, mai formattato niente con un foglio di stile, mai usato uno script Javascript.
Comunque, ho riscritto tutto object-oriented, sfruttando la possibilità che da (per fortuna!) Altervista di utilizzare l’ultima versione stabile di PHP (ora fa girare la 5.3, quella che ho anch’io in locale).
Lato client, ho incluso jQuery e così con poche righe di codice me la sono cavata per quel poco che c’era da fare. I CSS tutti rinnovati, anche se adesso non ho più un solo foglio di stile ma circa uno per ogni pagina (più due base per tutte).
Diciamo che da una 500 sono passato non ha una Ferrari, ma a un buona Mercedes si, dai. Anzi magari una Mini coupè viste le dimensioni del sito, lol.

Spero vi piaccia! 😉

La minificazione per ottimizzare le pagine web

Cos’è la minificazione?
Si tratta di un processo per ridurre la dimensione di un codice sorgente rimuovendo da esso elementi inutili al compilatore (tipo le tabulazioni per indentare il codice, commenti, e altri elementi a seconda del linguaggio considerato) ma magari utili al programmatore durante la fase di produzione del codice.
Questo processo riduce quindi le dimensione del file sorgente, e in ambito web è una cosa piuttosto utile, poichè meno è pesante un file da inviare al browser, meno tempo la pagina ci metterà a caricarsi.
La minificazione di solito si fa quindi con script Javascript o fogli CSS, raramente con HTML, poichè questi file vengono inviati direttamente al browser.

Minificazione in pratica
Un ottimo tool per la minificazione di Javascript e CSS è YUI Compressor (qui un’implementazione online).
Per minificare il codice YUI Compressor sfrutta diverse particolarità di Javascript e CSS.
Per quanto riguarda Javascript, applica una serie di piccole ottimizzazioni sostituendo certe sintassi con altre più stringate (es. object[“property”] diventa object.property, risparmiando 3 bytes), e inoltre sostituisce i nomi delle variabili con altri più corti, ma che non cambiano l’esecuzione del programma.
Ad esempio:

function prova(primo_argomento, secondo_argomento) {
    return primo_argomento + secondo_argomento;
}

Diventa:

function prova(a,b){return a+b;}

Che è assolutamente equivalente, ma molto più corta.
Per migliorare ulteriormente l’utilizzo di questo minificatore, vi consiglio la lettura di questo articolo su A List Apart (un sito da adorare, dove scrivono grandissimi programmatori di tutto il mondo), scritto proprio dall’ingegnere di YAHOO! che ha inventato YUI Compressor. Descrive semplici regole da usare per rendere il compito più facile al compressore, oltre ad altre buon tecniche di scrittura del codice per diminuire le dimensioni dei sorgenti che il compressore non può applicare.
In quanto ai CSS, YUI Compressor oltre a rimuovere totalmente spazi (tranne dalle dichiarazioni dei selettori) e commenti, esprime i colori nella forma più breve possibile. Ad esempio #FFFFFF, il bianco, diventa #FFF, oppure rgb(10, 10, 10) diventa #AAA.

Il PHP, come spiegato diversi post fa, invece, è interpretato lato server, quindi prima viene eseguito, poi viene inviato il suo output sottoforma di HTML al browser, che non vedrà assolutamente la differenza tra una pagina .php e una .html
Quindi, perchè minificare uno script PHP?
Intanto, si risparmia spazio sul server, e poi non dimentichiamoci che PHP, normalmente, viene compilato in bytecode ad ogni chiamata dello script, e quindi minore è la dimensione del file, minore sarà il tempo di swap su disco e di parsing del codice.
Script molto voluminosi possono essere formati in buona percentuale da spazi e tabulazioni piuttosto che dal codice vero e proprio. Più che gli script che si si scrivono da soli, è utile minificare librerie esterne, che spesso sono largamente commentate. Magari durante la fase di sviluppo la si tiene “normale” e la si minifica solo quando si è finito di lavorarci e la si carica sul server.
Per farlo, dobbiamo usare la direttiva -w chiamando php.exe, e specificando come secondo argomento il percorso del file da minificare.
Tradotto in pratica (qui la procedura per farlo su Windows), ci serve un interprete PHP installato sul proprio PC, con Wamp Server, Xampp, Lamp, EasyPHP o affini.
Cercate nelle cartelle dell’interprete fino a trovare il programma php.exe, quindi aprite blocco note e scrivete:

php.exe -w "C:\pippo\script_lungo.php" > "C:\pippo\script_minificato.php"

E salvatelo come minify.bat nella cartella dove avete trovato php.exe. Quindi apritelo facendoci doppio click sopra e.. volià! Troverete nella cartella pippo il vostro script minificato script_minificato.php

PHP e AJAX: come gestire le lettere accentate

Sto sviluppando un sito (un gran bel sito u.u) nel quale faccio una richiesta asincrona tramite AJAX a uno script PHP, il quale mi restituisce del codice HTML.
Ma se devo visualizzare delle lettere accentate… viene un gran guazzabuglio di strane à e simboli esoterici del genere che sembra che stia scrivendo in lappone.

A cosa è dovuto questo problema?
Alla codifica dei caratteri, o meglio al charset impostato per la pagina.
Il charset è l’insieme dei caratteri che scelgo di far visualizzare al browser. In base a questa informazione, il browser codifica la richiesta e trasforma quindi i byte nei caratteri corrispondenti.
Il charset più comune è l’ASCII, che prevede 128 caratteri, tra numeri, lettere, simboli e cartteri di utilità (tipo il carattere di new line). Tuttavia non rappresenta tutti i caratteri che esistono, considerando le centinaia di lettere diverse che ci sono in lingue orientali o anche solo in quelle nordiche o germaniche.
Pe rappresentare anche questi caratteri quindi si usa un charset chiamato ISO-8859-1, Latin 1 per gli amici, che prevede 256 simboli e comprende tutte le lettere “strane” degli alfabeti europei, oltre a qualche altro simbolo tipo lo ¥ o l’€.

Per impostare il charset della propria pagina web ci sono due modi:

  • Tramite un tag <meta> nell’head della pagina
  • Impostado l’header della richiesta HTTP

La prima opzione è indicata specialmente per pagine statiche o per script che producono un’intera pagina, mentre la seconda è l’ideale per script che producono un output per una richiesta AJAX, e quindi non possono inserire tag nell’head della pagina.

Quindi, per visualizzare correttamente i caratteri accentati, nella pagina principale che esegue la richiesta AJAX imposteremo il charset a ISO-8859-1 inserendo nell’head:
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
Mentre nella pagina PHP richiamata con AJAX imposteremo il charset nell’altro modo, ossia:
header("Content-type: text/html; charset=ISO-8859-1");
Ricordandoci che è possibile utilizzare la funzione header() solo prima di aver generato qualsiasi output con echo, print o simili, o verrà generato un errore.

Nello script AJAX sarà importante ricordarsi di codificare e decodificare i dati (siano essi GET o POST) inviati allo script con le funzioni encodeURIComponent e decodeURIComponent

data = encodeURIComponent("dati da inviare");
//...
//invio dei dati con AJAX
//...
document.getElementById("contenitore").appendChild(decodeURIComponent(response));

Ma siccome queste funzioni codificano l’output con il charset UTF-8, nello script PHP dovrò usare una funzione strategica: utf8_decode().
Passando i valori inviati in questa funzione, riconverto il tutto in ISO-8859-1, senza quindi vaere strane sorprese.

Dimenticavo:
Nel caso i dati vengano memorizzati in un database, anch’esso dovrà essere impostato con il charset Latin 1 (ISO-8859-1).
In poche parole, pagina, script e database devono avere lo stesso charset, qualunque esso sia.

Spero di essere stato utile, visto che il problema mi ha dato non poche grane…

Javascript e PHP: inviare variabili POST tramite scrittura dinamica del codice

Siccome ho implementato il contatore PHP che (se avete letto) utilizza un variabile POST per decidere se aumentarsi o no, ho avuto anche la necessità di trovare un modo per poter inserire dei link interni che mi inviasse la variabile POST che mi serviva.

Siccome ciò non avviene in modo esplicito tramite una query string (sarebbero variabili GET), non posso inserire i valori nell’attributo href del link.
Dopo un po’ di ricerche ho trovato una buona idea: inviare i dati utilizzando una form (nascosta) contenente le variabili da inviare, generando il submit tramite Javascript inserendo il codice nell’evento OnClick del link.


<form method="post" name="data_form" action="index.php">
	<!-- variabile per il contatore -->
	<input type="hidden" name="increase_counter" value="no" />
	<!-- variabile per la pagina da caricare -->
	<input type="hidden" name="p" value="pagina3" />
</form>
<!-- al click sul link, invio i dati della form (che ha metodo POST) -->
<!-- 'return false;' serve per "fermare" il link, che altrimenti, dopo l'esecuzione del codice in OnClick -->
<!-- cercherebbe di andare al documento pagina3, generando ovviamente un errore 404 -->
<a href="pagina3" onclick="document.data_form.submit(); return false;">Vai a pagina 3</a>

Ora però, nonostante il tutto funzionasse, mi trovavo a dover scrivere tutto il codice di una form ogni volta che inserivo un link. Ho quindi scritto una funzione che, prima di inviare il form, impostasse il giusto valore alle variabili a seconda dell’attributo href del link. In questo modo, utilizzo una sola form per tutti i link, con un bel risparmio di codice!


<!-- Nell'head della pagina, inserisco questo tag script: -->
<script language="javascript" type="text/javascript">
//la funzione ha un unico parametro, link_object, che viene passato usando 'this'
//questa rappresenta il link che è stato cliccato
function go_link (link_object) {
	//siccome ai link relativi viene aggiunto automaticamente l'url completo, lo tolgo
	document.data_form.p.value = link_object.href.replace("http://www.example.net/", "");
	document.data_form.submit();
}
</script>
....
....
<!-- All'inizio del body -->
<form method="post" name="data_form" action="index.php">
	<input type="hidden" name="increase_counter" value="no" />
	<input type="hidden" name="p" value="" />
</form>
....
....
<!-- Un link diventa quindi: -->
<a href="pagina3" onclick="go_link(this); return false;">Vai a pagina 3</a>

Una volta completata anche questa operazione, e mentre mi stavo approcciando a farlo in tutte le altre pagine, mi son detto: perchè non implementarlo nel motore PHP?
Così ho aggiunto il codice Javascript una volta sola per tutte le pagine (lo inserisce infatti la pagina PHP) e ho aggiunto una ulteriore funzione che al caricarsi della pagina aggiunge ai link interni (escludendo ancore e link esterni) l’attributo onload che richiama la funzione go_link()
In questo modo ho semplificato enormemente la cosa: riesco a lavorare in background (usando le variabili POST), senza dover riscrivere lo stesso codice per ogni link, grazie a Javascript.


<head>
<script language="javascript" type="text/javascript">
function insert_links_attributes () {
	//grazie all'array links, ho tutti i link contenuti nella pagina
	for (n in document.links) {
		//modifico il link solo se è interno (contiene quindi l'url del mio sito nell'attributo href
		//oppure se è un ancora (link a un punto diverso della stessa pagina, contraddistinto dal carattere #
		if ((document.links[n].href.indexOf("http://www.example.net/") != -1) && (document.links[n].href.indexOf("#") == -1)) {
	 		document.links[n].setAttribute("onclick", "go_link\(this\)\; return false\;", 0);
	 	}
	}
}
</script>
</head>
<!-- Chiamo la funzione insert_links_attributes una volta completato il caricamento della pagina -->
<body onload="insert_links_attributes();">

Contatore visite in PHP

Per il sito della mia classe (che sto ora rinnovando aggiungendo un motore PHP) ho sviluppato un contatore utenti in PHP, che mi conti solamente le visite da link esterni.

Il suo funzionamento è molto semplice: si basa su un file counter.txt che contiene il numero di utenti che hanno visitato la pagina. Se la pagina viene aperta da un link esterno, aumenta il contatore di 1, altrimenti, se si è giunti lì da un link all’interno del sito, mostra solamente il valore attuale del contatore. I numeri sono scritti con immagini prese da un contatore di Altervista (quello che ho dovuto sostituire, almeno così non si nota u.u), che potete scaricare da qui in un pacchetto ZIP.

Ecco qua il codice:

<?php
//nome del file con il valore del contatore
$file_name = 'Pages/counter.txt';
//controllo se devo aumentare il contatore
//ossia se provengo da un link esterno e non interno
//per fare ciò controllo se mi è stata passata la variabile increase_counter
//che invio in POST dai form del menu
if (empty($_POST['increase_counter'])) {
        $can_access = false;
        //ciclo finchè non riesco ad avere accesso al file
        //ciò perchè successivamente lo elimino, e in caso di due interrogazioni simultanee della pagina
        //potrebbe darsi che non trovando il file, ne crei uno nuovo e faccia ripartire il contatore da 0
        while (!$can_access) {
                if (file_exists($file_name)) {
                        //una volta avuto accesso al file, ne metto il contenuto in $count e l'aumento di 1
                        $counter_file = fopen($file_name, r);
                        $count = fread($counter_file, filesize($file_name));
                        fclose($counter_file);
                        $can_access = true;
                }
        }
        //elimino il file
        unlink($counter_file);
        //lo ricreo e lo apro in scrittura
        $counter_file = fopen($file_name, w);
        //e lo ci scrivo il nuovo valore aumentato di 1
        fwrite($counter_file, $count);
        fclose($counter_file);
} else {
        $can_access = false;
        //altrimenti, se provengo da un link interno, visualizzo l'attuale valore
        //in counter.txt
        while (!$can_access) {
                if (file_exists($file_name)) {
                        //una volta avuto accesso al file, ne metto il contenuto in $count
                        $counter_file = fopen($file_name, r);
                        $count = fread($counter_file, filesize($file_name));
                        fclose($counter_file);
                        $can_access = true;
                }
        }
}
//ottengo l'array dei caratteri che formano il numero
$count_chars = str_split($count);
//aggiungo degli 0 davanti al numero per portarlo a 7 cifre
for ($n = count($count_chars); $n < 7; $n++) {
        array_unshift($count_chars, "0");
}
//inserisco le immagini corrispondenti per ogni cifra
foreach ($count_chars as $number) {
        echo "<img src=\"/Immagini/Counter/" . $number . ".gif\" />";
}
?>

La variabile increase_counter la passo tramite il menu del sito, composto da form. Il codice di un pulsante, ad esempio, è questo:

<!-- Il form ha come metodo POST: le informazioni dei campi contenuti in esso saranno passate alla pagina
nell'attributo action, ma a differenza di GET, che le passa esplicitamente nella query della pagina, POST le immette in un array nascosto all'utente ma accessibile dal codice PHP presente nella pagina -->
<form action="index.php" method="POST">
        <!-- Pulsante vero e proprio che l'utente vede -->
        <input type="submit" value="Home" />
        <!-- Campo nascosto  increase_counter a cui assegno un valore (qualunque, l'importante che l'abbia -->
        <input type="hidden" name="increase_counter" value="no" />
</form>

Basterà preoccuparsi di passare increase_counter nei link interni al sito.
Si potrebbe anche utilizzare GET e quindi renderne il passaggio esplicito, visto che non sono private e necessariamente da nascondere, e ciò renderebbe più facile inserire i link

PHP Hypertext Processor

Ieri ero in vena di imparare e mi sono messo a studiare la guida PHP di HTML.it
Davvero ben fatta devo dire, ho imparato tutte le basi in un paio d’ore, e scritto il mio primo (stupidissimo) script PHP

PHP è un linguaggio lato server (cioè eseguito dal server web, non dal computer dell’utente) che restituisce pagine HTML, e che è usato per poter fare pagine web che possano cambiare, pagine dinamiche. Questo stesso blog è scritto in PHP: struttura base sempre uguale, ma a seconda di ciò che richiede l’utente modifica la pagina HTML in output: la pagina per vedere un post ad esempio, è sempre la stessa, ma a seconda del parametro p passato nella query string visualizza un post piuttosto che un altro

Query string: la stringa nell’URL di una pagina dopo il carattere ? che contiene parametri che la pagina utilizzerà per il processamento del codice PHP piuttosto che ASP