From 633ae3278ecce7c2b98fa1aa6106f963894c538a Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Mon, 2 Sep 2019 14:43:35 +0900 Subject: Add Net::FTP#features and Net::FTP#option Patch by darkphnx (Dan Wentworth) . Thanks! [Feature #15964] --- NEWS | 4 ++ lib/net/ftp.rb | 35 ++++++++++++++++++ test/net/ftp/test_ftp.rb | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/NEWS b/NEWS index baebe5c94b..2857cc9e4c 100644 --- a/NEWS +++ b/NEWS @@ -254,6 +254,10 @@ IRB:: * Enable auto indent and save/load history by default. +Net::FTP:: + + * Add features and options. [Feature #15964] + Net::IMAP:: * Add Server Name Indication (SNI) support. [Feature #15594] diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb index 757daa9224..d125c2c0f7 100644 --- a/lib/net/ftp.rb +++ b/lib/net/ftp.rb @@ -1297,6 +1297,41 @@ module Net voidcmd(cmd) end + # + # Issues a FEAT command + # + # Returns an array of supported optional features + # + 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 + + # + # Issues an OPTS command + # - name Should be the name of the option to set + # - params is any optional parameters to supply with the option + # + # example: option('UTF8', 'ON') => 'OPTS UTF8 ON' + # + def option(name, params = nil) + cmd = "OPTS #{name}" + cmd += " #{params}" if params + + voidcmd(cmd) + end + # # Closes the connection. Further operations are impossible until you open # a new connection with #connect. diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb index 39f1220dbb..2504a48d0a 100644 --- a/test/net/ftp/test_ftp.rb +++ b/test/net/ftp/test_ftp.rb @@ -1530,6 +1530,102 @@ EOF end end + def test_features + commands = [] + server = create_ftp_server { |sock| + sock.print("220 (test_ftp).\r\n") + commands.push(sock.gets) + sock.print("211-Features\r\n") + sock.print(" LANG EN*\r\n") + sock.print(" UTF8\r\n") + sock.print("211 End\r\n") + } + begin + begin + ftp = Net::FTP.new + ftp.connect(SERVER_ADDR, server.port) + assert_equal(['LANG EN*', 'UTF8'], ftp.features) + assert_equal("FEAT\r\n", commands.shift) + assert_equal(nil, commands.shift) + ensure + ftp.close if ftp + end + ensure + server.close + end + end + + def test_features_not_implemented + commands = [] + server = create_ftp_server { |sock| + sock.print("220 (test_ftp).\r\n") + commands.push(sock.gets) + sock.print("502 Not Implemented\r\n") + } + begin + begin + ftp = Net::FTP.new + ftp.connect(SERVER_ADDR, server.port) + assert_raise(Net::FTPPermError) do + ftp.features + end + assert_equal("FEAT\r\n", commands.shift) + assert_equal(nil, commands.shift) + ensure + ftp.close if ftp + end + ensure + server.close + end + + end + + def test_option + commands = [] + server = create_ftp_server { |sock| + sock.print("220 (test_ftp)\r\n") + commands.push(sock.gets) + sock.print("200 OPTS UTF8 command successful\r\n") + } + begin + begin + ftp = Net::FTP.new + ftp.connect(SERVER_ADDR, server.port) + ftp.option("UTF8", "ON") + assert_equal("OPTS UTF8 ON\r\n", commands.shift) + assert_equal(nil, commands.shift) + ensure + ftp.close if ftp + end + ensure + server.close + end + end + + def test_option_not_implemented + commands = [] + server = create_ftp_server { |sock| + sock.print("220 (test_ftp)\r\n") + commands.push(sock.gets) + sock.print("502 Not implemented\r\n") + } + begin + begin + ftp = Net::FTP.new + ftp.connect(SERVER_ADDR, server.port) + assert_raise(Net::FTPPermError) do + ftp.option("UTF8", "ON") + end + assert_equal("OPTS UTF8 ON\r\n", commands.shift) + assert_equal(nil, commands.shift) + ensure + ftp.close if ftp + end + ensure + server.close + end + end + def test_mlst commands = [] server = create_ftp_server { |sock| -- cgit v1.2.3