Skip to content

Commit bdd8bad

Browse files
authored
🔀 Merge pull request #540 from ruby/drop-uidplus_datauid
🔥 Remove deprecated UIDPlusData class
2 parents d4ada3b + 1c5d21a commit bdd8bad

File tree

7 files changed

+97
-182
lines changed

7 files changed

+97
-182
lines changed

lib/net/imap.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,7 @@ def status(mailbox, attr)
20212021
#
20222022
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
20232023
# supported and the destination supports persistent UIDs, the server's
2024-
# response should include an +APPENDUID+ response code with UIDPlusData.
2024+
# response should include an +APPENDUID+ response code with AppendUIDData.
20252025
# This will report the UIDVALIDITY of the destination mailbox and the
20262026
# assigned UID of the appended message.
20272027
#
@@ -2778,7 +2778,7 @@ def uid_store(set, attr, flags, unchangedsince: nil)
27782778
#
27792779
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
27802780
# supported, the server's response should include a +COPYUID+ response code
2781-
# with UIDPlusData. This will report the UIDVALIDITY of the destination
2781+
# with CopyUIDData. This will report the UIDVALIDITY of the destination
27822782
# mailbox, the UID set of the source messages, and the assigned UID set of
27832783
# the moved messages.
27842784
#
@@ -2819,7 +2819,7 @@ def uid_copy(set, mailbox)
28192819
#
28202820
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
28212821
# supported, the server's response should include a +COPYUID+ response code
2822-
# with UIDPlusData. This will report the UIDVALIDITY of the destination
2822+
# with CopyUIDData. This will report the UIDVALIDITY of the destination
28232823
# mailbox, the UID set of the source messages, and the assigned UID set of
28242824
# the moved messages.
28252825
#

lib/net/imap/config.rb

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -360,39 +360,32 @@ def self.[](config)
360360
#
361361
# Alias for responses_without_block
362362

363-
# Whether ResponseParser should use the deprecated UIDPlusData or
364-
# CopyUIDData for +COPYUID+ response codes, and UIDPlusData or
365-
# AppendUIDData for +APPENDUID+ response codes.
363+
# **NOTE:** <em>+UIDPlusData+ has been removed since +v0.6.0+, and this
364+
# config option only affects deprecation warnings.
365+
# This config option will be **removed** in +v0.7.0+.</em>
366366
#
367-
# UIDPlusData stores its data in arrays of numbers, which is vulnerable to
368-
# a memory exhaustion denial of service attack from an untrusted or
369-
# compromised server. Set this option to +false+ to completely block this
370-
# vulnerability. Otherwise, parser_max_deprecated_uidplus_data_size
371-
# mitigates this vulnerability.
367+
# ResponseParser always returns CopyUIDData for +COPYUID+ response codes,
368+
# and AppendUIDData for +APPENDUID+ response codes. Previously, this
369+
# option determined when UIDPlusData would be returned instead.
372370
#
373-
# AppendUIDData and CopyUIDData are _mostly_ backward-compatible with
374-
# UIDPlusData. Most applications should be able to upgrade with little
375-
# or no changes.
371+
# Parser support for +UIDPLUS+ added in +v0.3.2+.
376372
#
377-
# <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
373+
# Config option added in +v0.4.19+ and +v0.5.6+.
378374
#
379-
# <em>(Config option added in +v0.4.19+ and +v0.5.6+.)</em>
375+
# <em>UIDPlusData removed in +v0.6.0+.</em>
380376
#
381-
# <em>UIDPlusData will be removed in +v0.6+ and this config setting will
382-
# be ignored.</em>
383-
#
384-
# ==== Valid options
377+
# ==== Options
385378
#
386379
# [+true+ <em>(original default)</em>]
387-
# ResponseParser only uses UIDPlusData.
380+
# <em>Since v0.6.0:</em>
381+
# Prints a deprecation warning when parsing +COPYUID+ or +APPENDUID+.
388382
#
389383
# [+:up_to_max_size+ <em>(default since +v0.5.6+)</em>]
390-
# ResponseParser uses UIDPlusData when the +uid-set+ size is below
391-
# parser_max_deprecated_uidplus_data_size. Above that size,
392-
# ResponseParser uses AppendUIDData or CopyUIDData.
384+
# <em>Since v0.6.0:</em>
385+
# Prints a deprecation warning when parsing +COPYUID+ or +APPENDUID+.
393386
#
394-
# [+false+ <em>(planned default for +v0.6+)</em>]
395-
# ResponseParser _only_ uses AppendUIDData and CopyUIDData.
387+
# [+false+ <em>(default since +v0.6.0+)</em>]
388+
# This is the only supported option <em>(since v0.6.0)</em>.
396389
attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
397390
true, :up_to_max_size, false
398391
], defaults: {
@@ -401,22 +394,22 @@ def self.[](config)
401394
0.6r => false,
402395
}
403396

404-
# The maximum +uid-set+ size that ResponseParser will parse into
405-
# deprecated UIDPlusData. This limit only applies when
406-
# parser_use_deprecated_uidplus_data is not +false+.
397+
# **NOTE:** <em>+UIDPlusData+ has been removed since +v0.6.0+, and this
398+
# config option is ignored.
399+
# This config option will be **removed** in +v0.7.0+.</em>
407400
#
408-
# <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
401+
# ResponseParser always returns CopyUIDData for +COPYUID+ response codes,
402+
# and AppendUIDData for +APPENDUID+ response codes. Previously, this
403+
# option determined when UIDPlusData would be returned instead.
409404
#
410-
# <em>Support for limiting UIDPlusData to a maximum size was added in
411-
# +v0.3.8+, +v0.4.19+, and +v0.5.6+.</em>
405+
# Parser support for +UIDPLUS+ added in +v0.3.2+.
412406
#
413-
# <em>UIDPlusData will be removed in +v0.6+.</em>
407+
# Support for limiting UIDPlusData to a maximum size was added in
408+
# +v0.3.8+, +v0.4.19+, and +v0.5.6+.
414409
#
415-
# ==== Versioned Defaults
410+
# <em>UIDPlusData was removed in +v0.6.0+.</em>
416411
#
417-
# Because this limit guards against a remote server causing catastrophic
418-
# memory exhaustion, the versioned default (used by #load_defaults) also
419-
# applies to versions without the feature.
412+
# ==== Versioned Defaults
420413
#
421414
# * +0.3+ and prior: <tt>10,000</tt>
422415
# * +0.4+: <tt>1,000</tt>

lib/net/imap/response_data.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ class IMAP < Protocol
66
autoload :FetchData, "#{__dir__}/fetch_data"
77
autoload :UIDFetchData, "#{__dir__}/fetch_data"
88
autoload :SearchResult, "#{__dir__}/search_result"
9-
autoload :UIDPlusData, "#{__dir__}/uidplus_data"
109
autoload :AppendUIDData, "#{__dir__}/uidplus_data"
1110
autoload :CopyUIDData, "#{__dir__}/uidplus_data"
1211
autoload :VanishedData, "#{__dir__}/vanished_data"
@@ -260,8 +259,8 @@ class ResponseText < Struct.new(:code, :text)
260259
#
261260
# === +UIDPLUS+ extension
262261
# See {[RFC4315 §3]}[https://www.rfc-editor.org/rfc/rfc4315#section-3].
263-
# * +APPENDUID+, #data is UIDPlusData. See IMAP#append.
264-
# * +COPYUID+, #data is UIDPlusData. See IMAP#copy.
262+
# * +APPENDUID+, #data is AppendUIDData. See IMAP#append.
263+
# * +COPYUID+, #data is CopyUIDData. See IMAP#copy.
265264
# * +UIDNOTSTICKY+, #data is +nil+. See IMAP#select.
266265
#
267266
# === +SEARCHRES+ extension

lib/net/imap/response_parser.rb

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,24 +2017,19 @@ def resp_code_copy__data
20172017
CopyUID(validity, src_uids, dst_uids)
20182018
end
20192019

2020-
def AppendUID(...) DeprecatedUIDPlus(...) || AppendUIDData.new(...) end
2021-
def CopyUID(...) DeprecatedUIDPlus(...) || CopyUIDData.new(...) end
2022-
20232020
# TODO: remove this code in the v0.6.0 release
20242021
def DeprecatedUIDPlus(validity, src_uids = nil, dst_uids)
20252022
return unless config.parser_use_deprecated_uidplus_data
2026-
compact_uid_sets = [src_uids, dst_uids].compact
2027-
count = compact_uid_sets.map { _1.count_with_duplicates }.max
2028-
max = config.parser_max_deprecated_uidplus_data_size
2029-
if count <= max
2030-
src_uids &&= src_uids.each_ordered_number.to_a
2031-
dst_uids = dst_uids.each_ordered_number.to_a
2032-
UIDPlusData.new(validity, src_uids, dst_uids)
2033-
elsif config.parser_use_deprecated_uidplus_data != :up_to_max_size
2034-
parse_error("uid-set is too large: %d > %d", count, max)
2035-
end
2023+
warn("#{Config}#parser_use_deprecated_uidplus_data is ignored " \
2024+
"since v0.6.0. Disable this warning by setting " \
2025+
"config.parser_use_deprecated_uidplus_data = false.",
2026+
category: :deprecated, uplevel: 9)
2027+
nil
20362028
end
20372029

2030+
def AppendUID(...) DeprecatedUIDPlus(...) || AppendUIDData.new(...) end
2031+
def CopyUID(...) DeprecatedUIDPlus(...) || CopyUIDData.new(...) end
2032+
20382033
ADDRESS_REGEXP = /\G
20392034
\( (?: NIL | #{Patterns::QUOTED_rev2} ) # 1: NAME
20402035
\s (?: NIL | #{Patterns::QUOTED_rev2} ) # 2: ROUTE

lib/net/imap/uidplus_data.rb

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,8 @@
33
module Net
44
class IMAP < Protocol
55

6-
# *NOTE:* <em>UIDPlusData is deprecated and will be removed in the +0.6.0+
7-
# release.</em> To use AppendUIDData and CopyUIDData before +0.6.0+, set
8-
# Config#parser_use_deprecated_uidplus_data to +false+.
9-
#
10-
# UIDPlusData represents the ResponseCode#data that accompanies the
11-
# +APPENDUID+ and +COPYUID+ {response codes}[rdoc-ref:ResponseCode].
12-
#
13-
# A server that supports +UIDPLUS+ should send UIDPlusData in response to
14-
# the append[rdoc-ref:Net::IMAP#append], copy[rdoc-ref:Net::IMAP#copy],
15-
# move[rdoc-ref:Net::IMAP#move], {uid copy}[rdoc-ref:Net::IMAP#uid_copy],
16-
# and {uid move}[rdoc-ref:Net::IMAP#uid_move] commands---unless the
17-
# destination mailbox reports +UIDNOTSTICKY+.
18-
#
19-
# Note that append[rdoc-ref:Net::IMAP#append], copy[rdoc-ref:Net::IMAP#copy]
20-
# and {uid_copy}[rdoc-ref:Net::IMAP#uid_copy] return UIDPlusData in their
21-
# TaggedResponse. But move[rdoc-ref:Net::IMAP#copy] and
22-
# {uid_move}[rdoc-ref:Net::IMAP#uid_move] _should_ send UIDPlusData in an
23-
# UntaggedResponse response before sending their TaggedResponse. However
24-
# some servers do send UIDPlusData in the TaggedResponse for +MOVE+
25-
# commands---this complies with the older +UIDPLUS+ specification but is
26-
# discouraged by the +MOVE+ extension and disallowed by +IMAP4rev2+.
27-
#
28-
# == Required capability
29-
# Requires either +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315]]
30-
# or +IMAP4rev2+ capability.
31-
#
32-
class UIDPlusData < Struct.new(:uidvalidity, :source_uids, :assigned_uids)
33-
##
34-
# method: uidvalidity
35-
# :call-seq: uidvalidity -> nonzero uint32
36-
#
37-
# The UIDVALIDITY of the destination mailbox.
38-
39-
##
40-
# method: source_uids
41-
# :call-seq: source_uids -> nil or an array of nonzero uint32
42-
#
43-
# The UIDs of the copied or moved messages.
44-
#
45-
# Note:: Returns +nil+ for Net::IMAP#append.
46-
47-
##
48-
# method: assigned_uids
49-
# :call-seq: assigned_uids -> an array of nonzero uint32
50-
#
51-
# The newly assigned UIDs of the copied, moved, or appended messages.
52-
#
53-
# Note:: This always returns an array, even when it contains only one UID.
54-
55-
##
56-
# :call-seq: uid_mapping -> nil or a hash
57-
#
58-
# Returns a hash mapping each source UID to the newly assigned destination
59-
# UID.
60-
#
61-
# Note:: Returns +nil+ for Net::IMAP#append.
62-
def uid_mapping
63-
source_uids&.zip(assigned_uids)&.to_h
64-
end
65-
end
66-
676
# >>>
68-
# *NOTE:* <em>AppendUIDData will replace UIDPlusData for +APPENDUID+ in the
7+
# *NOTE:* <em>AppendUIDData replaced UIDPlusData for +APPENDUID+ in the
698
# +0.6.0+ release.</em> To use AppendUIDData before +0.6.0+, set
709
# Config#parser_use_deprecated_uidplus_data to +false+.
7110
#
@@ -109,7 +48,7 @@ def size
10948
end
11049

11150
# >>>
112-
# *NOTE:* <em>CopyUIDData will replace UIDPlusData for +COPYUID+ in the
51+
# *NOTE:* <em>CopyUIDData replaced UIDPlusData for +COPYUID+ in the
11352
# +0.6.0+ release.</em> To use CopyUIDData before +0.6.0+, set
11453
# Config#parser_use_deprecated_uidplus_data to +false+.
11554
#

test/net/imap/test_response_parser.rb

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -201,28 +201,40 @@ def test_fetch_binary_and_binary_size
201201
end
202202
end
203203

204+
def assert_deprecated_appenduid_data_warning
205+
assert_warn(/#{__FILE__}.*warning.*parser_use_deprecated_uidplus_data is ignored/) do
206+
result = yield
207+
assert_instance_of Net::IMAP::AppendUIDData, result.data.code.data
208+
result
209+
end
210+
end
211+
204212
test "APPENDUID with parser_use_deprecated_uidplus_data = true" do
205213
parser = Net::IMAP::ResponseParser.new(config: {
206214
parser_use_deprecated_uidplus_data: true,
207215
parser_max_deprecated_uidplus_data_size: 10_000,
208216
})
209-
assert_raise_with_message Net::IMAP::ResponseParseError, /uid-set is too large/ do
217+
assert_deprecated_appenduid_data_warning do
210218
parser.parse(
211219
"A004 OK [APPENDUID 1 10000:20000,1] Done\r\n"
212220
)
213221
end
214-
response = parser.parse("A004 OK [APPENDUID 1 100:200] Done\r\n")
222+
response = assert_deprecated_appenduid_data_warning do
223+
parser.parse("A004 OK [APPENDUID 1 100:200] Done\r\n")
224+
end
215225
uidplus = response.data.code.data
216226
assert_equal 101, uidplus.assigned_uids.size
217227
parser.config.parser_max_deprecated_uidplus_data_size = 100
218-
assert_raise_with_message Net::IMAP::ResponseParseError, /uid-set is too large/ do
228+
assert_deprecated_appenduid_data_warning do
219229
parser.parse(
220230
"A004 OK [APPENDUID 1 100:200] Done\r\n"
221231
)
222232
end
223-
response = parser.parse("A004 OK [APPENDUID 1 101:200] Done\r\n")
233+
response = assert_deprecated_appenduid_data_warning do
234+
parser.parse("A004 OK [APPENDUID 1 101:200] Done\r\n")
235+
end
224236
uidplus = response.data.code.data
225-
assert_instance_of Net::IMAP::UIDPlusData, uidplus
237+
assert_instance_of Net::IMAP::AppendUIDData, uidplus
226238
assert_equal 100, uidplus.assigned_uids.size
227239
end
228240

@@ -231,9 +243,13 @@ def test_fetch_binary_and_binary_size
231243
parser_use_deprecated_uidplus_data: :up_to_max_size,
232244
parser_max_deprecated_uidplus_data_size: 100
233245
})
234-
response = parser.parse("A004 OK [APPENDUID 1 101:200] Done\r\n")
235-
assert_instance_of Net::IMAP::UIDPlusData, response.data.code.data
236-
response = parser.parse("A004 OK [APPENDUID 1 100:200] Done\r\n")
246+
response = assert_deprecated_appenduid_data_warning do
247+
parser.parse("A004 OK [APPENDUID 1 101:200] Done\r\n")
248+
end
249+
assert_instance_of Net::IMAP::AppendUIDData, response.data.code.data
250+
response = assert_deprecated_appenduid_data_warning do
251+
parser.parse("A004 OK [APPENDUID 1 100:200] Done\r\n")
252+
end
237253
assert_instance_of Net::IMAP::AppendUIDData, response.data.code.data
238254
end
239255

@@ -242,8 +258,10 @@ def test_fetch_binary_and_binary_size
242258
parser_use_deprecated_uidplus_data: false,
243259
parser_max_deprecated_uidplus_data_size: 10_000_000,
244260
})
245-
response = parser.parse("A004 OK [APPENDUID 1 10] Done\r\n")
246-
assert_instance_of Net::IMAP::AppendUIDData, response.data.code.data
261+
assert_warn("") do
262+
response = parser.parse("A004 OK [APPENDUID 1 10] Done\r\n")
263+
assert_instance_of Net::IMAP::AppendUIDData, response.data.code.data
264+
end
247265
end
248266

249267
test "COPYUID with backwards ranges" do
@@ -276,29 +294,42 @@ def test_fetch_binary_and_binary_size
276294
end
277295
end
278296

297+
def assert_deprecated_copyuid_data_warning(check: true)
298+
assert_warn(/#{__FILE__}.*warning.*parser_use_deprecated_uidplus_data is ignored/) do
299+
result = yield
300+
assert_instance_of Net::IMAP::CopyUIDData, result.data.code.data if check
301+
result
302+
end
303+
end
304+
279305
test "COPYUID with parser_use_deprecated_uidplus_data = true" do
280306
parser = Net::IMAP::ResponseParser.new(config: {
281307
parser_use_deprecated_uidplus_data: true,
282308
parser_max_deprecated_uidplus_data_size: 10_000,
283309
})
284-
assert_raise_with_message Net::IMAP::ResponseParseError, /uid-set is too large/ do
285-
parser.parse(
286-
"A004 OK [copyUID 1 10000:20000,1 1:10001] Done\r\n"
287-
)
310+
assert_deprecated_copyuid_data_warning(check: false) do
311+
assert_raise_with_message Net::IMAP::DataFormatError, /mismatched uid-set sizes/ do
312+
parser.parse(
313+
"A004 OK [copyUID 1 10000:20000,1 1:10001] Done\r\n"
314+
)
315+
end
316+
end
317+
response = assert_deprecated_copyuid_data_warning do
318+
parser.parse("A004 OK [copyUID 1 100:200 1:101] Done\r\n")
288319
end
289-
response = parser.parse("A004 OK [copyUID 1 100:200 1:101] Done\r\n")
290320
uidplus = response.data.code.data
291321
assert_equal 101, uidplus.assigned_uids.size
292322
assert_equal 101, uidplus.source_uids.size
293323
parser.config.parser_max_deprecated_uidplus_data_size = 100
294-
assert_raise_with_message Net::IMAP::ResponseParseError, /uid-set is too large/ do
324+
assert_deprecated_copyuid_data_warning do
295325
parser.parse(
296326
"A004 OK [copyUID 1 100:200 1:101] Done\r\n"
297327
)
298328
end
299-
response = parser.parse("A004 OK [copyUID 1 101:200 1:100] Done\r\n")
329+
response = assert_deprecated_copyuid_data_warning do
330+
parser.parse("A004 OK [copyUID 1 101:200 1:100] Done\r\n")
331+
end
300332
uidplus = response.data.code.data
301-
assert_instance_of Net::IMAP::UIDPlusData, uidplus
302333
assert_equal 100, uidplus.assigned_uids.size
303334
assert_equal 100, uidplus.source_uids.size
304335
end
@@ -308,12 +339,12 @@ def test_fetch_binary_and_binary_size
308339
parser_use_deprecated_uidplus_data: :up_to_max_size,
309340
parser_max_deprecated_uidplus_data_size: 100
310341
})
311-
response = parser.parse("A004 OK [COPYUID 1 101:200 1:100] Done\r\n")
312-
copyuid = response.data.code.data
313-
assert_instance_of Net::IMAP::UIDPlusData, copyuid
314-
response = parser.parse("A004 OK [COPYUID 1 100:200 1:101] Done\r\n")
315-
copyuid = response.data.code.data
316-
assert_instance_of Net::IMAP::CopyUIDData, copyuid
342+
assert_deprecated_copyuid_data_warning do
343+
parser.parse("A004 OK [COPYUID 1 101:200 1:100] Done\r\n")
344+
end
345+
assert_deprecated_copyuid_data_warning do
346+
parser.parse("A004 OK [COPYUID 1 100:200 1:101] Done\r\n")
347+
end
317348
end
318349

319350
test "COPYUID with parser_use_deprecated_uidplus_data = false" do

0 commit comments

Comments
 (0)