1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/ruby/library/net/ftp/fixtures/server.rb
eregon 8c5b60eb22 Update to ruby/spec@a6b8805
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60525 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-28 15:15:48 +00:00

277 lines
6.7 KiB
Ruby

module NetFTPSpecs
class DummyFTP
attr_accessor :connect_message
attr_reader :login_user, :login_pass, :login_acct
# hostname or IP address
attr_reader :hostname
# port number
attr_reader :server_port
def initialize
@hostname = "localhost"
@server = TCPServer.new(@hostname, 0)
@server_port = @server.addr[1]
@handlers = {}
@commands = []
@connect_message = nil
end
def serve_once
@thread = Thread.new do
@socket = @server.accept
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1)
begin
handle_request
ensure
@socket.close
end
end
end
def handle_request
# Send out the welcome message.
response @connect_message || "220 Dummy FTP Server ready!"
begin
while command = @socket.gets
command, argument = command.chomp.split(" ", 2)
if command == "QUIT"
self.response("221 OK, bye")
break
elsif proc_handler = @handlers[command.downcase.to_sym]
if argument.nil?
proc_handler.call(self)
else
proc_handler.call(self, argument)
end
else
if argument.nil?
self.send(command.downcase.to_sym)
else
self.send(command.downcase.to_sym, argument)
end
end
end
rescue => e
self.error_response("Exception: #{e} #{e.backtrace.inspect}")
end
end
def error_response(text)
self.response("451 #{text}")
end
def response(text)
@socket.puts(text) unless @socket.closed?
end
def stop
@datasocket.close unless @datasocket.nil? || @datasocket.closed?
@server.close
@thread.join
end
##
def handle(sym, &block)
@handlers[sym] = block
end
def should_receive(method)
@handler_for = method
self
end
def and_respond(text)
@handlers[@handler_for] = lambda { |s, *args| s.response(text) }
end
##
# FTP methods
##
def abor
self.response("226 Closing data connection. (ABOR)")
end
def acct(account)
@login_acct = account
self.response("230 User '#{account}' logged in, proceed. (ACCT)")
end
def cdup
self.response("200 Command okay. (CDUP)")
end
def cwd(dir)
self.response("200 Command okay. (CWD #{dir})")
end
def dele(file)
self.response("250 Requested file action okay, completed. (DELE #{file})")
end
def eprt(arg)
_, _, host, port = arg.split("|")
@datasocket = TCPSocket.new(host, port)
self.response("200 port opened")
end
def help(param = :default)
if param == :default
self.response("211 System status, or system help reply. (HELP)")
else
self.response("211 System status, or system help reply. (HELP #{param})")
end
end
def list(folder)
self.response("150 opening ASCII connection for file list")
@datasocket.puts("-rw-r--r-- 1 spec staff 507 17 Jul 18:41 last_response_code.rb")
@datasocket.puts("-rw-r--r-- 1 spec staff 50 17 Jul 18:41 list.rb")
@datasocket.puts("-rw-r--r-- 1 spec staff 48 17 Jul 18:41 pwd.rb")
@datasocket.close()
self.response("226 transfer complete (LIST #{folder})")
end
def mdtm(filename)
self.response("213 19980705132316")
end
def mkd(foldername)
self.response(%Q{257 "#{foldername.gsub('"', '""')}" created.})
end
def nlst(folder = nil)
self.response("150 opening ASCII connection for file list")
@datasocket.puts("last_response_code.rb")
@datasocket.puts("list.rb")
@datasocket.puts("pwd.rb")
@datasocket.close()
self.response("226 transfer complete (NLST#{folder ? " #{folder}" : ""})")
end
def noop
self.response("200 Command okay. (NOOP)")
end
def pass(password)
@login_pass = password
self.response("230 User logged in, proceed. (PASS #{password})")
end
def port(arg)
nums = arg.split(",")
if nums[0] == "::1"
# IPv6
port = nums[1].to_i * 256 + nums[2].to_i
host = nums[0]
else
# IPv4
port = nums[4].to_i * 256 + nums[5].to_i
host = nums[0..3].join(".")
end
@datasocket = TCPSocket.new(host, port)
self.response("200 port opened")
end
def pwd
self.response('257 "/some/dir/" - current directory')
end
def retr(file)
self.response("125 Data transfer starting")
if @restart_at && @restart_at == 20
@datasocket.puts("of the file named '#{file}'.")
@restart_at = nil
else
@datasocket.puts("This is the content")
@datasocket.puts("of the file named '#{file}'.")
end
@datasocket.close()
self.response("226 Closing data connection. (RETR #{file})")
end
def rest(at_bytes)
@restart_at = at_bytes.to_i
self.response("350 Requested file action pending further information. (REST)")
end
def rmd(folder)
self.response("250 Requested file action okay, completed. (RMD #{folder})")
end
def rnfr(from)
@rename_from = from
self.response("350 Requested file action pending further information.")
end
def rnto(to)
self.response("250 Requested file action okay, completed. (Renamed #{@rename_from} to #{to})")
@rename_from = nil
end
def site(param)
self.response("200 Command okay. (SITE #{param})")
end
def size(filename)
if filename == "binary"
self.response("213 24")
else
self.response("213 1024")
end
end
def stat(param = :default)
if param == :default
self.response("211 System status, or system help reply. (STAT)")
else
self.response("211 System status, or system help reply. (STAT #{param})")
end
end
def stor(file)
tmp_file = tmp("#{file}file", false)
self.response("125 Data transfer starting.")
mode = @restart_at ? "a" : "w"
File.open(tmp_file, mode + "b") do |f|
loop do
data = @datasocket.recv(1024)
break if !data || data.empty?
f << data
end
end
#@datasocket.close()
self.response("200 OK, Data received. (STOR #{file})")
end
def appe(file)
@restart_at = true
stor(file)
end
def syst
self.response("215 FTP Dummy Server (SYST)")
end
def type(type)
self.response("200 TYPE switched to #{type}")
end
def user(name)
@login_user = name
self.response("230 User logged in, proceed. (USER #{name})")
end
end
end