FIX: store the topic links using the cooked upload url

This commit is contained in:
Régis Hanol 2018-08-14 12:23:32 +02:00
parent ad5f502332
commit de92913bf4
31 changed files with 116 additions and 110 deletions

View File

@ -112,7 +112,7 @@ class EmbedController < ApplicationController
end
response.headers['X-Frame-Options'] = "ALLOWALL"
rescue URI::InvalidURIError
rescue URI::Error
raise Discourse::InvalidAccess.new('invalid referer host')
end

View File

@ -88,7 +88,7 @@ class StaticController < ApplicationController
destination = uri.path
destination = "#{uri.path}?#{uri.query}" if uri.path =~ /new-topic/ || uri.path =~ /new-message/ || uri.path =~ /user-api-key/
end
rescue URI::InvalidURIError
rescue URI::Error
# Do nothing if the URI is invalid
end
end

View File

@ -60,7 +60,7 @@ class UserBadgesController < ApplicationController
if params[:reason].present?
path = begin
URI.parse(params[:reason]).path
rescue URI::InvalidURIError
rescue URI::Error
end
route = Rails.application.routes.recognize_path(path) if path

View File

@ -41,7 +41,7 @@ class Users::OmniauthCallbacksController < ApplicationController
if origin.present?
parsed = begin
URI.parse(origin)
rescue URI::InvalidURIError
rescue URI::Error
end
if parsed

View File

@ -106,7 +106,7 @@ module UserNotificationsHelper
def url_for_email(href)
URI(href).host.present? ? href : UrlHelper.absolute("#{Discourse.base_uri}#{href}")
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
href
end

View File

@ -6,7 +6,7 @@ module Jobs
begin
URI.parse(featured_link)
rescue URI::InvalidURIError
rescue URI::Error
topic.update_attributes(featured_link: URI.extract(featured_link).first)
end
end

View File

@ -149,7 +149,7 @@ module Jobs
# parse the src
begin
uri = URI.parse(src)
rescue URI::InvalidURIError
rescue URI::Error
return false
end

View File

@ -14,7 +14,7 @@ class EmbeddableHost < ActiveRecord::Base
if uri.is_a?(String)
uri = begin
URI(UrlHelper.escape_uri(uri))
rescue URI::InvalidURIError
rescue URI::Error
end
end
return false unless uri.present?
@ -45,7 +45,7 @@ class EmbeddableHost < ActiveRecord::Base
uri = begin
URI(UrlHelper.escape_uri(url))
rescue URI::InvalidURIError
rescue URI::Error
end
uri.present? && record_for_url(uri).present?

View File

@ -26,7 +26,7 @@ class IncomingLink < ActiveRecord::Base
begin
host = URI.parse(opts[:referer]).host
referer = opts[:referer][0..999]
rescue URI::InvalidURIError
rescue URI::Error
# bad uri, skip
end
end
@ -71,7 +71,7 @@ class IncomingLink < ActiveRecord::Base
self.incoming_referer_id = referer_record.id if referer_record
end
rescue URI::InvalidURIError
rescue URI::Error
# ignore
end

View File

@ -98,7 +98,7 @@ class PostAnalyzer
uri = self.class.parse_uri_rfc2396(u)
host = uri.host
@linked_hosts[host] ||= 1 unless host.nil?
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
# An invalid URI does not count as a host
next
end

View File

@ -77,7 +77,7 @@ class SiteSetting < ActiveRecord::Base
host = URI.parse(src).host
return !(setting.split('|').include?(host))
rescue URI::InvalidURIError
rescue URI::Error
return true
end

View File

@ -139,7 +139,7 @@ class TopicEmbed < ActiveRecord::Base
uri.host = original_uri.host
node[url_param] = uri.to_s
end
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
# If there is a mistyped URL, just do nothing
end
end

View File

@ -137,8 +137,9 @@ SQL
post_number = nil
if upload = Upload.get_from_url(url)
url = upload.url
internal = Discourse.store.internal?
# Store the same URL that will be used in the cooked version of the post
url = UrlHelper.cook_url(upload.url)
elsif route = Discourse.route_for(parsed)
internal = true
@ -217,7 +218,7 @@ SQL
end
end
rescue URI::InvalidURIError
rescue URI::Error
# if the URI is invalid, don't store it.
rescue ActionController::RoutingError
# If we can't find the route, no big deal

View File

@ -17,7 +17,7 @@ class TopicLinkClick < ActiveRecord::Base
uri = begin
URI.parse(url)
rescue URI::InvalidURIError
rescue URI::Error
end
urls = Set.new
@ -47,7 +47,7 @@ class TopicLinkClick < ActiveRecord::Base
if Discourse.asset_host.present?
cdn_uri = begin
URI.parse(Discourse.asset_host)
rescue URI::InvalidURIError
rescue URI::Error
end
if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path)
@ -59,7 +59,7 @@ class TopicLinkClick < ActiveRecord::Base
if SiteSetting.Upload.s3_cdn_url.present?
cdn_uri = begin
URI.parse(SiteSetting.Upload.s3_cdn_url)
rescue URI::InvalidURIError
rescue URI::Error
end
if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path)

View File

@ -80,7 +80,7 @@ class Upload < ActiveRecord::Base
uri = begin
URI(URI.unescape(url))
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
end
return if uri&.path.blank?

View File

@ -142,7 +142,7 @@ class UserProfile < ActiveRecord::Base
domain = begin
URI.parse(self.website).host
rescue URI::InvalidURIError
rescue URI::Error
end
self.errors.add :base, (I18n.t('user.website.domain_not_allowed', domains: allowed_domains.split('|').join(", "))) unless allowed_domains.split('|').include?(domain)
end

View File

@ -206,7 +206,7 @@ class UserSerializer < BasicUserSerializer
def website_name
uri = begin
URI(website.to_s)
rescue URI::InvalidURIError
rescue URI::Error
end
return if uri.nil? || uri.host.nil?

View File

@ -257,14 +257,14 @@ class CookedPostProcessor
return unless SiteSetting.crawl_images? || Discourse.store.has_been_uploaded?(url)
@size_cache[url] = FastImage.size(absolute_url)
rescue Zlib::BufError, URI::InvalidURIError, URI::InvalidComponentError, OpenSSL::SSL::SSLError
rescue Zlib::BufError, URI::Error, OpenSSL::SSL::SSLError
# FastImage.size raises BufError for some gifs, leave it.
end
def is_valid_image_url?(url)
uri = URI.parse(url)
%w(http https).include? uri.scheme
rescue URI::InvalidURIError
rescue URI::Error
end
def convert_to_link!(img)
@ -460,28 +460,14 @@ class CookedPostProcessor
end
def optimize_urls
# attachments can't be on the CDN when either setting is enabled
if SiteSetting.login_required || SiteSetting.prevent_anons_from_downloading_files
@doc.css("a.attachment[href]").each do |a|
href = a["href"].to_s
a["href"] = UrlHelper.schemaless UrlHelper.absolute_without_cdn(href) if UrlHelper.is_local(href)
end
end
use_s3_cdn = SiteSetting.Upload.enable_s3_uploads && SiteSetting.Upload.s3_cdn_url.present?
%w{href data-download-href}.each do |selector|
@doc.css("a[#{selector}]").each do |a|
href = a[selector].to_s
a[selector] = UrlHelper.schemaless UrlHelper.absolute(href) if UrlHelper.is_local(href)
a[selector] = Discourse.store.cdn_url(a[selector]) if use_s3_cdn
a[selector] = UrlHelper.cook_url(a[selector].to_s)
end
end
@doc.css("img[src]").each do |img|
src = img["src"].to_s
img["src"] = UrlHelper.schemaless UrlHelper.absolute(src) if UrlHelper.is_local(src)
img["src"] = Discourse.store.cdn_url(img["src"]) if use_s3_cdn
img["src"] = UrlHelper.cook_url(img["src"].to_s)
end
end
@ -544,7 +530,7 @@ class CookedPostProcessor
path =
begin
URI(img["src"]).path
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
nil
end

View File

@ -270,7 +270,7 @@ module Discourse
unless uri.is_a?(URI)
uri = begin
URI(uri)
rescue URI::InvalidURIError
rescue URI::Error
end
end

View File

@ -218,7 +218,7 @@ module Email
begin
uri = URI.parse(base_url)
host = uri.host.downcase if uri.host.present?
rescue URI::InvalidURIError
rescue URI::Error
end
end
host

View File

@ -153,7 +153,7 @@ module Email
# If an iframe is protocol relative, use SSL when displaying it
display_src = "#{src_uri.scheme || 'https'}://#{src_uri.host}#{src_uri.path}#{src_uri.query.nil? ? '' : '?' + src_uri.query}#{src_uri.fragment.nil? ? '' : '#' + src_uri.fragment}"
i.replace "<p><a href='#{src_uri.to_s}'>#{CGI.escapeHTML(display_src)}</a><p>"
rescue URI::InvalidURIError
rescue URI::Error
# If the URL is weird, remove the iframe
i.remove
end
@ -215,7 +215,7 @@ module Email
@fragment.css("a").each do |link|
begin
link["href"] = "#{site_uri}#{link['href']}" unless URI(link["href"].to_s).host.present?
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
# leave it
end
end

View File

@ -378,8 +378,8 @@ class FinalDestination
def uri(location)
begin
URI(location)
rescue URI::InvalidURIError, ArgumentError
URI.parse(location)
rescue URI::Error
end
end

View File

@ -46,7 +46,7 @@ class InlineOneboxer
if always_allow || domains
uri = begin
URI(url)
rescue URI::InvalidURIError
rescue URI::Error
end
if uri.present? &&

View File

@ -293,7 +293,7 @@ module PrettyText
else
l["rel"] = "nofollow noopener"
end
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
# add a nofollow anyway
l["rel"] = "nofollow noopener"
end
@ -363,7 +363,7 @@ module PrettyText
unless uri.host.present? || href.start_with?('mailto')
link["href"] = "#{site_uri}#{link['href']}"
end
rescue URI::InvalidURIError, URI::InvalidComponentError
rescue URI::Error
# leave it
end
end

View File

@ -426,13 +426,13 @@ module SiteSettingExtension
host = begin
URI.parse(url)&.host
rescue URI::InvalidURIError
rescue URI::Error
nil
end
host ||= begin
URI.parse("http://#{url}")&.host
rescue URI::InvalidURIError
rescue URI::Error
nil
end

View File

@ -31,4 +31,21 @@ class UrlHelper
encoded
end
def self.cook_url(url)
return url unless is_local(url)
uri = URI.parse(url)
filename = File.basename(uri.path)
is_attachment = !FileHelper.is_image?(filename)
no_cdn = SiteSetting.login_required || SiteSetting.prevent_anons_from_downloading_files
url = absolute_without_cdn(url)
url = Discourse.store.cdn_url(url) unless is_attachment && no_cdn
schemaless(url)
rescue URI::Error
url
end
end

View File

@ -4,7 +4,7 @@ class UploadUrlValidator < ActiveModel::EachValidator
uri =
begin
URI.parse(value)
rescue URI::InvalidURIError
rescue URI::Error
end
unless uri && Upload.exists?(url: value)

View File

@ -5,7 +5,7 @@ class UrlValidator < ActiveModel::EachValidator
begin
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && !uri.host.nil? && uri.host.include?(".")
rescue URI::InvalidURIError => e
rescue URI::Error => e
if (e.message =~ /URI must be ascii only/)
value = URI.encode(value)
retry

View File

@ -162,7 +162,7 @@ describe CookedPostProcessor do
FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0)
cpp.post_process_images
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/1/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/original/1X/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
<span class=\"filename\">logo.png</span><span class=\"informations\">1750x2000 1.21 KB</span><span class=\"expand\"></span>
</div></a></div></p>"
expect(cpp).to be_dirty
@ -170,25 +170,25 @@ describe CookedPostProcessor do
describe 'when image is an svg' do
let(:post) do
Fabricate(:post, raw: '<img src="/uploads/default/1/1234567890123456.svg">')
Fabricate(:post, raw: '<img src="/uploads/default/original/1X/1234567890123456.svg">')
end
it 'should not add lightbox' do
cpp.post_process_images
expect(cpp.html).to match_html("<p><img src=\"/uploads/default/1/1234567890123456.svg\" width=\"690\"\ height=\"788\"></p>")
expect(cpp.html).to match_html("<p><img src=\"/uploads/default/original/1X/1234567890123456.svg\" width=\"690\"\ height=\"788\"></p>")
end
describe 'when image src is an URL' do
let(:post) do
Fabricate(:post, raw: '<img src="http://test.discourse/uploads/default/1/1234567890123456.svg?somepamas">')
Fabricate(:post, raw: '<img src="http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas">')
end
it 'should not add lightbox' do
SiteSetting.crawl_images = true
cpp.post_process_images
expect(cpp.html).to match_html("<p><img src=\"http://test.discourse/uploads/default/1/1234567890123456.svg?somepamas\" width=\"690\"\ height=\"788\"></p>")
expect(cpp.html).to match_html("<p><img src=\"http://test.discourse/uploads/default/original/1X/1234567890123456.svg?somepamas\" width=\"690\"\ height=\"788\"></p>")
end
end
end
@ -239,7 +239,7 @@ describe CookedPostProcessor do
it "crops the image" do
cpp.post_process_images
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/1/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_230x500.png\" width=\"230\" height=\"500\"><div class=\"meta\">
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/original/1X/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_230x500.png\" width=\"230\" height=\"500\"><div class=\"meta\">
<span class=\"filename\">logo.png</span><span class=\"informations\">1125x2436 1.21 KB</span><span class=\"expand\"></span>
</div></a></div></p>"
expect(cpp).to be_dirty
@ -270,7 +270,7 @@ describe CookedPostProcessor do
it "generates overlay information" do
cpp.post_process_images
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/subfolder/uploads/default/1/1234567890123456.jpg\" data-download-href=\"/subfolder/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/subfolder/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/subfolder/uploads/default/original/1X/1234567890123456.jpg\" data-download-href=\"/subfolder/uploads/default/#{upload.sha1}\" title=\"logo.png\"><img src=\"/subfolder/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
<span class=\"filename\">logo.png</span><span class=\"informations\">1750x2000 1.21 KB</span><span class=\"expand\"></span>
</div></a></div></p>"
expect(cpp).to be_dirty
@ -279,7 +279,7 @@ describe CookedPostProcessor do
it "should escape the filename" do
upload.update_attributes!(original_filename: "><img src=x onerror=alert('haha')>.png")
cpp.post_process_images
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/subfolder/uploads/default/1/1234567890123456.jpg\" data-download-href=\"/subfolder/uploads/default/#{upload.sha1}\" title=\"&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png\"><img src=\"/subfolder/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/subfolder/uploads/default/original/1X/1234567890123456.jpg\" data-download-href=\"/subfolder/uploads/default/#{upload.sha1}\" title=\"&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png\"><img src=\"/subfolder/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" width=\"690\" height=\"788\"><div class=\"meta\">
<span class=\"filename\">&amp;gt;&amp;lt;img src=x onerror=alert(&amp;#39;haha&amp;#39;)&amp;gt;.png</span><span class=\"informations\">1750x2000 1.21 KB</span><span class=\"expand\"></span>
</div></a></div></p>"
end
@ -305,7 +305,7 @@ describe CookedPostProcessor do
it "generates overlay information" do
cpp.post_process_images
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/1/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"WAT\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" title=\"WAT\" width=\"690\" height=\"788\"><div class=\"meta\">
expect(cpp.html).to match_html "<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/original/1X/1234567890123456.jpg\" data-download-href=\"/uploads/default/#{upload.sha1}\" title=\"WAT\"><img src=\"/uploads/default/optimized/1X/#{upload.sha1}_1_690x788.png\" title=\"WAT\" width=\"690\" height=\"788\"><div class=\"meta\">
<span class=\"filename\">WAT</span><span class=\"informations\">1750x2000 1.21 KB</span><span class=\"expand\"></span>
</div></a></div></p>"
expect(cpp).to be_dirty
@ -594,13 +594,14 @@ describe CookedPostProcessor do
it "uses schemaless url for uploads" do
cpp.optimize_urls
expect(cpp.html).to match_html '<p><a href="//test.localhost/uploads/default/2/2345678901234567.jpg">Link</a><br>
<img src="//test.localhost/uploads/default/1/1234567890123456.jpg"><br>
expect(cpp.html).to match_html <<~HTML
<p><a href="//test.localhost/uploads/default/original/2X/2345678901234567.jpg">Link</a><br>
<img src="//test.localhost/uploads/default/original/1X/1234567890123456.jpg"><br>
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
<img src="http://foo.bar/image.png"><br>
<a class="attachment" href="//test.localhost/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
<img src="//test.localhost/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:">
</p>'
<img src="//test.localhost/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:"></p>
HTML
end
context "when CDN is enabled" do
@ -608,51 +609,55 @@ describe CookedPostProcessor do
it "uses schemaless CDN url for http uploads" do
Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com")
cpp.optimize_urls
expect(cpp.html).to match_html '<p><a href="//my.cdn.com/uploads/default/2/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/1/1234567890123456.jpg"><br>
expect(cpp.html).to match_html <<~HTML
<p><a href="//my.cdn.com/uploads/default/original/2X/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/original/1X/1234567890123456.jpg"><br>
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
<img src="http://foo.bar/image.png"><br>
<a class="attachment" href="//my.cdn.com/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:">
</p>'
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:"></p>
HTML
end
it "doesn't use schemaless CDN url for https uploads" do
Rails.configuration.action_controller.stubs(:asset_host).returns("https://my.cdn.com")
cpp.optimize_urls
expect(cpp.html).to match_html '<p><a href="https://my.cdn.com/uploads/default/2/2345678901234567.jpg">Link</a><br>
<img src="https://my.cdn.com/uploads/default/1/1234567890123456.jpg"><br>
expect(cpp.html).to match_html <<~HTML
<p><a href="https://my.cdn.com/uploads/default/original/2X/2345678901234567.jpg">Link</a><br>
<img src="https://my.cdn.com/uploads/default/original/1X/1234567890123456.jpg"><br>
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
<img src="http://foo.bar/image.png"><br>
<a class="attachment" href="https://my.cdn.com/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
<img src="https://my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:">
</p>'
<img src="https://my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:"></p>
HTML
end
it "doesn't use CDN when login is required" do
SiteSetting.login_required = true
Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com")
cpp.optimize_urls
expect(cpp.html).to match_html '<p><a href="//my.cdn.com/uploads/default/2/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/1/1234567890123456.jpg"><br>
expect(cpp.html).to match_html <<~HTML
<p><a href="//my.cdn.com/uploads/default/original/2X/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/original/1X/1234567890123456.jpg"><br>
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
<img src="http://foo.bar/image.png"><br>
<a class="attachment" href="//test.localhost/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:">
</p>'
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:"></p>
HTML
end
it "doesn't use CDN when preventing anons from downloading files" do
SiteSetting.prevent_anons_from_downloading_files = true
Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com")
cpp.optimize_urls
expect(cpp.html).to match_html '<p><a href="//my.cdn.com/uploads/default/2/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/1/1234567890123456.jpg"><br>
expect(cpp.html).to match_html <<~HTML
<p><a href="//my.cdn.com/uploads/default/original/2X/2345678901234567.jpg">Link</a><br>
<img src="//my.cdn.com/uploads/default/original/1X/1234567890123456.jpg"><br>
<a href="http://www.google.com" rel="nofollow noopener">Google</a><br>
<img src="http://foo.bar/image.png"><br>
<a class="attachment" href="//test.localhost/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)<br>
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:">
</p>'
<img src="//my.cdn.com/images/emoji/twitter/smile.png?v=5" title=":smile:" class="emoji" alt=":smile:"></p>
HTML
end
end

View File

@ -46,25 +46,25 @@ end
Fabricator(:post_with_plenty_of_images, from: :post) do
cooked '
<aside class="quote"><img src="/uploads/default/1/1234567890123456.jpg"></aside>
<div class="onebox-result"><img src="/uploads/default/1/1234567890123456.jpg"></div>
<div class="onebox"><img src="/uploads/default/1/1234567890123456.jpg"></div>
<aside class="quote"><img src="/uploads/default/original/1X/1234567890123456.jpg"></aside>
<div class="onebox-result"><img src="/uploads/default/original/1X/1234567890123456.jpg"></div>
<div class="onebox"><img src="/uploads/default/original/1X/1234567890123456.jpg"></div>
<p>With an emoji! <img src="//cdn.discourse.org/meta/images/emoji/twitter/smile.png?v=1" title=":smile:" class="emoji" alt="smile" width="72" height="72"></p>
'
end
Fabricator(:post_with_uploaded_image, from: :post) do
raw '<img src="/uploads/default/2/3456789012345678.png" width="1500" height="2000">'
raw '<img src="/uploads/default/original/2X/3456789012345678.png" width="1500" height="2000">'
end
Fabricator(:post_with_an_attachment, from: :post) do
raw '<a class="attachment" href="/uploads/default/186/66b3ed1503efc936.zip">archive.zip</a>'
raw '<a class="attachment" href="/uploads/default/origina/1X/66b3ed1503efc936.zip">archive.zip</a>'
end
Fabricator(:post_with_unsized_images, from: :post) do
raw '
<img src="http://foo.bar/image.png">
<img src="/uploads/default/1/1234567890123456.jpg">
<img src="/uploads/default/original/1X/1234567890123456.jpg">
'
end
@ -76,28 +76,28 @@ Fabricator(:post_with_image_urls, from: :post) do
end
Fabricator(:post_with_large_image, from: :post) do
raw '<img src="/uploads/default/1/1234567890123456.jpg">'
raw '<img src="/uploads/default/original/1X/1234567890123456.jpg">'
end
Fabricator(:post_with_large_image_and_title, from: :post) do
raw '<img src="/uploads/default/1/1234567890123456.jpg" title="WAT">'
raw '<img src="/uploads/default/original/1X/1234567890123456.jpg" title="WAT">'
end
Fabricator(:post_with_large_image_on_subfolder, from: :post) do
raw '<img src="/subfolder/uploads/default/1/1234567890123456.jpg">'
raw '<img src="/subfolder/uploads/default/original/1X/1234567890123456.jpg">'
end
Fabricator(:post_with_uploads, from: :post) do
raw '
<a href="/uploads/default/2/2345678901234567.jpg">Link</a>
<img src="/uploads/default/1/1234567890123456.jpg">
<a href="/uploads/default/original/2X/2345678901234567.jpg">Link</a>
<img src="/uploads/default/original/1X/1234567890123456.jpg">
'
end
Fabricator(:post_with_uploads_and_links, from: :post) do
raw '
<a href="/uploads/default/2/2345678901234567.jpg">Link</a>
<img src="/uploads/default/1/1234567890123456.jpg">
<a href="/uploads/default/original/2X/2345678901234567.jpg">Link</a>
<img src="/uploads/default/original/1X/1234567890123456.jpg">
<a href="http://www.google.com">Google</a>
<img src="http://foo.bar/image.png">
<a class="attachment" href="/uploads/default/original/1X/af2c2618032c679333bebf745e75f9088748d737.txt">text.txt</a> (20 Bytes)

View File

@ -27,25 +27,22 @@ describe TopicLink do
describe 'external links' do
before do
post = Fabricate(:post, raw: "
http://a.com/
http://b.com/b
http://#{'a' * 200}.com/invalid
http://b.com/#{'a' * 500}
", user: user, topic: topic)
post = Fabricate(:post, raw: <<~RAW, user: user, topic: topic)
http://a.com/
https://b.com/b
http://#{'a' * 200}.com/invalid
//b.com/#{'a' * 500}
RAW
TopicLink.extract_from(post)
end
it 'works' do
# has the forum topic links
expect(topic.topic_links.count).to eq(3)
# works with markdown links
expect(topic.topic_links.exists?(url: "http://a.com/")).to eq(true)
#works with markdown links followed by a period
expect(topic.topic_links.exists?(url: "http://b.com/b")).to eq(true)
expect(topic.topic_links.pluck(:url)).to contain_exactly(
"http://a.com/",
"https://b.com/b",
"//b.com/#{'a' * 500}"[0...TopicLink.max_url_length]
)
end
end