lib/net/imap.rb: support CHANGEDSINCE and MODSEQ

Patch by plehoux (Philippe-Antoine Lehoux).  [ruby-core:64272] [Feature #10119]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59424 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shugo 2017-07-26 07:47:34 +00:00
Родитель dc9fad3a1d
Коммит ae91976d56
2 изменённых файлов: 52 добавлений и 8 удалений

Просмотреть файл

@ -814,13 +814,13 @@ module Net
# #=> "12-Oct-2000 22:40:59 +0900" # #=> "12-Oct-2000 22:40:59 +0900"
# p data.attr["UID"] # p data.attr["UID"]
# #=> 98 # #=> 98
def fetch(set, attr) def fetch(set, attr, mod = nil)
return fetch_internal("FETCH", set, attr) return fetch_internal("FETCH", set, attr, mod)
end end
# Similar to #fetch(), but +set+ contains unique identifiers. # Similar to #fetch(), but +set+ contains unique identifiers.
def uid_fetch(set, attr) def uid_fetch(set, attr, mod = nil)
return fetch_internal("UID FETCH", set, attr) return fetch_internal("UID FETCH", set, attr, mod)
end end
# Sends a STORE command to alter data associated with messages # Sends a STORE command to alter data associated with messages
@ -1304,9 +1304,13 @@ module Net
when Integer when Integer
NumValidator.ensure_number(data) NumValidator.ensure_number(data)
when Array when Array
if data[0] == 'CHANGEDSINCE'
NumValidator.ensure_mod_sequence_value(data[1])
else
data.each do |i| data.each do |i|
validate_data(i) validate_data(i)
end end
end
when Time when Time
when Symbol when Symbol
else else
@ -1417,7 +1421,7 @@ module Net
end end
end end
def fetch_internal(cmd, set, attr) def fetch_internal(cmd, set, attr, mod = nil)
case attr case attr
when String then when String then
attr = RawData.new(attr) attr = RawData.new(attr)
@ -1429,7 +1433,11 @@ module Net
synchronize do synchronize do
@responses.delete("FETCH") @responses.delete("FETCH")
if mod
send_command(cmd, MessageSet.new(set), attr, mod)
else
send_command(cmd, MessageSet.new(set), attr) send_command(cmd, MessageSet.new(set), attr)
end
return @responses.delete("FETCH") return @responses.delete("FETCH")
end end
end end
@ -1663,6 +1671,15 @@ module Net
num != 0 && valid_number?(num) num != 0 && valid_number?(num)
end end
# Check is passed argument valid 'mod_sequence_value' in RFC 4551 terminology
def valid_mod_sequence_value?(num)
# mod-sequence-value = 1*DIGIT
# ; Positive unsigned 64-bit integer
# ; (mod-sequence)
# ; (1 <= n < 18,446,744,073,709,551,615)
num >= 1 && num < 18446744073709551615
end
# Ensure argument is 'number' or raise DataFormatError # Ensure argument is 'number' or raise DataFormatError
def ensure_number(num) def ensure_number(num)
return if valid_number?(num) return if valid_number?(num)
@ -1678,6 +1695,14 @@ module Net
msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}" msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}"
raise DataFormatError, msg raise DataFormatError, msg
end end
# Ensure argument is 'mod_sequence_value' or raise DataFormatError
def ensure_mod_sequence_value(num)
return if valid_mod_sequence_value?(num)
msg = "mod_sequence_value must be unsigned 64-bit integer: #{num}"
raise DataFormatError, msg
end
end end
end end
@ -2343,6 +2368,8 @@ module Net
name, val = body_data name, val = body_data
when /\A(?:UID)\z/ni when /\A(?:UID)\z/ni
name, val = uid_data name, val = uid_data
when /\A(?:MODSEQ)\z/ni
name, val = modseq_data
else else
parse_error("unknown attribute `%s' for {%d}", token.value, n) parse_error("unknown attribute `%s' for {%d}", token.value, n)
end end
@ -2832,6 +2859,16 @@ module Net
return name, number return name, number
end end
def modseq_data
token = match(T_ATOM)
name = token.value.upcase
match(T_SPACE)
match(T_LPAR)
modseq = number
match(T_RPAR)
return name, modseq
end
def text_response def text_response
token = match(T_ATOM) token = match(T_ATOM)
name = token.value.upcase name = token.value.upcase

Просмотреть файл

@ -304,4 +304,11 @@ EOF
assert_equal("INBOX", response.data.mailbox) assert_equal("INBOX", response.data.mailbox)
assert_equal(1234, response.data.attr["UIDVALIDITY"]) assert_equal(1234, response.data.attr["UIDVALIDITY"])
end end
# [Bug #10119]
def test_msg_att_modseq_data
parser = Net::IMAP::ResponseParser.new
response = parser.parse("* 1 FETCH (FLAGS (\Seen) MODSEQ (12345) UID 5)\r\n")
assert_equal(12345, response.data.attr["MODSEQ"])
end
end end