From a478287f95c624cdc5bd608b1cb9863ca8df23bc Mon Sep 17 00:00:00 2001 From: "M.Shibuya" Date: Sun, 17 Jan 2021 19:32:08 +0900 Subject: [PATCH] Fix URL escape issues by escaping on URI parse error only Fixes #2456, Closes #2457, Fixes #2472, Closes #2473, Fixes #2505, Fixes #2517, Closes #2518 --- lib/carrierwave/downloader/base.rb | 10 +++++++--- spec/downloader/base_spec.rb | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/carrierwave/downloader/base.rb b/lib/carrierwave/downloader/base.rb index ad77e921f..12a39f228 100644 --- a/lib/carrierwave/downloader/base.rb +++ b/lib/carrierwave/downloader/base.rb @@ -31,7 +31,7 @@ def download(url, remote_headers = {}) end ## - # Processes the given URL by parsing and escaping it. Public to allow overriding. + # Processes the given URL by parsing it, and escaping if necessary. Public to allow overriding. # # === Parameters # @@ -40,8 +40,12 @@ def download(url, remote_headers = {}) def process_uri(uri) uri_parts = uri.split('?') encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s - encoded_uri << '?' << Addressable::URI.encode(uri_parts.join('?')).gsub('%5B', '[').gsub('%5D', ']') if uri_parts.any? - URI.parse(encoded_uri) + query = uri_parts.any? ? "?#{uri_parts.join('?')}" : '' + begin + URI.parse("#{encoded_uri}#{query}") + rescue URI::InvalidURIError + URI.parse("#{encoded_uri}#{URI::DEFAULT_PARSER.escape(query)}") + end rescue URI::InvalidURIError, Addressable::URI::InvalidURIError raise CarrierWave::DownloadError, "couldn't parse URL: #{uri}" end diff --git a/spec/downloader/base_spec.rb b/spec/downloader/base_spec.rb index 3599352c5..3ca8a3c2a 100644 --- a/spec/downloader/base_spec.rb +++ b/spec/downloader/base_spec.rb @@ -159,6 +159,20 @@ expect(processed.to_s).to eq('http://example.com/%5D.jpg?test[]') end + it "escapes and parse unescaped characters in path" do + uri = 'http://example.com/あああ.jpg' + processed = subject.process_uri(uri) + expect(processed.class).to eq(URI::HTTP) + expect(processed.to_s).to eq('http://example.com/%E3%81%82%E3%81%82%E3%81%82.jpg') + end + + it "escapes and parse unescaped characters in query string" do + uri = 'http://example.com/?q=あああ' + processed = subject.process_uri(uri) + expect(processed.class).to eq(URI::HTTP) + expect(processed.to_s).to eq('http://example.com/?q=%E3%81%82%E3%81%82%E3%81%82') + end + it "throws an exception on bad uris" do uri = '~http:' expect { subject.process_uri(uri) }.to raise_error(CarrierWave::DownloadError)