Class Net::FTP
In: lib/net/ftp.rb
Parent: Object

This class implements the File Transfer Protocol. If you have used a command-line FTP program, and are familiar with the commands, you will be able to use this class easily. Some extra features are included to take advantage of Ruby‘s style and strengths.

Example

  require 'net/ftp'

Example 1

  ftp = Net::FTP.new('ftp.netlab.co.jp')
  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

Example 2

  Net::FTP.open('ftp.netlab.co.jp') 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

Major Methods

The following are the methods most likely to be useful to users:

Methods

abort   acct   chdir   close   closed?   connect   delete   dir   get   getaddress   getbinaryfile   getdir   getline   getmultiline   getresp   gettextfile   help   list   login   ls   makepasv   makeport   mdtm   mkdir   mtime   new   nlst   noop   open   open_socket   parse227   parse228   parse229   parse257   put   putbinaryfile   putline   puttextfile   pwd   quit   rename   retrbinary   retrlines   return_code   return_code=   rmdir   sanitize   sendcmd   sendport   set_socket   site   size   status   storbinary   storlines   system   transfercmd   voidcmd   voidresp  

Included Modules

MonitorMixin

External Aliases

last_response_code -> lastresp

Attributes

binary  [RW]  When true, transfers are performed in binary mode. Default: true.
debug_mode  [RW]  When true, all traffic to and from the server is written to +$stdout+. Default: false.
last_response  [R]  The server‘s last response.
last_response_code  [R]  The server‘s last response code.
passive  [RW]  When true, the connection is in passive mode. Default: false.
resume  [RW]  Sets or retrieves the resume status, which decides whether incomplete transfers are resumed or restarted. Default: false.
welcome  [R]  The server‘s welcome message.

Public Class methods

Creates and returns a new FTP object. If a host is given, a connection is made. Additionally, if the user is given, the given user name, password, and (optionally) account are used to log in. See login.

[Source]

     # File lib/net/ftp.rb, line 129
129:     def initialize(host = nil, user = nil, passwd = nil, acct = nil)
130:       super()
131:       @binary = true
132:       @passive = false
133:       @debug_mode = false
134:       @resume = false
135:       if host
136:         connect(host)
137:         if user
138:           login(user, passwd, acct)
139:         end
140:       end
141:     end

A synonym for FTP.new, but with a mandatory host parameter.

If a block is given, it is passed the FTP object, which will be closed when the block finishes, or when an exception is raised.

[Source]

     # File lib/net/ftp.rb, line 111
111:     def FTP.open(host, user = nil, passwd = nil, acct = nil)
112:       if block_given?
113:         ftp = new(host, user, passwd, acct)
114:         begin
115:           yield ftp
116:         ensure
117:           ftp.close
118:         end
119:       else
120:         new(host, user, passwd, acct)
121:       end
122:     end

Public Instance methods

Aborts the previous command (ABOR command).

[Source]

     # File lib/net/ftp.rb, line 745
745:     def abort
746:       line = "ABOR" + CRLF
747:       print "put: ABOR\n" if @debug_mode
748:       @sock.send(line, Socket::MSG_OOB)
749:       resp = getmultiline
750:       unless ["426", "226", "225"].include?(resp[0, 3])
751:         raise FTPProtoError, resp
752:       end
753:       return resp
754:     end

Sends the ACCT command. TODO: more info.

[Source]

     # File lib/net/ftp.rb, line 598
598:     def acct(account)
599:       cmd = "ACCT " + account
600:       voidcmd(cmd)
601:     end

Changes the (remote) directory.

[Source]

     # File lib/net/ftp.rb, line 668
668:     def chdir(dirname)
669:       if dirname == ".."
670:         begin
671:           voidcmd("CDUP")
672:           return
673:         rescue FTPPermError => e
674:           if e.message[0, 3] != "500"
675:             raise e
676:           end
677:         end
678:       end
679:       cmd = "CWD " + dirname
680:       voidcmd(cmd)
681:     end

Closes the connection. Further operations are impossible until you open a new connection with connect.

[Source]

     # File lib/net/ftp.rb, line 813
813:     def close
814:       @sock.close if @sock and not @sock.closed?
815:     end

Returns true iff the connection is closed.

[Source]

     # File lib/net/ftp.rb, line 820
820:     def closed?
821:       @sock == nil or @sock.closed?
822:     end

Establishes an FTP connection to host, optionally overriding the default port. If the environment variable SOCKS_SERVER is set, sets up the connection through a SOCKS proxy. Raises an exception (typically Errno::ECONNREFUSED) if the connection cannot be established.

[Source]

     # File lib/net/ftp.rb, line 170
170:     def connect(host, port = FTP_PORT)
171:       if @debug_mode
172:         print "connect: ", host, ", ", port, "\n"
173:       end
174:       synchronize do
175:         @sock = open_socket(host, port)
176:         voidresp
177:       end
178:     end

Deletes a file on the server.

[Source]

     # File lib/net/ftp.rb, line 654
654:     def delete(filename)
655:       resp = sendcmd("DELE " + filename)
656:       if resp[0, 3] == "250"
657:         return
658:       elsif resp[0] == ?5
659:         raise FTPPermError, resp
660:       else
661:         raise FTPReplyError, resp
662:       end
663:     end
dir(*args)

Alias for list

Retrieves remotefile in whatever mode the session is set (text or binary). See gettextfile and getbinaryfile.

[Source]

     # File lib/net/ftp.rb, line 534
534:     def get(remotefile, localfile = File.basename(remotefile),
535:             blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
536:       unless @binary
537:         gettextfile(remotefile, localfile, &block)
538:       else
539:         getbinaryfile(remotefile, localfile, blocksize, &block)
540:       end
541:     end

Retrieves remotefile in binary mode, storing the result in localfile. If a block is supplied, it is passed the retrieved data in blocksize chunks.

[Source]

     # File lib/net/ftp.rb, line 493
493:     def getbinaryfile(remotefile, localfile = File.basename(remotefile),
494:                       blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
495:       if @resume
496:         rest_offset = File.size?(localfile)
497:         f = open(localfile, "a")
498:       else
499:         rest_offset = nil
500:         f = open(localfile, "w")
501:       end
502:       begin
503:         f.binmode
504:         retrbinary("RETR " + remotefile, blocksize, rest_offset) do |data|
505:           f.write(data)
506:           yield(data) if block
507:         end
508:       ensure
509:         f.close
510:       end
511:     end
getdir()

Alias for pwd

Retrieves remotefile in ASCII (text) mode, storing the result in localfile. If a block is supplied, it is passed the retrieved data one line at a time.

[Source]

     # File lib/net/ftp.rb, line 518
518:     def gettextfile(remotefile, localfile = File.basename(remotefile), &block) # :yield: line
519:       f = open(localfile, "w")
520:       begin
521:         retrlines("RETR " + remotefile) do |line|
522:           f.puts(line)
523:           yield(line) if block
524:         end
525:       ensure
526:         f.close
527:       end
528:     end

Issues the HELP command.

[Source]

     # File lib/net/ftp.rb, line 779
779:     def help(arg = nil)
780:       cmd = "HELP"
781:       if arg
782:         cmd = cmd + " " + arg
783:       end
784:       sendcmd(cmd)
785:     end

Returns an array of file information in the directory (the output is like `ls -l`). If a block is given, it iterates through the listing.

[Source]

     # File lib/net/ftp.rb, line 622
622:     def list(*args, &block) # :yield: line
623:       cmd = "LIST"
624:       args.each do |arg|
625:         cmd = cmd + " " + arg
626:       end
627:       if block
628:         retrlines(cmd, &block)
629:       else
630:         lines = []
631:         retrlines(cmd) do |line|
632:           lines << line
633:         end
634:         return lines
635:       end
636:     end

Logs in to the remote host. The session must have been previously connected. If user is the string "anonymous" and the password is nil, a password of user@host is synthesized. If the acct parameter is not nil, an FTP ACCT command is sent following the successful login. Raises an exception on error (typically Net::FTPPermError).

[Source]

     # File lib/net/ftp.rb, line 372
372:     def login(user = "anonymous", passwd = nil, acct = nil)
373:       if user == "anonymous" and passwd == nil
374:         passwd = getaddress
375:       end
376:       
377:       resp = ""
378:       synchronize do
379:         resp = sendcmd('USER ' + user)
380:         if resp[0] == ?3
381:           raise FTPReplyError, resp if passwd.nil?
382:           resp = sendcmd('PASS ' + passwd)
383:         end
384:         if resp[0] == ?3
385:           raise FTPReplyError, resp if acct.nil?
386:           resp = sendcmd('ACCT ' + acct)
387:         end
388:       end
389:       if resp[0] != ?2
390:         raise FTPReplyError, resp
391:       end
392:       @welcome = resp
393:     end
ls(*args)

Alias for list

Issues the MDTM command. TODO: more info.

[Source]

     # File lib/net/ftp.rb, line 769
769:     def mdtm(filename)
770:       resp = sendcmd("MDTM " + filename)
771:       if resp[0, 3] == "213"
772:         return resp[3 .. -1].strip
773:       end
774:     end

Creates a remote directory.

[Source]

     # File lib/net/ftp.rb, line 710
710:     def mkdir(dirname)
711:       resp = sendcmd("MKD " + dirname)
712:       return parse257(resp)
713:     end

Returns the last modification time of the (remote) file. If local is true, it is returned as a local time, otherwise it‘s a UTC time.

[Source]

     # File lib/net/ftp.rb, line 701
701:     def mtime(filename, local = false)
702:       str = mdtm(filename)
703:       ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i}
704:       return local ? Time.local(*ary) : Time.gm(*ary)
705:     end

Returns an array of filenames in the remote directory.

[Source]

     # File lib/net/ftp.rb, line 606
606:     def nlst(dir = nil)
607:       cmd = "NLST"
608:       if dir
609:         cmd = cmd + " " + dir
610:       end
611:       files = []
612:       retrlines(cmd) do |line|
613:         files.push(line)
614:       end
615:       return files
616:     end

Issues a NOOP command.

[Source]

     # File lib/net/ftp.rb, line 797
797:     def noop
798:       voidcmd("NOOP")
799:     end

Transfers localfile to the server in whatever mode the session is set (text or binary). See puttextfile and putbinaryfile.

[Source]

     # File lib/net/ftp.rb, line 586
586:     def put(localfile, remotefile = File.basename(localfile),
587:             blocksize = DEFAULT_BLOCKSIZE, &block)
588:       unless @binary
589:         puttextfile(localfile, remotefile, &block)
590:       else
591:         putbinaryfile(localfile, remotefile, blocksize, &block)
592:       end
593:     end

Transfers localfile to the server in binary mode, storing the result in remotefile. If a block is supplied, calls it, passing in the transmitted data in blocksize chunks.

[Source]

     # File lib/net/ftp.rb, line 548
548:     def putbinaryfile(localfile, remotefile = File.basename(localfile),
549:                       blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
550:       if @resume
551:         begin
552:           rest_offset = size(remotefile)
553:         rescue Net::FTPPermError
554:           rest_offset = nil
555:         end
556:       else
557:         rest_offset = nil
558:       end
559:       f = open(localfile)
560:       begin
561:         f.binmode
562:         storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
563:       ensure
564:         f.close
565:       end
566:     end

Transfers localfile to the server in ASCII (text) mode, storing the result in remotefile. If callback or an associated block is supplied, calls it, passing in the transmitted data one line at a time.

[Source]

     # File lib/net/ftp.rb, line 573
573:     def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
574:       f = open(localfile)
575:       begin
576:         storlines("STOR " + remotefile, f, &block)
577:       ensure
578:         f.close
579:       end
580:     end

Returns the current remote directory.

[Source]

     # File lib/net/ftp.rb, line 725
725:     def pwd
726:       resp = sendcmd("PWD")
727:       return parse257(resp)
728:     end

Exits the FTP session.

[Source]

     # File lib/net/ftp.rb, line 790
790:     def quit
791:       voidcmd("QUIT")
792:     end

Renames a file on the server.

[Source]

     # File lib/net/ftp.rb, line 643
643:     def rename(fromname, toname)
644:       resp = sendcmd("RNFR " + fromname)
645:       if resp[0] != ?3
646:         raise FTPReplyError, resp
647:       end
648:       voidcmd("RNTO " + toname)
649:     end

Puts the connection into binary (image) mode, issues the given command, and fetches the data returned, passing it to the associated block in chunks of blocksize characters. Note that cmd is a server command (such as "RETR myfile").

[Source]

     # File lib/net/ftp.rb, line 401
401:     def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
402:       synchronize do
403:         voidcmd("TYPE I")
404:         conn = transfercmd(cmd, rest_offset)
405:         loop do
406:           data = conn.read(blocksize)
407:           break if data == nil
408:           yield(data)
409:         end
410:         conn.close
411:         voidresp
412:       end
413:     end

Puts the connection into ASCII (text) mode, issues the given command, and passes the resulting data, one line at a time, to the associated block. If no block is given, prints the lines. Note that cmd is a server command (such as "RETR myfile").

[Source]

     # File lib/net/ftp.rb, line 421
421:     def retrlines(cmd) # :yield: line
422:       synchronize do
423:         voidcmd("TYPE A")
424:         conn = transfercmd(cmd)
425:         loop do
426:           line = conn.gets
427:           break if line == nil
428:           if line[-2, 2] == CRLF
429:             line = line[0 .. -3]
430:           elsif line[-1] == ?\n
431:             line = line[0 .. -2]
432:           end
433:           yield(line)
434:         end
435:         conn.close
436:         voidresp
437:       end
438:     end

Obsolete

[Source]

     # File lib/net/ftp.rb, line 144
144:     def return_code
145:       $stderr.puts("warning: Net::FTP#return_code is obsolete and do nothing")
146:       return "\n"
147:     end

Obsolete

[Source]

     # File lib/net/ftp.rb, line 150
150:     def return_code=(s)
151:       $stderr.puts("warning: Net::FTP#return_code= is obsolete and do nothing")
152:     end

Removes a remote directory.

[Source]

     # File lib/net/ftp.rb, line 718
718:     def rmdir(dirname)
719:       voidcmd("RMD " + dirname)
720:     end

Sends a command and returns the response.

[Source]

     # File lib/net/ftp.rb, line 261
261:     def sendcmd(cmd)
262:       synchronize do
263:         putline(cmd)
264:         return getresp
265:       end
266:     end

WRITEME or make private

[Source]

     # File lib/net/ftp.rb, line 183
183:     def set_socket(sock, get_greeting = true)
184:       synchronize do
185:         @sock = sock
186:         if get_greeting
187:           voidresp
188:         end
189:       end
190:     end

Issues a SITE command.

[Source]

     # File lib/net/ftp.rb, line 804
804:     def site(arg)
805:       cmd = "SITE " + arg
806:       voidcmd(cmd)
807:     end

Returns the size of the given (remote) filename.

[Source]

     # File lib/net/ftp.rb, line 686
686:     def size(filename)
687:       voidcmd("TYPE I")
688:       resp = sendcmd("SIZE " + filename)
689:       if resp[0, 3] != "213" 
690:         raise FTPReplyError, resp
691:       end
692:       return resp[3..-1].strip.to_i
693:     end

Returns the status (STAT command).

[Source]

     # File lib/net/ftp.rb, line 759
759:     def status
760:       line = "STAT" + CRLF
761:       print "put: STAT\n" if @debug_mode
762:       @sock.send(line, Socket::MSG_OOB)
763:       return getresp
764:     end

Puts the connection into binary (image) mode, issues the given server-side command (such as "STOR myfile"), and sends the contents of the file named file to the server. If the optional block is given, it also passes it the data, in chunks of blocksize characters.

[Source]

     # File lib/net/ftp.rb, line 446
446:     def storbinary(cmd, file, blocksize, rest_offset = nil, &block) # :yield: data
447:       if rest_offset
448:         file.seek(rest_offset, IO::SEEK_SET)
449:       end
450:       synchronize do
451:         voidcmd("TYPE I")
452:         conn = transfercmd(cmd, rest_offset)
453:         loop do
454:           buf = file.read(blocksize)
455:           break if buf == nil
456:           conn.write(buf)
457:           yield(buf) if block
458:         end
459:         conn.close
460:         voidresp
461:       end
462:     end

Puts the connection into ASCII (text) mode, issues the given server-side command (such as "STOR myfile"), and sends the contents of the file named file to the server, one line at a time. If the optional block is given, it also passes it the lines.

[Source]

     # File lib/net/ftp.rb, line 470
470:     def storlines(cmd, file, &block) # :yield: line
471:       synchronize do
472:         voidcmd("TYPE A")
473:         conn = transfercmd(cmd)
474:         loop do
475:           buf = file.gets
476:           break if buf == nil
477:           if buf[-2, 2] != CRLF
478:             buf = buf.chomp + CRLF
479:           end
480:           conn.write(buf)
481:           yield(buf) if block
482:         end
483:         conn.close
484:         voidresp
485:       end
486:     end

Returns system information.

[Source]

     # File lib/net/ftp.rb, line 734
734:     def system
735:       resp = sendcmd("SYST")
736:       if resp[0, 3] != "215"
737:         raise FTPReplyError, resp
738:       end
739:       return resp[4 .. -1]
740:     end

Sends a command and expect a response beginning with ‘2’.

[Source]

     # File lib/net/ftp.rb, line 271
271:     def voidcmd(cmd)
272:       synchronize do
273:         putline(cmd)
274:         voidresp
275:       end
276:     end

Private Instance methods

[Source]

     # File lib/net/ftp.rb, line 348
348:     def getaddress
349:       thishost = Socket.gethostname rescue ""
350:       if not thishost.index(".")
351:         thishost = Socket.gethostbyname(thishost)[0] rescue ""
352:       end
353:       if ENV.has_key?("LOGNAME")
354:         realuser = ENV["LOGNAME"]
355:       elsif ENV.has_key?("USER")
356:         realuser = ENV["USER"]
357:       else
358:         realuser = "anonymous"
359:       end
360:       return realuser + "@" + thishost
361:     end

[Source]

     # File lib/net/ftp.rb, line 210
210:     def getline
211:       line = @sock.readline # if get EOF, raise EOFError
212:       line.sub!(/(\r\n|\n|\r)\z/n, "")
213:       if @debug_mode
214:         print "get: ", sanitize(line), "\n"
215:       end
216:       return line
217:     end

[Source]

     # File lib/net/ftp.rb, line 220
220:     def getmultiline
221:       line = getline
222:       buff = line
223:       if line[3] == ?-
224:           code = line[0, 3]
225:         begin
226:           line = getline
227:           buff << "\n" << line
228:         end until line[0, 3] == code and line[3] != ?-
229:       end
230:       return buff << "\n"
231:     end

[Source]

     # File lib/net/ftp.rb, line 234
234:     def getresp
235:       @last_response = getmultiline
236:       @last_response_code = @last_response[0, 3]
237:       case @last_response_code
238:       when /\A[123]/
239:         return @last_response
240:       when /\A4/
241:         raise FTPTempError, @last_response
242:       when /\A5/
243:         raise FTPPermError, @last_response
244:       else
245:         raise FTPProtoError, @last_response
246:       end
247:     end

[Source]

     # File lib/net/ftp.rb, line 300
300:     def makepasv
301:       if @sock.peeraddr[0] == "AF_INET"
302:         host, port = parse227(sendcmd("PASV"))
303:       else
304:         host, port = parse229(sendcmd("EPSV"))
305:         #     host, port = parse228(sendcmd("LPSV"))
306:       end
307:       return host, port
308:     end

[Source]

     # File lib/net/ftp.rb, line 291
291:     def makeport
292:       sock = TCPServer.open(@sock.addr[3], 0)
293:       port = sock.addr[1]
294:       host = sock.addr[3]
295:       resp = sendport(host, port)
296:       return sock
297:     end

[Source]

     # File lib/net/ftp.rb, line 154
154:     def open_socket(host, port)
155:       if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
156:         @passive = true
157:         return SOCKSSocket.open(host, port)
158:       else
159:         return TCPSocket.open(host, port)
160:       end
161:     end

[Source]

     # File lib/net/ftp.rb, line 824
824:     def parse227(resp)
825:       if resp[0, 3] != "227"
826:         raise FTPReplyError, resp
827:       end
828:       left = resp.index("(")
829:       right = resp.index(")")
830:       if left == nil or right == nil
831:         raise FTPProtoError, resp
832:       end
833:       numbers = resp[left + 1 .. right - 1].split(",")
834:       if numbers.length != 6
835:         raise FTPProtoError, resp
836:       end
837:       host = numbers[0, 4].join(".")
838:       port = (numbers[4].to_i << 8) + numbers[5].to_i
839:       return host, port
840:     end

[Source]

     # File lib/net/ftp.rb, line 843
843:     def parse228(resp)
844:       if resp[0, 3] != "228"
845:         raise FTPReplyError, resp
846:       end
847:       left = resp.index("(")
848:       right = resp.index(")")
849:       if left == nil or right == nil
850:         raise FTPProtoError, resp
851:       end
852:       numbers = resp[left + 1 .. right - 1].split(",")
853:       if numbers[0] == "4"
854:         if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2"
855:           raise FTPProtoError, resp
856:         end
857:         host = numbers[2, 4].join(".")
858:         port = (numbers[7].to_i << 8) + numbers[8].to_i
859:       elsif numbers[0] == "6"
860:         if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2"
861:           raise FTPProtoError, resp
862:         end
863:         v6 = ["", "", "", "", "", "", "", ""]
864:         for i in 0 .. 7
865:           v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i,
866:                           numbers[(i * 2) + 3].to_i)
867:         end
868:         host = v6[0, 8].join(":")
869:         port = (numbers[19].to_i << 8) + numbers[20].to_i
870:       end 
871:       return host, port
872:     end

[Source]

     # File lib/net/ftp.rb, line 875
875:     def parse229(resp)
876:       if resp[0, 3] != "229"
877:         raise FTPReplyError, resp
878:       end
879:       left = resp.index("(")
880:       right = resp.index(")")
881:       if left == nil or right == nil
882:         raise FTPProtoError, resp
883:       end
884:       numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1])
885:       if numbers.length != 4
886:         raise FTPProtoError, resp
887:       end
888:       port = numbers[3].to_i
889:       host = (@sock.peeraddr())[3]
890:       return host, port
891:     end

[Source]

     # File lib/net/ftp.rb, line 894
894:     def parse257(resp)
895:       if resp[0, 3] != "257"
896:         raise FTPReplyError, resp
897:       end
898:       if resp[3, 2] != ' "'
899:         return ""
900:       end
901:       dirname = ""
902:       i = 5
903:       n = resp.length
904:       while i < n
905:         c = resp[i, 1]
906:         i = i + 1
907:         if c == '"'
908:           if i > n or resp[i, 1] != '"'
909:             break
910:           end
911:           i = i + 1
912:         end
913:         dirname = dirname + c
914:       end
915:       return dirname
916:     end

[Source]

     # File lib/net/ftp.rb, line 201
201:     def putline(line)
202:       if @debug_mode
203:         print "put: ", sanitize(line), "\n"
204:       end
205:       line = line + CRLF
206:       @sock.write(line)
207:     end

[Source]

     # File lib/net/ftp.rb, line 192
192:     def sanitize(s)
193:       if s =~ /^PASS /i
194:         return s[0, 5] + "*" * (s.length - 5)
195:       else
196:         return s
197:       end
198:     end

[Source]

     # File lib/net/ftp.rb, line 278
278:     def sendport(host, port)
279:       af = (@sock.peeraddr)[0]
280:       if af == "AF_INET"
281:         cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",")
282:       elsif af == "AF_INET6"
283:         cmd = sprintf("EPRT |2|%s|%d|", host, port)
284:       else
285:         raise FTPProtoError, host
286:       end
287:       voidcmd(cmd)
288:     end

[Source]

     # File lib/net/ftp.rb, line 311
311:     def transfercmd(cmd, rest_offset = nil)
312:       if @passive
313:         host, port = makepasv
314:         conn = open_socket(host, port)
315:         if @resume and rest_offset
316:           resp = sendcmd("REST " + rest_offset.to_s) 
317:           if resp[0] != ?3
318:             raise FTPReplyError, resp
319:           end
320:         end
321:         resp = sendcmd(cmd)
322:         # skip 2XX for some ftp servers
323:         resp = getresp if resp[0] == ?2
324:         if resp[0] != ?1
325:           raise FTPReplyError, resp
326:         end
327:       else
328:         sock = makeport
329:         if @resume and rest_offset
330:           resp = sendcmd("REST " + rest_offset.to_s) 
331:           if resp[0] != ?3
332:             raise FTPReplyError, resp
333:           end
334:         end
335:         resp = sendcmd(cmd)
336:         # skip 2XX for some ftp servers
337:         resp = getresp if resp[0] == ?2
338:         if resp[0] != ?1
339:           raise FTPReplyError, resp
340:         end
341:         conn = sock.accept
342:         sock.close
343:       end
344:       return conn
345:     end

[Source]

     # File lib/net/ftp.rb, line 250
250:     def voidresp
251:       resp = getresp
252:       if resp[0] != ?2
253:         raise FTPReplyError, resp
254:       end
255:     end

[Validate]