mechanize 2.7.6 → 2.8.2

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.

Files changed (119) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/ci-test.yml +53 -0
  4. data/.yardopts +8 -0
  5. data/{CHANGELOG.rdoc → CHANGELOG.md} +136 -87
  6. data/EXAMPLES.rdoc +1 -24
  7. data/Gemfile +1 -4
  8. data/{LICENSE.rdoc → LICENSE.txt} +4 -0
  9. data/README.md +77 -0
  10. data/Rakefile +18 -3
  11. data/examples/rubygems.rb +2 -2
  12. data/lib/mechanize.rb +3 -2
  13. data/lib/mechanize/chunked_termination_error.rb +1 -0
  14. data/lib/mechanize/content_type_error.rb +1 -0
  15. data/lib/mechanize/cookie.rb +1 -13
  16. data/lib/mechanize/cookie_jar.rb +4 -12
  17. data/lib/mechanize/directory_saver.rb +1 -0
  18. data/lib/mechanize/download.rb +2 -1
  19. data/lib/mechanize/element_matcher.rb +1 -0
  20. data/lib/mechanize/element_not_found_error.rb +1 -0
  21. data/lib/mechanize/file.rb +2 -1
  22. data/lib/mechanize/file_connection.rb +5 -3
  23. data/lib/mechanize/file_request.rb +1 -0
  24. data/lib/mechanize/file_response.rb +4 -1
  25. data/lib/mechanize/file_saver.rb +1 -0
  26. data/lib/mechanize/form.rb +2 -10
  27. data/lib/mechanize/form/button.rb +1 -0
  28. data/lib/mechanize/form/check_box.rb +1 -0
  29. data/lib/mechanize/form/field.rb +1 -0
  30. data/lib/mechanize/form/file_upload.rb +1 -0
  31. data/lib/mechanize/form/hidden.rb +1 -0
  32. data/lib/mechanize/form/image_button.rb +1 -0
  33. data/lib/mechanize/form/keygen.rb +1 -0
  34. data/lib/mechanize/form/multi_select_list.rb +1 -0
  35. data/lib/mechanize/form/option.rb +1 -0
  36. data/lib/mechanize/form/radio_button.rb +1 -0
  37. data/lib/mechanize/form/reset.rb +1 -0
  38. data/lib/mechanize/form/select_list.rb +1 -0
  39. data/lib/mechanize/form/submit.rb +1 -0
  40. data/lib/mechanize/form/text.rb +1 -0
  41. data/lib/mechanize/form/textarea.rb +1 -0
  42. data/lib/mechanize/headers.rb +1 -0
  43. data/lib/mechanize/history.rb +1 -0
  44. data/lib/mechanize/http.rb +1 -0
  45. data/lib/mechanize/http/agent.rb +16 -8
  46. data/lib/mechanize/http/auth_challenge.rb +1 -0
  47. data/lib/mechanize/http/auth_realm.rb +1 -0
  48. data/lib/mechanize/http/auth_store.rb +1 -0
  49. data/lib/mechanize/http/content_disposition_parser.rb +14 -2
  50. data/lib/mechanize/http/www_authenticate_parser.rb +3 -3
  51. data/lib/mechanize/image.rb +1 -0
  52. data/lib/mechanize/page.rb +4 -3
  53. data/lib/mechanize/page/base.rb +1 -0
  54. data/lib/mechanize/page/frame.rb +1 -0
  55. data/lib/mechanize/page/image.rb +1 -0
  56. data/lib/mechanize/page/label.rb +1 -0
  57. data/lib/mechanize/page/link.rb +8 -1
  58. data/lib/mechanize/page/meta_refresh.rb +1 -0
  59. data/lib/mechanize/parser.rb +1 -0
  60. data/lib/mechanize/pluggable_parsers.rb +1 -0
  61. data/lib/mechanize/prependable.rb +1 -0
  62. data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
  63. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
  64. data/lib/mechanize/response_code_error.rb +2 -1
  65. data/lib/mechanize/response_read_error.rb +1 -0
  66. data/lib/mechanize/robots_disallowed_error.rb +1 -0
  67. data/lib/mechanize/test_case.rb +34 -29
  68. data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
  69. data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
  70. data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
  71. data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
  72. data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
  73. data/lib/mechanize/test_case/form_servlet.rb +1 -0
  74. data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
  75. data/lib/mechanize/test_case/header_servlet.rb +1 -0
  76. data/lib/mechanize/test_case/http_refresh_servlet.rb +1 -0
  77. data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
  78. data/lib/mechanize/test_case/infinite_refresh_servlet.rb +1 -0
  79. data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
  80. data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
  81. data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
  82. data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
  83. data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
  84. data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
  85. data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
  86. data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
  87. data/lib/mechanize/test_case/referer_servlet.rb +1 -0
  88. data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
  89. data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
  90. data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
  91. data/lib/mechanize/test_case/robots_txt_servlet.rb +1 -0
  92. data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
  93. data/lib/mechanize/test_case/server.rb +1 -0
  94. data/lib/mechanize/test_case/servlets.rb +1 -0
  95. data/lib/mechanize/test_case/verb_servlet.rb +5 -6
  96. data/lib/mechanize/unauthorized_error.rb +1 -0
  97. data/lib/mechanize/unsupported_scheme_error.rb +1 -0
  98. data/lib/mechanize/util.rb +2 -1
  99. data/lib/mechanize/version.rb +2 -1
  100. data/lib/mechanize/xml_file.rb +1 -0
  101. data/mechanize.gemspec +45 -35
  102. data/test/htdocs/dir with spaces/foo.html +1 -0
  103. data/test/htdocs/tc_links.html +1 -1
  104. data/test/test_mechanize.rb +19 -7
  105. data/test/test_mechanize_cookie.rb +19 -19
  106. data/test/test_mechanize_cookie_jar.rb +85 -53
  107. data/test/test_mechanize_download.rb +13 -1
  108. data/test/test_mechanize_file.rb +10 -0
  109. data/test/test_mechanize_file_connection.rb +21 -3
  110. data/test/test_mechanize_file_response.rb +25 -1
  111. data/test/test_mechanize_form.rb +12 -0
  112. data/test/test_mechanize_form_keygen.rb +1 -0
  113. data/test/test_mechanize_http_agent.rb +53 -8
  114. data/test/test_mechanize_http_content_disposition_parser.rb +27 -0
  115. data/test/test_mechanize_link.rb +24 -0
  116. data/test/test_mechanize_page_encoding.rb +28 -1
  117. metadata +117 -71
  118. data/.travis.yml +0 -36
  119. data/README.rdoc +0 -77
@@ -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,41 @@ 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
+ skip if windows?
506
+ url = URI 'http://rubygems.org/'
507
+ path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
508
+
509
+ @jar.add(url, Mechanize::Cookie.new(cookie_values))
510
+
511
+ in_tmpdir do
512
+ @jar.save_as(path, :cookiestxt)
513
+ assert_equal(false, File.exist?('vul.txt'))
514
+ end
515
+ end
516
+
517
+ def test_prevent_command_injection_when_loading
518
+ skip if windows?
519
+ url = URI 'http://rubygems.org/'
520
+ path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
521
+
522
+ @jar.add(url, Mechanize::Cookie.new(cookie_values))
523
+
524
+ in_tmpdir do
525
+ @jar.save_as("cookies.txt", :cookiestxt)
526
+ @jar.clear!
527
+
528
+ assert_raises Errno::ENOENT do
529
+ @jar.load(path, :cookiestxt)
530
+ end
531
+ assert_equal(false, File.exist?('vul.txt'))
532
+ end
533
+ end
534
+
503
535
  def test_save_and_read_expired_cookies
504
- url = URI 'http://rubyforge.org/'
536
+ url = URI 'http://rubygems.org/'
505
537
 
506
- @jar.jar['rubyforge.org'] = {}
538
+ @jar.jar['rubygems.org'] = {}
507
539
 
508
540
 
509
541
  @jar.add url, Mechanize::Cookie.new(cookie_values)
@@ -515,7 +547,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
515
547
  # thanks to michal "ocher" ochman for reporting the bug responsible for this test.
516
548
  values = cookie_values(:expires => nil)
517
549
  values_ssl = values.merge(:name => 'Baz', :domain => "#{values[:domain]}:443")
518
- url = URI 'https://rubyforge.org/login'
550
+ url = URI 'https://rubygems.org/login'
519
551
 
520
552
  cookie = Mechanize::Cookie.new(values)
521
553
  @jar.add(url, cookie)
@@ -527,8 +559,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
527
559
  end
528
560
 
529
561
  def test_secure_cookie
530
- nurl = URI 'http://rubyforge.org/login'
531
- surl = URI 'https://rubyforge.org/login'
562
+ nurl = URI 'http://rubygems.org/login'
563
+ surl = URI 'https://rubygems.org/login'
532
564
 
533
565
  ncookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo1'))
534
566
  scookie = Mechanize::Cookie.new(cookie_values(:name => 'Foo2', :secure => true))
@@ -543,10 +575,10 @@ class TestMechanizeCookieJar < Mechanize::TestCase
543
575
  end
544
576
 
545
577
  def test_save_cookies_cookiestxt_subdomain
546
- top_url = URI 'http://rubyforge.org/'
547
- subdomain_url = URI 'http://admin.rubyforge.org/'
578
+ top_url = URI 'http://rubygems.org/'
579
+ subdomain_url = URI 'http://admin.rubygems.org/'
548
580
 
549
- # cookie1 is for *.rubyforge.org; cookie2 is only for rubyforge.org, no subdomains
581
+ # cookie1 is for *.rubygems.org; cookie2 is only for rubygems.org, no subdomains
550
582
  cookie1 = Mechanize::Cookie.new(cookie_values)
551
583
  cookie2 = Mechanize::Cookie.new(cookie_values(:name => 'Boo', :for_domain => false))
552
584
 
@@ -572,8 +604,8 @@ class TestMechanizeCookieJar < Mechanize::TestCase
572
604
  # * Cookies that match subdomains may have a leading dot, and must have
573
605
  # TRUE as the second field.
574
606
  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)
607
+ assert_equal(1, cookies_txt.grep( /^rubygems\.org\tFALSE/ ).length)
608
+ assert_equal(1, cookies_txt.grep( /^\.rubygems\.org\tTRUE/ ).length)
577
609
  end
578
610
 
579
611
  assert_equal(2, @jar.cookies(top_url).length)
@@ -46,6 +46,19 @@ class TestMechanizeDownload < Mechanize::TestCase
46
46
  end
47
47
  end
48
48
 
49
+ def test_save_bang_does_not_allow_command_injection
50
+ skip if windows?
51
+ uri = URI.parse 'http://example/foo.html'
52
+ body_io = StringIO.new '0123456789'
53
+
54
+ download = @parser.new uri, nil, body_io
55
+
56
+ in_tmpdir do
57
+ download.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
58
+ refute_operator(File, :exist?, "vul.txt")
59
+ end
60
+ end
61
+
49
62
  def test_save_tempfile
50
63
  uri = URI.parse 'http://example/foo.html'
51
64
  Tempfile.open @NAME do |body_io|
@@ -84,6 +97,5 @@ class TestMechanizeDownload < Mechanize::TestCase
84
97
 
85
98
  assert_equal "foo.html", download.filename
86
99
  end
87
-
88
100
  end
89
101
 
@@ -103,5 +103,15 @@ class TestMechanizeFile < Mechanize::TestCase
103
103
  end
104
104
  end
105
105
 
106
+ def test_save_bang_does_not_allow_command_injection
107
+ skip if windows?
108
+ uri = URI 'http://example/test.html'
109
+ page = Mechanize::File.new uri, nil, ''
110
+
111
+ in_tmpdir do
112
+ page.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
113
+ refute_operator(File, :exist?, "vul.txt")
114
+ end
115
+ end
106
116
  end
107
117
 
@@ -3,19 +3,37 @@ require 'mechanize/test_case'
3
3
  class TestMechanizeFileConnection < Mechanize::TestCase
4
4
 
5
5
  def test_request
6
- uri = URI.parse "file://#{File.expand_path __FILE__}"
6
+ file_path = File.expand_path(__FILE__)
7
+ uri = URI.parse "file://#{file_path}"
7
8
  conn = Mechanize::FileConnection.new
8
9
 
9
10
  body = ''
10
11
 
11
12
  conn.request uri, nil do |response|
13
+ assert_equal(file_path, response.file_path)
12
14
  response.read_body do |part|
13
15
  body << part
14
16
  end
15
17
  end
16
18
 
17
- assert_equal File.read(__FILE__), body
19
+ assert_equal File.read(__FILE__), body.gsub(/\r\n/, "\n")
18
20
  end
19
21
 
20
- end
22
+ def test_request_on_uri_with_windows_drive
23
+ uri_string = "file://C:/path/to/file.html"
24
+ expected_file_path = "C:/path/to/file.html"
25
+
26
+ uri = URI.parse(uri_string)
27
+ conn = Mechanize::FileConnection.new
21
28
 
29
+ called = false
30
+ yielded_file_path = nil
31
+ conn.request(uri, nil) do |response|
32
+ called = true
33
+ yielded_file_path = response.file_path
34
+ end
35
+
36
+ assert(called)
37
+ assert_equal(expected_file_path, yielded_file_path)
38
+ end
39
+ end