net-imap 0.3.7 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
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)"