jpmobile 0.1.6 → 1.0.0.pre

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.
Files changed (73) hide show
  1. data/README +0 -0
  2. data/README.rdoc +58 -29
  3. data/Rakefile +1 -1
  4. data/VERSION.yml +4 -4
  5. data/lib/jpmobile.rb +3 -0
  6. data/lib/jpmobile/email.rb +17 -2
  7. data/lib/jpmobile/emoticon.rb +87 -23
  8. data/lib/jpmobile/emoticon/au.rb +644 -0
  9. data/lib/jpmobile/emoticon/softbank.rb +488 -0
  10. data/lib/jpmobile/emoticon/z_combine.rb +16 -13
  11. data/lib/jpmobile/hook_action_controller.rb +1 -13
  12. data/lib/jpmobile/hook_action_view.rb +3 -62
  13. data/lib/jpmobile/mail.rb +316 -0
  14. data/lib/jpmobile/mailer.rb +31 -0
  15. data/lib/jpmobile/mobile/abstract_mobile.rb +66 -0
  16. data/lib/jpmobile/mobile/au.rb +25 -2
  17. data/lib/jpmobile/mobile/docomo.rb +23 -1
  18. data/lib/jpmobile/mobile/emobile.rb +1 -1
  19. data/lib/jpmobile/mobile/softbank.rb +33 -1
  20. data/lib/jpmobile/mobile/vodafone.rb +1 -1
  21. data/lib/jpmobile/mobile/willcom.rb +1 -1
  22. data/lib/jpmobile/path_set.rb +40 -0
  23. data/lib/jpmobile/rails.rb +24 -0
  24. data/lib/jpmobile/resolver.rb +38 -0
  25. data/lib/jpmobile/util.rb +223 -14
  26. data/lib/tasks/jpmobile_tasks.rake +41 -48
  27. data/spec/rack/jpmobile/emoticon_spec.rb +3 -8
  28. data/spec/rack/jpmobile/filter_spec.rb +1 -1
  29. data/spec/rack/jpmobile/params_filter_spec.rb +4 -4
  30. data/spec/rack_helper.rb +5 -9
  31. data/spec/unit/detect_by_email_spec.rb +29 -0
  32. data/spec/unit/emoticon_spec.rb +90 -0
  33. data/spec/unit/encoding_spec.rb +102 -0
  34. data/spec/unit/mail_spec.rb +117 -0
  35. data/spec/unit/receive_mail_spec.rb +289 -0
  36. data/spec/unit/spec_helper.rb +8 -0
  37. data/spec/unit/util_spec.rb +5 -0
  38. data/test/rails/overrides/app/controllers/application_controller.rb +3 -2
  39. data/test/rails/overrides/app/controllers/template_path_controller.rb +8 -0
  40. data/test/rails/overrides/app/models/mobile_mailer.rb +19 -0
  41. data/test/rails/overrides/app/models/normal_mailer.rb +9 -0
  42. data/test/rails/overrides/spec/models/mobile_mailer_spec.rb +737 -0
  43. data/test/rails/overrides/spec/models/normal_mailer_spec.rb +34 -0
  44. data/test/rails/overrides/spec/requests/template_path_spec.rb +13 -7
  45. data/test/rails/overrides/spec/spec_helper.rb +6 -0
  46. data/test/rails/rails_root/app/controllers/application_controller.rb +3 -2
  47. data/test/rails/rails_root/app/controllers/template_path_controller.rb +8 -0
  48. data/test/rails/rails_root/app/models/mobile_mailer.rb +2 -1
  49. data/test/rails/rails_root/app/models/normal_mailer.rb +9 -0
  50. data/test/rails/rails_root/config/initializers/secret_token.rb +1 -1
  51. data/test/rails/rails_root/spec/models/mobile_mailer_spec.rb +73 -80
  52. data/test/rails/rails_root/spec/models/normal_mailer_spec.rb +34 -0
  53. data/test/rails/rails_root/spec/requests/template_path_spec.rb +13 -7
  54. data/test/rails/rails_root/spec/spec_helper.rb +1 -1
  55. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile.rb +2 -1
  56. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/emoticon.rb +7 -5
  57. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/hook_action_controller.rb +1 -13
  58. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/hook_action_view.rb +3 -62
  59. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mail.rb +162 -111
  60. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mailer.rb +31 -0
  61. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mobile/abstract_mobile.rb +34 -3
  62. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mobile/au.rb +2 -5
  63. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mobile/docomo.rb +4 -5
  64. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/mobile/softbank.rb +7 -8
  65. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/path_set.rb +40 -0
  66. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/rack/params_filter.rb +1 -1
  67. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/rails.rb +24 -0
  68. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/resolver.rb +38 -0
  69. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/util.rb +33 -23
  70. metadata +43 -14
  71. data/test/legacy/emoticon_test.rb +0 -63
  72. data/test/legacy/helper.rb +0 -8
  73. data/test/rails/rails_root/vendor/plugins/jpmobile/lib/jpmobile/hook_action_mailer.rb +0 -22
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'jpmobile/mail'
3
+
4
+ module Jpmobile
5
+ module Mailer
6
+ class Base < ActionMailer::Base
7
+ self._view_paths = self._view_paths.dup
8
+ self.view_paths.unshift(Jpmobile::Resolver.new(File.join(::Rails.root, "app/views")))
9
+
10
+ def mail(headers={}, &block)
11
+ tos = headers[:to].split(/,/)
12
+
13
+ @mobile = if tos.size == 1
14
+ # for mobile
15
+ (Jpmobile::Email.detect(tos.first) || Jpmobile::Mobile::AbstractMobile).new(nil, nil)
16
+ else
17
+ # for multi to addresses
18
+ Jpmobile::Mobile::AbstractMobile.new(nil, nil)
19
+ end
20
+ self.lookup_context.mobile = @mobile.variants
21
+
22
+ m = super(headers, &block)
23
+
24
+ m.mobile = @mobile
25
+ m.charset = @mobile.mail_charset
26
+
27
+ m
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,9 @@ require 'ipaddr'
4
4
  module Jpmobile::Mobile
5
5
  # 携帯電話の抽象クラス。
6
6
  class AbstractMobile
7
+ # メールのデフォルトのcharset
8
+ MAIL_CHARSET = "ISO-2022-JP"
9
+
7
10
  def initialize(env, request)
8
11
  @env = env
9
12
  @request = request
@@ -65,6 +68,69 @@ module Jpmobile::Mobile
65
68
  def default_charset
66
69
  "UTF-8"
67
70
  end
71
+
72
+ # for view selector
73
+ def variants
74
+ return @_variants if @_variants
75
+
76
+ @_variants = self.class.ancestors.select {|c| c.to_s =~ /^Jpmobile/}.map do |klass|
77
+ klass = klass.to_s.
78
+ gsub(/Jpmobile::/, '').
79
+ gsub(/AbstractMobile::/, '').
80
+ gsub(/Mobile::SmartPhone/, 'smart_phone').
81
+ gsub(/::/, '_').
82
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
83
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
84
+ downcase
85
+ klass =~ /abstract/ ? "mobile" : klass
86
+ end
87
+
88
+ if @_variants.include?("smart_phone")
89
+ @_variants = @_variants.reject{|v| v == "mobile"}.map{|v| v.gsub(/mobile/, "smart_phone")}
90
+ end
91
+
92
+ @_variants
93
+ end
94
+
95
+ # メール送信用
96
+ def to_mail_subject(str)
97
+ "=?#{mail_charset}?B?" + [to_mail_encoding(str)].pack('m').strip + "?="
98
+ end
99
+ def to_mail_body(str)
100
+ to_mail_encoding(str)
101
+ end
102
+ def mail_charset(charset = nil)
103
+ (charset.nil? or charset == "") ? self.class::MAIL_CHARSET : charset
104
+ end
105
+ def to_mail_encoding(str)
106
+ str = Jpmobile::Emoticon.unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_PC_EMAIL, false)
107
+ Jpmobile::Util.encode(str, mail_charset)
108
+ end
109
+ def utf8_to_mail_encode(str)
110
+ case mail_charset
111
+ when /ISO-2022-JP/i
112
+ Jpmobile::Util.utf8_to_jis(str)
113
+ when /Shift_JIS/i
114
+ Jpmobile::Util.utf8_to_sjis(str)
115
+ else
116
+ str
117
+ end
118
+ end
119
+ def to_mail_internal(str, charset)
120
+ str
121
+ end
122
+ def to_mail_subject_encoded?(str)
123
+ str.match(/\=\?#{mail_charset}\?B.+\?\=/i)
124
+ end
125
+ def to_mail_body_encoded?(str)
126
+ Jpmobile::Util.jis?(str)
127
+ end
128
+ def decode_transfer_encoding(body, charset)
129
+ body = Jpmobile::Util.set_encoding(body, charset)
130
+ body = to_mail_internal(body, nil)
131
+ Jpmobile::Util.force_encode(body, charset, Jpmobile::Util::UTF8)
132
+ end
133
+
68
134
  # リクエストがこのクラスに属するか調べる
69
135
  # メソッド名に関して非常に不安
70
136
  def self.check_carrier(env)
@@ -9,7 +9,7 @@ module Jpmobile::Mobile
9
9
  # User-Agent文字列中に "UP.Browser" を含むVodafoneの端末があるので注意が必要
10
10
  USER_AGENT_REGEXP = /^(?:KDDI|UP.Browser\/.+?)-(.+?) /
11
11
  # 対応するメールアドレスの正規表現
12
- MAIL_ADDRESS_REGEXP = /^.+@ezweb\.ne\.jp$/
12
+ MAIL_ADDRESS_REGEXP = /.+@ezweb\.ne\.jp/
13
13
  # 簡易位置情報取得に対応していないデバイスID
14
14
  # http://www.au.kddi.com/ezfactory/tec/spec/eznavi.html
15
15
  LOCATION_UNSUPPORTED_DEVICE_ID = ["PT21", "TS25", "KCTE", "TST9", "KCU1", "SYT5", "KCTD", "TST8", "TST7", "KCTC", "SYT4", "KCTB", "KCTA", "TST6", "KCT9", "TST5", "TST4", "KCT8", "SYT3", "KCT7", "MIT1", "MAT3", "KCT6", "TST3", "KCT5", "KCT4", "SYT2", "MAT1", "MAT2", "TST2", "KCT3", "KCT2", "KCT1", "TST1", "SYT1"]
@@ -86,7 +86,6 @@ module Jpmobile::Mobile
86
86
  str = Jpmobile::Util.sjis_to_utf8(str)
87
87
  # 数値参照を UTF-8 に変換
88
88
  Jpmobile::Emoticon::unicodecr_to_utf8(str)
89
- # 半角->全角変換
90
89
  end
91
90
  def to_external(str, content_type, charset)
92
91
  # UTF-8を数値参照に
@@ -104,5 +103,29 @@ module Jpmobile::Mobile
104
103
  def default_charset
105
104
  "Shift_JIS"
106
105
  end
106
+
107
+ # メール送信用
108
+ def to_mail_subject(str)
109
+ "=?#{mail_charset}?B?" + [to_mail_encoding(str)].pack('m').strip + "?="
110
+ end
111
+ def to_mail_body(str)
112
+ to_mail_encoding(str)
113
+ end
114
+
115
+ def to_mail_internal(str, charset)
116
+ if Jpmobile::Util.jis?(str) or Jpmobile::Util.ascii_8bit?(str) or charset == mail_charset
117
+ # 絵文字を数値参照に変換
118
+ str = Jpmobile::Emoticon.external_to_unicodecr_au_mail(Jpmobile::Util.jis(str))
119
+ str = Jpmobile::Util.jis_to_utf8(Jpmobile::Util.jis(str))
120
+ end
121
+ str
122
+ end
123
+
124
+ private
125
+ def to_mail_encoding(str)
126
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
127
+ str = Jpmobile::Util.utf8_to_jis(str)
128
+ Jpmobile::Util.jis(Jpmobile::Emoticon.unicodecr_to_au_email(str))
129
+ end
107
130
  end
108
131
  end
@@ -7,7 +7,9 @@ module Jpmobile::Mobile
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /^DoCoMo/
9
9
  # 対応するメールアドレスの正規表現
10
- MAIL_ADDRESS_REGEXP = /^.+@docomo\.ne\.jp$/
10
+ MAIL_ADDRESS_REGEXP = /.+@docomo\.ne\.jp/
11
+ # メールのデフォルトのcharset
12
+ MAIL_CHARSET = "Shift_JIS"
11
13
 
12
14
  # オープンiエリアがあればエリアコードを +String+ で返す。無ければ +nil+ を返す。
13
15
  def areacode
@@ -94,6 +96,26 @@ module Jpmobile::Mobile
94
96
  "Shift_JIS"
95
97
  end
96
98
 
99
+ # メール送信用
100
+ def to_mail_subject(str)
101
+ str = to_external(str, nil, nil).first
102
+ "=?#{mail_charset}?B?" + [str].pack('m').strip + "?="
103
+ end
104
+ def to_mail_body(str)
105
+ to_external(str, nil, nil).first
106
+ end
107
+ def to_mail_internal(str, charset)
108
+ if Jpmobile::Util.shift_jis?(str) or Jpmobile::Util.ascii_8bit?(str) or charset == mail_charset
109
+ # 絵文字を数値参照に変換
110
+ str = Jpmobile::Emoticon.external_to_unicodecr_docomo(Jpmobile::Util.sjis(str))
111
+ end
112
+
113
+ str
114
+ end
115
+ def to_mail_body_encoded?(str)
116
+ Jpmobile::Util.shift_jis?(str)
117
+ end
118
+
97
119
  # i-mode ブラウザのバージョンを返す。
98
120
  # http://labs.unoh.net/2009/07/i_20.html
99
121
  def imode_browser_version
@@ -6,7 +6,7 @@ module Jpmobile::Mobile
6
6
  class Emobile < AbstractMobile
7
7
  USER_AGENT_REGEXP = %r{^emobile/|^Mozilla/5.0 \(H11T; like Gecko; OpenBrowser\) NetFront/3.4$|^Mozilla/4.0 \(compatible; MSIE 6.0; Windows CE; IEMobile 7.7\) S11HT$}
8
8
  # 対応するメールアドレスの正規表現
9
- MAIL_ADDRESS_REGEXP = /^.+@emnet\.ne\.jp$/
9
+ MAIL_ADDRESS_REGEXP = /.+@emnet\.ne\.jp/
10
10
  # EMnet対応端末から通知されるユニークなユーザIDを取得する。
11
11
  def em_uid
12
12
  @request.env['HTTP_X_EM_UID']
@@ -8,7 +8,9 @@ module Jpmobile::Mobile
8
8
  # 対応するuser-agentの正規表現
9
9
  USER_AGENT_REGEXP = /^(?:SoftBank|Semulator)/
10
10
  # 対応するメールアドレスの正規表現 ディズニーモバイル対応
11
- MAIL_ADDRESS_REGEXP = /^.+@(?:softbank\.ne\.jp|disney\.ne\.jp)$/
11
+ MAIL_ADDRESS_REGEXP = /.+@(?:softbank\.ne\.jp|disney\.ne\.jp)/
12
+ # メールのデフォルトのcharset
13
+ MAIL_CHARSET = "Shift_JIS"
12
14
 
13
15
  # 製造番号を返す。無ければ +nil+ を返す。
14
16
  def serial_number
@@ -58,5 +60,35 @@ module Jpmobile::Mobile
58
60
 
59
61
  [str, charset]
60
62
  end
63
+
64
+ # メール送信用
65
+ def to_mail_subject(str)
66
+ "=?#{mail_charset}?B?" + [to_mail_encoding(str)].pack('m').strip + "?="
67
+ end
68
+ def to_mail_body(str)
69
+ to_mail_encoding(str)
70
+ end
71
+ def to_mail_internal(str, charset)
72
+ # 絵文字を数値参照に変換
73
+ if Jpmobile::Util.utf8?(str) or charset == "UTF-8"
74
+ # UTF-8
75
+ str = Jpmobile::Emoticon.external_to_unicodecr_softbank(Jpmobile::Util.utf8(str))
76
+ elsif Jpmobile::Util.shift_jis?(str) or Jpmobile::Util.ascii_8bit?(str) or charset == mail_charset
77
+ # Shift_JIS
78
+ str = Jpmobile::Emoticon.external_to_unicodecr_softbank_sjis(Jpmobile::Util.sjis(str))
79
+ end
80
+
81
+ str
82
+ end
83
+ def to_mail_body_encoded?(str)
84
+ Jpmobile::Util.shift_jis?(str)
85
+ end
86
+
87
+ private
88
+ def to_mail_encoding(str)
89
+ str = Jpmobile::Emoticon.utf8_to_unicodecr(str)
90
+ str = Jpmobile::Util.utf8_to_sjis(str)
91
+ Jpmobile::Emoticon.unicodecr_to_softbank_email(str)
92
+ end
61
93
  end
62
94
  end
@@ -7,7 +7,7 @@ module Jpmobile::Mobile
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /^(Vodafone|Vemulator)/
9
9
  # 対応するメールアドレスの正規表現
10
- MAIL_ADDRESS_REGEXP = /^.+@[dhtcrknsq]\.vodafone\.ne\.jp$/
10
+ MAIL_ADDRESS_REGEXP = /.+@[dhtcrknsq]\.vodafone\.ne\.jp/
11
11
 
12
12
  # cookieに対応しているか?
13
13
  def supports_cookie?
@@ -7,7 +7,7 @@ module Jpmobile::Mobile
7
7
  # 対応するUser-Agentの正規表現
8
8
  USER_AGENT_REGEXP = /^Mozilla\/3.0\(WILLCOM/
9
9
  # 対応するメールアドレスの正規表現
10
- MAIL_ADDRESS_REGEXP = /^.+@(.+\.)?pdx\.ne\.jp$/
10
+ MAIL_ADDRESS_REGEXP = /.+@((.+\.)?pdx\.ne\.jp|willcom\.com)/
11
11
 
12
12
  # 位置情報があれば Position のインスタンスを返す。無ければ +nil+ を返す。
13
13
  def position
@@ -0,0 +1,40 @@
1
+ module Jpmobile
2
+ class PathSet < Array
3
+ %w(initialize << concat insert push unshift).each do |method|
4
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
5
+ def #{method}(*args)
6
+ super
7
+ typecast!
8
+ end
9
+ METHOD
10
+ end
11
+
12
+ def find(path, prefix = nil, partial = false, details = {}, key = nil)
13
+ template = find_all(path, prefix, partial, details, key).first
14
+ raise MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) unless template
15
+ template
16
+ end
17
+
18
+ def find_all(*args)
19
+ each do |resolver|
20
+ templates = resolver.find_all(*args)
21
+ return templates unless templates.empty?
22
+ end
23
+ []
24
+ end
25
+
26
+ def exists?(*args)
27
+ find_all(*args).any?
28
+ end
29
+
30
+ protected
31
+
32
+ def typecast!
33
+ each_with_index do |path, i|
34
+ path = path.to_s if path.is_a?(Pathname)
35
+ next unless path.is_a?(String)
36
+ self[i] = Jpmobile::Resolver.new(path)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -21,3 +21,27 @@ ActiveSupport.on_load(:before_configuration) do
21
21
  end
22
22
  end
23
23
  end
24
+
25
+ module Jpmobile
26
+ module ViewSelector
27
+ def self.included(base)
28
+ base.class_eval do
29
+ before_filter :register_mobile
30
+
31
+ self._view_paths = self._view_paths.dup
32
+ self.view_paths.unshift(Jpmobile::Resolver.new(File.join(Rails.root, "app/views")))
33
+ end
34
+ end
35
+
36
+ def register_mobile
37
+ if request.mobile
38
+ # register mobile
39
+ self.lookup_context.mobile = request.mobile.variants
40
+ end
41
+ end
42
+
43
+ def disable_mobile_view!
44
+ self.lookup_context.mobile = nil
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ module Jpmobile
2
+ class Resolver < ActionView::FileSystemResolver
3
+ # EXTENSION_ORDER = [:variants, :locale, :formats, :handlers]
4
+
5
+ def find_templates(name, prefix, partial, details)
6
+ path = build_path(name, prefix, partial, details)
7
+ query(path, EXTENSION_ORDER.map { |ext| details[ext] }, details[:formats], details[:mobile])
8
+ end
9
+
10
+ def build_path(name, prefix, partial, details)
11
+ path = ""
12
+ path << "#{prefix}/" unless prefix.empty?
13
+ path << (partial ? "_#{name}" : name)
14
+ path
15
+ end
16
+
17
+ def query(path, exts, formats, mobile)
18
+ query = File.join(@path, path)
19
+ query << '{' << mobile.map {|v| "_#{v}"}.join(',') << ',}' if mobile and mobile.respond_to?(:map)
20
+
21
+ exts.each do |ext|
22
+ query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << ',}'
23
+ end
24
+
25
+ query.gsub!(/\{\.html,/, "{.html,.text.html,")
26
+ query.gsub!(/\{\.text,/, "{.text,.text.plain,")
27
+
28
+ Dir[query].reject { |p| File.directory?(p) }.map do |p|
29
+ handler, format = extract_handler_and_format(p, formats)
30
+
31
+ contents = File.open(p, "rb") {|io| io.read }
32
+
33
+ ActionView::Template.new(contents, File.expand_path(p), handler,
34
+ :virtual_path => path, :format => format)
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/jpmobile/util.rb CHANGED
@@ -1,6 +1,16 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'tempfile'
2
3
  module Jpmobile
3
4
  module Util
5
+ # SJIS = "Shift_JIS"
6
+ SJIS = "Windows-31J"
7
+ UTF8 = "UTF-8"
8
+ JIS = "ISO-2022-JP"
9
+ BINARY = "ASCII-8BIT"
10
+
11
+ WAVE_DASH = [0x301c].pack("U")
12
+ FULLWIDTH_TILDE = [0xff5e].pack("U")
13
+
4
14
  module_function
5
15
  def deep_apply(obj, &proc)
6
16
  case obj
@@ -44,40 +54,69 @@ module Jpmobile
44
54
  new_obj
45
55
  end
46
56
 
47
- def sjis(ascii_8bit)
48
- if ascii_8bit.respond_to?(:force_encoding)
49
- ascii_8bit.force_encoding("Shift_JIS")
57
+ def sjis(str)
58
+ if str.respond_to?(:force_encoding) and !shift_jis?(str)
59
+ str.force_encoding(SJIS)
60
+ end
61
+ str
62
+ end
63
+
64
+ def utf8(str)
65
+ if str.respond_to?(:force_encoding) and !utf8?(str)
66
+ str.force_encoding(UTF8)
50
67
  end
51
- ascii_8bit
68
+ str
52
69
  end
53
70
 
54
- def utf8(ascii_8bit)
55
- if ascii_8bit.respond_to?(:force_encoding)
56
- ascii_8bit.force_encoding("utf-8")
71
+ def jis(str)
72
+ if str.respond_to?(:force_encoding) and !jis?(str)
73
+ str.force_encoding(JIS)
57
74
  end
58
- ascii_8bit
75
+ str
59
76
  end
60
77
 
61
78
  def ascii_8bit(str)
62
- if str.respond_to?(:force_encoding)
63
- str.force_encoding("ASCII-8BIT")
79
+ if str.respond_to?(:force_encoding) and !ascii_8bit?(str)
80
+ str.force_encoding(BINARY)
64
81
  end
65
82
  str
66
83
  end
67
84
 
68
85
  def utf8_to_sjis(utf8_str)
86
+ # 波ダッシュ対策
87
+ utf8_str = wavedash_to_fullwidth_tilde(utf8_str)
88
+
69
89
  if utf8_str.respond_to?(:encode)
70
- utf8_str.encode("Shift_JIS", :crlf_newline => true)
90
+ utf8_str.encode(SJIS, :crlf_newline => true)
71
91
  else
72
92
  NKF.nkf("-m0 -x -W --oc=cp932", utf8_str).gsub(/\n/, "\r\n")
73
93
  end
74
94
  end
75
95
 
76
96
  def sjis_to_utf8(sjis_str)
77
- if sjis_str.respond_to?(:encode)
78
- sjis_str.encode("UTF-8", :universal_newline => true)
97
+ utf8_str = if sjis_str.respond_to?(:encode)
98
+ sjis_str.encode("UTF-8", :universal_newline => true)
99
+ else
100
+ NKF.nkf("-m0 -x -w --ic=cp932", sjis_str).gsub(/\r\n/, "\n")
101
+ end
102
+
103
+ # 波ダッシュ対策
104
+ fullwidth_tilde_to_wavedash(utf8_str)
105
+ end
106
+
107
+ def utf8_to_jis(utf8_str)
108
+ if utf8_str.respond_to?(:encode)
109
+ utf8_str.encode(JIS, :crlf_newline => true)
110
+ else
111
+ NKF.nkf("-m0 -x -Wj", utf8_str).gsub(/\n/, "\r\n")
112
+ end
113
+ end
114
+
115
+ def jis_to_utf8(jis_str)
116
+ if jis_str.respond_to?(:encode)
117
+ jis_str.encode(UTF8, :universal_newline => true)
79
118
  else
80
- NKF.nkf("-m0 -x -w --ic=cp932", sjis_str).gsub(/\r\n/, "\n")
119
+ NKF.nkf("-m0 -x -Jw", jis_str).gsub(/\r\n/, "\n")
81
120
  end
82
121
  end
83
122
 
@@ -89,11 +128,181 @@ module Jpmobile
89
128
  end
90
129
  end
91
130
 
131
+ def regexp_to_sjis(sjis_str)
132
+ if Object.const_defined?(:Encoding)
133
+ Regexp.compile(Regexp.escape(sjis(sjis_str)))
134
+ else
135
+ Regexp.compile(Regexp.escape(sjis_str,"s"),nil,'s')
136
+ end
137
+ end
138
+
92
139
  def hash_to_utf8(hash)
93
140
  new_hash = {}
94
141
  hash.each do |keu, value|
95
142
  new_hash[utf8(key)] = utf8(value)
96
143
  end
97
144
  end
145
+
146
+ def sjis_regexp(sjis)
147
+ sjis_str = sjis.kind_of?(Numeric) ? [sjis].pack('n') : sjis
148
+
149
+ if Object.const_defined?(:Encoding)
150
+ Regexp.compile(Regexp.escape(sjis_str.force_encoding(SJIS)))
151
+ else
152
+ Regexp.compile(Regexp.escape(sjis_str,"s"),nil,'s')
153
+ end
154
+ end
155
+
156
+ def jis_regexp(jis)
157
+ jis_str = jis.kind_of?(Numeric) ? [jis].pack('n') : jis
158
+
159
+ if Object.const_defined?(:Encoding)
160
+ # Regexp.compile(Regexp.escape(jis_str.force_encoding("stateless-ISO-2022-JP-KDDI"))) # for au only
161
+ Regexp.compile(Regexp.escape(jis_str.force_encoding(BINARY))) # for au only
162
+ else
163
+ Regexp.compile(Regexp.escape(jis_str,"j"),nil,'j')
164
+ end
165
+ end
166
+
167
+ def jis_string_regexp
168
+ Regexp.compile(Regexp.escape(ascii_8bit("\x1b\x24\x42")) + "(.+)" + Regexp.escape(ascii_8bit("\x1b\x28\x42")))
169
+ end
170
+
171
+ def encode(str, charset)
172
+ if Object.const_defined?(:Encoding)
173
+ (charset.nil? or charset == "" or str.nil? or str == "") ? str : str.encode(charset)
174
+ else
175
+ if str.nil?
176
+ str
177
+ else
178
+ case charset
179
+ when /iso-2022-jp/i
180
+ NKF.nkf("-j", str)
181
+ when /shift_jis/i
182
+ NKF.nkf("-s", str)
183
+ when /utf-8/i
184
+ NKF.nkf("-w", str)
185
+ else
186
+ str
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ def wavedash_to_fullwidth_tilde(utf8_str)
193
+ utf8_str.gsub(WAVE_DASH, FULLWIDTH_TILDE)
194
+ end
195
+
196
+ def fullwidth_tilde_to_wavedash(utf8_str)
197
+ utf8_str.gsub(FULLWIDTH_TILDE, WAVE_DASH)
198
+ end
199
+
200
+ def force_encode(str, from, to)
201
+ s = str.dup
202
+ return str if detect_encoding(str) == to
203
+
204
+ if Object.const_defined?(:Encoding)
205
+ to = SJIS if to =~ /shift_jis/i
206
+
207
+ to_enc = ::Encoding.find(to)
208
+ return str if s.encoding == to_enc
209
+
210
+ if from
211
+ from_enc = ::Encoding.find(from)
212
+ s.force_encoding(from) unless s.encoding == from_enc
213
+ end
214
+
215
+ s.encode(to)
216
+ else
217
+ opt = []
218
+ opt << case from
219
+ when /iso-2022-jp/i
220
+ "-Jx"
221
+ when /shift_jis/i
222
+ "-Sx"
223
+ when /utf-8/i
224
+ "-Wx"
225
+ else
226
+ ""
227
+ end
228
+ opt << case to
229
+ when /iso-2022-jp/i
230
+ "-j"
231
+ when /shift_jis/i, /windows_31j/i
232
+ "-s"
233
+ when /utf-8/i
234
+ "-w"
235
+ else
236
+ ""
237
+ end
238
+ NKF.nkf(opt.join(" "), str)
239
+ end
240
+ end
241
+
242
+ def set_encoding(str, encoding)
243
+ if encoding and Object.const_defined?(:Encoding)
244
+ encoding = SJIS if encoding =~ /shift_jis/i
245
+
246
+ str.force_encoding(encoding)
247
+ end
248
+
249
+ str
250
+ end
251
+
252
+ def extract_charset(str)
253
+ case str
254
+ when /iso-2022-jp/i
255
+ "ISO-2022-JP"
256
+ when /shift_jis/i
257
+ "Shift_JIS"
258
+ when /utf-8/i
259
+ "UTF-8"
260
+ else
261
+ ""
262
+ end
263
+ end
264
+
265
+ def detect_encoding(str)
266
+ if Object.const_defined?(:Encoding)
267
+ case str.encoding
268
+ when ::Encoding::ISO2022_JP
269
+ JIS
270
+ when ::Encoding::Shift_JIS, ::Encoding::Windows_31J, ::Encoding::CP932
271
+ SJIS
272
+ when ::Encoding::UTF_8
273
+ UTF8
274
+ when ::Encoding::ASCII_8BIT
275
+ BINARY
276
+ else
277
+ BINARY
278
+ end
279
+ else
280
+ case NKF.guess(str)
281
+ when NKF::SJIS
282
+ SJIS
283
+ when NKF::JIS
284
+ JIS
285
+ when NKF::UTF8
286
+ UTF8
287
+ when NKF::BINARY
288
+ BINARY
289
+ else
290
+ BINARY
291
+ end
292
+ end
293
+ end
294
+
295
+ def ascii_8bit?(str)
296
+ detect_encoding(str) == BINARY
297
+ end
298
+ def utf8?(str)
299
+ detect_encoding(str) == UTF8
300
+ end
301
+ def shift_jis?(str)
302
+ detect_encoding(str) == SJIS
303
+ end
304
+ def jis?(str)
305
+ detect_encoding(str) == JIS
306
+ end
98
307
  end
99
308
  end