mechanize 2.7.6 → 2.12.2
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 +5 -5
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +43 -0
- data/.github/workflows/upstream.yml +51 -0
- data/.yardopts +8 -0
- data/{CHANGELOG.rdoc → CHANGELOG.md} +221 -96
- data/EXAMPLES.rdoc +1 -24
- data/Gemfile +10 -4
- data/{LICENSE.rdoc → LICENSE.txt} +4 -0
- data/README.md +77 -0
- data/Rakefile +18 -3
- data/examples/latest_user_agents.rb +100 -0
- data/examples/rubygems.rb +2 -2
- data/examples/wikipedia_links_to_philosophy.rb +5 -6
- data/lib/mechanize/chunked_termination_error.rb +1 -0
- data/lib/mechanize/content_type_error.rb +1 -0
- data/lib/mechanize/cookie.rb +3 -15
- data/lib/mechanize/cookie_jar.rb +13 -9
- data/lib/mechanize/directory_saver.rb +1 -0
- data/lib/mechanize/download.rb +2 -1
- data/lib/mechanize/element_matcher.rb +1 -0
- data/lib/mechanize/element_not_found_error.rb +1 -0
- data/lib/mechanize/file.rb +2 -1
- data/lib/mechanize/file_connection.rb +5 -3
- data/lib/mechanize/file_request.rb +1 -0
- data/lib/mechanize/file_response.rb +4 -1
- data/lib/mechanize/file_saver.rb +1 -0
- data/lib/mechanize/form/button.rb +1 -0
- data/lib/mechanize/form/check_box.rb +1 -0
- data/lib/mechanize/form/field.rb +1 -0
- data/lib/mechanize/form/file_upload.rb +1 -0
- data/lib/mechanize/form/hidden.rb +1 -0
- data/lib/mechanize/form/image_button.rb +1 -0
- data/lib/mechanize/form/keygen.rb +1 -0
- data/lib/mechanize/form/multi_select_list.rb +2 -1
- data/lib/mechanize/form/option.rb +1 -0
- data/lib/mechanize/form/radio_button.rb +1 -0
- data/lib/mechanize/form/reset.rb +1 -0
- data/lib/mechanize/form/select_list.rb +1 -0
- data/lib/mechanize/form/submit.rb +1 -0
- data/lib/mechanize/form/text.rb +1 -0
- data/lib/mechanize/form/textarea.rb +1 -0
- data/lib/mechanize/form.rb +5 -13
- data/lib/mechanize/headers.rb +1 -0
- data/lib/mechanize/history.rb +1 -0
- data/lib/mechanize/http/agent.rb +83 -10
- data/lib/mechanize/http/auth_challenge.rb +1 -0
- data/lib/mechanize/http/auth_realm.rb +1 -0
- data/lib/mechanize/http/auth_store.rb +1 -0
- data/lib/mechanize/http/content_disposition_parser.rb +15 -4
- data/lib/mechanize/http/www_authenticate_parser.rb +3 -3
- data/lib/mechanize/http.rb +1 -0
- data/lib/mechanize/image.rb +1 -0
- data/lib/mechanize/page/base.rb +1 -0
- data/lib/mechanize/page/frame.rb +1 -0
- data/lib/mechanize/page/image.rb +1 -0
- data/lib/mechanize/page/label.rb +1 -0
- data/lib/mechanize/page/link.rb +8 -1
- data/lib/mechanize/page/meta_refresh.rb +1 -0
- data/lib/mechanize/page.rb +6 -8
- data/lib/mechanize/parser.rb +1 -0
- data/lib/mechanize/pluggable_parsers.rb +2 -1
- data/lib/mechanize/prependable.rb +1 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
- data/lib/mechanize/response_code_error.rb +2 -1
- data/lib/mechanize/response_read_error.rb +1 -0
- data/lib/mechanize/robots_disallowed_error.rb +1 -0
- data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
- data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
- data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
- data/lib/mechanize/test_case/form_servlet.rb +1 -0
- data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
- data/lib/mechanize/test_case/header_servlet.rb +1 -0
- data/lib/mechanize/test_case/http_refresh_servlet.rb +1 -0
- data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +1 -0
- data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
- data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
- data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/referer_servlet.rb +1 -0
- data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
- data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
- data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
- data/lib/mechanize/test_case/robots_txt_servlet.rb +1 -0
- data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/server.rb +1 -0
- data/lib/mechanize/test_case/servlets.rb +1 -0
- data/lib/mechanize/test_case/verb_servlet.rb +5 -6
- data/lib/mechanize/test_case.rb +34 -34
- data/lib/mechanize/unauthorized_error.rb +1 -0
- data/lib/mechanize/unsupported_scheme_error.rb +1 -0
- data/lib/mechanize/util.rb +2 -1
- data/lib/mechanize/version.rb +2 -1
- data/lib/mechanize/xml_file.rb +1 -0
- data/lib/mechanize.rb +56 -37
- data/mechanize.gemspec +43 -35
- data/test/htdocs/dir with spaces/foo.html +1 -0
- data/test/htdocs/tc_links.html +1 -1
- data/test/test_mechanize.rb +21 -8
- data/test/test_mechanize_cookie.rb +38 -26
- data/test/test_mechanize_cookie_jar.rb +87 -54
- data/test/test_mechanize_directory_saver.rb +1 -0
- data/test/test_mechanize_download.rb +14 -1
- data/test/test_mechanize_element_not_found_error.rb +1 -0
- data/test/test_mechanize_file.rb +11 -0
- data/test/test_mechanize_file_connection.rb +23 -4
- data/test/test_mechanize_file_request.rb +1 -0
- data/test/test_mechanize_file_response.rb +26 -1
- data/test/test_mechanize_file_saver.rb +1 -0
- data/test/test_mechanize_form.rb +14 -1
- data/test/test_mechanize_form_check_box.rb +1 -0
- data/test/test_mechanize_form_encoding.rb +2 -1
- data/test/test_mechanize_form_field.rb +1 -0
- data/test/test_mechanize_form_file_upload.rb +1 -0
- data/test/test_mechanize_form_image_button.rb +1 -0
- data/test/test_mechanize_form_keygen.rb +2 -0
- data/test/test_mechanize_form_multi_select_list.rb +1 -0
- data/test/test_mechanize_form_option.rb +1 -0
- data/test/test_mechanize_form_radio_button.rb +1 -0
- data/test/test_mechanize_form_select_list.rb +1 -0
- data/test/test_mechanize_form_textarea.rb +1 -0
- data/test/test_mechanize_headers.rb +1 -0
- data/test/test_mechanize_history.rb +1 -0
- data/test/test_mechanize_http_agent.rb +187 -26
- data/test/test_mechanize_http_auth_challenge.rb +1 -0
- data/test/test_mechanize_http_auth_realm.rb +1 -0
- data/test/test_mechanize_http_auth_store.rb +1 -0
- data/test/test_mechanize_http_content_disposition_parser.rb +28 -0
- data/test/test_mechanize_http_www_authenticate_parser.rb +1 -0
- data/test/test_mechanize_image.rb +1 -0
- data/test/test_mechanize_link.rb +25 -0
- data/test/test_mechanize_page.rb +15 -0
- data/test/test_mechanize_page_encoding.rb +33 -5
- data/test/test_mechanize_page_frame.rb +1 -0
- data/test/test_mechanize_page_image.rb +1 -0
- data/test/test_mechanize_page_link.rb +27 -23
- data/test/test_mechanize_page_meta_refresh.rb +1 -0
- data/test/test_mechanize_parser.rb +1 -0
- data/test/test_mechanize_pluggable_parser.rb +1 -0
- data/test/test_mechanize_redirect_limit_reached_error.rb +1 -0
- data/test/test_mechanize_redirect_not_get_or_head_error.rb +1 -0
- data/test/test_mechanize_response_read_error.rb +1 -0
- data/test/test_mechanize_subclass.rb +1 -0
- data/test/test_mechanize_util.rb +4 -3
- data/test/test_mechanize_xml_file.rb +1 -0
- data/test/test_multi_select.rb +1 -0
- metadata +106 -86
- data/.travis.yml +0 -36
- data/README.rdoc +0 -77
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case'
|
|
2
3
|
|
|
3
4
|
module Enumerable
|
|
@@ -141,7 +142,7 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
141
142
|
def test_parse_date_fail
|
|
142
143
|
url = URI.parse('http://localhost/')
|
|
143
144
|
|
|
144
|
-
dates = [
|
|
145
|
+
dates = [
|
|
145
146
|
"20/06/95 21:07",
|
|
146
147
|
]
|
|
147
148
|
|
|
@@ -290,18 +291,18 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
290
291
|
end
|
|
291
292
|
|
|
292
293
|
def test_parse_valid_cookie
|
|
293
|
-
url = URI.parse('http://
|
|
294
|
+
url = URI.parse('http://rubygems.org/')
|
|
294
295
|
cookie_params = {}
|
|
295
296
|
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
|
296
297
|
cookie_params['path'] = 'path=/'
|
|
297
|
-
cookie_params['domain'] = 'domain=.
|
|
298
|
+
cookie_params['domain'] = 'domain=.rubygems.org'
|
|
298
299
|
cookie_params['httponly'] = 'HttpOnly'
|
|
299
300
|
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
|
300
301
|
|
|
301
302
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
302
|
-
|
|
303
|
+
|
|
303
304
|
cookie_params.keys.combine.each do |c|
|
|
304
|
-
cookie_text = "#{cookie_value}; "
|
|
305
|
+
cookie_text = +"#{cookie_value}; "
|
|
305
306
|
c.each_with_index do |key, idx|
|
|
306
307
|
if idx == (c.length - 1)
|
|
307
308
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -325,18 +326,18 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
325
326
|
end
|
|
326
327
|
|
|
327
328
|
def test_parse_valid_cookie_empty_value
|
|
328
|
-
url = URI.parse('http://
|
|
329
|
+
url = URI.parse('http://rubygems.org/')
|
|
329
330
|
cookie_params = {}
|
|
330
331
|
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
|
331
332
|
cookie_params['path'] = 'path=/'
|
|
332
|
-
cookie_params['domain'] = 'domain=.
|
|
333
|
+
cookie_params['domain'] = 'domain=.rubygems.org'
|
|
333
334
|
cookie_params['httponly'] = 'HttpOnly'
|
|
334
335
|
cookie_value = '12345%7D='
|
|
335
336
|
|
|
336
337
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
337
|
-
|
|
338
|
+
|
|
338
339
|
cookie_params.keys.combine.each do |c|
|
|
339
|
-
cookie_text = "#{cookie_value}; "
|
|
340
|
+
cookie_text = +"#{cookie_value}; "
|
|
340
341
|
c.each_with_index do |key, idx|
|
|
341
342
|
if idx == (c.length - 1)
|
|
342
343
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -361,19 +362,19 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
361
362
|
|
|
362
363
|
# If no path was given, use the one from the URL
|
|
363
364
|
def test_cookie_using_url_path
|
|
364
|
-
url = URI.parse('http://
|
|
365
|
+
url = URI.parse('http://rubygems.org/login.php')
|
|
365
366
|
cookie_params = {}
|
|
366
367
|
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
|
367
368
|
cookie_params['path'] = 'path=/'
|
|
368
|
-
cookie_params['domain'] = 'domain=.
|
|
369
|
+
cookie_params['domain'] = 'domain=.rubygems.org'
|
|
369
370
|
cookie_params['httponly'] = 'HttpOnly'
|
|
370
371
|
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
|
371
372
|
|
|
372
373
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
373
|
-
|
|
374
|
+
|
|
374
375
|
cookie_params.keys.combine.each do |c|
|
|
375
376
|
next if c.find { |k| k == 'path' }
|
|
376
|
-
cookie_text = "#{cookie_value}; "
|
|
377
|
+
cookie_text = +"#{cookie_value}; "
|
|
377
378
|
c.each_with_index do |key, idx|
|
|
378
379
|
if idx == (c.length - 1)
|
|
379
380
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -398,19 +399,19 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
398
399
|
|
|
399
400
|
# Test using secure cookies
|
|
400
401
|
def test_cookie_with_secure
|
|
401
|
-
url = URI.parse('http://
|
|
402
|
+
url = URI.parse('http://rubygems.org/')
|
|
402
403
|
cookie_params = {}
|
|
403
404
|
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
|
404
405
|
cookie_params['path'] = 'path=/'
|
|
405
|
-
cookie_params['domain'] = 'domain=.
|
|
406
|
+
cookie_params['domain'] = 'domain=.rubygems.org'
|
|
406
407
|
cookie_params['secure'] = 'secure'
|
|
407
408
|
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
|
408
409
|
|
|
409
410
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
410
|
-
|
|
411
|
+
|
|
411
412
|
cookie_params.keys.combine.each do |c|
|
|
412
413
|
next unless c.find { |k| k == 'secure' }
|
|
413
|
-
cookie_text = "#{cookie_value}; "
|
|
414
|
+
cookie_text = +"#{cookie_value}; "
|
|
414
415
|
c.each_with_index do |key, idx|
|
|
415
416
|
if idx == (c.length - 1)
|
|
416
417
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -435,18 +436,18 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
435
436
|
end
|
|
436
437
|
|
|
437
438
|
def test_parse_cookie_no_spaces
|
|
438
|
-
url = URI.parse('http://
|
|
439
|
+
url = URI.parse('http://rubygems.org/')
|
|
439
440
|
cookie_params = {}
|
|
440
441
|
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
|
441
442
|
cookie_params['path'] = 'path=/'
|
|
442
|
-
cookie_params['domain'] = 'domain=.
|
|
443
|
+
cookie_params['domain'] = 'domain=.rubygems.org'
|
|
443
444
|
cookie_params['httponly'] = 'HttpOnly'
|
|
444
445
|
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
|
445
446
|
|
|
446
447
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
447
|
-
|
|
448
|
+
|
|
448
449
|
cookie_params.keys.combine.each do |c|
|
|
449
|
-
cookie_text = "#{cookie_value};"
|
|
450
|
+
cookie_text = +"#{cookie_value};"
|
|
450
451
|
c.each_with_index do |key, idx|
|
|
451
452
|
if idx == (c.length - 1)
|
|
452
453
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -502,24 +503,35 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
502
503
|
cookie.domain = 'Dom.example.com'
|
|
503
504
|
assert 'dom.example.com', cookie.domain
|
|
504
505
|
|
|
505
|
-
|
|
506
|
+
new_domain = Object.new.tap { |o|
|
|
506
507
|
def o.to_str
|
|
507
508
|
'Example.com'
|
|
508
509
|
end
|
|
509
510
|
}
|
|
511
|
+
cookie.domain = new_domain
|
|
510
512
|
assert 'example.com', cookie.domain
|
|
513
|
+
|
|
514
|
+
new_domain = Object.new.tap { |o|
|
|
515
|
+
def o.to_str
|
|
516
|
+
'Example2.com'
|
|
517
|
+
end
|
|
518
|
+
}
|
|
519
|
+
assert_output nil, /The call of Mechanize::Cookie#set_domain/ do
|
|
520
|
+
cookie.set_domain(new_domain)
|
|
521
|
+
end
|
|
522
|
+
assert 'example2.com', cookie.domain
|
|
511
523
|
end
|
|
512
524
|
|
|
513
525
|
def test_cookie_httponly
|
|
514
|
-
url = URI.parse('http://
|
|
526
|
+
url = URI.parse('http://rubygems.org/')
|
|
515
527
|
cookie_params = {}
|
|
516
528
|
cookie_params['httponly'] = 'HttpOnly'
|
|
517
529
|
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
|
518
530
|
|
|
519
531
|
expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
|
|
520
|
-
|
|
532
|
+
|
|
521
533
|
cookie_params.keys.combine.each do |c|
|
|
522
|
-
cookie_text = "#{cookie_value}; "
|
|
534
|
+
cookie_text = +"#{cookie_value}; "
|
|
523
535
|
c.each_with_index do |key, idx|
|
|
524
536
|
if idx == (c.length - 1)
|
|
525
537
|
cookie_text << "#{cookie_params[key]}"
|
|
@@ -532,7 +544,7 @@ class TestMechanizeCookie < Mechanize::TestCase
|
|
|
532
544
|
|
|
533
545
|
assert_equal(true, cookie.httponly)
|
|
534
546
|
|
|
535
|
-
|
|
547
|
+
|
|
536
548
|
# if expires was set, make sure we parsed it
|
|
537
549
|
if c.find { |k| k == 'expires' }
|
|
538
550
|
assert_equal(expires, cookie.expires)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case'
|
|
3
|
+
require 'fileutils'
|
|
2
4
|
|
|
3
5
|
class TestMechanizeCookieJar < Mechanize::TestCase
|
|
4
6
|
|
|
@@ -39,23 +41,23 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
39
41
|
:path => '/',
|
|
40
42
|
:expires => Time.now + (10 * 86400),
|
|
41
43
|
:for_domain => true,
|
|
42
|
-
:domain => '
|
|
44
|
+
:domain => 'rubygems.org'
|
|
43
45
|
}.merge(options)
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def test_two_cookies_same_domain_and_name_different_paths
|
|
47
|
-
url = URI 'http://
|
|
49
|
+
url = URI 'http://rubygems.org/'
|
|
48
50
|
|
|
49
51
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
50
52
|
@jar.add(url, cookie)
|
|
51
53
|
@jar.add(url, Mechanize::Cookie.new(cookie_values(:path => '/onetwo')))
|
|
52
54
|
|
|
53
55
|
assert_equal(1, @jar.cookies(url).length)
|
|
54
|
-
assert_equal 2, @jar.cookies(URI('http://
|
|
56
|
+
assert_equal 2, @jar.cookies(URI('http://rubygems.org/onetwo')).length
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
def test_domain_case
|
|
58
|
-
url = URI 'http://
|
|
60
|
+
url = URI 'http://rubygems.org/'
|
|
59
61
|
|
|
60
62
|
# Add one cookie with an expiration date in the future
|
|
61
63
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -63,49 +65,49 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
63
65
|
assert_equal(1, @jar.cookies(url).length)
|
|
64
66
|
|
|
65
67
|
@jar.add(url, Mechanize::Cookie.new(
|
|
66
|
-
cookie_values(:domain => '
|
|
68
|
+
cookie_values(:domain => 'rubygems.Org', :name => 'aaron')))
|
|
67
69
|
|
|
68
70
|
assert_equal(2, @jar.cookies(url).length)
|
|
69
71
|
|
|
70
|
-
url2 = URI 'http://
|
|
72
|
+
url2 = URI 'http://rubygems.oRg/'
|
|
71
73
|
assert_equal(2, @jar.cookies(url2).length)
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def test_host_only
|
|
75
|
-
url = URI.parse('http://
|
|
77
|
+
url = URI.parse('http://rubygems.org/')
|
|
76
78
|
|
|
77
79
|
@jar.add(url, Mechanize::Cookie.new(
|
|
78
|
-
cookie_values(:domain => '
|
|
80
|
+
cookie_values(:domain => 'rubygems.org', :for_domain => false)))
|
|
79
81
|
|
|
80
82
|
assert_equal(1, @jar.cookies(url).length)
|
|
81
83
|
|
|
82
|
-
assert_equal(1, @jar.cookies(URI('http://
|
|
84
|
+
assert_equal(1, @jar.cookies(URI('http://rubygems.org/')).length)
|
|
83
85
|
|
|
84
|
-
assert_equal(1, @jar.cookies(URI('https://
|
|
86
|
+
assert_equal(1, @jar.cookies(URI('https://rubygems.org/')).length)
|
|
85
87
|
|
|
86
|
-
assert_equal(0, @jar.cookies(URI('http://www.
|
|
88
|
+
assert_equal(0, @jar.cookies(URI('http://www.rubygems.org/')).length)
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
def test_empty_value
|
|
90
92
|
values = cookie_values(:value => "")
|
|
91
|
-
url = URI 'http://
|
|
93
|
+
url = URI 'http://rubygems.org/'
|
|
92
94
|
|
|
93
95
|
# Add one cookie with an expiration date in the future
|
|
94
96
|
cookie = Mechanize::Cookie.new(values)
|
|
95
97
|
@jar.add(url, cookie)
|
|
96
98
|
assert_equal(1, @jar.cookies(url).length)
|
|
97
99
|
|
|
98
|
-
@jar.add url, Mechanize::Cookie.new(values.merge(:domain => '
|
|
100
|
+
@jar.add url, Mechanize::Cookie.new(values.merge(:domain => 'rubygems.Org',
|
|
99
101
|
:name => 'aaron'))
|
|
100
102
|
|
|
101
103
|
assert_equal(2, @jar.cookies(url).length)
|
|
102
104
|
|
|
103
|
-
url2 = URI 'http://
|
|
105
|
+
url2 = URI 'http://rubygems.oRg/'
|
|
104
106
|
assert_equal(2, @jar.cookies(url2).length)
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
def test_add_future_cookies
|
|
108
|
-
url = URI 'http://
|
|
110
|
+
url = URI 'http://rubygems.org/'
|
|
109
111
|
|
|
110
112
|
# Add one cookie with an expiration date in the future
|
|
111
113
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -117,14 +119,14 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
117
119
|
assert_equal(1, @jar.cookies(url).length)
|
|
118
120
|
|
|
119
121
|
# Make sure we can get the cookie from different paths
|
|
120
|
-
assert_equal(1, @jar.cookies(URI('http://
|
|
122
|
+
assert_equal(1, @jar.cookies(URI('http://rubygems.org/login')).length)
|
|
121
123
|
|
|
122
124
|
# Make sure we can't get the cookie from different domains
|
|
123
125
|
assert_equal(0, @jar.cookies(URI('http://google.com/')).length)
|
|
124
126
|
end
|
|
125
127
|
|
|
126
128
|
def test_add_multiple_cookies
|
|
127
|
-
url = URI 'http://
|
|
129
|
+
url = URI 'http://rubygems.org/'
|
|
128
130
|
|
|
129
131
|
# Add one cookie with an expiration date in the future
|
|
130
132
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -136,14 +138,14 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
136
138
|
assert_equal(2, @jar.cookies(url).length)
|
|
137
139
|
|
|
138
140
|
# Make sure we can get the cookie from different paths
|
|
139
|
-
assert_equal(2, @jar.cookies(URI('http://
|
|
141
|
+
assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
|
|
140
142
|
|
|
141
143
|
# Make sure we can't get the cookie from different domains
|
|
142
144
|
assert_equal(0, @jar.cookies(URI('http://google.com/')).length)
|
|
143
145
|
end
|
|
144
146
|
|
|
145
147
|
def test_add_rejects_cookies_that_do_not_contain_an_embedded_dot
|
|
146
|
-
url = URI 'http://
|
|
148
|
+
url = URI 'http://rubygems.org/'
|
|
147
149
|
|
|
148
150
|
tld_cookie = Mechanize::Cookie.new(cookie_values(:domain => '.org'))
|
|
149
151
|
@jar.add(url, tld_cookie)
|
|
@@ -196,43 +198,43 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
196
198
|
end
|
|
197
199
|
|
|
198
200
|
def test_cookie_without_leading_dot_does_not_cause_substring_match
|
|
199
|
-
url = URI 'http://
|
|
201
|
+
url = URI 'http://arubygems.org/'
|
|
200
202
|
|
|
201
|
-
cookie = Mechanize::Cookie.new(cookie_values(:domain => '
|
|
203
|
+
cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubygems.org'))
|
|
202
204
|
@jar.add(url, cookie)
|
|
203
205
|
|
|
204
206
|
assert_equal(0, @jar.cookies(url).length)
|
|
205
207
|
end
|
|
206
208
|
|
|
207
209
|
def test_cookie_without_leading_dot_matches_subdomains
|
|
208
|
-
url = URI 'http://admin.
|
|
210
|
+
url = URI 'http://admin.rubygems.org/'
|
|
209
211
|
|
|
210
|
-
cookie = Mechanize::Cookie.new(cookie_values(:domain => '
|
|
212
|
+
cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubygems.org'))
|
|
211
213
|
@jar.add(url, cookie)
|
|
212
214
|
|
|
213
215
|
assert_equal(1, @jar.cookies(url).length)
|
|
214
216
|
end
|
|
215
217
|
|
|
216
218
|
def test_cookies_with_leading_dot_match_subdomains
|
|
217
|
-
url = URI 'http://admin.
|
|
219
|
+
url = URI 'http://admin.rubygems.org/'
|
|
218
220
|
|
|
219
|
-
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.
|
|
221
|
+
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
|
|
220
222
|
|
|
221
223
|
assert_equal(1, @jar.cookies(url).length)
|
|
222
224
|
end
|
|
223
225
|
|
|
224
226
|
def test_cookies_with_leading_dot_match_parent_domains
|
|
225
|
-
url = URI 'http://
|
|
227
|
+
url = URI 'http://rubygems.org/'
|
|
226
228
|
|
|
227
|
-
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.
|
|
229
|
+
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
|
|
228
230
|
|
|
229
231
|
assert_equal(1, @jar.cookies(url).length)
|
|
230
232
|
end
|
|
231
233
|
|
|
232
234
|
def test_cookies_with_leading_dot_match_parent_domains_exactly
|
|
233
|
-
url = URI 'http://
|
|
235
|
+
url = URI 'http://arubygems.org/'
|
|
234
236
|
|
|
235
|
-
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.
|
|
237
|
+
@jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
|
|
236
238
|
|
|
237
239
|
assert_equal(0, @jar.cookies(url).length)
|
|
238
240
|
end
|
|
@@ -275,7 +277,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
275
277
|
end
|
|
276
278
|
|
|
277
279
|
def test_clear_bang
|
|
278
|
-
url = URI 'http://
|
|
280
|
+
url = URI 'http://rubygems.org/'
|
|
279
281
|
|
|
280
282
|
# Add one cookie with an expiration date in the future
|
|
281
283
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -289,7 +291,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
289
291
|
end
|
|
290
292
|
|
|
291
293
|
def test_save_cookies_yaml
|
|
292
|
-
url = URI 'http://
|
|
294
|
+
url = URI 'http://rubygems.org/'
|
|
293
295
|
|
|
294
296
|
# Add one cookie with an expiration date in the future
|
|
295
297
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -315,7 +317,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
315
317
|
end
|
|
316
318
|
|
|
317
319
|
def test_save_session_cookies_yaml
|
|
318
|
-
url = URI 'http://
|
|
320
|
+
url = URI 'http://rubygems.org/'
|
|
319
321
|
|
|
320
322
|
# Add one cookie with an expiration date in the future
|
|
321
323
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -341,7 +343,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
341
343
|
|
|
342
344
|
|
|
343
345
|
def test_save_cookies_cookiestxt
|
|
344
|
-
url = URI 'http://
|
|
346
|
+
url = URI 'http://rubygems.org/'
|
|
345
347
|
|
|
346
348
|
# Add one cookie with an expiration date in the future
|
|
347
349
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -378,7 +380,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
378
380
|
end
|
|
379
381
|
|
|
380
382
|
def test_expire_cookies
|
|
381
|
-
url = URI 'http://
|
|
383
|
+
url = URI 'http://rubygems.org/'
|
|
382
384
|
|
|
383
385
|
# Add one cookie with an expiration date in the future
|
|
384
386
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -390,7 +392,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
390
392
|
assert_equal(2, @jar.cookies(url).length)
|
|
391
393
|
|
|
392
394
|
# Make sure we can get the cookie from different paths
|
|
393
|
-
assert_equal(2, @jar.cookies(URI('http://
|
|
395
|
+
assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
|
|
394
396
|
|
|
395
397
|
# Expire the first cookie
|
|
396
398
|
@jar.add(url, Mechanize::Cookie.new(
|
|
@@ -405,7 +407,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
405
407
|
|
|
406
408
|
def test_session_cookies
|
|
407
409
|
values = cookie_values(:expires => nil)
|
|
408
|
-
url = URI 'http://
|
|
410
|
+
url = URI 'http://rubygems.org/'
|
|
409
411
|
|
|
410
412
|
# Add one cookie with an expiration date in the future
|
|
411
413
|
cookie = Mechanize::Cookie.new(values)
|
|
@@ -417,7 +419,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
417
419
|
assert_equal(2, @jar.cookies(url).length)
|
|
418
420
|
|
|
419
421
|
# Make sure we can get the cookie from different paths
|
|
420
|
-
assert_equal(2, @jar.cookies(URI('http://
|
|
422
|
+
assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
|
|
421
423
|
|
|
422
424
|
# Expire the first cookie
|
|
423
425
|
@jar.add(url, Mechanize::Cookie.new(values.merge(:expires => Time.now - (10 * 86400))))
|
|
@@ -430,7 +432,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
430
432
|
|
|
431
433
|
# When given a URI with a blank path, CookieJar#cookies should return
|
|
432
434
|
# cookies with the path '/':
|
|
433
|
-
url = URI 'http://
|
|
435
|
+
url = URI 'http://rubygems.org'
|
|
434
436
|
assert_equal '', url.path
|
|
435
437
|
assert_equal(0, @jar.cookies(url).length)
|
|
436
438
|
# Now add a cookie with the path set to '/':
|
|
@@ -441,7 +443,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
441
443
|
|
|
442
444
|
def test_paths
|
|
443
445
|
values = cookie_values(:path => "/login", :expires => nil)
|
|
444
|
-
url = URI 'http://
|
|
446
|
+
url = URI 'http://rubygems.org/login'
|
|
445
447
|
|
|
446
448
|
# Add one cookie with an expiration date in the future
|
|
447
449
|
cookie = Mechanize::Cookie.new(values)
|
|
@@ -453,8 +455,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
453
455
|
assert_equal(2, @jar.cookies(url).length)
|
|
454
456
|
|
|
455
457
|
# Make sure we don't get the cookie in a different path
|
|
456
|
-
assert_equal(0, @jar.cookies(URI('http://
|
|
457
|
-
assert_equal(0, @jar.cookies(URI('http://
|
|
458
|
+
assert_equal(0, @jar.cookies(URI('http://rubygems.org/hello')).length)
|
|
459
|
+
assert_equal(0, @jar.cookies(URI('http://rubygems.org/')).length)
|
|
458
460
|
|
|
459
461
|
# Expire the first cookie
|
|
460
462
|
@jar.add(url, Mechanize::Cookie.new(values.merge( :expires => Time.now - (10 * 86400))))
|
|
@@ -467,7 +469,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
467
469
|
end
|
|
468
470
|
|
|
469
471
|
def test_save_and_read_cookiestxt
|
|
470
|
-
url = URI 'http://
|
|
472
|
+
url = URI 'http://rubygems.org/'
|
|
471
473
|
|
|
472
474
|
# Add one cookie with an expiration date in the future
|
|
473
475
|
cookie = Mechanize::Cookie.new(cookie_values)
|
|
@@ -486,7 +488,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
486
488
|
end
|
|
487
489
|
|
|
488
490
|
def test_save_and_read_cookiestxt_with_session_cookies
|
|
489
|
-
url = URI 'http://
|
|
491
|
+
url = URI 'http://rubygems.org/'
|
|
490
492
|
|
|
491
493
|
@jar.add(url, Mechanize::Cookie.new(cookie_values(:expires => nil)))
|
|
492
494
|
|
|
@@ -500,22 +502,53 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
500
502
|
assert_equal(0, @jar.cookies(url).length)
|
|
501
503
|
end
|
|
502
504
|
|
|
505
|
+
def test_prevent_command_injection_when_saving
|
|
506
|
+
skip if windows?
|
|
507
|
+
url = URI 'http://rubygems.org/'
|
|
508
|
+
path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
|
|
509
|
+
|
|
510
|
+
@jar.add(url, Mechanize::Cookie.new(cookie_values))
|
|
511
|
+
|
|
512
|
+
in_tmpdir do
|
|
513
|
+
@jar.save_as(path, :cookiestxt)
|
|
514
|
+
assert_equal(false, File.exist?('vul.txt'))
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
def test_prevent_command_injection_when_loading
|
|
519
|
+
skip if windows?
|
|
520
|
+
url = URI 'http://rubygems.org/'
|
|
521
|
+
path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
|
|
522
|
+
|
|
523
|
+
@jar.add(url, Mechanize::Cookie.new(cookie_values))
|
|
524
|
+
|
|
525
|
+
in_tmpdir do
|
|
526
|
+
@jar.save_as("cookies.txt", :cookiestxt)
|
|
527
|
+
@jar.clear!
|
|
528
|
+
|
|
529
|
+
assert_raises Errno::ENOENT do
|
|
530
|
+
@jar.load(path, :cookiestxt)
|
|
531
|
+
end
|
|
532
|
+
assert_equal(false, File.exist?('vul.txt'))
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
503
536
|
def test_save_and_read_expired_cookies
|
|
504
|
-
url = URI 'http://
|
|
537
|
+
url = URI 'http://rubygems.org/'
|
|
505
538
|
|
|
506
|
-
@jar.jar['
|
|
539
|
+
@jar.jar['rubygems.org'] = {}
|
|
507
540
|
|
|
508
541
|
|
|
509
542
|
@jar.add url, Mechanize::Cookie.new(cookie_values)
|
|
510
543
|
|
|
511
|
-
# HACK no
|
|
544
|
+
# HACK no assertion
|
|
512
545
|
end
|
|
513
546
|
|
|
514
547
|
def test_ssl_cookies
|
|
515
548
|
# thanks to michal "ocher" ochman for reporting the bug responsible for this test.
|
|
516
549
|
values = cookie_values(:expires => nil)
|
|
517
550
|
values_ssl = values.merge(:name => 'Baz', :domain => "#{values[:domain]}:443")
|
|
518
|
-
url = URI 'https://
|
|
551
|
+
url = URI 'https://rubygems.org/login'
|
|
519
552
|
|
|
520
553
|
cookie = Mechanize::Cookie.new(values)
|
|
521
554
|
@jar.add(url, cookie)
|
|
@@ -527,8 +560,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
527
560
|
end
|
|
528
561
|
|
|
529
562
|
def test_secure_cookie
|
|
530
|
-
nurl = URI 'http://
|
|
531
|
-
surl = URI 'https://
|
|
563
|
+
nurl = URI 'http://rubygems.org/login'
|
|
564
|
+
surl = URI 'https://rubygems.org/login'
|
|
532
565
|
|
|
533
566
|
ncookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo1'))
|
|
534
567
|
scookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo2', :secure => true))
|
|
@@ -543,10 +576,10 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
543
576
|
end
|
|
544
577
|
|
|
545
578
|
def test_save_cookies_cookiestxt_subdomain
|
|
546
|
-
top_url = URI 'http://
|
|
547
|
-
subdomain_url = URI 'http://admin.
|
|
579
|
+
top_url = URI 'http://rubygems.org/'
|
|
580
|
+
subdomain_url = URI 'http://admin.rubygems.org/'
|
|
548
581
|
|
|
549
|
-
# cookie1 is for *.
|
|
582
|
+
# cookie1 is for *.rubygems.org; cookie2 is only for rubygems.org, no subdomains
|
|
550
583
|
cookie1 = Mechanize::Cookie.new(cookie_values)
|
|
551
584
|
cookie2 = Mechanize::Cookie.new(cookie_values(:name => 'Boo', :for_domain => false))
|
|
552
585
|
|
|
@@ -572,8 +605,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
|
|
|
572
605
|
# * Cookies that match subdomains may have a leading dot, and must have
|
|
573
606
|
# TRUE as the second field.
|
|
574
607
|
cookies_txt = File.readlines("cookies.txt")
|
|
575
|
-
assert_equal(1, cookies_txt.grep( /^
|
|
576
|
-
assert_equal(1, cookies_txt.grep( /^\.
|
|
608
|
+
assert_equal(1, cookies_txt.grep( /^rubygems\.org\tFALSE/ ).length)
|
|
609
|
+
assert_equal(1, cookies_txt.grep( /^\.rubygems\.org\tTRUE/ ).length)
|
|
577
610
|
end
|
|
578
611
|
|
|
579
612
|
assert_equal(2, @jar.cookies(top_url).length)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case'
|
|
2
3
|
|
|
3
4
|
class TestMechanizeDownload < Mechanize::TestCase
|
|
@@ -46,6 +47,19 @@ class TestMechanizeDownload < Mechanize::TestCase
|
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
50
|
+
def test_save_bang_does_not_allow_command_injection
|
|
51
|
+
skip if windows?
|
|
52
|
+
uri = URI.parse 'http://example/foo.html'
|
|
53
|
+
body_io = StringIO.new '0123456789'
|
|
54
|
+
|
|
55
|
+
download = @parser.new uri, nil, body_io
|
|
56
|
+
|
|
57
|
+
in_tmpdir do
|
|
58
|
+
download.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
|
|
59
|
+
refute_operator(File, :exist?, "vul.txt")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
49
63
|
def test_save_tempfile
|
|
50
64
|
uri = URI.parse 'http://example/foo.html'
|
|
51
65
|
Tempfile.open @NAME do |body_io|
|
|
@@ -84,6 +98,5 @@ class TestMechanizeDownload < Mechanize::TestCase
|
|
|
84
98
|
|
|
85
99
|
assert_equal "foo.html", download.filename
|
|
86
100
|
end
|
|
87
|
-
|
|
88
101
|
end
|
|
89
102
|
|
data/test/test_mechanize_file.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case'
|
|
2
3
|
|
|
3
4
|
class TestMechanizeFile < Mechanize::TestCase
|
|
@@ -103,5 +104,15 @@ class TestMechanizeFile < Mechanize::TestCase
|
|
|
103
104
|
end
|
|
104
105
|
end
|
|
105
106
|
|
|
107
|
+
def test_save_bang_does_not_allow_command_injection
|
|
108
|
+
skip if windows?
|
|
109
|
+
uri = URI 'http://example/test.html'
|
|
110
|
+
page = Mechanize::File.new uri, nil, ''
|
|
111
|
+
|
|
112
|
+
in_tmpdir do
|
|
113
|
+
page.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
|
|
114
|
+
refute_operator(File, :exist?, "vul.txt")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
106
117
|
end
|
|
107
118
|
|
|
@@ -1,21 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case'
|
|
2
3
|
|
|
3
4
|
class TestMechanizeFileConnection < Mechanize::TestCase
|
|
4
5
|
|
|
5
6
|
def test_request
|
|
6
|
-
|
|
7
|
+
file_path = File.expand_path(__FILE__)
|
|
8
|
+
uri = URI.parse "file://#{file_path}"
|
|
7
9
|
conn = Mechanize::FileConnection.new
|
|
8
10
|
|
|
9
|
-
body = ''
|
|
11
|
+
body = +''
|
|
10
12
|
|
|
11
13
|
conn.request uri, nil do |response|
|
|
14
|
+
assert_equal(file_path, response.file_path)
|
|
12
15
|
response.read_body do |part|
|
|
13
16
|
body << part
|
|
14
17
|
end
|
|
15
18
|
end
|
|
16
19
|
|
|
17
|
-
assert_equal File.read(__FILE__), body
|
|
20
|
+
assert_equal File.read(__FILE__), body.gsub(/\r\n/, "\n")
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
def test_request_on_uri_with_windows_drive
|
|
24
|
+
uri_string = "file://C:/path/to/file.html"
|
|
25
|
+
expected_file_path = "C:/path/to/file.html"
|
|
26
|
+
|
|
27
|
+
uri = URI.parse(uri_string)
|
|
28
|
+
conn = Mechanize::FileConnection.new
|
|
21
29
|
|
|
30
|
+
called = false
|
|
31
|
+
yielded_file_path = nil
|
|
32
|
+
conn.request(uri, nil) do |response|
|
|
33
|
+
called = true
|
|
34
|
+
yielded_file_path = response.file_path
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
assert(called)
|
|
38
|
+
assert_equal(expected_file_path, yielded_file_path)
|
|
39
|
+
end
|
|
40
|
+
end
|