Skip to content

Commit 3faf749

Browse files
committed
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
1 parent c655c17 commit 3faf749

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

lib/carrierwave/downloader/base.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def download(url, remote_headers = {})
3131
end
3232

3333
##
34-
# Processes the given URL by parsing and escaping it. Public to allow overriding.
34+
# Processes the given URL by parsing it, and escaping if necessary. Public to allow overriding.
3535
#
3636
# === Parameters
3737
#
@@ -40,8 +40,12 @@ def download(url, remote_headers = {})
4040
def process_uri(uri)
4141
uri_parts = uri.split('?')
4242
encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s
43-
encoded_uri << '?' << Addressable::URI.encode(uri_parts.join('?')).gsub('%5B', '[').gsub('%5D', ']') if uri_parts.any?
44-
URI.parse(encoded_uri)
43+
query = uri_parts.any? ? "?#{uri_parts.join('?')}" : ''
44+
begin
45+
URI.parse("#{encoded_uri}#{query}")
46+
rescue URI::InvalidURIError
47+
URI.parse("#{encoded_uri}#{URI::DEFAULT_PARSER.escape(query)}")
48+
end
4549
rescue URI::InvalidURIError, Addressable::URI::InvalidURIError
4650
raise CarrierWave::DownloadError, "couldn't parse URL: #{uri}"
4751
end

spec/downloader/base_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,20 @@
159159
expect(processed.to_s).to eq('http://example.com/%5D.jpg?test[]')
160160
end
161161

162+
it "escapes and parse unescaped characters in path" do
163+
uri = 'http://example.com/あああ.jpg'
164+
processed = subject.process_uri(uri)
165+
expect(processed.class).to eq(URI::HTTP)
166+
expect(processed.to_s).to eq('http://example.com/%E3%81%82%E3%81%82%E3%81%82.jpg')
167+
end
168+
169+
it "escapes and parse unescaped characters in query string" do
170+
uri = 'http://example.com/?q=あああ'
171+
processed = subject.process_uri(uri)
172+
expect(processed.class).to eq(URI::HTTP)
173+
expect(processed.to_s).to eq('http://example.com/?q=%E3%81%82%E3%81%82%E3%81%82')
174+
end
175+
162176
it "throws an exception on bad uris" do
163177
uri = '~http:'
164178
expect { subject.process_uri(uri) }.to raise_error(CarrierWave::DownloadError)

0 commit comments

Comments
 (0)