Zjištění kódování webové stránky
Školení, která pořádám
Webová stránka může mít nastaveno kódování buď v HTTP hlavičce nebo v <meta>
značce. Pokud toto kódování chceme zjistit PHP skriptem, lze postupovat takto:
<?php
/** Zjištění kódování HTML stránky z HTTP hlaviček nebo <meta> značky
* @param string cesta k lokálnímu nebo vzdálenému souboru
* @return string zjištěné kódování, false v případě nenalezení
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function get_charset($filename) {
$fp = fopen($filename, "r");
// zjištění z HTTP hlaviček
$meta_data = stream_get_meta_data($fp);
if (strtoupper($meta_data["wrapper_type"]) == "HTTP") {
foreach ($meta_data["wrapper_data"] as $header) {
if (stristr($header, "Content-Type:")) {
if (preg_match('~; *charset=([^;]+)~i', $header, $match)) {
return $match[1];
}
break;
}
}
}
// zjištění z <meta> značky
while (($s = fread($fp, 1024))) {
if (preg_match('~<meta(\\s[^>]*http-equiv=[\'"]?Content-Type[^>]*)~i', $s, $matches)) {
if (preg_match('~\\scontent=[\'"][^\'"]*; *charset=([^;\'"]+)~i', $matches[1], $match)) {
return $match[1];
}
break;
} elseif (stristr($s, "</head>")) { // stripos není použit proto, že je až v PHP 5
break;
}
}
return false;
}
echo get_charset("http://www.example.org/");
?>
Pokud je kódování nastaveno v HTTP hlavičce, zjistíme ho jednoduše díky funkci stream_get_meta_data. V opačném případě se ze souboru načítá kód do té doby, dokud se na značku s kódováním nenarazí nebo dokud neskončí HTML hlavičky. Pokud bychom se souborem potřebovali dále pracovat, bylo by samozřejmě lepší ho rovnou načíst (nejspíš funkcí stream_get_contents) a značku hledat až v načteném souboru. Přestože byla funkce primárně napsaná pro soubory dostupné protokolem HTTP, funguje i s místními soubory, kdy kódování zjišťuje pouze z <meta>
značky. Pro načtení meta značky by se dala použít funkce get_meta_tags.
Diskuse
Gioel:
a kde sa to da najlepsie vyuzit?
Mimochodem, jake kodovani posilas v pozadavku na server (accept-charset)? Ono pak muzes dojit k tomu, ze tak funkce je v praxi docela nepouzitelna...
2Gioel: pokud z tech stranek sosas kusy textu, tak potrebujes zjistit, zda je mas prekodovavat do sveho a pripadne tedy z jakeho. Tj. vyuziti to mit muze. Jen to muze mit problemy u stranek, ktere se posilaji v tom kodovani, ktere si vyzadal klient (typicky mod_czech)
Gioel:
ale ved keby som aj zistil potrebne kodovanie a upravim na pozadovane tak tam budu take chyby, nie?
Gioel:
Ako ze sa zobrazi zle ako ze niekto znaky sa zle zobrazia, to sa stane ked sa zmeni kodovanie, nie?
Mordae:
Ne, to se stane pokud pošleš text v jiném kódování, než specifikuješ...
Právě kvůli těmto problémům je tu tahle fce - když chceš něco odjinud a přek=odovat to do kódování tvého webu. Zjednodušeně řečeno.
Markétka:
Ahoj. Chtěla bych se zeptat, jak docílim toho, aby se mé stránky zobrazovali v prohlížečích stejně. Např. na mozile to mám přesně podle mých představ, ale na internet explorer je to rozhozené. Obrázek je mimo a dokonce místo např. ž se zobrazí kostička. Taky bych se chtěla zeptat, jestli mi můžete doporučit nějakej program na tvorbu webových stránek. Mockrát děkuji za odpověď.
Šroubek:
Dobrý skriptík - hodně mi pomohl...
Ale přece bych měl jednu připomnku: Podmínku 'if ($meta_data["wrapper_type"] == "HTTP")' bych roršířil o "http" (malými písmeny) - jinak v případě že testovaná stránka má hodnotu wrapper_type malým písmem tak tato podmínka neprojde a funkce vrátí hodnotu false.
Jakub Vrána :
Díky za upozornění, změnilo se to v PHP 5.1. Opravil jsem to.
Radim Daniel Pánek:
Používám:
@$meta_data = stream_get_meta_data( $fp );
if ( strtoupper ( $meta_data["wrapper_type"] ) == "HTTP" ) {
foreach ( $meta_data["wrapper_data"] as $header ) {
if ( stristr( $header, "Content-Type:" ) ) {
if ( preg_match('~; *charset=([^;]+)~i', $header, $match) ) {
return $match[1];
}
break;
}
}
}
Diskuse je zrušena z důvodu spamu.