Так как и обещал выкладываю чего, навоял. Я понимаю что ниже изложенное решение не являться лекарством от всех болячек, и даже не является одним из лидеров решения проблемы, но пока так, со временем все будет.
Код не оптимизирован и специально составлен в развернутом виде, привык работать с комфортом не во вред глазам и мозгу, так что если товарищи оптимизаторы захотят сократить код, то милости просим, и народ не забываем выкладывать примеры оптимизации и улучшения.
Перейдем к исходникам, функции:
PHP:
function getPageCharset($v = 0, $v2 = false) {
//preg_match('#<meta[^<>]*content=[\'"].*charset=(.+)[\'"][^<>]*>#iU', $v, $rm1);
preg_match('#<meta[^<>]*content=[\'"].*(utf-8|windows-1251)[\'"][^<>]*>#iU', $v, $rm1);
unset($rm1[0]);
if ( $rm1[1] != '' )
{
$r = $rm1[1];
}
else {
$r = $v2;
}
$r = strtolower($r);
return ( $r ) ;
}
Функция getPageCharset() предназначена для получения кодировки из мета тега страницы.
Принимает два значения на входе:
$v = Тело страници.
$v2 = кодировка по умолчанию
PHP:
function chkIsUtf8($v = '', $v2 = 2) {
$r = 0;
#check #1
$cV = strlen($v);
for ($i=0; $i < $cV; $i++) {
$c = ord($v[$i]);
if ($c < 0x80) {
$n = 0; # 0bbbbbbb
}
else if (($c & 0xE0) == 0xC0) {
$n=1; # 110bbbbb
}
else if (($c & 0xF0) == 0xE0) {
$n=2; # 1110bbbb
}
else if (($c & 0xF8) == 0xF0) {
$n=3; # 11110bbb
}
else if (($c & 0xFC) == 0xF8) {
$n=4; # 111110bb
}
else if (($c & 0xFE) == 0xFC) {
$n=5; # 1111110b
}
else {
$r = 1;
break; # Does not match any model
}
for ($i2=0; $i2<$n; $i2++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $cV) OR ((ord($v[$i]) & 0xC0) != 0x80)) {
$r = 1;
break(2);
}
}
}
if ($r) {
$r = 0;
}
else {
$r++;
}
#check #2
if (function_exists(mb_check_encoding)) {
if (mb_check_encoding($v, 'utf-8')) {
$r++;
}
}
#check #3
if (preg_match('#.#u', $v)) {
$r++;
}
if ($r >= $v2) {
$r = 1;
}
else {
$r = 0;
}
return $r;
}
Функция chkIsUtf8() проверяет строку на кодировку геа-8.
Принимает два значения на входе:
$v = Проверяемая строка, в нашем случае тело страницы.
$v2 = строгость проверки. Функция проверяет строку на utf-8 последовательно 3-мя способами, по умолчанию параметр строгости проверки выставлен в значение 2, то есть если в 2-х проверка результат будет положительный? то функция скажет что строка имеет кодировку utf-8
PHP:
function getCharsetString($v = '') {
$r = false;
if (chkIsUtf8($v)) {
$r = 'utf-8';
}
else {
$cp1251 = 0;
$koi8u = 0;
$cV = strlen($v);
for($i=0; $i<$cV; $i++) {
$c = ord($v[$i]);
if (($c>223 AND $c<256) OR ($c==179) OR ($c==180) OR ($c==186) OR ($c==191)) {
$cp1251++; // а-я, і, ґ, є, Ї
}
if (($c>191 AND $c<224) OR ($c==164) OR ($c==166) OR ($c==167) OR ($c==173)) {
$koi8u++; // а-я, є, і, ї, ґ
}
}
if ($cp1251>$koi8u) {
$r = 'windows-1251';
}
else {
$r = 'koi8-u';
}
}
return $r;
}
Функция getCharsetString() возвращает кодировку строки, сейчас поддерживает определение следующих кодировок utf-8, windows-1251, koi8-u, и зависит от функции chkIsUtf8().
Принимает одно значения на входе:
$v = Проверяемая строка, в нашем случае тело страницы.
PHP:
function chkCharsetPage($v = '', $v2 = false) {
$charset1 = $v2;
if ($v != '') {
$charset2 = TCorE_helper::getPageCharset($v);
$charset3 = TCorE_helper::getCharsetString($v);
}
else {
$charset2 = false;
$charset3 = false;
}
if (($charset1 != false) AND ($charset1 == $charset2 OR $charset1 == $charset3)) {
$r = $charset1;
}
else if ($charset2 != false AND $charset2 == $charset3) {
$r = $charset2;
}
else if ($charset1 != false AND $charset2 == false) {
$r = $charset1;
}
else if ($charset3 != false) {
$r = $charset3;
}
else {
$r = false;
}
return $r;
}
Функция chkCharsetPage() проверяет и возвращает кодировку страницы.
Принимает два значения на входе:
$v = Проверяемая строка, в нашем случае тело страницы.
$v2 = выпарсеная кодировка из заголовков ответа сервера.
запуск работы:
PHP:
$pageBody = '...ПОЛУЧАЕМ ТЕЛО СТРАНИЦЫ...';
$pageHeaderCharset = '...РАСПАРСИВАЕМ ЗАГОЛОВКИ ПЕРЕДАННЫЕ НАМ СЕРВЕРОМ НА НАЛИЧИЕ КОДИРОВКИ...';
$pageBody = preg_replace( '#(\n|\r|\t| {2,})#', '', $pageBody);
echo chkCharsetPage($pageBody, $pageHeaderCharset);
Теперь хочу немного рассказать ка да чего, собственно функция chkCharsetPage() являеться локомотивом для всех остальных функций, и заниматься конечным определением кодировки страницы.
Работа функции основывается на следующих принципах и правилах:
1) Определение по возможности, вариантов кодировки в 3 местах:
1.1) Заголовки ответа сервера
1.2) Мета данные страницы
1.3) Самостоятельный анализ тела документа на пренадлежность к кодировкам.
2) Выполнение правил определения кодировки (всего 5
2.1) Если БЫЛА ПОЛУЧЕНА кодировка из Заголовков ответа сервера И она РАВНА кодировке Мета данных страницы ИЛИ кодировке Самостоятельного анализа, ТО возвращается кодировка Заголовков ответа сервера. В ИНОМ случае выполняется следующее правило.
2.2) Если БЫЛА ПОЛУЧЕНА кодировка Мета данных страницы И она РАВНА кодировке Самостоятельного анализа, ТО возвращается кодировка Мета данных страницы. В ИНОМ случае выполняется следующее правило.
2.3) Если БЫЛА ПОЛУЧЕНА кодировка из Заголовков ответа сервера И кодировка из Мета данных страницы НЕ ПОЛУЧЕНА, ТО возвращается кодировка Заголовков ответа сервера. В ИНОМ случае выполняется следующее правило.
2.4) Если БЫЛА ПОЛУЧЕНА кодировка Самостоятельного анализа, ТО возвращается кодировка Самостоятельного анализа. В ИНОМ случае выполняется следующее правило.
2.5) В ОСТАЛЬНЫХ случаях возвращается false.
Ну в общем как то так
Советы, замечания, предложения в студию.
P.S.: Извиняюсь за такой огромный пост.