класс Net::FTP
Этот класс реализует протокол File передачи файлов. Если вы использовали программу командной строки FTP и знакомы с её командами, вы легко освоите этот класс. Некоторые дополнительные функции реализованы с учётом стиля и сильных сторон Ruby.
Пример
require 'net/ftp'
Пример 1
ftp = Net::FTP.new('example.com')
ftp.login
files = ftp.chdir('pub/lang/ruby/contrib')
files = ftp.list('n*')
ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
ftp.close
Пример 2
Net::FTP.open('example.com') do |ftp|
ftp.login
files = ftp.chdir('pub/lang/ruby/contrib')
files = ftp.list('n*')
ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
end
Основные методы
Ниже приведены методы, которые чаще всего будут полезны пользователям:
Константы
- CASE_DEPENDENT_PARSER
- CASE_INDEPENDENT_PARSER
- DECIMAL_PARSER
- FACT_PARSERS
- OCTAL_PARSER
- TIME_PARSER
Атрибуты
Когда true, передачи выполняются в двоичном режиме. По умолчанию: true.
Когда true, весь трафик к серверу и от него записывается в +$stdout+. По умолчанию: false.
Последний ответ сервера.
Код последнего ответа сервера.
Код последнего ответа сервера.
Количество секунд ожидания открытия соединения. Может быть любым числом, включая дробные. Если объект FTP не сможет открыть соединение за это время, он сгенерирует исключение Net::OpenTimeout. Значение по умолчанию nil.
Когда true, соединение находится в пассивном режиме. По умолчанию: true.
Количество секунд ожидания прочтения одного блока (через одну вызов read(2)). Может быть любым числом, включая дробные. Если объект FTP не сможет прочитать данные за это время, он сгенерирует исключение Timeout::Error. Значение по умолчанию 60 секунд.
Устанавливает или получает значение параметра resume, определяющего, возобновлять ли незавершенные передачи или начинать их заново. По умолчанию: false.
Количество секунд ожидания рукопожатия TLS. Может быть любым числом, включая дробные. Если объект FTP не сможет завершить TLS рукопожатие за это время, он сгенерирует исключение Net::OpenTimeout. Значение по умолчанию nil. Если ssl_handshake_timeout равно nil, используется open_timeout вместо него.
Приветственное сообщение сервера.
Публичные методы класса
# File lib/net/ftp.rb, line 152 def self.default_passive @@default_passive end
По умолчанию соединения находятся в пассивном режиме. По умолчанию: true.
# File lib/net/ftp.rb, line 146 def self.default_passive=(value) @@default_passive = value end
По умолчанию соединения находятся в пассивном режиме. По умолчанию: true.
# File lib/net/ftp.rb, line 212
def initialize(host = nil, user_or_options = {}, passwd = nil, acct = nil)
super()
begin
options = user_or_options.to_hash
rescue NoMethodError
# for backward compatibility
options = {}
options[:username] = user_or_options
options[:password] = passwd
options[:account] = acct
end
@host = nil
if options[:ssl]
unless defined?(OpenSSL::SSL)
raise "SSL extension not installed"
end
ssl_params = options[:ssl] == true ? {} : options[:ssl]
@ssl_context = SSLContext.new
@ssl_context.set_params(ssl_params)
if defined?(VerifyCallbackProc)
@ssl_context.verify_callback = VerifyCallbackProc
end
@ssl_context.session_cache_mode =
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
@ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
@ssl_session = nil
if options[:private_data_connection].nil?
@private_data_connection = true
else
@private_data_connection = options[:private_data_connection]
end
else
@ssl_context = nil
if options[:private_data_connection]
raise ArgumentError,
"private_data_connection can be set to true only when ssl is enabled"
end
@private_data_connection = false
end
@binary = true
if options[:passive].nil?
@passive = @@default_passive
else
@passive = options[:passive]
end
if options[:debug_mode].nil?
@debug_mode = false
else
@debug_mode = options[:debug_mode]
end
@resume = false
@bare_sock = @sock = NullSocket.new
@logged_in = false
@open_timeout = options[:open_timeout]
@ssl_handshake_timeout = options[:ssl_handshake_timeout]
@read_timeout = options[:read_timeout] || 60
if host
connect(host, options[:port] || FTP_PORT)
if options[:username]
login(options[:username], options[:password], options[:account])
end
end
end Создаёт и возвращает новый объект FTP. Если указан параметр host, соединение будет установлено.
options — это хэш параметров, каждый ключ которого — символ.
Доступные параметры:
- port
-
Номер порта (значение по умолчанию 21)
- ssl
-
Если
options[:ssl]равно true, будет попытка использовать SSL (теперь TLS) для подключения к серверу. Для этого необходимо установить расширенияOpenSSL[OSSL] и RubyOpenSSL[RSSL]. Еслиoptions[:ssl]— хэш, он передаётся методуOpenSSL::SSL::SSLContext#set_paramsв качестве параметров. - private_data_connection
-
Если true, TLS используется для соединений данных. По умолчанию:
trueкогдаoptions[:ssl]равно true. - username
-
Имя пользователя для входа. Если
options[:username]— строка “anonymous” иoptions[:password]—nil, в качестве пароля используется “anonymous@”. - password
-
Пароль для входа.
- account
-
Информация об учётной записи для ACCT.
- passive
-
Если
true, соединение будет в пассивном режиме. По умолчанию:true. -
open_timeout -
Количество секунд ожидания открытия соединения. Подробнее в
Net::FTP#open_timeout. По умолчанию:nil. -
read_timeout -
Количество секунд ожидания прочтения одного блока. Подробнее в
Net::FTP#read_timeout. По умолчанию:60. -
ssl_handshake_timeout -
Количество секунд ожидания рукопожатия TLS. Подробнее в
Net::FTP#ssl_handshake_timeout. По умолчанию:nil. -
debug_mode -
Когда
true, весь трафик к серверу и от него записывается в +$stdout+. По умолчанию:false.
MonitorMixin::new # File lib/net/ftp.rb, line 162
def FTP.open(host, *args)
if block_given?
ftp = new(host, *args)
begin
yield ftp
ensure
ftp.close
end
else
new(host, *args)
end
end Синоним для FTP.new, но с обязательным параметром host.
Если задан блок, он передаётся объекту FTP. Объект будет закрыт по завершении блока или при возникновении исключения.
Публичные методы экземпляра
# File lib/net/ftp.rb, line 1231
def abort
line = "ABOR" + CRLF
print "put: ABOR\n" if @debug_mode
@sock.send(line, Socket::MSG_OOB)
resp = getmultiline
unless ["426", "226", "225"].include?(resp[0, 3])
raise FTPProtoError, resp
end
return resp
end Прерывает предыдущую команду (команда ABOR).
# File lib/net/ftp.rb, line 884 def acct(account) cmd = "ACCT " + account voidcmd(cmd) end
Отправляет команду ACCT.
Это менее распространённая FTP команда, для отправки информации об учётной записи, если удалённый хост требует её.
# File lib/net/ftp.rb, line 279
def binary=(newmode)
if newmode != @binary
@binary = newmode
send_type_command if @logged_in
end
end Установка для переключения передачи в двоичном режиме. newmode может быть либо true, либо false
# File lib/net/ftp.rb, line 1152
def chdir(dirname)
if dirname == ".."
begin
voidcmd("CDUP")
return
rescue FTPPermError => e
if e.message[0, 3] != "500"
raise e
end
end
end
cmd = "CWD #{dirname}"
voidcmd(cmd)
end Изменяет (удалённый) каталог.
# File lib/net/ftp.rb, line 1345
def close
if @sock and not @sock.closed?
begin
@sock.shutdown(Socket::SHUT_WR) rescue nil
orig, self.read_timeout = self.read_timeout, 3
@sock.read rescue nil
ensure
@sock.close
self.read_timeout = orig
end
end
end Закрывает соединение. Дальнейшие операции невозможны, пока вы не откроете новое соединение с помощью connect.
# File lib/net/ftp.rb, line 1361 def closed? @sock == nil or @sock.closed? end
Возвращает true, если соединение закрыто.
# File lib/net/ftp.rb, line 367
def connect(host, port = FTP_PORT)
if @debug_mode
print "connect: ", host, ", ", port, "\n"
end
synchronize do
@host = host
@bare_sock = open_socket(host, port)
@sock = BufferedSocket.new(@bare_sock, read_timeout: @read_timeout)
voidresp
if @ssl_context
begin
voidcmd("AUTH TLS")
ssl_sock = start_tls_session(@bare_sock)
@sock = BufferedSSLSocket.new(ssl_sock, read_timeout: @read_timeout)
if @private_data_connection
voidcmd("PBSZ 0")
voidcmd("PROT P")
end
rescue OpenSSL::SSL::SSLError, OpenTimeout
@sock.close
raise
end
end
end
end Устанавливает FTP соединение с хостом, при необходимости переопределяя порт по умолчанию. Если установлена переменная окружения SOCKS_SERVER, устанавливает соединение через прокси SOCKS. Вызывает исключение (обычно Errno::ECONNREFUSED), если соединение не может быть установлено.
# File lib/net/ftp.rb, line 1138
def delete(filename)
resp = sendcmd("DELE #{filename}")
if resp.start_with?("250")
return
elsif resp.start_with?("5")
raise FTPPermError, resp
else
raise FTPReplyError, resp
end
end Удаляет файл на сервере.
# File lib/net/ftp.rb, line 1311
def features
resp = sendcmd("FEAT")
if !resp.start_with?("211")
raise FTPReplyError, resp
end
feats = []
resp.split("\n").each do |line|
next if !line.start_with?(' ') # skip status lines
feats << line.strip
end
return feats
end Выполняет команду FEAT
Возвращает массив поддерживаемых дополнительных функций
# File lib/net/ftp.rb, line 813
def get(remotefile, localfile = File.basename(remotefile),
blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
if @binary
getbinaryfile(remotefile, localfile, blocksize, &block)
else
gettextfile(remotefile, localfile, &block)
end
end Извлекает remotefile в том режиме, в котором установлен сеанс (текстовый или двоичный). См. gettextfile и getbinaryfile.
# File lib/net/ftp.rb, line 752
def getbinaryfile(remotefile, localfile = File.basename(remotefile),
blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
f = nil
result = nil
if localfile
if @resume
rest_offset = File.size?(localfile)
f = File.open(localfile, "a")
else
rest_offset = nil
f = File.open(localfile, "w")
end
elsif !block_given?
result = String.new
end
begin
f&.binmode
retrbinary("RETR #{remotefile}", blocksize, rest_offset) do |data|
f&.write(data)
block&.(data)
result&.concat(data)
end
return result
ensure
f&.close
end
end Извлекает remotefile в двоичном режиме, сохраняя результат в localfile. Если localfile равно nil, возвращает извлечённые данные. Если предоставлен блок, ему передаются извлечённые данные в виде фрагментов по blocksize.
# File lib/net/ftp.rb, line 787
def gettextfile(remotefile, localfile = File.basename(remotefile),
&block) # :yield: line
f = nil
result = nil
if localfile
f = File.open(localfile, "w")
elsif !block_given?
result = String.new
end
begin
retrlines("RETR #{remotefile}") do |line, newline|
l = newline ? line + "\n" : line
f&.print(l)
block&.(line, newline)
result&.concat(l)
end
return result
ensure
f&.close
end
end Извлекает remotefile в режиме ASCII (текстовом), сохраняя результат в localfile. Если localfile равно nil, возвращает извлечённые данные. Если предоставлен блок, ему передаются извлечённые данные построчно.
# File lib/net/ftp.rb, line 1274
def help(arg = nil)
cmd = "HELP"
if arg
cmd = cmd + " " + arg
end
sendcmd(cmd)
end Выполняет команду HELP.
# File lib/net/ftp.rb, line 908
def list(*args, &block) # :yield: line
cmd = "LIST"
args.each do |arg|
cmd = "#{cmd} #{arg}"
end
lines = []
retrlines(cmd) do |line|
lines << line
end
if block
lines.each(&block)
end
return lines
end Возвращает массив информации о файлах в каталоге (вывод похож на `ls -l`). Если задан блок, он проходит итерацию по списку.
# File lib/net/ftp.rb, line 599
def login(user = "anonymous", passwd = nil, acct = nil)
if user == "anonymous" and passwd == nil
passwd = "anonymous@"
end
resp = ""
synchronize do
resp = sendcmd('USER ' + user)
if resp.start_with?("3")
raise FTPReplyError, resp if passwd.nil?
resp = sendcmd('PASS ' + passwd)
end
if resp.start_with?("3")
raise FTPReplyError, resp if acct.nil?
resp = sendcmd('ACCT ' + acct)
end
end
if !resp.start_with?("2")
raise FTPReplyError, resp
end
@welcome = resp
send_type_command
@logged_in = true
end Выполняет вход на удалённый хост. Сеанс должен быть предварительно подключен. Если user — это строка «anonymous», а password — nil, используется «anonymous@» в качестве пароля. Если параметр acct не равен nil, после успешного входа в систему отправляется команда FTP ACCT. Вызывает исключение при ошибке (обычно Net::FTPPermError).
# File lib/net/ftp.rb, line 1264
def mdtm(filename)
resp = sendcmd("MDTM #{filename}")
if resp.start_with?("213")
return get_body(resp)
end
end Возвращает необработанное время последнего изменения (удалённого) файла в формате «YYYYMMDDhhmmss» (команда MDTM).
Используйте mtime, если вам нужен разобранный экземпляр Time.
# File lib/net/ftp.rb, line 1196
def mkdir(dirname)
resp = sendcmd("MKD #{dirname}")
return parse257(resp)
end Создаёт удалённый каталог.
# File lib/net/ftp.rb, line 1112
def mlsd(pathname = nil, &block) # :yield: entry
cmd = pathname ? "MLSD #{pathname}" : "MLSD"
entries = []
retrlines(cmd) do |line|
entries << parse_mlsx_entry(line)
end
if block
entries.each(&block)
end
return entries
end Возвращает массив записей каталога, указанного pathname. Каждая запись содержит данные (например, размер, время последнего изменения и т.д.) и имя пути. Если задан блок, он проходит итерацию по списку. Если pathname пропущен, предполагается текущий каталог.
# File lib/net/ftp.rb, line 1090
def mlst(pathname = nil)
cmd = pathname ? "MLST #{pathname}" : "MLST"
resp = sendcmd(cmd)
if !resp.start_with?("250")
raise FTPReplyError, resp
end
line = resp.lines[1]
unless line
raise FTPProtoError, resp
end
entry = line.sub(/\A(250-| *)/, "")
return parse_mlsx_entry(entry)
end Возвращает данные (например, размер, время последнего изменения, тип записи и т.д.) о файле или каталоге, указанном pathname. Если pathname пропущен, предполагается текущий каталог.
# File lib/net/ftp.rb, line 1189 def mtime(filename, local = false) return TIME_PARSER.(mdtm(filename), local) end
Возвращает время последнего изменения (удалённого) файла. Если local равно true, оно возвращается как локальное время, в противном случае это время UTC.
# File lib/net/ftp.rb, line 892
def nlst(dir = nil)
cmd = "NLST"
if dir
cmd = "#{cmd} #{dir}"
end
files = []
retrlines(cmd) do |line|
files.push(line)
end
return files
end Возвращает массив имен файлов в удаленном каталоге.
# File lib/net/ftp.rb, line 1294
def noop
voidcmd("NOOP")
end Отправляет команду NOOP.
Ничего не делает, кроме возвращения ответа.
# File lib/net/ftp.rb, line 1334
def option(name, params = nil)
cmd = "OPTS #{name}"
cmd += " #{params}" if params
voidcmd(cmd)
end Отправляет команду OPTS
-
name Должно быть именем опции для установки
-
params - любые необязательные параметры для передачи вместе с опцией
пример: option('UTF8', 'ON') => 'OPTS UTF8 ON'
# File lib/net/ftp.rb, line 869
def put(localfile, remotefile = File.basename(localfile),
blocksize = DEFAULT_BLOCKSIZE, &block)
if @binary
putbinaryfile(localfile, remotefile, blocksize, &block)
else
puttextfile(localfile, remotefile, &block)
end
end Переносит localfile на сервер в том режиме, в котором установлен сеанс (текстовый или бинарный). См. puttextfile и putbinaryfile.
# File lib/net/ftp.rb, line 827
def putbinaryfile(localfile, remotefile = File.basename(localfile),
blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
if @resume
begin
rest_offset = size(remotefile)
rescue Net::FTPPermError
rest_offset = nil
end
else
rest_offset = nil
end
f = File.open(localfile)
begin
f.binmode
if rest_offset
storbinary("APPE #{remotefile}", f, blocksize, rest_offset, &block)
else
storbinary("STOR #{remotefile}", f, blocksize, rest_offset, &block)
end
ensure
f.close
end
end Переносит localfile на сервер в бинарном режиме, сохраняя результат в remotefile. Если предоставлен блок, вызывает его, передавая переданные данные в blocksize блоках.
# File lib/net/ftp.rb, line 856
def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
f = File.open(localfile)
begin
storlines("STOR #{remotefile}", f, &block)
ensure
f.close
end
end Переносит localfile на сервер в режиме ASCII (текст), сохраняя результат в remotefile. Если предоставлен обратный вызов или связанный блок, вызывает его, передавая переданные данные построчно.
# File lib/net/ftp.rb, line 1211
def pwd
resp = sendcmd("PWD")
return parse257(resp)
end Возвращает текущий удаленный каталог.
# File lib/net/ftp.rb, line 1285
def quit
voidcmd("QUIT")
end Завершает сеанс FTP.
# File lib/net/ftp.rb, line 129 def read_timeout=(sec) @sock.read_timeout = sec @read_timeout = sec end
Установщик для атрибута read_timeout.
# File lib/net/ftp.rb, line 1127
def rename(fromname, toname)
resp = sendcmd("RNFR #{fromname}")
if !resp.start_with?("3")
raise FTPReplyError, resp
end
voidcmd("RNTO #{toname}")
end Переименовывает файл на сервере.
# File lib/net/ftp.rb, line 630
def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
synchronize do
with_binary(true) do
begin
conn = transfercmd(cmd, rest_offset)
while data = conn.read(blocksize)
yield(data)
end
conn.shutdown(Socket::SHUT_WR) rescue nil
conn.read_timeout = 1
conn.read rescue nil
ensure
conn.close if conn
end
voidresp
end
end
end Переводит соединение в бинарный (графический) режим, выполняет заданную команду и извлекает возвращенные данные, передавая их в связанный блок по частям по blocksize символов. Обратите внимание, что cmd - это команда сервера (например, «RETR myfile»).
# File lib/net/ftp.rb, line 655
def retrlines(cmd) # :yield: line
synchronize do
with_binary(false) do
begin
conn = transfercmd(cmd)
while line = conn.gets
yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?)
end
conn.shutdown(Socket::SHUT_WR) rescue nil
conn.read_timeout = 1
conn.read rescue nil
ensure
conn.close if conn
end
voidresp
end
end
end Переводит соединение в режим ASCII (текст), выполняет заданную команду и передает результирующие данные построчно в связанный блок. Если блок не задан, печатает строки. Обратите внимание, что cmd - это команда сервера (например, «RETR myfile»).
# File lib/net/ftp.rb, line 1204
def rmdir(dirname)
voidcmd("RMD #{dirname}")
end Удаляет удаленный каталог.
# File lib/net/ftp.rb, line 492
def sendcmd(cmd)
synchronize do
putline(cmd)
return getresp
end
end Отправляет команду и возвращает ответ.
# File lib/net/ftp.rb, line 1301 def site(arg) cmd = "SITE " + arg voidcmd(cmd) end
Отправляет команду SITE.
# File lib/net/ftp.rb, line 1175
def size(filename)
with_binary(true) do
resp = sendcmd("SIZE #{filename}")
if !resp.start_with?("213")
raise FTPReplyError, resp
end
return get_body(resp).to_i
end
end Возвращает размер заданного (удаленного) имени файла.
# File lib/net/ftp.rb, line 1248
def status(pathname = nil)
line = pathname ? "STAT #{pathname}" : "STAT"
if /[\r\n]/ =~ line
raise ArgumentError, "A line must not contain CR or LF"
end
print "put: #{line}\n" if @debug_mode
@sock.send(line + CRLF, Socket::MSG_OOB)
return getresp
end Возвращает статус (команда STAT).
- pathname
-
когда stat вызывается с pathname в качестве параметра, он работает как список, но намного быстрее и через тот же tcp-сеанс.
# File lib/net/ftp.rb, line 680
def storbinary(cmd, file, blocksize, rest_offset = nil) # :yield: data
if rest_offset
file.seek(rest_offset, IO::SEEK_SET)
end
synchronize do
with_binary(true) do
begin
conn = transfercmd(cmd)
while buf = file.read(blocksize)
conn.write(buf)
yield(buf) if block_given?
end
conn.shutdown(Socket::SHUT_WR) rescue nil
conn.read_timeout = 1
conn.read rescue nil
ensure
conn.close if conn
end
voidresp
end
end
rescue Errno::EPIPE
# EPIPE, in this case, means that the data connection was unexpectedly
# terminated. Rather than just raising EPIPE to the caller, check the
# response on the control connection. If getresp doesn't raise a more
# appropriate exception, re-raise the original exception.
getresp
raise
end Переводит соединение в бинарный (графический) режим, выполняет заданную команду на стороне сервера (например, «STOR myfile») и отправляет содержимое файла с именем file на сервер. Если предоставлен необязательный блок, он также передает ему данные блоками по blocksize символов.
# File lib/net/ftp.rb, line 716
def storlines(cmd, file) # :yield: line
synchronize do
with_binary(false) do
begin
conn = transfercmd(cmd)
while buf = file.gets
if buf[-2, 2] != CRLF
buf = buf.chomp + CRLF
end
conn.write(buf)
yield(buf) if block_given?
end
conn.shutdown(Socket::SHUT_WR) rescue nil
conn.read_timeout = 1
conn.read rescue nil
ensure
conn.close if conn
end
voidresp
end
end
rescue Errno::EPIPE
# EPIPE, in this case, means that the data connection was unexpectedly
# terminated. Rather than just raising EPIPE to the caller, check the
# response on the control connection. If getresp doesn't raise a more
# appropriate exception, re-raise the original exception.
getresp
raise
end Переводит соединение в режим ASCII (текст), выполняет заданную команду на стороне сервера (например, «STOR myfile») и отправляет содержимое файла с именем file на сервер построчно. Если предоставлен необязательный блок, он также передает ему строки.
# File lib/net/ftp.rb, line 1220
def system
resp = sendcmd("SYST")
if !resp.start_with?("215")
raise FTPReplyError, resp
end
return get_body(resp)
end Возвращает информацию о системе.
# File lib/net/ftp.rb, line 502
def voidcmd(cmd)
synchronize do
putline(cmd)
voidresp
end
end Отправляет команду и ожидает ответа, начинающегося с '2'.
Свойства методов частного экземпляра
# File lib/net/ftp.rb, line 1070
def parse_mlsx_entry(entry)
facts, pathname = entry.chomp.split(/ /, 2)
unless pathname
raise FTPProtoError, entry
end
return MLSxEntry.new(
facts.scan(/(.*?)=(.*?);/).each_with_object({}) {
|(factname, value), h|
name = factname.downcase
h[name] = FACT_PARSERS[name].(value)
},
pathname)
end # File lib/net/ftp.rb, line 1399
def parse_pasv_ipv4_host(s)
return s.tr(",", ".")
end # File lib/net/ftp.rb, line 1404
def parse_pasv_ipv6_host(s)
return s.split(/,/).map { |i|
"%02x" % i.to_i
}.each_slice(2).map(&:join).join(":")
end # File lib/net/ftp.rb, line 1411
def parse_pasv_port(s)
return s.split(/,/).map(&:to_i).inject { |x, y|
(x << 8) + y
}
end # File lib/net/ftp.rb, line 344
def start_tls_session(sock)
ssl_sock = SSLSocket.new(sock, @ssl_context)
ssl_sock.sync_close = true
ssl_sock.hostname = @host if ssl_sock.respond_to? :hostname=
if @ssl_session &&
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
# ProFTPD returns 425 for data connections if session is not reused.
ssl_sock.session = @ssl_session
end
ssl_socket_connect(ssl_sock, @ssl_handshake_timeout || @open_timeout)
if @ssl_context.verify_mode != VERIFY_NONE
ssl_sock.post_connection_check(@host)
end
return ssl_sock
end
Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.