summaryrefslogtreecommitdiff
path: root/lib/net/imap.rb
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-07-26 07:47:34 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-07-26 07:47:34 +0000
commitae91976d561e3855753b936fa9ac6048f64e30bd (patch)
tree060ab033fcccab6efca0de440393f2e8867a0c0d /lib/net/imap.rb
parentdc9fad3a1d45f0ef4c408198b63f4f0354fdb575 (diff)
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
Diffstat (limited to 'lib/net/imap.rb')
-rw-r--r--lib/net/imap.rb53
1 files changed, 45 insertions, 8 deletions
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 3f8794cac0..dc185183cd 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -814,13 +814,13 @@ module Net
# #=> "12-Oct-2000 22:40:59 +0900"
# p data.attr["UID"]
# #=> 98
- def fetch(set, attr)
- return fetch_internal("FETCH", set, attr)
+ def fetch(set, attr, mod = nil)
+ return fetch_internal("FETCH", set, attr, mod)
end
# Similar to #fetch(), but +set+ contains unique identifiers.
- def uid_fetch(set, attr)
- return fetch_internal("UID FETCH", set, attr)
+ def uid_fetch(set, attr, mod = nil)
+ return fetch_internal("UID FETCH", set, attr, mod)
end
# Sends a STORE command to alter data associated with messages
@@ -1304,8 +1304,12 @@ module Net
when Integer
NumValidator.ensure_number(data)
when Array
- data.each do |i|
- validate_data(i)
+ if data[0] == 'CHANGEDSINCE'
+ NumValidator.ensure_mod_sequence_value(data[1])
+ else
+ data.each do |i|
+ validate_data(i)
+ end
end
when Time
when Symbol
@@ -1417,7 +1421,7 @@ module Net
end
end
- def fetch_internal(cmd, set, attr)
+ def fetch_internal(cmd, set, attr, mod = nil)
case attr
when String then
attr = RawData.new(attr)
@@ -1429,7 +1433,11 @@ module Net
synchronize do
@responses.delete("FETCH")
- send_command(cmd, MessageSet.new(set), attr)
+ if mod
+ send_command(cmd, MessageSet.new(set), attr, mod)
+ else
+ send_command(cmd, MessageSet.new(set), attr)
+ end
return @responses.delete("FETCH")
end
end
@@ -1663,6 +1671,15 @@ module Net
num != 0 && valid_number?(num)
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
def ensure_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}"
raise DataFormatError, msg
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
@@ -2343,6 +2368,8 @@ module Net
name, val = body_data
when /\A(?:UID)\z/ni
name, val = uid_data
+ when /\A(?:MODSEQ)\z/ni
+ name, val = modseq_data
else
parse_error("unknown attribute `%s' for {%d}", token.value, n)
end
@@ -2832,6 +2859,16 @@ module Net
return name, number
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
token = match(T_ATOM)
name = token.value.upcase