net-imap 0.3.4 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BSDL +22 -0
- data/COPYING +56 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +3 -22
- data/README.md +25 -8
- data/Rakefile +0 -7
- data/docs/styles.css +72 -23
- data/lib/net/imap/authenticators.rb +26 -57
- data/lib/net/imap/command_data.rb +74 -54
- data/lib/net/imap/config/attr_accessors.rb +75 -0
- data/lib/net/imap/config/attr_inheritance.rb +90 -0
- data/lib/net/imap/config/attr_type_coercion.rb +61 -0
- data/lib/net/imap/config.rb +470 -0
- data/lib/net/imap/data_encoding.rb +21 -9
- data/lib/net/imap/data_lite.rb +226 -0
- data/lib/net/imap/deprecated_client_options.rb +142 -0
- data/lib/net/imap/errors.rb +27 -1
- data/lib/net/imap/esearch_result.rb +180 -0
- data/lib/net/imap/fetch_data.rb +597 -0
- data/lib/net/imap/flags.rb +1 -1
- data/lib/net/imap/response_data.rb +250 -440
- data/lib/net/imap/response_parser/parser_utils.rb +245 -0
- data/lib/net/imap/response_parser.rb +1867 -1184
- data/lib/net/imap/sasl/anonymous_authenticator.rb +69 -0
- data/lib/net/imap/sasl/authentication_exchange.rb +139 -0
- data/lib/net/imap/sasl/authenticators.rb +122 -0
- data/lib/net/imap/sasl/client_adapter.rb +123 -0
- data/lib/net/imap/{authenticators/cram_md5.rb → sasl/cram_md5_authenticator.rb} +24 -14
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +342 -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} +28 -18
- 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 +101 -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 +148 -44
- data/lib/net/imap/sasl_adapter.rb +20 -0
- data/lib/net/imap/search_result.rb +146 -0
- data/lib/net/imap/sequence_set.rb +1565 -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/uidplus_data.rb +244 -0
- data/lib/net/imap/vanished_data.rb +56 -0
- data/lib/net/imap.rb +2090 -823
- data/net-imap.gemspec +7 -8
- data/rakelib/benchmarks.rake +91 -0
- data/rakelib/rfcs.rake +2 -0
- data/rakelib/saslprep.rake +4 -4
- data/rakelib/string_prep_tables_generator.rb +84 -60
- data/sample/net-imap.rb +167 -0
- metadata +45 -49
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/test.yml +0 -31
- data/.gitignore +0 -10
- 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
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-imap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
- nicholas a. evans
|
9
|
-
autorequire:
|
10
9
|
bindir: exe
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2025-02-07 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: net-protocol
|
@@ -39,75 +38,73 @@ dependencies:
|
|
39
38
|
- - ">="
|
40
39
|
- !ruby/object:Gem::Version
|
41
40
|
version: '0'
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: digest
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - ">="
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '0'
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
56
|
-
- !ruby/object:Gem::Dependency
|
57
|
-
name: strscan
|
58
|
-
requirement: !ruby/object:Gem::Requirement
|
59
|
-
requirements:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
63
|
-
type: :development
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
41
|
description: Ruby client api for Internet Message Access Protocol
|
71
42
|
email:
|
72
43
|
- shugo@ruby-lang.org
|
73
|
-
- nick@
|
44
|
+
- nick@rubinick.dev
|
74
45
|
executables: []
|
75
46
|
extensions: []
|
76
47
|
extra_rdoc_files: []
|
77
48
|
files:
|
78
|
-
-
|
79
|
-
-
|
80
|
-
- ".gitignore"
|
49
|
+
- BSDL
|
50
|
+
- COPYING
|
81
51
|
- Gemfile
|
82
52
|
- LICENSE.txt
|
83
53
|
- README.md
|
84
54
|
- Rakefile
|
85
|
-
- benchmarks/stringprep.yml
|
86
|
-
- benchmarks/table-regexps.yml
|
87
55
|
- docs/styles.css
|
88
56
|
- lib/net/imap.rb
|
89
57
|
- 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
58
|
- lib/net/imap/command_data.rb
|
59
|
+
- lib/net/imap/config.rb
|
60
|
+
- lib/net/imap/config/attr_accessors.rb
|
61
|
+
- lib/net/imap/config/attr_inheritance.rb
|
62
|
+
- lib/net/imap/config/attr_type_coercion.rb
|
96
63
|
- lib/net/imap/data_encoding.rb
|
64
|
+
- lib/net/imap/data_lite.rb
|
65
|
+
- lib/net/imap/deprecated_client_options.rb
|
97
66
|
- lib/net/imap/errors.rb
|
67
|
+
- lib/net/imap/esearch_result.rb
|
68
|
+
- lib/net/imap/fetch_data.rb
|
98
69
|
- lib/net/imap/flags.rb
|
99
70
|
- lib/net/imap/response_data.rb
|
100
71
|
- lib/net/imap/response_parser.rb
|
72
|
+
- lib/net/imap/response_parser/parser_utils.rb
|
101
73
|
- lib/net/imap/sasl.rb
|
102
|
-
- lib/net/imap/sasl/
|
103
|
-
- lib/net/imap/sasl/
|
74
|
+
- lib/net/imap/sasl/anonymous_authenticator.rb
|
75
|
+
- lib/net/imap/sasl/authentication_exchange.rb
|
76
|
+
- lib/net/imap/sasl/authenticators.rb
|
77
|
+
- lib/net/imap/sasl/client_adapter.rb
|
78
|
+
- lib/net/imap/sasl/cram_md5_authenticator.rb
|
79
|
+
- lib/net/imap/sasl/digest_md5_authenticator.rb
|
80
|
+
- lib/net/imap/sasl/external_authenticator.rb
|
81
|
+
- lib/net/imap/sasl/gs2_header.rb
|
82
|
+
- lib/net/imap/sasl/login_authenticator.rb
|
83
|
+
- lib/net/imap/sasl/oauthbearer_authenticator.rb
|
84
|
+
- lib/net/imap/sasl/plain_authenticator.rb
|
85
|
+
- lib/net/imap/sasl/protocol_adapters.rb
|
86
|
+
- lib/net/imap/sasl/scram_algorithm.rb
|
87
|
+
- lib/net/imap/sasl/scram_authenticator.rb
|
104
88
|
- lib/net/imap/sasl/stringprep.rb
|
105
|
-
- lib/net/imap/sasl/
|
89
|
+
- lib/net/imap/sasl/xoauth2_authenticator.rb
|
90
|
+
- lib/net/imap/sasl_adapter.rb
|
91
|
+
- lib/net/imap/search_result.rb
|
92
|
+
- lib/net/imap/sequence_set.rb
|
93
|
+
- lib/net/imap/stringprep.rb
|
94
|
+
- lib/net/imap/stringprep/nameprep.rb
|
95
|
+
- lib/net/imap/stringprep/saslprep.rb
|
96
|
+
- lib/net/imap/stringprep/saslprep_tables.rb
|
97
|
+
- lib/net/imap/stringprep/tables.rb
|
98
|
+
- lib/net/imap/stringprep/trace.rb
|
99
|
+
- lib/net/imap/uidplus_data.rb
|
100
|
+
- lib/net/imap/vanished_data.rb
|
106
101
|
- net-imap.gemspec
|
102
|
+
- rakelib/benchmarks.rake
|
107
103
|
- rakelib/rdoc.rake
|
108
104
|
- rakelib/rfcs.rake
|
109
105
|
- rakelib/saslprep.rake
|
110
106
|
- rakelib/string_prep_tables_generator.rb
|
107
|
+
- sample/net-imap.rb
|
111
108
|
homepage: https://github.com/ruby/net-imap
|
112
109
|
licenses:
|
113
110
|
- Ruby
|
@@ -115,7 +112,7 @@ licenses:
|
|
115
112
|
metadata:
|
116
113
|
homepage_uri: https://github.com/ruby/net-imap
|
117
114
|
source_code_uri: https://github.com/ruby/net-imap
|
118
|
-
|
115
|
+
changelog_uri: https://github.com/ruby/net-imap/releases
|
119
116
|
rdoc_options: []
|
120
117
|
require_paths:
|
121
118
|
- lib
|
@@ -123,15 +120,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
120
|
requirements:
|
124
121
|
- - ">="
|
125
122
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
123
|
+
version: 3.1.0
|
127
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
125
|
requirements:
|
129
126
|
- - ">="
|
130
127
|
- !ruby/object:Gem::Version
|
131
128
|
version: '0'
|
132
129
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
134
|
-
signing_key:
|
130
|
+
rubygems_version: 3.6.2
|
135
131
|
specification_version: 4
|
136
132
|
summary: Ruby client api for Internet Message Access Protocol
|
137
133
|
test_files: []
|
data/.github/dependabot.yml
DELETED
data/.github/workflows/test.yml
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
name: ubuntu
|
2
|
-
|
3
|
-
on: [push, pull_request]
|
4
|
-
|
5
|
-
jobs:
|
6
|
-
build:
|
7
|
-
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
8
|
-
strategy:
|
9
|
-
matrix:
|
10
|
-
ruby: [ head, '3.1', '3.0', '2.7' ]
|
11
|
-
os: [ ubuntu-latest, macos-latest ]
|
12
|
-
experimental: [false]
|
13
|
-
include:
|
14
|
-
# - ruby: 2.6
|
15
|
-
# os: ubuntu-latest
|
16
|
-
# experimental: true
|
17
|
-
- ruby: 2.6
|
18
|
-
os: macos-latest
|
19
|
-
experimental: false
|
20
|
-
runs-on: ${{ matrix.os }}
|
21
|
-
continue-on-error: ${{ matrix.experimental }}
|
22
|
-
steps:
|
23
|
-
- uses: actions/checkout@v3
|
24
|
-
- name: Set up Ruby
|
25
|
-
uses: ruby/setup-ruby@v1
|
26
|
-
with:
|
27
|
-
ruby-version: ${{ matrix.ruby }}
|
28
|
-
- name: Install dependencies
|
29
|
-
run: bundle install
|
30
|
-
- name: Run test
|
31
|
-
run: rake test
|
data/.gitignore
DELETED
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)"
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Net::IMAP authenticator for the "`DIGEST-MD5`" SASL mechanism type, specified
|
4
|
-
# in RFC2831(https://tools.ietf.org/html/rfc2831). See Net::IMAP#authenticate.
|
5
|
-
#
|
6
|
-
# == Deprecated
|
7
|
-
#
|
8
|
-
# "+DIGEST-MD5+" has been deprecated by
|
9
|
-
# {RFC6331}[https://tools.ietf.org/html/rfc6331] and should not be relied on for
|
10
|
-
# security. It is included for compatibility with existing servers.
|
11
|
-
class Net::IMAP::DigestMD5Authenticator
|
12
|
-
def process(challenge)
|
13
|
-
case @stage
|
14
|
-
when STAGE_ONE
|
15
|
-
@stage = STAGE_TWO
|
16
|
-
sparams = {}
|
17
|
-
c = StringScanner.new(challenge)
|
18
|
-
while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/)
|
19
|
-
k, v = c[1], c[2]
|
20
|
-
if v =~ /^"(.*)"$/
|
21
|
-
v = $1
|
22
|
-
if v =~ /,/
|
23
|
-
v = v.split(',')
|
24
|
-
end
|
25
|
-
end
|
26
|
-
sparams[k] = v
|
27
|
-
end
|
28
|
-
|
29
|
-
raise Net::IMAP::DataFormatError, "Bad Challenge: '#{challenge}'" unless c.eos?
|
30
|
-
raise Net::IMAP::Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth")
|
31
|
-
|
32
|
-
response = {
|
33
|
-
:nonce => sparams['nonce'],
|
34
|
-
:username => @user,
|
35
|
-
:realm => sparams['realm'],
|
36
|
-
:cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]),
|
37
|
-
:'digest-uri' => 'imap/' + sparams['realm'],
|
38
|
-
:qop => 'auth',
|
39
|
-
:maxbuf => 65535,
|
40
|
-
:nc => "%08d" % nc(sparams['nonce']),
|
41
|
-
:charset => sparams['charset'],
|
42
|
-
}
|
43
|
-
|
44
|
-
response[:authzid] = @authname unless @authname.nil?
|
45
|
-
|
46
|
-
# now, the real thing
|
47
|
-
a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') )
|
48
|
-
|
49
|
-
a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':')
|
50
|
-
a1 << ':' + response[:authzid] unless response[:authzid].nil?
|
51
|
-
|
52
|
-
a2 = "AUTHENTICATE:" + response[:'digest-uri']
|
53
|
-
a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/
|
54
|
-
|
55
|
-
response[:response] = Digest::MD5.hexdigest(
|
56
|
-
[
|
57
|
-
Digest::MD5.hexdigest(a1),
|
58
|
-
response.values_at(:nonce, :nc, :cnonce, :qop),
|
59
|
-
Digest::MD5.hexdigest(a2)
|
60
|
-
].join(':')
|
61
|
-
)
|
62
|
-
|
63
|
-
return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',')
|
64
|
-
when STAGE_TWO
|
65
|
-
@stage = nil
|
66
|
-
# if at the second stage, return an empty string
|
67
|
-
if challenge =~ /rspauth=/
|
68
|
-
return ''
|
69
|
-
else
|
70
|
-
raise ResponseParseError, challenge
|
71
|
-
end
|
72
|
-
else
|
73
|
-
raise ResponseParseError, challenge
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def initialize(user, password, authname = nil, warn_deprecation: true)
|
78
|
-
if warn_deprecation
|
79
|
-
warn "WARNING: DIGEST-MD5 SASL mechanism was deprecated by RFC6331."
|
80
|
-
# TODO: recommend SCRAM instead.
|
81
|
-
end
|
82
|
-
require "digest/md5"
|
83
|
-
require "strscan"
|
84
|
-
@user, @password, @authname = user, password, authname
|
85
|
-
@nc, @stage = {}, STAGE_ONE
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
STAGE_ONE = :stage_one
|
92
|
-
STAGE_TWO = :stage_two
|
93
|
-
|
94
|
-
def nc(nonce)
|
95
|
-
if @nc.has_key? nonce
|
96
|
-
@nc[nonce] = @nc[nonce] + 1
|
97
|
-
else
|
98
|
-
@nc[nonce] = 1
|
99
|
-
end
|
100
|
-
return @nc[nonce]
|
101
|
-
end
|
102
|
-
|
103
|
-
# some responses need quoting
|
104
|
-
def qdval(k, v)
|
105
|
-
return if k.nil? or v.nil?
|
106
|
-
if %w"username authzid realm nonce cnonce digest-uri qop".include? k
|
107
|
-
v = v.gsub(/([\\"])/, "\\\1")
|
108
|
-
return '%s="%s"' % [k, v]
|
109
|
-
else
|
110
|
-
return '%s=%s' % [k, v]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
Net::IMAP.add_authenticator "DIGEST-MD5", self
|
115
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Authenticator for the "+PLAIN+" SASL mechanism, specified in
|
4
|
-
# RFC4616[https://tools.ietf.org/html/rfc4616]. See Net::IMAP#authenticate.
|
5
|
-
#
|
6
|
-
# +PLAIN+ authentication sends the password in cleartext.
|
7
|
-
# RFC3501[https://tools.ietf.org/html/rfc3501] encourages servers to disable
|
8
|
-
# cleartext authentication until after TLS has been negotiated.
|
9
|
-
# RFC8314[https://tools.ietf.org/html/rfc8314] recommends TLS version 1.2 or
|
10
|
-
# greater be used for all traffic, and deprecate cleartext access ASAP. +PLAIN+
|
11
|
-
# can be secured by TLS encryption.
|
12
|
-
class Net::IMAP::PlainAuthenticator
|
13
|
-
|
14
|
-
def process(data)
|
15
|
-
return "#@authzid\0#@username\0#@password"
|
16
|
-
end
|
17
|
-
|
18
|
-
# :nodoc:
|
19
|
-
NULL = -"\0".b
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# +username+ is the authentication identity, the identity whose +password+ is
|
24
|
-
# used. +username+ is referred to as +authcid+ by
|
25
|
-
# RFC4616[https://tools.ietf.org/html/rfc4616].
|
26
|
-
#
|
27
|
-
# +authzid+ is the authorization identity (identity to act as). It can
|
28
|
-
# usually be left blank. When +authzid+ is left blank (nil or empty string)
|
29
|
-
# the server will derive an identity from the credentials and use that as the
|
30
|
-
# authorization identity.
|
31
|
-
def initialize(username, password, authzid: nil)
|
32
|
-
raise ArgumentError, "username contains NULL" if username&.include?(NULL)
|
33
|
-
raise ArgumentError, "password contains NULL" if password&.include?(NULL)
|
34
|
-
raise ArgumentError, "authzid contains NULL" if authzid&.include?(NULL)
|
35
|
-
@username = username
|
36
|
-
@password = password
|
37
|
-
@authzid = authzid
|
38
|
-
end
|
39
|
-
|
40
|
-
Net::IMAP.add_authenticator "PLAIN", self
|
41
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Net::IMAP::XOauth2Authenticator
|
4
|
-
def process(_data)
|
5
|
-
build_oauth2_string(@user, @oauth2_token)
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
def initialize(user, oauth2_token)
|
11
|
-
@user = user
|
12
|
-
@oauth2_token = oauth2_token
|
13
|
-
end
|
14
|
-
|
15
|
-
def build_oauth2_string(user, oauth2_token)
|
16
|
-
format("user=%s\1auth=Bearer %s\1\1", user, oauth2_token)
|
17
|
-
end
|
18
|
-
|
19
|
-
Net::IMAP.add_authenticator 'XOAUTH2', self
|
20
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "saslprep_tables"
|
4
|
-
|
5
|
-
module Net::IMAP::SASL
|
6
|
-
|
7
|
-
# SASLprep#saslprep can be used to prepare a string according to [RFC4013].
|
8
|
-
#
|
9
|
-
# \SASLprep maps characters three ways: to nothing, to space, and Unicode
|
10
|
-
# normalization form KC. \SASLprep prohibits codepoints from nearly all
|
11
|
-
# standard StringPrep tables (RFC3454, Appendix "C"), and uses \StringPrep's
|
12
|
-
# standard bidirectional characters requirements (Appendix "D"). \SASLprep
|
13
|
-
# also uses \StringPrep's definition of "Unassigned" codepoints (Appendix "A").
|
14
|
-
module SASLprep
|
15
|
-
|
16
|
-
# Used to short-circuit strings that don't need preparation.
|
17
|
-
ASCII_NO_CTRLS = /\A[\x20-\x7e]*\z/u.freeze
|
18
|
-
|
19
|
-
module_function
|
20
|
-
|
21
|
-
# Prepares a UTF-8 +string+ for comparison, using the \SASLprep profile
|
22
|
-
# RFC4013 of the StringPrep algorithm RFC3454.
|
23
|
-
#
|
24
|
-
# By default, prohibited strings will return +nil+. When +exception+ is
|
25
|
-
# +true+, a StringPrepError describing the violation will be raised.
|
26
|
-
#
|
27
|
-
# When +stored+ is +true+, "unassigned" codepoints will be prohibited. For
|
28
|
-
# \StringPrep and the \SASLprep profile, "unassigned" refers to Unicode 3.2,
|
29
|
-
# and not later versions. See RFC3454 §7 for more information.
|
30
|
-
#
|
31
|
-
def saslprep(str, stored: false, exception: false)
|
32
|
-
return str if ASCII_NO_CTRLS.match?(str) # raises on incompatible encoding
|
33
|
-
str = str.encode("UTF-8") # also dups (and raises for invalid encoding)
|
34
|
-
str.gsub!(MAP_TO_SPACE, " ")
|
35
|
-
str.gsub!(MAP_TO_NOTHING, "")
|
36
|
-
str.unicode_normalize!(:nfkc)
|
37
|
-
# These regexps combine the prohibited and bidirectional checks
|
38
|
-
return str unless str.match?(stored ? PROHIBITED_STORED : PROHIBITED)
|
39
|
-
return nil unless exception
|
40
|
-
# raise helpful errors to indicate *why* it failed:
|
41
|
-
tables = stored ? TABLES_PROHIBITED_STORED : TABLES_PROHIBITED
|
42
|
-
StringPrep.check_prohibited! str, *tables, bidi: true, profile: "SASLprep"
|
43
|
-
raise StringPrep::InvalidStringError.new(
|
44
|
-
"unknown error", string: string, profile: "SASLprep"
|
45
|
-
)
|
46
|
-
rescue ArgumentError, Encoding::CompatibilityError => ex
|
47
|
-
if /invalid byte sequence|incompatible encoding/.match? ex.message
|
48
|
-
return nil unless exception
|
49
|
-
raise StringPrepError.new(ex.message, string: str, profile: "saslprep")
|
50
|
-
end
|
51
|
-
raise ex
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#--
|
4
|
-
# This file is generated from RFC3454, by rake. Don't edit directly.
|
5
|
-
#++
|
6
|
-
|
7
|
-
module Net::IMAP::SASL
|
8
|
-
|
9
|
-
module SASLprep
|
10
|
-
|
11
|
-
# RFC4013 §2.1 Mapping - mapped to space
|
12
|
-
# * non-ASCII space characters (\StringPrep\[\"C.1.2\"]) that can be
|
13
|
-
# mapped to SPACE (U+0020), and
|
14
|
-
#
|
15
|
-
# Equal to \StringPrep\[\"C.1.2\"].
|
16
|
-
# Redefined here to avoid loading the StringPrep module.
|
17
|
-
MAP_TO_SPACE = /[\u200b\p{Zs}&&[^ ]]/.freeze
|
18
|
-
|
19
|
-
# RFC4013 §2.1 Mapping - mapped to nothing
|
20
|
-
# the "commonly mapped to nothing" characters (\StringPrep\[\"B.1\"])
|
21
|
-
# that can be mapped to nothing.
|
22
|
-
#
|
23
|
-
# Equal to \StringPrep\[\"B.1\"].
|
24
|
-
# Redefined here to avoid loading the StringPrep module.
|
25
|
-
MAP_TO_NOTHING = /[\u{00ad 034f 1806 2060 feff}\u{180b}-\u{180d}\u{200b}-\u{200d}\u{fe00}-\u{fe0f}]/.freeze
|
26
|
-
|
27
|
-
# RFC4013 §2.3 Prohibited Output::
|
28
|
-
# * Non-ASCII space characters — \StringPrep\[\"C.1.2\"]
|
29
|
-
# * ASCII control characters — \StringPrep\[\"C.2.1\"]
|
30
|
-
# * Non-ASCII control characters — \StringPrep\[\"C.2.2\"]
|
31
|
-
# * Private Use characters — \StringPrep\[\"C.3\"]
|
32
|
-
# * Non-character code points — \StringPrep\[\"C.4\"]
|
33
|
-
# * Surrogate code points — \StringPrep\[\"C.5\"]
|
34
|
-
# * Inappropriate for plain text characters — \StringPrep\[\"C.6\"]
|
35
|
-
# * Inappropriate for canonical representation characters — \StringPrep\[\"C.7\"]
|
36
|
-
# * Change display properties or deprecated characters — \StringPrep\[\"C.8\"]
|
37
|
-
# * Tagging characters — \StringPrep\[\"C.9\"]
|
38
|
-
TABLES_PROHIBITED = ["C.1.2", "C.2.1", "C.2.2", "C.3", "C.4", "C.5", "C.6", "C.7", "C.8", "C.9"].freeze
|
39
|
-
|
40
|
-
# Adds unassigned (by Unicode 3.2) codepoints to TABLES_PROHIBITED.
|
41
|
-
#
|
42
|
-
# RFC4013 §2.5 Unassigned Code Points::
|
43
|
-
# This profile specifies the \StringPrep\[\"A.1\"] table as its list of
|
44
|
-
# unassigned code points.
|
45
|
-
TABLES_PROHIBITED_STORED = ["A.1", *TABLES_PROHIBITED].freeze
|
46
|
-
|
47
|
-
# Matches codepoints prohibited by RFC4013 §2.3.
|
48
|
-
#
|
49
|
-
# See TABLES_PROHIBITED.
|
50
|
-
#
|
51
|
-
# Equal to +Regexp.union+ of the TABLES_PROHIBITED tables. Redefined
|
52
|
-
# here to avoid loading the StringPrep module unless necessary.
|
53
|
-
PROHIBITED_OUTPUT = /[\u{06dd 070f 1680 180e 3000 feff e0001}\u{0000}-\u{001f}\u{007f}-\u{00a0}\u{0340}-\u{0341}\u{2000}-\u{200f}\u{2028}-\u{202f}\u{205f}-\u{2063}\u{206a}-\u{206f}\u{2ff0}-\u{2ffb}\u{e000}-\u{f8ff}\u{fdd0}-\u{fdef}\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{e0020}-\u{e007f}\u{efffe}-\u{10ffff}\p{Cs}]/.freeze
|
54
|
-
|
55
|
-
# RFC4013 §2.5 Unassigned Code Points::
|
56
|
-
# This profile specifies the \StringPrep\[\"A.1\"] table as its list of
|
57
|
-
# unassigned code points.
|
58
|
-
UNASSIGNED = /\p{^AGE=3.2}/.freeze
|
59
|
-
|
60
|
-
# Matches codepoints prohibited by RFC4013 §2.3 and §2.5.
|
61
|
-
#
|
62
|
-
# See TABLES_PROHIBITED_STORED.
|
63
|
-
PROHIBITED_OUTPUT_STORED = Regexp.union(
|
64
|
-
UNASSIGNED, PROHIBITED_OUTPUT
|
65
|
-
).freeze
|
66
|
-
|
67
|
-
# Bidirectional Characters [StringPrep, §6]
|
68
|
-
BIDI_FAILURE = /(?mx-i: # RandALCat followed by LCat
|
69
|
-
(?<r_and_al_cat>[\u{05be 05c0 05c3 061b 061f 06dd 0710 07b1 200f fb1d fb3e}\u{05d0}-\u{05ea}\u{05f0}-\u{05f4}\u{0621}-\u{063a}\u{0640}-\u{064a}\u{066d}-\u{066f}\u{0671}-\u{06d5}\u{06e5}-\u{06e6}\u{06fa}-\u{06fe}\u{0700}-\u{070d}\u{0712}-\u{072c}\u{0780}-\u{07a5}\u{fb1f}-\u{fb28}\u{fb2a}-\u{fb36}\u{fb38}-\u{fb3c}\u{fb40}-\u{fb41}\u{fb43}-\u{fb44}\u{fb46}-\u{fbb1}\u{fbd3}-\u{fd3d}\u{fd50}-\u{fd8f}\u{fd92}-\u{fdc7}\u{fdf0}-\u{fdfc}\u{fe70}-\u{fe74}\u{fe76}-\u{fefc}])
|
70
|
-
.*?
|
71
|
-
(?<l_cat>[\u{00aa 00b5 00ba 02ee 037a 0386 038c 0589 0903 0950 09b2 09d7 0a5e 0a83 0a8d 0ac9 0ad0 0ae0 0b40 0b57 0b83 0b9c 0bd7 0cbe 0cde 0d57 0dbd 0e84 0e8a 0e8d 0ea5 0ea7 0ebd 0ec6 0f36 0f38 0f7f 0f85 0fcf 102c 1031 1038 10fb 1248 1258 1288 12b0 12c0 1310 17dc 1f59 1f5b 1f5d 1fbe 200e 2071 207f 2102 2107 2115 2124 2126 2128 2395 1d4a2 1d4bb 1d546}\u{0041}-\u{005a}\u{0061}-\u{007a}\u{00c0}-\u{00d6}\u{00d8}-\u{00f6}\u{00f8}-\u{0220}\u{0222}-\u{0233}\u{0250}-\u{02ad}\u{02b0}-\u{02b8}\u{02bb}-\u{02c1}\u{02d0}-\u{02d1}\u{02e0}-\u{02e4}\u{0388}-\u{038a}\u{038e}-\u{03a1}\u{03a3}-\u{03ce}\u{03d0}-\u{03f5}\u{0400}-\u{0482}\u{048a}-\u{04ce}\u{04d0}-\u{04f5}\u{04f8}-\u{04f9}\u{0500}-\u{050f}\u{0531}-\u{0556}\u{0559}-\u{055f}\u{0561}-\u{0587}\u{0905}-\u{0939}\u{093d}-\u{0940}\u{0949}-\u{094c}\u{0958}-\u{0961}\u{0964}-\u{0970}\u{0982}-\u{0983}\u{0985}-\u{098c}\u{098f}-\u{0990}\u{0993}-\u{09a8}\u{09aa}-\u{09b0}\u{09b6}-\u{09b9}\u{09be}-\u{09c0}\u{09c7}-\u{09c8}\u{09cb}-\u{09cc}\u{09dc}-\u{09dd}\u{09df}-\u{09e1}\u{09e6}-\u{09f1}\u{09f4}-\u{09fa}\u{0a05}-\u{0a0a}\u{0a0f}-\u{0a10}\u{0a13}-\u{0a28}\u{0a2a}-\u{0a30}\u{0a32}-\u{0a33}\u{0a35}-\u{0a36}\u{0a38}-\u{0a39}\u{0a3e}-\u{0a40}\u{0a59}-\u{0a5c}\u{0a66}-\u{0a6f}\u{0a72}-\u{0a74}\u{0a85}-\u{0a8b}\u{0a8f}-\u{0a91}\u{0a93}-\u{0aa8}\u{0aaa}-\u{0ab0}\u{0ab2}-\u{0ab3}\u{0ab5}-\u{0ab9}\u{0abd}-\u{0ac0}\u{0acb}-\u{0acc}\u{0ae6}-\u{0aef}\u{0b02}-\u{0b03}\u{0b05}-\u{0b0c}\u{0b0f}-\u{0b10}\u{0b13}-\u{0b28}\u{0b2a}-\u{0b30}\u{0b32}-\u{0b33}\u{0b36}-\u{0b39}\u{0b3d}-\u{0b3e}\u{0b47}-\u{0b48}\u{0b4b}-\u{0b4c}\u{0b5c}-\u{0b5d}\u{0b5f}-\u{0b61}\u{0b66}-\u{0b70}\u{0b85}-\u{0b8a}\u{0b8e}-\u{0b90}\u{0b92}-\u{0b95}\u{0b99}-\u{0b9a}\u{0b9e}-\u{0b9f}\u{0ba3}-\u{0ba4}\u{0ba8}-\u{0baa}\u{0bae}-\u{0bb5}\u{0bb7}-\u{0bb9}\u{0bbe}-\u{0bbf}\u{0bc1}-\u{0bc2}\u{0bc6}-\u{0bc8}\u{0bca}-\u{0bcc}\u{0be7}-\u{0bf2}\u{0c01}-\u{0c03}\u{0c05}-\u{0c0c}\u{0c0e}-\u{0c10}\u{0c12}-\u{0c28}\u{0c2a}-\u{0c33}\u{0c35}-\u{0c39}\u{0c41}-\u{0c44}\u{0c60}-\u{0c61}\u{0c66}-\u{0c6f}\u{0c82}-\u{0c83}\u{0c85}-\u{0c8c}\u{0c8e}-\u{0c90}\u{0c92}-\u{0ca8}\u{0caa}-\u{0cb3}\u{0cb5}-\u{0cb9}\u{0cc0}-\u{0cc4}\u{0cc7}-\u{0cc8}\u{0cca}-\u{0ccb}\u{0cd5}-\u{0cd6}\u{0ce0}-\u{0ce1}\u{0ce6}-\u{0cef}\u{0d02}-\u{0d03}\u{0d05}-\u{0d0c}\u{0d0e}-\u{0d10}\u{0d12}-\u{0d28}\u{0d2a}-\u{0d39}\u{0d3e}-\u{0d40}\u{0d46}-\u{0d48}\u{0d4a}-\u{0d4c}\u{0d60}-\u{0d61}\u{0d66}-\u{0d6f}\u{0d82}-\u{0d83}\u{0d85}-\u{0d96}\u{0d9a}-\u{0db1}\u{0db3}-\u{0dbb}\u{0dc0}-\u{0dc6}\u{0dcf}-\u{0dd1}\u{0dd8}-\u{0ddf}\u{0df2}-\u{0df4}\u{0e01}-\u{0e30}\u{0e32}-\u{0e33}\u{0e40}-\u{0e46}\u{0e4f}-\u{0e5b}\u{0e81}-\u{0e82}\u{0e87}-\u{0e88}\u{0e94}-\u{0e97}\u{0e99}-\u{0e9f}\u{0ea1}-\u{0ea3}\u{0eaa}-\u{0eab}\u{0ead}-\u{0eb0}\u{0eb2}-\u{0eb3}\u{0ec0}-\u{0ec4}\u{0ed0}-\u{0ed9}\u{0edc}-\u{0edd}\u{0f00}-\u{0f17}\u{0f1a}-\u{0f34}\u{0f3e}-\u{0f47}\u{0f49}-\u{0f6a}\u{0f88}-\u{0f8b}\u{0fbe}-\u{0fc5}\u{0fc7}-\u{0fcc}\u{1000}-\u{1021}\u{1023}-\u{1027}\u{1029}-\u{102a}\u{1040}-\u{1057}\u{10a0}-\u{10c5}\u{10d0}-\u{10f8}\u{1100}-\u{1159}\u{115f}-\u{11a2}\u{11a8}-\u{11f9}\u{1200}-\u{1206}\u{1208}-\u{1246}\u{124a}-\u{124d}\u{1250}-\u{1256}\u{125a}-\u{125d}\u{1260}-\u{1286}\u{128a}-\u{128d}\u{1290}-\u{12ae}\u{12b2}-\u{12b5}\u{12b8}-\u{12be}\u{12c2}-\u{12c5}\u{12c8}-\u{12ce}\u{12d0}-\u{12d6}\u{12d8}-\u{12ee}\u{12f0}-\u{130e}\u{1312}-\u{1315}\u{1318}-\u{131e}\u{1320}-\u{1346}\u{1348}-\u{135a}\u{1361}-\u{137c}\u{13a0}-\u{13f4}\u{1401}-\u{1676}\u{1681}-\u{169a}\u{16a0}-\u{16f0}\u{1700}-\u{170c}\u{170e}-\u{1711}\u{1720}-\u{1731}\u{1735}-\u{1736}\u{1740}-\u{1751}\u{1760}-\u{176c}\u{176e}-\u{1770}\u{1780}-\u{17b6}\u{17be}-\u{17c5}\u{17c7}-\u{17c8}\u{17d4}-\u{17da}\u{17e0}-\u{17e9}\u{1810}-\u{1819}\u{1820}-\u{1877}\u{1880}-\u{18a8}\u{1e00}-\u{1e9b}\u{1ea0}-\u{1ef9}\u{1f00}-\u{1f15}\u{1f18}-\u{1f1d}\u{1f20}-\u{1f45}\u{1f48}-\u{1f4d}\u{1f50}-\u{1f57}\u{1f5f}-\u{1f7d}\u{1f80}-\u{1fb4}\u{1fb6}-\u{1fbc}\u{1fc2}-\u{1fc4}\u{1fc6}-\u{1fcc}\u{1fd0}-\u{1fd3}\u{1fd6}-\u{1fdb}\u{1fe0}-\u{1fec}\u{1ff2}-\u{1ff4}\u{1ff6}-\u{1ffc}\u{210a}-\u{2113}\u{2119}-\u{211d}\u{212a}-\u{212d}\u{212f}-\u{2131}\u{2133}-\u{2139}\u{213d}-\u{213f}\u{2145}-\u{2149}\u{2160}-\u{2183}\u{2336}-\u{237a}\u{249c}-\u{24e9}\u{3005}-\u{3007}\u{3021}-\u{3029}\u{3031}-\u{3035}\u{3038}-\u{303c}\u{3041}-\u{3096}\u{309d}-\u{309f}\u{30a1}-\u{30fa}\u{30fc}-\u{30ff}\u{3105}-\u{312c}\u{3131}-\u{318e}\u{3190}-\u{31b7}\u{31f0}-\u{321c}\u{3220}-\u{3243}\u{3260}-\u{327b}\u{327f}-\u{32b0}\u{32c0}-\u{32cb}\u{32d0}-\u{32fe}\u{3300}-\u{3376}\u{337b}-\u{33dd}\u{33e0}-\u{33fe}\u{3400}-\u{4db5}\u{4e00}-\u{9fa5}\u{a000}-\u{a48c}\u{ac00}-\u{d7a3}\u{e000}-\u{fa2d}\u{fa30}-\u{fa6a}\u{fb00}-\u{fb06}\u{fb13}-\u{fb17}\u{ff21}-\u{ff3a}\u{ff41}-\u{ff5a}\u{ff66}-\u{ffbe}\u{ffc2}-\u{ffc7}\u{ffca}-\u{ffcf}\u{ffd2}-\u{ffd7}\u{ffda}-\u{ffdc}\u{10300}-\u{1031e}\u{10320}-\u{10323}\u{10330}-\u{1034a}\u{10400}-\u{10425}\u{10428}-\u{1044d}\u{1d000}-\u{1d0f5}\u{1d100}-\u{1d126}\u{1d12a}-\u{1d166}\u{1d16a}-\u{1d172}\u{1d183}-\u{1d184}\u{1d18c}-\u{1d1a9}\u{1d1ae}-\u{1d1dd}\u{1d400}-\u{1d454}\u{1d456}-\u{1d49c}\u{1d49e}-\u{1d49f}\u{1d4a5}-\u{1d4a6}\u{1d4a9}-\u{1d4ac}\u{1d4ae}-\u{1d4b9}\u{1d4bd}-\u{1d4c0}\u{1d4c2}-\u{1d4c3}\u{1d4c5}-\u{1d505}\u{1d507}-\u{1d50a}\u{1d50d}-\u{1d514}\u{1d516}-\u{1d51c}\u{1d51e}-\u{1d539}\u{1d53b}-\u{1d53e}\u{1d540}-\u{1d544}\u{1d54a}-\u{1d550}\u{1d552}-\u{1d6a3}\u{1d6a8}-\u{1d7c9}\u{20000}-\u{2a6d6}\u{2f800}-\u{2fa1d}\u{f0000}-\u{ffffd}\u{100000}-\u{10fffd}\p{Cs}])
|
72
|
-
| # RandALCat preceded by LCat
|
73
|
-
\g<l_cat> .*? \g<r_and_al_cat>
|
74
|
-
) | (?mx-i: # contains RandALCat but doesn't start with RandALCat
|
75
|
-
\A(?<not_r_nor_al>(?-mix:[^\u{05be 05c0 05c3 061b 061f 06dd 0710 07b1 200f fb1d fb3e}\u{05d0}-\u{05ea}\u{05f0}-\u{05f4}\u{0621}-\u{063a}\u{0640}-\u{064a}\u{066d}-\u{066f}\u{0671}-\u{06d5}\u{06e5}-\u{06e6}\u{06fa}-\u{06fe}\u{0700}-\u{070d}\u{0712}-\u{072c}\u{0780}-\u{07a5}\u{fb1f}-\u{fb28}\u{fb2a}-\u{fb36}\u{fb38}-\u{fb3c}\u{fb40}-\u{fb41}\u{fb43}-\u{fb44}\u{fb46}-\u{fbb1}\u{fbd3}-\u{fd3d}\u{fd50}-\u{fd8f}\u{fd92}-\u{fdc7}\u{fdf0}-\u{fdfc}\u{fe70}-\u{fe74}\u{fe76}-\u{fefc}]))
|
76
|
-
.*?
|
77
|
-
g<r_and_al_cat>
|
78
|
-
| # contains RandALCat but doesn't end with RandALCat
|
79
|
-
\g<r_and_al_cat> .*? \g<not_r_nor_al>\z
|
80
|
-
)/mx.freeze
|
81
|
-
|
82
|
-
# Matches strings prohibited by RFC4013 §2.3 and §2.4.
|
83
|
-
#
|
84
|
-
# This checks prohibited output and bidirectional characters.
|
85
|
-
PROHIBITED = Regexp.union(
|
86
|
-
PROHIBITED_OUTPUT, BIDI_FAILURE,
|
87
|
-
)
|
88
|
-
|
89
|
-
# Matches strings prohibited by RFC4013 §2.3, §2.4, and §2.5.
|
90
|
-
#
|
91
|
-
# This checks prohibited output, bidirectional characters, and
|
92
|
-
# unassigned codepoints.
|
93
|
-
PROHIBITED_STORED = Regexp.union(
|
94
|
-
PROHIBITED_OUTPUT_STORED, BIDI_FAILURE,
|
95
|
-
)
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|