Class: URI::FTP
- Includes:
- OpenURI::OpenRead
- Defined in:
- lib/uri/ftp.rb,
lib/open-uri.rb
Overview
FTP URI syntax is defined by RFC1738 section 3.2.
This class will be redesigned because of difference of implementations; the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it is a good summary about the de facto spec. tools.ietf.org/html/draft-hoffman-ftp-uri-04
Constant Summary collapse
- DEFAULT_PORT =
A Default port of 21 for URI::FTP.
21
- COMPONENT =
An Array of the available components for URI::FTP.
[ :scheme, :userinfo, :host, :port, :path, :typecode ].freeze
- TYPECODE =
Typecode is “a”, “i”, or “d”.
-
“a” indicates a text file (the FTP command was ASCII)
-
“i” indicates a binary file (FTP command IMAGE)
-
“d” indicates the contents of a directory should be displayed
-
['a', 'i', 'd'].freeze
- TYPECODE_PREFIX =
Typecode prefix “;type=”.
';type='.freeze
Constants inherited from Generic
Constants included from URI
DEFAULT_PARSER, Parser, REGEXP, RFC3986_PARSER, TBLDECWWWCOMP_, TBLENCURICOMP_, TBLENCWWWCOMP_, VERSION, VERSION_CODE
Instance Attribute Summary collapse
-
#typecode ⇒ Object
typecode accessor.
Attributes inherited from Generic
#fragment, #host, #opaque, #port, #query, #scheme
Class Method Summary collapse
-
.build(args) ⇒ Object
Description.
- .new2(user, password, host, port, path, typecode = nil, arg_check = true) ⇒ Object
Instance Method Summary collapse
-
#buffer_open(buf, proxy, options) ⇒ Object
:nodoc:.
-
#initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = nil, arg_check = false) ⇒ FTP
constructor
Description.
-
#merge(oth) ⇒ Object
:nodoc:.
-
#path ⇒ Object
Returns the path from an FTP URI.
-
#to_s ⇒ Object
Returns a String representation of the URI::FTP.
Methods included from OpenURI::OpenRead
Methods inherited from Generic
#==, #absolute?, build2, #coerce, component, #component, #decoded_password, #decoded_user, #default_port, default_port, #eql?, #find_proxy, #hash, #hierarchical?, #hostname, #hostname=, #inspect, #merge!, #normalize, #normalize!, #parser, #password, #password=, #registry, #registry=, #relative?, #route_from, #route_to, #select, use_proxy?, use_registry, #user, #user=, #userinfo, #userinfo=
Methods included from URI
decode_uri_component, decode_www_form, decode_www_form_component, encode_uri_component, encode_www_form, encode_www_form_component, extract, for, join, open, parse, regexp, register_scheme, scheme_list, split
Constructor Details
#initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = nil, arg_check = false) ⇒ FTP
Description
Creates a new URI::FTP object from generic URL components with no syntax checking.
Unlike build(), this method does not escape the path component as required by RFC1738; instead it is treated as per RFC2396.
Arguments are scheme
, userinfo
, host
, port
, registry
, path
, opaque
, query
, and fragment
, in that order.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/uri/ftp.rb', line 133 def initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = nil, arg_check = false) raise InvalidURIError unless path path = path.sub(/^\//,'') path.sub!(/^%2F/,'/') super(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser, arg_check) @typecode = nil if tmp = @path.index(TYPECODE_PREFIX) typecode = @path[tmp + TYPECODE_PREFIX.size..-1] @path = @path[0..tmp - 1] if arg_check self.typecode = typecode else self.set_typecode(typecode) end end end |
Instance Attribute Details
#typecode ⇒ Object
typecode accessor.
See URI::FTP::COMPONENT.
161 162 163 |
# File 'lib/uri/ftp.rb', line 161 def typecode @typecode end |
Class Method Details
.build(args) ⇒ Object
Description
Creates a new URI::FTP object from components, with syntax checking.
The components accepted are userinfo
, host
, port
, path
, and typecode
.
The components should be provided either as an Array, or as a Hash with keys formed by preceding the component names with a colon.
If an Array is used, the components must be passed in the order [userinfo, host, port, path, typecode]
.
If the path supplied is absolute, it will be escaped in order to make it absolute in the URI.
Examples:
require 'uri'
uri1 = URI::FTP.build(['user:password', 'ftp.example.com', nil,
'/path/file.zip', 'i'])
uri1.to_s # => "ftp://user:[email protected]/%2Fpath/file.zip;type=i"
uri2 = URI::FTP.build({:host => 'ftp.example.com',
:path => 'ruby/src'})
uri2.to_s # => "ftp://ftp.example.com/ruby/src"
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/uri/ftp.rb', line 96 def self.build(args) # Fix the incoming path to be generic URL syntax # FTP path -> URL path # foo/bar /foo/bar # /foo/bar /%2Ffoo/bar # if args.kind_of?(Array) args[3] = '/' + args[3].sub(/^\//, '%2F') else args[:path] = '/' + args[:path].sub(/^\//, '%2F') end tmp = Util::make_components_hash(self, args) if tmp[:typecode] if tmp[:typecode].size == 1 tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] end tmp[:path] << tmp[:typecode] end return super(tmp) end |
.new2(user, password, host, port, path, typecode = nil, arg_check = true) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/uri/ftp.rb', line 47 def self.new2(user, password, host, port, path, typecode = nil, arg_check = true) # :nodoc: # Do not use this method! Not tested. [Bug #7301] # This methods remains just for compatibility, # Keep it undocumented until the active maintainer is assigned. typecode = nil if typecode.size == 0 if typecode && !TYPECODE.include?(typecode) raise ArgumentError, "bad typecode is specified: #{typecode}" end # do escape self.new('ftp', [user, password], host, port, nil, typecode ? path + TYPECODE_PREFIX + typecode : path, nil, nil, nil, arg_check) end |
Instance Method Details
#buffer_open(buf, proxy, options) ⇒ Object
:nodoc:
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
# File 'lib/open-uri.rb', line 777 def buffer_open(buf, proxy, ) # :nodoc: if proxy OpenURI.open_http(buf, self, proxy, ) return end begin require 'net/ftp' rescue LoadError abort "net/ftp is not found. You may need to `gem install net-ftp` to install net/ftp." end path = self.path path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it. directories = path.split(%r{/}, -1) directories.each {|d| d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") } } unless filename = directories.pop raise ArgumentError, "no filename: #{self.inspect}" end directories.each {|d| if /[\r\n]/ =~ d raise ArgumentError, "invalid directory: #{d.inspect}" end } if /[\r\n]/ =~ filename raise ArgumentError, "invalid filename: #{filename.inspect}" end typecode = self.typecode if typecode && /\A[aid]\z/ !~ typecode raise ArgumentError, "invalid typecode: #{typecode.inspect}" end # The access sequence is defined by RFC 1738 ftp = Net::FTP.new ftp.connect(self.hostname, self.port) ftp.passive = ![:ftp_active_mode] # todo: extract user/passwd from .netrc. user = 'anonymous' passwd = nil user, passwd = self.userinfo.split(/:/) if self.userinfo ftp.login(user, passwd) directories.each {|cwd| ftp.voidcmd("CWD #{cwd}") } if typecode # xxx: typecode D is not handled. ftp.voidcmd("TYPE #{typecode.upcase}") end if [:content_length_proc] [:content_length_proc].call(ftp.size(filename)) end ftp.retrbinary("RETR #{filename}", 4096) { |str| buf << str [:progress_proc].call(buf.size) if [:progress_proc] } ftp.close buf.io.rewind end |
#merge(oth) ⇒ Object
:nodoc:
214 215 216 217 218 219 220 221 |
# File 'lib/uri/ftp.rb', line 214 def merge(oth) # :nodoc: tmp = super(oth) if self != tmp tmp.set_typecode(oth.typecode) end return tmp end |
#path ⇒ Object
Returns the path from an FTP URI.
RFC 1738 specifically states that the path for an FTP URI does not include the / which separates the URI path from the URI host. Example:
ftp://ftp.example.com/pub/ruby
The above URI indicates that the client should connect to ftp.example.com then cd to pub/ruby from the initial login directory.
If you want to cd to an absolute directory, you must include an escaped / (%2F) in the path. Example:
ftp://ftp.example.com/%2Fpub/ruby
This method will then return “/pub/ruby”.
240 241 242 |
# File 'lib/uri/ftp.rb', line 240 def path return @path.sub(/^\//,'').sub(/^%2F/,'/') end |
#to_s ⇒ Object
Returns a String representation of the URI::FTP.
251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/uri/ftp.rb', line 251 def to_s save_path = nil if @typecode save_path = @path @path = @path + TYPECODE_PREFIX + @typecode end str = super if @typecode @path = save_path end return str end |