onebox 1.7.3 → 1.7.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|