본문 바로가기
프로그래밍/Source

[일본]SoftBank 그림문자(絵文字)관련 처리

by 백룡화검 2010. 1. 28.




예전에 스퀘어 에닉스 관련 작업을 할때도

그림문자 처리와 관련해서 고생을 했었는데

이번에 또 고생을 했기에 혹시 잊을까봐 기록해 둔다.

SoftBank의 경우 특이하게도 그림문자(絵文字)만 UTF-8의 인코딩을 사용한다.

때문에 일반적으로 일본 웹페이지를 구성할때 사용하는 SJIS에서는 처리하기가 애매하다.

※ 도코모와 AU는 SJIS형식을 사용한다.

예전에는 SJIS를 사용했었으나 언제부터인가 UTF-8로 바뀌었다.

그래서 오래된 그림분자 변환 로직의 경우 제대로 동작하지 않는 현상이 발생했다.

더군다나 SJIS형식의 페이지에서 전송한 UTF-8데이터는 문자 코드가 변해 버려서

UTF-8형식으로의 체크도 힘들어 진다.

해결한 방법은 일단 입력받은 데이터 중에서 그림문자만 분류한 다음

해당 그림 문자의 Encoding을 SJIS에서 UTF-8로 변경한다음 UTF-8용의

그림문자 맵 데이터와 맵핑한후 SJIS용의 WebCode로 변경하는 방법을 사용했다.

이용한 소스는 다음과 같다.
/**
 * Convert character encoding from Shift_JIS to UTF-8.
 *
 * @param  string  $text
 * @return string
 */
function _convertSjisToUtf8($text)
{
    $backup = mb_substitute_character();
    mb_substitute_character('long');
    $text = mb_convert_encoding($text, 'UTF-8', 'SJIS');
    mb_substitute_character($backup);

    $pattern  = '/BAD\+([0-9A-F]{4})/';
    //$callback = array($this, '_fallbackSjisToUtf8');
    $text     = preg_replace_callback($pattern, '_fallbackSjisToUtf8', $text);

    return $text;
}

/**
 * Callback function called by _convertSjisToUtf8() method.
 *
 * This function converts Shift_JIS hexadecimal code to UTF-8 binary data.
 *
 * @param  array   $matches
 * @return string
 */
function _fallbackSjisToUtf8($matches)
{
    $sjis = hexdec($matches[1]);
    $high = $sjis >> 8;
    $low  = $sjis & 0xFF;

    if ($low > 0xA0) {
        if ($high === 0xF7 && $low <= 0xFA) {
            $unicode = "\xE2" . chr($low - 0xA0);
        } else if ($high === 0xF9 && $low <= 0xED) {
            $unicode = "\xE3" . chr($low - 0xA0);
        } else if ($high === 0xFB && $low <= 0xDE) {
            $unicode = "\xE5" . chr($low - 0xA0);
        }
    } else if ($low > 0x40) {
        if ($low >= 0x80) {
            --$low;
        }
        if ($high === 0xF7 && $low < 0x9B) {
            $unicode = "\xE1" . chr($low - 0x40);
        } else if ($high === 0xF9 && $low < 0x9B) {
            $unicode = "\xE0" . chr($low - 0x40);
        } else if ($high === 0xFB && $low < 0x8D) {
            $unicode = "\xE4" . chr($low - 0x40);
        }
    }

    return mb_convert_encoding($unicode, 'UTF-8', 'UCS-2');
}

사용방법은 _convertSjisToUtf8에 변경 하고 싶은 그림문자를 집어 넣으면 된다.

참조한 소스와 수정한 파일은 첨부 파일을 참고 하길 바란다.