mechanize 2.7.7 → 2.8.3

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/ci-test.yml +36 -8
  4. data/.yardopts +8 -0
  5. data/{CHANGELOG.rdoc → CHANGELOG.md} +117 -88
  6. data/Gemfile +1 -6
  7. data/{LICENSE.rdoc → LICENSE.txt} +4 -0
  8. data/README.md +77 -0
  9. data/Rakefile +18 -3
  10. data/lib/mechanize/chunked_termination_error.rb +1 -0
  11. data/lib/mechanize/content_type_error.rb +1 -0
  12. data/lib/mechanize/cookie.rb +1 -13
  13. data/lib/mechanize/cookie_jar.rb +2 -10
  14. data/lib/mechanize/directory_saver.rb +1 -0
  15. data/lib/mechanize/download.rb +1 -0
  16. data/lib/mechanize/element_matcher.rb +1 -0
  17. data/lib/mechanize/element_not_found_error.rb +1 -0
  18. data/lib/mechanize/file.rb +1 -0
  19. data/lib/mechanize/file_connection.rb +5 -3
  20. data/lib/mechanize/file_request.rb +1 -0
  21. data/lib/mechanize/file_response.rb +3 -0
  22. data/lib/mechanize/file_saver.rb +1 -0
  23. data/lib/mechanize/form/button.rb +1 -0
  24. data/lib/mechanize/form/check_box.rb +1 -0
  25. data/lib/mechanize/form/field.rb +1 -0
  26. data/lib/mechanize/form/file_upload.rb +1 -0
  27. data/lib/mechanize/form/hidden.rb +1 -0
  28. data/lib/mechanize/form/image_button.rb +1 -0
  29. data/lib/mechanize/form/keygen.rb +1 -0
  30. data/lib/mechanize/form/multi_select_list.rb +1 -0
  31. data/lib/mechanize/form/option.rb +1 -0
  32. data/lib/mechanize/form/radio_button.rb +1 -0
  33. data/lib/mechanize/form/reset.rb +1 -0
  34. data/lib/mechanize/form/select_list.rb +1 -0
  35. data/lib/mechanize/form/submit.rb +1 -0
  36. data/lib/mechanize/form/text.rb +1 -0
  37. data/lib/mechanize/form/textarea.rb +1 -0
  38. data/lib/mechanize/form.rb +1 -9
  39. data/lib/mechanize/headers.rb +1 -0
  40. data/lib/mechanize/history.rb +1 -0
  41. data/lib/mechanize/http/agent.rb +16 -8
  42. data/lib/mechanize/http/auth_challenge.rb +1 -0
  43. data/lib/mechanize/http/auth_realm.rb +1 -0
  44. data/lib/mechanize/http/auth_store.rb +1 -0
  45. data/lib/mechanize/http/content_disposition_parser.rb +14 -2
  46. data/lib/mechanize/http/www_authenticate_parser.rb +3 -3
  47. data/lib/mechanize/http.rb +1 -0
  48. data/lib/mechanize/image.rb +1 -0
  49. data/lib/mechanize/page/base.rb +1 -0
  50. data/lib/mechanize/page/frame.rb +1 -0
  51. data/lib/mechanize/page/image.rb +1 -0
  52. data/lib/mechanize/page/label.rb +1 -0
  53. data/lib/mechanize/page/link.rb +8 -1
  54. data/lib/mechanize/page/meta_refresh.rb +1 -0
  55. data/lib/mechanize/page.rb +4 -3
  56. data/lib/mechanize/parser.rb +1 -0
  57. data/lib/mechanize/pluggable_parsers.rb +1 -0
  58. data/lib/mechanize/prependable.rb +1 -0
  59. data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
  60. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
  61. data/lib/mechanize/response_code_error.rb +2 -1
  62. data/lib/mechanize/response_read_error.rb +1 -0
  63. data/lib/mechanize/robots_disallowed_error.rb +1 -0
  64. data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
  65. data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
  66. data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
  67. data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
  68. data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
  69. data/lib/mechanize/test_case/form_servlet.rb +1 -0
  70. data/lib/mechanize/test_case/gzip_servlet.rb +1 -0
  71. data/lib/mechanize/test_case/header_servlet.rb +1 -0
  72. data/lib/mechanize/test_case/http_refresh_servlet.rb +1 -0
  73. data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
  74. data/lib/mechanize/test_case/infinite_refresh_servlet.rb +1 -0
  75. data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
  76. data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
  77. data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
  78. data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
  79. data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
  80. data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
  81. data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
  82. data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
  83. data/lib/mechanize/test_case/referer_servlet.rb +1 -0
  84. data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
  85. data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
  86. data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
  87. data/lib/mechanize/test_case/robots_txt_servlet.rb +1 -0
  88. data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
  89. data/lib/mechanize/test_case/server.rb +1 -0
  90. data/lib/mechanize/test_case/servlets.rb +1 -0
  91. data/lib/mechanize/test_case/verb_servlet.rb +1 -0
  92. data/lib/mechanize/test_case.rb +32 -27
  93. data/lib/mechanize/unauthorized_error.rb +1 -0
  94. data/lib/mechanize/unsupported_scheme_error.rb +1 -0
  95. data/lib/mechanize/util.rb +2 -1
  96. data/lib/mechanize/version.rb +2 -1
  97. data/lib/mechanize/xml_file.rb +1 -0
  98. data/lib/mechanize.rb +2 -1
  99. data/mechanize.gemspec +48 -34
  100. data/test/htdocs/dir with spaces/foo.html +1 -0
  101. data/test/test_mechanize.rb +5 -4
  102. data/test/test_mechanize_cookie_jar.rb +2 -0
  103. data/test/test_mechanize_download.rb +1 -0
  104. data/test/test_mechanize_file.rb +1 -0
  105. data/test/test_mechanize_file_connection.rb +21 -3
  106. data/test/test_mechanize_file_response.rb +6 -0
  107. data/test/test_mechanize_http_agent.rb +47 -7
  108. data/test/test_mechanize_http_content_disposition_parser.rb +27 -0
  109. data/test/test_mechanize_link.rb +24 -0
  110. data/test/test_mechanize_page_encoding.rb +28 -1
  111. metadata +145 -56
  112. data/README.rdoc +0 -77
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Raised when Mechanize encounters an error while reading the response body
3
4
  # from the server. Contains the response headers and the response body up to
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Exception that is raised when an access to a resource is disallowed by
2
3
  # robots.txt or by HTML document itself.
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class BadChunkingServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET req, res
3
4
  res.keep_alive = false if res.respond_to? :keep_alive=
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class BasicAuthServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req,res)
3
4
  htpd = nil
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class ContentTypeServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  ct = req.query['ct'] || "text/html; charset=utf-8"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'logger'
2
3
 
3
4
  class DigestAuthServlet < WEBrick::HTTPServlet::AbstractServlet
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class FileUploadServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_POST req, res
3
4
  res.body = req.body
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class FormServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res.content_type = 'text/html'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stringio'
2
3
  require 'zlib'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class HeaderServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res.content_type = "text/plain"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class HttpRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res['Content-Type'] = req.query['ct'] || "text/html"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class InfiniteRedirectServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res['Content-Type'] = req.query['ct'] || "text/html"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class InfiniteRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  address = "#{req.host}:#{req.port}"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class ManyCookiesAsStringServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  cookies = []
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class ManyCookiesServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  name_cookie = WEBrick::Cookie.new("name", "Aaron")
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class ModifiedSinceServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  s_time = 'Fri, 04 May 2001 00:00:38 GMT'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class NTLMServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
 
3
4
  def do_GET(req, res)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class OneCookieNoSpacesServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  cookie = WEBrick::Cookie.new("foo", "bar")
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class OneCookieServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  cookie = WEBrick::Cookie.new("foo", "bar")
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class QuotedValueCookieServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  cookie = WEBrick::Cookie.new("quoted", "\"value\"")
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class RedirectServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res['Content-Type'] = req.query['ct'] || 'text/html'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class RefererServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res['Content-Type'] = "text/html"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class RefreshWithEmptyUrl < WEBrick::HTTPServlet::AbstractServlet
2
3
  @@count = 0
3
4
  def do_GET(req, res)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class RefreshWithoutUrl < WEBrick::HTTPServlet::AbstractServlet
2
3
  @@count = 0
3
4
  def do_GET(req, res)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class ResponseCodeServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res['Content-Type'] = req.query['ct'] || "text/html"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class RobotsTxtServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  if /301/ === req['Host'] && req.path == '/robots.txt'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class SendCookiesServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  def do_GET(req, res)
3
4
  res.content_type = 'text/html'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'webrick'
2
3
  require 'mechanize/test_case/servlets'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'mechanize/test_case/bad_chunking_servlet'
2
3
  require 'mechanize/test_case/basic_auth_servlet'
3
4
  require 'mechanize/test_case/content_type_servlet'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class VerbServlet < WEBrick::HTTPServlet::AbstractServlet
2
3
  %w[HEAD GET POST PUT DELETE].each do |verb|
3
4
  define_method "do_#{verb}" do |req, res|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'mechanize'
2
3
  require 'logger'
3
4
  require 'tempfile'
@@ -57,12 +58,12 @@ class Mechanize::TestCase < Minitest::Test
57
58
 
58
59
  def fake_page agent = @mech
59
60
  uri = URI 'http://fake.example/'
60
- html = <<-END
61
- <html>
62
- <body>
63
- <form><input type="submit" value="submit" /></form>
64
- </body>
65
- </html>
61
+ html = String.new(<<~END)
62
+ <html>
63
+ <body>
64
+ <form><input type="submit" value="submit" /></form>
65
+ </body>
66
+ </html>
66
67
  END
67
68
 
68
69
  Mechanize::Page.new uri, nil, html, 200, agent
@@ -87,11 +88,9 @@ class Mechanize::TestCase < Minitest::Test
87
88
  # Creates a Mechanize::CookieJar by parsing the given +str+
88
89
 
89
90
  def cookie_jar str, uri = URI('http://example')
90
- jar = Mechanize::CookieJar.new
91
-
92
- jar.parse str, uri
93
-
94
- jar
91
+ Mechanize::CookieJar.new.tap do |jar|
92
+ jar.parse str, uri
93
+ end
95
94
  end
96
95
 
97
96
  ##
@@ -109,22 +108,18 @@ class Mechanize::TestCase < Minitest::Test
109
108
  # Creates a Nokogiri Node +element+ with the given +attributes+
110
109
 
111
110
  def node element, attributes = {}
112
- doc = Nokogiri::HTML::Document.new
113
-
114
- node = Nokogiri::XML::Node.new element, doc
115
-
116
- attributes.each do |name, value|
117
- node[name] = value
111
+ Nokogiri::XML::Node.new(element, Nokogiri::HTML::Document.new).tap do |node|
112
+ attributes.each do |name, value|
113
+ node[name] = value
114
+ end
118
115
  end
119
-
120
- node
121
116
  end
122
117
 
123
118
  ##
124
119
  # Creates a Mechanize::Page for the given +uri+ with the given
125
120
  # +content_type+, response +body+ and HTTP status +code+
126
121
 
127
- def page uri, content_type = 'text/html', body = '', code = 200
122
+ def page uri, content_type = 'text/html', body = String.new, code = 200
128
123
  uri = URI uri unless URI::Generic === uri
129
124
 
130
125
  Mechanize::Page.new(uri, { 'content-type' => content_type }, body, code,
@@ -173,15 +168,25 @@ UQIBATANBgkqhkiG9w0BAQUFAANBAAAB////////////////////////////////
173
168
  # Creates a Tempfile with +content+ that is immediately unlinked
174
169
 
175
170
  def tempfile content
176
- body_io = Tempfile.new @NAME
177
- body_io.unlink
178
- body_io.write content
179
- body_io.flush
180
- body_io.rewind
171
+ Tempfile.new(@NAME).tap do |body_io|
172
+ body_io.unlink
173
+ body_io.write content
174
+ body_io.flush
175
+ body_io.rewind
176
+ end
177
+ end
181
178
 
182
- body_io
179
+ ##
180
+ # Returns true if the current platform is a Windows platform
181
+ def windows?
182
+ ::RUBY_PLATFORM =~ /mingw|mswin/
183
183
  end
184
184
 
185
+ ##
186
+ # Return the contents of the file without Windows carriage returns
187
+ def file_contents_without_cr(path)
188
+ File.read(path).gsub(/\r\n/, "\n")
189
+ end
185
190
  end
186
191
 
187
192
  require 'mechanize/test_case/servlets'
@@ -312,7 +317,7 @@ class Response # :nodoc:
312
317
 
313
318
  def initialize
314
319
  @header = {}
315
- @body = ''
320
+ @body = String.new
316
321
  @code = nil
317
322
  @query = nil
318
323
  @cookies = []
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Mechanize::UnauthorizedError < Mechanize::ResponseCodeError
2
3
 
3
4
  attr_reader :challenges
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Mechanize::UnsupportedSchemeError < Mechanize::Error
2
3
  attr_accessor :scheme, :uri
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cgi'
2
3
  require 'nkf'
3
4
 
@@ -15,7 +16,7 @@ class Mechanize::Util
15
16
  def build_query_string(parameters, enc = nil)
16
17
  each_parameter(parameters).inject(nil) { |s, (k, v)|
17
18
  # WEBrick::HTTP.escape* has some problems about m17n on ruby-1.9.*.
18
- (s.nil? ? '' : s << '&') << [CGI.escape(k.to_s), CGI.escape(v.to_s)].join('=')
19
+ (s.nil? ? String.new : s << '&') << [CGI.escape(k.to_s), CGI.escape(v.to_s)].join('=')
19
20
  } || ''
20
21
  end
21
22
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Mechanize
2
- VERSION = "2.7.7"
3
+ VERSION = "2.8.3"
3
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This class encapsulates an XML file. If Mechanize finds a content-type
3
4
  # of 'text/xml' or 'application/xml' this class will be instantiated and
data/lib/mechanize.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'mechanize/version'
2
3
  require 'fileutils'
3
4
  require 'forwardable'
@@ -114,7 +115,7 @@ class Mechanize
114
115
 
115
116
  AGENT_ALIASES = {
116
117
  'Mechanize' => "Mechanize/#{VERSION} Ruby/#{ruby_version} (http://github.com/sparklemotion/mechanize/)",
117
- 'Linux Firefox' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0',
118
+ 'Linux Firefox' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0',
118
119
  'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)',
119
120
  'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624',
120
121
  'Mac Firefox' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0',
data/mechanize.gemspec CHANGED
@@ -1,20 +1,19 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'mechanize/version'
2
+ # frozen_string_literal: true
3
+ require_relative 'lib/mechanize/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "mechanize"
8
- spec.version = Mechanize::VERSION
9
- spec.homepage = "http://docs.seattlerb.org/mechanize/"
10
- spec.summary = %q{The Mechanize library is used for automating interaction with websites}
11
- spec.description =
6
+ spec.name = "mechanize"
7
+ spec.version = Mechanize::VERSION
8
+ spec.homepage = "https://github.com/sparklemotion/mechanize"
9
+ spec.summary = 'The Mechanize library is used for automating interaction with websites'
10
+ spec.description =
12
11
  [
13
12
  "The Mechanize library is used for automating interaction with websites.",
14
13
  "Mechanize automatically stores and sends cookies, follows redirects,",
15
14
  "and can follow links and submit forms. Form fields can be populated and",
16
15
  "submitted. Mechanize also keeps track of the sites that you have visited as",
17
- "a history."
16
+ "a history.",
18
17
  ].join("\n")
19
18
 
20
19
  spec.authors =
@@ -23,7 +22,7 @@ Gem::Specification.new do |spec|
23
22
  'Aaron Patterson',
24
23
  'Mike Dalessio',
25
24
  'Akinori MUSHA',
26
- 'Lee Jarvis'
25
+ 'Lee Jarvis',
27
26
  ]
28
27
  spec.email =
29
28
  [
@@ -31,32 +30,47 @@ Gem::Specification.new do |spec|
31
30
  'aaron.patterson@gmail.com',
32
31
  'mike.dalessio@gmail.com',
33
32
  'knu@idaemons.org',
34
- 'ljjarvis@gmail.com'
33
+ 'ljjarvis@gmail.com',
35
34
  ]
36
35
 
37
- spec.license = "MIT"
36
+ spec.metadata = {
37
+ 'yard.run' => 'yard',
38
+ 'bug_tracker_uri' => 'https://github.com/sparklemotion/mechanize/issues',
39
+ 'changelog_uri' => 'https://github.com/sparklemotion/mechanize/blob/main/CHANGELOG.md',
40
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/mechanize',
41
+ 'homepage_uri' => 'https://github.com/sparklemotion/mechanize',
42
+ 'source_code_uri' => 'https://github.com/sparklemotion/mechanize'
43
+ }
44
+
45
+ spec.license = "MIT"
38
46
 
39
47
  spec.require_paths = ["lib"]
40
- spec.files = `git ls-files`.split($/)
41
- spec.test_files = spec.files.grep(%r{^test/})
42
-
43
- spec.extra_rdoc_files += Dir['*.rdoc']
44
- spec.rdoc_options = ["--main", "README.rdoc"]
45
-
46
- spec.required_ruby_version = ">= 1.9.2"
47
-
48
- spec.add_runtime_dependency "net-http-digest_auth", [ ">= 1.1.1", "~> 1.1" ]
49
- if RUBY_VERSION >= "2.0"
50
- spec.add_runtime_dependency "mime-types", [ ">= 1.17.2" ]
51
- spec.add_runtime_dependency "net-http-persistent", [ ">= 2.5.2"]
52
- else
53
- spec.add_runtime_dependency "mime-types", [ ">= 1.17.2", "< 3" ]
54
- spec.add_runtime_dependency "net-http-persistent", [ ">= 2.5.2", "~> 2.5" ]
55
- end
56
- spec.add_runtime_dependency "http-cookie", [ "~> 1.0" ]
57
- spec.add_runtime_dependency "nokogiri", [ "~> 1.6" ]
58
- spec.add_runtime_dependency "ntlm-http", [ ">= 0.1.1", "~> 0.1" ]
59
- spec.add_runtime_dependency "webrobots", [ "< 0.2", ">= 0.0.9" ]
60
- spec.add_runtime_dependency "domain_name", [ ">= 0.5.1", "~> 0.5" ]
61
- spec.add_runtime_dependency 'webrick', "~> 1.7"
48
+ spec.files = %x(git ls-files).split($/)
49
+ spec.test_files = spec.files.grep(%r{^test/})
50
+
51
+ spec.extra_rdoc_files += Dir['*.rdoc', '*.md']
52
+ spec.rdoc_options = ["--main", "README.md"]
53
+
54
+ spec.required_ruby_version = ">= 2.5.0"
55
+
56
+ spec.add_runtime_dependency("addressable", "~> 2.8")
57
+ spec.add_runtime_dependency("domain_name", ">= 0.5.20190701", "~> 0.5")
58
+ spec.add_runtime_dependency("http-cookie", ">= 1.0.3", "~> 1.0")
59
+ spec.add_runtime_dependency("mime-types", "~> 3.0")
60
+ spec.add_runtime_dependency("net-http-digest_auth", ">= 1.4.1", "~> 1.4")
61
+
62
+ # careful! some folks are relying on older versions of net-http-persistent
63
+ # - see the socks proxy patch in use at #507 and #464
64
+ # - see use of retry_change_requests that was removed at #558
65
+ spec.add_runtime_dependency("net-http-persistent", ">= 2.5.2", "< 5.0.dev")
66
+
67
+ spec.add_runtime_dependency("nokogiri", ">= 1.11.2", "~> 1.11")
68
+ spec.add_runtime_dependency("rubyntlm", ">= 0.6.3", "~> 0.6")
69
+ spec.add_runtime_dependency("webrick", "~> 1.7")
70
+ spec.add_runtime_dependency("webrobots", "~> 0.1.2")
71
+
72
+ spec.add_development_dependency("minitest", "~> 5.14")
73
+ spec.add_development_dependency("rake", "~> 13.0")
74
+ spec.add_development_dependency("rdoc", "~> 6.3")
75
+ spec.add_development_dependency("rubocop", "~> 1.12")
62
76
  end
@@ -1 +1,2 @@
1
1
  HELLO
2
+
@@ -346,6 +346,7 @@ but not <a href="/" rel="me nofollow">this</a>!
346
346
  end
347
347
 
348
348
  def test_download_does_not_allow_command_injection
349
+ skip if windows?
349
350
  in_tmpdir do
350
351
  @mech.download('http://example', '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
351
352
 
@@ -949,7 +950,7 @@ but not <a href="/" rel="me nofollow">this</a>!
949
950
  "Content-Disposition: form-data; name=\"userfile1\"; filename=\"#{name}\"",
950
951
  page.body
951
952
  )
952
- assert_operator page.body.bytesize, :>, File.size(__FILE__)
953
+ assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
953
954
  end
954
955
 
955
956
  def test_post_file_upload_nonascii
@@ -968,7 +969,7 @@ but not <a href="/" rel="me nofollow">this</a>!
968
969
  page.body
969
970
  )
970
971
  assert_match("Content-Type: application/zip", page.body)
971
- assert_operator page.body.bytesize, :>, File.size(__FILE__)
972
+ assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
972
973
  end
973
974
 
974
975
  def test_post_file_upload
@@ -987,7 +988,7 @@ but not <a href="/" rel="me nofollow">this</a>!
987
988
  page.body
988
989
  )
989
990
  assert_match("Content-Type: application/zip", page.body)
990
- assert_operator page.body.bytesize, :>, File.size(__FILE__)
991
+ assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
991
992
  end
992
993
 
993
994
  def test_post_redirect
@@ -1182,7 +1183,7 @@ but not <a href="/" rel="me nofollow">this</a>!
1182
1183
 
1183
1184
  page = @mech.submit(form)
1184
1185
 
1185
- contents = File.binread __FILE__
1186
+ contents = File.binread(__FILE__).gsub(/\r\n/, "\n")
1186
1187
  basename = File.basename __FILE__
1187
1188
 
1188
1189
  assert_match(
@@ -502,6 +502,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
502
502
  end
503
503
 
504
504
  def test_prevent_command_injection_when_saving
505
+ skip if windows?
505
506
  url = URI 'http://rubygems.org/'
506
507
  path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
507
508
 
@@ -514,6 +515,7 @@ class TestMechanizeCookieJar < Mechanize::TestCase
514
515
  end
515
516
 
516
517
  def test_prevent_command_injection_when_loading
518
+ skip if windows?
517
519
  url = URI 'http://rubygems.org/'
518
520
  path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
519
521
 
@@ -47,6 +47,7 @@ class TestMechanizeDownload < Mechanize::TestCase
47
47
  end
48
48
 
49
49
  def test_save_bang_does_not_allow_command_injection
50
+ skip if windows?
50
51
  uri = URI.parse 'http://example/foo.html'
51
52
  body_io = StringIO.new '0123456789'
52
53
 
@@ -104,6 +104,7 @@ class TestMechanizeFile < Mechanize::TestCase
104
104
  end
105
105
 
106
106
  def test_save_bang_does_not_allow_command_injection
107
+ skip if windows?
107
108
  uri = URI 'http://example/test.html'
108
109
  page = Mechanize::File.new uri, nil, ''
109
110
 
@@ -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
@@ -1,6 +1,11 @@
1
1
  require 'mechanize/test_case'
2
2
 
3
3
  class TestMechanizeFileResponse < Mechanize::TestCase
4
+ def test_file_path
5
+ res = Mechanize::FileResponse.new("/path/to/foo.html")
6
+ assert_equal("/path/to/foo.html", res.file_path)
7
+ end
8
+
4
9
  def test_content_type
5
10
  Tempfile.open %w[pi .nothtml] do |tempfile|
6
11
  res = Mechanize::FileResponse.new tempfile.path
@@ -31,6 +36,7 @@ class TestMechanizeFileResponse < Mechanize::TestCase
31
36
  end
32
37
 
33
38
  def test_read_body_does_not_allow_command_injection
39
+ skip if windows?
34
40
  in_tmpdir do
35
41
  FileUtils.touch('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
36
42
  res = Mechanize::FileResponse.new('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')