检查bom头和utf8编码检查
<?php
set_time_limit(0);
$basedir = ".";//检查的目录 ..为上级目录
$otherDirArr = [".svn",'images','web'];//排除目录
$fileTypeArr = ['.php'];//检查文件类型
$auto = 0;//0 1为自动更改文件编码
$display = 1;
checkdir($basedir,$otherDirArr,$fileTypeArr);
function checkdir($basedir,$otherDirArr,$fileTypeArr)
{
global $display;
if ($dh = opendir($basedir))
{
while (($file = readdir($dh)) !== false)
{
if ($file != '.' && $file != '..' )
{
if (!is_dir($basedir . "/" . $file) )
{//文件
if(in_array(strrchr($file, '.'),$fileTypeArr))
{//指定文件扩展
$fileName = "文 件: {$basedir}/{$file}";
$fileName = str_pad($fileName, 160, "-");
$result = checkBOM("$basedir/$file");
if ($display == 0 && $result == 'BOM not found')
{
}
else
{
echo $fileName . checkBOM("$basedir/$file") . " <br>";
}
//检查
}
}
else
{
if(!in_array($file,$otherDirArr))
{
$dirname = $basedir . "/" . $file; // 如果是目录
echo "<br>目 录: {$dirname}<br>";
checkdir($dirname,$otherDirArr,$fileTypeArr); // 递归
}
}
}
}
closedir($dh);
}
}
function checkBOM($filename)
{
$msg = "";
global $auto;
$contents = file_get_contents($filename);
$charset[1] = substr($contents, 0, 1);
$charset[2] = substr($contents, 1, 1);
$charset[3] = substr($contents, 2, 1);
// BOM的前三个字符的ASCII码分别为239、187、191
if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191)
{
if ($auto == 1)
{
$rest = substr($contents, 3);
rewrite($filename, $rest);
$msg = ("<b style='color:fuchsia'>BOM find, automatically removed</b>");
}
else
{
$msg = ("<b style='color: red'>BOM find</b>");
}
}
else
{
$msg = ("<b style='color: green'>BOM not find</b>");
}
switch (utf8_check($contents))
{
case 1:
$msg .= " 编码有BOM头";break;
case 2:
$msg .= " 编码utf8";break;
case 3:
$msg .= " 编码较可能是utf8";break;
case 4:
$msg .= " 编码较不可能是utf8";break;
}
return $msg;
}
function utf8_check($text)
{
$utf8_bom = chr(0xEF).chr(0xBB).chr(0xBF);
// BOM头检查
if (strstr($text, $utf8_bom) === 0)
return 1;
$text_len = strlen($text);
// UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;
// 如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。
// UTF-8最多可用到6个字节。
//
// 如表:
// < 0x80 1字节 0xxxxxxx
// < 0xE0 2字节 110xxxxx 10xxxxxx
// < 0xF0 3字节 1110xxxx 10xxxxxx 10xxxxxx
// < 0xF8 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// < 0xFC 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// < 0xFE 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
$bad = 0; // 不符合utf8规范的字符数
$good = 0; // 符号utf8规范的字符数
$need_check = 0; // 遇到多字节的utf8字符后,需要检查的连续字节数
$have_check = 0; // 已经检查过的连续字节数
for ($i = 0; $i < $text_len; $i ++) {
$c = ord($text[$i]);
if ($need_check > 0) {
$c = ord($text[$i]);
$c = ($c >> 6) << 6;
$have_check ++;
// 10xxxxxx ~ 10111111
if ($c != 0x80) {
$i -= $have_check;
$need_check = 0;
$have_check = 0;
$bad ++;
}
else if ($need_check == $have_check) {
$need_check = 0;
$have_check = 0;
$good ++;
}
continue;
}
if ($c < 0x80) // 0xxxxxxx
$good ++;
else if ($c < 0xE0) // 110xxxxx
$need_check = 1;
else if ($c < 0xF0) // 1110xxxx
$need_check = 2;
else if ($c < 0xF8) // 11110xxx
$need_check = 3;
else if ($c < 0xFC) // 111110xx
$need_check = 4;
else if ($c < 0xFE) // 1111110x
$need_check = 5;
else
$bad ++;
}
if ($bad == 0)
return 2;
else if ($good > $bad)
return 3;
else
return 4;
}
function rewrite($filename, $data)
{
$filenum = fopen($filename, "w");
flock($filenum, LOCK_EX);
fwrite($filenum, $data);
fclose($filenum);
}