From 88725d6ce85115ea3b0652007db5d40a1c069be3 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 27 Apr 2017 14:42:22 +0200 Subject: OEmbed support for PreviewCard (#2337) * OEmbed support for PreviewCard * Improve ProviderDiscovery code failure treatment * Do not crawl links if there is a content warning, since those don't display a link card anyway * Reset db schema * Fresh migrate * Fix rubocop style issues Fix #1681 - return existing access token when applicable instead of creating new * Fix test * Extract http client to helper * Improve oembed controller --- app/lib/formatter.rb | 8 ++++++-- app/lib/provider_discovery.rb | 36 ++++++++++++++++++++++++++++++++++++ app/lib/sanitize_config.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 app/lib/provider_discovery.rb create mode 100644 app/lib/sanitize_config.rb (limited to 'app/lib') diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 1d8e90d1f..5ae6238d9 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true require 'singleton' +require_relative './sanitize_config' class Formatter include Singleton include RoutingHelper include ActionView::Helpers::TextHelper - include ActionView::Helpers::SanitizeHelper def format(status) return reformat(status.content) unless status.local? @@ -23,7 +23,7 @@ class Formatter end def reformat(html) - sanitize(html, tags: %w(a br p span), attributes: %w(href rel class)) + sanitize(html, Sanitize::Config::MASTODON_STRICT) end def plaintext(status) @@ -43,6 +43,10 @@ class Formatter html.html_safe # rubocop:disable Rails/OutputSafety end + def sanitize(html, config) + Sanitize.fragment(html, config) + end + private def encode(html) diff --git a/app/lib/provider_discovery.rb b/app/lib/provider_discovery.rb new file mode 100644 index 000000000..761ddae0f --- /dev/null +++ b/app/lib/provider_discovery.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class ProviderDiscovery < OEmbed::ProviderDiscovery + include HttpHelper + + class << self + def discover_provider(url, options = {}) + res = http_client.get(url) + format = options[:format] + + raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html' + + html = Nokogiri::HTML(res.to_s) + + if format.nil? || format == :json + provider_endpoint ||= html.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value + format ||= :json if provider_endpoint + end + + if format.nil? || format == :xml + provider_endpoint ||= html.at_xpath('//link[@type="application/xml+oembed"]')&.attribute('href')&.value + format ||= :xml if provider_endpoint + end + + begin + provider_endpoint = Addressable::URI.parse(provider_endpoint) + provider_endpoint.query = nil + provider_endpoint = provider_endpoint.to_s + rescue Addressable::URI::InvalidURIError + raise OEmbed::NotFound, url + end + + OEmbed::Provider.new(provider_endpoint, format || OEmbed::Formatter.default) + end + end +end diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb new file mode 100644 index 000000000..7cf1c3062 --- /dev/null +++ b/app/lib/sanitize_config.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class Sanitize + module Config + HTTP_PROTOCOLS ||= ['http', 'https', :relative].freeze + + MASTODON_STRICT ||= freeze_config( + elements: %w(p br span a), + + attributes: { + 'a' => %w(href), + 'span' => %w(class), + }, + + protocols: { + 'a' => { 'href' => HTTP_PROTOCOLS }, + } + ) + + MASTODON_OEMBED ||= freeze_config merge( + RELAXED, + elements: RELAXED[:elements] + %w(audio embed iframe source video), + + attributes: merge( + RELAXED[:attributes], + 'audio' => %w(controls), + 'embed' => %w(height src type width), + 'iframe' => %w(allowfullscreen frameborder height scrolling src width), + 'source' => %w(src type), + 'video' => %w(controls height loop width), + 'div' => [:data] + ), + + protocols: merge( + RELAXED[:protocols], + 'embed' => { 'src' => HTTP_PROTOCOLS }, + 'iframe' => { 'src' => HTTP_PROTOCOLS }, + 'source' => { 'src' => HTTP_PROTOCOLS } + ) + ) + end +end -- cgit