mail 2.6.6 → 2.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +25 -6
  3. data/Dependencies.txt +0 -1
  4. data/Gemfile +5 -8
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +22 -11
  7. data/Rakefile +0 -6
  8. data/lib/mail.rb +2 -10
  9. data/lib/mail/attachments_list.rb +3 -2
  10. data/lib/mail/body.rb +3 -3
  11. data/lib/mail/core_extensions/smtp.rb +19 -16
  12. data/lib/mail/core_extensions/string.rb +0 -4
  13. data/lib/mail/elements/address.rb +9 -4
  14. data/lib/mail/elements/address_list.rb +10 -18
  15. data/lib/mail/elements/content_disposition_element.rb +8 -15
  16. data/lib/mail/elements/content_location_element.rb +5 -10
  17. data/lib/mail/elements/content_transfer_encoding_element.rb +5 -10
  18. data/lib/mail/elements/content_type_element.rb +8 -19
  19. data/lib/mail/elements/date_time_element.rb +6 -14
  20. data/lib/mail/elements/envelope_from_element.rb +14 -21
  21. data/lib/mail/elements/message_ids_element.rb +8 -12
  22. data/lib/mail/elements/mime_version_element.rb +6 -14
  23. data/lib/mail/elements/phrase_list.rb +6 -9
  24. data/lib/mail/elements/received_element.rb +9 -15
  25. data/lib/mail/encodings.rb +12 -14
  26. data/lib/mail/field.rb +7 -4
  27. data/lib/mail/fields/common/parameter_hash.rb +1 -1
  28. data/lib/mail/fields/content_type_field.rb +2 -7
  29. data/lib/mail/fields/unstructured_field.rb +2 -2
  30. data/lib/mail/header.rb +1 -0
  31. data/lib/mail/message.rb +23 -25
  32. data/lib/mail/multibyte.rb +51 -0
  33. data/lib/mail/multibyte/chars.rb +27 -27
  34. data/lib/mail/network/delivery_methods/exim.rb +10 -6
  35. data/lib/mail/network/delivery_methods/sendmail.rb +2 -6
  36. data/lib/mail/network/delivery_methods/smtp.rb +14 -6
  37. data/lib/mail/parsers.rb +16 -24
  38. data/lib/mail/parsers/address_lists_parser.rb +15321 -112
  39. data/lib/mail/parsers/address_lists_parser.rl +166 -0
  40. data/lib/mail/parsers/content_disposition_parser.rb +698 -55
  41. data/lib/mail/parsers/content_disposition_parser.rl +76 -0
  42. data/lib/mail/parsers/content_location_parser.rb +565 -23
  43. data/lib/mail/parsers/content_location_parser.rl +65 -0
  44. data/lib/mail/parsers/content_transfer_encoding_parser.rb +410 -22
  45. data/lib/mail/parsers/content_transfer_encoding_parser.rl +58 -0
  46. data/lib/mail/parsers/content_type_parser.rb +841 -54
  47. data/lib/mail/parsers/content_type_parser.rl +77 -0
  48. data/lib/mail/parsers/date_time_parser.rb +773 -26
  49. data/lib/mail/parsers/date_time_parser.rl +56 -0
  50. data/lib/mail/parsers/envelope_from_parser.rb +2051 -36
  51. data/lib/mail/parsers/envelope_from_parser.rl +76 -0
  52. data/lib/mail/parsers/message_ids_parser.rb +1494 -25
  53. data/lib/mail/parsers/message_ids_parser.rl +76 -0
  54. data/lib/mail/parsers/mime_version_parser.rb +393 -26
  55. data/lib/mail/parsers/mime_version_parser.rl +55 -0
  56. data/lib/mail/parsers/phrase_lists_parser.rb +529 -19
  57. data/lib/mail/parsers/phrase_lists_parser.rl +77 -0
  58. data/lib/mail/parsers/received_parser.rb +4711 -38
  59. data/lib/mail/parsers/received_parser.rl +78 -0
  60. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +12 -0
  61. data/lib/mail/parsers/rfc2045_content_type.rl +24 -0
  62. data/lib/mail/parsers/rfc2045_mime.rl +15 -0
  63. data/lib/mail/parsers/rfc2183_content_disposition.rl +14 -0
  64. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +16 -0
  65. data/lib/mail/parsers/rfc5322.rl +57 -0
  66. data/lib/mail/parsers/rfc5322_address.rl +70 -0
  67. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +7 -1
  68. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +56 -0
  69. data/lib/mail/part.rb +1 -1
  70. data/lib/mail/parts_list.rb +5 -6
  71. data/lib/mail/utilities.rb +4 -2
  72. data/lib/mail/version.rb +3 -3
  73. data/lib/mail/version_specific/ruby_1_8.rb +28 -2
  74. data/lib/mail/version_specific/ruby_1_9.rb +48 -8
  75. metadata +28 -45
  76. data/lib/mail/core_extensions/string/access.rb +0 -146
  77. data/lib/mail/core_extensions/string/multibyte.rb +0 -79
  78. data/lib/mail/parsers/ragel.rb +0 -18
  79. data/lib/mail/parsers/ragel/common.rl +0 -185
  80. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  81. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  82. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  83. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  84. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  85. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  86. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  87. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  88. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  89. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  90. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  91. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  92. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  93. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  94. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  95. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  96. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  97. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  98. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  99. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  100. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  101. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  102. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  103. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  104. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  105. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'net/imap' # for decode_utf7
3
4
 
4
5
  module Mail
5
6
  class Ruby18
@@ -56,7 +57,27 @@ module Mail
56
57
  end
57
58
 
58
59
  def Ruby18.transcode_charset(str, from_encoding, to_encoding = 'UTF-8')
59
- Iconv.conv("#{normalize_iconv_charset_encoding(to_encoding)}//IGNORE", normalize_iconv_charset_encoding(from_encoding), str)
60
+ case from_encoding
61
+ when /utf-?7/i
62
+ decode_utf7(str)
63
+ else
64
+ retried = false
65
+ begin
66
+ Iconv.conv("#{normalize_iconv_charset_encoding(to_encoding)}//IGNORE", normalize_iconv_charset_encoding(from_encoding), str)
67
+ rescue Iconv::InvalidEncoding
68
+ if retried
69
+ raise
70
+ else
71
+ from_encoding = 'ASCII'
72
+ retried = true
73
+ retry
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def Ruby18.decode_utf7(str)
80
+ Net::IMAP.decode_utf7(str)
60
81
  end
61
82
 
62
83
  def Ruby18.b_value_encode(str, encoding)
@@ -97,7 +118,12 @@ module Mail
97
118
  end
98
119
 
99
120
  def Ruby18.param_decode(str, encoding)
100
- URI.unescape(str)
121
+ str = URI.unescape(str)
122
+ if encoding
123
+ transcode_charset(str, encoding)
124
+ else
125
+ str
126
+ end
101
127
  end
102
128
 
103
129
  def Ruby18.param_encode(str)
@@ -5,13 +5,23 @@ module Mail
5
5
  class Ruby19
6
6
  class StrictCharsetEncoder
7
7
  def encode(string, charset)
8
- string.force_encoding(Mail::Ruby19.pick_encoding(charset))
8
+ case charset
9
+ when /utf-?7/i
10
+ Mail::Ruby19.decode_utf7(string)
11
+ else
12
+ string.force_encoding(Mail::Ruby19.pick_encoding(charset))
13
+ end
9
14
  end
10
15
  end
11
16
 
12
17
  class BestEffortCharsetEncoder
13
18
  def encode(string, charset)
14
- string.force_encoding(pick_encoding(charset))
19
+ case charset
20
+ when /utf-?7/i
21
+ Mail::Ruby19.decode_utf7(string)
22
+ else
23
+ string.force_encoding(pick_encoding(charset))
24
+ end
15
25
  end
16
26
 
17
27
  private
@@ -78,7 +88,31 @@ module Mail
78
88
  end
79
89
 
80
90
  def Ruby19.transcode_charset(str, from_encoding, to_encoding = Encoding::UTF_8)
81
- charset_encoder.encode(str.dup, from_encoding).encode(to_encoding, :undef => :replace, :invalid => :replace, :replace => '')
91
+ to_encoding = Encoding.find(to_encoding)
92
+ replacement_char = to_encoding == Encoding::UTF_8 ? '�' : '?'
93
+ charset_encoder.encode(str.dup, from_encoding).encode(to_encoding, :undef => :replace, :invalid => :replace, :replace => replacement_char)
94
+ end
95
+
96
+ # From Ruby stdlib Net::IMAP
97
+ def Ruby19.encode_utf7(string)
98
+ string.gsub(/(&)|[^\x20-\x7e]+/) do
99
+ if $1
100
+ "&-"
101
+ else
102
+ base64 = [$&.encode(Encoding::UTF_16BE)].pack("m0")
103
+ "&" + base64.delete("=").tr("/", ",") + "-"
104
+ end
105
+ end.force_encoding(Encoding::ASCII_8BIT)
106
+ end
107
+
108
+ def Ruby19.decode_utf7(utf7)
109
+ utf7.gsub(/&([^-]+)?-/n) do
110
+ if $1
111
+ ($1.tr(",", "/") + "===").unpack("m")[0].encode(Encoding::UTF_8, Encoding::UTF_16BE)
112
+ else
113
+ "&"
114
+ end
115
+ end
82
116
  end
83
117
 
84
118
  def Ruby19.b_value_encode(str, encoding = nil)
@@ -93,8 +127,7 @@ module Mail
93
127
  str = Ruby19.decode_base64(match[2])
94
128
  str = charset_encoder.encode(str, charset)
95
129
  end
96
- decoded = str.encode(Encoding::UTF_8, :invalid => :replace, :replace => "")
97
- decoded.valid_encoding? ? decoded : decoded.encode(Encoding::UTF_16LE, :invalid => :replace, :replace => "").encode(Encoding::UTF_8)
130
+ transcode_to_scrubbed_utf8(str)
98
131
  rescue Encoding::UndefinedConversionError, ArgumentError, Encoding::ConverterNotFoundError
99
132
  warn "Encoding conversion failed #{$!}"
100
133
  str.dup.force_encoding(Encoding::UTF_8)
@@ -118,8 +151,7 @@ module Mail
118
151
  # jruby/jruby#829 which subtly changes String#encode semantics.
119
152
  str.force_encoding(Encoding::UTF_8) if str.encoding == Encoding::ASCII_8BIT
120
153
  end
121
- decoded = str.encode(Encoding::UTF_8, :invalid => :replace, :replace => "")
122
- decoded.valid_encoding? ? decoded : decoded.encode(Encoding::UTF_16LE, :invalid => :replace, :replace => "").encode(Encoding::UTF_8)
154
+ transcode_to_scrubbed_utf8(str)
123
155
  rescue Encoding::UndefinedConversionError, ArgumentError, Encoding::ConverterNotFoundError
124
156
  warn "Encoding conversion failed #{$!}"
125
157
  str.dup.force_encoding(Encoding::UTF_8)
@@ -128,7 +160,10 @@ module Mail
128
160
  def Ruby19.param_decode(str, encoding)
129
161
  str = uri_parser.unescape(str)
130
162
  str = charset_encoder.encode(str, encoding) if encoding
131
- str
163
+ transcode_to_scrubbed_utf8(str)
164
+ rescue Encoding::UndefinedConversionError, ArgumentError, Encoding::ConverterNotFoundError
165
+ warn "Encoding conversion failed #{$!}"
166
+ str.dup.force_encoding(Encoding::UTF_8)
132
167
  end
133
168
 
134
169
  def Ruby19.param_encode(str)
@@ -221,6 +256,11 @@ module Mail
221
256
  end
222
257
  end
223
258
  end
259
+
260
+ def transcode_to_scrubbed_utf8(str)
261
+ decoded = str.encode(Encoding::UTF_8, :undef => :replace, :invalid => :replace, :replace => "�")
262
+ decoded.valid_encoding? ? decoded : decoded.encode(Encoding::UTF_16LE, :invalid => :replace, :replace => "�").encode(Encoding::UTF_8)
263
+ end
224
264
  end
225
265
  end
226
266
  end
metadata CHANGED
@@ -1,35 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.6
4
+ version: 2.7.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikel Lindsaar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-09 00:00:00.000000000 Z
11
+ date: 2017-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: mime-types
14
+ name: mini_mime
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '4'
19
+ version: 0.1.1
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: '1.16'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '4'
26
+ version: 0.1.1
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: bundler
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -112,8 +106,6 @@ files:
112
106
  - lib/mail/constants.rb
113
107
  - lib/mail/core_extensions/smtp.rb
114
108
  - lib/mail/core_extensions/string.rb
115
- - lib/mail/core_extensions/string/access.rb
116
- - lib/mail/core_extensions/string/multibyte.rb
117
109
  - lib/mail/elements.rb
118
110
  - lib/mail/elements/address.rb
119
111
  - lib/mail/elements/address_list.rb
@@ -201,45 +193,36 @@ files:
201
193
  - lib/mail/network/retriever_methods/test_retriever.rb
202
194
  - lib/mail/parsers.rb
203
195
  - lib/mail/parsers/address_lists_parser.rb
196
+ - lib/mail/parsers/address_lists_parser.rl
204
197
  - lib/mail/parsers/content_disposition_parser.rb
198
+ - lib/mail/parsers/content_disposition_parser.rl
205
199
  - lib/mail/parsers/content_location_parser.rb
200
+ - lib/mail/parsers/content_location_parser.rl
206
201
  - lib/mail/parsers/content_transfer_encoding_parser.rb
202
+ - lib/mail/parsers/content_transfer_encoding_parser.rl
207
203
  - lib/mail/parsers/content_type_parser.rb
204
+ - lib/mail/parsers/content_type_parser.rl
208
205
  - lib/mail/parsers/date_time_parser.rb
206
+ - lib/mail/parsers/date_time_parser.rl
209
207
  - lib/mail/parsers/envelope_from_parser.rb
208
+ - lib/mail/parsers/envelope_from_parser.rl
210
209
  - lib/mail/parsers/message_ids_parser.rb
210
+ - lib/mail/parsers/message_ids_parser.rl
211
211
  - lib/mail/parsers/mime_version_parser.rb
212
+ - lib/mail/parsers/mime_version_parser.rl
212
213
  - lib/mail/parsers/phrase_lists_parser.rb
213
- - lib/mail/parsers/ragel.rb
214
- - lib/mail/parsers/ragel/common.rl
215
- - lib/mail/parsers/ragel/date_time.rl
216
- - lib/mail/parsers/ragel/parser_info.rb
217
- - lib/mail/parsers/ragel/ruby.rb
218
- - lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb
219
- - lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl
220
- - lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb
221
- - lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl
222
- - lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb
223
- - lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl
224
- - lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb
225
- - lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl
226
- - lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb
227
- - lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl
228
- - lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb
229
- - lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl
230
- - lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb
231
- - lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl
232
- - lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb
233
- - lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl
234
- - lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb
235
- - lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl
236
- - lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb
237
- - lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl
238
- - lib/mail/parsers/ragel/ruby/machines/rb_actions.rl
239
- - lib/mail/parsers/ragel/ruby/machines/received_machine.rb
240
- - lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl
241
- - lib/mail/parsers/ragel/ruby/parser.rb.rl.erb
214
+ - lib/mail/parsers/phrase_lists_parser.rl
242
215
  - lib/mail/parsers/received_parser.rb
216
+ - lib/mail/parsers/received_parser.rl
217
+ - lib/mail/parsers/rfc2045_content_transfer_encoding.rl
218
+ - lib/mail/parsers/rfc2045_content_type.rl
219
+ - lib/mail/parsers/rfc2045_mime.rl
220
+ - lib/mail/parsers/rfc2183_content_disposition.rl
221
+ - lib/mail/parsers/rfc5234_abnf_core_rules.rl
222
+ - lib/mail/parsers/rfc5322.rl
223
+ - lib/mail/parsers/rfc5322_address.rl
224
+ - lib/mail/parsers/rfc5322_date_time.rl
225
+ - lib/mail/parsers/rfc5322_lexical_tokens.rl
243
226
  - lib/mail/part.rb
244
227
  - lib/mail/parts_list.rb
245
228
  - lib/mail/utilities.rb
@@ -264,12 +247,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
264
247
  version: '0'
265
248
  required_rubygems_version: !ruby/object:Gem::Requirement
266
249
  requirements:
267
- - - ">="
250
+ - - ">"
268
251
  - !ruby/object:Gem::Version
269
- version: '0'
252
+ version: 1.3.1
270
253
  requirements: []
271
254
  rubyforge_project:
272
- rubygems_version: 2.6.11
255
+ rubygems_version: 2.6.12
273
256
  signing_key:
274
257
  specification_version: 4
275
258
  summary: Mail provides a nice Ruby DSL for making, sending and reading emails.
@@ -1,146 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- # This is not loaded if ActiveSupport is already loaded
5
-
6
- # This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
7
- # itself does not depend on ActiveSupport to avoid versioning conflicts
8
-
9
- class String
10
- unless '1.9'.respond_to?(:force_encoding)
11
- # Returns the character at the +position+ treating the string as an array (where 0 is the first character).
12
- #
13
- # Examples:
14
- # "hello".at(0) # => "h"
15
- # "hello".at(4) # => "o"
16
- # "hello".at(10) # => ERROR if < 1.9, nil in 1.9
17
- def at(position)
18
- mb_chars[position, 1].to_s
19
- end
20
-
21
- # Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
22
- #
23
- # Examples:
24
- # "hello".from(0) # => "hello"
25
- # "hello".from(2) # => "llo"
26
- # "hello".from(10) # => "" if < 1.9, nil in 1.9
27
- def from(position)
28
- mb_chars[position..-1].to_s
29
- end
30
-
31
- # Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
32
- #
33
- # Examples:
34
- # "hello".to(0) # => "h"
35
- # "hello".to(2) # => "hel"
36
- # "hello".to(10) # => "hello"
37
- def to(position)
38
- mb_chars[0..position].to_s
39
- end
40
-
41
- # Returns the first character of the string or the first +limit+ characters.
42
- #
43
- # Examples:
44
- # "hello".first # => "h"
45
- # "hello".first(2) # => "he"
46
- # "hello".first(10) # => "hello"
47
- def first(limit = 1)
48
- if limit == 0
49
- ''
50
- elsif limit >= size
51
- self
52
- else
53
- mb_chars[0...limit].to_s
54
- end
55
- end
56
-
57
- # Returns the last character of the string or the last +limit+ characters.
58
- #
59
- # Examples:
60
- # "hello".last # => "o"
61
- # "hello".last(2) # => "lo"
62
- # "hello".last(10) # => "hello"
63
- def last(limit = 1)
64
- if limit == 0
65
- ''
66
- elsif limit >= size
67
- self
68
- else
69
- mb_chars[(-limit)..-1].to_s
70
- end
71
- end
72
- else
73
- def at(position)
74
- self[position]
75
- end
76
-
77
- def from(position)
78
- self[position..-1]
79
- end
80
-
81
- def to(position)
82
- self[0..position]
83
- end
84
-
85
- def first(limit = 1)
86
- if limit == 0
87
- ''
88
- elsif limit >= size
89
- self
90
- else
91
- to(limit - 1)
92
- end
93
- end
94
-
95
- def last(limit = 1)
96
- if limit == 0
97
- ''
98
- elsif limit >= size
99
- self
100
- else
101
- from(-limit)
102
- end
103
- end
104
- end
105
-
106
- if Module.method(:const_get).arity == 1
107
- # Tries to find a constant with the name specified in the argument string:
108
- #
109
- # "Module".constantize # => Module
110
- # "Test::Unit".constantize # => Test::Unit
111
- #
112
- # The name is assumed to be the one of a top-level constant, no matter whether
113
- # it starts with "::" or not. No lexical context is taken into account:
114
- #
115
- # C = 'outside'
116
- # module M
117
- # C = 'inside'
118
- # C # => 'inside'
119
- # "C".constantize # => 'outside', same as ::C
120
- # end
121
- #
122
- # NameError is raised when the name is not in CamelCase or the constant is
123
- # unknown.
124
- def constantize
125
- names = self.split('::')
126
- names.shift if names.empty? || names.first.empty?
127
-
128
- constant = Object
129
- names.each do |name|
130
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
131
- end
132
- constant
133
- end
134
- else
135
- def constantize #:nodoc:
136
- names = self.split('::')
137
- names.shift if names.empty? || names.first.empty?
138
-
139
- constant = Object
140
- names.each do |name|
141
- constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
142
- end
143
- constant
144
- end
145
- end
146
- end
@@ -1,79 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- # This is not loaded if ActiveSupport is already loaded
5
-
6
- # This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
7
- # itself does not depend on ActiveSupport to avoid versioning conflicts
8
-
9
- require 'mail/multibyte'
10
-
11
- class String
12
- if RUBY_VERSION >= "1.9"
13
- # == Multibyte proxy
14
- #
15
- # +mb_chars+ is a multibyte safe proxy for string methods.
16
- #
17
- # In Ruby 1.8 and older it creates and returns an instance of the Mail::Multibyte::Chars class which
18
- # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
19
- # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
20
- #
21
- # name = 'Claus Müller'
22
- # name.reverse # => "rell??M sualC"
23
- # name.length # => 13
24
- #
25
- # name.mb_chars.reverse.to_s # => "rellüM sualC"
26
- # name.mb_chars.length # => 12
27
- #
28
- # In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
29
- # it becomes easy to run one version of your code on multiple Ruby versions.
30
- #
31
- # == Method chaining
32
- #
33
- # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
34
- # method chaining on the result of any of these methods.
35
- #
36
- # name.mb_chars.reverse.length # => 12
37
- #
38
- # == Interoperability and configuration
39
- #
40
- # The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
41
- # String and Char work like expected. The bang! methods change the internal string representation in the Chars
42
- # object. Interoperability problems can be resolved easily with a +to_s+ call.
43
- #
44
- # For more information about the methods defined on the Chars proxy see Mail::Multibyte::Chars. For
45
- # information about how to change the default Multibyte behaviour see Mail::Multibyte.
46
- def mb_chars
47
- if Mail::Multibyte.proxy_class.consumes?(self)
48
- Mail::Multibyte.proxy_class.new(self)
49
- else
50
- self
51
- end
52
- end
53
-
54
- def is_utf8? #:nodoc
55
- case encoding
56
- when Encoding::UTF_8
57
- valid_encoding?
58
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
59
- dup.force_encoding(Encoding::UTF_8).valid_encoding?
60
- else
61
- false
62
- end
63
- end
64
- else
65
- def mb_chars
66
- if Mail::Multibyte.proxy_class.wants?(self)
67
- Mail::Multibyte.proxy_class.new(self)
68
- else
69
- self
70
- end
71
- end
72
-
73
- # Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
74
- # them), returns false otherwise.
75
- def is_utf8?
76
- Mail::Multibyte::Chars.consumes?(self)
77
- end
78
- end
79
- end