mechanize 2.7.6 → 2.7.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mechanize might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7e684f2f1ceb7fca81909282b30a28c04272caef
4
- data.tar.gz: c08ef7e0f2aefd788f9808175afb4f97bce60b3f
2
+ SHA256:
3
+ metadata.gz: feff4acdf05edc4c615ab91f9ab0b7abfd1987dbd998ed07a36489189594edf2
4
+ data.tar.gz: efce735d57a4b2259f30a630829f432f270e3aa353fb9d4f5ad032df06387e84
5
5
  SHA512:
6
- metadata.gz: fed2bde694313e6ddae6d44bbbf0ac90aa6b651ab7027628125b2095b33a73dc3fdaf8481335197ab0cf9cbea7c9dfa9396f4e3c4199cdc3563f76b20728f18c
7
- data.tar.gz: a547f0f8d1c6f8d0b7c8ff580e487b64b79fbec3cca64a514407243529248e6892f66d9af746bc6c429458750e7b5782510cb3e8180f8464f08c8c0c0c0351b9
6
+ metadata.gz: f83a08c469e67045f58f3f3685cb17618db889dd85d1b7f2e56da1c9ae7744f36815a1f811f09bd99614c529b42f2038100a64fb06cdee1569d43bb831ea3fae
7
+ data.tar.gz: c01289d967e87c40e0936c2f973847da696bc92d9255a5c5f20099ff795ce57430f45a631a02a9395cfe7066e27731ec040a879fd255468b43cf9a1b5149c3eb
@@ -0,0 +1,25 @@
1
+ name: "ci"
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ "*" ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby-version: ["2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "jruby"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true
24
+ - name: Run tests
25
+ run: bundle exec rake
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,32 @@
1
1
  = Mechanize CHANGELOG
2
2
 
3
+ === 2.7.7 / 2021-02-01
4
+
5
+ * Security fixes for CVE-2021-21289
6
+
7
+ Mechanize `>= v2.0`, `< v2.7.7` allows for OS commands to be injected into several classes'
8
+ methods via implicit use of Ruby's `Kernel.open` method. Exploitation is possible only if
9
+ untrusted input is used as a local filename and passed to any of these calls:
10
+
11
+ - `Mechanize::CookieJar#load`: since v2.0 (see 208e3ed)
12
+ - `Mechanize::CookieJar#save_as`: since v2.0 (see 5b776a4)
13
+ - `Mechanize#download`: since v2.2 (see dc91667)
14
+ - `Mechanize::Download#save` and `#save!` since v2.1 (see 98b2f51, bd62ff0)
15
+ - `Mechanize::File#save` and `#save_as`: since v2.1 (see 2bf7519)
16
+ - `Mechanize::FileResponse#read_body`: since v2.0 (see 01039f5)
17
+
18
+ See https://github.com/sparklemotion/mechanize/security/advisories/GHSA-qrqm-fpv6-6r8g for more
19
+ information.
20
+
21
+ Also see #547, #548. Thank you, @kyoshidajp!
22
+
23
+ * New Features
24
+ * Support for Ruby 3.0 by adding `webrick` as a runtime dependency. (#557) @pvalena
25
+
26
+ * Bug fix
27
+ * Ignore input fields with blank names (#542, #536)
28
+
29
+
3
30
  === 2.7.6
4
31
 
5
32
  * New Features
data/EXAMPLES.rdoc CHANGED
@@ -24,29 +24,6 @@ example, <code>do ... end.submit</code> is the same as <code>{ ...
24
24
  end
25
25
  end
26
26
 
27
- == Rubyforge
28
-
29
- require 'rubygems'
30
- require 'mechanize'
31
-
32
- a = Mechanize.new
33
- a.get('http://rubyforge.org/') do |page|
34
- # Click the login link
35
- login_page = a.click(page.link_with(:text => /Log In/))
36
-
37
- # Submit the login form
38
- my_page = login_page.form_with(:action => '/account/login.php') do |f|
39
- f.form_loginname = ARGV[0]
40
- f.form_pw = ARGV[1]
41
- end.click_button
42
-
43
- my_page.links.each do |link|
44
- text = link.text.strip
45
- next unless text.length > 0
46
- puts text
47
- end
48
- end
49
-
50
27
  == File Upload
51
28
 
52
29
  Upload a file to flickr.
@@ -129,7 +106,7 @@ This example also demonstrates subclassing Mechanize.
129
106
 
130
107
  class TestMech < Mechanize
131
108
  def process
132
- get 'http://rubyforge.org/'
109
+ get 'http://rubygems.org/'
133
110
  search_form = page.forms.first
134
111
  search_form.words = 'WWW'
135
112
  submit search_form
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # In order to be able to install on 1.9.3 and 2.0.0
4
- ruby RUBY_VERSION
3
+ gem "rake"
4
+ gem "bundler"
5
+ gem "rdoc"
6
+ gem "minitest"
5
7
 
6
8
  gemspec
data/README.rdoc CHANGED
@@ -48,7 +48,7 @@ Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de)
48
48
 
49
49
  Copyright (c) 2006-2011:
50
50
 
51
- * {Aaron Patterson}[http://tenderlovemaking.com] (aaronp@rubyforge.org)
51
+ * {Aaron Patterson}[http://tenderlovemaking.com] (aaron.patterson@gmail.com)
52
52
  * {Mike Dalessio}[http://mike.daless.io] (mike@csa.net)
53
53
 
54
54
  Copyright (c) 2011-2015:
data/examples/rubygems.rb CHANGED
@@ -1,4 +1,4 @@
1
- # This example logs a user in to rubyforge and prints out the body of the
1
+ # This example logs a user in to rubygems and prints out the body of the
2
2
  # page after logging the user in.
3
3
  require 'rubygems'
4
4
  require 'mechanize'
@@ -9,7 +9,7 @@ mech = Mechanize.new
9
9
  mech.log = Logger.new $stderr
10
10
  mech.agent.http.debug_output = $stderr
11
11
 
12
- # Load the rubyforge website
12
+ # Load the rubygems website
13
13
  page = mech.get('https://rubygems.org/')
14
14
  page = mech.click page.link_with(:text => /Sign in/) # Click the login link
15
15
  form = page.forms[1] # Select the first form
data/lib/mechanize.rb CHANGED
@@ -175,7 +175,7 @@ class Mechanize
175
175
  # as SSL parameters or proxies:
176
176
  #
177
177
  # agent = Mechanize.new do |a|
178
- # a.proxy_host = 'proxy.example'
178
+ # a.proxy_addr = 'proxy.example'
179
179
  # a.proxy_port = 8080
180
180
  # end
181
181
  #
@@ -396,7 +396,7 @@ class Mechanize
396
396
  io = if io_or_filename.respond_to? :write then
397
397
  io_or_filename
398
398
  else
399
- open io_or_filename, 'wb'
399
+ ::File.open(io_or_filename, 'wb')
400
400
  end
401
401
 
402
402
  case page
@@ -65,7 +65,7 @@ class Mechanize
65
65
  class CookieJar < ::HTTP::CookieJar
66
66
  def save(output, *options)
67
67
  output.respond_to?(:write) or
68
- return open(output, 'w') { |io| save(io, *options) }
68
+ return ::File.open(output, 'w') { |io| save(io, *options) }
69
69
 
70
70
  opthash = {
71
71
  :format => :yaml,
@@ -119,7 +119,7 @@ class Mechanize
119
119
 
120
120
  def load(input, *options)
121
121
  input.respond_to?(:write) or
122
- return open(input, 'r') { |io| load(io, *options) }
122
+ return ::File.open(input, 'r') { |io| load(io, *options) }
123
123
 
124
124
  opthash = {
125
125
  :format => :yaml,
@@ -71,7 +71,7 @@ class Mechanize::Download
71
71
  dirname = File.dirname filename
72
72
  FileUtils.mkdir_p dirname
73
73
 
74
- open filename, 'wb' do |io|
74
+ ::File.open(filename, 'wb')do |io|
75
75
  until @body_io.eof? do
76
76
  io.write @body_io.read 16384
77
77
  end
@@ -82,7 +82,7 @@ class Mechanize::File
82
82
  dirname = File.dirname filename
83
83
  FileUtils.mkdir_p dirname
84
84
 
85
- open filename, 'wb' do |f|
85
+ ::File.open(filename, 'wb')do |f|
86
86
  f.write body
87
87
  end
88
88
 
@@ -15,7 +15,7 @@ class Mechanize::FileResponse
15
15
  if directory?
16
16
  yield dir_body
17
17
  else
18
- open @file_path, 'rb' do |io|
18
+ ::File.open(@file_path, 'rb') do |io|
19
19
  yield io.read
20
20
  end
21
21
  end
@@ -305,7 +305,7 @@ class Mechanize::Form
305
305
  successful_controls = []
306
306
 
307
307
  (fields + checkboxes).reject do |f|
308
- f.node["disabled"]
308
+ f.node["disabled"] || f.node["name"] == ""
309
309
  end.sort.each do |f|
310
310
  case f
311
311
  when Mechanize::Form::CheckBox
@@ -230,9 +230,9 @@ class Net::HTTP # :nodoc:
230
230
  else
231
231
  filename = "htdocs#{path.gsub(/[^\/\\.\w\s]/, '_')}"
232
232
  unless PAGE_CACHE[filename]
233
- open("#{Mechanize::TestCase::TEST_DIR}/#{filename}", 'rb') { |io|
233
+ ::File.open("#{Mechanize::TestCase::TEST_DIR}/#{filename}", 'rb') do |io|
234
234
  PAGE_CACHE[filename] = io.read
235
- }
235
+ end
236
236
  end
237
237
 
238
238
  res.body = PAGE_CACHE[filename]
@@ -13,8 +13,8 @@ class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
13
13
  end
14
14
 
15
15
  if name = req.query['file'] then
16
- open "#{TEST_DIR}/htdocs/#{name}" do |io|
17
- string = ""
16
+ ::File.open("#{TEST_DIR}/htdocs/#{name}") do |io|
17
+ string = String.new
18
18
  zipped = StringIO.new string, 'w'
19
19
  Zlib::GzipWriter.wrap zipped do |gz|
20
20
  gz.write io.read
@@ -22,7 +22,7 @@ class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
22
22
  res.body = string
23
23
  end
24
24
  else
25
- res.body = ''
25
+ res.body = String.new
26
26
  end
27
27
 
28
28
  res['Content-Encoding'] = req['X-ResponseContentEncoding'] || 'gzip'
@@ -1,11 +1,9 @@
1
1
  class VerbServlet < WEBrick::HTTPServlet::AbstractServlet
2
2
  %w[HEAD GET POST PUT DELETE].each do |verb|
3
- eval <<-METHOD
4
- def do_#{verb}(req, res)
5
- res.header['X-Request-Method'] = #{verb.dump}
6
- res.body = #{verb.dump}
7
- end
8
- METHOD
3
+ define_method "do_#{verb}" do |req, res|
4
+ res.header['X-Request-Method'] = verb
5
+ res.body = verb
6
+ end
9
7
  end
10
8
  end
11
9
 
@@ -1,3 +1,3 @@
1
1
  class Mechanize
2
- VERSION = "2.7.6"
2
+ VERSION = "2.7.7"
3
3
  end
data/mechanize.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.email =
29
29
  [
30
30
  'drbrain@segment7.net',
31
- 'aaronp@rubyforge.org',
31
+ 'aaron.patterson@gmail.com',
32
32
  'mike.dalessio@gmail.com',
33
33
  'knu@idaemons.org',
34
34
  'ljjarvis@gmail.com'
@@ -58,9 +58,5 @@ Gem::Specification.new do |spec|
58
58
  spec.add_runtime_dependency "ntlm-http", [ ">= 0.1.1", "~> 0.1" ]
59
59
  spec.add_runtime_dependency "webrobots", [ "< 0.2", ">= 0.0.9" ]
60
60
  spec.add_runtime_dependency "domain_name", [ ">= 0.5.1", "~> 0.5" ]
61
-
62
- spec.add_development_dependency "rake"
63
- spec.add_development_dependency "bundler", "~> 1.3"
64
- spec.add_development_dependency "rdoc", "~> 4.0"
65
- spec.add_development_dependency "minitest", "~> 5.0"
61
+ spec.add_runtime_dependency 'webrick', "~> 1.7"
66
62
  end
@@ -7,7 +7,7 @@
7
7
  <a href="thing.html" class="thing_link">Thing!</a>
8
8
  <a href="thing.html">Ruby <b>Rocks!</b></a>
9
9
  <!-- Testing a bug with escaped stuff in links:
10
- http://rubyforge.org/pipermail/mechanize-users/2006-September/000002.html
10
+ http://rubygems.org/pipermail/mechanize-users/2006-September/000002.html
11
11
  -->
12
12
  <a href="link%20with%20space.html">encoded space</a>
13
13
  <a href="link with space.html">not encoded space</a>
@@ -345,6 +345,14 @@ but not <a href="/" rel="me nofollow">this</a>!
345
345
  end
346
346
  end
347
347
 
348
+ def test_download_does_not_allow_command_injection
349
+ in_tmpdir do
350
+ @mech.download('http://example', '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
351
+
352
+ refute_operator(File, :exist?, "vul.txt")
353
+ end
354
+ end
355
+
348
356
  def test_get
349
357
  uri = URI 'http://localhost'
350
358
 
@@ -689,9 +697,7 @@ but not <a href="/" rel="me nofollow">this</a>!
689
697
  end
690
698
 
691
699
  def test_get_space
692
- page = nil
693
-
694
- page = @mech.get("http://localhost/tc_bad_links.html ")
700
+ @mech.get("http://localhost/tc_bad_links.html ")
695
701
 
696
702
  assert_match(/tc_bad_links.html$/, @mech.history.last.uri.to_s)
697
703
 
@@ -1056,6 +1062,11 @@ but not <a href="/" rel="me nofollow">this</a>!
1056
1062
  end
1057
1063
 
1058
1064
  def test_retry_change_requests_equals
1065
+ unless Gem::Requirement.new("< 4.0.0").satisfied_by?(Gem::Version.new(Net::HTTP::Persistent::VERSION))
1066
+ # see https://github.com/drbrain/net-http-persistent/pull/100
1067
+ skip("net-http-persistent 4.0.0 and later does not support retry_change_requests")
1068
+ end
1069
+
1059
1070
  refute @mech.retry_change_requests
1060
1071
 
1061
1072
  @mech.retry_change_requests = true
@@ -141,7 +141,7 @@ class TestMechanizeCookie < Mechanize::TestCase
141
141
  def test_parse_date_fail
142
142
  url = URI.parse('http://localhost/')
143
143
 
144
- dates = [
144
+ dates = [
145
145
  "20/06/95 21:07",
146
146
  ]
147
147
 
@@ -290,16 +290,16 @@ class TestMechanizeCookie < Mechanize::TestCase
290
290
  end
291
291
 
292
292
  def test_parse_valid_cookie
293
- url = URI.parse('http://rubyforge.org/')
293
+ url = URI.parse('http://rubygems.org/')
294
294
  cookie_params = {}
295
295
  cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
296
296
  cookie_params['path'] = 'path=/'
297
- cookie_params['domain'] = 'domain=.rubyforge.org'
297
+ cookie_params['domain'] = 'domain=.rubygems.org'
298
298
  cookie_params['httponly'] = 'HttpOnly'
299
299
  cookie_value = '12345%7D=ASDFWEE345%3DASda'
300
300
 
301
301
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
302
-
302
+
303
303
  cookie_params.keys.combine.each do |c|
304
304
  cookie_text = "#{cookie_value}; "
305
305
  c.each_with_index do |key, idx|
@@ -325,16 +325,16 @@ class TestMechanizeCookie < Mechanize::TestCase
325
325
  end
326
326
 
327
327
  def test_parse_valid_cookie_empty_value
328
- url = URI.parse('http://rubyforge.org/')
328
+ url = URI.parse('http://rubygems.org/')
329
329
  cookie_params = {}
330
330
  cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
331
331
  cookie_params['path'] = 'path=/'
332
- cookie_params['domain'] = 'domain=.rubyforge.org'
332
+ cookie_params['domain'] = 'domain=.rubygems.org'
333
333
  cookie_params['httponly'] = 'HttpOnly'
334
334
  cookie_value = '12345%7D='
335
335
 
336
336
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
337
-
337
+
338
338
  cookie_params.keys.combine.each do |c|
339
339
  cookie_text = "#{cookie_value}; "
340
340
  c.each_with_index do |key, idx|
@@ -361,16 +361,16 @@ class TestMechanizeCookie < Mechanize::TestCase
361
361
 
362
362
  # If no path was given, use the one from the URL
363
363
  def test_cookie_using_url_path
364
- url = URI.parse('http://rubyforge.org/login.php')
364
+ url = URI.parse('http://rubygems.org/login.php')
365
365
  cookie_params = {}
366
366
  cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
367
367
  cookie_params['path'] = 'path=/'
368
- cookie_params['domain'] = 'domain=.rubyforge.org'
368
+ cookie_params['domain'] = 'domain=.rubygems.org'
369
369
  cookie_params['httponly'] = 'HttpOnly'
370
370
  cookie_value = '12345%7D=ASDFWEE345%3DASda'
371
371
 
372
372
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
373
-
373
+
374
374
  cookie_params.keys.combine.each do |c|
375
375
  next if c.find { |k| k == 'path' }
376
376
  cookie_text = "#{cookie_value}; "
@@ -398,16 +398,16 @@ class TestMechanizeCookie < Mechanize::TestCase
398
398
 
399
399
  # Test using secure cookies
400
400
  def test_cookie_with_secure
401
- url = URI.parse('http://rubyforge.org/')
401
+ url = URI.parse('http://rubygems.org/')
402
402
  cookie_params = {}
403
403
  cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
404
404
  cookie_params['path'] = 'path=/'
405
- cookie_params['domain'] = 'domain=.rubyforge.org'
405
+ cookie_params['domain'] = 'domain=.rubygems.org'
406
406
  cookie_params['secure'] = 'secure'
407
407
  cookie_value = '12345%7D=ASDFWEE345%3DASda'
408
408
 
409
409
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
410
-
410
+
411
411
  cookie_params.keys.combine.each do |c|
412
412
  next unless c.find { |k| k == 'secure' }
413
413
  cookie_text = "#{cookie_value}; "
@@ -435,16 +435,16 @@ class TestMechanizeCookie < Mechanize::TestCase
435
435
  end
436
436
 
437
437
  def test_parse_cookie_no_spaces
438
- url = URI.parse('http://rubyforge.org/')
438
+ url = URI.parse('http://rubygems.org/')
439
439
  cookie_params = {}
440
440
  cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
441
441
  cookie_params['path'] = 'path=/'
442
- cookie_params['domain'] = 'domain=.rubyforge.org'
442
+ cookie_params['domain'] = 'domain=.rubygems.org'
443
443
  cookie_params['httponly'] = 'HttpOnly'
444
444
  cookie_value = '12345%7D=ASDFWEE345%3DASda'
445
445
 
446
446
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
447
-
447
+
448
448
  cookie_params.keys.combine.each do |c|
449
449
  cookie_text = "#{cookie_value};"
450
450
  c.each_with_index do |key, idx|
@@ -511,13 +511,13 @@ class TestMechanizeCookie < Mechanize::TestCase
511
511
  end
512
512
 
513
513
  def test_cookie_httponly
514
- url = URI.parse('http://rubyforge.org/')
514
+ url = URI.parse('http://rubygems.org/')
515
515
  cookie_params = {}
516
516
  cookie_params['httponly'] = 'HttpOnly'
517
517
  cookie_value = '12345%7D=ASDFWEE345%3DASda'
518
518
 
519
519
  expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
520
-
520
+
521
521
  cookie_params.keys.combine.each do |c|
522
522
  cookie_text = "#{cookie_value}; "
523
523
  c.each_with_index do |key, idx|
@@ -532,7 +532,7 @@ class TestMechanizeCookie < Mechanize::TestCase
532
532
 
533
533
  assert_equal(true, cookie.httponly)
534
534
 
535
-
535
+
536
536
  # if expires was set, make sure we parsed it
537
537
  if c.find { |k| k == 'expires' }
538
538
  assert_equal(expires, cookie.expires)
@@ -1,4 +1,5 @@
1
1
  require 'mechanize/test_case'
2
+ require 'fileutils'
2
3
 
3
4
  class TestMechanizeCookieJar < Mechanize::TestCase
4
5
 
@@ -39,23 +40,23 @@ class TestMechanizeCookieJar < Mechanize::TestCase
39
40
  :path => '/',
40
41
  :expires => Time.now + (10 * 86400),
41
42
  :for_domain => true,
42
- :domain => 'rubyforge.org'
43
+ :domain => 'rubygems.org'
43
44
  }.merge(options)
44
45
  end
45
46
 
46
47
  def test_two_cookies_same_domain_and_name_different_paths
47
- url = URI 'http://rubyforge.org/'
48
+ url = URI 'http://rubygems.org/'
48
49
 
49
50
  cookie = Mechanize::Cookie.new(cookie_values)
50
51
  @jar.add(url, cookie)
51
52
  @jar.add(url, Mechanize::Cookie.new(cookie_values(:path => '/onetwo')))
52
53
 
53
54
  assert_equal(1, @jar.cookies(url).length)
54
- assert_equal 2, @jar.cookies(URI('http://rubyforge.org/onetwo')).length
55
+ assert_equal 2, @jar.cookies(URI('http://rubygems.org/onetwo')).length
55
56
  end
56
57
 
57
58
  def test_domain_case
58
- url = URI 'http://rubyforge.org/'
59
+ url = URI 'http://rubygems.org/'
59
60
 
60
61
  # Add one cookie with an expiration date in the future
61
62
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -63,49 +64,49 @@ class TestMechanizeCookieJar < Mechanize::TestCase
63
64
  assert_equal(1, @jar.cookies(url).length)
64
65
 
65
66
  @jar.add(url, Mechanize::Cookie.new(
66
- cookie_values(:domain => 'RuByForge.Org', :name => 'aaron')))
67
+ cookie_values(:domain => 'rubygems.Org', :name => 'aaron')))
67
68
 
68
69
  assert_equal(2, @jar.cookies(url).length)
69
70
 
70
- url2 = URI 'http://RuByFoRgE.oRg/'
71
+ url2 = URI 'http://rubygems.oRg/'
71
72
  assert_equal(2, @jar.cookies(url2).length)
72
73
  end
73
74
 
74
75
  def test_host_only
75
- url = URI.parse('http://rubyforge.org/')
76
+ url = URI.parse('http://rubygems.org/')
76
77
 
77
78
  @jar.add(url, Mechanize::Cookie.new(
78
- cookie_values(:domain => 'rubyforge.org', :for_domain => false)))
79
+ cookie_values(:domain => 'rubygems.org', :for_domain => false)))
79
80
 
80
81
  assert_equal(1, @jar.cookies(url).length)
81
82
 
82
- assert_equal(1, @jar.cookies(URI('http://RubyForge.org/')).length)
83
+ assert_equal(1, @jar.cookies(URI('http://rubygems.org/')).length)
83
84
 
84
- assert_equal(1, @jar.cookies(URI('https://RubyForge.org/')).length)
85
+ assert_equal(1, @jar.cookies(URI('https://rubygems.org/')).length)
85
86
 
86
- assert_equal(0, @jar.cookies(URI('http://www.rubyforge.org/')).length)
87
+ assert_equal(0, @jar.cookies(URI('http://www.rubygems.org/')).length)
87
88
  end
88
89
 
89
90
  def test_empty_value
90
91
  values = cookie_values(:value => "")
91
- url = URI 'http://rubyforge.org/'
92
+ url = URI 'http://rubygems.org/'
92
93
 
93
94
  # Add one cookie with an expiration date in the future
94
95
  cookie = Mechanize::Cookie.new(values)
95
96
  @jar.add(url, cookie)
96
97
  assert_equal(1, @jar.cookies(url).length)
97
98
 
98
- @jar.add url, Mechanize::Cookie.new(values.merge(:domain => 'RuByForge.Org',
99
+ @jar.add url, Mechanize::Cookie.new(values.merge(:domain => 'rubygems.Org',
99
100
  :name => 'aaron'))
100
101
 
101
102
  assert_equal(2, @jar.cookies(url).length)
102
103
 
103
- url2 = URI 'http://RuByFoRgE.oRg/'
104
+ url2 = URI 'http://rubygems.oRg/'
104
105
  assert_equal(2, @jar.cookies(url2).length)
105
106
  end
106
107
 
107
108
  def test_add_future_cookies
108
- url = URI 'http://rubyforge.org/'
109
+ url = URI 'http://rubygems.org/'
109
110
 
110
111
  # Add one cookie with an expiration date in the future
111
112
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -117,14 +118,14 @@ class TestMechanizeCookieJar < Mechanize::TestCase
117
118
  assert_equal(1, @jar.cookies(url).length)
118
119
 
119
120
  # Make sure we can get the cookie from different paths
120
- assert_equal(1, @jar.cookies(URI('http://rubyforge.org/login')).length)
121
+ assert_equal(1, @jar.cookies(URI('http://rubygems.org/login')).length)
121
122
 
122
123
  # Make sure we can't get the cookie from different domains
123
124
  assert_equal(0, @jar.cookies(URI('http://google.com/')).length)
124
125
  end
125
126
 
126
127
  def test_add_multiple_cookies
127
- url = URI 'http://rubyforge.org/'
128
+ url = URI 'http://rubygems.org/'
128
129
 
129
130
  # Add one cookie with an expiration date in the future
130
131
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -136,14 +137,14 @@ class TestMechanizeCookieJar < Mechanize::TestCase
136
137
  assert_equal(2, @jar.cookies(url).length)
137
138
 
138
139
  # Make sure we can get the cookie from different paths
139
- assert_equal(2, @jar.cookies(URI('http://rubyforge.org/login')).length)
140
+ assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
140
141
 
141
142
  # Make sure we can't get the cookie from different domains
142
143
  assert_equal(0, @jar.cookies(URI('http://google.com/')).length)
143
144
  end
144
145
 
145
146
  def test_add_rejects_cookies_that_do_not_contain_an_embedded_dot
146
- url = URI 'http://rubyforge.org/'
147
+ url = URI 'http://rubygems.org/'
147
148
 
148
149
  tld_cookie = Mechanize::Cookie.new(cookie_values(:domain => '.org'))
149
150
  @jar.add(url, tld_cookie)
@@ -196,43 +197,43 @@ class TestMechanizeCookieJar < Mechanize::TestCase
196
197
  end
197
198
 
198
199
  def test_cookie_without_leading_dot_does_not_cause_substring_match
199
- url = URI 'http://arubyforge.org/'
200
+ url = URI 'http://arubygems.org/'
200
201
 
201
- cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubyforge.org'))
202
+ cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubygems.org'))
202
203
  @jar.add(url, cookie)
203
204
 
204
205
  assert_equal(0, @jar.cookies(url).length)
205
206
  end
206
207
 
207
208
  def test_cookie_without_leading_dot_matches_subdomains
208
- url = URI 'http://admin.rubyforge.org/'
209
+ url = URI 'http://admin.rubygems.org/'
209
210
 
210
- cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubyforge.org'))
211
+ cookie = Mechanize::Cookie.new(cookie_values(:domain => 'rubygems.org'))
211
212
  @jar.add(url, cookie)
212
213
 
213
214
  assert_equal(1, @jar.cookies(url).length)
214
215
  end
215
216
 
216
217
  def test_cookies_with_leading_dot_match_subdomains
217
- url = URI 'http://admin.rubyforge.org/'
218
+ url = URI 'http://admin.rubygems.org/'
218
219
 
219
- @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubyforge.org')))
220
+ @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
220
221
 
221
222
  assert_equal(1, @jar.cookies(url).length)
222
223
  end
223
224
 
224
225
  def test_cookies_with_leading_dot_match_parent_domains
225
- url = URI 'http://rubyforge.org/'
226
+ url = URI 'http://rubygems.org/'
226
227
 
227
- @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubyforge.org')))
228
+ @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
228
229
 
229
230
  assert_equal(1, @jar.cookies(url).length)
230
231
  end
231
232
 
232
233
  def test_cookies_with_leading_dot_match_parent_domains_exactly
233
- url = URI 'http://arubyforge.org/'
234
+ url = URI 'http://arubygems.org/'
234
235
 
235
- @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubyforge.org')))
236
+ @jar.add(url, Mechanize::Cookie.new(cookie_values(:domain => '.rubygems.org')))
236
237
 
237
238
  assert_equal(0, @jar.cookies(url).length)
238
239
  end
@@ -275,7 +276,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
275
276
  end
276
277
 
277
278
  def test_clear_bang
278
- url = URI 'http://rubyforge.org/'
279
+ url = URI 'http://rubygems.org/'
279
280
 
280
281
  # Add one cookie with an expiration date in the future
281
282
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -289,7 +290,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
289
290
  end
290
291
 
291
292
  def test_save_cookies_yaml
292
- url = URI 'http://rubyforge.org/'
293
+ url = URI 'http://rubygems.org/'
293
294
 
294
295
  # Add one cookie with an expiration date in the future
295
296
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -315,7 +316,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
315
316
  end
316
317
 
317
318
  def test_save_session_cookies_yaml
318
- url = URI 'http://rubyforge.org/'
319
+ url = URI 'http://rubygems.org/'
319
320
 
320
321
  # Add one cookie with an expiration date in the future
321
322
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -341,7 +342,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
341
342
 
342
343
 
343
344
  def test_save_cookies_cookiestxt
344
- url = URI 'http://rubyforge.org/'
345
+ url = URI 'http://rubygems.org/'
345
346
 
346
347
  # Add one cookie with an expiration date in the future
347
348
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -378,7 +379,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
378
379
  end
379
380
 
380
381
  def test_expire_cookies
381
- url = URI 'http://rubyforge.org/'
382
+ url = URI 'http://rubygems.org/'
382
383
 
383
384
  # Add one cookie with an expiration date in the future
384
385
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -390,7 +391,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
390
391
  assert_equal(2, @jar.cookies(url).length)
391
392
 
392
393
  # Make sure we can get the cookie from different paths
393
- assert_equal(2, @jar.cookies(URI('http://rubyforge.org/login')).length)
394
+ assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
394
395
 
395
396
  # Expire the first cookie
396
397
  @jar.add(url, Mechanize::Cookie.new(
@@ -405,7 +406,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
405
406
 
406
407
  def test_session_cookies
407
408
  values = cookie_values(:expires => nil)
408
- url = URI 'http://rubyforge.org/'
409
+ url = URI 'http://rubygems.org/'
409
410
 
410
411
  # Add one cookie with an expiration date in the future
411
412
  cookie = Mechanize::Cookie.new(values)
@@ -417,7 +418,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
417
418
  assert_equal(2, @jar.cookies(url).length)
418
419
 
419
420
  # Make sure we can get the cookie from different paths
420
- assert_equal(2, @jar.cookies(URI('http://rubyforge.org/login')).length)
421
+ assert_equal(2, @jar.cookies(URI('http://rubygems.org/login')).length)
421
422
 
422
423
  # Expire the first cookie
423
424
  @jar.add(url, Mechanize::Cookie.new(values.merge(:expires => Time.now - (10 * 86400))))
@@ -430,7 +431,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
430
431
 
431
432
  # When given a URI with a blank path, CookieJar#cookies should return
432
433
  # cookies with the path '/':
433
- url = URI 'http://rubyforge.org'
434
+ url = URI 'http://rubygems.org'
434
435
  assert_equal '', url.path
435
436
  assert_equal(0, @jar.cookies(url).length)
436
437
  # Now add a cookie with the path set to '/':
@@ -441,7 +442,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
441
442
 
442
443
  def test_paths
443
444
  values = cookie_values(:path => "/login", :expires => nil)
444
- url = URI 'http://rubyforge.org/login'
445
+ url = URI 'http://rubygems.org/login'
445
446
 
446
447
  # Add one cookie with an expiration date in the future
447
448
  cookie = Mechanize::Cookie.new(values)
@@ -453,8 +454,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
453
454
  assert_equal(2, @jar.cookies(url).length)
454
455
 
455
456
  # Make sure we don't get the cookie in a different path
456
- assert_equal(0, @jar.cookies(URI('http://rubyforge.org/hello')).length)
457
- assert_equal(0, @jar.cookies(URI('http://rubyforge.org/')).length)
457
+ assert_equal(0, @jar.cookies(URI('http://rubygems.org/hello')).length)
458
+ assert_equal(0, @jar.cookies(URI('http://rubygems.org/')).length)
458
459
 
459
460
  # Expire the first cookie
460
461
  @jar.add(url, Mechanize::Cookie.new(values.merge( :expires => Time.now - (10 * 86400))))
@@ -467,7 +468,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
467
468
  end
468
469
 
469
470
  def test_save_and_read_cookiestxt
470
- url = URI 'http://rubyforge.org/'
471
+ url = URI 'http://rubygems.org/'
471
472
 
472
473
  # Add one cookie with an expiration date in the future
473
474
  cookie = Mechanize::Cookie.new(cookie_values)
@@ -486,7 +487,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
486
487
  end
487
488
 
488
489
  def test_save_and_read_cookiestxt_with_session_cookies
489
- url = URI 'http://rubyforge.org/'
490
+ url = URI 'http://rubygems.org/'
490
491
 
491
492
  @jar.add(url, Mechanize::Cookie.new(cookie_values(:expires => nil)))
492
493
 
@@ -500,10 +501,39 @@ class TestMechanizeCookieJar < Mechanize::TestCase
500
501
  assert_equal(0, @jar.cookies(url).length)
501
502
  end
502
503
 
504
+ def test_prevent_command_injection_when_saving
505
+ url = URI 'http://rubygems.org/'
506
+ path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
507
+
508
+ @jar.add(url, Mechanize::Cookie.new(cookie_values))
509
+
510
+ in_tmpdir do
511
+ @jar.save_as(path, :cookiestxt)
512
+ assert_equal(false, File.exist?('vul.txt'))
513
+ end
514
+ end
515
+
516
+ def test_prevent_command_injection_when_loading
517
+ url = URI 'http://rubygems.org/'
518
+ path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
519
+
520
+ @jar.add(url, Mechanize::Cookie.new(cookie_values))
521
+
522
+ in_tmpdir do
523
+ @jar.save_as("cookies.txt", :cookiestxt)
524
+ @jar.clear!
525
+
526
+ assert_raises Errno::ENOENT do
527
+ @jar.load(path, :cookiestxt)
528
+ end
529
+ assert_equal(false, File.exist?('vul.txt'))
530
+ end
531
+ end
532
+
503
533
  def test_save_and_read_expired_cookies
504
- url = URI 'http://rubyforge.org/'
534
+ url = URI 'http://rubygems.org/'
505
535
 
506
- @jar.jar['rubyforge.org'] = {}
536
+ @jar.jar['rubygems.org'] = {}
507
537
 
508
538
 
509
539
  @jar.add url, Mechanize::Cookie.new(cookie_values)
@@ -515,7 +545,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
515
545
  # thanks to michal "ocher" ochman for reporting the bug responsible for this test.
516
546
  values = cookie_values(:expires => nil)
517
547
  values_ssl = values.merge(:name => 'Baz', :domain => "#{values[:domain]}:443")
518
- url = URI 'https://rubyforge.org/login'
548
+ url = URI 'https://rubygems.org/login'
519
549
 
520
550
  cookie = Mechanize::Cookie.new(values)
521
551
  @jar.add(url, cookie)
@@ -527,8 +557,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
527
557
  end
528
558
 
529
559
  def test_secure_cookie
530
- nurl = URI 'http://rubyforge.org/login'
531
- surl = URI 'https://rubyforge.org/login'
560
+ nurl = URI 'http://rubygems.org/login'
561
+ surl = URI 'https://rubygems.org/login'
532
562
 
533
563
  ncookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo1'))
534
564
  scookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo2', :secure => true))
@@ -543,10 +573,10 @@ class TestMechanizeCookieJar < Mechanize::TestCase
543
573
  end
544
574
 
545
575
  def test_save_cookies_cookiestxt_subdomain
546
- top_url = URI 'http://rubyforge.org/'
547
- subdomain_url = URI 'http://admin.rubyforge.org/'
576
+ top_url = URI 'http://rubygems.org/'
577
+ subdomain_url = URI 'http://admin.rubygems.org/'
548
578
 
549
- # cookie1 is for *.rubyforge.org; cookie2 is only for rubyforge.org, no subdomains
579
+ # cookie1 is for *.rubygems.org; cookie2 is only for rubygems.org, no subdomains
550
580
  cookie1 = Mechanize::Cookie.new(cookie_values)
551
581
  cookie2 = Mechanize::Cookie.new(cookie_values(:name => 'Boo', :for_domain => false))
552
582
 
@@ -572,8 +602,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
572
602
  # * Cookies that match subdomains may have a leading dot, and must have
573
603
  # TRUE as the second field.
574
604
  cookies_txt = File.readlines("cookies.txt")
575
- assert_equal(1, cookies_txt.grep( /^rubyforge\.org\tFALSE/ ).length)
576
- assert_equal(1, cookies_txt.grep( /^\.rubyforge\.org\tTRUE/ ).length)
605
+ assert_equal(1, cookies_txt.grep( /^rubygems\.org\tFALSE/ ).length)
606
+ assert_equal(1, cookies_txt.grep( /^\.rubygems\.org\tTRUE/ ).length)
577
607
  end
578
608
 
579
609
  assert_equal(2, @jar.cookies(top_url).length)
@@ -46,6 +46,18 @@ class TestMechanizeDownload < Mechanize::TestCase
46
46
  end
47
47
  end
48
48
 
49
+ def test_save_bang_does_not_allow_command_injection
50
+ uri = URI.parse 'http://example/foo.html'
51
+ body_io = StringIO.new '0123456789'
52
+
53
+ download = @parser.new uri, nil, body_io
54
+
55
+ in_tmpdir do
56
+ download.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
57
+ refute_operator(File, :exist?, "vul.txt")
58
+ end
59
+ end
60
+
49
61
  def test_save_tempfile
50
62
  uri = URI.parse 'http://example/foo.html'
51
63
  Tempfile.open @NAME do |body_io|
@@ -84,6 +96,5 @@ class TestMechanizeDownload < Mechanize::TestCase
84
96
 
85
97
  assert_equal "foo.html", download.filename
86
98
  end
87
-
88
99
  end
89
100
 
@@ -103,5 +103,14 @@ class TestMechanizeFile < Mechanize::TestCase
103
103
  end
104
104
  end
105
105
 
106
+ def test_save_bang_does_not_allow_command_injection
107
+ uri = URI 'http://example/test.html'
108
+ page = Mechanize::File.new uri, nil, ''
109
+
110
+ in_tmpdir do
111
+ page.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
112
+ refute_operator(File, :exist?, "vul.txt")
113
+ end
114
+ end
106
115
  end
107
116
 
@@ -1,7 +1,6 @@
1
1
  require 'mechanize/test_case'
2
2
 
3
3
  class TestMechanizeFileResponse < Mechanize::TestCase
4
-
5
4
  def test_content_type
6
5
  Tempfile.open %w[pi .nothtml] do |tempfile|
7
6
  res = Mechanize::FileResponse.new tempfile.path
@@ -19,5 +18,24 @@ class TestMechanizeFileResponse < Mechanize::TestCase
19
18
  end
20
19
  end
21
20
 
22
- end
21
+ def test_read_body
22
+ Tempfile.open %w[pi .html] do |tempfile|
23
+ tempfile.write("asdfasdfasdf")
24
+ tempfile.close
23
25
 
26
+ res = Mechanize::FileResponse.new(tempfile.path)
27
+ res.read_body do |input|
28
+ assert_equal("asdfasdfasdf", input)
29
+ end
30
+ end
31
+ end
32
+
33
+ def test_read_body_does_not_allow_command_injection
34
+ in_tmpdir do
35
+ FileUtils.touch('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
36
+ res = Mechanize::FileResponse.new('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
37
+ res.read_body { |_| }
38
+ refute_operator(File, :exist?, "vul.txt")
39
+ end
40
+ end
41
+ end
@@ -65,6 +65,18 @@ class TestMechanizeForm < Mechanize::TestCase
65
65
  assert query.all? { |x| x[1] == '' }
66
66
  end
67
67
 
68
+ def test_build_query_blank_input_name
69
+ html = Nokogiri::HTML <<-HTML
70
+ <form>
71
+ <input type="text" name="" value="foo" />
72
+ </form>
73
+ HTML
74
+
75
+ form = Mechanize::Form.new html.at('form'), @mech, @page
76
+
77
+ assert_equal [], form.build_query
78
+ end
79
+
68
80
  def test_build_query_radio_button_duplicate
69
81
  html = Nokogiri::HTML <<-HTML
70
82
  <form>
@@ -22,6 +22,7 @@ class TestMechanizeFormKeygen < Mechanize::TestCase
22
22
  end
23
23
 
24
24
  def test_spki_signature
25
+ skip("JRuby PKI doesn't handle this for reasons I've been unable to understand") if RUBY_ENGINE=~/jruby/
25
26
  spki = OpenSSL::Netscape::SPKI.new @keygen.value
26
27
  assert_equal @keygen.challenge, spki.challenge
27
28
  assert_equal @keygen.key.public_key.to_pem, spki.public_key.to_pem
@@ -935,7 +935,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
935
935
  body_io = StringIO.new \
936
936
  "\037\213\b\0002\002\225M\000\003+H,*\001"
937
937
 
938
- return if jruby_zlib?
938
+ skip if jruby_zlib?
939
939
 
940
940
  e = assert_raises Mechanize::Error do
941
941
  @agent.response_content_encoding @res, body_io
@@ -1590,6 +1590,11 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1590
1590
  end
1591
1591
 
1592
1592
  def test_retry_change_request_equals
1593
+ unless Gem::Requirement.new("< 4.0.0").satisfied_by?(Gem::Version.new(Net::HTTP::Persistent::VERSION))
1594
+ # see https://github.com/drbrain/net-http-persistent/pull/100
1595
+ skip("net-http-persistent 4.0.0 and later does not support retry_change_requests")
1596
+ end
1597
+
1593
1598
  refute @agent.http.retry_change_requests
1594
1599
 
1595
1600
  @agent.retry_change_requests = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mechanize
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.6
4
+ version: 2.7.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Hodel
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2018-06-02 00:00:00.000000000 Z
15
+ date: 2021-02-01 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: net-http-digest_auth
@@ -151,61 +151,19 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.5'
153
153
  - !ruby/object:Gem::Dependency
154
- name: rake
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: bundler
154
+ name: webrick
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
157
  - - "~>"
172
158
  - !ruby/object:Gem::Version
173
- version: '1.3'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: '1.3'
181
- - !ruby/object:Gem::Dependency
182
- name: rdoc
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '4.0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '4.0'
195
- - !ruby/object:Gem::Dependency
196
- name: minitest
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '5.0'
202
- type: :development
159
+ version: '1.7'
160
+ type: :runtime
203
161
  prerelease: false
204
162
  version_requirements: !ruby/object:Gem::Requirement
205
163
  requirements:
206
164
  - - "~>"
207
165
  - !ruby/object:Gem::Version
208
- version: '5.0'
166
+ version: '1.7'
209
167
  description: |-
210
168
  The Mechanize library is used for automating interaction with websites.
211
169
  Mechanize automatically stores and sends cookies, follows redirects,
@@ -214,22 +172,22 @@ description: |-
214
172
  a history.
215
173
  email:
216
174
  - drbrain@segment7.net
217
- - aaronp@rubyforge.org
175
+ - aaron.patterson@gmail.com
218
176
  - mike.dalessio@gmail.com
219
177
  - knu@idaemons.org
220
178
  - ljjarvis@gmail.com
221
179
  executables: []
222
180
  extensions: []
223
181
  extra_rdoc_files:
224
- - EXAMPLES.rdoc
225
- - CHANGELOG.rdoc
226
182
  - GUIDE.rdoc
183
+ - EXAMPLES.rdoc
227
184
  - LICENSE.rdoc
185
+ - CHANGELOG.rdoc
228
186
  - README.rdoc
229
187
  files:
230
188
  - ".autotest"
189
+ - ".github/workflows/ci-test.yml"
231
190
  - ".gitignore"
232
- - ".travis.yml"
233
191
  - CHANGELOG.rdoc
234
192
  - EXAMPLES.rdoc
235
193
  - GUIDE.rdoc
@@ -455,8 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
455
413
  - !ruby/object:Gem::Version
456
414
  version: '0'
457
415
  requirements: []
458
- rubyforge_project:
459
- rubygems_version: 2.6.14.1
416
+ rubygems_version: 3.1.4
460
417
  signing_key:
461
418
  specification_version: 4
462
419
  summary: The Mechanize library is used for automating interaction with websites
data/.travis.yml DELETED
@@ -1,36 +0,0 @@
1
- ---
2
- language: ruby
3
- notifications:
4
- email:
5
- - drbrain@segment7.net
6
- - ljjarvis@gmail.com
7
- - knu@idaemons.org
8
-
9
- sudo: false
10
-
11
- # bundler is missing for jruby-head in travis-ci
12
- # https://github.com/travis-ci/travis-ci/issues/5861
13
- before_install:
14
- - gem install --conservative bundler -v'1.13.7'
15
-
16
- script: rake test
17
-
18
- matrix:
19
- include:
20
- - rvm: 1.9.3
21
- - rvm: 2.0.0
22
- - rvm: 2.1
23
- - rvm: 2.2
24
- - rvm: 2.3.3
25
- - rvm: 2.4.0
26
- - rvm: ruby-head
27
- - rvm: jruby-1.7.27
28
- - rvm: jruby-9.1.14.0
29
- - rvm: jruby-head
30
- allow_failures:
31
- - rvm: jruby-9.1.14.0
32
- - rvm: jruby-head
33
-
34
- env:
35
- global:
36
- - JRUBY_OPTS="--debug"