mail 2.6.6 → 2.7.0.rc1

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 (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
OSZAR »