unoh.github.com

SoftBank絵文字の対処法

Fri Jan 12 07:00:17 -0800 2007

こんにちは。harukです。

今回はSoftBankの絵文字の対処法の基礎的な部分についてです。

絵文字コードは以下のようになっています。

0x1B    0x24($)   【 ? 】    【 X 】…   0x0F

【 ? 】 = G / E / F / O / P / Q

【 X 】 = 0x21~0x7E

【 X 】の部分には、[ < ]や[ ' ]や[ \ ]などが含まれているので多少やっかいです。

入力された絵文字を含む文字列を表示する際などには HTMLエンコード(実体参照化)してあげなければいけませんが、

絵文字の中もエンコードされてしまいます。

(例)

こんにちは(0x1B)(0x24)G>(0x0F)

こんにちは(0x1B)(0x24)G&gt;(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);
    }