rack-ketai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
 - data/MIT-LICENSE +21 -0
 - data/README.rdoc +122 -0
 - data/VERSION +1 -0
 - data/lib/rack/ketai/carrier/abstract.rb +263 -0
 - data/lib/rack/ketai/carrier/au.rb +153 -0
 - data/lib/rack/ketai/carrier/cidrs/au.rb +32 -0
 - data/lib/rack/ketai/carrier/cidrs/docomo.rb +14 -0
 - data/lib/rack/ketai/carrier/cidrs/softbank.rb +10 -0
 - data/lib/rack/ketai/carrier/docomo.rb +157 -0
 - data/lib/rack/ketai/carrier/emoji/ausjisstrtoemojiid.rb +1391 -0
 - data/lib/rack/ketai/carrier/emoji/docomosjisstrtoemojiid.rb +759 -0
 - data/lib/rack/ketai/carrier/emoji/emojidata.rb +836 -0
 - data/lib/rack/ketai/carrier/emoji/emojiidtotypecast.rb +432 -0
 - data/lib/rack/ketai/carrier/emoji/softbankutf8strtoemojiid.rb +1119 -0
 - data/lib/rack/ketai/carrier/emoji/softbankwebcodetoutf8str.rb +499 -0
 - data/lib/rack/ketai/carrier/general.rb +75 -0
 - data/lib/rack/ketai/carrier/iphone.rb +16 -0
 - data/lib/rack/ketai/carrier/softbank.rb +144 -0
 - data/lib/rack/ketai/carrier/specs/au.rb +1 -0
 - data/lib/rack/ketai/carrier/specs/docomo.rb +1 -0
 - data/lib/rack/ketai/carrier/specs/softbank.rb +1 -0
 - data/lib/rack/ketai/carrier.rb +18 -0
 - data/lib/rack/ketai/display.rb +16 -0
 - data/lib/rack/ketai/middleware.rb +36 -0
 - data/lib/rack/ketai.rb +12 -0
 - data/spec/spec_helper.rb +11 -0
 - data/spec/unit/au_filter_spec.rb +96 -0
 - data/spec/unit/au_spec.rb +240 -0
 - data/spec/unit/carrier_spec.rb +30 -0
 - data/spec/unit/display_spec.rb +25 -0
 - data/spec/unit/docomo_filter_spec.rb +106 -0
 - data/spec/unit/docomo_spec.rb +344 -0
 - data/spec/unit/emoticon_filter_spec.rb +91 -0
 - data/spec/unit/filter_spec.rb +38 -0
 - data/spec/unit/iphone_spec.rb +16 -0
 - data/spec/unit/middleware_spec.rb +38 -0
 - data/spec/unit/softbank_filter_spec.rb +133 -0
 - data/spec/unit/softbank_spec.rb +200 -0
 - data/spec/unit/valid_addr_spec.rb +86 -0
 - data/test/spec_runner.rb +29 -0
 - data/tools/generate_emoji_dic.rb +434 -0
 - data/tools/update_speclist.rb +87 -0
 - metadata +138 -0
 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            tools/tmp
         
     | 
    
        data/MIT-LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            The MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2009 Yuichi Takeuchi
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 13 
     | 
    
         
            +
            all copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 21 
     | 
    
         
            +
            THE SOFTWARE.
         
     | 
    
        data/README.rdoc
    ADDED
    
    | 
         @@ -0,0 +1,122 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            = rack-ketai: A Rack Middleware for Japanese mobile-phones
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            == rack-ketaiとは
         
     | 
| 
      
 4 
     | 
    
         
            +
            携帯電話向けサイトを構築する際に役立ちそうな機能を提供する(ことが目標の)ミドルウェアです。
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            * 携帯電話キャリア判別
         
     | 
| 
      
 7 
     | 
    
         
            +
            * 端末名の取得
         
     | 
| 
      
 8 
     | 
    
         
            +
            * ユーザID、端末IDの取得
         
     | 
| 
      
 9 
     | 
    
         
            +
            * ディスプレイ情報(サイズ、色数)の取得
         
     | 
| 
      
 10 
     | 
    
         
            +
            * Cookie使用の可否
         
     | 
| 
      
 11 
     | 
    
         
            +
            * キャッシュサイズの取得
         
     | 
| 
      
 12 
     | 
    
         
            +
            * IPアドレス帯域の正当性チェック
         
     | 
| 
      
 13 
     | 
    
         
            +
            * 入出力文字コード変換(DoCoMo、auのみ)
         
     | 
| 
      
 14 
     | 
    
         
            +
            * 絵文字キャリア間変換
         
     | 
| 
      
 15 
     | 
    
         
            +
            * PCでの絵文字表示(TypePadの絵文字使用)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            テスト環境もまともにないので、万年αテスト中です。自己責任で、よくテストを行ってご利用下さい。
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            == 使えそうなRubyのバージョン
         
     | 
| 
      
 20 
     | 
    
         
            +
            適当テストを通ったバージョンです。
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            CRuby 1.8.5, 1.8.6, 1.8.7, 1.9.1
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            JRuby 1.4.0
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            == 使用例
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            === 携帯電話の識別
         
     | 
| 
      
 29 
     | 
    
         
            +
              require 'rubygems'
         
     | 
| 
      
 30 
     | 
    
         
            +
              require 'sinatra'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              require 'rack/ketai'
         
     | 
| 
      
 33 
     | 
    
         
            +
              use Rack::Ketai
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              get '/' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                case request.env['rack.ketai']
         
     | 
| 
      
 37 
     | 
    
         
            +
                when Rack::Ketai::Carrier::Docomo
         
     | 
| 
      
 38 
     | 
    
         
            +
                  "こんにちは、DoCoMo世界!"
         
     | 
| 
      
 39 
     | 
    
         
            +
                when Rack::Ketai::Carrier::Au
         
     | 
| 
      
 40 
     | 
    
         
            +
                  "こんにちは、Au世界!"
         
     | 
| 
      
 41 
     | 
    
         
            +
                when Rack::Ketai::Carrier::Softbank
         
     | 
| 
      
 42 
     | 
    
         
            +
                  "こんにちは、Softbank世界!"
         
     | 
| 
      
 43 
     | 
    
         
            +
                else
         
     | 
| 
      
 44 
     | 
    
         
            +
                  "こんにちは、その他の世界!"
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            単に携帯電話でのアクセスか識別するのであれば、<tt>#mobile?</tt>を使います。
         
     | 
| 
      
 49 
     | 
    
         
            +
              env['rack.ketai'].mobile?
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            互換性のため、携帯電話からのアクセスでないときには、特異メソッド<tt>#mobile? => false</tt>を定義した<tt>nil</tt>が設定されます。
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            === 端末名の取得
         
     | 
| 
      
 54 
     | 
    
         
            +
              env['rack.ketai'].name # => "SO903i"
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            === ユーザID、端末IDの取得
         
     | 
| 
      
 57 
     | 
    
         
            +
            各キャリアの利用者の識別に関する情報の扱いを一元化します。
         
     | 
| 
      
 58 
     | 
    
         
            +
            これにより、携帯サイトでのユーザ認証等が容易になります。(後述のIPアドレス帯域チェックと併用すること)
         
     | 
| 
      
 59 
     | 
    
         
            +
              ketai = env['rack.ketai']
         
     | 
| 
      
 60 
     | 
    
         
            +
              ketai.subscriberid  # ユーザID:iモードID or FOMAカード製造番号/EZ番号/x-jphone-uid
         
     | 
| 
      
 61 
     | 
    
         
            +
              ketai.deviceid      # 端末ID:端末製造番号(DoCoMo)/端末シリアル(SoftbankMobile)
         
     | 
| 
      
 62 
     | 
    
         
            +
              ketai.ident         # ユーザか端末を識別する情報(ユーザID or 端末製造番号)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            === ディスプレイ情報の取得
         
     | 
| 
      
 65 
     | 
    
         
            +
            環境変数もしくは http://ke-tai.org/ で公開されている携帯端末スペック一覧のデータから縦横ピクセル数及び色数を取得できます。
         
     | 
| 
      
 66 
     | 
    
         
            +
              ketai = env['rack.ketai']
         
     | 
| 
      
 67 
     | 
    
         
            +
              display = ketai.display
         
     | 
| 
      
 68 
     | 
    
         
            +
              display.colors # 色数 取得できなければ nil
         
     | 
| 
      
 69 
     | 
    
         
            +
              display.width  # 横サイズ 取得できなければ nil
         
     | 
| 
      
 70 
     | 
    
         
            +
              display.height # 縦サイズ 取得できなければ nil
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            === Cookie使用の可否
         
     | 
| 
      
 73 
     | 
    
         
            +
            DoCoMoの場合はiモードブラウザ2.0、SoftBankは現行の全機種、auも全機種(WAP1.0端末はSSL通信時利用不可)っぽいのでそれを判別してくれます。(できるだけ...)
         
     | 
| 
      
 74 
     | 
    
         
            +
              if env['rack.ketai'].supports_cookie?
         
     | 
| 
      
 75 
     | 
    
         
            +
                # Cookie 使用可能
         
     | 
| 
      
 76 
     | 
    
         
            +
              else
         
     | 
| 
      
 77 
     | 
    
         
            +
                # Cookie 使用不可
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            === キャッシュサイズの取得
         
     | 
| 
      
 81 
     | 
    
         
            +
            環境変数や端末名からブラウザのキャッシュサイズ(Bytes)を取得します。取得できない場合は、それっぽい最小の値を返します。
         
     | 
| 
      
 82 
     | 
    
         
            +
              env['rack.ketai'].cache_size # => 100000 (100KB)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            === IPアドレス帯域の正当性チェック
         
     | 
| 
      
 85 
     | 
    
         
            +
            ユーザのアクセス元のIPアドレスがキャリアが公開するアドレス帯に含まれているか確認できます。
         
     | 
| 
      
 86 
     | 
    
         
            +
            ユーザID等の偽装防止等に役立ちます。
         
     | 
| 
      
 87 
     | 
    
         
            +
              ketai = env['rack.ketai']
         
     | 
| 
      
 88 
     | 
    
         
            +
              unless ketai.mobile? && ketai.valid_addr?
         
     | 
| 
      
 89 
     | 
    
         
            +
                # 携帯からのアクセスでない
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            === 入出力文字コード変換
         
     | 
| 
      
 93 
     | 
    
         
            +
            DoCoMoまたはauの携帯電話との通信でShift_JISを使うようになります。
         
     | 
| 
      
 94 
     | 
    
         
            +
            Content-typeも便宜書き換えます。
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            === 絵文字キャリア間変換
         
     | 
| 
      
 97 
     | 
    
         
            +
            入力された絵文字を、emoji4unicodeによる変換テーブルを元に [e:XXX] という文字列に置き換えます。
         
     | 
| 
      
 98 
     | 
    
         
            +
            (XXX はemoji4unicodeによる絵文字のID)
         
     | 
| 
      
 99 
     | 
    
         
            +
            文字列に置き換えるようにしたのは、PCからの絵文字の入力・表示への対応を容易にするためです。
         
     | 
| 
      
 100 
     | 
    
         
            +
            出力時にキャリアに応じた絵文字コードに変換します。
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            なお、文字コード変換及び絵文字変換を行いたくない場合は、<tt>:disable_filter</tt>オプションを設定します。
         
     | 
| 
      
 103 
     | 
    
         
            +
              use Rack::Ketai, :disable_filter => true
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            === PCでの絵文字表示
         
     | 
| 
      
 106 
     | 
    
         
            +
            SixApartが公開している絵文字アイコン画像を別途ダウンロード・配置し、簡単なコードを追加することで携帯キャリア以外でのアクセスの際に絵文字画像を表示できます。
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            TypePadの絵文字アイコン画像と、携帯コンテンツ表示モジュールをフリー(自由)ライセンスで公開
         
     | 
| 
      
 109 
     | 
    
         
            +
            http://start.typepad.jp/typecast/
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            絵文字アイコンをダウンロードし、public/images/emoticons/*.gif に配置した場合の例
         
     | 
| 
      
 112 
     | 
    
         
            +
              use Rack::Static, :urls => ['/images'], :root => 'public'
         
     | 
| 
      
 113 
     | 
    
         
            +
              use Rack::Ketai, :emoticons_path => '/images/emoticons'
         
     | 
| 
      
 114 
     | 
    
         
            +
              run MyApp.new
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            === 作者
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            Copyright 2009-2010 (c) Yuichi Takeuchi, under MIT License
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            Yuichi Takeuchi <mizincogrammer@gmail.com>
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            http://d.hatena.ne.jp/mizincogrammer
         
     | 
    
        data/VERSION
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            0.1.0
         
     | 
| 
         @@ -0,0 +1,263 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'tempfile'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'singleton'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'nkf'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rack/request'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'stringio'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'ipaddr'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            unless IPAddr.instance_methods.include?("to_range")
         
     | 
| 
      
 10 
     | 
    
         
            +
              class IPAddr
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def coerce_other(other)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  case other
         
     | 
| 
      
 14 
     | 
    
         
            +
                  when IPAddr
         
     | 
| 
      
 15 
     | 
    
         
            +
                    other
         
     | 
| 
      
 16 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.class.new(other)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  else
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.class.new(other, @family)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Returns the successor to the ipaddr.
         
     | 
| 
      
 24 
     | 
    
         
            +
                def succ
         
     | 
| 
      
 25 
     | 
    
         
            +
                  return self.clone.set(@addr + 1, @family)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
                
         
     | 
| 
      
 28 
     | 
    
         
            +
                # Compares the ipaddr with another.
         
     | 
| 
      
 29 
     | 
    
         
            +
                def <=>(other)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  other = coerce_other(other)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  
         
     | 
| 
      
 32 
     | 
    
         
            +
                  return nil if other.family != @family
         
     | 
| 
      
 33 
     | 
    
         
            +
                  
         
     | 
| 
      
 34 
     | 
    
         
            +
                  return @addr <=> other.to_i
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
                include Comparable
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
      
 38 
     | 
    
         
            +
                def to_range
         
     | 
| 
      
 39 
     | 
    
         
            +
                  begin_addr = (@addr & @mask_addr)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  
         
     | 
| 
      
 41 
     | 
    
         
            +
                  case @family
         
     | 
| 
      
 42 
     | 
    
         
            +
                  when Socket::AF_INET
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end_addr = (@addr | (IN4MASK ^ @mask_addr))
         
     | 
| 
      
 44 
     | 
    
         
            +
                  when Socket::AF_INET6
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end_addr = (@addr | (IN6MASK ^ @mask_addr))
         
     | 
| 
      
 46 
     | 
    
         
            +
                  else
         
     | 
| 
      
 47 
     | 
    
         
            +
                    raise "unsupported address family"
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  return clone.set(begin_addr, @family)..clone.set(end_addr, @family)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
                
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            module Rack::Ketai::Carrier
         
     | 
| 
      
 56 
     | 
    
         
            +
              class Abstract
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def filters
         
     | 
| 
      
 60 
     | 
    
         
            +
                    []
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def valid_addr?(remote_addr)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    cidrs = nil
         
     | 
| 
      
 65 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 66 
     | 
    
         
            +
                      cidrs = self::CIDRS
         
     | 
| 
      
 67 
     | 
    
         
            +
                    rescue NameError
         
     | 
| 
      
 68 
     | 
    
         
            +
                      return nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    remote = IPAddr.new(remote_addr)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    cidrs.any?{ |cidr| cidr.include?(remote) }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  alias :valid_ip? :valid_addr?
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def initialize(env)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @env = env
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
                
         
     | 
| 
      
 80 
     | 
    
         
            +
                USER_AGENT_REGEXP = nil
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def filtering(env, options = { }, &block)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  env = options[:disable_filter] ? env : filters(options).inject(env) { |env, filter| filter.inbound(env) }
         
     | 
| 
      
 84 
     | 
    
         
            +
                  ret = block.call(env)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  ret[2] = ret[2].body if ret[2].is_a?(Rack::Response)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  options[:disable_filter] ? ret : filters(options).reverse.inject(ret) { |r, filter| filter.outbound(*r) }
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def filters(options = { })
         
     | 
| 
      
 90 
     | 
    
         
            +
                  self.class.filters.collect do |klass|
         
     | 
| 
      
 91 
     | 
    
         
            +
                    klass.new(options)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
                
         
     | 
| 
      
 95 
     | 
    
         
            +
                # 携帯端末か
         
     | 
| 
      
 96 
     | 
    
         
            +
                def mobile?
         
     | 
| 
      
 97 
     | 
    
         
            +
                  false
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                # サブスクライバID
         
     | 
| 
      
 101 
     | 
    
         
            +
                # 契約者毎にユニーク
         
     | 
| 
      
 102 
     | 
    
         
            +
                def subscriberid
         
     | 
| 
      
 103 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                # デバイスID
         
     | 
| 
      
 107 
     | 
    
         
            +
                # 端末毎にユニーク
         
     | 
| 
      
 108 
     | 
    
         
            +
                def deviceid
         
     | 
| 
      
 109 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
                
         
     | 
| 
      
 112 
     | 
    
         
            +
                # 識別情報
         
     | 
| 
      
 113 
     | 
    
         
            +
                def ident
         
     | 
| 
      
 114 
     | 
    
         
            +
                  subscriberid || deviceid
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # 機種名(略名)
         
     | 
| 
      
 118 
     | 
    
         
            +
                def name
         
     | 
| 
      
 119 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                # ディスプレイ情報
         
     | 
| 
      
 123 
     | 
    
         
            +
                def display
         
     | 
| 
      
 124 
     | 
    
         
            +
                  Rack::Ketai::Display.new
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                # キャリアのIPアドレス帯を利用しているか
         
     | 
| 
      
 128 
     | 
    
         
            +
                def valid_addr?
         
     | 
| 
      
 129 
     | 
    
         
            +
                  self.class.valid_ip? @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_ADDR']
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
                alias :valid_ip? :valid_addr?
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                # キャッシュサイズ
         
     | 
| 
      
 134 
     | 
    
         
            +
                def cache_size
         
     | 
| 
      
 135 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                # Cookieのサポート
         
     | 
| 
      
 139 
     | 
    
         
            +
                def supports_cookie?
         
     | 
| 
      
 140 
     | 
    
         
            +
                  false
         
     | 
| 
      
 141 
     | 
    
         
            +
                end
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
            end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            class Rack::Ketai::Carrier::Abstract
         
     | 
| 
      
 146 
     | 
    
         
            +
              class Filter
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                def initialize(options = { })
         
     | 
| 
      
 149 
     | 
    
         
            +
                  @options = options.clone
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
                
         
     | 
| 
      
 152 
     | 
    
         
            +
                def inbound(env)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  apply_incoming?(env) ? to_internal(env) : env
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
                
         
     | 
| 
      
 156 
     | 
    
         
            +
                def outbound(status, headers, body)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  apply_outgoing?(status, headers, body) ? to_external(status, headers, body) : [status, headers, body]
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                private
         
     | 
| 
      
 161 
     | 
    
         
            +
                def to_internal(env)
         
     | 
| 
      
 162 
     | 
    
         
            +
                  env
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
                
         
     | 
| 
      
 165 
     | 
    
         
            +
                def to_external(status, headers, body)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  if headers['Content-Type']
         
     | 
| 
      
 167 
     | 
    
         
            +
                    case headers['Content-Type']
         
     | 
| 
      
 168 
     | 
    
         
            +
                    when /charset=[\w\-]+/i
         
     | 
| 
      
 169 
     | 
    
         
            +
                      headers['Content-Type'].sub!(/charset=[\w\-]+/, 'charset=utf-8')
         
     | 
| 
      
 170 
     | 
    
         
            +
                    else
         
     | 
| 
      
 171 
     | 
    
         
            +
                      headers['Content-Type'] << "; charset=utf-8"
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
      
 174 
     | 
    
         
            +
                  [status, headers, body]
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
                
         
     | 
| 
      
 177 
     | 
    
         
            +
                def full_apply(*argv, &proc)
         
     | 
| 
      
 178 
     | 
    
         
            +
                  argv.each do |obj|
         
     | 
| 
      
 179 
     | 
    
         
            +
                    deep_apply(obj, &proc)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
      
 182 
     | 
    
         
            +
                
         
     | 
| 
      
 183 
     | 
    
         
            +
                def deep_apply(obj, &proc)
         
     | 
| 
      
 184 
     | 
    
         
            +
                  case obj
         
     | 
| 
      
 185 
     | 
    
         
            +
                  when Hash
         
     | 
| 
      
 186 
     | 
    
         
            +
                    obj.each_pair do |key, value|
         
     | 
| 
      
 187 
     | 
    
         
            +
                      obj[key] = deep_apply(value, &proc)
         
     | 
| 
      
 188 
     | 
    
         
            +
                    end
         
     | 
| 
      
 189 
     | 
    
         
            +
                    obj
         
     | 
| 
      
 190 
     | 
    
         
            +
                  when Array
         
     | 
| 
      
 191 
     | 
    
         
            +
                    obj.collect!{ |value| deep_apply(value, &proc)}
         
     | 
| 
      
 192 
     | 
    
         
            +
                  when NilClass, TrueClass, FalseClass, Tempfile, StringIO
         
     | 
| 
      
 193 
     | 
    
         
            +
                    obj
         
     | 
| 
      
 194 
     | 
    
         
            +
                  else
         
     | 
| 
      
 195 
     | 
    
         
            +
                    proc.call(obj)
         
     | 
| 
      
 196 
     | 
    
         
            +
                  end
         
     | 
| 
      
 197 
     | 
    
         
            +
                end
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                def apply_incoming?(env); true; end
         
     | 
| 
      
 200 
     | 
    
         
            +
                def apply_outgoing?(status, headers, body)
         
     | 
| 
      
 201 
     | 
    
         
            +
                  headers['Content-Type'] !~ /^(.+?)(?:;|$)/
         
     | 
| 
      
 202 
     | 
    
         
            +
                  [nil, "text/html", "application/xhtml+xml"].include?($1)
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
              end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
              
         
     | 
| 
      
 208 
     | 
    
         
            +
              class SjisFilter < Filter
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                private
         
     | 
| 
      
 211 
     | 
    
         
            +
                def to_internal(env)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  request = Rack::Request.new(env)
         
     | 
| 
      
 213 
     | 
    
         
            +
                  
         
     | 
| 
      
 214 
     | 
    
         
            +
                  # 最低でも1回呼んでないと query_string, form_hash等が未設定
         
     | 
| 
      
 215 
     | 
    
         
            +
                  request.params
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                  # 同一オブジェクトが両方に入ってたりして二重にかかることがあるので
         
     | 
| 
      
 218 
     | 
    
         
            +
                  converted_objects = []
         
     | 
| 
      
 219 
     | 
    
         
            +
                  converter = lambda { |value|
         
     | 
| 
      
 220 
     | 
    
         
            +
                    unless converted_objects.include?(value)
         
     | 
| 
      
 221 
     | 
    
         
            +
                      value = NKF.nkf('-m0 -x -Sw', value)
         
     | 
| 
      
 222 
     | 
    
         
            +
                      converted_objects << value
         
     | 
| 
      
 223 
     | 
    
         
            +
                    end
         
     | 
| 
      
 224 
     | 
    
         
            +
                    value
         
     | 
| 
      
 225 
     | 
    
         
            +
                  }
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                  full_apply(request.env["rack.request.query_hash"],
         
     | 
| 
      
 228 
     | 
    
         
            +
                             request.env["rack.request.form_hash"],
         
     | 
| 
      
 229 
     | 
    
         
            +
                             &converter)
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  request.env
         
     | 
| 
      
 232 
     | 
    
         
            +
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
                
         
     | 
| 
      
 234 
     | 
    
         
            +
                def to_external(status, headers, body)
         
     | 
| 
      
 235 
     | 
    
         
            +
                  if body.is_a?(Array)
         
     | 
| 
      
 236 
     | 
    
         
            +
                    body = body.collect do |str|
         
     | 
| 
      
 237 
     | 
    
         
            +
                      NKF.nkf('-m0 -x -Ws', str)
         
     | 
| 
      
 238 
     | 
    
         
            +
                    end
         
     | 
| 
      
 239 
     | 
    
         
            +
                  else
         
     | 
| 
      
 240 
     | 
    
         
            +
                    body = NKF.nkf('-m0 -x -Ws', body)
         
     | 
| 
      
 241 
     | 
    
         
            +
                  end
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                  if headers['Content-Type']
         
     | 
| 
      
 244 
     | 
    
         
            +
                    case headers['Content-Type']
         
     | 
| 
      
 245 
     | 
    
         
            +
                    when /charset=[\w\-]+/i
         
     | 
| 
      
 246 
     | 
    
         
            +
                      headers['Content-Type'].sub!(/charset=[\w\-]+/, 'charset=shift_jis')
         
     | 
| 
      
 247 
     | 
    
         
            +
                    else
         
     | 
| 
      
 248 
     | 
    
         
            +
                      headers['Content-Type'] << "; charset=shift_jis"
         
     | 
| 
      
 249 
     | 
    
         
            +
                    end
         
     | 
| 
      
 250 
     | 
    
         
            +
                  end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                  content = (body.is_a?(Array) ? body[0] : body).to_s
         
     | 
| 
      
 253 
     | 
    
         
            +
                  headers['Content-Length'] = (content.respond_to?(:bytesize) ? content.bytesize : content.size).to_s if headers.member?('Content-Length')
         
     | 
| 
      
 254 
     | 
    
         
            +
                
         
     | 
| 
      
 255 
     | 
    
         
            +
                  [status, headers, body]
         
     | 
| 
      
 256 
     | 
    
         
            +
                end
         
     | 
| 
      
 257 
     | 
    
         
            +
                
         
     | 
| 
      
 258 
     | 
    
         
            +
              end
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
            end
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
            require 'rack/ketai/carrier/emoji/emojidata'
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,153 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'scanf'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Rack
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Ketai
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Carrier
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class Au < Abstract
         
     | 
| 
      
 8 
     | 
    
         
            +
                    autoload :CIDRS, 'rack/ketai/carrier/cidrs/au'
         
     | 
| 
      
 9 
     | 
    
         
            +
                    autoload :SPECS, 'rack/ketai/carrier/specs/au'
         
     | 
| 
      
 10 
     | 
    
         
            +
                    
         
     | 
| 
      
 11 
     | 
    
         
            +
                    USER_AGENT_REGEXP = /^(?:KDDI|UP.Browser\/.+?)-(.+?) /
         
     | 
| 
      
 12 
     | 
    
         
            +
              
         
     | 
| 
      
 13 
     | 
    
         
            +
                    class Filter < ::Rack::Ketai::Carrier::Abstract::SjisFilter
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                      # 絵文字コード -> 絵文字ID 対応表から、絵文字コード検出用の正規表現をつくる
         
     | 
| 
      
 16 
     | 
    
         
            +
                      # 複数の絵文字の組み合わせのものを前におくことで
         
     | 
| 
      
 17 
     | 
    
         
            +
                      # そっちを優先的にマッチさせる
         
     | 
| 
      
 18 
     | 
    
         
            +
                      def Filter.sjis_regexp
         
     | 
| 
      
 19 
     | 
    
         
            +
                        @sjis_regexp ||=
         
     | 
| 
      
 20 
     | 
    
         
            +
                          if RUBY_VERSION >= '1.9.1'
         
     | 
| 
      
 21 
     | 
    
         
            +
                            codes = EMOJI_TO_EMOJIID.keys.sort_by{ |codes| - codes.size }.collect{ |sjis| Regexp.escape(sjis)}
         
     | 
| 
      
 22 
     | 
    
         
            +
                            Regexp.new(codes.join('|'), nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                          else
         
     | 
| 
      
 24 
     | 
    
         
            +
                            codes = EMOJI_TO_EMOJIID.keys.sort_by{ |codes| - codes.size }.collect{ |sjis| Regexp.escape(sjis, 's') }
         
     | 
| 
      
 25 
     | 
    
         
            +
                            Regexp.new(codes.join('|'), nil, 's')
         
     | 
| 
      
 26 
     | 
    
         
            +
                          end
         
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                      private
         
     | 
| 
      
 30 
     | 
    
         
            +
                      def to_internal(env)
         
     | 
| 
      
 31 
     | 
    
         
            +
                        # au SJISバイナリ -> 絵文字ID表記
         
     | 
| 
      
 32 
     | 
    
         
            +
                        request = Rack::Request.new(env)
         
     | 
| 
      
 33 
     | 
    
         
            +
                        
         
     | 
| 
      
 34 
     | 
    
         
            +
                        request.params  # 最低でも1回呼んでないと query_stringが未設定
         
     | 
| 
      
 35 
     | 
    
         
            +
                        
         
     | 
| 
      
 36 
     | 
    
         
            +
                        converter = lambda do |value|
         
     | 
| 
      
 37 
     | 
    
         
            +
                          value.force_encoding('Shift_JIS') if value.respond_to?(:force_encoding)
         
     | 
| 
      
 38 
     | 
    
         
            +
                          value.gsub(Filter.sjis_regexp) do |match|
         
     | 
| 
      
 39 
     | 
    
         
            +
                            format("[e:%03X]", EMOJI_TO_EMOJIID[match])
         
     | 
| 
      
 40 
     | 
    
         
            +
                          end
         
     | 
| 
      
 41 
     | 
    
         
            +
                        end
         
     | 
| 
      
 42 
     | 
    
         
            +
                        deep_apply(request.env["rack.request.query_hash"], &converter)
         
     | 
| 
      
 43 
     | 
    
         
            +
                        deep_apply(request.env["rack.request.form_hash"], &converter)
         
     | 
| 
      
 44 
     | 
    
         
            +
                        
         
     | 
| 
      
 45 
     | 
    
         
            +
                        # 文字コード変換
         
     | 
| 
      
 46 
     | 
    
         
            +
                        super(request.env)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
                      
         
     | 
| 
      
 49 
     | 
    
         
            +
                      def to_external(status, headers, body)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        status, headers, body = super
         
     | 
| 
      
 51 
     | 
    
         
            +
                        
         
     | 
| 
      
 52 
     | 
    
         
            +
                        return [status, headers, body] unless body[0]
         
     | 
| 
      
 53 
     | 
    
         
            +
                        
         
     | 
| 
      
 54 
     | 
    
         
            +
                        body = body.collect do |str|
         
     | 
| 
      
 55 
     | 
    
         
            +
                          str.gsub(/\[e:([0-9A-F]{3})\]/) do |match|
         
     | 
| 
      
 56 
     | 
    
         
            +
                            emojiid = $1.scanf('%X').first
         
     | 
| 
      
 57 
     | 
    
         
            +
                            sjis = EMOJIID_TO_EMOJI[emojiid]
         
     | 
| 
      
 58 
     | 
    
         
            +
                            if sjis
         
     | 
| 
      
 59 
     | 
    
         
            +
                              # 絵文字があるので差替え
         
     | 
| 
      
 60 
     | 
    
         
            +
                              sjis
         
     | 
| 
      
 61 
     | 
    
         
            +
                            else
         
     | 
| 
      
 62 
     | 
    
         
            +
                              # 絵文字がないので代替文字列
         
     | 
| 
      
 63 
     | 
    
         
            +
                              emoji_data = EMOJI_DATA[emojiid]
         
     | 
| 
      
 64 
     | 
    
         
            +
                              NKF.nkf('-Ws', (emoji_data[:fallback] || emoji_data[:name] || '〓'))
         
     | 
| 
      
 65 
     | 
    
         
            +
                            end
         
     | 
| 
      
 66 
     | 
    
         
            +
                          end
         
     | 
| 
      
 67 
     | 
    
         
            +
                        end
         
     | 
| 
      
 68 
     | 
    
         
            +
                        
         
     | 
| 
      
 69 
     | 
    
         
            +
                        content = (body.is_a?(Array) ? body[0] : body).to_s
         
     | 
| 
      
 70 
     | 
    
         
            +
                        headers['Content-Length'] = (content.respond_to?(:bytesize) ? content.bytesize : content.size).to_s if headers.member?('Content-Length')
         
     | 
| 
      
 71 
     | 
    
         
            +
                        
         
     | 
| 
      
 72 
     | 
    
         
            +
                        [status, headers, body]
         
     | 
| 
      
 73 
     | 
    
         
            +
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    
         
     | 
| 
      
 76 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 77 
     | 
    
         
            +
                      def filters
         
     | 
| 
      
 78 
     | 
    
         
            +
                        super | [Rack::Ketai::Carrier::Au::Filter]
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    def mobile?
         
     | 
| 
      
 83 
     | 
    
         
            +
                      true
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    def subscriberid
         
     | 
| 
      
 87 
     | 
    
         
            +
                      ezno
         
     | 
| 
      
 88 
     | 
    
         
            +
                    end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                    def ezno
         
     | 
| 
      
 91 
     | 
    
         
            +
                      @ezno ||= @env['HTTP_X_UP_SUBNO'].to_s =~ /^(\w{14}_\w{2}\.ezweb\.ne\.jp)$/ && $1
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 95 
     | 
    
         
            +
                      # UAの最初の - の後ろが略称
         
     | 
| 
      
 96 
     | 
    
         
            +
                      @name ||= @env['HTTP_USER_AGENT'] =~ /^[^\-]+\-(\w+)/ && $1
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                    def display
         
     | 
| 
      
 100 
     | 
    
         
            +
                      return @display if @display
         
     | 
| 
      
 101 
     | 
    
         
            +
                      width = height = colors = nil
         
     | 
| 
      
 102 
     | 
    
         
            +
                      if @env['HTTP_X_UP_DEVCAP_SCREENPIXELS'].to_s =~ /(\d+),(\d+)/
         
     | 
| 
      
 103 
     | 
    
         
            +
                        width = $1.to_i
         
     | 
| 
      
 104 
     | 
    
         
            +
                        height = $2.to_i
         
     | 
| 
      
 105 
     | 
    
         
            +
                      end
         
     | 
| 
      
 106 
     | 
    
         
            +
                      width ||= spec[5]
         
     | 
| 
      
 107 
     | 
    
         
            +
                      height ||= spec[6]
         
     | 
| 
      
 108 
     | 
    
         
            +
                      
         
     | 
| 
      
 109 
     | 
    
         
            +
                      color_depth = (@env['HTTP_X_UP_DEVCAP_SCREENDEPTH'].to_s =~ /^(\d+)/ && $1).to_i
         
     | 
| 
      
 110 
     | 
    
         
            +
                      colors = color_depth > 0 ? 2 ** color_depth : spec[7]
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                      @display = Rack::Ketai::Display.new(:colors => colors,
         
     | 
| 
      
 113 
     | 
    
         
            +
                                                          :width => width,
         
     | 
| 
      
 114 
     | 
    
         
            +
                                                          :height => height)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    # Cookie対応
         
     | 
| 
      
 118 
     | 
    
         
            +
                    # 全機種対応(GW側で保持)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    # SSL接続時はWAP2.0ブラウザ搭載端末でのみ端末に保持したCookieを送出
         
     | 
| 
      
 120 
     | 
    
         
            +
                    # http://www.au.kddi.com/ezfactory/tec/spec/cookie.html
         
     | 
| 
      
 121 
     | 
    
         
            +
                    def supports_cookie?
         
     | 
| 
      
 122 
     | 
    
         
            +
                      is_wap1? && use_ssl? ? false : true
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                    # キャッシュサイズ
         
     | 
| 
      
 126 
     | 
    
         
            +
                    # HTTP_X_UP_DEVCAP_MAX_PDU に入ってくる…が一部古い携帯は入らないらしい
         
     | 
| 
      
 127 
     | 
    
         
            +
                    def cache_size
         
     | 
| 
      
 128 
     | 
    
         
            +
                      @cache_size ||= (val = @env['HTTP_X_UP_DEVCAP_MAX_PDU'].to_i) > 0 ? val : 8220
         
     | 
| 
      
 129 
     | 
    
         
            +
                    end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                    private
         
     | 
| 
      
 132 
     | 
    
         
            +
                    def spec
         
     | 
| 
      
 133 
     | 
    
         
            +
                      @spec ||= SPECS[name] || []
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    def use_ssl?
         
     | 
| 
      
 137 
     | 
    
         
            +
                      @env['HTTPS'].to_s.downcase == 'on' || @env['X_FORWARDED_PROTO'] == 'https'
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                    # WAP1ブラウザではKDDIからはじまらない
         
     | 
| 
      
 141 
     | 
    
         
            +
                    def is_wap1?
         
     | 
| 
      
 142 
     | 
    
         
            +
                      @env['HTTP_USER_AGENT'] !~ /^KDDI\-/
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
            end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
            # 変換テーブル読み込み
         
     | 
| 
      
 151 
     | 
    
         
            +
            require 'rack/ketai/carrier/emoji/ausjisstrtoemojiid'
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            # http://www.au.kddi.com/ezfactory/tec/spec/ezsava_ip.html
         
     | 
| 
      
 3 
     | 
    
         
            +
            # 2010.6.22時点
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Rack::Ketai::Carrier::Au::CIDRS = %w(
         
     | 
| 
      
 6 
     | 
    
         
            +
            210.230.128.224/28
         
     | 
| 
      
 7 
     | 
    
         
            +
            121.111.227.160/27
         
     | 
| 
      
 8 
     | 
    
         
            +
            61.117.1.0/28
         
     | 
| 
      
 9 
     | 
    
         
            +
            219.108.158.0/27
         
     | 
| 
      
 10 
     | 
    
         
            +
            219.125.146.0/28
         
     | 
| 
      
 11 
     | 
    
         
            +
            61.117.2.32/29
         
     | 
| 
      
 12 
     | 
    
         
            +
            61.117.2.40/29
         
     | 
| 
      
 13 
     | 
    
         
            +
            219.108.158.40/29
         
     | 
| 
      
 14 
     | 
    
         
            +
            219.125.148.0/25
         
     | 
| 
      
 15 
     | 
    
         
            +
            222.5.63.0/25
         
     | 
| 
      
 16 
     | 
    
         
            +
            222.5.63.128/25
         
     | 
| 
      
 17 
     | 
    
         
            +
            222.5.62.128/25
         
     | 
| 
      
 18 
     | 
    
         
            +
            59.135.38.128/25
         
     | 
| 
      
 19 
     | 
    
         
            +
            219.108.157.0/25
         
     | 
| 
      
 20 
     | 
    
         
            +
            219.125.145.0/25
         
     | 
| 
      
 21 
     | 
    
         
            +
            121.111.231.0/25
         
     | 
| 
      
 22 
     | 
    
         
            +
            121.111.227.0/25
         
     | 
| 
      
 23 
     | 
    
         
            +
            118.152.214.192/26
         
     | 
| 
      
 24 
     | 
    
         
            +
            118.159.131.0/25
         
     | 
| 
      
 25 
     | 
    
         
            +
            118.159.133.0/25
         
     | 
| 
      
 26 
     | 
    
         
            +
            118.159.132.160/27
         
     | 
| 
      
 27 
     | 
    
         
            +
            111.86.142.0/26
         
     | 
| 
      
 28 
     | 
    
         
            +
            111.86.141.64/26
         
     | 
| 
      
 29 
     | 
    
         
            +
            111.86.141.128/26
         
     | 
| 
      
 30 
     | 
    
         
            +
            111.86.141.192/26
         
     | 
| 
      
 31 
     | 
    
         
            +
            118.159.133.19/26
         
     | 
| 
      
 32 
     | 
    
         
            +
            ).collect{ |cidr| IPAddr.new(cidr) }
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            # http://www.nttdocomo.co.jp/service/imode/make/content/ip/index.html
         
     | 
| 
      
 3 
     | 
    
         
            +
            # 2010.4.19時点
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Rack::Ketai::Carrier::Docomo::CIDRS = %w(
         
     | 
| 
      
 6 
     | 
    
         
            +
            210.153.84.0/24
         
     | 
| 
      
 7 
     | 
    
         
            +
            210.136.161.0/24
         
     | 
| 
      
 8 
     | 
    
         
            +
            210.153.86.0/24
         
     | 
| 
      
 9 
     | 
    
         
            +
            124.146.174.0/24
         
     | 
| 
      
 10 
     | 
    
         
            +
            124.146.175.0/24
         
     | 
| 
      
 11 
     | 
    
         
            +
            202.229.176.0/24
         
     | 
| 
      
 12 
     | 
    
         
            +
            202.229.177.0/24
         
     | 
| 
      
 13 
     | 
    
         
            +
            202.229.178.0/24
         
     | 
| 
      
 14 
     | 
    
         
            +
            ).collect{ |cidr| IPAddr.new(cidr) }
         
     |