From db38fea37fb2f40399cac3b239f4955d78f8347c Mon Sep 17 00:00:00 2001 From: knu Date: Thu, 15 Feb 2007 02:41:45 +0000 Subject: * lib/uri/generic.rb (URI::Generic::userinfo): should support empty password. [ruby-core:10290] * lib/uri/generic.rb (URI::Generic::set_password): password can be cleared by nil. [ruby-core:10290] * lib/uri/common.rb (escape): regard second string argument as a character set properly. [ruby-dev:27692] * lib/uri: Lovely RDOC patches from mathew (metaATpoboxDOTcom). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@11747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/uri/common.rb | 8 +++-- lib/uri/ftp.rb | 86 ++++++++++++++++++++++++++++++++++++++++++------------ lib/uri/generic.rb | 7 +++-- lib/uri/http.rb | 49 ++++++++++++++++++++++++++----- lib/uri/https.rb | 4 +++ lib/uri/mailto.rb | 45 ++++++++++++++++++++++------ 6 files changed, 161 insertions(+), 38 deletions(-) (limited to 'lib') diff --git a/lib/uri/common.rb b/lib/uri/common.rb index ccf57bd93b..f74f0eb2e1 100644 --- a/lib/uri/common.rb +++ b/lib/uri/common.rb @@ -261,6 +261,7 @@ module URI # +unsafe+:: # Regexp that matches all symbols that must be replaced with codes. # By default uses REGEXP::UNSAFE. + # When this argument is a String, it represents a character set. # # == Description # @@ -277,10 +278,13 @@ module URI # p URI.unescape(enc_uri) # # => "http://example.com/?a=\t\r" # + # p URI.escape("@?@!", "!?") + # # => "@%3F@%21" + # def escape(str, unsafe = UNSAFE) unless unsafe.kind_of?(Regexp) # perhaps unsafe is String object - unsafe = Regexp.new(Regexp.quote(unsafe), false, 'N') + unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false, 'N') end str.gsub(unsafe) do |us| tmp = '' @@ -542,7 +546,7 @@ module URI # require "uri" # # URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.") - # # => ["http://foo.example.org/bla", "mailto:test@example.com"] + # # => ["http://foo.example.com/bla", "mailto:test@example.com"] # def self.extract(str, schemes = nil, &block) if block_given? diff --git a/lib/uri/ftp.rb b/lib/uri/ftp.rb index 26109e4d27..3afdce01b4 100644 --- a/lib/uri/ftp.rb +++ b/lib/uri/ftp.rb @@ -11,7 +11,7 @@ require 'uri/generic' module URI # - # RFC1738 section 3.2. + # FTP URI syntax is defined by RFC1738 section 3.2. # class FTP < Generic DEFAULT_PORT = 21 @@ -22,12 +22,11 @@ module URI :path, :typecode ].freeze # - # Typecode is, "a", "i" or "d". - # As for "a" the text, as for "i" binary, - # as for "d" the directory is displayed. - # "A" with the text, as for "i" being binary, - # is because the respective data type was called ASCII and - # IMAGE with the protocol of FTP. + # 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 # TYPECODE = ['a', 'i', 'd'].freeze TYPECODE_PREFIX = ';type='.freeze @@ -52,11 +51,43 @@ module URI # # == Description # - # Creates a new URI::FTP object from components of URI::FTP with - # check. It is scheme, userinfo, host, port, path and typecode. It - # provided by an Array or a Hash. typecode is "a", "i" or "d". + # 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 # 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] @@ -72,16 +103,14 @@ module URI # # == Description # - # Create a new URI::FTP object from ``generic'' components with no - # check. + # Creates a new URI::FTP object from generic URL components with no + # syntax checking. # - # == Usage + # Unlike build(), this method does not escape the path component as + # required by RFC1738; instead it is treated as per RFC2396. # - # require 'uri' - # p ftp = URI.parse("ftp://ftp.ruby-lang.org/pub/ruby/;type=d") - # # => # - # p ftp.typecode - # # => "d" + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+ and +fragment+, in that order. # def initialize(*arg) super(*arg) @@ -130,6 +159,27 @@ module URI return tmp end + # 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 + def to_s save_path = nil if @typecode diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index 51c2bf17f6..cae6169190 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -12,6 +12,7 @@ module URI # # Base class for all URI classes. + # Implements generic URI syntax as per RFC 2396. # class Generic include URI @@ -336,7 +337,7 @@ module URI protected :set_user def set_password(v) - set_userinfo(@user, v) + @password = v v end protected :set_password @@ -355,7 +356,9 @@ module URI private :escape_userpass def userinfo - if !@password + if @user.nil? or @user.empty? + nil + elsif @password.nil? or @password.empty? @user else @user + ':' + @password diff --git a/lib/uri/http.rb b/lib/uri/http.rb index 1f8bf587aa..87eb8893f2 100644 --- a/lib/uri/http.rb +++ b/lib/uri/http.rb @@ -11,7 +11,12 @@ require 'uri/generic' module URI # - # RFC1738 section 3.3. + # The syntax of HTTP URIs is defined in RFC1738 section 3.3. + # + # Note that the Ruby URI library allows HTTP URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See . # class HTTP < Generic DEFAULT_PORT = 80 @@ -27,9 +32,27 @@ module URI # # == Description # - # Create a new URI::HTTP object from components of URI::HTTP with - # check. It is scheme, userinfo, host, port, path, query and - # fragment. It provided by an Array of a Hash. + # Create a new URI::HTTP object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, query and + # fragment. + # + # 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, query, fragment]. + # + # Example: + # + # newuri = URI::HTTP.build({:host => 'www.example.com', + # :path> => '/foo/bar'}) + # + # newuri = URI::HTTP.build([nil, "www.example.com", nil, "/path", + # "query", 'fragment']) + # + # Currently, if passed userinfo components this method generates + # invalid HTTP URIs as per RFC 1738. # def self.build(args) tmp = Util::make_components_hash(self, args) @@ -39,8 +62,17 @@ module URI # # == Description # - # Create a new URI::HTTP object from ``generic'' components with no - # check. + # Create a new URI::HTTP object from generic URI components as per + # RFC 2396. No HTTP-specific syntax checking (as per RFC 1738) is + # performed. + # + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+ and +fragment+, in that order. + # + # Example: + # + # uri = URI::HTTP.new(['http', nil, "www.example.com", nil, "/path", + # "query", 'fragment']) # def initialize(*arg) super(*arg) @@ -49,7 +81,10 @@ module URI # # == Description # - # Returns: path + '?' + query + # Returns the full path for an HTTP request, as required by Net::HTTP::Get. + # + # If the URI contains a query, the full path is URI#path + '?' + URI#query. + # Otherwise, the path is simply URI#path. # def request_uri r = path_query diff --git a/lib/uri/https.rb b/lib/uri/https.rb index 78e5b9af12..9761636304 100644 --- a/lib/uri/https.rb +++ b/lib/uri/https.rb @@ -9,6 +9,10 @@ require 'uri/http' module URI + + # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather + # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs; + # see URI::HTTP. class HTTPS < HTTP DEFAULT_PORT = 443 end diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb index 0c93ae1c0d..44f04f2dd5 100644 --- a/lib/uri/mailto.rb +++ b/lib/uri/mailto.rb @@ -61,11 +61,29 @@ module URI # # == Description # - # Creates a new URI::MailTo object from components of URI::MailTo - # with check. It is to and headers. It provided by an Array of a - # Hash. You can provide headers as String like - # "subject=subscribe&cc=addr" or Array like [["subject", - # "subscribe"], ["cc", "addr"]] + # Creates a new URI::MailTo object from components, with syntax checking. + # + # Components can be provided as an Array or Hash. If an Array is used, + # the components must be supplied as [to, headers]. + # + # If a Hash is used, the keys are the component names preceded by colons. + # + # The headers can be supplied as a pre-encoded string, such as + # "subject=subscribe&cc=address", or as an Array of Arrays like + # [['subject', 'subscribe'], ['cc', 'address']] + # + # Examples: + # + # require 'uri' + # + # m1 = URI::MailTo.build(['joe@example.com', 'subject=Ruby']) + # puts m1.to_s -> mailto:joe@example.com?subject=Ruby + # + # m2 = URI::MailTo.build(['john@example.com', [['Subject', 'Ruby'], ['Cc', 'jack@example.com']]]) + # puts m2.to_s -> mailto:john@example.com?Subject=Ruby&Cc=jack@example.com + # + # m3 = URI::MailTo.build({:to => 'listman@example.com', :headers => [['subject', 'subscribe']]}) + # puts m3.to_s -> mailto:listman@example.com?subject=subscribe # def self.build(args) tmp = Util::make_components_hash(self, args) @@ -104,9 +122,11 @@ module URI # # == Description # - # Creates a new URI::MailTo object from ``generic'' components with - # no check. Because, this method is usually called from URI::parse - # and the method checks validity of each components. + # Creates a new URI::MailTo object from generic URL components with + # no syntax checking. + # + # This method is usually called from URI::parse, which checks + # the validity of each component. # def initialize(*arg) super(*arg) @@ -128,7 +148,11 @@ module URI "unrecognised opaque part for mailtoURL: #{@opaque}" end end + + # The primary e-mail address of the URL, as a String attr_reader :to + + # E-mail headers set by the URL, as an Array of Arrays attr_reader :headers def check_to(v) @@ -203,8 +227,11 @@ module URI '' end end + + # Returns the RFC822 e-mail text equivalent of the URL, as a String. + # + # Example: # - # == Usage # require 'uri' # # uri = URI.parse("mailto:ruby-list@ruby-lang.org?Subject=subscribe&cc=myaddr") -- cgit v1.2.3