ficon 0.5 → 0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9f5f2c6b36b5360a88f4eac14c07c96f7fefb9674fb6bed0bdf4a7be63ad2d0
4
- data.tar.gz: f85066461f2384ed8e2ed3d302e5e3ffe537178dfaf40c128e056dd16c1e3027
3
+ metadata.gz: 95a5b1a8dba294c92d13f898bde371078e1927d67cb9e4af351608647f916d2f
4
+ data.tar.gz: 06f32b6dc310b8c7ea7dba49672f2ae85a8f1eaac890938414d27b031bf0808c
5
5
  SHA512:
6
- metadata.gz: 7ac7f80ea66b97249dccbfcdd4c7adf82b741125c23dbd92339346fb63e772bcfcea893279cca1b05b100946d567ee4c82bdfc9ba85dcd4fd10c881bef987ae9
7
- data.tar.gz: 8c4421c19189b779f19aca1699521e600c25f4a17807dc22a546913a28e0d230263642d8610ef68f81d548f66be4cff1654dc9a12a644319c281432555428b4e
6
+ metadata.gz: bf4e5662d4b7322e559dd116524453025cd23d76407395c6da71ed7d15e8c8298f87ac97009c5ab52b551bfed6f1cc3bc61ba5f730e026340b09c9faef355161
7
+ data.tar.gz: df182b513fe144fca1d6a5eb6d5a2e58c4d92b69df063ce6df08a0567d7e7a83d9cef0c34a464778723f664e3650f95aee49b13814f1913133912ab81f83cc12
data/lib/ficon/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Ficon
2
- VERSION = "0.5"
2
+ VERSION = "0.6"
3
3
  end
data/lib/ficon.rb CHANGED
@@ -203,6 +203,27 @@ class Ficon
203
203
  end
204
204
  rescue => e
205
205
  @url_status = classify_exception_status(e)
206
+
207
+ # If HTTP request failed and we're using HTTP, try HTTPS automatically
208
+ if uri.scheme == "http" &&
209
+ !uri.to_s.include?("://localhost") &&
210
+ !uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
211
+ puts "HTTP request failed, trying HTTPS for #{uri}"
212
+ https_uri = uri.dup
213
+ https_uri.scheme = "https"
214
+ https_uri.port = 443 if https_uri.port == 80
215
+
216
+ begin
217
+ https_response = fetch_url(https_uri, redirect_limit)
218
+ if https_response
219
+ puts "HTTPS request succeeded, using HTTPS URL"
220
+ return https_response
221
+ end
222
+ rescue => https_error
223
+ puts "HTTPS fallback also failed: #{https_error.inspect}"
224
+ end
225
+ end
226
+
206
227
  puts "Failed to fetch #{uri}: #{e.inspect}"
207
228
  nil
208
229
  end
data/test/ficon_test.rb CHANGED
@@ -1,93 +1,92 @@
1
- #require 'rubygems'
2
- require 'debug'
3
- require 'resolv'
1
+ # require 'rubygems'
2
+ require "debug"
3
+ require "resolv"
4
4
 
5
5
  require "minitest/autorun"
6
6
 
7
7
  PathHere = File.dirname(__FILE__)
8
8
  $LOAD_PATH.unshift File.join(PathHere, "..", "lib")
9
9
 
10
- require 'ficon'
11
-
12
- SiteTests = []
13
- SiteTests << { html: %Q{<meta name="msapplication-TileImage" content="https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"/> }, value: 'https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png' }
14
- SiteTests << { html: %Q{<link rel="shortcut icon" type="image/ico" href="https://s.yimg.com/pw/favicon.ico"> }, value: 'https://s.yimg.com/pw/favicon.ico' }
15
- SiteTests << { html: %Q{<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">}, value: 'https://site.com/apple-touch-icon.png' }
16
- SiteTests << { html: %Q{<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png' }
17
- SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/57.png' }
18
- SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/114.png' }
19
- SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/72.png' }
20
- SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/144.png' }
21
- SiteTests << { html: %Q{<link rel="shortcut icon" href="/favicon.png">}, value: 'https://site.com/favicon.png' }
22
- SiteTests << { html: %Q{<link rel="shortcut icon" href="favicon.ico" />}, value: 'https://site.com/favicon.ico' }
23
- SiteTests << { html: %Q{<link rel="apple-touch-icon" href="/apple-touch-icon.png">}, value: 'https://site.com/apple-touch-icon.png' }
24
- SiteTests << { html: %Q{<link rel="shortcut icon" href="http://example.com/myicon.ico" />}, value: 'http://example.com/myicon.ico'}
25
- SiteTests << { html: %Q{<link rel="icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
26
- SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
27
- SiteTests << { html: %Q{<link rel="icon" type="image/png" href="http://example.com/image.png" />}, value: 'http://example.com/image.png' }
28
- SiteTests << { html: %Q{<link rel="icon" type="image/gif" href="http://example.com/image.gif" />}, value: 'http://example.com/image.gif' }
29
- SiteTests << { html: %Q{<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>}, value: 'http://example.com/image.ico' }
30
- SiteTests << { html: %Q{<link rel="shortcut icon" href="https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico" />}, value: 'https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico' }
31
- SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
32
- SiteTests << { html: %Q{<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
33
- SiteTests << { html: %Q{<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>}, value: 'https://site.com/win8-tile-144.png' }
34
-
35
- PageTests = []
36
- PageTests << { html: %Q{<meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" />}, value: 'https://www.facebook.com/images/fb_icon_325x325.png' }
10
+ require "ficon"
37
11
 
12
+ SiteTests = []
13
+ SiteTests << {html: %(<meta name="msapplication-TileImage" content="https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"/> ), value: "https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"}
14
+ SiteTests << {html: %(<link rel="shortcut icon" type="image/ico" href="https://s.yimg.com/pw/favicon.ico"> ), value: "https://s.yimg.com/pw/favicon.ico"}
15
+ SiteTests << {html: %(<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">), value: "https://site.com/apple-touch-icon.png"}
16
+ SiteTests << {html: %(<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png"}
17
+ SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/57.png"}
18
+ SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/114.png"}
19
+ SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/72.png"}
20
+ SiteTests << {html: %(<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">), value: "https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/144.png"}
21
+ SiteTests << {html: %(<link rel="shortcut icon" href="/favicon.png">), value: "https://site.com/favicon.png"}
22
+ SiteTests << {html: %(<link rel="shortcut icon" href="favicon.ico" />), value: "https://site.com/favicon.ico"}
23
+ SiteTests << {html: %(<link rel="apple-touch-icon" href="/apple-touch-icon.png">), value: "https://site.com/apple-touch-icon.png"}
24
+ SiteTests << {html: %(<link rel="shortcut icon" href="http://example.com/myicon.ico" />), value: "http://example.com/myicon.ico"}
25
+ SiteTests << {html: %(<link rel="icon" href="http://example.com/image.ico" />), value: "http://example.com/image.ico"}
26
+ SiteTests << {html: %(<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />), value: "http://example.com/image.ico"}
27
+ SiteTests << {html: %(<link rel="icon" type="image/png" href="http://example.com/image.png" />), value: "http://example.com/image.png"}
28
+ SiteTests << {html: %(<link rel="icon" type="image/gif" href="http://example.com/image.gif" />), value: "http://example.com/image.gif"}
29
+ SiteTests << {html: %(<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>), value: "http://example.com/image.ico"}
30
+ SiteTests << {html: %(<link rel="shortcut icon" href="https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico" />), value: "https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico"}
31
+ SiteTests << {html: %(<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />), value: "https://site.com/viconline/img/favicon.ico?1393375504"}
32
+ SiteTests << {html: %(<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />), value: "https://site.com/viconline/img/favicon.ico?1393375504"}
33
+ SiteTests << {html: %(<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>), value: "https://site.com/win8-tile-144.png"}
34
+
35
+ PageTests = []
36
+ PageTests << {html: %(<meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" />), value: "https://www.facebook.com/images/fb_icon_325x325.png"}
38
37
 
39
38
  class FiconTest < Minitest::Test
40
- ENV['FICON_DB']=File.join( File.dirname(__FILE__), 'test.db')
39
+ ENV["FICON_DB"] = File.join(File.dirname(__FILE__), "test.db")
41
40
  def test_html_chunks
42
41
  SiteTests.each do |t|
43
- result = Ficon.site_images('https://site.com', Nokogiri::HTML(t[:html]) )[0]
44
- assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
42
+ result = Ficon.site_images("https://site.com", Nokogiri::HTML(t[:html]))[0]
43
+ assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
45
44
  end
46
45
  PageTests.each do |t|
47
- result = Ficon.page_images('https://site.com', Nokogiri::HTML(t[:html]) )[0]
48
- assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
46
+ result = Ficon.page_images("https://site.com", Nokogiri::HTML(t[:html]))[0]
47
+ assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
49
48
  end
50
49
  end
51
50
 
52
51
  def test_tile_color_extraction
53
- html = %Q{<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>}
54
- result = Ficon.site_images('https://site.com', Nokogiri::HTML(html))[0]
55
- assert_equal 'https://site.com/win8-tile-144.png', result.url
56
- assert_equal '#00aced', result.tile_color
52
+ html = %(<meta name="msapplication-TileImage" content="/win8-tile-144.png"/><meta name="msapplication-TileColor" content="#00aced"/>)
53
+ result = Ficon.site_images("https://site.com", Nokogiri::HTML(html))[0]
54
+ assert_equal "https://site.com/win8-tile-144.png", result.url
55
+ assert_equal "#00aced", result.tile_color
57
56
  end
58
57
 
59
58
  def test_custom_user_agent
60
59
  # Test default user agent
61
- ficon_default = Ficon.new('https://example.com')
60
+ ficon_default = Ficon.new("https://example.com")
62
61
  assert_match(/^FiconBot\/0\.\d+/, ficon_default.user_agent)
63
-
62
+
64
63
  # Test custom user agent
65
- custom_agent = 'MyApp/1.0 (Custom Bot)'
66
- ficon_custom = Ficon.new('https://example.com', user_agent: custom_agent)
64
+ custom_agent = "MyApp/1.0 (Custom Bot)"
65
+ ficon_custom = Ficon.new("https://example.com", user_agent: custom_agent)
67
66
  assert_equal custom_agent, ficon_custom.user_agent
68
-
67
+
69
68
  # Test user agent can be changed after initialization
70
- ficon_custom.user_agent = 'Changed/2.0'
71
- assert_equal 'Changed/2.0', ficon_custom.user_agent
69
+ ficon_custom.user_agent = "Changed/2.0"
70
+ assert_equal "Changed/2.0", ficon_custom.user_agent
72
71
  end
73
72
 
74
73
  def test_response_status_classification
75
- ficon = Ficon.new('https://example.com')
76
-
74
+ ficon = Ficon.new("https://example.com")
75
+
77
76
  # Test ALIVE status (2xx)
78
77
  assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(200))
79
78
  assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(201))
80
79
  assert_equal Ficon::ALIVE, ficon.classify_response_status(mock_response(299))
81
-
80
+
82
81
  # Test DEAD status (404, 410)
83
82
  assert_equal Ficon::DEAD, ficon.classify_response_status(mock_response(404))
84
83
  assert_equal Ficon::DEAD, ficon.classify_response_status(mock_response(410))
85
-
84
+
86
85
  # Test BLOCKED status (401, 403, 429)
87
86
  assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(401))
88
87
  assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(403))
89
88
  assert_equal Ficon::BLOCKED, ficon.classify_response_status(mock_response(429))
90
-
89
+
91
90
  # Test SICK status (5xx and others)
92
91
  assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(500))
93
92
  assert_equal Ficon::SICK, ficon.classify_response_status(mock_response(502))
@@ -96,22 +95,79 @@ class FiconTest < Minitest::Test
96
95
  end
97
96
 
98
97
  def test_exception_status_classification
99
- ficon = Ficon.new('https://example.com')
100
-
98
+ ficon = Ficon.new("https://example.com")
99
+
101
100
  # Test DEAD status (DNS and resolution errors)
102
101
  assert_equal Ficon::DEAD, ficon.classify_exception_status(SocketError.new)
103
102
  assert_equal Ficon::DEAD, ficon.classify_exception_status(Resolv::ResolvError.new)
104
-
103
+
105
104
  # Test SICK status (network and timeout errors)
106
105
  assert_equal Ficon::SICK, ficon.classify_exception_status(Timeout::Error.new)
107
106
  assert_equal Ficon::SICK, ficon.classify_exception_status(Errno::ECONNREFUSED.new)
108
107
  assert_equal Ficon::SICK, ficon.classify_exception_status(OpenSSL::SSL::SSLError.new)
109
- assert_equal Ficon::SICK, ficon.classify_exception_status(Net::HTTPError.new('error', nil))
110
-
108
+ assert_equal Ficon::SICK, ficon.classify_exception_status(Net::HTTPError.new("error", nil))
109
+
111
110
  # Test default to SICK for unknown exceptions
112
111
  assert_equal Ficon::SICK, ficon.classify_exception_status(StandardError.new)
113
112
  end
114
113
 
114
+ def test_http_to_https_fallback_conditions
115
+ # Test that localhost URLs are not converted to HTTPS
116
+ ficon_localhost = Ficon.allocate
117
+ uri_localhost = URI("http://localhost:3000/test")
118
+
119
+ # Mock the fetch_url method to simulate HTTP failure
120
+ def ficon_localhost.fetch_url(uri, redirect_limit = 5)
121
+ if uri.scheme == "http" && !uri.to_s.include?("://localhost") && !uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
122
+ # This should not be reached for localhost
123
+ raise "Should not attempt HTTPS fallback for localhost"
124
+ end
125
+ nil
126
+ end
127
+
128
+ # This should not raise an exception
129
+ result = ficon_localhost.send(:fetch_url, uri_localhost)
130
+ assert_nil result
131
+
132
+ # Test that IP addresses are not converted to HTTPS
133
+ ficon_ip = Ficon.allocate
134
+ uri_ip = URI("http://192.168.1.1/test")
135
+
136
+ def ficon_ip.fetch_url(uri, redirect_limit = 5)
137
+ if uri.scheme == "http" && !uri.to_s.include?("://localhost") && !uri.host.match?(/^\d+\.\d+\.\d+\.\d+$/)
138
+ # This should not be reached for IP addresses
139
+ raise "Should not attempt HTTPS fallback for IP addresses"
140
+ end
141
+ nil
142
+ end
143
+
144
+ # This should not raise an exception
145
+ result = ficon_ip.send(:fetch_url, uri_ip)
146
+ assert_nil result
147
+ end
148
+
149
+ def test_https_port_conversion
150
+ # Test that port 80 is converted to 443 when switching to HTTPS
151
+ http_uri = URI("http://example.com:80/test")
152
+ assert_equal 80, http_uri.port
153
+
154
+ https_uri = http_uri.dup
155
+ https_uri.scheme = "https"
156
+ https_uri.port = 443 if https_uri.port == 80
157
+
158
+ assert_equal "https", https_uri.scheme
159
+ assert_equal 443, https_uri.port
160
+
161
+ # Test that custom ports are preserved
162
+ http_custom_uri = URI("http://example.com:8080/test")
163
+ https_custom_uri = http_custom_uri.dup
164
+ https_custom_uri.scheme = "https"
165
+ https_custom_uri.port = 443 if https_custom_uri.port == 80
166
+
167
+ assert_equal "https", https_custom_uri.scheme
168
+ assert_equal 8080, https_custom_uri.port # Should remain unchanged
169
+ end
170
+
115
171
  private
116
172
 
117
173
  def mock_response(code)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ficon
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: '0.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Milne