diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | lib/uri/generic.rb | 104 | ||||
-rw-r--r-- | test/uri/test_generic.rb | 75 | ||||
-rw-r--r-- | version.h | 8 |
4 files changed, 122 insertions, 70 deletions
@@ -1,3 +1,8 @@ +Wed Aug 1 12:40:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * generic.rb (URI::Generic::merge_path): behave as RFC 3986. + [ruby-talk:252052] + Tue Jul 31 23:38:09 2007 Tadayoshi Funaba <tadf@dotrb.org> * lib/date/format.rb (_parse): now interprets slashed numerical diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index 2b66adeb93..bcf293ec0a 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -616,65 +616,65 @@ module URI private :split_path def merge_path(base, rel) + # RFC2396, Section 5.2, 5) - if rel[0] == ?/ #/ - # RFC2396, Section 5.2, 5) - return rel + # RFC2396, Section 5.2, 6) + base_path = split_path(base) + rel_path = split_path(rel) + + # RFC2396, Section 5.2, 6), a) + base_path << '' if base_path.last == '..' + while i = base_path.index('..') + base_path.slice!(i - 1, 2) + end - else - # RFC2396, Section 5.2, 6) - base_path = split_path(base) - rel_path = split_path(rel) - - # RFC2396, Section 5.2, 6), a) - base_path << '' if base_path.last == '..' - while i = base_path.index('..') - base_path.slice!(i - 1, 2) - end - if base_path.empty? - base_path = [''] # keep '/' for root directory - else - base_path.pop - end + if (first = rel_path.first) and first.empty? + base_path.clear + rel_path.shift + end - # RFC2396, Section 5.2, 6), c) - # RFC2396, Section 5.2, 6), d) - rel_path.push('') if rel_path.last == '.' || rel_path.last == '..' - rel_path.delete('.') - - # RFC2396, Section 5.2, 6), e) - tmp = [] - rel_path.each do |x| - if x == '..' && - !(tmp.empty? || tmp.last == '..') - tmp.pop - else - tmp << x - end + # RFC2396, Section 5.2, 6), c) + # RFC2396, Section 5.2, 6), d) + rel_path.push('') if rel_path.last == '.' || rel_path.last == '..' + rel_path.delete('.') + + # RFC2396, Section 5.2, 6), e) + tmp = [] + rel_path.each do |x| + if x == '..' && + !(tmp.empty? || tmp.last == '..') + tmp.pop + else + tmp << x end + end - add_trailer_slash = true - while x = tmp.shift - if x == '..' && base_path.size > 1 - # RFC2396, Section 4 - # a .. or . in an absolute path has no special meaning - base_path.pop - else - # if x == '..' - # valid absolute (but abnormal) path "/../..." - # else - # valid absolute path - # end - base_path << x - tmp.each {|t| base_path << t} - add_trailer_slash = false - break - end + add_trailer_slash = !tmp.empty? + if base_path.empty? + base_path = [''] # keep '/' for root directory + elsif add_trailer_slash + base_path.pop + end + while x = tmp.shift + if x == '..' + # RFC2396, Section 4 + # a .. or . in an absolute path has no special meaning + base_path.pop if base_path.size > 1 + else + # if x == '..' + # valid absolute (but abnormal) path "/../..." + # else + # valid absolute path + # end + base_path << x + tmp.each {|t| base_path << t} + add_trailer_slash = false + break end - base_path.push('') if add_trailer_slash - - return base_path.join('/') end + base_path.push('') if add_trailer_slash + + return base_path.join('/') end private :merge_path diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb index 96707abbbc..8ac0149c60 100644 --- a/test/uri/test_generic.rb +++ b/test/uri/test_generic.rb @@ -1,10 +1,7 @@ require 'test/unit' require 'uri' -module URI - - -class TestGeneric < Test::Unit::TestCase +class URI::TestGeneric < Test::Unit::TestCase def setup @url = 'http://a/b/c/d;p?q' @base_url = URI.parse(@url) @@ -296,11 +293,11 @@ class TestGeneric < Test::Unit::TestCase assert_equal('//g', url.to_s) # http://a/b/c/d;p?q -# ?y = http://a/b/c/?y +# ?y = http://a/b/c/d;p?y url = @base_url.merge('?y') assert_kind_of(URI::HTTP, url) - assert_equal('http://a/b/c/?y', url.to_s) - url = @base_url.route_to('http://a/b/c/?y') + assert_equal('http://a/b/c/d;p?y', url.to_s) + url = @base_url.route_to('http://a/b/c/d;p?y') assert_kind_of(URI::Generic, url) assert_equal('?y', url.to_s) @@ -452,10 +449,10 @@ class TestGeneric < Test::Unit::TestCase assert_equal('', url.to_s) # http://a/b/c/d;p?q -# /./g = http://a/./g +# /./g = http://a/g url = @base_url.merge('/./g') assert_kind_of(URI::HTTP, url) - assert_equal('http://a/./g', url.to_s) + assert_equal('http://a/g', url.to_s) url = @base_url.route_to('http://a/./g') assert_kind_of(URI::Generic, url) assert_equal('/./g', url.to_s) @@ -464,7 +461,7 @@ class TestGeneric < Test::Unit::TestCase # /../g = http://a/../g url = @base_url.merge('/../g') assert_kind_of(URI::HTTP, url) - assert_equal('http://a/../g', url.to_s) + assert_equal('http://a/g', url.to_s) url = @base_url.route_to('http://a/../g') assert_kind_of(URI::Generic, url) assert_equal('/../g', url.to_s) @@ -506,10 +503,10 @@ class TestGeneric < Test::Unit::TestCase assert_equal('..g', url.to_s) # http://a/b/c/d;p?q -# ../../../g = http://a/../g +# ../../../g = http://a/g url = @base_url.merge('../../../g') assert_kind_of(URI::HTTP, url) - assert_equal('http://a/../g', url.to_s) + assert_equal('http://a/g', url.to_s) url = @base_url.route_to('http://a/../g') assert_kind_of(URI::Generic, url) assert('../../../g' != url.to_s) # ok? yes, it confuses you @@ -519,7 +516,7 @@ class TestGeneric < Test::Unit::TestCase # ../../../../g = http://a/../../g url = @base_url.merge('../../../../g') assert_kind_of(URI::HTTP, url) - assert_equal('http://a/../../g', url.to_s) + assert_equal('http://a/g', url.to_s) url = @base_url.route_to('http://a/../../g') assert_kind_of(URI::Generic, url) assert('../../../../g' != url.to_s) # ok? yes, it confuses you @@ -692,7 +689,57 @@ class TestGeneric < Test::Unit::TestCase assert_raises(URI::InvalidURIError) { uri.path = 'bar' } assert_raises(URI::InvalidURIError) { uri.query = 'bar' } end -end + def m(s) + @base_url.merge(s).to_s +end + def test_rfc3986_examples + assert_equal("g:h", m("g:h")) + assert_equal("http://a/b/c/g", m("g")) + assert_equal("http://a/b/c/g", m("./g")) + assert_equal("http://a/b/c/g/", m("g/")) + assert_equal("http://a/g", m("/g")) + assert_equal("http://g", m("//g")) + assert_equal("http://a/b/c/d;p?y", m("?y")) + assert_equal("http://a/b/c/g?y", m("g?y")) + assert_equal("http://a/b/c/d;p?q#s", m("#s")) + assert_equal("http://a/b/c/g#s", m("g#s")) + assert_equal("http://a/b/c/g?y#s", m("g?y#s")) + assert_equal("http://a/b/c/;x", m(";x")) + assert_equal("http://a/b/c/g;x", m("g;x")) + assert_equal("http://a/b/c/g;x?y#s", m("g;x?y#s")) + assert_equal("http://a/b/c/d;p?q", m("")) + assert_equal("http://a/b/c/", m(".")) + assert_equal("http://a/b/c/", m("./")) + assert_equal("http://a/b/", m("..")) + assert_equal("http://a/b/", m("../")) + assert_equal("http://a/b/g", m("../g")) + assert_equal("http://a/", m("../..")) + assert_equal("http://a/", m("../../")) + assert_equal("http://a/g", m("../../g")) + assert_equal("http://a/g", m("../../../g")) + assert_equal("http://a/g", m("../../../../g")) + + assert_equal("http://a/g", m("/./g")) + assert_equal("http://a/g", m("/../g")) + assert_equal("http://a/b/c/g.", m("g.")) + assert_equal("http://a/b/c/.g", m(".g")) + assert_equal("http://a/b/c/g..", m("g..")) + assert_equal("http://a/b/c/..g", m("..g")) + + assert_equal("http://a/b/g", m("./../g")) + assert_equal("http://a/b/c/g/", m("./g/.")) + assert_equal("http://a/b/c/g/h", m("g/./h")) + assert_equal("http://a/b/c/h", m("g/../h")) + assert_equal("http://a/b/c/g;x=1/y", m("g;x=1/./y")) + assert_equal("http://a/b/c/y", m("g;x=1/../y")) + + assert_equal("http://a/b/c/g?y/./x", m("g?y/./x")) + assert_equal("http://a/b/c/g?y/../x", m("g?y/../x")) + assert_equal("http://a/b/c/g#s/./x", m("g#s/./x")) + assert_equal("http://a/b/c/g#s/../x", m("g#s/../x")) + + assert_equal("http:g", m("http:g")) + end end @@ -1,15 +1,15 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2007-07-30" +#define RUBY_RELEASE_DATE "2007-08-01" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20070730 +#define RUBY_RELEASE_CODE 20070801 #define RUBY_PATCHLEVEL 0 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 9 #define RUBY_VERSION_TEENY 0 #define RUBY_RELEASE_YEAR 2007 -#define RUBY_RELEASE_MONTH 7 -#define RUBY_RELEASE_DAY 30 +#define RUBY_RELEASE_MONTH 8 +#define RUBY_RELEASE_DAY 1 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; |