net-imap 0.3.7 → 0.4.5

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.

Potentially problematic release.


This version of net-imap might be problematic. Click here for more details.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pages.yml +46 -0
  3. data/.github/workflows/test.yml +5 -12
  4. data/.gitignore +2 -0
  5. data/Gemfile +3 -0
  6. data/README.md +15 -4
  7. data/Rakefile +0 -7
  8. data/docs/styles.css +0 -12
  9. data/lib/net/imap/authenticators.rb +26 -57
  10. data/lib/net/imap/command_data.rb +13 -6
  11. data/lib/net/imap/data_encoding.rb +14 -2
  12. data/lib/net/imap/deprecated_client_options.rb +139 -0
  13. data/lib/net/imap/errors.rb +20 -0
  14. data/lib/net/imap/fetch_data.rb +518 -0
  15. data/lib/net/imap/response_data.rb +116 -252
  16. data/lib/net/imap/response_parser/parser_utils.rb +240 -0
  17. data/lib/net/imap/response_parser.rb +1535 -1003
  18. data/lib/net/imap/sasl/anonymous_authenticator.rb +69 -0
  19. data/lib/net/imap/sasl/authentication_exchange.rb +107 -0
  20. data/lib/net/imap/sasl/authenticators.rb +118 -0
  21. data/lib/net/imap/sasl/client_adapter.rb +72 -0
  22. data/lib/net/imap/{authenticators/cram_md5.rb → sasl/cram_md5_authenticator.rb} +21 -11
  23. data/lib/net/imap/sasl/digest_md5_authenticator.rb +180 -0
  24. data/lib/net/imap/sasl/external_authenticator.rb +83 -0
  25. data/lib/net/imap/sasl/gs2_header.rb +80 -0
  26. data/lib/net/imap/{authenticators/login.rb → sasl/login_authenticator.rb} +25 -16
  27. data/lib/net/imap/sasl/oauthbearer_authenticator.rb +199 -0
  28. data/lib/net/imap/sasl/plain_authenticator.rb +101 -0
  29. data/lib/net/imap/sasl/protocol_adapters.rb +45 -0
  30. data/lib/net/imap/sasl/scram_algorithm.rb +58 -0
  31. data/lib/net/imap/sasl/scram_authenticator.rb +287 -0
  32. data/lib/net/imap/sasl/stringprep.rb +6 -66
  33. data/lib/net/imap/sasl/xoauth2_authenticator.rb +106 -0
  34. data/lib/net/imap/sasl.rb +144 -43
  35. data/lib/net/imap/sasl_adapter.rb +21 -0
  36. data/lib/net/imap/sequence_set.rb +67 -0
  37. data/lib/net/imap/stringprep/nameprep.rb +70 -0
  38. data/lib/net/imap/stringprep/saslprep.rb +69 -0
  39. data/lib/net/imap/stringprep/saslprep_tables.rb +96 -0
  40. data/lib/net/imap/stringprep/tables.rb +146 -0
  41. data/lib/net/imap/stringprep/trace.rb +85 -0
  42. data/lib/net/imap/stringprep.rb +159 -0
  43. data/lib/net/imap.rb +1055 -612
  44. data/net-imap.gemspec +4 -3
  45. data/rakelib/benchmarks.rake +91 -0
  46. data/rakelib/saslprep.rake +4 -4
  47. data/rakelib/string_prep_tables_generator.rb +82 -60
  48. metadata +31 -13
  49. data/benchmarks/stringprep.yml +0 -65
  50. data/benchmarks/table-regexps.yml +0 -39
  51. data/lib/net/imap/authenticators/digest_md5.rb +0 -115
  52. data/lib/net/imap/authenticators/plain.rb +0 -41
  53. data/lib/net/imap/authenticators/xoauth2.rb +0 -20
  54. data/lib/net/imap/sasl/saslprep.rb +0 -55
  55. data/lib/net/imap/sasl/saslprep_tables.rb +0 -98
  56. data/lib/net/imap/sasl/stringprep_tables.rb +0 -153
data/net-imap.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  name = File.basename(__FILE__, ".gemspec")
4
4
  version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
5
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
5
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb"), :encoding=> 'utf-8') do |line|
6
6
  /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
7
7
  end rescue nil
8
8
  end
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.summary = %q{Ruby client api for Internet Message Access Protocol}
17
17
  spec.description = %q{Ruby client api for Internet Message Access Protocol}
18
18
  spec.homepage = "https://github.com/ruby/net-imap"
19
- spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
19
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.3")
20
20
  spec.licenses = ["Ruby", "BSD-2-Clause"]
21
21
 
22
22
  spec.metadata["homepage_uri"] = spec.homepage
@@ -25,7 +25,8 @@ Gem::Specification.new do |spec|
25
25
  # Specify which files should be added to the gem when it is released.
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(bin|test|spec|features|rfcs)/}) }
28
+ `git ls-files -z 2>/dev/null`.split("\x0")
29
+ .reject {|f| f.match(%r{^(bin|test|spec|benchmarks|features|rfcs)/}) }
29
30
  end
30
31
  spec.bindir = "exe"
31
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ PARSER_TEST_FIXTURES = FileList.new "test/net/imap/fixtures/response_parser/*.yml"
4
+ CLOBBER.include "benchmarks/parser.yml"
5
+ CLEAN.include "benchmarks/Gemfile-*"
6
+
7
+ BENCHMARK_INIT = <<RUBY
8
+ require "yaml"
9
+ require "net/imap"
10
+
11
+ def load_response(file, name)
12
+ YAML.unsafe_load_file(file).dig(:tests, name, :response)
13
+ .force_encoding "ASCII-8BIT" \\
14
+ or abort "ERRORO: missing %p fixture data in %p" % [name, file]
15
+ end
16
+
17
+ parser = Net::IMAP::ResponseParser.new
18
+ RUBY
19
+
20
+ file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
21
+ require "yaml"
22
+ require "pathname"
23
+ require "net/imap"
24
+
25
+ path = Pathname.new(__dir__) / "../test/net/imap/fixtures/response_parser"
26
+ files = path.glob("*.yml")
27
+ tests = files.flat_map {|file|
28
+ file.read
29
+ .gsub(%r{([-:]) !ruby/(object|struct):\S+}) { $1 }
30
+ .then {
31
+ YAML.safe_load(_1, filename: file,
32
+ permitted_classes: [Symbol, Regexp], aliases: true)
33
+ }
34
+ .fetch(:tests)
35
+ .select {|test_name, test|
36
+ :parser_assert_equal == test.fetch(:test_type) {
37
+ test.key?(:expected) ? :parser_assert_equal : :parser_pending
38
+ }
39
+ }
40
+ .map {|test_name, test| [test_name.to_s, test.fetch(:response)] }
41
+ }
42
+
43
+ benchmarks = tests.map {|fixture_name, response|
44
+ {"name" => fixture_name.delete_prefix("test_"),
45
+ "prelude" => "response = %s" % [response.dump],
46
+ "script" => "parser.parse(response)"}
47
+ }
48
+ .sort_by { _1["name"] }
49
+
50
+ YAML.dump({"prelude" => BENCHMARK_INIT, "benchmark" => benchmarks})
51
+ .then { File.write t.name, _1 }
52
+ end
53
+
54
+ namespace :benchmarks do
55
+ desc "Generate benchmarks from fixture data"
56
+ task :generate => "benchmarks/parser.yml"
57
+
58
+ desc "run the parser benchmarks comparing multiple gem versions"
59
+ task :compare => :generate do |task, args|
60
+ cd Pathname.new(__dir__) + ".."
61
+ current = `git describe --tags --dirty`.chomp
62
+ current = "dev" if current.empty?
63
+ versions = args.to_a
64
+ if versions.empty?
65
+ latest = %x{git describe --tags --abbrev=0 --match 'v*.*.*'}.chomp
66
+ versions = latest.empty? ? [] : [latest.delete_prefix("v")]
67
+ end
68
+ versions = versions.to_h { [_1, "Gemfile-v#{_1}"] }
69
+ cd "benchmarks" do
70
+ versions.each do |version, gemfile|
71
+ File.write gemfile, <<~RUBY
72
+ # frozen_string_literal: true
73
+ source "https://rubygems.org"
74
+ gem "net-imap", #{version.dump}
75
+ RUBY
76
+ end
77
+ versions = {current => "../Gemfile" , **versions}.map {
78
+ "%s::/usr/bin/env BUNDLE_GEMFILE=%s ruby" % _1
79
+ }.join(";")
80
+
81
+ extra = ENV.fetch("BENCHMARK_ARGS", "").shellsplit
82
+
83
+ sh("benchmark-driver",
84
+ "--bundler",
85
+ "-e", versions,
86
+ "parser.yml",
87
+ *extra)
88
+ end
89
+ end
90
+
91
+ end
@@ -10,17 +10,17 @@ end
10
10
 
11
11
  directory "lib/net/imap/sasl"
12
12
 
13
- file "lib/net/imap/sasl/stringprep_tables.rb" => generator.rb_deps do |t|
13
+ file "lib/net/imap/stringprep/tables.rb" => generator.rb_deps do |t|
14
14
  File.write t.name, generator.stringprep_rb
15
15
  end
16
16
 
17
- file "lib/net/imap/sasl/saslprep_tables.rb" => generator.rb_deps do |t|
17
+ file "lib/net/imap/stringprep/saslprep_tables.rb" => generator.rb_deps do |t|
18
18
  File.write t.name, generator.saslprep_rb
19
19
  end
20
20
 
21
21
  GENERATED_RUBY = FileList.new(
22
- "lib/net/imap/sasl/stringprep_tables.rb",
23
- "lib/net/imap/sasl/saslprep_tables.rb",
22
+ "lib/net/imap/stringprep/tables.rb",
23
+ "lib/net/imap/stringprep/saslprep_tables.rb",
24
24
  )
25
25
 
26
26
  CLEAN.include generator.clean_deps
@@ -62,9 +62,9 @@ class StringPrepTablesGenerator
62
62
  # This file is generated from RFC3454, by rake. Don't edit directly.
63
63
  #++
64
64
 
65
- module Net::IMAP::SASL
65
+ module Net::IMAP::StringPrep
66
66
 
67
- module StringPrep
67
+ module Tables
68
68
 
69
69
  #{asgn_table "A.1"}
70
70
 
@@ -74,6 +74,12 @@ class StringPrepTablesGenerator
74
74
 
75
75
  #{asgn_table "B.3"}
76
76
 
77
+ #{asgn_mapping "B.1", ""}
78
+
79
+ #{asgn_mapping "B.2"}
80
+
81
+ #{asgn_mapping "B.3"}
82
+
77
83
  #{asgn_table "C.1.1"}
78
84
 
79
85
  #{asgn_table "C.1.2"}
@@ -105,14 +111,16 @@ class StringPrepTablesGenerator
105
111
 
106
112
  BIDI_DESC_REQ2 = "A string with RandALCat characters must not contain LCat characters."
107
113
 
108
- # Bidirectional Characters [StringPrep, §6], Requirement 2::
114
+ # Bidirectional Characters [StringPrep, §6], Requirement 2
115
+ # >>>
109
116
  # If a string contains any RandALCat character, the string MUST NOT
110
117
  # contain any LCat character.
111
118
  BIDI_FAILS_REQ2 = #{bidi_fails_req2.inspect}.freeze
112
119
 
113
120
  BIDI_DESC_REQ3 = "A string with RandALCat characters must start and end with RandALCat characters."
114
121
 
115
- # Bidirectional Characters [StringPrep, §6], Requirement 3::
122
+ # Bidirectional Characters [StringPrep, §6], Requirement 3
123
+ # >>>
116
124
  # If a string contains any RandALCat character, a RandALCat
117
125
  # character MUST be the first character of the string, and a
118
126
  # RandALCat character MUST be the last character of the string.
@@ -122,15 +130,21 @@ class StringPrepTablesGenerator
122
130
  BIDI_FAILURE = #{bidi_failure_regexp.inspect}.freeze
123
131
 
124
132
  # Names of each codepoint table in the RFC-3454 appendices
125
- TABLE_TITLES = {
133
+ TITLES = {
126
134
  #{table_titles_rb}
127
135
  }.freeze
128
136
 
129
137
  # Regexps matching each codepoint table in the RFC-3454 appendices
130
- TABLE_REGEXPS = {
138
+ REGEXPS = {
131
139
  #{table_regexps_rb}
132
140
  }.freeze
133
141
 
142
+ MAPPINGS = {
143
+ "B.1" => [IN_B_1, MAP_B_1].freeze,
144
+ "B.2" => [IN_B_2, MAP_B_2].freeze,
145
+ "B.3" => [IN_B_3, MAP_B_3].freeze,
146
+ }.freeze
147
+
134
148
  end
135
149
  end
136
150
  RUBY
@@ -157,27 +171,30 @@ class StringPrepTablesGenerator
157
171
  # This file is generated from RFC3454, by rake. Don't edit directly.
158
172
  #++
159
173
 
160
- module Net::IMAP::SASL
174
+ module Net::IMAP::StringPrep
161
175
 
162
176
  module SASLprep
163
177
 
164
178
  # RFC4013 §2.1 Mapping - mapped to space
165
- # * non-ASCII space characters (\\StringPrep\\[\\"C.1.2\\"]) that can be
166
- # mapped to SPACE (U+0020), and
179
+ # >>>
180
+ # non-ASCII space characters (\\StringPrep\\[\\"C.1.2\\"]) that can
181
+ # be mapped to SPACE (U+0020)
167
182
  #
168
183
  # Equal to \\StringPrep\\[\\"C.1.2\\"].
169
- # Redefined here to avoid loading the StringPrep module.
184
+ # Redefined here to avoid loading StringPrep::Tables unless necessary.
170
185
  MAP_TO_SPACE = #{regex_str "C.1.2"}
171
186
 
172
187
  # RFC4013 §2.1 Mapping - mapped to nothing
173
- # the "commonly mapped to nothing" characters (\\StringPrep\\[\\"B.1\\"])
174
- # that can be mapped to nothing.
188
+ # >>>
189
+ # the "commonly mapped to nothing" characters
190
+ # (\\StringPrep\\[\\"B.1\\"]) that can be mapped to nothing.
175
191
  #
176
192
  # Equal to \\StringPrep\\[\\"B.1\\"].
177
- # Redefined here to avoid loading the StringPrep module.
193
+ # Redefined here to avoid loading StringPrep::Tables unless necessary.
178
194
  MAP_TO_NOTHING = #{regex_str "B.1"}
179
195
 
180
- # RFC4013 §2.3 Prohibited Output::
196
+ # RFC4013 §2.3 Prohibited Output
197
+ # >>>
181
198
  # * Non-ASCII space characters — \\StringPrep\\[\\"C.1.2\\"]
182
199
  # * ASCII control characters — \\StringPrep\\[\\"C.2.1\\"]
183
200
  # * Non-ASCII control characters — \\StringPrep\\[\\"C.2.2\\"]
@@ -192,45 +209,52 @@ class StringPrepTablesGenerator
192
209
 
193
210
  # Adds unassigned (by Unicode 3.2) codepoints to TABLES_PROHIBITED.
194
211
  #
195
- # RFC4013 §2.5 Unassigned Code Points::
196
- # This profile specifies the \\StringPrep\\[\\"A.1\\"] table as its list of
197
- # unassigned code points.
212
+ # RFC4013 §2.5 Unassigned Code Points
213
+ # >>>
214
+ # This profile specifies the \\StringPrep\\[\\"A.1\\"] table as its
215
+ # list of unassigned code points.
198
216
  TABLES_PROHIBITED_STORED = ["A.1", *TABLES_PROHIBITED].freeze
199
217
 
200
- # Matches codepoints prohibited by RFC4013 §2.3.
218
+ # A Regexp matching codepoints prohibited by RFC4013 §2.3.
201
219
  #
202
- # See TABLES_PROHIBITED.
203
- #
204
- # Equal to +Regexp.union+ of the TABLES_PROHIBITED tables. Redefined
205
- # here to avoid loading the StringPrep module unless necessary.
220
+ # This combines all of the TABLES_PROHIBITED tables.
206
221
  PROHIBITED_OUTPUT = #{regex_str(*SASL_TABLES_PROHIBITED)}
207
222
 
208
- # RFC4013 §2.5 Unassigned Code Points::
209
- # This profile specifies the \\StringPrep\\[\\"A.1\\"] table as its list of
210
- # unassigned code points.
223
+ # RFC4013 §2.5 Unassigned Code Points
224
+ # >>>
225
+ # This profile specifies the \\StringPrep\\[\\"A.1\\"] table as its
226
+ # list of unassigned code points.
227
+ #
228
+ # Equal to \\StringPrep\\[\\"A.1\\"].
229
+ # Redefined here to avoid loading StringPrep::Tables unless necessary.
211
230
  UNASSIGNED = #{regex_str "A.1"}
212
231
 
213
- # Matches codepoints prohibited by RFC4013 §2.3 and §2.5.
232
+ # A Regexp matching codepoints prohibited by RFC4013 §2.3 and §2.5.
214
233
  #
215
- # See TABLES_PROHIBITED_STORED.
234
+ # This combines PROHIBITED_OUTPUT and UNASSIGNED.
216
235
  PROHIBITED_OUTPUT_STORED = Regexp.union(
217
236
  UNASSIGNED, PROHIBITED_OUTPUT
218
237
  ).freeze
219
238
 
220
239
  # Bidirectional Characters [StringPrep, §6]
240
+ #
241
+ # A Regexp for strings that don't satisfy StringPrep's Bidirectional
242
+ # Characters rules.
243
+ #
244
+ # Equal to StringPrep::Tables::BIDI_FAILURE.
245
+ # Redefined here to avoid loading StringPrep::Tables unless necessary.
221
246
  BIDI_FAILURE = #{bidi_failure_regexp.inspect}.freeze
222
247
 
223
- # Matches strings prohibited by RFC4013 §2.3 and §2.4.
248
+ # A Regexp matching strings prohibited by RFC4013 §2.3 and §2.4.
224
249
  #
225
- # This checks prohibited output and bidirectional characters.
250
+ # This combines PROHIBITED_OUTPUT and BIDI_FAILURE.
226
251
  PROHIBITED = Regexp.union(
227
252
  PROHIBITED_OUTPUT, BIDI_FAILURE,
228
253
  )
229
254
 
230
- # Matches strings prohibited by RFC4013 §2.3, §2.4, and §2.5.
255
+ # A Regexp matching strings prohibited by RFC4013 §2.3, §2.4, and §2.5.
231
256
  #
232
- # This checks prohibited output, bidirectional characters, and
233
- # unassigned codepoints.
257
+ # This combines PROHIBITED_OUTPUT_STORED and BIDI_FAILURE.
234
258
  PROHIBITED_STORED = Regexp.union(
235
259
  PROHIBITED_OUTPUT_STORED, BIDI_FAILURE,
236
260
  )
@@ -284,6 +308,15 @@ class StringPrepTablesGenerator
284
308
  .map{|s,e| s..(e || s)}
285
309
  end
286
310
 
311
+ # TODO: DRY with unicode_normalize
312
+ def to_map(table)
313
+ table = table.to_hash
314
+ .transform_keys { Integer _1, 16 }
315
+ .transform_keys { [_1].pack("U*") }
316
+ .transform_values {|cps| cps.map { Integer _1, 16 } }
317
+ .transform_values { _1.pack("U*") }
318
+ end
319
+
287
320
  # Starting from a codepoints array (rather than ranges) to deduplicate merged
288
321
  # tables.
289
322
  def to_regexp(codepoints, negate: false)
@@ -352,6 +385,13 @@ class StringPrepTablesGenerator
352
385
  asgn_regex(name, regexp_for(name, negate: negate), negate: negate)
353
386
  end
354
387
 
388
+ def asgn_mapping(name, replacement = to_map(tables[name]))
389
+ cname = name.tr(?., ?_).upcase
390
+ "# Replacements for %s\n%s%s = %p.freeze" % [
391
+ "IN_#{name}", " " * 2, "MAP_#{cname}", replacement,
392
+ ]
393
+ end
394
+
355
395
  def regexp_const_desc(name, negate: false)
356
396
  if negate then "Matches the negation of the %s table" % [name]
357
397
  else %q{%s \\StringPrep\\[\\"%s\\"]} % [titles.fetch(name), name]
@@ -376,40 +416,22 @@ class StringPrepTablesGenerator
376
416
  def bidi_L ; regexp_for "D.2" end
377
417
 
378
418
  def bidi_fails_req2
379
- / # RandALCat followed by LCat
380
- (?<r_and_al_cat>#{bidi_R_AL.source})
381
- .*?
382
- (?<l_cat>#{bidi_L.source})
383
- | # RandALCat preceded by LCat
384
- \g<l_cat> .*? \g<r_and_al_cat>
385
- /mux
419
+ Regexp.union(
420
+ /#{bidi_R_AL}.*?#{bidi_L}/mu, # RandALCat followed by LCat
421
+ /#{bidi_L}.*?#{bidi_R_AL}/mu, # RandALCat preceded by LCat
422
+ )
386
423
  end
387
424
 
388
425
  def bidi_fails_req3
389
- / # contains RandALCat but doesn't start with RandALCat
390
- \A(?<not_r_nor_al>#{bidi_not_R_AL})
391
- .*?
392
- (?<r_and_al_cat>#{bidi_R_AL})
393
- | # contains RandALCat but doesn't end with RandALCat
394
- \g<r_and_al_cat> .*? \g<not_r_nor_al>\z
395
- /mux
426
+ # contains RandALCat:
427
+ Regexp.union(
428
+ /\A#{bidi_not_R_AL}.*?#{bidi_R_AL}/mu, # but doesn't start with RandALCat
429
+ /#{bidi_R_AL}.*?#{bidi_not_R_AL}\z/mu, # but doesn't end with RandALCat
430
+ )
396
431
  end
397
432
 
398
- # shares the bidi_R_AL definition between both req2 and req3
399
433
  def bidi_failure_regexp
400
- req3_with_backref = bidi_fails_req3.source
401
- .gsub(%r{\(\?\<r_and_al_cat\>\(.*?\)\)}, "\g<r_and_al_cat>")
402
- .then{|re|"(?mx-i:#{re})"}
403
- /#{bidi_fails_req2} | #{req3_with_backref}/mux
404
- end
405
-
406
- def bidi_consts
407
- <<~RUBY
408
- #############
409
- # Bidirectional checks.
410
- #
411
-
412
- RUBY
434
+ Regexp.union(bidi_fails_req2, bidi_fails_req3)
413
435
  end
414
436
 
415
437
  SASL_TABLES_PROHIBITED = %w[
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-07-26 00:00:00.000000000 Z
12
+ date: 2023-11-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -76,34 +76,52 @@ extensions: []
76
76
  extra_rdoc_files: []
77
77
  files:
78
78
  - ".github/dependabot.yml"
79
+ - ".github/workflows/pages.yml"
79
80
  - ".github/workflows/test.yml"
80
81
  - ".gitignore"
81
82
  - Gemfile
82
83
  - LICENSE.txt
83
84
  - README.md
84
85
  - Rakefile
85
- - benchmarks/stringprep.yml
86
- - benchmarks/table-regexps.yml
87
86
  - docs/styles.css
88
87
  - lib/net/imap.rb
89
88
  - lib/net/imap/authenticators.rb
90
- - lib/net/imap/authenticators/cram_md5.rb
91
- - lib/net/imap/authenticators/digest_md5.rb
92
- - lib/net/imap/authenticators/login.rb
93
- - lib/net/imap/authenticators/plain.rb
94
- - lib/net/imap/authenticators/xoauth2.rb
95
89
  - lib/net/imap/command_data.rb
96
90
  - lib/net/imap/data_encoding.rb
91
+ - lib/net/imap/deprecated_client_options.rb
97
92
  - lib/net/imap/errors.rb
93
+ - lib/net/imap/fetch_data.rb
98
94
  - lib/net/imap/flags.rb
99
95
  - lib/net/imap/response_data.rb
100
96
  - lib/net/imap/response_parser.rb
97
+ - lib/net/imap/response_parser/parser_utils.rb
101
98
  - lib/net/imap/sasl.rb
102
- - lib/net/imap/sasl/saslprep.rb
103
- - lib/net/imap/sasl/saslprep_tables.rb
99
+ - lib/net/imap/sasl/anonymous_authenticator.rb
100
+ - lib/net/imap/sasl/authentication_exchange.rb
101
+ - lib/net/imap/sasl/authenticators.rb
102
+ - lib/net/imap/sasl/client_adapter.rb
103
+ - lib/net/imap/sasl/cram_md5_authenticator.rb
104
+ - lib/net/imap/sasl/digest_md5_authenticator.rb
105
+ - lib/net/imap/sasl/external_authenticator.rb
106
+ - lib/net/imap/sasl/gs2_header.rb
107
+ - lib/net/imap/sasl/login_authenticator.rb
108
+ - lib/net/imap/sasl/oauthbearer_authenticator.rb
109
+ - lib/net/imap/sasl/plain_authenticator.rb
110
+ - lib/net/imap/sasl/protocol_adapters.rb
111
+ - lib/net/imap/sasl/scram_algorithm.rb
112
+ - lib/net/imap/sasl/scram_authenticator.rb
104
113
  - lib/net/imap/sasl/stringprep.rb
105
- - lib/net/imap/sasl/stringprep_tables.rb
114
+ - lib/net/imap/sasl/xoauth2_authenticator.rb
115
+ - lib/net/imap/sasl_adapter.rb
116
+ - lib/net/imap/sequence_set.rb
117
+ - lib/net/imap/stringprep.rb
118
+ - lib/net/imap/stringprep/nameprep.rb
119
+ - lib/net/imap/stringprep/saslprep.rb
120
+ - lib/net/imap/stringprep/saslprep_tables.rb
121
+ - lib/net/imap/stringprep/tables.rb
122
+ - lib/net/imap/stringprep/trace.rb
106
123
  - net-imap.gemspec
124
+ - rakelib/benchmarks.rake
107
125
  - rakelib/rdoc.rake
108
126
  - rakelib/rfcs.rake
109
127
  - rakelib/saslprep.rake
@@ -123,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
141
  requirements:
124
142
  - - ">="
125
143
  - !ruby/object:Gem::Version
126
- version: 2.6.0
144
+ version: 2.7.3
127
145
  required_rubygems_version: !ruby/object:Gem::Requirement
128
146
  requirements:
129
147
  - - ">="
@@ -1,65 +0,0 @@
1
- ---
2
- prelude: |
3
- begin
4
- require "mongo" # gem install mongo
5
- require "idn" # gem install idn-ruby
6
- rescue LoadError
7
- warn "You must 'gem install mongo idn-ruby' for this benchmark."
8
- raise
9
- end
10
-
11
- MStrPrep = Mongo::Auth::StringPrep
12
-
13
- # this indirection will slow it down a little bit
14
- def mongo_saslprep(string)
15
- MStrPrep.prepare(string,
16
- MStrPrep::Profiles::SASL::MAPPINGS,
17
- MStrPrep::Profiles::SASL::PROHIBITED,
18
- normalize: true,
19
- bidi: true)
20
- rescue Mongo::Error::FailedStringPrepValidation
21
- nil
22
- end
23
-
24
- $LOAD_PATH.unshift "./lib"
25
- require "net/imap"
26
- def net_imap_saslprep(string)
27
- Net::IMAP::SASL::SASLprep.saslprep string, exception: false
28
- end
29
-
30
- def libidn_saslprep(string)
31
- IDN::Stringprep.with_profile(string, "SASLprep")
32
- rescue IDN::Stringprep::StringprepError
33
- nil
34
- end
35
-
36
- benchmark:
37
- - net_imap_saslprep "I\u00ADX" # RFC example 1. IX
38
- - net_imap_saslprep "user" # RFC example 2. user
39
- - net_imap_saslprep "USER" # RFC example 3. user
40
- - net_imap_saslprep "\u00aa" # RFC example 4. a
41
- - net_imap_saslprep "\u2168" # RFC example 5. IX
42
- - net_imap_saslprep "\u0007" # RFC example 6. Error - prohibited character
43
- - net_imap_saslprep "\u0627\u0031" # RFC example 7. Error - bidirectional check
44
- - net_imap_saslprep "I\u2000X" # map to space: I X
45
- - net_imap_saslprep "a longer string, e.g. a password"
46
-
47
- - libidn_saslprep "I\u00ADX" # RFC example 1. IX
48
- - libidn_saslprep "user" # RFC example 2. user
49
- - libidn_saslprep "USER" # RFC example 3. user
50
- - libidn_saslprep "\u00aa" # RFC example 4. a
51
- - libidn_saslprep "\u2168" # RFC example 5. IX
52
- - libidn_saslprep "\u0007" # RFC example 6. Error - prohibited character
53
- - libidn_saslprep "\u0627\u0031" # RFC example 7. Error - bidirectional check
54
- - libidn_saslprep "I\u2000X" # map to space: I X
55
- - libidn_saslprep "a longer string, e.g. a password"
56
-
57
- - mongo_saslprep "I\u00ADX" # RFC example 1. IX
58
- - mongo_saslprep "user" # RFC example 2. user
59
- - mongo_saslprep "USER" # RFC example 3. user
60
- - mongo_saslprep "\u00aa" # RFC example 4. a
61
- - mongo_saslprep "\u2168" # RFC example 5. IX
62
- - mongo_saslprep "\u0007" # RFC example 6. Error - prohibited character
63
- - mongo_saslprep "\u0627\u0031" # RFC example 7. Error - bidirectional check
64
- - mongo_saslprep "I\u2000X" # map to space: I X
65
- - mongo_saslprep "a longer string, e.g. a password"
@@ -1,39 +0,0 @@
1
- prelude: |
2
- require "json"
3
- require "set"
4
-
5
- all_codepoints = (0..0x10ffff).map{_1.chr("UTF-8") rescue nil}.compact
6
-
7
- rfc3454_tables = Dir["rfcs/rfc3454*.json"]
8
- .first
9
- .then{File.read _1}
10
- .then{JSON.parse _1}
11
- titles = rfc3454_tables.delete("titles")
12
-
13
- sets = rfc3454_tables
14
- .transform_values{|t|t.keys rescue t}
15
- .transform_values{|table|
16
- table
17
- .map{_1.split(?-).map{|i|Integer i, 16}}
18
- .flat_map{_2 ? (_1.._2).to_a : _1}
19
- .to_set
20
- }
21
-
22
- TABLE_A1_SET = sets.fetch "A.1"
23
- ASSIGNED_3_2 = /\p{AGE=3.2}/
24
- UNASSIGNED_3_2 = /\P{AGE=3.2}/
25
- TABLE_A1_REGEX = /(?-mix:[\u{0000}-\u{001f}\u{007f}-\u{00a0}\u{0340}-\u{0341}\u{06dd}\u{070f}\u{1680}\u{180e}\u{2000}-\u{200f}\u{2028}-\u{202f}\u{205f}-\u{2063}\u{206a}-\u{206f}\u{2ff0}-\u{2ffb}\u{3000}\u{e000}-\u{f8ff}\u{fdd0}-\u{fdef}\u{feff}\u{fff9}-\u{ffff}\u{1d173}-\u{1d17a}\u{1fffe}-\u{1ffff}\u{2fffe}-\u{2ffff}\u{3fffe}-\u{3ffff}\u{4fffe}-\u{4ffff}\u{5fffe}-\u{5ffff}\u{6fffe}-\u{6ffff}\u{7fffe}-\u{7ffff}\u{8fffe}-\u{8ffff}\u{9fffe}-\u{9ffff}\u{afffe}-\u{affff}\u{bfffe}-\u{bffff}\u{cfffe}-\u{cffff}\u{dfffe}-\u{dffff}\u{e0001}\u{e0020}-\u{e007f}\u{efffe}-\u{10ffff}])|(?-mix:\p{Cs})/.freeze
26
-
27
- benchmark:
28
-
29
- # matches A.1
30
- - script: "all_codepoints.grep(TABLE_A1_SET)"
31
- - script: "all_codepoints.grep(TABLE_A1_REGEX)"
32
- - script: "all_codepoints.grep(UNASSIGNED_3_2)"
33
- - script: "all_codepoints.grep_v(ASSIGNED_3_2)"
34
-
35
- # doesn't match A.1
36
- - script: "all_codepoints.grep_v(TABLE_A1_SET)"
37
- - script: "all_codepoints.grep_v(TABLE_A1_REGEX)"
38
- - script: "all_codepoints.grep_v(UNASSIGNED_3_2)"
39
- - script: "all_codepoints.grep(ASSIGNED_3_2)"