我遇到的问题是提交给PHP脚本然后插入MySQL数据库的Web表单。
问题在于Copy&从Microsoft Word或类似的文字处理软件粘贴,主要影响项目符号,但有时会影响引号和单引号。我无法嗅到该人提交的字符编码。
我的文件顶部有以下代码(函数)来处理数据:
function init_byte_map(){
global $byte_map;
for($x=128;$x<256;++$x){
$byte_map[chr($x)]=utf8_encode(chr($x));
}
$cp1252_map=array(
"\x80"=>"\xE2\x82\xAC", // EURO SIGN
"\x82" => "\xE2\x80\x9A", // SINGLE LOW-9 QUOTATION MARK
"\x83" => "\xC6\x92", // LATIN SMALL LETTER F WITH HOOK
"\x84" => "\xE2\x80\x9E", // DOUBLE LOW-9 QUOTATION MARK
"\x85" => "\xE2\x80\xA6", // HORIZONTAL ELLIPSIS
"\x86" => "\xE2\x80\xA0", // DAGGER
"\x87" => "\xE2\x80\xA1", // DOUBLE DAGGER
"\x88" => "\xCB\x86", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\x89" => "\xE2\x80\xB0", // PER MILLE SIGN
"\x8A" => "\xC5\xA0", // LATIN CAPITAL LETTER S WITH CARON
"\x8B" => "\xE2\x80\xB9", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\x8C" => "\xC5\x92", // LATIN CAPITAL LIGATURE OE
"\x8E" => "\xC5\xBD", // LATIN CAPITAL LETTER Z WITH CARON
"\x91" => "\xE2\x80\x98", // LEFT SINGLE QUOTATION MARK
"\x92" => "\xE2\x80\x99", // RIGHT SINGLE QUOTATION MARK
"\x93" => "\xE2\x80\x9C", // LEFT DOUBLE QUOTATION MARK
"\x94" => "\xE2\x80\x9D", // RIGHT DOUBLE QUOTATION MARK
"\x95" => "\xE2\x80\xA2", // BULLET
"\x96" => "\xE2\x80\x93", // EN DASH
"\x97" => "\xE2\x80\x94", // EM DASH
"\x98" => "\xCB\x9C", // SMALL TILDE
"\x99" => "\xE2\x84\xA2", // TRADE MARK SIGN
"\x9A" => "\xC5\xA1", // LATIN SMALL LETTER S WITH CARON
"\x9B" => "\xE2\x80\xBA", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\x9C" => "\xC5\x93", // LATIN SMALL LIGATURE OE
"\x9E" => "\xC5\xBE", // LATIN SMALL LETTER Z WITH CARON
"\x9F" => "\xC5\xB8" // LATIN CAPITAL LETTER Y WITH DIAERESIS
);
foreach($cp1252_map as $k=>$v){
$byte_map[$k]=$v;
}
}
function fix_latin($instr){
if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's all valid UTF-8 already
global $nibble_good_chars,$byte_map;
$outstr='';
$char='';
$rest='';
while((strlen($instr))>0){
if(1==preg_match($nibble_good_chars,$input,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$char;
}elseif(1==preg_match('@^(.)(.*)$@s',$input,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$byte_map[$char];
}
$instr=$rest;
}
return $outstr;
}
$byte_map=array();
init_byte_map();
$ascii_char='[\x00-\x7F]';
$cont_byte='[\x80-\xBF]';
$utf8_2='[\xC0-\xDF]'.$cont_byte;
$utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
$utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
$utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
$nibble_good_chars = "@^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$@s";
然后我收到每个表单字段并运行fix_latin函数。
foreach ($jobdata AS $field => $string)
{
$string = fix_latin($string);
$jobdata[$field] = addslashes(str_replace("\n", '<br />', htmlspecialchars($string)));
}
数据输入数据库,并通过电子邮件发送给系统管理员进行审批。今天我收到了一封管理员电子邮件,内容如下:
Job Description: Responsibilities:
路 Assist multi-state companies
当我查看数据库或在脚本中编辑时,子弹替换为方框,而不是•实体。
答案 0 :(得分:0)
表单应使用与其主机文档相同的字符编码进行提交。理论上,您可以在声明表单时使用<form accept-charset="UTF-8">
覆盖字符编码,但这在Internet Explorer中不起作用(惊喜)。
如果您对包含表单的页面使用相同的字符编码,则需要使用正确的字符编码来获取数据。
此外,如果您的脚本同时发送电子邮件并将数据存储到表中,则需要确保电子邮件和表格都使用相同的字符编码。您需要在电子邮件中设置相应的标题,以确保读者知道您正在使用的字符编码。
我建议您始终使用UTF8,确保您的数据库和网页都使用UTF8编码,并且您的脚本发送的任何电子邮件也会设置一个标题,表明它们也使用UTF8进行编码。它应该有希望消除像您一直使用的那样繁琐的转换功能的需要。我自己在一个项目中遇到了类似的问题,起初我尝试了解决问题的方法,但最终它只是处理得太多了,因为你需要捕获和处理成千上万的潜在输入。
与此同时,一个简单的解决方法是不直接从Word粘贴,而是从Word粘贴到简单的文本编辑器(如记事本),然后从记事本复制并粘贴到浏览器。