From 136c8556a17590f870672d89a52ed2867c9cd22f Mon Sep 17 00:00:00 2001 From: John Joseph Bachir Date: Tue, 11 Oct 2011 16:42:22 -0400 Subject: [PATCH 1/2] test for Connection.prepare_path escaping spaces --- test/connection_test.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/connection_test.rb b/test/connection_test.rb index 5098881..2db1dcf 100644 --- a/test/connection_test.rb +++ b/test/connection_test.rb @@ -121,7 +121,12 @@ def test_request_only_escapes_the_path_the_first_time_it_runs_and_not_subsequent flexmock(connection.http).should_receive(:request).ordered connection.request :put, unescaped_path end - + + def test_prepare_path_percent_escapes_spaces + assert_equal 'foo%20bar%20baz', + Connection.prepare_path('foo bar baz') + end + def test_if_request_has_no_body_then_the_content_length_is_set_to_zero # References bug: http://rubyforge.org/tracker/index.php?func=detail&aid=13052&group_id=2409&atid=9356 connection = Connection.new(@keys) From d991d415695c33c2609a1144994632a6d77ca4ea Mon Sep 17 00:00:00 2001 From: John Joseph Bachir Date: Tue, 11 Oct 2011 17:40:27 -0400 Subject: [PATCH 2/2] Escape reserved characters when generating urls. Uses rfc3986 reserved characters, without /, because slashes in the s3 object name have already been accounted for when the name was created. (i.e. the end-to-end expectation is that they are used as namespace delimiters when used in URLs). This patch also escapes spaces with percent encoding. More info on what is considered reserved: rfc 3986 specifies these as reserved characters in a URL: !*'();:@&=+$,/?#[] of these, Amazon thinks these need to be escaped when it generates urls from its web console: ';:@&=+$,?#[ ] and Amazon thinks these DO NOT need to be escaped: !*() Amazon escapes spaces with + Ruby's URI provides two regexes. What it considers to be reserved is an inexplicable subset of rfc3986 URI::REGEXP::PATTERN::UNRESERVED -_.!~*'()a-zA-Z\\d URI::REGEXP::PATTERN::RESERVED ;/?:@&=+$,\\[\\] --- lib/aws/s3/connection.rb | 3 ++- test/connection_test.rb | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/aws/s3/connection.rb b/lib/aws/s3/connection.rb index 1b91127..d4d150e 100644 --- a/lib/aws/s3/connection.rb +++ b/lib/aws/s3/connection.rb @@ -8,7 +8,8 @@ def connect(options = {}) def prepare_path(path) path = path.remove_extended unless path.valid_utf8? - URI.escape(path) + chars_to_escape = /[!*'();:@&=+$,\?#\[\]\s]/ # rfc3986, without /, plus space + URI.escape( path, chars_to_escape ) end end diff --git a/test/connection_test.rb b/test/connection_test.rb index 2db1dcf..8994e70 100644 --- a/test/connection_test.rb +++ b/test/connection_test.rb @@ -127,6 +127,22 @@ def test_prepare_path_percent_escapes_spaces Connection.prepare_path('foo bar baz') end + def test_url_for_escapes_file_paths_with_reserved_characters + reserved_chars = '!*\'();:@&=+$,?#[ ]' # rfc3986, without /, plus space + connection = + Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :port => 80) + assert_match( + /http:\/\/s3.amazonaws.com\/Foo\/%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%3F%23%5B%20%5D\/foo\/bar\?AWSAccessKeyId=[^&]*&Expires=[^&]*&Signature=.*$/, + AWS::S3::S3Object.url_for("#{reserved_chars}/foo/bar", 'Foo') + ) + end + + def test_prepare_path_escapes_all_uri_reserved_charachters_except_slash + reserved_chars = '!*\'();:@&=+$,?#[ ]' # rfc3986, without /, plus space + assert_equal '%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%3F%23%5B%20%5D/foo/bar', + Connection.prepare_path("#{reserved_chars}/foo/bar") + end + def test_if_request_has_no_body_then_the_content_length_is_set_to_zero # References bug: http://rubyforge.org/tracker/index.php?func=detail&aid=13052&group_id=2409&atid=9356 connection = Connection.new(@keys)