こんにちは。harukです。
今回はSoftBankの絵文字の対処法の基礎的な部分についてです。
絵文字コードは以下のようになっています。
0x1B 0x24($) 【 ? 】 【 X 】… 0x0F
【 ? 】 = G / E / F / O / P / Q
【 X 】 = 0x21~0x7E
【 X 】の部分には、[ < ]や[ ' ]や[ \ ]などが含まれているので多少やっかいです。
入力された絵文字を含む文字列を表示する際などには HTMLエンコード(実体参照化)してあげなければいけませんが、
絵文字の中もエンコードされてしまいます。
(例)
こんにちは(0x1B)(0x24)G>(0x0F)
↓
こんにちは(0x1B)(0x24)G>(0x0F)
となってしまい、4文字の別の絵文字になってしまいます。
対応するにはPHPでは以下のように行います。
function SB_htmlspecialchars($str)
{
$emoji_range = '[G|E|F|O|P|Q][\x21-\x7E]';
$pattern = '/[\x1B][\x24]'.$emoji_range.'+[\x0F]/';
$matches = array();
$match_count = preg_match_all($pattern, $str, $matches);
if (!$match_count) {
return _htmlspecialchars($str);
}
$matches[0][] = '';
$split = preg_split($pattern, $str);
$split = array_map('_htmlspecialchars', $split);
$htmlstr = '';
foreach ($split as $key => $val) {
$htmlstr .= $val.$matches[0][$key];
}
return $htmlstr;
}
function _htmlspecialchars($str)
{
$encode = mb_internal_encoding();
return htmlspecialchars($str, ENT_QUOTES, $encode);
}
さきほどの例文で、注意点が一つあります。
古い機種で、絵文字で終わっている場合に末尾の(0x0F)がつかない端末があります。。。
そのため、受け取った文字列に最初に以下の処理を通しておきます。
/* 末尾に0x0Fがない場合に追加 */
function SBEmoji($str)
{
$emoji_range = '[G|E|F|O|P|Q][\x21-\x7E]';
$pattern = '/[\x1B][\x24]'.$emoji_range.'+([\x0F]?)$/';
$matches = array();
preg_match_all($pattern, $str, $matches);
if (isset($matches[1][0]) && $matches[1][0] === '') {
$str .= pack("C*", 0x0F);
}
return $str;
}
こんな感じでSoftBankのエスケープシーケンスでの絵文字を対応しておけば問題はないと思います。
あとは、絵文字の相互変換のために、連続している絵文字を1文字ずつに分けたり、
2バイトの絵文字の対応を行ったり、という処理があるぐらいです。
基礎の部分でしたが、お役に立てれば幸いです。
最後に今年の目標を…「Vodafoneと言わないようにする」
修正(2007/10/19 18:15)
コメントにて指摘があり修正しました。ありがとうございます。
// 修正前
preg_match_all($pattern, $str, $matches);
if (count($matches) == 0) {
return _htmlspecialchars($str);
}
// 修正後
$match_count = preg_match_all($pattern, $str, $matches);
if (!$match_count) {
return _htmlspecialchars($str);
}