onebox 1.7.3 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/onebox/engine.rb +2 -2
- data/lib/onebox/engine/audio_onebox.rb +8 -2
- data/lib/onebox/engine/audioboom_onebox.rb +2 -3
- data/lib/onebox/engine/bandcamp_onebox.rb +4 -2
- data/lib/onebox/engine/coub_onebox.rb +2 -1
- data/lib/onebox/engine/douban_onebox.rb +11 -10
- data/lib/onebox/engine/five_hundred_px_onebox.rb +2 -1
- data/lib/onebox/engine/flickr_onebox.rb +2 -1
- data/lib/onebox/engine/gfycat_onebox.rb +5 -3
- data/lib/onebox/engine/giphy_onebox.rb +4 -2
- data/lib/onebox/engine/google_calendar_onebox.rb +13 -9
- data/lib/onebox/engine/google_maps_onebox.rb +2 -2
- data/lib/onebox/engine/image_onebox.rb +9 -4
- data/lib/onebox/engine/imgur_onebox.rb +55 -34
- data/lib/onebox/engine/mixcloud_onebox.rb +2 -1
- data/lib/onebox/engine/replit_onebox.rb +2 -3
- data/lib/onebox/engine/sketchfab_onebox.rb +4 -2
- data/lib/onebox/engine/slides_onebox.rb +2 -1
- data/lib/onebox/engine/soundcloud_onebox.rb +2 -1
- data/lib/onebox/engine/standard_embed.rb +3 -3
- data/lib/onebox/engine/steam_store_onebox.rb +4 -2
- data/lib/onebox/engine/video_onebox.rb +7 -2
- data/lib/onebox/engine/vimeo_onebox.rb +2 -1
- data/lib/onebox/engine/whitelisted_generic_onebox.rb +8 -3
- data/lib/onebox/engine/youku_onebox.rb +5 -12
- data/lib/onebox/file_type_finder.rb +7 -7
- data/lib/onebox/helpers.rb +8 -8
- data/lib/onebox/layout.rb +1 -1
- data/lib/onebox/onebox_sanitize_config.rb +24 -0
- data/lib/onebox/preview.rb +9 -2
- data/lib/onebox/version.rb +1 -1
- data/onebox.gemspec +1 -0
- data/spec/lib/onebox/engine/audio_onebox_spec.rb +0 -4
- data/spec/lib/onebox/engine/image_onebox_spec.rb +0 -4
- data/spec/lib/onebox/engine_spec.rb +1 -7
- data/spec/lib/onebox/preview_spec.rb +15 -0
- data/spec/spec_helper.rb +2 -6
- data/templates/_layout.mustache +1 -1
- data/templates/douban.mustache +1 -1
- data/templates/googledocs.mustache +2 -2
- data/templates/whitelistedgeneric.mustache +1 -1
- data/templates/wikipedia.mustache +1 -1
- data/templates/xkcd.mustache +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31e3e276aeb010031132237bf3e98b6b75901de0
|
4
|
+
data.tar.gz: 1619ea75ad1e8b795b6a932f6b2deabdcbb51f73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e2b1ef745998ec0cb12dee9b7454e19b834fc9fa7b895c95e8b4bb17b18926abbf1cbae6ce77d9d36a8440ab8bd460a070514f31aa4d56fd0c9a660a3c72eb4
|
7
|
+
data.tar.gz: d3ee07279fede7a2ef9dd8ebbd9410d19434c002a113950797a01afb1ae6690a12835bea7525ee358bcfc8a7f9f22ceb2dbfe4d2fa213c2a0b50da8cd592cd61
|
data/lib/onebox/engine.rb
CHANGED
@@ -42,8 +42,8 @@ module Onebox
|
|
42
42
|
@timeout = timeout || Onebox.options.timeout
|
43
43
|
end
|
44
44
|
|
45
|
-
# raises error if not defined in onebox engine.
|
46
|
-
# an engine.
|
45
|
+
# raises error if not defined in onebox engine.
|
46
|
+
# This is the output method for an engine.
|
47
47
|
def to_html
|
48
48
|
fail NoMethodError, "Engines need to implement this method"
|
49
49
|
end
|
@@ -10,8 +10,14 @@ module Onebox
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_html
|
13
|
-
|
14
|
-
|
13
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(@url)
|
14
|
+
|
15
|
+
<<-HTML
|
16
|
+
<audio controls>
|
17
|
+
<source src="#{escaped_url}">
|
18
|
+
<a href="#{escaped_url}">#{@url}</a>
|
19
|
+
</audio>
|
20
|
+
HTML
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -9,11 +9,10 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
oembed = get_oembed
|
12
|
-
|
13
|
-
# we want the image to have the same dimensions as the embedded html
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:thumbnail_url])
|
14
13
|
|
15
14
|
<<-HTML
|
16
|
-
<img src="#{
|
15
|
+
<img src="#{escaped_src}" style="max-width: #{oembed[:width]}px; max-height: #{oembed[:height]}px;" #{Helpers.title_attr(oembed)}>
|
17
16
|
HTML
|
18
17
|
end
|
19
18
|
|
@@ -9,15 +9,17 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
og = get_opengraph
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:image])
|
13
|
+
"<img src='#{escaped_src}' height='#{og[:video_height]}' #{Helpers.title_attr(og)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_html
|
16
17
|
og = get_opengraph
|
17
18
|
src = og[:video_secure_url] || og[:video]
|
19
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(src)
|
18
20
|
|
19
21
|
<<-HTML
|
20
|
-
<iframe src="#{
|
22
|
+
<iframe src="#{escaped_src}"
|
21
23
|
width="#{og[:video_width]}"
|
22
24
|
height="#{og[:video_height]}"
|
23
25
|
scrolling="no"
|
@@ -9,7 +9,8 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
oembed = get_oembed
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:thumbnail_url])
|
13
|
+
"<img src='#{escaped_src}' height='#{oembed[:thumbnail_height]}' width='#{oembed[:thumbnail_width]}' #{Helpers.title_attr(oembed)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_html
|
@@ -9,14 +9,15 @@ module Onebox
|
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
def data
|
13
|
+
{
|
14
|
+
link: link,
|
15
|
+
title: raw.css('title').text.gsub("\n",'').strip(),
|
16
|
+
image: raw.css('img[rel*="v:"]').first['src'],
|
17
|
+
description: raw.css('meta[name=description]').first['content'],
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
22
23
|
end
|
@@ -9,7 +9,8 @@ module Onebox
|
|
9
9
|
|
10
10
|
def to_html
|
11
11
|
og = get_opengraph
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:image])
|
13
|
+
"<img src='#{escaped_src}' width='#{og[:image_width]}' height='#{og[:image_height]}' #{Helpers.title_attr(og)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
end
|
@@ -9,7 +9,8 @@ module Onebox
|
|
9
9
|
|
10
10
|
def to_html
|
11
11
|
og = get_opengraph
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:image])
|
13
|
+
"<img src='#{escaped_src}' width='#{og[:image_width]}' height='#{og[:image_height]}' #{Helpers.title_attr(og)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
end
|
@@ -10,9 +10,10 @@ module Onebox
|
|
10
10
|
def to_html
|
11
11
|
oembed = get_oembed
|
12
12
|
src = Nokogiri::HTML::fragment(oembed[:html]).at_css("iframe")["src"]
|
13
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(src)
|
13
14
|
|
14
15
|
<<-HTML
|
15
|
-
<iframe src="#{
|
16
|
+
<iframe src="#{escaped_src}"
|
16
17
|
width="#{oembed[:width]}"
|
17
18
|
height="#{oembed[:height]}"
|
18
19
|
scrolling="no"
|
@@ -23,10 +24,11 @@ module Onebox
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def placeholder_html
|
26
|
-
|
27
|
+
og = get_opengraph
|
28
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:image])
|
27
29
|
|
28
30
|
<<-HTML
|
29
|
-
<img src="#{
|
31
|
+
<img src="#{escaped_src}" width="#{og[:image_width]}" height="#{og[:image_height]}">
|
30
32
|
HTML
|
31
33
|
end
|
32
34
|
|
@@ -9,10 +9,12 @@ module Onebox
|
|
9
9
|
|
10
10
|
def to_html
|
11
11
|
oembed = get_oembed
|
12
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(oembed[:url])
|
13
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:image])
|
12
14
|
|
13
15
|
<<-HTML
|
14
|
-
<a href="#{
|
15
|
-
<img src="#{
|
16
|
+
<a href="#{escaped_url}" target="_blank">
|
17
|
+
<img src="#{escaped_src}" width="#{oembed[:width]}" height="#{oembed[:height]}" #{Helpers.title_attr(oembed)}>
|
16
18
|
</a>
|
17
19
|
HTML
|
18
20
|
end
|
@@ -8,18 +8,22 @@ module Onebox
|
|
8
8
|
|
9
9
|
def to_html
|
10
10
|
url = @url.split('&').first
|
11
|
-
|
11
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(url)
|
12
|
+
"<iframe src='#{src}&rm=minimal' style='border: 0' width='800' height='600' frameborder='0' scrolling='no'>#{placeholder_html}</iframe>"
|
12
13
|
end
|
13
14
|
|
14
15
|
def placeholder_html
|
15
|
-
|
16
|
-
<div placeholder
|
17
|
-
<div style='
|
18
|
-
<div
|
19
|
-
<
|
20
|
-
</
|
21
|
-
|
16
|
+
<<-HTML
|
17
|
+
<div placeholder>
|
18
|
+
<div class='gdocs-onebox gdocs-onebox-splash' style='display:table-cell;vertical-align:middle;width:800px;height:600px'>
|
19
|
+
<div style='text-align:center;'>
|
20
|
+
<div class='gdocs-onebox-logo g-calendar-logo'></div>
|
21
|
+
<p>Google Calendar</p>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
HTML
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
25
|
-
end
|
29
|
+
end
|
@@ -52,9 +52,9 @@ module Onebox
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def placeholder_html
|
55
|
-
width
|
55
|
+
width = @placeholder_width || 690
|
56
56
|
height = @placeholder_height || 400
|
57
|
-
"<img src
|
57
|
+
"<img src='#{@placeholder}' width='#{width}' height='#{height}'/>"
|
58
58
|
end
|
59
59
|
|
60
60
|
private
|
@@ -11,12 +11,17 @@ module Onebox
|
|
11
11
|
|
12
12
|
def to_html
|
13
13
|
# Fix Dropbox image links
|
14
|
-
if /^https:\/\/www.dropbox.com\/s
|
15
|
-
@url.
|
14
|
+
if @url[/^https:\/\/www.dropbox.com\/s\//]
|
15
|
+
@url.sub!("https://www.dropbox.com", "https://dl.dropboxusercontent.com")
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(@url)
|
19
|
+
|
20
|
+
<<-HTML
|
21
|
+
<a href="#{escaped_url}" target="_blank">
|
22
|
+
<img src="#{escaped_url}">
|
23
|
+
</a>
|
24
|
+
HTML
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -8,46 +8,67 @@ module Onebox
|
|
8
8
|
always_https
|
9
9
|
|
10
10
|
def to_html
|
11
|
-
|
12
|
-
return
|
13
|
-
return
|
14
|
-
return
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def placeholder_html
|
19
|
-
imgur_data = get_imgur_data
|
20
|
-
return "<video width='#{imgur_data[:"video:width"]}' height='#{imgur_data[:"video:height"]}' #{Helpers.title_attr(imgur_data)} controls autoplay loop><source src='#{imgur_data[:"video:secure_url"]}' type='video/mp4'><source src='#{imgur_data[:"video:secure_url"].gsub('mp4', 'webm')}' type='video/webm'></video>" if imgur_data[:"video:secure_url"]
|
21
|
-
return "<img src='#{get_secure_link(imgur_data[:image])}' #{Helpers.title_attr(imgur_data)} alt='Imgur' height='#{imgur_data[:"image:height"]}' width='#{imgur_data[:"image:width"]}'>"
|
22
|
-
return nil
|
11
|
+
og = get_opengraph
|
12
|
+
return video_html(og) if !Onebox::Helpers::blank?(og[:video_secure_url])
|
13
|
+
return album_html(og) if is_album?
|
14
|
+
return image_html(og) if !Onebox::Helpers::blank?(og[:image])
|
15
|
+
nil
|
23
16
|
end
|
24
17
|
|
25
18
|
private
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
19
|
+
|
20
|
+
def video_html(og)
|
21
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:video_secure_url])
|
22
|
+
|
23
|
+
<<-HTML
|
24
|
+
<video width='#{og[:video_width]}' height='#{og[:video_height]}' #{Helpers.title_attr(og)} controls loop>
|
25
|
+
<source src='#{escaped_src}' type='video/mp4'>
|
26
|
+
<source src='#{escaped_src.gsub('mp4', 'webm')}' type='video/webm'>
|
27
|
+
</video>
|
28
|
+
HTML
|
36
29
|
end
|
37
|
-
return imgur_data
|
38
|
-
end
|
39
30
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
31
|
+
def album_html(og)
|
32
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(url)
|
33
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(get_secure_link(og[:image]))
|
34
|
+
|
35
|
+
<<-HTML
|
36
|
+
<div class='onebox imgur-album'>
|
37
|
+
<a href='#{escaped_url}' target='_blank'>
|
38
|
+
<span class='outer-box' style='width:#{og[:image_width]}px'>
|
39
|
+
<span class='inner-box'>
|
40
|
+
<span class='album-title'>[Album] #{og[:title]}</span>
|
41
|
+
</span>
|
42
|
+
</span>
|
43
|
+
<img src='#{escaped_src}' #{Helpers.title_attr(og)} height='#{og[:image_height]}' width='#{og[:image_width]}'>
|
44
|
+
</a>
|
45
|
+
</div>
|
46
|
+
HTML
|
47
|
+
end
|
48
|
+
|
49
|
+
def is_album?
|
50
|
+
oembed_data = Onebox::Helpers.symbolize_keys(::MultiJson.load(Onebox::Helpers.fetch_response("http://api.imgur.com/oembed.json?url=#{url}").body))
|
51
|
+
imgur_data_id = Nokogiri::HTML(oembed_data[:html]).xpath("//blockquote").attr("data-id")
|
52
|
+
imgur_data_id.to_s[/a\//]
|
53
|
+
end
|
54
|
+
|
55
|
+
def image_html(og)
|
56
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(url)
|
57
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(get_secure_link(og[:image]))
|
58
|
+
|
59
|
+
<<-HTML
|
60
|
+
<a href='#{escaped_url}' target='_blank'>
|
61
|
+
<img src='#{escaped_src}' #{Helpers.title_attr(og)} alt='Imgur' height='#{og[:image_height]}' width='#{og[:image_width]}'>
|
62
|
+
</a>
|
63
|
+
HTML
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_secure_link(link)
|
67
|
+
secure_link = URI(link)
|
68
|
+
secure_link.scheme = 'https'
|
69
|
+
secure_link.to_s
|
70
|
+
end
|
45
71
|
|
46
|
-
def get_secure_link(link)
|
47
|
-
secure_link = URI(link)
|
48
|
-
secure_link.scheme = 'https'
|
49
|
-
secure_link.to_s
|
50
|
-
end
|
51
72
|
end
|
52
73
|
end
|
53
74
|
end
|
@@ -9,7 +9,8 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
oembed = get_oembed
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:image])
|
13
|
+
"<img src='#{escaped_src}' height='#{oembed[:height]}' #{Helpers.title_attr(oembed)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_html
|
@@ -9,11 +9,10 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
oembed = get_oembed
|
12
|
-
|
13
|
-
# we want the image to have the same dimensions as the embedded html
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:thumbnail_url])
|
14
13
|
|
15
14
|
<<-HTML
|
16
|
-
<img src="#{
|
15
|
+
<img src="#{escaped_src}" style="max-width: #{oembed[:width]}px; max-height: #{oembed[:height]}px;" #{Helpers.title_attr(oembed)}>
|
17
16
|
HTML
|
18
17
|
end
|
19
18
|
|
@@ -11,9 +11,10 @@ module Onebox
|
|
11
11
|
opengraph = get_opengraph
|
12
12
|
|
13
13
|
src = opengraph[:video_url].gsub("?autostart=1", "")
|
14
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(src)
|
14
15
|
|
15
16
|
<<-HTML
|
16
|
-
<iframe src="#{
|
17
|
+
<iframe src="#{escaped_src}"
|
17
18
|
width="#{opengraph[:video_width]}"
|
18
19
|
height="#{opengraph[:video_height]}"
|
19
20
|
scrolling="no"
|
@@ -25,7 +26,8 @@ module Onebox
|
|
25
26
|
|
26
27
|
def placeholder_html
|
27
28
|
opengraph = get_opengraph
|
28
|
-
|
29
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(opengraph[:image])
|
30
|
+
"<img src='#{escaped_src}'>"
|
29
31
|
end
|
30
32
|
|
31
33
|
end
|
@@ -13,7 +13,8 @@ module Onebox
|
|
13
13
|
|
14
14
|
def placeholder_html
|
15
15
|
return if Onebox::Helpers.blank?(oembed_data[:thumbnail_url])
|
16
|
-
|
16
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed_data[:thumbnail_url])
|
17
|
+
"<img src='#{escaped_src}' #{Helpers.title_attr(oembed_data)}>"
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
@@ -95,14 +95,14 @@ module Onebox
|
|
95
95
|
html_doc.css('meta').each do |m|
|
96
96
|
if (m["property"] && m["property"][/^og:(.+)$/i]) || (m["name"] && m["name"][/^og:(.+)$/i])
|
97
97
|
value = (m["content"] || m["value"]).to_s
|
98
|
-
og[$1.tr('-:','_').to_sym] ||=
|
98
|
+
og[$1.tr('-:','_').to_sym] ||= value unless Onebox::Helpers::blank?(value)
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
# Attempt to retrieve the title from the meta tag
|
103
103
|
title_element = html_doc.at_css('title')
|
104
104
|
if title_element && title_element.text
|
105
|
-
og[:title] ||=
|
105
|
+
og[:title] ||= title_element.text unless Onebox::Helpers.blank?(title_element.text)
|
106
106
|
end
|
107
107
|
|
108
108
|
og
|
@@ -116,7 +116,7 @@ module Onebox
|
|
116
116
|
html_doc.css('meta').each do |m|
|
117
117
|
if (m["property"] && m["property"][/^twitter:(.+)$/i]) || (m["name"] && m["name"][/^twitter:(.+)$/i])
|
118
118
|
value = (m["content"] || m["value"]).to_s
|
119
|
-
twitter[$1.tr('-:','_').to_sym] ||=
|
119
|
+
twitter[$1.tr('-:','_').to_sym] ||= value unless Onebox::Helpers::blank?(value)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
@@ -9,11 +9,12 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
og = get_opengraph
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(og[:image])
|
12
13
|
<<-HTML
|
13
14
|
<div style='width:100%; height:190px; background-color:#262626; color:#9e9e9e; margin:15px 0;'>
|
14
15
|
<div style='padding:10px'>
|
15
16
|
<h3 style='color:#fff; margin:10px 0 10px 5px;'>#{og[:title]}</h3>
|
16
|
-
<img src='
|
17
|
+
<img src='escaped_src' style='float:left; max-width:184px; margin:5px 15px 0 5px'/>
|
17
18
|
<p>#{og[:description]}</p>
|
18
19
|
</div>
|
19
20
|
</div>
|
@@ -22,9 +23,10 @@ module Onebox
|
|
22
23
|
|
23
24
|
def to_html
|
24
25
|
iframe_url = @url.gsub('/app/', '/widget/')
|
26
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(iframe_url)
|
25
27
|
|
26
28
|
<<-HTML
|
27
|
-
<iframe src='#{
|
29
|
+
<iframe src='#{escaped_src}'
|
28
30
|
frameborder='0'
|
29
31
|
width='100%'
|
30
32
|
height='190'>
|
@@ -10,8 +10,13 @@ module Onebox
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_html
|
13
|
-
|
14
|
-
|
13
|
+
escaped_url = ::Onebox::Helpers.normalize_url_for_output(@url)
|
14
|
+
<<-HTML
|
15
|
+
<video width='100%' height='100%' controls>
|
16
|
+
<source src='#{escaped_url}'>
|
17
|
+
<a href='#{escaped_url}'>#{@url}</a>
|
18
|
+
</video>
|
19
|
+
HTML
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
@@ -9,7 +9,8 @@ module Onebox
|
|
9
9
|
|
10
10
|
def placeholder_html
|
11
11
|
oembed = get_oembed
|
12
|
-
|
12
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(oembed[:thumbnail_url])
|
13
|
+
"<img src='#{escaped_src}' width='#{oembed[:thumbnail_width]}' height='#{oembed[:thumbnail_height]}' #{Helpers.title_attr(oembed)}>"
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_html
|
@@ -278,13 +278,18 @@ module Onebox
|
|
278
278
|
def image_html
|
279
279
|
return if Onebox::Helpers.blank?(data[:image])
|
280
280
|
|
281
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(data[:image])
|
282
|
+
|
281
283
|
alt = data[:description] || data[:title]
|
282
284
|
width = data[:image_width] || data[:thumbnail_width] || data[:width]
|
283
285
|
height = data[:image_height] || data[:thumbnail_height] || data[:height]
|
284
|
-
|
286
|
+
|
287
|
+
"<img src='#{escaped_src}' alt='#{alt}' width='#{width}' height='#{height}'>"
|
285
288
|
end
|
286
289
|
|
287
290
|
def video_html
|
291
|
+
escaped_src = ::Onebox::Helpers.normalize_url_for_output(data[:video])
|
292
|
+
|
288
293
|
if data[:video_type] == "video/mp4"
|
289
294
|
<<-HTML
|
290
295
|
<video title='#{data[:title]}'
|
@@ -292,12 +297,12 @@ module Onebox
|
|
292
297
|
height='#{data[:video_height]}'
|
293
298
|
style='max-width:100%'
|
294
299
|
controls=''>
|
295
|
-
<source src='#{
|
300
|
+
<source src='#{escaped_src}'>
|
296
301
|
</video>
|
297
302
|
HTML
|
298
303
|
else
|
299
304
|
<<-HTML
|
300
|
-
<iframe src='#{
|
305
|
+
<iframe src='#{escaped_src}'
|
301
306
|
title='#{data[:title]}'
|
302
307
|
width='#{data[:video_width]}'
|
303
308
|
height='#{data[:video_height]}'
|
@@ -11,28 +11,21 @@ module Onebox
|
|
11
11
|
# * http://v.youku.com/v_show/id_XMTQ5MjgyMjMyOA==.html?from=y1.3-tech-index3-232-10183.89969-89963.3-1
|
12
12
|
def video_id
|
13
13
|
match = uri.path.match(/\/v_show\/id_([a-zA-Z0-9_=\-]+)(\.html)?.*/)
|
14
|
-
|
15
|
-
|
16
|
-
nil
|
14
|
+
match && match[1]
|
17
15
|
rescue
|
18
|
-
|
16
|
+
nil
|
19
17
|
end
|
20
18
|
|
21
19
|
def to_html
|
22
|
-
"<embed width='570' height='360' src='https://players.youku.com/player.php/sid/#{video_id}/v.swf'
|
23
|
-
end
|
24
|
-
|
25
|
-
def placeholder_html
|
26
|
-
to_html
|
20
|
+
"<embed width='570' height='360' src='https://players.youku.com/player.php/sid/#{video_id}/v.swf' type='application/x-shockwave-flash'></embed>"
|
27
21
|
end
|
28
22
|
|
29
23
|
private
|
30
24
|
|
31
|
-
# Note: May throw! Make sure to rescue.
|
32
25
|
def uri
|
33
26
|
@_uri ||= URI(@url)
|
34
27
|
end
|
35
28
|
|
36
|
-
end
|
37
|
-
end
|
29
|
+
end
|
30
|
+
end
|
38
31
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Onebox
|
2
2
|
module FileTypeFinder
|
3
|
-
|
3
|
+
|
4
4
|
# In general, most of file extension names would be recognized
|
5
5
|
# by Highlights.js. However, some need to be checked in other
|
6
6
|
# ways, either because they just aren't included, because they
|
@@ -19,7 +19,7 @@ module Onebox
|
|
19
19
|
".simplecov" => "rb", # Not official, but seems commonly found
|
20
20
|
".sty" => "tex"
|
21
21
|
}
|
22
|
-
|
22
|
+
|
23
23
|
# Some extensionless files for which we know the type
|
24
24
|
# These should all be stored LOWERCASE, just for consistency.
|
25
25
|
# The ones that I know of also include the ".lock" fake extension.
|
@@ -28,7 +28,7 @@ module Onebox
|
|
28
28
|
# FIRST by their types and THEN by their names.
|
29
29
|
@extensionless_files = {
|
30
30
|
"cmake.in" => "cmake",
|
31
|
-
|
31
|
+
|
32
32
|
"gruntfile" => "js",
|
33
33
|
"gulpfile" => "js",
|
34
34
|
|
@@ -43,7 +43,7 @@ module Onebox
|
|
43
43
|
"rakefile" => "rb",
|
44
44
|
"thorfile" => "rb",
|
45
45
|
"vagrantfile" => "rb",
|
46
|
-
|
46
|
+
|
47
47
|
"boxfile" => "yaml" # Not currently (2014-11) in Highlight.js
|
48
48
|
}
|
49
49
|
|
@@ -51,7 +51,7 @@ module Onebox
|
|
51
51
|
lower_name = file_name.downcase
|
52
52
|
# First check against the known lists of "special" files and extensions.
|
53
53
|
return @extensionless_files[lower_name] if @extensionless_files.has_key?(lower_name)
|
54
|
-
|
54
|
+
|
55
55
|
@long_file_types.each { |extension,type|
|
56
56
|
return type if lower_name.end_with?(extension)
|
57
57
|
}
|
@@ -60,10 +60,10 @@ module Onebox
|
|
60
60
|
# but add one so we don't return the "." itself.
|
61
61
|
dot_spot = lower_name.rindex(".")
|
62
62
|
return lower_name[(dot_spot+1)..-1] if dot_spot
|
63
|
-
|
63
|
+
|
64
64
|
# If we couldn't figure it out from the name,
|
65
65
|
# let the highlighter figure it out from the content.
|
66
|
-
|
66
|
+
""
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
data/lib/onebox/helpers.rb
CHANGED
@@ -19,9 +19,8 @@ module Onebox
|
|
19
19
|
raise Net::HTTPError.new('HTTP redirect too deep', location) if limit == 0
|
20
20
|
|
21
21
|
uri = URI(location)
|
22
|
-
if !uri.host
|
23
|
-
|
24
|
-
end
|
22
|
+
uri = URI("#{domain}#{location}") if !uri.host
|
23
|
+
|
25
24
|
http = Net::HTTP.new(uri.host, uri.port)
|
26
25
|
http.open_timeout = Onebox.options.connect_timeout
|
27
26
|
http.read_timeout = Onebox.options.timeout
|
@@ -32,10 +31,10 @@ module Onebox
|
|
32
31
|
|
33
32
|
response = http.request_get(uri.request_uri,headers)
|
34
33
|
|
35
|
-
cookie = response.get_fields('set-cookie')
|
36
|
-
|
37
|
-
header = {'cookie' => cookie.join("")}
|
34
|
+
if cookie = response.get_fields('set-cookie')
|
35
|
+
header = { 'cookie' => cookie.join }
|
38
36
|
end
|
37
|
+
|
39
38
|
header = nil unless header.is_a? Hash
|
40
39
|
|
41
40
|
case response
|
@@ -63,15 +62,16 @@ module Onebox
|
|
63
62
|
end
|
64
63
|
|
65
64
|
def self.title_attr(meta)
|
66
|
-
(meta && !blank?(meta[:title])) ? "title='#{
|
65
|
+
(meta && !blank?(meta[:title])) ? "title='#{meta[:title]}'" : ""
|
67
66
|
end
|
68
67
|
|
69
68
|
def self.normalize_url_for_output(url)
|
69
|
+
return "" unless url
|
70
70
|
url = url.dup
|
71
71
|
# expect properly encoded url, remove any unsafe chars
|
72
72
|
url.gsub!("'", "'")
|
73
73
|
url.gsub!('"', """)
|
74
|
-
url.gsub!(/[
|
74
|
+
url.gsub!(/[^\w\-`._~:\/?#\[\]@!$&'\(\)*+,;=]/, "")
|
75
75
|
url
|
76
76
|
end
|
77
77
|
|
data/lib/onebox/layout.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Sanitize
|
2
|
+
module Config
|
3
|
+
|
4
|
+
HTTP_PROTOCOLS ||= ['http', 'https', :relative].freeze
|
5
|
+
|
6
|
+
ONEBOX ||= freeze_config merge(RELAXED,
|
7
|
+
elements: RELAXED[:elements] + %w[audio embed iframe source video],
|
8
|
+
|
9
|
+
attributes: merge(RELAXED[:attributes],
|
10
|
+
'audio' => %w[controls],
|
11
|
+
'embed' => %w[height src type width],
|
12
|
+
'iframe' => %w[allowfullscreen frameborder height scrolling src width],
|
13
|
+
'source' => %w[src type],
|
14
|
+
'video' => %w[controls height loop width],
|
15
|
+
),
|
16
|
+
|
17
|
+
protocols: merge(RELAXED[:protocols],
|
18
|
+
'embed' => { 'src' => HTTP_PROTOCOLS },
|
19
|
+
'iframe' => { 'src' => HTTP_PROTOCOLS },
|
20
|
+
'source' => { 'src' => HTTP_PROTOCOLS },
|
21
|
+
),
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
data/lib/onebox/preview.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "sanitize"
|
2
|
+
require_relative "onebox_sanitize_config"
|
3
|
+
|
1
4
|
module Onebox
|
2
5
|
class Preview
|
3
6
|
attr_reader :cache
|
@@ -11,14 +14,14 @@ module Onebox
|
|
11
14
|
|
12
15
|
def to_s
|
13
16
|
return "" unless engine
|
14
|
-
process_html
|
17
|
+
sanitize process_html engine_html
|
15
18
|
rescue *Onebox::Preview.web_exceptions
|
16
19
|
""
|
17
20
|
end
|
18
21
|
|
19
22
|
def placeholder_html
|
20
23
|
return "" unless engine
|
21
|
-
process_html
|
24
|
+
sanitize process_html engine.placeholder_html
|
22
25
|
rescue *Onebox::Preview.web_exceptions
|
23
26
|
""
|
24
27
|
end
|
@@ -62,6 +65,10 @@ module Onebox
|
|
62
65
|
html
|
63
66
|
end
|
64
67
|
|
68
|
+
def sanitize(html)
|
69
|
+
Sanitize.fragment(html, Sanitize::Config::ONEBOX)
|
70
|
+
end
|
71
|
+
|
65
72
|
def engine
|
66
73
|
return nil unless @engine_class
|
67
74
|
@engine ||= @engine_class.new(@url, cache)
|
data/lib/onebox/version.rb
CHANGED
data/onebox.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency 'moneta', '~> 0.8'
|
25
25
|
spec.add_runtime_dependency 'htmlentities', '~> 4.3.4'
|
26
26
|
spec.add_runtime_dependency 'fast_blank', '>= 1.0.0'
|
27
|
+
spec.add_runtime_dependency 'sanitize'
|
27
28
|
|
28
29
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
29
30
|
spec.add_development_dependency 'rake', '~> 10.4'
|
@@ -28,8 +28,4 @@ describe Onebox::Engine::AudioOnebox do
|
|
28
28
|
it "includes a fallback direct link to the audio" do
|
29
29
|
expect(Onebox.preview('http://kolber.github.io/audiojs/demos/mp3/juicy.mp3').to_s).to match(/<a.*mp3/)
|
30
30
|
end
|
31
|
-
|
32
|
-
it "correctly escapes single quotes" do
|
33
|
-
expect(Onebox.preview("http://test.com/test'ing.mp3").to_s).not_to match(/test'ing/)
|
34
|
-
end
|
35
31
|
end
|
@@ -36,8 +36,4 @@ describe Onebox::Engine::ImageOnebox do
|
|
36
36
|
it "includes a direct link to the image" do
|
37
37
|
expect(Onebox.preview('http://www.discourse.org/images/logo.png').to_s).to match(/<a.*png/)
|
38
38
|
end
|
39
|
-
|
40
|
-
it "doesn't inline single quotes" do
|
41
|
-
expect(Onebox.preview("http://host/path/to/Image'withquote.png").to_s).to match(/Image'withquote/)
|
42
|
-
end
|
43
39
|
end
|
@@ -18,18 +18,12 @@ describe Onebox::Engine do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
describe "#link" do
|
21
|
-
before { allow(Onebox::View).to receive(:template) { %|this
|
21
|
+
before { allow(Onebox::View).to receive(:template) { %|this should be a template| } }
|
22
22
|
|
23
23
|
it "escapes `link`" do
|
24
24
|
html = OneboxEngineExample.new(%|http://foo.com/'?a=1&b=2|).to_html
|
25
25
|
expect(html).not_to match(/&(?!amp;)(?!#39;)/)
|
26
26
|
end
|
27
|
-
|
28
|
-
it "escapes xss" do
|
29
|
-
skip 'this is checking the wrong thing'
|
30
|
-
html = OneboxEngineExample.new(%|http://foo.com/'?%20onmouseover=alert(/foo/)|).to_html
|
31
|
-
expect(html).not_to include(%|onmouseover=alert(/foo/)|)
|
32
|
-
end
|
33
27
|
end
|
34
28
|
|
35
29
|
describe "#record" do
|
@@ -82,4 +82,19 @@ describe Onebox::Preview do
|
|
82
82
|
expect(preview.send(:engine)).to be_an(Onebox::Engine)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
describe "xss" do
|
87
|
+
let(:xss) { "wat' onerror='alert(/XSS/)" }
|
88
|
+
let(:img_html) { "<img src='#{xss}'>" }
|
89
|
+
|
90
|
+
it "prevents XSS" do
|
91
|
+
preview = described_class.new(preview_url)
|
92
|
+
preview.expects(:engine_html).returns(img_html)
|
93
|
+
|
94
|
+
result = preview.to_s
|
95
|
+
expect(result).not_to match(/onerror/)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
85
100
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -26,10 +26,6 @@ shared_context "engines" do
|
|
26
26
|
let(:html) { @html }
|
27
27
|
let(:data) { @data }
|
28
28
|
let(:link) { @link }
|
29
|
-
|
30
|
-
def escaped_data(key)
|
31
|
-
CGI.escapeHTML(data[key])
|
32
|
-
end
|
33
29
|
end
|
34
30
|
|
35
31
|
shared_examples_for "an engine" do
|
@@ -64,7 +60,7 @@ shared_examples_for "a layout engine" do
|
|
64
60
|
end
|
65
61
|
|
66
62
|
it "includes title" do
|
67
|
-
expect(html).to include(
|
63
|
+
expect(html).to include(data[:title])
|
68
64
|
end
|
69
65
|
|
70
66
|
it "includes link" do
|
@@ -76,7 +72,7 @@ shared_examples_for "a layout engine" do
|
|
76
72
|
end
|
77
73
|
|
78
74
|
it "includes domain" do
|
79
|
-
expect(html).to include(%|class="domain" href="#{
|
75
|
+
expect(html).to include(%|class="domain" href="#{data[:domain]}|)
|
80
76
|
end
|
81
77
|
end
|
82
78
|
end
|
data/templates/_layout.mustache
CHANGED
data/templates/douban.mustache
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
<a href='{{
|
1
|
+
<a href='{{link}}' target="_blank"><span class='googledocs-onebox-logo g-{{type}}-logo'></span></a>
|
2
2
|
|
3
|
-
<h3><a href='{{
|
3
|
+
<h3><a href='{{link}}' target="_blank">{{title}}</a></h3>
|
4
4
|
|
5
5
|
<p>{{description}}</p>
|
data/templates/xkcd.mustache
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: onebox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joanna Zeta
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-01-
|
13
|
+
date: 2017-01-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: multi_json
|
@@ -96,6 +96,20 @@ dependencies:
|
|
96
96
|
- - ">="
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: 1.0.0
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: sanitize
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :runtime
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
99
113
|
- !ruby/object:Gem::Dependency
|
100
114
|
name: bundler
|
101
115
|
requirement: !ruby/object:Gem::Requirement
|
@@ -361,6 +375,7 @@ files:
|
|
361
375
|
- lib/onebox/layout.rb
|
362
376
|
- lib/onebox/layout_support.rb
|
363
377
|
- lib/onebox/matcher.rb
|
378
|
+
- lib/onebox/onebox_sanitize_config.rb
|
364
379
|
- lib/onebox/preview.rb
|
365
380
|
- lib/onebox/status_check.rb
|
366
381
|
- lib/onebox/template_support.rb
|