Project

General

Profile

Feature #13379 » imap.patch

ahorek (Pavel Rosický), 03/28/2017 10:34 PM

View differences:

lib/net/imap.rb
18 18
require "monitor"
19 19
require "digest/md5"
20 20
require "strscan"
21
require 'net/protocol'
21 22
begin
22 23
  require "openssl"
23 24
rescue LoadError
......
221 222
    # Returns all response handlers.
222 223
    attr_reader :response_handlers
223 224

  
225
    # Seconds to wait until a connection is opened.
226
    # If the IMAP object cannot open a connection within this time,
227
    # it raises a Net::OpenTimeout exception. The default value is 30 seconds.
228
    attr_reader :open_timeout
229

  
230
    # Seconds to wait until reading one block (by one read(1) call).
231
    # If the IMAP object cannot complete a read() within this time,
232
    # it raises a Net::ReadTimeout exception. The default value is 60 seconds.
233
    attr_reader :read_timeout
234

  
224 235
    # The thread to receive exceptions.
225 236
    attr_accessor :client_thread
226 237

  
......
1048 1059
    #         be installed.
1049 1060
    #         If options[:ssl] is a hash, it's passed to
1050 1061
    #         OpenSSL::SSL::SSLContext#set_params as parameters.
1062
    # open_timeout:: Seconds to wait until a connection is opened
1063
    # read_timeout:: Seconds to wait until reading one block
1051 1064
    #
1052 1065
    # The most common errors are:
1053 1066
    #
......
1076 1089
      @port = options[:port] || (options[:ssl] ? SSL_PORT : PORT)
1077 1090
      @tag_prefix = "RUBY"
1078 1091
      @tagno = 0
1092
      @open_timeout = options[:open_timeout] || 30
1093
      @read_timeout = options[:read_timeout] || 60
1079 1094
      @parser = ResponseParser.new
1080
      @sock = TCPSocket.open(@host, @port)
1095
      @sock = Socket.tcp(@host, @port, :connect_timeout => @open_timeout)
1081 1096
      begin
1082 1097
        if options[:ssl]
1083 1098
          start_tls_session(options[:ssl])
......
1199 1214
      end
1200 1215
    end
1201 1216

  
1217
    def get_response_data(length, terminator = nil)
1218
      str = nil
1219
      buff = String.new
1220
      while true
1221
        str = @sock.read_nonblock(length, :exception => false)
1222
        case str
1223
        when :wait_readable
1224
          @sock.to_io.wait_readable(@read_timeout) or
1225
            raise Net::ReadTimeout, "#{@host}:#{@port} read timeout (exceeds #{@read_timeout} seconds)"
1226
        when nil
1227
          break
1228
        else
1229
          buff.concat(str)
1230
          if terminator ? buff.include?(terminator) : (buff.length >= length)
1231
            break
1232
          end
1233
        end
1234
      end
1235
      buff
1236
    end
1237

  
1202 1238
    def get_response
1203 1239
      buff = String.new
1204 1240
      while true
1205
        s = @sock.gets(CRLF)
1206
        break unless s
1241
        s = get_response_data(1, CRLF)
1242
        break if s.length == 0
1207 1243
        buff.concat(s)
1208 1244
        if /\{(\d+)\}\r\n/n =~ s
1209
          s = @sock.read($1.to_i)
1245
          s = get_response_data($1.to_i)
1210 1246
          buff.concat(s)
1211 1247
        else
1212 1248
          break
1213
-