mechanize 2.7.2 → 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 +5 -5
- data/.github/workflows/ci-test.yml +25 -0
- data/.gitignore +15 -0
- data/CHANGELOG.rdoc +83 -0
- data/EXAMPLES.rdoc +2 -25
- data/Gemfile +8 -0
- data/README.rdoc +12 -18
- data/Rakefile +22 -38
- data/examples/{rubyforge.rb → rubygems.rb} +7 -6
- data/lib/mechanize.rb +85 -35
- data/lib/mechanize/cookie_jar.rb +2 -2
- data/lib/mechanize/directory_saver.rb +14 -2
- data/lib/mechanize/download.rb +6 -1
- data/lib/mechanize/element_matcher.rb +35 -14
- data/lib/mechanize/element_not_found_error.rb +19 -0
- data/lib/mechanize/file.rb +13 -3
- data/lib/mechanize/file_response.rb +2 -4
- data/lib/mechanize/form.rb +157 -46
- data/lib/mechanize/form/field.rb +46 -0
- data/lib/mechanize/form/multi_select_list.rb +13 -14
- data/lib/mechanize/form/option.rb +2 -1
- data/lib/mechanize/history.rb +1 -1
- data/lib/mechanize/http/agent.rb +104 -59
- data/lib/mechanize/http/auth_realm.rb +1 -1
- data/lib/mechanize/http/auth_store.rb +2 -0
- data/lib/mechanize/http/content_disposition_parser.rb +4 -1
- data/lib/mechanize/http/www_authenticate_parser.rb +2 -2
- data/lib/mechanize/page.rb +195 -49
- data/lib/mechanize/page/frame.rb +3 -1
- data/lib/mechanize/page/image.rb +2 -0
- data/lib/mechanize/page/link.rb +5 -0
- data/lib/mechanize/parser.rb +3 -3
- data/lib/mechanize/pluggable_parsers.rb +13 -1
- data/lib/mechanize/test_case.rb +7 -2
- data/lib/mechanize/test_case/gzip_servlet.rb +3 -3
- data/lib/mechanize/test_case/http_refresh_servlet.rb +1 -2
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +1 -2
- data/lib/mechanize/test_case/robots_txt_servlet.rb +14 -0
- data/lib/mechanize/test_case/servlets.rb +3 -0
- data/lib/mechanize/test_case/verb_servlet.rb +4 -6
- data/lib/mechanize/unauthorized_error.rb +1 -1
- data/lib/mechanize/unsupported_scheme_error.rb +4 -2
- data/lib/mechanize/util.rb +89 -43
- data/lib/mechanize/version.rb +3 -0
- data/mechanize.gemspec +62 -0
- data/test/htdocs/find_link.html +1 -4
- data/test/htdocs/tc_links.html +1 -1
- data/test/test_mechanize.rb +118 -55
- data/test/test_mechanize_cookie.rb +75 -60
- data/test/test_mechanize_cookie_jar.rb +110 -59
- data/test/test_mechanize_download.rb +40 -3
- data/test/test_mechanize_element_not_found_error.rb +15 -0
- data/test/test_mechanize_file.rb +29 -10
- data/test/test_mechanize_file_response.rb +21 -3
- data/test/test_mechanize_form.rb +69 -11
- data/test/test_mechanize_form_check_box.rb +10 -0
- data/test/test_mechanize_form_encoding.rb +3 -8
- data/test/test_mechanize_form_keygen.rb +1 -0
- data/test/test_mechanize_form_multi_select_list.rb +5 -1
- data/test/test_mechanize_http_agent.rb +139 -12
- data/test/test_mechanize_http_auth_challenge.rb +14 -0
- data/test/test_mechanize_http_auth_realm.rb +7 -1
- data/test/test_mechanize_http_auth_store.rb +37 -0
- data/test/test_mechanize_http_content_disposition_parser.rb +8 -1
- data/test/test_mechanize_http_www_authenticate_parser.rb +24 -0
- data/test/test_mechanize_link.rb +61 -3
- data/test/test_mechanize_page.rb +82 -7
- data/test/test_mechanize_page_encoding.rb +2 -3
- data/test/test_mechanize_page_image.rb +1 -1
- data/test/test_mechanize_page_link.rb +20 -5
- data/test/test_mechanize_page_meta_refresh.rb +1 -1
- data/test/test_mechanize_parser.rb +12 -2
- data/test/test_mechanize_util.rb +46 -11
- metadata +125 -111
- data/.gemtest +0 -0
- data/.travis.yml +0 -26
- data/Manifest.txt +0 -203
- data/lib/mechanize/monkey_patch.rb +0 -17
- data/test/htdocs/robots.txt +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: feff4acdf05edc4c615ab91f9ab0b7abfd1987dbd998ed07a36489189594edf2
|
4
|
+
data.tar.gz: efce735d57a4b2259f30a630829f432f270e3aa353fb9d4f5ad032df06387e84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/.gitignore
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,88 @@
|
|
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
|
+
|
30
|
+
=== 2.7.6
|
31
|
+
|
32
|
+
* New Features
|
33
|
+
* Mechanize#set_proxy accepts an HTTP URL/URI. (#513)
|
34
|
+
|
35
|
+
* Bug fix
|
36
|
+
* Fix element(s)_with(search: selector) methods not working for forms, form fields and frames. (#444)
|
37
|
+
* Improve the filename parser for the `Content-Disposition` header. (#496, #517)
|
38
|
+
* Accept `Content-Encoding: identity`. (#515)
|
39
|
+
* Mechanize::Page#title no longer picks a title in an embeded SVG/RDF element. (#503)
|
40
|
+
* Make Mechanize::Form#has_field? boolean. (#501)
|
41
|
+
|
42
|
+
=== 2.7.5
|
43
|
+
|
44
|
+
* New Features
|
45
|
+
* All 4xx responses and RedirectLimitReachedError when fetching robots.txt are treated as full allow just like Googlebot does.
|
46
|
+
* Enable support for mime-types > 3.
|
47
|
+
|
48
|
+
* Bug fix
|
49
|
+
* Don't cause infinite loop when `GET /robots.txt` redirects. (#457)
|
50
|
+
* Fix basic authentication for a realm that contains uppercase characters. (#458, #459)
|
51
|
+
* Fix encoding error when uploading a file which name is non-ASCII. (#333)
|
52
|
+
|
53
|
+
=== 2.7.4
|
54
|
+
|
55
|
+
* New Features
|
56
|
+
* Accept array-like and hash-like values as query/parameter value.
|
57
|
+
A new utility method Mechanize::Util.each_parameter is added, and Mechanize::Util.build_query_string is enhanced
|
58
|
+
for this feature.
|
59
|
+
* Allow passing a `Form::FileUpload` instance to `#post`. #350 by Sam
|
60
|
+
Rawlins.
|
61
|
+
* Capture link when scheme is unsupported. #362 by Jon Rowe.
|
62
|
+
* Pre-defined User-Agent stings are updated to those of more recent versions, and new aliases for IE 10/11 and Edge are added.
|
63
|
+
* Support for mime-types 1.x is restored while keeping compatible with mime-types 2.x.
|
64
|
+
* Mechanize::Page now responds to #xpath, #css, #at_xpath, #at_css, and #%.
|
65
|
+
* element(s)_with methods now accept :xpath and :css options for doing xpath/css
|
66
|
+
selector searching.
|
67
|
+
* Pass URI information to Nokogiri where applicable. #405 @lulalala
|
68
|
+
|
69
|
+
* Bug fix
|
70
|
+
* Don't raise an exception if a connection has set a {read,open}_timeout and
|
71
|
+
a `file://` request is made. (#397)
|
72
|
+
* Fix whitespace bug in WWW-Authenticate. #451, #450, by Rasmus Bergholdt
|
73
|
+
* Don't allow redirect from a non-file URL to a file URL for security reasons. (#455)
|
74
|
+
|
75
|
+
=== 2.7.3
|
76
|
+
|
77
|
+
* New Features
|
78
|
+
* Allow net-http-persistent instance to be named. #324, John Weir.
|
79
|
+
* #save and #save! return filename #340
|
80
|
+
* Updated mime-types requirement to 2.x versions. #348 by Jeff Nyman.
|
81
|
+
|
82
|
+
* Bug fix
|
83
|
+
* Ensure Download#save! defaults back to original filename if
|
84
|
+
none is provided (#300)
|
85
|
+
|
3
86
|
=== 2.7.2
|
4
87
|
|
5
88
|
* Bug fix
|
data/EXAMPLES.rdoc
CHANGED
@@ -15,7 +15,7 @@ example, <code>do ... end.submit</code> is the same as <code>{ ...
|
|
15
15
|
}
|
16
16
|
|
17
17
|
a.get('http://google.com/') do |page|
|
18
|
-
search_result = page.form_with(:
|
18
|
+
search_result = page.form_with(:id => 'gbqf') do |search|
|
19
19
|
search.q = 'Hello world'
|
20
20
|
end.submit
|
21
21
|
|
@@ -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://
|
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
ADDED
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
= Mechanize {<img src="https://secure.travis-ci.org/sparklemotion/mechanize.
|
1
|
+
= Mechanize {<img src="https://secure.travis-ci.org/sparklemotion/mechanize.svg?rvm=2.3.3" />}[http://travis-ci.org/sparklemotion/mechanize]
|
2
2
|
|
3
|
-
* http://
|
3
|
+
* http://docs.seattlerb.org/mechanize
|
4
4
|
* https://github.com/sparklemotion/mechanize
|
5
5
|
|
6
6
|
== Description
|
@@ -14,32 +14,26 @@ a history.
|
|
14
14
|
== Dependencies
|
15
15
|
|
16
16
|
* ruby 1.9.2 or newer
|
17
|
-
* nokogiri[
|
17
|
+
* nokogiri[https://github.com/sparklemotion/nokogiri]
|
18
18
|
|
19
19
|
== Support:
|
20
20
|
|
21
|
-
The mechanize mailing list is available here:
|
22
|
-
|
23
|
-
* http://rubyforge.org/mailman/listinfo/mechanize-users
|
24
|
-
|
25
21
|
The bug tracker is available here:
|
26
22
|
|
27
23
|
* https://github.com/sparklemotion/mechanize/issues
|
28
24
|
|
29
25
|
== Examples
|
30
26
|
|
31
|
-
If you are just starting, check out the GUIDE[http://
|
32
|
-
the EXAMPLES[http://
|
27
|
+
If you are just starting, check out the GUIDE[http://docs.seattlerb.org/mechanize/GUIDE_rdoc.html] or
|
28
|
+
the EXAMPLES[http://docs.seattlerb.org/mechanize/EXAMPLES_rdoc.html] file.
|
33
29
|
|
34
30
|
== Developers
|
35
31
|
|
36
|
-
|
32
|
+
Use bundler to install dependencies:
|
37
33
|
|
38
|
-
|
39
|
-
rake newb
|
34
|
+
bundle install
|
40
35
|
|
41
|
-
|
42
|
-
subsequent test runs:
|
36
|
+
Run all tests with:
|
43
37
|
|
44
38
|
rake test
|
45
39
|
|
@@ -54,14 +48,14 @@ Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de)
|
|
54
48
|
|
55
49
|
Copyright (c) 2006-2011:
|
56
50
|
|
57
|
-
* {Aaron Patterson}[http://tenderlovemaking.com] (
|
51
|
+
* {Aaron Patterson}[http://tenderlovemaking.com] (aaron.patterson@gmail.com)
|
58
52
|
* {Mike Dalessio}[http://mike.daless.io] (mike@csa.net)
|
59
53
|
|
60
|
-
Copyright (c) 2011-
|
54
|
+
Copyright (c) 2011-2015:
|
61
55
|
|
62
56
|
* {Eric Hodel}[http://blog.segment7.net] (drbrain@segment7.net)
|
63
57
|
* {Akinori MUSHA}[http://blog.akinori.org] (knu@idaemons.org)
|
64
|
-
* {Lee Jarvis}[http://
|
58
|
+
* {Lee Jarvis}[http://twitter.com/lee_jarvis] (ljjarvis@gmail.com)
|
65
59
|
|
66
60
|
This library comes with a shameless plug for employing me
|
67
61
|
(Aaron[http://tenderlovemaking.com/]) programming Ruby, my favorite language!
|
@@ -79,5 +73,5 @@ library!
|
|
79
73
|
|
80
74
|
== License
|
81
75
|
|
82
|
-
This library is distributed under the MIT license. Please see the LICENSE[http://
|
76
|
+
This library is distributed under the MIT license. Please see the LICENSE[http://docs.seattlerb.org/mechanize/LICENSE_rdoc.html] file.
|
83
77
|
|
data/Rakefile
CHANGED
@@ -1,38 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
hoe = Hoe.spec 'mechanize' do
|
9
|
-
developer 'Eric Hodel', 'drbrain@segment7.net'
|
10
|
-
developer 'Aaron Patterson', 'aaronp@rubyforge.org'
|
11
|
-
developer 'Mike Dalessio', 'mike.dalessio@gmail.com'
|
12
|
-
developer 'Akinori MUSHA', 'knu@idaemons.org'
|
13
|
-
developer 'Lee Jarvis', 'ljjarvis@gmail.com'
|
14
|
-
|
15
|
-
self.readme_file = 'README.rdoc'
|
16
|
-
self.history_file = 'CHANGELOG.rdoc'
|
17
|
-
self.extra_rdoc_files += Dir['*.rdoc']
|
18
|
-
|
19
|
-
rdoc_locations << 'rubyforge.org:/var/www/gforge-projects/mechanize/'
|
20
|
-
|
21
|
-
self.extra_deps << ['net-http-digest_auth', '~> 1.1', '>= 1.1.1']
|
22
|
-
self.extra_deps << ['net-http-persistent', '~> 2.5', '>= 2.5.2']
|
23
|
-
self.extra_deps << ['mime-types', '~> 1.17', '>= 1.17.2']
|
24
|
-
self.extra_deps << ['http-cookie', '~> 1.0.0']
|
25
|
-
self.extra_deps << ['nokogiri', '~> 1.4']
|
26
|
-
self.extra_deps << ['ntlm-http', '~> 0.1', '>= 0.1.1']
|
27
|
-
self.extra_deps << ['webrobots', '< 0.2', '>= 0.0.9']
|
28
|
-
self.extra_deps << ['domain_name', '~> 0.5', '>= 0.5.1']
|
29
|
-
|
30
|
-
self.extra_dev_deps << ['minitest', '~> 5.0']
|
31
|
-
|
32
|
-
self.spec_extras[:required_ruby_version] = '>= 1.8.7'
|
3
|
+
begin
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
rescue LoadError
|
33
6
|
end
|
34
7
|
|
35
|
-
task
|
8
|
+
require 'rdoc/task'
|
9
|
+
require 'rake/testtask'
|
10
|
+
|
11
|
+
task :prerelease => [:clobber_rdoc, :test]
|
36
12
|
|
37
13
|
desc "Update SSL Certificate"
|
38
14
|
task('ssl_cert') do |p|
|
@@ -46,12 +22,20 @@ task('ssl_cert') do |p|
|
|
46
22
|
sh "rm server.key.org"
|
47
23
|
end
|
48
24
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
25
|
+
RDoc::Task.new do |rdoc|
|
26
|
+
rdoc.main = "README.rdoc"
|
27
|
+
rdoc.rdoc_dir = 'doc'
|
28
|
+
rdoc.rdoc_files.include( "CHANGELOG.rdoc", "EXAMPLES.rdoc", "GUIDE.rdoc", "LICENSE.rdoc", "README.rdoc", "lib/**/*.rb")
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run tests"
|
32
|
+
Rake::TestTask.new { |t|
|
33
|
+
t.test_files = Dir['test/**/test*.rb']
|
34
|
+
t.verbose = true
|
35
|
+
}
|
36
|
+
|
37
|
+
task publish_docs: %w[rdoc] do
|
38
|
+
sh 'rsync', '-avzO', '--delete', 'doc/', 'docs-push.seattlerb.org:/data/www/docs.seattlerb.org/mechanize/'
|
56
39
|
end
|
57
40
|
|
41
|
+
task default: :test
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# This example logs a user in to
|
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,12 +9,13 @@ mech = Mechanize.new
|
|
9
9
|
mech.log = Logger.new $stderr
|
10
10
|
mech.agent.http.debug_output = $stderr
|
11
11
|
|
12
|
-
# Load the
|
13
|
-
page = mech.get('
|
14
|
-
page = mech.click page.link_with(:text => /
|
12
|
+
# Load the rubygems website
|
13
|
+
page = mech.get('https://rubygems.org/')
|
14
|
+
page = mech.click page.link_with(:text => /Sign in/) # Click the login link
|
15
15
|
form = page.forms[1] # Select the first form
|
16
|
-
form
|
17
|
-
form
|
16
|
+
form["session[who]"] = ARGV[0]
|
17
|
+
form["session[password]"] = ARGV[1]
|
18
|
+
form["commit"] = "Sign in"
|
18
19
|
|
19
20
|
# Submit the form
|
20
21
|
page = form.submit form.buttons.first
|
data/lib/mechanize.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
+
require 'mechanize/version'
|
1
2
|
require 'fileutils'
|
2
3
|
require 'forwardable'
|
3
|
-
require 'iconv' if RUBY_VERSION < '1.9.2'
|
4
|
-
require 'mime/types'
|
5
4
|
require 'mutex_m'
|
6
5
|
require 'net/http/digest_auth'
|
7
6
|
require 'net/http/persistent'
|
@@ -70,11 +69,6 @@ require 'zlib'
|
|
70
69
|
|
71
70
|
class Mechanize
|
72
71
|
|
73
|
-
##
|
74
|
-
# The version of Mechanize you are using.
|
75
|
-
|
76
|
-
VERSION = '2.7.2'
|
77
|
-
|
78
72
|
##
|
79
73
|
# Base mechanize error class
|
80
74
|
|
@@ -92,22 +86,26 @@ class Mechanize
|
|
92
86
|
# description in parenthesis is for informative purposes and is not part of
|
93
87
|
# the alias name.
|
94
88
|
#
|
95
|
-
# * Linux Firefox (
|
89
|
+
# * Linux Firefox (43.0 on Ubuntu Linux)
|
96
90
|
# * Linux Konqueror (3)
|
97
91
|
# * Linux Mozilla
|
98
|
-
# * Mac Firefox (
|
92
|
+
# * Mac Firefox (43.0)
|
99
93
|
# * Mac Mozilla
|
100
|
-
# * Mac Safari (
|
94
|
+
# * Mac Safari (9.0 on OS X 10.11.2)
|
101
95
|
# * Mac Safari 4
|
102
96
|
# * Mechanize (default)
|
103
97
|
# * Windows IE 6
|
104
98
|
# * Windows IE 7
|
105
99
|
# * Windows IE 8
|
106
100
|
# * Windows IE 9
|
101
|
+
# * Windows IE 10 (Windows 8 64bit)
|
102
|
+
# * Windows IE 11 (Windows 8.1 64bit)
|
103
|
+
# * Windows Edge
|
107
104
|
# * Windows Mozilla
|
108
|
-
# *
|
109
|
-
# *
|
110
|
-
# *
|
105
|
+
# * Windows Firefox (43.0)
|
106
|
+
# * iPhone (iOS 9.1)
|
107
|
+
# * iPad (iOS 9.1)
|
108
|
+
# * Android (5.1.1)
|
111
109
|
#
|
112
110
|
# Example:
|
113
111
|
#
|
@@ -116,26 +114,37 @@ class Mechanize
|
|
116
114
|
|
117
115
|
AGENT_ALIASES = {
|
118
116
|
'Mechanize' => "Mechanize/#{VERSION} Ruby/#{ruby_version} (http://github.com/sparklemotion/mechanize/)",
|
119
|
-
'Linux Firefox' => 'Mozilla/5.0 (X11;
|
117
|
+
'Linux Firefox' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0',
|
120
118
|
'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)',
|
121
119
|
'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624',
|
122
|
-
'Mac Firefox' => 'Mozilla/5.0 (Macintosh;
|
120
|
+
'Mac Firefox' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0',
|
123
121
|
'Mac Mozilla' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401',
|
124
122
|
'Mac Safari 4' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-at) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10',
|
125
|
-
'Mac Safari' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X
|
126
|
-
'Windows Chrome' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
123
|
+
'Mac Safari' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9',
|
124
|
+
'Windows Chrome' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36',
|
127
125
|
'Windows IE 6' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
|
128
126
|
'Windows IE 7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
|
129
127
|
'Windows IE 8' => 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
|
130
128
|
'Windows IE 9' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
|
129
|
+
'Windows IE 10' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)',
|
130
|
+
'Windows IE 11' => 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
|
131
|
+
'Windows Edge' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586',
|
131
132
|
'Windows Mozilla' => 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6',
|
132
|
-
'
|
133
|
-
'
|
134
|
-
'
|
133
|
+
'Windows Firefox' => 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0',
|
134
|
+
'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B5110e Safari/601.1',
|
135
|
+
'iPad' => 'Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
|
136
|
+
'Android' => 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.76 Safari/537.36',
|
135
137
|
}
|
136
138
|
|
137
|
-
AGENT_ALIASES
|
138
|
-
|
139
|
+
AGENT_ALIASES.default_proc = proc { |hash, key|
|
140
|
+
case key
|
141
|
+
when /FireFox/
|
142
|
+
if ua = hash[nkey = key.sub(/FireFox/, 'Firefox')]
|
143
|
+
warn "Mechanize#user_agent_alias: #{key.inspect} should be spelled as #{nkey.inspect}"
|
144
|
+
ua
|
145
|
+
end
|
146
|
+
end
|
147
|
+
}
|
139
148
|
|
140
149
|
def self.inherited(child) # :nodoc:
|
141
150
|
child.html_parser = html_parser
|
@@ -166,12 +175,20 @@ class Mechanize
|
|
166
175
|
# as SSL parameters or proxies:
|
167
176
|
#
|
168
177
|
# agent = Mechanize.new do |a|
|
169
|
-
# a.
|
178
|
+
# a.proxy_addr = 'proxy.example'
|
170
179
|
# a.proxy_port = 8080
|
171
180
|
# end
|
181
|
+
#
|
182
|
+
# If you need segregated SSL connections give each agent a unique
|
183
|
+
# name. Otherwise the connections will be shared. This is
|
184
|
+
# particularly important if you are using certifcates.
|
185
|
+
#
|
186
|
+
# agent_1 = Mechanize.new 'conn1'
|
187
|
+
# agent_2 = Mechanize.new 'conn2'
|
188
|
+
#
|
172
189
|
|
173
|
-
def initialize
|
174
|
-
@agent = Mechanize::HTTP::Agent.new
|
190
|
+
def initialize(connection_name = 'mechanize')
|
191
|
+
@agent = Mechanize::HTTP::Agent.new(connection_name)
|
175
192
|
@agent.context = self
|
176
193
|
@log = nil
|
177
194
|
|
@@ -334,12 +351,21 @@ class Mechanize
|
|
334
351
|
click real_link
|
335
352
|
else
|
336
353
|
button = nil
|
354
|
+
# Note that this will not work if we have since navigated to a different page.
|
355
|
+
# Should rather make each button aware of its parent form.
|
337
356
|
form = page.forms.find do |f|
|
338
357
|
button = f.button_with(:value => link)
|
339
358
|
button.is_a? Form::Submit
|
340
359
|
end
|
341
360
|
submit form, button if form
|
342
361
|
end
|
362
|
+
when Form::Submit, Form::ImageButton then
|
363
|
+
# Note that this will not work if we have since navigated to a different page.
|
364
|
+
# Should rather make each button aware of its parent form.
|
365
|
+
form = page.forms.find do |f|
|
366
|
+
f.buttons.include?(link)
|
367
|
+
end
|
368
|
+
submit form, link if form
|
343
369
|
else
|
344
370
|
referer = current_page()
|
345
371
|
href = link.respond_to?(:href) ? link.href :
|
@@ -370,7 +396,7 @@ class Mechanize
|
|
370
396
|
io = if io_or_filename.respond_to? :write then
|
371
397
|
io_or_filename
|
372
398
|
else
|
373
|
-
open
|
399
|
+
::File.open(io_or_filename, 'wb')
|
374
400
|
end
|
375
401
|
|
376
402
|
case page
|
@@ -392,6 +418,9 @@ class Mechanize
|
|
392
418
|
##
|
393
419
|
# DELETE +uri+ with +query_params+, and setting +headers+:
|
394
420
|
#
|
421
|
+
# +query_params+ is formatted into a query string using
|
422
|
+
# Mechanize::Util.build_query_string, which see.
|
423
|
+
#
|
395
424
|
# delete('http://example/', {'q' => 'foo'}, {})
|
396
425
|
|
397
426
|
def delete(uri, query_params = {}, headers = {})
|
@@ -405,6 +434,9 @@ class Mechanize
|
|
405
434
|
# +headers+.
|
406
435
|
#
|
407
436
|
# The +referer+ may be a URI or a page.
|
437
|
+
#
|
438
|
+
# +parameters+ is formatted into a query string using
|
439
|
+
# Mechanize::Util.build_query_string, which see.
|
408
440
|
|
409
441
|
def get(uri, parameters = [], referer = nil, headers = {})
|
410
442
|
method = :get
|
@@ -445,6 +477,9 @@ class Mechanize
|
|
445
477
|
##
|
446
478
|
# HEAD +uri+ with +query_params+ and +headers+:
|
447
479
|
#
|
480
|
+
# +query_params+ is formatted into a query string using
|
481
|
+
# Mechanize::Util.build_query_string, which see.
|
482
|
+
#
|
448
483
|
# head('http://example/', {'q' => 'foo'}, {})
|
449
484
|
|
450
485
|
def head(uri, query_params = {}, headers = {})
|
@@ -456,9 +491,13 @@ class Mechanize
|
|
456
491
|
end
|
457
492
|
|
458
493
|
##
|
459
|
-
# POST to the given +uri+ with the given +query+.
|
460
|
-
#
|
461
|
-
#
|
494
|
+
# POST to the given +uri+ with the given +query+.
|
495
|
+
#
|
496
|
+
# +query+ is processed using Mechanize::Util.each_parameter (which
|
497
|
+
# see), and then encoded into an entity body. If any IO/FileUpload
|
498
|
+
# object is specified as a field value the "enctype" will be
|
499
|
+
# multipart/form-data, or application/x-www-form-urlencoded
|
500
|
+
# otherwise.
|
462
501
|
#
|
463
502
|
# Examples:
|
464
503
|
# agent.post 'http://example.com/', "foo" => "bar"
|
@@ -481,12 +520,15 @@ class Mechanize
|
|
481
520
|
|
482
521
|
form = Form.new(node)
|
483
522
|
|
484
|
-
query
|
523
|
+
Mechanize::Util.each_parameter(query) { |k, v|
|
485
524
|
if v.is_a?(IO)
|
486
525
|
form.enctype = 'multipart/form-data'
|
487
526
|
ul = Form::FileUpload.new({'name' => k.to_s},::File.basename(v.path))
|
488
527
|
ul.file_data = v.read
|
489
528
|
form.file_uploads << ul
|
529
|
+
elsif v.is_a?(Form::FileUpload)
|
530
|
+
form.enctype = 'multipart/form-data'
|
531
|
+
form.file_uploads << v
|
490
532
|
else
|
491
533
|
form.fields << Form::Field.new({'name' => k.to_s},v)
|
492
534
|
end
|
@@ -510,6 +552,8 @@ class Mechanize
|
|
510
552
|
def request_with_entity(verb, uri, entity, headers = {})
|
511
553
|
cur_page = current_page || Page.new
|
512
554
|
|
555
|
+
log.debug("query: #{ entity.inspect }") if log
|
556
|
+
|
513
557
|
headers = {
|
514
558
|
'Content-Type' => 'application/octet-stream',
|
515
559
|
'Content-Length' => entity.size.to_s,
|
@@ -926,6 +970,12 @@ Use of #auth and #basic_auth are deprecated due to a security vulnerability.
|
|
926
970
|
@agent.redirection_limit = limit
|
927
971
|
end
|
928
972
|
|
973
|
+
##
|
974
|
+
# Resolve the full path of a link / uri
|
975
|
+
def resolve link
|
976
|
+
@agent.resolve link
|
977
|
+
end
|
978
|
+
|
929
979
|
##
|
930
980
|
# A hash of custom request headers that will be sent on every request
|
931
981
|
|
@@ -1130,19 +1180,19 @@ Use of #auth and #basic_auth are deprecated due to a security vulnerability.
|
|
1130
1180
|
end
|
1131
1181
|
|
1132
1182
|
##
|
1133
|
-
# SSL version to use.
|
1183
|
+
# SSL version to use.
|
1134
1184
|
|
1135
1185
|
def ssl_version
|
1136
1186
|
@agent.ssl_version
|
1137
|
-
end
|
1187
|
+
end
|
1138
1188
|
|
1139
1189
|
##
|
1140
1190
|
# Sets the SSL version to use to +version+ without client/server
|
1141
|
-
# negotiation.
|
1191
|
+
# negotiation.
|
1142
1192
|
|
1143
1193
|
def ssl_version= ssl_version
|
1144
1194
|
@agent.ssl_version = ssl_version
|
1145
|
-
end
|
1195
|
+
end
|
1146
1196
|
|
1147
1197
|
##
|
1148
1198
|
# A callback for additional certificate verification. See
|
@@ -1285,6 +1335,7 @@ Use of #auth and #basic_auth are deprecated due to a security vulnerability.
|
|
1285
1335
|
|
1286
1336
|
end
|
1287
1337
|
|
1338
|
+
require 'mechanize/element_not_found_error'
|
1288
1339
|
require 'mechanize/response_read_error'
|
1289
1340
|
require 'mechanize/chunked_termination_error'
|
1290
1341
|
require 'mechanize/content_type_error'
|
@@ -1307,7 +1358,6 @@ require 'mechanize/http/content_disposition_parser'
|
|
1307
1358
|
require 'mechanize/http/www_authenticate_parser'
|
1308
1359
|
require 'mechanize/image'
|
1309
1360
|
require 'mechanize/page'
|
1310
|
-
require 'mechanize/monkey_patch'
|
1311
1361
|
require 'mechanize/pluggable_parsers'
|
1312
1362
|
require 'mechanize/redirect_limit_reached_error'
|
1313
1363
|
require 'mechanize/redirect_not_get_or_head_error'
|