[前][次][番号順一覧][スレッド一覧]

ruby-changes:47309

From: shugo <ko1@a...>
Date: Wed, 26 Jul 2017 16:47:42 +0900 (JST)
Subject: [ruby-changes:47309] shugo:r59424 (trunk): lib/net/imap.rb: support CHANGEDSINCE and MODSEQ

shugo	2017-07-26 16:47:34 +0900 (Wed, 26 Jul 2017)

  New Revision: 59424

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59424

  Log:
    lib/net/imap.rb: support CHANGEDSINCE and MODSEQ
    
    Patch by plehoux (Philippe-Antoine Lehoux).  [ruby-core:64272] [Feature #10119]

  Modified files:
    trunk/lib/net/imap.rb
    trunk/test/net/imap/test_imap_response_parser.rb
Index: lib/net/imap.rb
===================================================================
--- lib/net/imap.rb	(revision 59423)
+++ lib/net/imap.rb	(revision 59424)
@@ -814,13 +814,13 @@ module Net https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L814
     #   #=> "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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L1304
       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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L1421
       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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L1433
 
       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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L1671
           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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L1695
           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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L2368
             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 https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L2859
         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
Index: test/net/imap/test_imap_response_parser.rb
===================================================================
--- test/net/imap/test_imap_response_parser.rb	(revision 59423)
+++ test/net/imap/test_imap_response_parser.rb	(revision 59424)
@@ -304,4 +304,11 @@ EOF https://github.com/ruby/ruby/blob/trunk/test/net/imap/test_imap_response_parser.rb#L304
     assert_equal("INBOX", response.data.mailbox)
     assert_equal(1234, response.data.attr["UIDVALIDITY"])
   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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]