Mobile on Rails をSoftBank のあれな絵文字仕様に対応させた

また、SoftBank(Vodafone)の3G携帯にはSJISの外字領域を使用して絵文字を送出する機種が存在します。それらの機種については現在未対応(絵文字は全て削除される)です。


Young risk taker.: [Rails] SoftBank携帯からの制御文字を含む入力の変換に関するバグFix (Mobile on Rails)

ということで、あれな仕様のSoftBank の絵文字を扱えるようにした。

host /home/mhag/svn_work/foo% svn diff -r2450:HEAD
Index: vendor/plugins/mobile_on_rails/lib/mobile/emoji/softbank.rb
===================================================================
--- vendor/plugins/mobile_on_rails/lib/mobile/emoji/softbank.rb (revision 2450)
+++ vendor/plugins/mobile_on_rails/lib/mobile/emoji/softbank.rb (revision 2451)
@@ -14,13 +14,34 @@
           len = bytes.length
           ret = ''
           while i < len do
-            if bytes[i] != 0x1b # Not emoticons
+            if bytes[i] != 0x1b && bytes[i] != 0xf9 && bytes[i] != 0xf7 && bytes[i] != 0xfb # Not emoticons
               # Multibyte characters
               if (bytes[i] > 0x80 && bytes[i] < 0xa0) || (bytes[i] > 0xdf && bytes[i] < 0xf0)
                 ret += [sprintf("%x%x", bytes[i], bytes[i+=1])].pack('H4')
               else # Single byte character
                 ret += [bytes[i]].pack('C')
               end
+            elsif bytes[i] == 0xf9 || bytes[i] == 0xf7 || bytes[i] == 0xfb
+              code_area = bytes[i]
+              sjis = bytes[i + 1]
+
+              # Begin of web code
+              emoji_bytes = [0x24]
+
+              emoji_bytes << "G".unpack('C')[0] if code_area == 0xf9 && (0x41 .. 0x9b) === sjis
+              emoji_bytes << "E".unpack('C')[0] if code_area == 0xf7 && (0x41 .. 0x9b) === sjis
+              emoji_bytes << "F".unpack('C')[0] if code_area == 0xf7 && (0xa1 .. 0xf3) === sjis
+              emoji_bytes << "O".unpack('C')[0] if code_area == 0xf9 && (0xa1 .. 0xed) === sjis
+              emoji_bytes << "P".unpack('C')[0] if code_area == 0xfb && (0x41 .. 0x9b) === sjis
+              emoji_bytes << "Q".unpack('C')[0] if code_area == 0xfb && (0xa1 .. 0xd7) === sjis
+
+              emoji_bytes << (sjis - 0x20) if (0x41 .. 0x7e) === sjis
+              emoji_bytes << (sjis - 0x21) if (0x80 .. 0x9b) === sjis
+              emoji_bytes << (sjis - 0x80) if (0xa1 .. 0xed) === sjis
+
+              # pack('C3') だと、vodafone 絵文字のときにエラー(GEFOPQ が含まれないため)
+              ret += "__SB_#{emoji_bytes.pack('C*')}__"
+              i += 1
             else
               emoji_bytes = []
               emoji_bytes << bytes[i] while bytes[i+=1] != 0x0f
Index: vendor/plugins/mobile_on_rails/lib/mobile/controller.rb
===================================================================
--- vendor/plugins/mobile_on_rails/lib/mobile/controller.rb     (revision 2450)
+++ vendor/plugins/mobile_on_rails/lib/mobile/controller.rb     (revision 2451)
@@ -83,6 +83,24 @@
     def after_filter_for_mobile
       if request && request.mobile?
         response.body = NKF.nkf('-Ws -m0 -x', response.body)
+
+        p = /__SB_\$([GEFOPQ])([^_]+)__/
+
+        h_map = {
+          "&quot;" => "\"",
+          "&lt;" => "<",
+          "&gt;" => ">",
+          "&amp;" => "&",
+        }
+
+        response.body.gsub!(p) do |match|
+          if h_map.has_key?($2)
+            "__SB_\$#{$1}#{h_map[$2]}__"
+          else
+            match
+          end
+        end
+
         if request.mobile_carrier == ActionController::Mobile::DoCoMo
           response.body = response.body.to_emoji_from_internal_encode(:to => Emoji::DoCoMo)
         elsif request.mobile_carrier == ActionController::Mobile::AU


softbank.rb が主な修正対象。
ソフトバンクの絵文字を検出する正規表現 | ke-tai.org - インフィニットループ
SoftBankの一部機種の絵文字はSJIS外字領域を使用しているらしい - 覇王色を求めて
SoftBank 絵文字一覧
SoftBank 技術資料(HTML 編 211ページ以降)
を参考にして、Shift_JIS の外字領域に割り当てられている絵文字コード
Mobile on Rails が扱っているウェブコードっぽい近い形に変換する処理を加えた。
(例. 0xF90x41 ⇒ __SB_$G!__)


実はこれだけだとE002 やE01C, E01E(絵文字一覧参照)などの絵文字を扱ったときにうまくない。
上記の絵文字はMobile on Rails によって、それぞれ以下のように変換される。

E002 ⇒ __SB_$"!__
E01C ⇒ __SB_$<!__
E01E ⇒ __SB_$>!__

これらは出力時に h() によるエスケープの対象となる(404 Not Found)ため
絵文字の表示、変換が行われなくなってしまう。
この問題を解決するために、controller.rb にも修正を加えた。
コードを見て分かるとおり、一度 h() でエスケープされた文字列のうち
SoftBank の絵文字になりうるものだけはエスケープを解除している。
かなり無駄な処理ではあるが、極力修正範囲を狭くする(アプリには手を入れない)ためと割り切った。
この件はSoftBank のあれな絵文字仕様とは関係なく、以前から存在していたのだと思う。


これで無事にSoftBank のあれな絵文字仕様であっても
Mobile on Rails で扱えるようになった。