2013-11-20 17 views
5

La funzione PHP strtolower() deve convertire le stringhe in lettere minuscole. Ma, si dice in the PHP Manual (enfasi aggiunta):Quando è sicuro utilizzare la funzione PHP strtolower()?

Returns stringa con tutti i caratteri alfabetici convertiti in minuscolo.

Nota che 'alfabetico' è determinato dalle impostazioni internazionali correnti. Questo significa che, ad esempio, nella locale predefinita "C", caratteri come umlaut-A (Ä) non verranno convertiti.

Il manuale è in silenzio su codifiche qui, ma è noto che strtolower() corromperà stringhe UTF-8, dove si suppone di utilizzare mb_strtolower() invece.

Sto cercando una soluzione nei casi in cui l'estensione mbstringnon è disponibile, e voleva sapere quando è sicuro da usare strtolower().

Grazie ai puntatori che mi hanno dato le persone che commentano questa domanda, sembra che la parte rilevante della sorgente PHP sia la chiamata alla funzione tolower() nella libreria ctype.h. Il library documentation dice (corsivo):

Se l'argomento di tolower() rappresenta una lettera maiuscola, ed esiste un corrispondente lettera minuscola (come definito dalle informazioni di tipo carattere nel programma categoria di localizzazione LC_CTYPE, il risultato deve essere la corrispondente lettera minuscola .

Secondo le mie prove, in PHP con set_locale(LC_CTYPE, 'C'); personaggi come Ä (codificato in ISO-8859-1) non vengono toccati. Ma in alcune altre localizzazioni, la funzione restituisce il minuscolo ä (di nuovo, in ISO-8859-1). In ogni caso, la modifica delle impostazioni internazionali a una che utilizza un set di caratteri UTF-8 non fa fa funzionare PHP strtolower() sul carattere UTF-8 Ä.

Considerando la crescente quantità di problemi relativi a I18N e ambienti multilingue, questa informazione può essere di fondamentale importanza. Molte applicazioni si basano su strtolower() per un semplice controllo senza distinzione tra maiuscole e minuscole. Considerare:

$_POST['username'] = 'Michèlle'; 
if (strtolower($_POST['username']) == $database['username']) ... 

Ora, a seconda della codifica, locali e forse alcune altre variabili, il codice di cui sopra funzionerà in alcuni ambienti, ma non in altri.

La domanda è: Dato che la funzione PHP strtolower() utilizza la funzione ctype.h della biblioteca tolower, che dipende dal "programma di categoria di localizzazione", quando è sicuro di contare su questa funzione? Il comportamento può essere calcolato nei seguenti casi?

  1. La stringa ASCII
  2. La stringa è codificato in ISO-8859-1
  3. La stringa è codificata in qualche altra codifica con la corrispondente serie locale.

(Edit: Domanda riformulato completamente il 26 nov 2013.)

+0

PHP è open source, quindi trovalo nel codice sorgente. –

+0

[Ecco la parte rilevante della fonte] (http://lxr.php.net/xref/PHP_TRUNK/ext/standard/string.c#1397). –

+1

@AmalMurali In realtà, il lavoro viene svolto qui: http://lxr.php.net/xref/PHP_TRUNK/ext/standard/string.c#1376 –

risposta

0

La funzione strtolower() PHP fa uso la funzione C tolower() all'interno della sua implementazione che opera su ogni singolo byte (ottetto) della stringa passata para metro.

Questo è il motivo per cui set_locale(LC_CTYPE, 'C'); non corrompe le stringhe codificate UTF-8 perché non cambierà byte> 127. Cioè cambia solo il caso dei caratteri US-ASCII A-Z.

Il "C" locale è impostato di default e non è necessario impostarla in modo esplicito con setlocale(), solo se le altre parti dell'applicazione sono impostarlo su un valore diverso.

Questo spiega anche perché modificando LC_CTYPE in un locale UTF8 come "de_DE.UTF-8" non sarebbe convertito "Ä" a "ä": La lettera è codificato con due bytes 0xC3 0x84 di cui entrambi vengono passate come un singolo carattere (ottetto) alla funzione tolower() C, pertanto sono invariate poiché su un singolo byte un'elaborazione UTF-8 inferiore può trattare solo con i caratteri < 128 che di nuovo è effettivamente solo AZ. Che è effettivamente come il locale C.

Quindi l'impostazione di LC_CTYPE su "C" impedisce la rottura delle stringhe UTF-8 in uso con strtolower().

0

utilizza la funzione c tolower (ref: http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.2.html) dal ctype.h library.

È possibile visualizzare le relative sezioni della sorgente qui:

+0

Dal link fornito: "Se il carattere corrisponde alla condizione appropriata, viene convertito. [...] Se il carattere è un carattere maiuscolo (dalla A alla Z), viene convertito in lettere minuscole (dalla a alla z) "Apparentemente non è tutta la verità, dal momento che strtolower() WILL sul mio sistema converte (ISO-8859-1 codificato)' Ä' in 'ä'. –

+0

@HeikkiU hmm, sto guardando il sorgente e 'php_strtolower' è davvero semplice. Se si dispone di un ambiente di test C/C++, provare a riprodurre questi risultati utilizzando direttamente 'tolower'. L'unica altra cosa che riesco a vedere è che 'strtolower' chiama' zend_parse_parameters', ma non vedo nulla che indichi qualche modifica del valore per far sì che 'tolower' si comporti diversamente dal normale. –

+0

Non ho questa opzione per il test. Ma deve esserci qualcosa di più, altrimenti il ​​manuale direbbe semplicemente "Converte A-Z in a-z", vero? E, prima di menzionarlo, non ho il sovraccarico di mbstring abilitato. –