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.
- checksums.yaml +4 -4
- data/.github/workflows/pages.yml +46 -0
- data/.github/workflows/test.yml +5 -12
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.md +15 -4
- data/Rakefile +0 -7
- data/docs/styles.css +0 -12
- data/lib/net/imap/authenticators.rb +26 -57
- data/lib/net/imap/command_data.rb +13 -6
- data/lib/net/imap/data_encoding.rb +14 -2
- data/lib/net/imap/deprecated_client_options.rb +139 -0
- data/lib/net/imap/errors.rb +20 -0
- data/lib/net/imap/fetch_data.rb +518 -0
- data/lib/net/imap/response_data.rb +116 -252
- data/lib/net/imap/response_parser/parser_utils.rb +240 -0
- data/lib/net/imap/response_parser.rb +1535 -1003
- data/lib/net/imap/sasl/anonymous_authenticator.rb +69 -0
- data/lib/net/imap/sasl/authentication_exchange.rb +107 -0
- data/lib/net/imap/sasl/authenticators.rb +118 -0
- data/lib/net/imap/sasl/client_adapter.rb +72 -0
- data/lib/net/imap/{authenticators/cram_md5.rb → sasl/cram_md5_authenticator.rb} +21 -11
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +180 -0
- data/lib/net/imap/sasl/external_authenticator.rb +83 -0
- data/lib/net/imap/sasl/gs2_header.rb +80 -0
- data/lib/net/imap/{authenticators/login.rb → sasl/login_authenticator.rb} +25 -16
- data/lib/net/imap/sasl/oauthbearer_authenticator.rb +199 -0
- data/lib/net/imap/sasl/plain_authenticator.rb +101 -0
- data/lib/net/imap/sasl/protocol_adapters.rb +45 -0
- data/lib/net/imap/sasl/scram_algorithm.rb +58 -0
- data/lib/net/imap/sasl/scram_authenticator.rb +287 -0
- data/lib/net/imap/sasl/stringprep.rb +6 -66
- data/lib/net/imap/sasl/xoauth2_authenticator.rb +106 -0
- data/lib/net/imap/sasl.rb +144 -43
- data/lib/net/imap/sasl_adapter.rb +21 -0
- data/lib/net/imap/sequence_set.rb +67 -0
- data/lib/net/imap/stringprep/nameprep.rb +70 -0
- data/lib/net/imap/stringprep/saslprep.rb +69 -0
- data/lib/net/imap/stringprep/saslprep_tables.rb +96 -0
- data/lib/net/imap/stringprep/tables.rb +146 -0
- data/lib/net/imap/stringprep/trace.rb +85 -0
- data/lib/net/imap/stringprep.rb +159 -0
- data/lib/net/imap.rb +1055 -612
- data/net-imap.gemspec +4 -3
- data/rakelib/benchmarks.rake +91 -0
- data/rakelib/saslprep.rake +4 -4
- data/rakelib/string_prep_tables_generator.rb +82 -60
- metadata +31 -13
- data/benchmarks/stringprep.yml +0 -65
- data/benchmarks/table-regexps.yml +0 -39
- data/lib/net/imap/authenticators/digest_md5.rb +0 -115
- data/lib/net/imap/authenticators/plain.rb +0 -41
- data/lib/net/imap/authenticators/xoauth2.rb +0 -20
- data/lib/net/imap/sasl/saslprep.rb +0 -55
- data/lib/net/imap/sasl/saslprep_tables.rb +0 -98
- 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.
|
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")
|
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
|
data/rakelib/saslprep.rake
CHANGED
@@ -10,17 +10,17 @@ end
|
|
10
10
|
|
11
11
|
directory "lib/net/imap/sasl"
|
12
12
|
|
13
|
-
file "lib/net/imap/
|
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/
|
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/
|
23
|
-
"lib/net/imap/
|
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::
|
65
|
+
module Net::IMAP::StringPrep
|
66
66
|
|
67
|
-
module
|
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
|
-
|
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
|
-
|
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::
|
174
|
+
module Net::IMAP::StringPrep
|
161
175
|
|
162
176
|
module SASLprep
|
163
177
|
|
164
178
|
# RFC4013 §2.1 Mapping - mapped to space
|
165
|
-
#
|
166
|
-
#
|
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
|
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
|
-
#
|
174
|
-
#
|
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
|
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
|
-
#
|
197
|
-
#
|
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
|
-
#
|
218
|
+
# A Regexp matching codepoints prohibited by RFC4013 §2.3.
|
201
219
|
#
|
202
|
-
#
|
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
|
-
#
|
210
|
-
#
|
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
|
-
#
|
232
|
+
# A Regexp matching codepoints prohibited by RFC4013 §2.3 and §2.5.
|
214
233
|
#
|
215
|
-
#
|
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
|
-
#
|
248
|
+
# A Regexp matching strings prohibited by RFC4013 §2.3 and §2.4.
|
224
249
|
#
|
225
|
-
# This
|
250
|
+
# This combines PROHIBITED_OUTPUT and BIDI_FAILURE.
|
226
251
|
PROHIBITED = Regexp.union(
|
227
252
|
PROHIBITED_OUTPUT, BIDI_FAILURE,
|
228
253
|
)
|
229
254
|
|
230
|
-
#
|
255
|
+
# A Regexp matching strings prohibited by RFC4013 §2.3, §2.4, and §2.5.
|
231
256
|
#
|
232
|
-
# This
|
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
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
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
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
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
|
-
|
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.
|
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-
|
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/
|
103
|
-
- lib/net/imap/sasl/
|
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/
|
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.
|
144
|
+
version: 2.7.3
|
127
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
146
|
requirements:
|
129
147
|
- - ">="
|
data/benchmarks/stringprep.yml
DELETED
@@ -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)"
|