From f96b410bc7e81fee98752dd7d715791fae5b2378 Mon Sep 17 00:00:00 2001 From: Shawn Veader Date: Mon, 10 Sep 2012 17:50:04 -0300 Subject: [PATCH] Decode attributes pulled from URI.parse The RFC indicates that username and passwords may be encoded. http://tools.ietf.org/html/rfc2396#section-3.2.2 Found this trying to use the mysql://username:password@host:port/db and having special characters in the password which needed to be URI encoded. --- activerecord/CHANGELOG.md | 6 +++++- .../connection_adapters/connection_specification.rb | 2 ++ .../test/cases/connection_specification/resolver_test.rb | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 888990416e..c99f09f478 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 4.0.0 (unreleased) ## +* Decode URI encoded attributes on database connection URLs. + + *Shawn Veader* + * Add `find_or_create_by`, `find_or_create_by!` and `find_or_initialize_by` methods to `Relation`. @@ -38,7 +42,7 @@ *Jon Leighton* -* Fix bug with presence validation of associations. Would incorrectly add duplicated errors +* Fix bug with presence validation of associations. Would incorrectly add duplicated errors when the association was blank. Bug introduced in 1fab518c6a75dac5773654646eb724a59741bc13. *Scott Willson* diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index b9a61f7d91..09250d3c01 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -73,6 +73,8 @@ module ActiveRecord :database => config.path.sub(%r{^/},""), :host => config.host } spec.reject!{ |_,value| value.blank? } + uri_parser = URI::Parser.new + spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) } if config.query options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys spec.merge!(options) diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index 434d2b7ba5..40c4dc94d1 100644 --- a/activerecord/test/cases/connection_specification/resolver_test.rb +++ b/activerecord/test/cases/connection_specification/resolver_test.rb @@ -36,6 +36,14 @@ module ActiveRecord :host => "foo", :encoding => "utf8" }, spec) end + + def test_encoded_password + skip "only if mysql is available" unless defined?(MysqlAdapter) + password = 'am@z1ng_p@ssw0rd#!' + encoded_password = URI.encode_www_form_component(password) + spec = resolve "mysql://foo:#{encoded_password}@localhost/bar" + assert_equal password, spec[:password] + end end end end