forked from jpmobile/jpmobile
/
abstract_mobile.rb
191 lines (165 loc) · 5.35 KB
/
abstract_mobile.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# -*- coding: utf-8 -*-
require 'ipaddr'
module Jpmobile::Mobile
# 携帯電話の抽象クラス。
class AbstractMobile
# メールのデフォルトのcharset
MAIL_CHARSET = "ISO-2022-JP"
def initialize(env, request)
@env = env
@request = request
end
# 対応するuser-agentの正規表現
USER_AGENT_REGEXP = nil
# 対応するメールアドレスの正規表現
MAIL_ADDRESS_REGEXP = nil
# 緯度経度があれば Position のインスタンスを返す。
def position; return nil; end
# 契約者又は端末を識別する文字列があれば返す。
def ident; ident_subscriber || ident_device; end
# 契約者を識別する文字列があれば返す。
def ident_subscriber; nil; end
# 端末を識別する文字列があれば返す。
def ident_device; nil; end
# 当該キャリアのIPアドレス帯域からのアクセスであれば +true+ を返す。
# そうでなければ +false+ を返す。
# IP空間が定義されていない場合は +nil+ を返す。
def self.valid_ip? remote_addr
@ip_list ||= ip_address_class
return false unless @ip_list
@ip_list.valid_ip?(remote_addr)
end
def valid_ip?
@__valid_ip ||= self.class.valid_ip? @request.ip
end
# 画面情報を +Display+ クラスのインスタンスで返す。
def display
@__displlay ||= Jpmobile::Mobile::Terminfo.new(self, @env)
rescue LoadError
puts "display method require jpmobile-terminfo plugin."
end
# クッキーをサポートしているか。
def supports_cookie?
return false
end
# smartphone かどうか
def smart_phone?
false
end
# Jpmobile::Rack::Filter を適用するかどうか
def apply_filter?
true
end
# Jpmobile::Rack::ParamsFilter を適用するかどうか
def apply_params_filter?
true
end
# エンコーディング変換用
def to_internal(str)
str
end
def to_external(str, content_type, charset)
[str, charset]
end
def default_charset
"UTF-8"
end
# for view selector
def variants
return @_variants if @_variants
@_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/}.map do |klass|
klass = klass.to_s.
gsub(/Jpmobile::/, '').
gsub(/AbstractMobile::/, '').
gsub(/Mobile::SmartPhone/, 'smart_phone').
gsub(/::/, '_').
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
gsub(/([a-z\d])([A-Z])/, '\1_\2').
downcase
klass =~ /abstract/ ? "mobile" : klass
end
if @_variants.include?("smart_phone")
@_variants = @_variants.reject{|v| v == "mobile"}.map{|v| v.gsub(/mobile/, "smart_phone")}
end
@_variants
end
# メール送信用
def to_mail_subject(str)
Jpmobile::Util.fold_text(Jpmobile::Emoticon.unicodecr_to_utf8(str)).
map{|text| "=?#{mail_charset}?B?" + [to_mail_encoding(text)].pack('m').strip + "?=" }.
join("\n\s")
end
def to_mail_body(str)
to_mail_encoding(str)
end
def mail_charset(charset = nil)
# (charset.nil? or charset == "") ? self.class::MAIL_CHARSET : charset
self.class::MAIL_CHARSET
end
def to_mail_encoding(str)
str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_PC_EMAIL, false)
Jpmobile::Util.encode(str, mail_charset)
end
def utf8_to_mail_encode(str)
case mail_charset
when /ISO-2022-JP/i
Jpmobile::Util.utf8_to_jis(str)
when /Shift_JIS/i
Jpmobile::Util.utf8_to_sjis(str)
else
str
end
end
def to_mail_internal(str, charset)
str
end
def to_mail_subject_encoded?(str)
str.match(/\=\?#{mail_charset}\?B.+\?\=/i)
end
def to_mail_body_encoded?(str)
Jpmobile::Util.jis?(str)
end
def decode_transfer_encoding(body, charset)
body = Jpmobile::Util.set_encoding(body, charset)
body = to_mail_internal(body, nil)
Jpmobile::Util.force_encode(body, charset, Jpmobile::Util::UTF8)
end
# リクエストがこのクラスに属するか調べる
# メソッド名に関して非常に不安
def self.check_carrier(env)
self::USER_AGENT_REGEXP && env['HTTP_USER_AGENT'] =~ self::USER_AGENT_REGEXP
end
#XXX: lib/jpmobile.rbのautoloadで先に各キャリアの定数を定義しているから動くのです
Jpmobile::Mobile.carriers.each do |carrier|
carrier_class = Jpmobile::Mobile.const_get(carrier)
next if carrier_class == self
define_method "#{carrier.downcase}?" do
self.is_a?(carrier_class)
end
end
def self.carrier(env)
::Jpmobile::Mobile.carriers.each do |const|
c = ::Jpmobile::Mobile.const_get(const)
if c.check_carrier(env)
res = ::Rack::Request.new(env)
return c.new(env, res)
end
end
nil
end
private
# リクエストのパラメータ。
def params
if @request.respond_to? :parameters
@request.parameters
else
@request.params
end
end
#
def self.ip_address_class
eval("::Jpmobile::Mobile::IpAddresses::#{self.to_s.split(/::/).last}").new rescue nil
end
end
end