favicon_party 0.7.4 → 0.7.5
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/favicon_party.rb +2 -2
- data/lib/favicon_party/fetcher.rb +13 -9
- data/lib/favicon_party/http_client.rb +1 -1
- data/lib/favicon_party/image.rb +11 -9
- data/lib/favicon_party/utils.rb +6 -2
- data/lib/favicon_party/version.rb +1 -1
- data/test/fetcher_test.rb +9 -3
- data/test/fixtures/favicons/specimens/a_jpeg.jpg +0 -0
- data/test/fixtures/favicons/specimens/not_actually_transparent.png +0 -0
- data/test/fixtures/http_headers/wevorce.com.txt +35 -0
- data/test/image_test.rb +22 -16
- data/test/test_helper.rb +6 -0
- data/test/utils_test.rb +14 -10
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c61876eea35371d7d84d0346af3f1a1c4093914
|
|
4
|
+
data.tar.gz: 4b67af13faf4e76cfc051540dcf03c2e72f3d3d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 295085e97b4d77f279f5e7cd12c0f23b52bc7dbe03219256fb4a8002bfe555b501a25ff472f110624708d429462a3443dc346ea80935360c34622bfe255b2548
|
|
7
|
+
data.tar.gz: c92b657ea171abcbab0bbb3b886d34b157bf193bfa6ac16a749194c0ebf0623823280556c156cbb9520d72f4620b98d3175bfcfd4f5380e0f559907255b3d84c
|
data/lib/favicon_party.rb
CHANGED
|
@@ -19,6 +19,7 @@ module FaviconParty
|
|
|
19
19
|
attr_accessor :query_url, :final_url, :favicon_url, :candidate_urls, :html, :data
|
|
20
20
|
|
|
21
21
|
def initialize(url, options = {})
|
|
22
|
+
@options = options
|
|
22
23
|
@query_url = prefix_url(url)
|
|
23
24
|
@final_url = nil
|
|
24
25
|
@favicon_url = nil
|
|
@@ -50,7 +51,7 @@ module FaviconParty
|
|
|
50
51
|
@candidate_urls.each do |url|
|
|
51
52
|
data = FaviconParty::Image.new(get_favicon_data_from_url(url))
|
|
52
53
|
begin
|
|
53
|
-
if data.valid?
|
|
54
|
+
if data.valid?(@options)
|
|
54
55
|
@favicon_url = url
|
|
55
56
|
return data
|
|
56
57
|
end
|
|
@@ -88,7 +89,7 @@ module FaviconParty
|
|
|
88
89
|
href = URI.join(url_root, href).to_s rescue nil
|
|
89
90
|
end
|
|
90
91
|
href
|
|
91
|
-
end.compact
|
|
92
|
+
end.compact.uniq
|
|
92
93
|
end
|
|
93
94
|
|
|
94
95
|
def set_candidate_favicon_urls
|
|
@@ -97,20 +98,23 @@ module FaviconParty
|
|
|
97
98
|
@candidate_urls << URI.join(url_root, "favicon.png").to_s
|
|
98
99
|
end
|
|
99
100
|
|
|
101
|
+
def final_location(response_headers)
|
|
102
|
+
location = response_headers.scan(/^Location: (.*)$/)[-1]
|
|
103
|
+
location && location[0].strip
|
|
104
|
+
end
|
|
105
|
+
|
|
100
106
|
# Follow redirects from the query url to get to the last url
|
|
101
107
|
#
|
|
102
108
|
def final_url
|
|
103
109
|
return @final_url if !@final_url.nil?
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if final =~ /\Ahttp/
|
|
109
|
-
@final_url = URI.encode final
|
|
110
|
+
location = final_location(FaviconParty::HTTPClient.head(@query_url))
|
|
111
|
+
if !location.nil?
|
|
112
|
+
if location =~ /\Ahttp/
|
|
113
|
+
@final_url = URI.encode location
|
|
110
114
|
else
|
|
111
115
|
uri = URI @query_url
|
|
112
116
|
root = "#{uri.scheme}://#{uri.host}"
|
|
113
|
-
@final_url = URI.encode URI.join(root,
|
|
117
|
+
@final_url = URI.encode URI.join(root, location).to_s
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
120
|
if !@final_url.nil?
|
data/lib/favicon_party/image.rb
CHANGED
|
@@ -57,20 +57,22 @@ module FaviconParty
|
|
|
57
57
|
|
|
58
58
|
# Does the data look like a valid favicon?
|
|
59
59
|
#
|
|
60
|
-
def valid?
|
|
60
|
+
def valid?(options = {})
|
|
61
61
|
@error =
|
|
62
62
|
if blank?
|
|
63
63
|
"source_data is blank"
|
|
64
|
-
elsif size_too_big?
|
|
65
|
-
"source_data file size too big"
|
|
66
64
|
elsif !valid_mime_type?
|
|
67
65
|
"source_data mime-type is invalid - #{mime_type}"
|
|
68
|
-
elsif transparent?
|
|
69
|
-
"source_data is a transparent image"
|
|
70
66
|
elsif one_pixel?
|
|
71
67
|
"source_data is a 1x1 image"
|
|
72
|
-
elsif
|
|
73
|
-
"
|
|
68
|
+
elsif size_too_big?
|
|
69
|
+
"source_data file size too big"
|
|
70
|
+
elsif !options[:no_color_check]
|
|
71
|
+
if transparent?
|
|
72
|
+
"source_data is a transparent image"
|
|
73
|
+
elsif one_color?
|
|
74
|
+
"png_data is one color (or close to it)"
|
|
75
|
+
end
|
|
74
76
|
end
|
|
75
77
|
@error.nil?
|
|
76
78
|
end
|
|
@@ -95,8 +97,8 @@ module FaviconParty
|
|
|
95
97
|
|
|
96
98
|
def transparent?
|
|
97
99
|
with_temp_data_file(@source_data) do |t|
|
|
98
|
-
cmd = "convert #{t.path.to_s} -
|
|
99
|
-
imagemagick_run(cmd)
|
|
100
|
+
cmd = "convert #{t.path.to_s} -format '%[opaque]' info:"
|
|
101
|
+
imagemagick_run(cmd) != "true"
|
|
100
102
|
end
|
|
101
103
|
end
|
|
102
104
|
|
data/lib/favicon_party/utils.rb
CHANGED
|
@@ -6,8 +6,12 @@ module FaviconParty
|
|
|
6
6
|
|
|
7
7
|
module Utils
|
|
8
8
|
|
|
9
|
-
def prefix_url(url)
|
|
10
|
-
|
|
9
|
+
def prefix_url(url, options = {})
|
|
10
|
+
unless options[:downcase] == false
|
|
11
|
+
url = URI.encode url.strip.downcase
|
|
12
|
+
else
|
|
13
|
+
url = URI.encode url.strip
|
|
14
|
+
end
|
|
11
15
|
if url =~ /https?:\/\//
|
|
12
16
|
url
|
|
13
17
|
else
|
data/test/fetcher_test.rb
CHANGED
|
@@ -17,15 +17,21 @@ class FetcherTest < Minitest::Test
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def test_fetcher_finds_favicon_urls_in_html
|
|
20
|
-
html =
|
|
20
|
+
html = read_fixture("html/page1.html")
|
|
21
21
|
assert @fetcher.find_favicon_urls_in_html(html).length == 1
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def test_fetcher_decodes_base64_data_uri_links
|
|
25
|
-
|
|
26
|
-
image = FaviconParty::Image.new(
|
|
25
|
+
data = read_fixture("favicons/transparent-16x16.png", "rb")
|
|
26
|
+
image = FaviconParty::Image.new(data)
|
|
27
27
|
data_uri = "data:image/png;base64,#{image.base64_png}"
|
|
28
28
|
assert @fetcher.get_favicon_data_from_url(data_uri) == image.source_data
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def test_fetcher_finds_location_headers_in_http_response
|
|
32
|
+
@fetcher = FaviconParty::Fetcher.new("wevorce.com")
|
|
33
|
+
location = @fetcher.final_location(read_fixture("http_headers/wevorce.com.txt"))
|
|
34
|
+
assert location == "https://www.wevorce.com"
|
|
35
|
+
end
|
|
36
|
+
|
|
31
37
|
end
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
HTTP/1.1 303 See Other
|
|
2
|
+
Content-Type: text/html; charset=utf-8
|
|
3
|
+
Connection: keep-alive
|
|
4
|
+
Status: 303 See Other
|
|
5
|
+
X-Frame-Options: SAMEORIGIN
|
|
6
|
+
X-XSS-Protection: 1; mode=block
|
|
7
|
+
X-Content-Type-Options: nosniff
|
|
8
|
+
Location: https://www.wevorce.com
|
|
9
|
+
Cache-Control: no-cache
|
|
10
|
+
Set-Cookie: request_method=HEAD; path=/
|
|
11
|
+
X-Request-Id: ed843a1e-dbc3-4e2f-ae25-596e41391d4f
|
|
12
|
+
X-Runtime: 0.006208
|
|
13
|
+
X-Powered-By: Phusion Passenger 4.0.53
|
|
14
|
+
Date: Mon, 14 Dec 2015 01:21:42 GMT
|
|
15
|
+
Server: nginx/1.6.2 + Phusion Passenger 4.0.53
|
|
16
|
+
P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
|
|
17
|
+
|
|
18
|
+
HTTP/1.1 200 OK
|
|
19
|
+
Server: Cowboy
|
|
20
|
+
Connection: keep-alive
|
|
21
|
+
Date: Mon, 14 Dec 2015 01:21:42 GMT
|
|
22
|
+
Status: 200 OK
|
|
23
|
+
Strict-Transport-Security: max-age=31536000
|
|
24
|
+
Content-Type: text/html; charset=utf-8
|
|
25
|
+
Content-Length: 43979
|
|
26
|
+
X-Ua-Compatible: IE=Edge,chrome=1
|
|
27
|
+
Etag: "a3ef0ea6d0a8dad4f9e59bbf765000c5"
|
|
28
|
+
Cache-Control: max-age=0, private, must-revalidate
|
|
29
|
+
Set-Cookie: remember_token=; path=/; expires=Mon, 14-Dec-2015 02:21:42 GMT; secure
|
|
30
|
+
Set-Cookie: _wevorce_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWRmZmVjNzFjOWM2ZTM0M2Y4MWI5YTdmNzdjN2FmNjRiBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMWpuV3RsUVdNYXozNVVab21XUFBDb2VqQU1mb0hzZWx2bXhzY1BwTDZ1VDA9BjsARkkiFmFuYWx5dGljc19zdGFydGVkBjsARlQ%3D--426d95420320c7ef844c19e07f53ae02df49c050; path=/; secure; HttpOnly
|
|
31
|
+
X-Request-Id: a71f958c-7112-4c1b-981c-48c821a2ba4e
|
|
32
|
+
X-Runtime: 0.068463
|
|
33
|
+
X-Rack-Cache: miss
|
|
34
|
+
Via: 1.1 vegur
|
|
35
|
+
|
data/test/image_test.rb
CHANGED
|
@@ -13,46 +13,52 @@ class ImageTest < Minitest::Test
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def test_transparent_png_is_invalid
|
|
16
|
-
|
|
17
|
-
@image = @klass.new open(filename, "rb").read
|
|
16
|
+
@image = @klass.new read_fixture("favicons/transparent-16x16.png", "rb")
|
|
18
17
|
assert @image.mime_type == "image/png"
|
|
19
|
-
assert @image.transparent?
|
|
20
|
-
assert @image.one_color?
|
|
18
|
+
assert @image.transparent?
|
|
19
|
+
assert @image.one_color?
|
|
21
20
|
assert @image.valid? == false
|
|
22
21
|
end
|
|
23
22
|
|
|
23
|
+
def test_does_not_detect_jpeg_as_transparent
|
|
24
|
+
@image = @klass.new read_fixture("favicons/specimens/a_jpeg.jpg", "rb")
|
|
25
|
+
assert @image.mime_type == "image/jpeg"
|
|
26
|
+
assert @image.transparent? == false
|
|
27
|
+
assert @image.valid? == true
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
def test_1x1_gif_is_invalid
|
|
25
|
-
|
|
26
|
-
@image = @klass.new open(filename, "rb").read
|
|
31
|
+
@image = @klass.new read_fixture("favicons/transparent-1x1.gif", "rb")
|
|
27
32
|
assert @image.mime_type == "image/gif"
|
|
28
|
-
assert @image.
|
|
33
|
+
assert @image.transparent?
|
|
34
|
+
assert @image.one_color?
|
|
35
|
+
assert @image.one_pixel?
|
|
29
36
|
assert @image.valid? == false
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
def test_all_white_ico_is_invalid
|
|
33
|
-
|
|
34
|
-
@image = @klass.new open(filename, "rb").read
|
|
40
|
+
@image = @klass.new read_fixture("favicons/white-16x16.ico")
|
|
35
41
|
assert %w( image/x-ico image/x-icon ).include? @image.mime_type
|
|
36
|
-
assert @image.one_color?
|
|
42
|
+
assert @image.one_color?
|
|
43
|
+
assert @image.transparent? == false
|
|
37
44
|
assert @image.valid? == false
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
def test_svg_mime_type_is_valid
|
|
41
|
-
|
|
42
|
-
@image = @klass.new open(filename, "rb").read
|
|
48
|
+
@image = @klass.new read_fixture("favicons/white-16x16.svg")
|
|
43
49
|
assert @image.one_color?
|
|
50
|
+
assert @image.transparent? == false
|
|
44
51
|
assert @image.valid_mime_type?
|
|
52
|
+
assert @image.valid?(:no_color_check => true)
|
|
45
53
|
end
|
|
46
54
|
|
|
47
55
|
def test_base64_png_works
|
|
48
|
-
|
|
49
|
-
@image = @klass.new open(filename, "rb").read
|
|
56
|
+
@image = @klass.new read_fixture("favicons/white-16x16.ico")
|
|
50
57
|
assert !@image.base64_png.nil?
|
|
51
58
|
end
|
|
52
59
|
|
|
53
60
|
def test_dimensions_returns_correct_dimensions
|
|
54
|
-
|
|
55
|
-
@image = @klass.new open(filename, "rb").read
|
|
61
|
+
@image = @klass.new read_fixture("favicons/white-16x16.ico")
|
|
56
62
|
assert @image.dimensions == "16x16"
|
|
57
63
|
end
|
|
58
64
|
|
data/test/test_helper.rb
CHANGED
data/test/utils_test.rb
CHANGED
|
@@ -5,28 +5,27 @@ class UtilsTest < Minitest::Test
|
|
|
5
5
|
include FaviconParty::Utils
|
|
6
6
|
|
|
7
7
|
def test_get_mime_type_detects_png_correctly
|
|
8
|
-
|
|
9
|
-
assert get_mime_type(
|
|
8
|
+
data = read_fixture("favicons/transparent-16x16.png", "rb")
|
|
9
|
+
assert get_mime_type(data) == "image/png"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def test_get_mime_type_detects_gif_correctly
|
|
13
|
-
|
|
14
|
-
assert get_mime_type(
|
|
13
|
+
data = read_fixture("favicons/transparent-1x1.gif", "rb")
|
|
14
|
+
assert get_mime_type(data) == "image/gif"
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def test_get_mime_type_detects_ico_correctly
|
|
18
|
-
|
|
19
|
-
assert %w( image/x-ico image/x-icon ).include? get_mime_type(
|
|
18
|
+
data = read_fixture("favicons/white-16x16.ico", "rb")
|
|
19
|
+
assert %w( image/x-ico image/x-icon ).include? get_mime_type(data)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def test_get_mime_type_detects_svg_correctly
|
|
23
|
-
|
|
24
|
-
assert get_mime_type(
|
|
23
|
+
data = read_fixture("favicons/white-16x16.svg", "rb")
|
|
24
|
+
assert get_mime_type(data) == "image/svg+xml"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def test_get_mime_type_detects_html_correctly
|
|
28
|
-
|
|
29
|
-
assert get_mime_type(open(filename, "rb").read) == "text/html"
|
|
28
|
+
assert get_mime_type(read_fixture("html/page1.html")) == "text/html"
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def test_prefix_url_always_returns_prefixed_urls
|
|
@@ -34,6 +33,11 @@ class UtilsTest < Minitest::Test
|
|
|
34
33
|
assert prefix_url("http://localhost") =~ /\Ahttp:\/\//
|
|
35
34
|
end
|
|
36
35
|
|
|
36
|
+
def test_prefix_url_does_not_downcase_when_a_flag_is_set
|
|
37
|
+
assert prefix_url("localhost/tEsT", :downcase => false) =~ /\/tEsT/
|
|
38
|
+
assert prefix_url("localhost/tEsT") =~ /\/test/
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
def test_encode_utf8_returns_valid_utf8_string
|
|
38
42
|
string = "\x12\x61\xA3"
|
|
39
43
|
assert !string.valid_encoding?
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: favicon_party
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Linmiao Xu
|
|
@@ -91,12 +91,15 @@ files:
|
|
|
91
91
|
- lib/favicon_party/utils.rb
|
|
92
92
|
- lib/favicon_party/version.rb
|
|
93
93
|
- test/fetcher_test.rb
|
|
94
|
+
- test/fixtures/favicons/specimens/a_jpeg.jpg
|
|
95
|
+
- test/fixtures/favicons/specimens/not_actually_transparent.png
|
|
94
96
|
- test/fixtures/favicons/transparent-16x16.png
|
|
95
97
|
- test/fixtures/favicons/transparent-1x1.gif
|
|
96
98
|
- test/fixtures/favicons/transparent-1x1.png
|
|
97
99
|
- test/fixtures/favicons/white-16x16.ico
|
|
98
100
|
- test/fixtures/favicons/white-16x16.svg
|
|
99
101
|
- test/fixtures/html/page1.html
|
|
102
|
+
- test/fixtures/http_headers/wevorce.com.txt
|
|
100
103
|
- test/http_client_test.rb
|
|
101
104
|
- test/image_test.rb
|
|
102
105
|
- test/loader_test.rb
|