jpmobile 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,8 @@ end
4
4
 
5
5
  module Jpmobile
6
6
  module Emoticon
7
- GETA = 0x3013
7
+ GETA_CODE = 0x3013
8
+ GETA = [GETA_CODE].pack('U')
8
9
 
9
10
  SJIS_TO_UNICODE = {}
10
11
  SJIS_TO_UNICODE.update(DOCOMO_SJIS_TO_UNICODE)
@@ -32,5 +33,20 @@ module Jpmobile
32
33
 
33
34
  SOFTBANK_SJIS_REGEXP = Regexp.union(*SOFTBANK_SJIS_TO_UNICODE.keys.map{|s| Jpmobile::Util.sjis_regexp(s)}).freeze
34
35
  AU_EMAILJIS_REGEXP = Regexp.union(*AU_EMAILJIS_TO_UNICODE.keys.map{|s| Jpmobile::Util.jis_regexp(s)})
36
+
37
+ # for unicode/google emoticons
38
+ UNICODE_EMOTICONS = (UNICODE_TO_DOCOMO_UNICODE.keys|UNICODE_TO_AU_UNICODE.keys|UNICODE_TO_SOFTBANK_UNICODE.keys).uniq
39
+ GOOGLE_EMOTICONS = (GOOGLE_TO_DOCOMO_UNICODE.keys|GOOGLE_TO_AU_UNICODE.keys|GOOGLE_TO_SOFTBANK_UNICODE.keys).uniq
40
+
41
+ UNICODE_EMOTICON_REGEXP = Regexp.union(*UNICODE_EMOTICONS.map{|x| x.kind_of?(Array) ? x.pack('UU') : [x].pack('U')}).freeze
42
+ GOOGLE_EMOTICON_REGEXP = Regexp.union(*GOOGLE_EMOTICONS.map{|x| x.kind_of?(Array) ? x.pack('UU') : [x].pack('U')}).freeze
43
+
44
+ UNICODE_EMOTICON_TO_CARRIER_EMOTICON = UNICODE_TO_DOCOMO_UNICODE.merge(UNICODE_TO_AU_UNICODE.merge(UNICODE_TO_SOFTBANK_UNICODE))
45
+ GOOGLE_EMOTICON_TO_CARRIER_EMOTICON = GOOGLE_TO_SOFTBANK_UNICODE.merge(GOOGLE_TO_AU_UNICODE.merge(GOOGLE_TO_DOCOMO_UNICODE))
46
+
47
+ CONVERSION_TABLE_TO_UNICODE_EMOTICON = Jpmobile::Util.invert_table(UNICODE_TO_DOCOMO_UNICODE).merge(
48
+ Jpmobile::Util.invert_table(UNICODE_TO_AU_UNICODE).merge(Jpmobile::Util.invert_table(UNICODE_TO_SOFTBANK_UNICODE)))
49
+ CONVERSION_TABLE_TO_GOOGLE_EMOTICON = Jpmobile::Util.invert_table(GOOGLE_TO_SOFTBANK_UNICODE).merge(
50
+ Jpmobile::Util.invert_table(GOOGLE_TO_AU_UNICODE).merge(Jpmobile::Util.invert_table(GOOGLE_TO_DOCOMO_UNICODE)))
35
51
  end
36
52
  end
@@ -80,7 +80,7 @@ module Jpmobile::Mobile
80
80
  def variants
81
81
  return @_variants if @_variants
82
82
 
83
- @_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/}.map do |klass|
83
+ @_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/ && c.to_s !~ /Emoticon/}.map do |klass|
84
84
  klass = klass.to_s.
85
85
  gsub(/Jpmobile::/, '').
86
86
  gsub(/AbstractMobile::/, '').
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class Android < SmartPhone
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /Android/
9
+
10
+ include Jpmobile::Mobile::GoogleEmoticon
9
11
  end
10
12
  end
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class AndroidTablet < Tablet
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = Regexp.union(/(?!Android.+Mobile)Android/, /Android.+SC-01C/)
9
+
10
+ include Jpmobile::Mobile::GoogleEmoticon
9
11
  end
10
12
  end
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ # =BlackBerry
3
+
4
+ module Jpmobile::Mobile
5
+ # ==BlackBerry
6
+ class BlackBerry < SmartPhone
7
+ # 対応するUser-Agentの正規表現
8
+ USER_AGENT_REGEXP = /BlackBerry/
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Jpmobile::Mobile
3
+ module GoogleEmoticon
4
+ # Jpmobile::Rack::Filter を適用する
5
+ def apply_filter?
6
+ Jpmobile.config.smart_phone_emoticon_compatibility
7
+ end
8
+
9
+ # Jpmobile::Rack::ParamsFilter を適用する
10
+ def apply_params_filter?
11
+ Jpmobile.config.smart_phone_emoticon_compatibility
12
+ end
13
+
14
+ # 文字コード変換
15
+ def to_internal(str)
16
+ # Google絵文字を数値参照に変換
17
+ str = Jpmobile::Emoticon.external_to_unicodecr_google(Jpmobile::Util.utf8(str))
18
+ # 数値参照を UTF-8 に変換
19
+ Jpmobile::Emoticon.unicodecr_to_utf8(str)
20
+ end
21
+ def to_external(str, content_type, charset)
22
+ # UTF-8を数値参照に
23
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
24
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_GOOGLE_EMOTICON, false)
25
+
26
+ [str, charset]
27
+ end
28
+ end
29
+ end
@@ -6,5 +6,7 @@ module Jpmobile::Mobile
6
6
  class Ipad < Tablet
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /iPad/
9
+
10
+ include Jpmobile::Mobile::UnicodeEmoticon
9
11
  end
10
12
  end
@@ -7,30 +7,6 @@ module Jpmobile::Mobile
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /iPhone/
9
9
 
10
- # Jpmobile::Rack::Filter を適用する
11
- def apply_filter?
12
- true
13
- end
14
-
15
- # Jpmobile::Rack::ParamsFilter を適用する
16
- def apply_params_filter?
17
- true
18
- end
19
-
20
- # 文字コード変換
21
- def to_internal(str)
22
- # 絵文字を数値参照に変換
23
- str = Jpmobile::Emoticon.external_to_unicodecr_softbank(Jpmobile::Util.utf8(str))
24
- # 数値参照を UTF-8 に変換
25
- Jpmobile::Emoticon.unicodecr_to_utf8(str)
26
- end
27
- def to_external(str, content_type, charset)
28
- # UTF-8を数値参照に
29
- str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
30
- # 数値参照を絵文字コードに変換
31
- str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_SOFTBANK, false)
32
-
33
- [str, charset]
34
- end
10
+ include Jpmobile::Mobile::UnicodeEmoticon
35
11
  end
36
12
  end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Jpmobile::Mobile
3
+ module UnicodeEmoticon
4
+ # Jpmobile::Rack::Filter を適用する
5
+ def apply_filter?
6
+ Jpmobile.config.smart_phone_emoticon_compatibility
7
+ end
8
+
9
+ # Jpmobile::Rack::ParamsFilter を適用する
10
+ def apply_params_filter?
11
+ Jpmobile.config.smart_phone_emoticon_compatibility
12
+ end
13
+
14
+ # 文字コード変換
15
+ def to_internal(str)
16
+ if unicode_emoticon?
17
+ # Unicode絵文字を数値参照に変換
18
+ str = Jpmobile::Emoticon.external_to_unicodecr_unicode60(Jpmobile::Util.utf8(str))
19
+ else
20
+ # SoftBank絵文字を数値参照に変換
21
+ str = Jpmobile::Emoticon.external_to_unicodecr_softbank(Jpmobile::Util.utf8(str))
22
+ end
23
+ # 数値参照を UTF-8 に変換
24
+ Jpmobile::Emoticon.unicodecr_to_utf8(str)
25
+ end
26
+ def to_external(str, content_type, charset)
27
+ # UTF-8を数値参照に
28
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
29
+ if unicode_emoticon?
30
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_UNICODE_EMOTICON, false)
31
+ else
32
+ # 数値参照を絵文字コードに変換
33
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_SOFTBANK, false)
34
+ end
35
+
36
+ [str, charset]
37
+ end
38
+
39
+ def unicode_emoticon?
40
+ @request.user_agent.match(/ OS 5_/)
41
+ end
42
+ end
43
+ end
data/lib/jpmobile/rack.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'rack/utils'
3
+ require 'singleton'
3
4
 
4
5
  module Jpmobile
5
6
  module Rack
@@ -12,10 +13,14 @@ module Jpmobile
12
13
  end
13
14
 
14
15
  class Configuration
16
+ include Singleton
17
+
15
18
  attr_accessor :form_accept_charset_conversion
19
+ attr_accessor :smart_phone_emoticon_compatibility
16
20
 
17
21
  def initialize
18
- @form_accept_charset_conversion = false
22
+ @form_accept_charset_conversion = false
23
+ @smart_phone_emoticon_compatibility = false
19
24
  end
20
25
 
21
26
  def mobile_filter
@@ -19,7 +19,7 @@ ActiveSupport.on_load(:before_configuration) do
19
19
  class Application
20
20
  class Configuration
21
21
  def jpmobile
22
- @jpmobile ||= ::Jpmobile::Configuration.new
22
+ @jpmobile ||= ::Jpmobile.config
23
23
  end
24
24
  end
25
25
  end
data/lib/jpmobile/util.rb CHANGED
@@ -187,7 +187,7 @@ module Jpmobile
187
187
  end
188
188
 
189
189
  def jis_string_regexp
190
- Regexp.compile(Regexp.escape(ascii_8bit("\x1b\x24\x42")) + "(.+)" + Regexp.escape(ascii_8bit("\x1b\x28\x42")))
190
+ Regexp.compile(Regexp.escape(ascii_8bit("\x1b\x24\x42")) + "(.+?)" + Regexp.escape(ascii_8bit("\x1b\x28\x42")))
191
191
  end
192
192
 
193
193
  def encode(str, charset)
@@ -379,5 +379,19 @@ module Jpmobile
379
379
  end
380
380
 
381
381
  end
382
+
383
+ def invert_table(hash)
384
+ result = {}
385
+ hash.keys.each do |key|
386
+ if result[hash[key]]
387
+ if !key.kind_of?(Array) and !result[hash[key]].kind_of?(Array) and result[hash[key]] > key
388
+ result[hash[key]] = key
389
+ end
390
+ else
391
+ result[hash[key]] = key
392
+ end
393
+ end
394
+ result
395
+ end
382
396
  end
383
397
  end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../rack_helper.rb')
3
+
4
+ describe Jpmobile::Rack::MobileCarrier, "Windows Phone" do
5
+ include Rack::Test::Methods
6
+
7
+ context "端末種別で" do
8
+ it "BlackBerryを判別できること" do
9
+ res = Rack::MockRequest.env_for(
10
+ 'http://jpmobile-rails.org/',
11
+ 'HTTP_USER_AGENT' => 'BlackBerry9000/4.6.0.224 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/220')
12
+ env = Jpmobile::Rack::MobileCarrier.new(UnitApplication.new).call(res)[1]
13
+
14
+ env['rack.jpmobile'].class.should == Jpmobile::Mobile::BlackBerry
15
+ env['rack.jpmobile'].position.should be_nil
16
+ env['rack.jpmobile'].smart_phone?.should be_true
17
+ env['rack.jpmobile'].supports_cookie?.should be_true
18
+ end
19
+ end
20
+ end
@@ -7,6 +7,8 @@ describe "絵文字が" do
7
7
  include Jpmobile::Util
8
8
 
9
9
  before(:each) do
10
+ Jpmobile.config.smart_phone_emoticon_compatibility = true
11
+
10
12
  @docomo_cr = "&#xE63E;";
11
13
  @docomo_utf8 = [0xe63e].pack("U")
12
14
  @docomo_docomopoint = "&#xE6D5;"
@@ -271,4 +273,169 @@ describe "絵文字が" do
271
273
  response_body(res).should == [0xe04a].pack('U')
272
274
  end
273
275
  end
276
+
277
+ context 'for iPhone' do
278
+ context 'lower iOS 4' do
279
+ before(:each) do
280
+ @res = Rack::MockRequest.env_for(
281
+ "/",
282
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
283
+ 'Content-Type' => 'text/html; charset=utf-8')
284
+ end
285
+
286
+ it 'should convert Softbank emoticon' do
287
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@softbank_cr))).call(@res)[2]
288
+ response_body(response).should == [0xe04a].pack('U')
289
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@softbank_utf8))).call(@res)[2]
290
+ response_body(response).should == [0xe04a].pack('U')
291
+ end
292
+
293
+ it "converts query parameters" do
294
+ query_string = "q=" + URI.encode([0xe04A].pack("U"))
295
+
296
+ res = Rack::MockRequest.env_for(
297
+ "/?#{query_string}",
298
+ "REQUEST_METHOD" => "GET",
299
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
300
+ 'Content-Type' => 'text/html; charset=utf-8')
301
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
302
+ req = Rack::Request.new(res[1])
303
+ req.params['q'].should == [0xf04a].pack("U")
304
+ response_body(res).should == [0xe04a].pack('U')
305
+ end
306
+
307
+ it 'should not convert 〓' do
308
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
309
+ response_body(response).should == '〓'
310
+ end
311
+ end
312
+
313
+ context 'upper iOS 5' do
314
+ before(:each) do
315
+ @res = Rack::MockRequest.env_for(
316
+ "/",
317
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Safari/7534.48.3",
318
+ 'Content-Type' => 'text/html; charset=utf-8')
319
+ @unicode_single = "\342\230\200"
320
+ @unicode_multi = "\342\233\205"
321
+ end
322
+
323
+ it "should convert Unicode emoticon" do
324
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@unicode_single))).call(@res)[2]
325
+ response_body(response).should == [0x2600].pack('U*')
326
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@unicode_multi))).call(@res)[2]
327
+ response_body(response).should == [0x26C5].pack('U*')
328
+ end
329
+
330
+ it "converts query parameters" do
331
+ query_string = "q=" + URI.encode(@unicode_multi)
332
+
333
+ res = Rack::MockRequest.env_for(
334
+ "/?#{query_string}",
335
+ "REQUEST_METHOD" => "GET",
336
+ 'HTTP_USER_AGENT' => "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; ja-jp) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7",
337
+ 'Content-Type' => 'text/html; charset=utf-8')
338
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
339
+ req = Rack::Request.new(res[1])
340
+ req.params['q'].should == [0x26C5].pack("U")
341
+ response_body(res).should == [0x26C5].pack('U')
342
+ end
343
+
344
+ it 'should not convert 〓' do
345
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
346
+ response_body(response).should == '〓'
347
+ end
348
+ end
349
+ end
350
+
351
+ context 'for Android' do
352
+ before(:each) do
353
+ @google_single = "\363\276\200\200"
354
+ @google_multi = "\363\276\200\217"
355
+ end
356
+
357
+ context 'mobile' do
358
+ before(:each) do
359
+ @res = Rack::MockRequest.env_for(
360
+ "/",
361
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; SonyEriccsonSO-01B Build/R1EA018) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1',
362
+ 'Content-Type' => 'text/html; charset=utf-8')
363
+ end
364
+
365
+ it "should convert Google emoticon" do
366
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_single))).call(@res)[2]
367
+ response_body(response).should == [0xFE000].pack('U*')
368
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_multi))).call(@res)[2]
369
+ response_body(response).should == [0xFE00F].pack('U*')
370
+ end
371
+
372
+ it "converts query parameters irreversibly" do
373
+ query_string = "q=" + URI.encode(@google_multi)
374
+
375
+ res = Rack::MockRequest.env_for(
376
+ "/?#{query_string}",
377
+ "REQUEST_METHOD" => "GET",
378
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; SonyEriccsonSO-01B Build/R1EA018) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1',
379
+ 'Content-Type' => 'text/html; charset=utf-8')
380
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
381
+ req = Rack::Request.new(res[1])
382
+ req.params['q'].should == [0xe63e, 0xe63f].pack("U*")
383
+ response_body(res).should == [0xfe000, 0xfe001].pack("U*")
384
+ end
385
+
386
+ it 'should not convert 〓' do
387
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
388
+ response_body(response).should == '〓'
389
+ end
390
+ end
391
+
392
+ context 'tablet' do
393
+ before(:each) do
394
+ @res = Rack::MockRequest.env_for(
395
+ "/",
396
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
397
+ 'Content-Type' => 'text/html; charset=utf-8')
398
+ end
399
+
400
+ it "should convert Google emoticon" do
401
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_single))).call(@res)[2]
402
+ response_body(response).should == [0xFE000].pack('U*')
403
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new(@google_multi))).call(@res)[2]
404
+ response_body(response).should == [0xFE00F].pack('U*')
405
+ end
406
+
407
+ it "converts query parameters irreversibly" do
408
+ query_string = "q=" + URI.encode(@google_multi)
409
+
410
+ res = Rack::MockRequest.env_for(
411
+ "/?#{query_string}",
412
+ "REQUEST_METHOD" => "GET",
413
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
414
+ 'Content-Type' => 'text/html; charset=utf-8')
415
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
416
+ req = Rack::Request.new(res[1])
417
+ req.params['q'].should == [0xe63e, 0xe63f].pack("U*")
418
+ response_body(res).should == [0xfe000, 0xfe001].pack("U*")
419
+ end
420
+
421
+ it 'should not convert 〓' do
422
+ response = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::Filter.new(UnitApplication.new('〓'))).call(@res)[2]
423
+ response_body(response).should == '〓'
424
+ end
425
+
426
+ it 'should convert unsupported emoticon to "〓"' do
427
+ query_string = "q=" + URI.encode("\xF3\xBE\x93\xA4")
428
+
429
+ res = Rack::MockRequest.env_for(
430
+ "/?#{query_string}",
431
+ "REQUEST_METHOD" => "GET",
432
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Linux; U; Android 2.2; ja-jp; SC-01C Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
433
+ 'Content-Type' => 'text/html; charset=utf-8')
434
+ res = Jpmobile::Rack::MobileCarrier.new(Jpmobile::Rack::ParamsFilter.new(Jpmobile::Rack::Filter.new(RenderParamApp.new))).call(res)
435
+ req = Rack::Request.new(res[1])
436
+ req.params['q'].should == '〓'
437
+ response_body(res).should == '〓'
438
+ end
439
+ end
440
+ end
274
441
  end