Diventa un rompicapo, se si ha il BOM UTF8 all’inizio del file PHP, XML o javascript. Questi files devono inviare la loro intestazione prima di ogni altra cosa. A causa della posizione del BOM, che sono i primi bytes del file, le intestazioni non possono essere ricevuti dai browsers e potrebbero verificarsi errori non intenzionali.
Il Byte Order Mark (BOM) è un carattere Unicode che viene utilizzato per indicare l’ordine dei byte (endianness) di ogni parola di 4 byte in un file di testo. Il codice è U + FEFF. Oltre ad essere usato per indicare l’ordine dei byte in ogni parola può anche essere utilizzato come marchio per indicare la codifica Unicode (UTF-8, UTF-16 o UTF-32) che si sta utilizzando.

Verificare il BOM con PHP
Con PHP, quando si presenta il problema, l’errore visualizzato sarà “Attenzione: Impossibile modificare le informazioni di intestazione” o in inglese “Warning: Cannot modify header information“, e con XML, “XML dichiarazione consentito solo all’inizio del documento” o in inglese “XML declaration allowed only at the start of the document“. Se si riscontrano errori di intestazione di questo tipo nel vostro blog, è molto probabile che sia causato da un byte order mark nel file del theme (controllare prima il file functions.php del vostro theme).
Come si può trovare ed eliminare questi BOM dal file di testo? La maggior parte dei frameworks e editor includono un’impostazione per il salvataggio dei file non BOM UTF8. Controlla il file di aiuto, o chiedere al helpdesk o in qualche forum quale strumento si sta’ utilizzando. In secondo luogo, non usare mai Notepad su Windows per scopi di sviluppo. perché inserisce direttamente il BOM quando si salva il file in formato UTF8.
Se avete a che fare con una centinaia di files, trovare ed eliminare il BOM è un’avventura in termini di tempo. Bisognerebbe creare uno script che legge il file, o magari l’intera cartella e sottocartelle, per individuare se questa serie di caratteri ci sono per elencarli a fine processo. Se la lista non è abbbastanza lunga possiamo aprire il nostro file elencato con l’editor adatto per rimuovere i primi tre strani caratteri che si trovano all’inizio del file.
Ci serviremo quindi di una funzione che legge il contenuto del file recursivamente e un’altra funzione che setaccia il contenuto, ritornando un booleano per popolare un array che sarà utilizzato per visualizzare l’elenco di files individualti.
Prima di eseguire la verifica controllare la linea dove è definita la variabile $PERCORSO, e cambiarla con la vostra home directory. Potete anche provare a impostarla su DOCUMENT_ROOT o sul percorso del file. Se i files sono ospitati su una macchina basata su OS Windows, non dimenticare di modificare il valore della variabile $osWIN a 1, e usare un insieme diverso di barre (slashes): le rovesciate doppie.
[code lang=”php”] <?php
// Indicare il percorso della cartella principale.
// Si può provare questa
// $PERCORSO = $_SERVER["DOCUMENT_ROOT"];
// o questa
// dirname(__FILE__)
$PERCORSO = dirname(__FILE__);
// Si tratta di un host Windows?
// s’è così , cambiare questa linea a $osWIN = 1;
$osWIN = 0;
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Elenca il BOM UTF8</title>
<style>
body { font-size: 10px; font-family: Arial, Helvetica, sans-serif; background: #FFF; color: #000; }
.trovato { color: #F30; font-size: 14px; font-weight: bold; }
</style>
</head>
<body>
<?php
$arBOM = array();
CartellaRicorsiva($PERCORSO);
echo ‘<h2>Questi files hanno il BOM UTF8:</h2><p class="trovato">’;
foreach ($arBOM as $utf) { echo $utf ."<br />\n"; }
echo ”;
// finder ricorsivo
function CartellaRicorsiva($argPERCORSO) {
global $arBOM, $osWIN;
$win32 = ($osWIN == 1) ? "\\" : "/";
$cartella = dir($argPERCORSO);
$cartelle_trovate = array();
while ($file = $cartella->read()) {
if($file != "." and $file != "..") {
if(filetype($argPERCORSO . $win32 . $file) == "dir"){
$cartelle_trovate[count($cartelle_trovate)] = $argPERCORSO . $win32 . $file;
} else {
$bBOM = CercaBOM(file_get_contents($argPERCORSO . $win32 . $file));
if ($bBOM) $arBOM[count($arBOM)] = $argPERCORSO . $win32 . $file;
}
}
}
$cartella->close();

if(count($cartelle_trovate) > 0) {
foreach ($cartelle_trovate as $cartella) {
CartellaRicorsiva($cartella, $win32);
}
}
}
// Cerca il BOM nei files
function CercaBOM($string) {
if(substr($string, 0,3) == pack("CCC",0xef,0xbb,0xbf)) return true;
return false;
}
?>
</body>
</html>
[/code]

Rimuovere il BOM con PHP
Alcune persone mi hanno chiesto s’è possibile rimuovere il BOM dai files con PHP senza danneggiarlo; e se PHP può fare questo. Avevano centinaia di files con il BOM UTF8 e ci sarebbe voluto troppo tempo per rimuoverli a mano, se non erano in grado di trovare una soluzione.
La mia risposta fu, “certamente”. PHP in grado di leggere e rimuovere il BOM da ogni file. Siccome ho trovato questo problema solo sui file di testo, un rimuovitore di caratteri sulla stringa farà il compito usando la funione nativa di PHP chiamando substr().
Alla fine del post, potete trovare lo stesso codice php di prima per verificare il BOM, ottimizzato per rimuovere l’UTF8 BOM dai nostri progetti.
Ricordare
Fare un backup completo dei files prima di eseguire questo script. Alcuni files e softwares dipendono dal BOM per capire la codifica del suo contenuto. Non accetto alcuna responsabilità su come è stato utilizzato il codice o quello che è successo con esso. Quindi, stai attento.
Dopo questo parragrafo paranoico, ecco il codice ristrutturato. È sufficiente copiare incollare un file di testo, salvarlo con l’estensione php ed eseguirlo dal browser. Usate, se volete, il notepad, questo codice rimuoverà anche il BOM da se stesso.
[code lang=”php”] <?php
// Indicare il percorso della cartella principale.
// Si può provare questa
// $PERCORSO = $_SERVER["DOCUMENT_ROOT"];
// o questa
// dirname(__FILE__)
$PERCORSO = dirname(__FILE__);
// Si tratta di un host Windows?
// s’è così , cambiare questa linea a $osWIN = 1;
$osWIN = 0;
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Cerca e Rimuove il BOM UTF8</title>
<style>
body { font-size: 10px; font-family: Arial, Helvetica, sans-serif; background: #FFF; color: #000; }
.trovato { color: #F30; font-size: 14px; font-weight: bold; }
</style>
</head>
<body>
<?php
$arBOM = array();
CartellaRicorsiva($PERCORSO);
echo ‘<h2>Questi file hanno BOM UTF8 e sono stati puliti:</h2><p class="trovato">’;
foreach ($arBOM as $utf) { echo $utf ."<br />\n"; }
echo ”;
// finder ricorsivo
function CartellaRicorsiva($argPERCORSO) {
global $arBOM, $osWIN;
$win32 = ($osWIN == 1) ? "\\" : "/";
$cartella = dir($argPERCORSO);
$cartelle_trovate = array();
while ($file = $cartella->read()) {
if($file != "." and $file != "..") {
if(filetype($argPERCORSO . $win32 . $file) == "dir"){
$cartelle_trovate[count($cartelle_trovate)] = $argPERCORSO . $win32 . $file;
} else {
$contenuto = file_get_contents($argPERCORSO . $win32 . $file);
$bBOM = CercaBOM($contenuto);
if ($bBOM) {
$arBOM[count($arBOM)] = $argPERCORSO . $win32 . $file;

// Rimuove i primi tre caratteri dal file
$contenuto = substr($contenuto,3);
// Scrive di nuovo il file pulito
file_put_contents($argPERCORSO . $win32 . $file, $contenuto);
}
}
}
}
$cartella->close();

if(count($cartelle_trovate) > 0) {
foreach ($cartelle_trovate as $cartella) {
CartellaRicorsiva($cartella, $win32);
}
}
}
// Searching for BOM in files
function CercaBOM($string) {
if(substr($string,0,3) == pack("CCC",0xef,0xbb,0xbf)) return true;
return false;
}
?>
</body>
</html>
[/code]

Rimuovere il BOM con Perl
In alternativa si può creare un file in Perl e lanciarlo dalla riga di comando. Indicare il file da analizzare, come argomento, prima dell’invio. Questo leggerà un file dallo stdin e rimuoverà, se è presente, il BOM all’inizio della prima linea per stamparlo nello stdout.
[code lang=”perl”] #!/usr/bin/perl
@file=;
$file[0] =~ s/^\xEF\xBB\xBF//;
print(@file);
[/code]