net-imap 0.5.8 → 0.5.9
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/lib/net/imap/response_data.rb +0 -1
- data/lib/net/imap/sequence_set.rb +240 -90
- data/lib/net/imap.rb +46 -16
- data/rakelib/string_prep_tables_generator.rb +4 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a31378c34762136e5fc341801a0b4073157dc6c35df6aae3254d3f7b90a07b7
|
4
|
+
data.tar.gz: cbf787e39ecfde5a7af0061baba54eae3d7b12077679854ea62b335fc9b48798
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd0c8a34fa212bb42a55e943bf8184c614256b52da4ac13bdddb48f74c8517f5c7b72addb2153af42d76f2a8bcf42627ceb34e874b7842d8a6dfd542ba577578
|
7
|
+
data.tar.gz: 91dd4d1d35582abb9e4fd0df64c63ee5c9320f3404d548bff0a4023e32dc9a6ddd6b90cd1cc221e637a4719f3cc5699d57cc337ea17a6454b3aa7d7be9ffb423
|
data/Gemfile
CHANGED
@@ -6,7 +6,6 @@ module Net
|
|
6
6
|
autoload :FetchData, "#{__dir__}/fetch_data"
|
7
7
|
autoload :UIDFetchData, "#{__dir__}/fetch_data"
|
8
8
|
autoload :SearchResult, "#{__dir__}/search_result"
|
9
|
-
autoload :SequenceSet, "#{__dir__}/sequence_set"
|
10
9
|
autoload :UIDPlusData, "#{__dir__}/uidplus_data"
|
11
10
|
autoload :AppendUIDData, "#{__dir__}/uidplus_data"
|
12
11
|
autoload :CopyUIDData, "#{__dir__}/uidplus_data"
|
@@ -18,21 +18,9 @@ module Net
|
|
18
18
|
#
|
19
19
|
# == Creating sequence sets
|
20
20
|
#
|
21
|
-
# SequenceSet.new with no arguments creates an empty sequence set. Note
|
22
|
-
# that an empty sequence set is invalid in the \IMAP grammar.
|
23
|
-
#
|
24
|
-
# set = Net::IMAP::SequenceSet.new
|
25
|
-
# set.empty? #=> true
|
26
|
-
# set.valid? #=> false
|
27
|
-
# set.valid_string #!> raises DataFormatError
|
28
|
-
# set << 1..10
|
29
|
-
# set.empty? #=> false
|
30
|
-
# set.valid? #=> true
|
31
|
-
# set.valid_string #=> "1:10"
|
32
|
-
#
|
33
21
|
# SequenceSet.new may receive a single optional argument: a non-zero 32 bit
|
34
22
|
# unsigned integer, a range, a <tt>sequence-set</tt> formatted string,
|
35
|
-
# another
|
23
|
+
# another SequenceSet, a Set (containing only numbers or <tt>*</tt>), or an
|
36
24
|
# Array containing any of these (array inputs may be nested).
|
37
25
|
#
|
38
26
|
# set = Net::IMAP::SequenceSet.new(1)
|
@@ -48,30 +36,114 @@ module Net
|
|
48
36
|
# set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
|
49
37
|
# set.valid_string #=> "1:10,55,1024:2048"
|
50
38
|
#
|
51
|
-
#
|
52
|
-
#
|
39
|
+
# SequenceSet.new with no arguments creates an empty sequence set. Note
|
40
|
+
# that an empty sequence set is invalid in the \IMAP grammar.
|
41
|
+
#
|
42
|
+
# set = Net::IMAP::SequenceSet.new
|
43
|
+
# set.empty? #=> true
|
44
|
+
# set.valid? #=> false
|
45
|
+
# set.valid_string #!> raises DataFormatError
|
46
|
+
# set << 1..10
|
47
|
+
# set.empty? #=> false
|
48
|
+
# set.valid? #=> true
|
49
|
+
# set.valid_string #=> "1:10"
|
50
|
+
#
|
51
|
+
# Using SequenceSet.new with another SequenceSet input behaves the same as
|
52
|
+
# calling #dup on the other set. The input's #string will be preserved.
|
53
|
+
#
|
54
|
+
# input = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
|
55
|
+
# copy = Net::IMAP::SequenceSet.new(input)
|
56
|
+
# input.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
57
|
+
# copy.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
58
|
+
# copy2 = input.dup # same as calling new with a SequenceSet input
|
59
|
+
# copy == input #=> true, same set membership
|
60
|
+
# copy.eql? input #=> true, same string value
|
61
|
+
# copy.equal? input #=> false, different objects
|
62
|
+
#
|
63
|
+
# copy.normalize!
|
64
|
+
# copy.valid_string #=> "1:10,1024,2048"
|
65
|
+
# copy == input #=> true, same set membership
|
66
|
+
# copy.eql? input #=> false, different string value
|
53
67
|
#
|
68
|
+
# copy << 999
|
69
|
+
# copy.valid_string #=> "1:10,999,1024,2048"
|
70
|
+
# copy == input #=> false, different set membership
|
71
|
+
# copy.eql? input #=> false, different string value
|
72
|
+
#
|
73
|
+
# Use Net::IMAP::SequenceSet() to coerce a single (optional) input.
|
74
|
+
# A SequenceSet input is returned without duplication, even when frozen.
|
75
|
+
#
|
76
|
+
# set = Net::IMAP::SequenceSet()
|
77
|
+
# set.string #=> nil
|
78
|
+
# set.frozen? #=> false
|
79
|
+
#
|
80
|
+
# # String order is preserved
|
81
|
+
# set = Net::IMAP::SequenceSet("1,2,3:7,5,6:10,2048,1024")
|
82
|
+
# set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
83
|
+
# set.frozen? #=> false
|
84
|
+
#
|
85
|
+
# # Other inputs are normalized
|
86
|
+
# set = Net::IMAP::SequenceSet([1, 2, [3..7, 5], 6..10, 2048, 1024])
|
87
|
+
# set.valid_string #=> "1:10,55,1024:2048"
|
88
|
+
# set.frozen? #=> false
|
89
|
+
#
|
90
|
+
# unfrozen = set
|
91
|
+
# frozen = set.dup.freeze
|
92
|
+
# unfrozen.equal? Net::IMAP::SequenceSet(unfrozen) #=> true
|
93
|
+
# frozen.equal? Net::IMAP::SequenceSet(frozen) #=> true
|
94
|
+
#
|
95
|
+
# Use ::[] to coerce one or more arguments into a valid frozen SequenceSet.
|
96
|
+
# A valid frozen SequenceSet is returned directly, without allocating a new
|
97
|
+
# object. ::[] will not create an invalid (empty) set.
|
98
|
+
#
|
99
|
+
# Net::IMAP::SequenceSet[] #!> raises ArgumentError
|
100
|
+
# Net::IMAP::SequenceSet[nil] #!> raises DataFormatError
|
101
|
+
# Net::IMAP::SequenceSet[""] #!> raises DataFormatError
|
102
|
+
#
|
103
|
+
# # String order is preserved
|
54
104
|
# set = Net::IMAP::SequenceSet["1,2,3:7,5,6:10,2048,1024"]
|
55
105
|
# set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
106
|
+
# set.frozen? #=> true
|
107
|
+
#
|
108
|
+
# # Other inputs are normalized
|
56
109
|
# set = Net::IMAP::SequenceSet[1, 2, [3..7, 5], 6..10, 2048, 1024]
|
57
110
|
# set.valid_string #=> "1:10,55,1024:2048"
|
111
|
+
# set.frozen? #=> true
|
112
|
+
#
|
113
|
+
# frozen = set
|
114
|
+
# unfrozen = set.dup
|
115
|
+
# frozen.equal? Net::IMAP::SequenceSet[frozen] #=> true
|
116
|
+
# unfrozen.equal? Net::IMAP::SequenceSet[unfrozen] #=> false
|
117
|
+
#
|
118
|
+
# Objects which respond to +to_sequence_set+ (such as SearchResult and
|
119
|
+
# ThreadMember) can be coerced to a SequenceSet with ::new, ::try_convert,
|
120
|
+
# ::[], or Net::IMAP::SequenceSet.
|
121
|
+
#
|
122
|
+
# search = imap.uid_search(["SUBJECT", "hello", "NOT", "SEEN"])
|
123
|
+
# seqset = Net::IMAP::SequenceSet(search) - already_fetched
|
124
|
+
# fetch = imap.uid_fetch(seqset, "FAST")
|
58
125
|
#
|
59
126
|
# == Ordered and Normalized sets
|
60
127
|
#
|
61
128
|
# Sometimes the order of the set's members is significant, such as with the
|
62
129
|
# +ESORT+, <tt>CONTEXT=SORT</tt>, and +UIDPLUS+ extensions. So, when a
|
63
|
-
# sequence set is created
|
64
|
-
# #string representation is preserved.
|
130
|
+
# sequence set is created from a single string (such as by the parser), that
|
131
|
+
# #string representation is preserved. Assigning a string with #string= or
|
132
|
+
# #replace will also preserve that string. Use #each_entry, #entries, or
|
133
|
+
# #each_ordered_number to enumerate the entries in their #string order.
|
134
|
+
# Hash equality (using #eql?) is based on the string representation.
|
65
135
|
#
|
66
|
-
# Internally, SequenceSet
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# the set in
|
136
|
+
# Internally, SequenceSet uses a normalized uint32 set representation which
|
137
|
+
# sorts and de-duplicates all numbers and coalesces adjacent or overlapping
|
138
|
+
# entries. Many methods use this sorted set representation for <tt>O(lg
|
139
|
+
# n)</tt> searches. Use #each_element, #elements, #each_range, #ranges,
|
140
|
+
# #each_number, or #numbers to enumerate the set in sorted order. Basic
|
141
|
+
# object equality (using #==) is based on set membership, without regard to
|
142
|
+
# #entry order or #string normalization.
|
71
143
|
#
|
72
|
-
# Most modification methods
|
73
|
-
#
|
74
|
-
#
|
144
|
+
# Most modification methods reset #string to its #normalized form, so that
|
145
|
+
# #entries and #elements are identical. Use #append to preserve #entries
|
146
|
+
# order while modifying a set.
|
75
147
|
#
|
76
148
|
# == Using <tt>*</tt>
|
77
149
|
#
|
@@ -153,6 +225,7 @@ module Net
|
|
153
225
|
# * ::new: Creates a new mutable sequence set, which may be empty (invalid).
|
154
226
|
# * ::try_convert: Calls +to_sequence_set+ on an object and verifies that
|
155
227
|
# the result is a SequenceSet.
|
228
|
+
# * Net::IMAP::SequenceSet(): Coerce an input using ::try_convert or ::new.
|
156
229
|
# * ::empty: Returns a frozen empty (invalid) SequenceSet.
|
157
230
|
# * ::full: Returns a frozen SequenceSet containing every possible number.
|
158
231
|
#
|
@@ -178,8 +251,7 @@ module Net
|
|
178
251
|
#
|
179
252
|
# <i>Set membership:</i>
|
180
253
|
# - #include? (aliased as #member?):
|
181
|
-
# Returns whether a given element
|
182
|
-
# contained by the set.
|
254
|
+
# Returns whether a given element is contained by the set.
|
183
255
|
# - #include_star?: Returns whether the set contains <tt>*</tt>.
|
184
256
|
#
|
185
257
|
# <i>Minimum and maximum value elements:</i>
|
@@ -337,13 +409,12 @@ module Net
|
|
337
409
|
# An empty SequenceSet is invalid and will raise a DataFormatError.
|
338
410
|
#
|
339
411
|
# Use ::new to create a mutable or empty SequenceSet.
|
412
|
+
#
|
413
|
+
# Related: ::new, Net::IMAP::SequenceSet(), ::try_convert
|
340
414
|
def [](first, *rest)
|
341
415
|
if rest.empty?
|
342
|
-
|
343
|
-
|
344
|
-
else
|
345
|
-
new(first).validate.freeze
|
346
|
-
end
|
416
|
+
set = try_convert(first)&.validate
|
417
|
+
set&.frozen? ? set : (set&.dup || new(first).validate).freeze
|
347
418
|
else
|
348
419
|
new(first).merge(*rest).validate.freeze
|
349
420
|
end
|
@@ -358,6 +429,8 @@ module Net
|
|
358
429
|
#
|
359
430
|
# If +obj.to_sequence_set+ doesn't return a SequenceSet, an exception is
|
360
431
|
# raised.
|
432
|
+
#
|
433
|
+
# Related: Net::IMAP::SequenceSet(), ::new, ::[]
|
361
434
|
def try_convert(obj)
|
362
435
|
return obj if obj.is_a?(SequenceSet)
|
363
436
|
return nil unless obj.respond_to?(:to_sequence_set)
|
@@ -376,20 +449,85 @@ module Net
|
|
376
449
|
end
|
377
450
|
|
378
451
|
# Create a new SequenceSet object from +input+, which may be another
|
379
|
-
# SequenceSet, an IMAP formatted +sequence-set+ string, a
|
380
|
-
# range, <tt>:*</tt>,
|
381
|
-
#
|
382
|
-
#
|
452
|
+
# SequenceSet, an IMAP formatted +sequence-set+ string, a non-zero 32 bit
|
453
|
+
# unsigned integer, a range, <tt>:*</tt>, a Set of numbers or <tt>*</tt>,
|
454
|
+
# an object that responds to +to_sequence_set+ (such as SearchResult) or
|
455
|
+
# an Array of these (array inputs may be nested).
|
456
|
+
#
|
457
|
+
# set = Net::IMAP::SequenceSet.new(1)
|
458
|
+
# set.valid_string #=> "1"
|
459
|
+
# set = Net::IMAP::SequenceSet.new(1..100)
|
460
|
+
# set.valid_string #=> "1:100"
|
461
|
+
# set = Net::IMAP::SequenceSet.new(1...100)
|
462
|
+
# set.valid_string #=> "1:99"
|
463
|
+
# set = Net::IMAP::SequenceSet.new([1, 2, 5..])
|
464
|
+
# set.valid_string #=> "1:2,5:*"
|
465
|
+
# set = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
|
466
|
+
# set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
467
|
+
# set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
|
468
|
+
# set.valid_string #=> "1:10,55,1024:2048"
|
469
|
+
#
|
470
|
+
# With no arguments (or +nil+) creates an empty sequence set. Note that
|
471
|
+
# an empty sequence set is invalid in the \IMAP grammar.
|
472
|
+
#
|
473
|
+
# set = Net::IMAP::SequenceSet.new
|
474
|
+
# set.empty? #=> true
|
475
|
+
# set.valid? #=> false
|
476
|
+
# set.valid_string #!> raises DataFormatError
|
477
|
+
# set << 1..10
|
478
|
+
# set.empty? #=> false
|
479
|
+
# set.valid? #=> true
|
480
|
+
# set.valid_string #=> "1:10"
|
481
|
+
#
|
482
|
+
# When +input+ is a SequenceSet, ::new behaves the same as calling #dup on
|
483
|
+
# that other set. The input's #string will be preserved.
|
484
|
+
#
|
485
|
+
# input = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
|
486
|
+
# copy = Net::IMAP::SequenceSet.new(input)
|
487
|
+
# input.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
488
|
+
# copy.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
|
489
|
+
# copy2 = input.dup # same as calling new with a SequenceSet input
|
490
|
+
# copy == input #=> true, same set membership
|
491
|
+
# copy.eql? input #=> true, same string value
|
492
|
+
# copy.equal? input #=> false, different objects
|
493
|
+
#
|
494
|
+
# copy.normalize!
|
495
|
+
# copy.valid_string #=> "1:10,1024,2048"
|
496
|
+
# copy == input #=> true, same set membership
|
497
|
+
# copy.eql? input #=> false, different string value
|
498
|
+
#
|
499
|
+
# copy << 999
|
500
|
+
# copy.valid_string #=> "1:10,999,1024,2048"
|
501
|
+
# copy == input #=> false, different set membership
|
502
|
+
# copy.eql? input #=> false, different string value
|
503
|
+
#
|
504
|
+
# === Alternative set creation methods
|
505
|
+
#
|
506
|
+
# * ::[] returns a frozen validated (non-empty) SequenceSet, without
|
507
|
+
# allocating a new object when the input is already a valid frozen
|
508
|
+
# SequenceSet.
|
509
|
+
# * Net::IMAP::SequenceSet() coerces an input to SequenceSet, without
|
510
|
+
# allocating a new object when the input is already a SequenceSet.
|
511
|
+
# * ::try_convert calls +to_sequence_set+ on inputs that support it and
|
512
|
+
# returns +nil+ for inputs that don't.
|
513
|
+
# * ::empty and ::full both return frozen singleton sets which can be
|
514
|
+
# combined with set operations (#|, #&, #^, #-, etc) to make new sets.
|
515
|
+
#
|
516
|
+
# See SequenceSet@Creating+sequence+sets.
|
383
517
|
def initialize(input = nil) input ? replace(input) : clear end
|
384
518
|
|
385
519
|
# Removes all elements and returns self.
|
386
|
-
def clear
|
520
|
+
def clear
|
521
|
+
modifying! # redundant check, to normalize the error message for JRuby
|
522
|
+
@tuples, @string = [], nil
|
523
|
+
self
|
524
|
+
end
|
387
525
|
|
388
526
|
# Replace the contents of the set with the contents of +other+ and returns
|
389
527
|
# +self+.
|
390
528
|
#
|
391
|
-
# +other+ may be another SequenceSet
|
392
|
-
#
|
529
|
+
# +other+ may be another SequenceSet or any other object that would be
|
530
|
+
# accepted by ::new.
|
393
531
|
def replace(other)
|
394
532
|
case other
|
395
533
|
when SequenceSet then initialize_dup(other)
|
@@ -439,11 +577,13 @@ module Net
|
|
439
577
|
if str.nil?
|
440
578
|
clear
|
441
579
|
else
|
580
|
+
modifying! # redundant check, to normalize the error message for JRuby
|
442
581
|
str = String.try_convert(str) or raise ArgumentError, "not a string"
|
443
582
|
tuples = str_to_tuples str
|
444
583
|
@tuples, @string = [], -str
|
445
584
|
tuples_add tuples
|
446
585
|
end
|
586
|
+
str
|
447
587
|
end
|
448
588
|
|
449
589
|
# Returns the \IMAP +sequence-set+ string representation, or an empty
|
@@ -503,8 +643,9 @@ module Net
|
|
503
643
|
|
504
644
|
# :call-seq: self === other -> true | false | nil
|
505
645
|
#
|
506
|
-
# Returns whether +other+ is contained within the set.
|
507
|
-
#
|
646
|
+
# Returns whether +other+ is contained within the set. +other+ may be any
|
647
|
+
# object that would be accepted by ::new. Returns +nil+ if StandardError
|
648
|
+
# is raised while converting +other+ to a comparable type.
|
508
649
|
#
|
509
650
|
# Related: #cover?, #include?, #include_star?
|
510
651
|
def ===(other)
|
@@ -518,12 +659,12 @@ module Net
|
|
518
659
|
# Returns whether +other+ is contained within the set. +other+ may be any
|
519
660
|
# object that would be accepted by ::new.
|
520
661
|
#
|
521
|
-
# Related: #===, #include?, #include_star?
|
662
|
+
# Related: #===, #include?, #include_star?, #intersect?
|
522
663
|
def cover?(other) input_to_tuples(other).none? { !include_tuple?(_1) } end
|
523
664
|
|
524
665
|
# Returns +true+ when a given number or range is in +self+, and +false+
|
525
|
-
# otherwise. Returns +
|
526
|
-
# <tt>*</tt
|
666
|
+
# otherwise. Returns +nil+ when +number+ isn't a valid SequenceSet
|
667
|
+
# element (Integer, Range, <tt>*</tt>, +sequence-set+ string).
|
527
668
|
#
|
528
669
|
# set = Net::IMAP::SequenceSet["5:10,100,111:115"]
|
529
670
|
# set.include? 1 #=> false
|
@@ -531,8 +672,8 @@ module Net
|
|
531
672
|
# set.include? 11..20 #=> false
|
532
673
|
# set.include? 100 #=> true
|
533
674
|
# set.include? 6 #=> true, covered by "5:10"
|
534
|
-
# set.include?
|
535
|
-
# set.include? "
|
675
|
+
# set.include? 6..9 #=> true, covered by "5:10"
|
676
|
+
# set.include? "6:9" #=> true, strings are parsed
|
536
677
|
# set.include? 4..9 #=> false, intersection is not sufficient
|
537
678
|
# set.include? "*" #=> false, use #limit to re-interpret "*"
|
538
679
|
# set.include? -1 #=> false, -1 is interpreted as "*"
|
@@ -541,11 +682,14 @@ module Net
|
|
541
682
|
# set.include? :* #=> true
|
542
683
|
# set.include? "*" #=> true
|
543
684
|
# set.include? -1 #=> true
|
544
|
-
# set.include?
|
545
|
-
# set.include?
|
685
|
+
# set.include?(200..) #=> true
|
686
|
+
# set.include?(100..) #=> false
|
546
687
|
#
|
547
|
-
# Related: #include_star?, #cover?,
|
548
|
-
def include?(element)
|
688
|
+
# Related: #include_star?, #cover?, #===, #intersect?
|
689
|
+
def include?(element)
|
690
|
+
tuple = input_to_tuple element rescue nil
|
691
|
+
!!include_tuple?(tuple) if tuple
|
692
|
+
end
|
549
693
|
|
550
694
|
alias member? include?
|
551
695
|
|
@@ -558,7 +702,7 @@ module Net
|
|
558
702
|
# Net::IMAP::SequenceSet["5:10"].intersect? "7,9,11" #=> true
|
559
703
|
# Net::IMAP::SequenceSet["5:10"].intersect? "11:33" #=> false
|
560
704
|
#
|
561
|
-
# Related: #intersection, #disjoint?
|
705
|
+
# Related: #intersection, #disjoint?, #cover?, #include?
|
562
706
|
def intersect?(other)
|
563
707
|
valid? && input_to_tuples(other).any? { intersect_tuple? _1 }
|
564
708
|
end
|
@@ -577,7 +721,7 @@ module Net
|
|
577
721
|
|
578
722
|
# :call-seq:
|
579
723
|
# max(star: :*) => integer or star or nil
|
580
|
-
# max(count
|
724
|
+
# max(count) => SequenceSet
|
581
725
|
#
|
582
726
|
# Returns the maximum value in +self+, +star+ when the set includes
|
583
727
|
# <tt>*</tt>, or +nil+ when the set is empty.
|
@@ -597,7 +741,7 @@ module Net
|
|
597
741
|
|
598
742
|
# :call-seq:
|
599
743
|
# min(star: :*) => integer or star or nil
|
600
|
-
# min(count
|
744
|
+
# min(count) => SequenceSet
|
601
745
|
#
|
602
746
|
# Returns the minimum value in +self+, +star+ when the only value in the
|
603
747
|
# set is <tt>*</tt>, or +nil+ when the set is empty.
|
@@ -615,10 +759,11 @@ module Net
|
|
615
759
|
end
|
616
760
|
end
|
617
761
|
|
618
|
-
# :call-seq: minmax(star: :*) =>
|
762
|
+
# :call-seq: minmax(star: :*) => [min, max] or nil
|
619
763
|
#
|
620
764
|
# Returns a 2-element array containing the minimum and maximum numbers in
|
621
|
-
# +self+, or +nil+ when the set is empty.
|
765
|
+
# +self+, or +nil+ when the set is empty. +star+ is handled the same way
|
766
|
+
# as by #min and #max.
|
622
767
|
#
|
623
768
|
# Related: #min, #max
|
624
769
|
def minmax(star: :*); [min(star: star), max(star: star)] unless empty? end
|
@@ -640,9 +785,7 @@ module Net
|
|
640
785
|
# Returns a new sequence set that has every number in the +other+ object
|
641
786
|
# added.
|
642
787
|
#
|
643
|
-
# +other+ may be any object that would be accepted by ::new
|
644
|
-
# bit unsigned integer, range, <tt>sequence-set</tt> formatted string,
|
645
|
-
# another sequence set, or an enumerable containing any of these.
|
788
|
+
# +other+ may be any object that would be accepted by ::new.
|
646
789
|
#
|
647
790
|
# Net::IMAP::SequenceSet["1:5"] | 2 | [4..6, 99]
|
648
791
|
# #=> Net::IMAP::SequenceSet["1:6,99"]
|
@@ -666,9 +809,7 @@ module Net
|
|
666
809
|
# Returns a new sequence set built by duplicating this set and removing
|
667
810
|
# every number that appears in +other+.
|
668
811
|
#
|
669
|
-
# +other+ may be any object that would be accepted by ::new
|
670
|
-
# bit unsigned integer, range, <tt>sequence-set</tt> formatted string,
|
671
|
-
# another sequence set, or an enumerable containing any of these.
|
812
|
+
# +other+ may be any object that would be accepted by ::new.
|
672
813
|
#
|
673
814
|
# Net::IMAP::SequenceSet[1..5] - 2 - 4 - 6
|
674
815
|
# #=> Net::IMAP::SequenceSet["1,3,5"]
|
@@ -678,7 +819,7 @@ module Net
|
|
678
819
|
# ==== Set identities
|
679
820
|
#
|
680
821
|
# <tt>lhs - rhs</tt> is equivalent to:
|
681
|
-
# * <tt>~
|
822
|
+
# * <tt>~rhs - ~lhs</tt>
|
682
823
|
# * <tt>lhs & ~rhs</tt>
|
683
824
|
# * <tt>~(~lhs | rhs)</tt>
|
684
825
|
# * <tt>lhs & (lhs ^ rhs)</tt>
|
@@ -694,9 +835,7 @@ module Net
|
|
694
835
|
# Returns a new sequence set containing only the numbers common to this
|
695
836
|
# set and +other+.
|
696
837
|
#
|
697
|
-
# +other+ may be any object that would be accepted by ::new
|
698
|
-
# bit unsigned integer, range, <tt>sequence-set</tt> formatted string,
|
699
|
-
# another sequence set, or an enumerable containing any of these.
|
838
|
+
# +other+ may be any object that would be accepted by ::new.
|
700
839
|
#
|
701
840
|
# Net::IMAP::SequenceSet[1..5] & [2, 4, 6]
|
702
841
|
# #=> Net::IMAP::SequenceSet["2,4"]
|
@@ -724,9 +863,7 @@ module Net
|
|
724
863
|
# Returns a new sequence set containing numbers that are exclusive between
|
725
864
|
# this set and +other+.
|
726
865
|
#
|
727
|
-
# +other+ may be any object that would be accepted by ::new
|
728
|
-
# bit unsigned integer, range, <tt>sequence-set</tt> formatted string,
|
729
|
-
# another sequence set, or an enumerable containing any of these.
|
866
|
+
# +other+ may be any object that would be accepted by ::new.
|
730
867
|
#
|
731
868
|
# Net::IMAP::SequenceSet[1..5] ^ [2, 4, 6]
|
732
869
|
# #=> Net::IMAP::SequenceSet["1,3,5:6"]
|
@@ -776,10 +913,11 @@ module Net
|
|
776
913
|
# #string will be regenerated. Use #merge to add many elements at once.
|
777
914
|
#
|
778
915
|
# Use #append to append new elements to #string. See
|
779
|
-
#
|
916
|
+
# SequenceSet@Ordered+and+Normalized+sets.
|
780
917
|
#
|
781
918
|
# Related: #add?, #merge, #union, #append
|
782
919
|
def add(element)
|
920
|
+
modifying! # short-circuit before input_to_tuple
|
783
921
|
tuple_add input_to_tuple element
|
784
922
|
normalize!
|
785
923
|
end
|
@@ -790,11 +928,11 @@ module Net
|
|
790
928
|
# Unlike #add, #merge, or #union, the new value is appended to #string.
|
791
929
|
# This may result in a #string which has duplicates or is out-of-order.
|
792
930
|
#
|
793
|
-
# See
|
931
|
+
# See SequenceSet@Ordered+and+Normalized+sets.
|
794
932
|
#
|
795
933
|
# Related: #add, #merge, #union
|
796
934
|
def append(entry)
|
797
|
-
modifying!
|
935
|
+
modifying! # short-circuit before input_to_tuple
|
798
936
|
tuple = input_to_tuple entry
|
799
937
|
entry = tuple_to_str tuple
|
800
938
|
string unless empty? # write @string before tuple_add
|
@@ -812,6 +950,7 @@ module Net
|
|
812
950
|
#
|
813
951
|
# Related: #add, #merge, #union, #include?
|
814
952
|
def add?(element)
|
953
|
+
modifying! # short-circuit before include?
|
815
954
|
add element unless include? element
|
816
955
|
end
|
817
956
|
|
@@ -824,6 +963,7 @@ module Net
|
|
824
963
|
#
|
825
964
|
# Related: #delete?, #delete_at, #subtract, #difference
|
826
965
|
def delete(element)
|
966
|
+
modifying! # short-circuit before input_to_tuple
|
827
967
|
tuple_subtract input_to_tuple element
|
828
968
|
normalize!
|
829
969
|
end
|
@@ -861,6 +1001,7 @@ module Net
|
|
861
1001
|
#
|
862
1002
|
# Related: #delete, #delete_at, #subtract, #difference, #disjoint?
|
863
1003
|
def delete?(element)
|
1004
|
+
modifying! # short-circuit before input_to_tuple
|
864
1005
|
tuple = input_to_tuple element
|
865
1006
|
if tuple.first == tuple.last
|
866
1007
|
return unless include_tuple? tuple
|
@@ -901,6 +1042,7 @@ module Net
|
|
901
1042
|
#
|
902
1043
|
# Related: #slice, #delete_at, #delete, #delete?, #subtract, #difference
|
903
1044
|
def slice!(index, length = nil)
|
1045
|
+
modifying! # short-circuit before slice
|
904
1046
|
deleted = slice(index, length) and subtract deleted
|
905
1047
|
deleted
|
906
1048
|
end
|
@@ -908,14 +1050,13 @@ module Net
|
|
908
1050
|
# Merges all of the elements that appear in any of the +sets+ into the
|
909
1051
|
# set, and returns +self+.
|
910
1052
|
#
|
911
|
-
# The +sets+ may be any objects that would be accepted by ::new
|
912
|
-
# 32 bit unsigned integers, ranges, <tt>sequence-set</tt> formatted
|
913
|
-
# strings, other sequence sets, or enumerables containing any of these.
|
1053
|
+
# The +sets+ may be any objects that would be accepted by ::new.
|
914
1054
|
#
|
915
1055
|
# #string will be regenerated after all sets have been merged.
|
916
1056
|
#
|
917
1057
|
# Related: #add, #add?, #union
|
918
1058
|
def merge(*sets)
|
1059
|
+
modifying! # short-circuit before input_to_tuples
|
919
1060
|
tuples_add input_to_tuples sets
|
920
1061
|
normalize!
|
921
1062
|
end
|
@@ -923,9 +1064,7 @@ module Net
|
|
923
1064
|
# Removes all of the elements that appear in any of the given +sets+ from
|
924
1065
|
# the set, and returns +self+.
|
925
1066
|
#
|
926
|
-
# The +sets+ may be any objects that would be accepted by ::new
|
927
|
-
# 32 bit unsigned integers, ranges, <tt>sequence-set</tt> formatted
|
928
|
-
# strings, other sequence sets, or enumerables containing any of these.
|
1067
|
+
# The +sets+ may be any objects that would be accepted by ::new.
|
929
1068
|
#
|
930
1069
|
# Related: #difference
|
931
1070
|
def subtract(*sets)
|
@@ -941,7 +1080,7 @@ module Net
|
|
941
1080
|
# This is useful when the given order is significant, for example in a
|
942
1081
|
# ESEARCH response to IMAP#sort.
|
943
1082
|
#
|
944
|
-
# See
|
1083
|
+
# See SequenceSet@Ordered+and+Normalized+sets.
|
945
1084
|
#
|
946
1085
|
# Related: #each_entry, #elements
|
947
1086
|
def entries; each_entry.to_a end
|
@@ -950,7 +1089,7 @@ module Net
|
|
950
1089
|
#
|
951
1090
|
# The returned elements are sorted and coalesced, even when the input
|
952
1091
|
# #string is not. <tt>*</tt> will sort last. See #normalize,
|
953
|
-
#
|
1092
|
+
# SequenceSet@Ordered+and+Normalized+sets.
|
954
1093
|
#
|
955
1094
|
# By itself, <tt>*</tt> translates to <tt>:*</tt>. A range containing
|
956
1095
|
# <tt>*</tt> translates to an endless range. Use #limit to translate both
|
@@ -967,7 +1106,7 @@ module Net
|
|
967
1106
|
#
|
968
1107
|
# The returned elements are sorted and coalesced, even when the input
|
969
1108
|
# #string is not. <tt>*</tt> will sort last. See #normalize,
|
970
|
-
#
|
1109
|
+
# SequenceSet@Ordered+and+Normalized+sets.
|
971
1110
|
#
|
972
1111
|
# <tt>*</tt> translates to an endless range. By itself, <tt>*</tt>
|
973
1112
|
# translates to <tt>:*..</tt>. Use #limit to set <tt>*</tt> to a maximum
|
@@ -984,7 +1123,7 @@ module Net
|
|
984
1123
|
# Returns a sorted array of all of the number values in the sequence set.
|
985
1124
|
#
|
986
1125
|
# The returned numbers are sorted and de-duplicated, even when the input
|
987
|
-
# #string is not. See #normalize,
|
1126
|
+
# #string is not. See #normalize, SequenceSet@Ordered+and+Normalized+sets.
|
988
1127
|
#
|
989
1128
|
# Net::IMAP::SequenceSet["2,5:9,6,12:11"].numbers
|
990
1129
|
# #=> [2, 5, 6, 7, 8, 9, 11, 12]
|
@@ -1016,7 +1155,7 @@ module Net
|
|
1016
1155
|
# no sorting, deduplication, or coalescing. When #string is in its
|
1017
1156
|
# normalized form, this will yield the same values as #each_element.
|
1018
1157
|
#
|
1019
|
-
# See
|
1158
|
+
# See SequenceSet@Ordered+and+Normalized+sets.
|
1020
1159
|
#
|
1021
1160
|
# Related: #entries, #each_element
|
1022
1161
|
def each_entry(&block) # :yields: integer or range or :*
|
@@ -1028,7 +1167,7 @@ module Net
|
|
1028
1167
|
# and returns self. Returns an enumerator when called without a block.
|
1029
1168
|
#
|
1030
1169
|
# The returned numbers are sorted and de-duplicated, even when the input
|
1031
|
-
# #string is not. See #normalize,
|
1170
|
+
# #string is not. See #normalize, SequenceSet@Ordered+and+Normalized+sets.
|
1032
1171
|
#
|
1033
1172
|
# Related: #elements, #each_entry
|
1034
1173
|
def each_element # :yields: integer or range or :*
|
@@ -1424,6 +1563,7 @@ module Net
|
|
1424
1563
|
#
|
1425
1564
|
# Related: #limit
|
1426
1565
|
def limit!(max:)
|
1566
|
+
modifying! # short-circuit, and normalize the error message for JRuby
|
1427
1567
|
star = include_star?
|
1428
1568
|
max = to_tuple_int(max)
|
1429
1569
|
tuple_subtract [max + 1, STAR_INT]
|
@@ -1438,6 +1578,7 @@ module Net
|
|
1438
1578
|
#
|
1439
1579
|
# Related: #complement
|
1440
1580
|
def complement!
|
1581
|
+
modifying! # short-circuit, and normalize the error message for JRuby
|
1441
1582
|
return replace(self.class.full) if empty?
|
1442
1583
|
return clear if full?
|
1443
1584
|
flat = @tuples.flat_map { [_1 - 1, _2 + 1] }
|
@@ -1451,7 +1592,7 @@ module Net
|
|
1451
1592
|
#
|
1452
1593
|
# The returned set's #string is sorted and deduplicated. Adjacent or
|
1453
1594
|
# overlapping elements will be merged into a single larger range.
|
1454
|
-
# See
|
1595
|
+
# See SequenceSet@Ordered+and+Normalized+sets.
|
1455
1596
|
#
|
1456
1597
|
# Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalize
|
1457
1598
|
# #=> Net::IMAP::SequenceSet["1:7,9:11"]
|
@@ -1464,17 +1605,18 @@ module Net
|
|
1464
1605
|
end
|
1465
1606
|
|
1466
1607
|
# Resets #string to be sorted, deduplicated, and coalesced. Returns
|
1467
|
-
# +self+. See
|
1608
|
+
# +self+. See SequenceSet@Ordered+and+Normalized+sets.
|
1468
1609
|
#
|
1469
1610
|
# Related: #normalize, #normalized_string
|
1470
1611
|
def normalize!
|
1612
|
+
modifying! # redundant check, to normalize the error message for JRuby
|
1471
1613
|
@string = nil
|
1472
1614
|
self
|
1473
1615
|
end
|
1474
1616
|
|
1475
1617
|
# Returns a normalized +sequence-set+ string representation, sorted
|
1476
1618
|
# and deduplicated. Adjacent or overlapping elements will be merged into
|
1477
|
-
# a single larger range. See
|
1619
|
+
# a single larger range. See SequenceSet@Ordered+and+Normalized+sets.
|
1478
1620
|
#
|
1479
1621
|
# Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalized_string
|
1480
1622
|
# #=> "1:7,9:11"
|
@@ -1496,7 +1638,15 @@ module Net
|
|
1496
1638
|
end
|
1497
1639
|
end
|
1498
1640
|
|
1499
|
-
|
1641
|
+
##
|
1642
|
+
# :method: to_sequence_set
|
1643
|
+
# :call-seq: to_sequence_set -> self
|
1644
|
+
#
|
1645
|
+
# Returns +self+
|
1646
|
+
#
|
1647
|
+
# Related: ::try_convert
|
1648
|
+
|
1649
|
+
# :nodoc: (work around rdoc bug)
|
1500
1650
|
alias to_sequence_set itself
|
1501
1651
|
|
1502
1652
|
# Unstable API: currently for internal use only (Net::IMAP#validate_data)
|
@@ -1537,6 +1687,7 @@ module Net
|
|
1537
1687
|
end
|
1538
1688
|
|
1539
1689
|
def initialize_dup(other)
|
1690
|
+
modifying! # redundant check, to normalize the error message for JRuby
|
1540
1691
|
@tuples = other.tuples.map(&:dup)
|
1541
1692
|
@string = other.string&.-@
|
1542
1693
|
super
|
@@ -1563,9 +1714,8 @@ module Net
|
|
1563
1714
|
when Array then set.flat_map { input_to_tuples _1 }
|
1564
1715
|
when nil then []
|
1565
1716
|
else
|
1566
|
-
raise DataFormatError,
|
1567
|
-
|
1568
|
-
"got %p" % [set]
|
1717
|
+
raise DataFormatError, "expected nz-number, range, '*', Set, Array; " \
|
1718
|
+
"got %p" % [set]
|
1569
1719
|
end
|
1570
1720
|
end
|
1571
1721
|
|
data/lib/net/imap.rb
CHANGED
@@ -788,7 +788,7 @@ module Net
|
|
788
788
|
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
789
789
|
#
|
790
790
|
class IMAP < Protocol
|
791
|
-
VERSION = "0.5.
|
791
|
+
VERSION = "0.5.9"
|
792
792
|
|
793
793
|
# Aliases for supported capabilities, to be used with the #enable command.
|
794
794
|
ENABLE_ALIASES = {
|
@@ -801,6 +801,7 @@ module Net
|
|
801
801
|
autoload :ResponseReader, "#{dir}/response_reader"
|
802
802
|
autoload :SASL, "#{dir}/sasl"
|
803
803
|
autoload :SASLAdapter, "#{dir}/sasl_adapter"
|
804
|
+
autoload :SequenceSet, "#{dir}/sequence_set"
|
804
805
|
autoload :StringPrep, "#{dir}/stringprep"
|
805
806
|
|
806
807
|
include MonitorMixin
|
@@ -809,6 +810,22 @@ module Net
|
|
809
810
|
include SSL
|
810
811
|
end
|
811
812
|
|
813
|
+
# :call-seq:
|
814
|
+
# Net::IMAP::SequenceSet(set = nil) -> SequenceSet
|
815
|
+
#
|
816
|
+
# Coerces +set+ into a SequenceSet, using either SequenceSet.try_convert or
|
817
|
+
# SequenceSet.new.
|
818
|
+
#
|
819
|
+
# * When +set+ is a SequenceSet, that same set is returned.
|
820
|
+
# * When +set+ responds to +to_sequence_set+, +set.to_sequence_set+ is
|
821
|
+
# returned.
|
822
|
+
# * Otherwise, returns the result from calling SequenceSet.new with +set+.
|
823
|
+
#
|
824
|
+
# Related: SequenceSet.try_convert, SequenceSet.new, SequenceSet::[]
|
825
|
+
def self.SequenceSet(set = nil)
|
826
|
+
SequenceSet.try_convert(set) || SequenceSet.new(set)
|
827
|
+
end
|
828
|
+
|
812
829
|
# Returns the global Config object
|
813
830
|
def self.config; Config.global end
|
814
831
|
|
@@ -1114,28 +1131,27 @@ module Net
|
|
1114
1131
|
|
1115
1132
|
# Disconnects from the server.
|
1116
1133
|
#
|
1134
|
+
# Waits for receiver thread to close before returning. Slow or stuck
|
1135
|
+
# response handlers can cause #disconnect to hang until they complete.
|
1136
|
+
#
|
1117
1137
|
# Related: #logout, #logout!
|
1118
1138
|
def disconnect
|
1139
|
+
in_logout_state = try_state_logout?
|
1119
1140
|
return if disconnected?
|
1120
|
-
state_logout!
|
1121
1141
|
begin
|
1122
|
-
|
1123
|
-
# try to call SSL::SSLSocket#io.
|
1124
|
-
@sock.io.shutdown
|
1125
|
-
rescue NoMethodError
|
1126
|
-
# @sock is not an SSL::SSLSocket.
|
1127
|
-
@sock.shutdown
|
1128
|
-
end
|
1142
|
+
@sock.to_io.shutdown
|
1129
1143
|
rescue Errno::ENOTCONN
|
1130
1144
|
# ignore `Errno::ENOTCONN: Socket is not connected' on some platforms.
|
1131
1145
|
rescue Exception => e
|
1132
1146
|
@receiver_thread.raise(e)
|
1133
1147
|
end
|
1148
|
+
@sock.close
|
1134
1149
|
@receiver_thread.join
|
1135
|
-
synchronize do
|
1136
|
-
@sock.close
|
1137
|
-
end
|
1138
1150
|
raise e if e
|
1151
|
+
ensure
|
1152
|
+
# Try again after shutting down the receiver thread. With no reciever
|
1153
|
+
# left to wait for, any remaining locks should be _very_ brief.
|
1154
|
+
state_logout! unless in_logout_state
|
1139
1155
|
end
|
1140
1156
|
|
1141
1157
|
# Returns true if disconnected from the server.
|
@@ -3062,8 +3078,8 @@ module Net
|
|
3062
3078
|
raise @exception || Net::IMAP::Error.new("connection closed")
|
3063
3079
|
end
|
3064
3080
|
ensure
|
3081
|
+
remove_response_handler(response_handler)
|
3065
3082
|
unless @receiver_thread_terminating
|
3066
|
-
remove_response_handler(response_handler)
|
3067
3083
|
put_string("DONE#{CRLF}")
|
3068
3084
|
response = get_tagged_response(tag, "IDLE", idle_response_timeout)
|
3069
3085
|
end
|
@@ -3346,8 +3362,6 @@ module Net
|
|
3346
3362
|
rescue Exception => ex
|
3347
3363
|
@receiver_thread_exception = ex
|
3348
3364
|
# don't exit the thread with an exception
|
3349
|
-
ensure
|
3350
|
-
state_logout!
|
3351
3365
|
end
|
3352
3366
|
end
|
3353
3367
|
|
@@ -3429,6 +3443,8 @@ module Net
|
|
3429
3443
|
@idle_done_cond.signal
|
3430
3444
|
end
|
3431
3445
|
end
|
3446
|
+
ensure
|
3447
|
+
state_logout!
|
3432
3448
|
end
|
3433
3449
|
|
3434
3450
|
def get_tagged_response(tag, cmd, timeout = nil)
|
@@ -3791,15 +3807,29 @@ module Net
|
|
3791
3807
|
end
|
3792
3808
|
|
3793
3809
|
def state_unselected!
|
3794
|
-
|
3810
|
+
synchronize do
|
3811
|
+
state_authenticated! if connection_state.to_sym == :selected
|
3812
|
+
end
|
3795
3813
|
end
|
3796
3814
|
|
3797
3815
|
def state_logout!
|
3816
|
+
return true if connection_state in [:logout, *]
|
3798
3817
|
synchronize do
|
3818
|
+
return true if connection_state in [:logout, *]
|
3799
3819
|
@connection_state = ConnectionState::Logout.new
|
3800
3820
|
end
|
3801
3821
|
end
|
3802
3822
|
|
3823
|
+
# don't wait to aqcuire the lock
|
3824
|
+
def try_state_logout?
|
3825
|
+
return true if connection_state in [:logout, *]
|
3826
|
+
return false unless acquired_lock = mon_try_enter
|
3827
|
+
state_logout!
|
3828
|
+
true
|
3829
|
+
ensure
|
3830
|
+
mon_exit if acquired_lock
|
3831
|
+
end
|
3832
|
+
|
3803
3833
|
def sasl_adapter
|
3804
3834
|
SASLAdapter.new(self, &method(:send_command_with_continuations))
|
3805
3835
|
end
|
@@ -388,9 +388,11 @@ class StringPrepTablesGenerator
|
|
388
388
|
end
|
389
389
|
|
390
390
|
def asgn_mapping(name, replacement = to_map(tables[name]))
|
391
|
+
indent = " " * 2
|
392
|
+
replacement = replacement.inspect.gsub(/" => "/, '"=>"')
|
391
393
|
cname = name.tr(?., ?_).upcase
|
392
|
-
"# Replacements for %s\n%s%s = %
|
393
|
-
"IN_#{name}",
|
394
|
+
"# Replacements for %s\n%s%s = %s.freeze" % [
|
395
|
+
"IN_#{name}", indent, "MAP_#{cname}", replacement,
|
394
396
|
]
|
395
397
|
end
|
396
398
|
|