FIX: Re-download hotlinked optimized images (#7249)

* FIX: Download local images, even if download remote is disabled
This commit is contained in:
David Taylor 2019-03-27 20:31:12 +00:00 committed by Régis Hanol
parent 12181599db
commit 95d5819218
2 changed files with 60 additions and 19 deletions

View File

@ -35,8 +35,6 @@ module Jobs
end end
def execute(args) def execute(args)
return unless SiteSetting.download_remote_images_to_local?
post_id = args[:post_id] post_id = args[:post_id]
raise Discourse::InvalidParameters.new(:post_id) unless post_id.present? raise Discourse::InvalidParameters.new(:post_id) unless post_id.present?
@ -60,7 +58,7 @@ module Jobs
src = original_src = image['src'] src = original_src = image['src']
src = "#{SiteSetting.force_https ? "https" : "http"}:#{src}" if src.start_with?("//") src = "#{SiteSetting.force_https ? "https" : "http"}:#{src}" if src.start_with?("//")
if is_valid_image_url(src) if should_download_image?(src)
begin begin
# have we already downloaded that file? # have we already downloaded that file?
schemeless_src = remove_scheme(original_src) schemeless_src = remove_scheme(original_src)
@ -136,16 +134,21 @@ module Jobs
def extract_images_from(html) def extract_images_from(html)
doc = Nokogiri::HTML::fragment(html) doc = Nokogiri::HTML::fragment(html)
doc.css("img[src]") - doc.css("img.avatar") doc.css("img[src]") - doc.css("img.avatar") - doc.css(".lightbox img[src]")
end end
def is_valid_image_url(src) def should_download_image?(src)
# make sure we actually have a url # make sure we actually have a url
return false unless src.present? return false unless src.present?
# we don't want to pull uploaded images
return false if Discourse.store.has_been_uploaded?(src) # If file is on the forum or CDN domain
# we don't want to pull relative images if Discourse.store.has_been_uploaded?(src) || src =~ /\A\/[^\/]/i
return false if src =~ /\A\/[^\/]/i # Return true if we can't find the upload in the db
return !Upload.get_from_url(src)
end
# Don't download non-local images unless site setting enabled
return false unless SiteSetting.download_remote_images_to_local?
# parse the src # parse the src
begin begin
@ -157,11 +160,6 @@ module Jobs
hostname = uri.hostname hostname = uri.hostname
return false unless hostname return false unless hostname
# we don't want to pull images hosted on the CDN (if we use one)
return false if Discourse.asset_host.present? && URI.parse(Discourse.asset_host).hostname == hostname
return false if SiteSetting.Upload.s3_cdn_url.present? && URI.parse(SiteSetting.Upload.s3_cdn_url).hostname == hostname
# we don't want to pull images hosted on the main domain
return false if URI.parse(Discourse.base_url_no_prefix).hostname == hostname
# check the domains blacklist # check the domains blacklist
SiteSetting.should_download_images?(src) SiteSetting.should_download_images?(src)
end end

View File

@ -124,22 +124,65 @@ describe Jobs::PullHotlinkedImages do
end end
end end
describe '#is_valid_image_url' do describe '#should_download_image?' do
subject { described_class.new } subject { described_class.new }
describe 'when url is invalid' do describe 'when url is invalid' do
it 'should return false' do it 'should return false' do
expect(subject.is_valid_image_url("null")).to eq(false) expect(subject.should_download_image?("null")).to eq(false)
expect(subject.is_valid_image_url("meta.discourse.org")).to eq(false) expect(subject.should_download_image?("meta.discourse.org")).to eq(false)
end end
end end
describe 'when url is valid' do describe 'when url is valid' do
it 'should return true' do it 'should return true' do
expect(subject.is_valid_image_url("http://meta.discourse.org")).to eq(true) expect(subject.should_download_image?("http://meta.discourse.org")).to eq(true)
expect(subject.is_valid_image_url("//meta.discourse.org")).to eq(true) expect(subject.should_download_image?("//meta.discourse.org")).to eq(true)
end
end
describe 'when url is an upload' do
it 'should return false for original' do
expect(subject.should_download_image?(Fabricate(:upload).url)).to eq(false)
end
it 'should return true for optimized' do
src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image))
expect(subject.should_download_image?(src)).to eq(true)
end
end
context "when download_remote_images_to_local? is false" do
before do
SiteSetting.download_remote_images_to_local = false
end
it "still returns true for optimized" do
src = Discourse.store.get_path_for_optimized_image(Fabricate(:optimized_image))
expect(subject.should_download_image?(src)).to eq(true)
end
it 'returns false for valid remote URLs' do
expect(subject.should_download_image?("http://meta.discourse.org")).to eq(false)
end end
end end
end end
describe "with a lightboxed image" do
let(:upload) { Fabricate(:upload) }
before do
FastImage.expects(:size).returns([1750, 2000])
OptimizedImage.stubs(:resize).returns(true)
end
it "doesn't remove optimized images from lightboxes" do
post = Fabricate(:post, raw: "![alt](#{upload.short_url})")
Jobs::ProcessPost.new.execute(post_id: post.id)
expect { Jobs::PullHotlinkedImages.new.execute(post_id: post.id) }.not_to change { Upload.count }
expect(post.reload.cooked).to include "/uploads/default/optimized/" # Ensure the lightbox was actually rendered
end
end
end end