2002-01-10 11:00:51 +03:00
|
|
|
#
|
2004-03-24 14:53:31 +03:00
|
|
|
# = uri/ftp.rb
|
2002-01-10 11:00:51 +03:00
|
|
|
#
|
2004-03-24 14:53:31 +03:00
|
|
|
# Author:: Akira Yamada <akira@ruby-lang.org>
|
|
|
|
# License:: You can redistribute it and/or modify it under the same term as Ruby.
|
|
|
|
# Revision:: $Id$
|
2002-01-10 11:00:51 +03:00
|
|
|
#
|
|
|
|
|
|
|
|
require 'uri/generic'
|
|
|
|
|
|
|
|
module URI
|
|
|
|
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# FTP URI syntax is defined by RFC1738 section 3.2.
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2002-01-10 11:00:51 +03:00
|
|
|
class FTP < Generic
|
|
|
|
DEFAULT_PORT = 21
|
|
|
|
|
|
|
|
COMPONENT = [
|
|
|
|
:scheme,
|
|
|
|
:userinfo, :host, :port,
|
|
|
|
:path, :typecode
|
|
|
|
].freeze
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# 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
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2002-01-10 11:00:51 +03:00
|
|
|
TYPECODE = ['a', 'i', 'd'].freeze
|
|
|
|
TYPECODE_PREFIX = ';type='.freeze
|
|
|
|
|
|
|
|
def self.new2(user, password, host, port, path,
|
2004-03-24 14:53:31 +03:00
|
|
|
typecode = nil, arg_check = true)
|
2002-01-10 11:00:51 +03:00
|
|
|
typecode = nil if typecode.size == 0
|
|
|
|
if typecode && !TYPECODE.include?(typecode)
|
2004-03-24 14:53:31 +03:00
|
|
|
raise ArgumentError,
|
|
|
|
"bad typecode is specified: #{typecode}"
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
# do escape
|
|
|
|
|
|
|
|
self.new('ftp',
|
2004-03-24 14:53:31 +03:00
|
|
|
[user, password],
|
|
|
|
host, port, nil,
|
|
|
|
typecode ? path + TYPECODE_PREFIX + typecode : path,
|
|
|
|
nil, nil, nil, arg_check)
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
|
|
|
# == Description
|
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# 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'
|
|
|
|
#
|
|
|
|
# uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
|
|
|
|
# '/path/file.> zip', 'i'])
|
|
|
|
# puts uri.to_s -> ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a
|
|
|
|
#
|
|
|
|
# uri2 = URI::FTP.build({:host => 'ftp.example.com',
|
|
|
|
# :path => 'ruby/src'})
|
|
|
|
# puts uri2.to_s -> ftp://ftp.example.com/ruby/src
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2002-01-10 11:00:51 +03:00
|
|
|
def self.build(args)
|
2005-08-24 09:08:00 +04:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
2002-01-10 11:00:51 +03:00
|
|
|
tmp = Util::make_components_hash(self, args)
|
|
|
|
|
|
|
|
if tmp[:typecode]
|
2004-03-24 14:53:31 +03:00
|
|
|
if tmp[:typecode].size == 1
|
|
|
|
tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode]
|
|
|
|
end
|
|
|
|
tmp[:path] << tmp[:typecode]
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
return super(tmp)
|
|
|
|
end
|
|
|
|
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
|
|
|
# == Description
|
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# Creates a new URI::FTP object from generic URL components with no
|
|
|
|
# syntax checking.
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# Unlike build(), this method does not escape the path component as
|
|
|
|
# required by RFC1738; instead it is treated as per RFC2396.
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2005-08-24 09:08:00 +04:00
|
|
|
# Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
|
|
|
|
# +opaque+, +query+ and +fragment+, in that order.
|
2004-03-24 14:53:31 +03:00
|
|
|
#
|
2002-01-10 11:00:51 +03:00
|
|
|
def initialize(*arg)
|
|
|
|
super(*arg)
|
|
|
|
@typecode = nil
|
|
|
|
tmp = @path.index(TYPECODE_PREFIX)
|
|
|
|
if tmp
|
2004-03-24 14:53:31 +03:00
|
|
|
typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
|
|
|
|
self.set_path(@path[0..tmp - 1])
|
|
|
|
|
|
|
|
if arg[-1]
|
|
|
|
self.typecode = typecode
|
|
|
|
else
|
|
|
|
self.set_typecode(typecode)
|
|
|
|
end
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
attr_reader :typecode
|
|
|
|
|
|
|
|
def check_typecode(v)
|
|
|
|
if TYPECODE.include?(v)
|
2004-03-24 14:53:31 +03:00
|
|
|
return true
|
2002-01-10 11:00:51 +03:00
|
|
|
else
|
2004-03-24 14:53:31 +03:00
|
|
|
raise InvalidComponentError,
|
|
|
|
"bad typecode(expected #{TYPECODE.join(', ')}): #{v}"
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
private :check_typecode
|
|
|
|
|
|
|
|
def set_typecode(v)
|
|
|
|
@typecode = v
|
|
|
|
end
|
|
|
|
protected :set_typecode
|
|
|
|
|
|
|
|
def typecode=(typecode)
|
|
|
|
check_typecode(typecode)
|
|
|
|
set_typecode(typecode)
|
2003-02-14 08:32:48 +03:00
|
|
|
typecode
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
2004-03-24 14:53:31 +03:00
|
|
|
def merge(oth) # :nodoc:
|
2002-01-10 11:00:51 +03:00
|
|
|
tmp = super(oth)
|
|
|
|
if self != tmp
|
2004-03-24 14:53:31 +03:00
|
|
|
tmp.set_typecode(oth.typecode)
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
return tmp
|
|
|
|
end
|
|
|
|
|
2005-08-24 09:08:00 +04:00
|
|
|
# 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 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"
|
|
|
|
#
|
|
|
|
def path
|
|
|
|
return @path.sub(/^\//,'').sub(/^%2F/,'/')
|
|
|
|
end
|
|
|
|
|
2003-10-04 07:49:01 +04:00
|
|
|
def to_s
|
2002-01-10 11:00:51 +03:00
|
|
|
save_path = nil
|
|
|
|
if @typecode
|
2004-03-24 14:53:31 +03:00
|
|
|
save_path = @path
|
|
|
|
@path = @path + TYPECODE_PREFIX + @typecode
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
str = super
|
|
|
|
if @typecode
|
2004-03-24 14:53:31 +03:00
|
|
|
@path = save_path
|
2002-01-10 11:00:51 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
return str
|
|
|
|
end
|
2004-03-24 14:53:31 +03:00
|
|
|
end
|
2002-01-10 11:00:51 +03:00
|
|
|
@@schemes['FTP'] = FTP
|
2004-03-24 14:53:31 +03:00
|
|
|
end
|