diff --git a/fog.gemspec b/fog.gemspec index 2f6e0ba9f..3cd571865 100644 --- a/fog.gemspec +++ b/fog.gemspec @@ -50,6 +50,7 @@ Gem::Specification.new do |s| s.add_dependency('net-ssh', '>=2.1.3') s.add_dependency('nokogiri', '~>1.5') s.add_dependency('ruby-hmac') + s.add_dependency('unicode', "~> 0.4.4") ## List your development dependencies here. Development dependencies are ## those that are only needed during development diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb index afe2fe2b8..5054940aa 100644 --- a/lib/fog/aws.rb +++ b/lib/fog/aws.rb @@ -1,6 +1,7 @@ require 'fog/core' require 'fog/aws/credential_fetcher' require 'fog/aws/signaturev4' +require 'unicode' module Fog module AWS extend Fog::Provider @@ -85,7 +86,8 @@ module Fog end def self.escape(string) - string.gsub(/([^a-zA-Z0-9_.\-~]+)/) { + string = Unicode::normalize_C(string) + string.gsub(/([^a-zA-Z0-9_.\-~\/]+)/) { "%" + $1.unpack("H2" * $1.bytesize).join("%").upcase } end diff --git a/tests/aws/signed_params_tests.rb b/tests/aws/signed_params_tests.rb index 1df3950de..d1e3f124c 100644 --- a/tests/aws/signed_params_tests.rb +++ b/tests/aws/signed_params_tests.rb @@ -2,4 +2,16 @@ Shindo.tests('AWS | signed_params', ['aws']) do returns( Fog::AWS.escape( "'Stöp!' said Fred_-~." ) ) { "%27St%C3%B6p%21%27%20said%20Fred_-~." } + + tests('Keys can contain a hierarchical prefix which should not be escaped') do + returns( Fog::AWS.escape( "key/with/prefix" ) ) { "key/with/prefix" } + end + + tests('Keys should be canonicalised using Unicode NFC') do + returns( Fog::AWS.escape( ["00E9".to_i(16)].pack("U*") ) ) { "%C3%A9" } + + tests('Characters with combining mark should be combined and then escaped') do + returns( Fog::AWS.escape( ["0065".to_i(16), "0301".to_i(16)].pack("U*") ) ) { "%C3%A9" } + end + end end