mechanize 2.7.4 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ci-test.yml +45 -0
- data/.yardopts +8 -0
- data/{CHANGELOG.rdoc → CHANGELOG.md} +151 -86
- data/EXAMPLES.rdoc +1 -24
- data/Gemfile +1 -1
- data/{LICENSE.rdoc → LICENSE.txt} +4 -0
- data/README.md +77 -0
- data/Rakefile +18 -3
- data/examples/rubygems.rb +2 -2
- data/lib/mechanize.rb +3 -2
- data/lib/mechanize/chunked_termination_error.rb +1 -0
- data/lib/mechanize/content_type_error.rb +1 -0
- data/lib/mechanize/cookie.rb +1 -13
- data/lib/mechanize/cookie_jar.rb +4 -12
- data/lib/mechanize/directory_saver.rb +1 -0
- data/lib/mechanize/download.rb +2 -1
- data/lib/mechanize/element_matcher.rb +5 -1
- data/lib/mechanize/element_not_found_error.rb +1 -0
- data/lib/mechanize/file.rb +2 -1
- data/lib/mechanize/file_connection.rb +5 -3
- data/lib/mechanize/file_request.rb +1 -0
- data/lib/mechanize/file_response.rb +4 -1
- data/lib/mechanize/file_saver.rb +1 -0
- data/lib/mechanize/form.rb +112 -45
- data/lib/mechanize/form/button.rb +1 -0
- data/lib/mechanize/form/check_box.rb +1 -0
- data/lib/mechanize/form/field.rb +47 -0
- data/lib/mechanize/form/file_upload.rb +1 -0
- data/lib/mechanize/form/hidden.rb +1 -0
- data/lib/mechanize/form/image_button.rb +1 -0
- data/lib/mechanize/form/keygen.rb +1 -0
- data/lib/mechanize/form/multi_select_list.rb +8 -14
- data/lib/mechanize/form/option.rb +3 -1
- data/lib/mechanize/form/radio_button.rb +1 -0
- data/lib/mechanize/form/reset.rb +1 -0
- data/lib/mechanize/form/select_list.rb +1 -0
- data/lib/mechanize/form/submit.rb +1 -0
- data/lib/mechanize/form/text.rb +1 -0
- data/lib/mechanize/form/textarea.rb +1 -0
- data/lib/mechanize/headers.rb +1 -0
- data/lib/mechanize/history.rb +2 -1
- data/lib/mechanize/http.rb +1 -0
- data/lib/mechanize/http/agent.rb +81 -38
- data/lib/mechanize/http/auth_challenge.rb +1 -0
- data/lib/mechanize/http/auth_realm.rb +2 -1
- data/lib/mechanize/http/auth_store.rb +1 -0
- data/lib/mechanize/http/content_disposition_parser.rb +18 -3
- data/lib/mechanize/http/www_authenticate_parser.rb +4 -4
- data/lib/mechanize/image.rb +1 -0
- data/lib/mechanize/page.rb +8 -5
- data/lib/mechanize/page/base.rb +1 -0
- data/lib/mechanize/page/frame.rb +4 -1
- data/lib/mechanize/page/image.rb +1 -0
- data/lib/mechanize/page/label.rb +1 -0
- data/lib/mechanize/page/link.rb +8 -1
- data/lib/mechanize/page/meta_refresh.rb +1 -0
- data/lib/mechanize/parser.rb +4 -3
- data/lib/mechanize/pluggable_parsers.rb +1 -0
- data/lib/mechanize/prependable.rb +1 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
- data/lib/mechanize/response_code_error.rb +2 -1
- data/lib/mechanize/response_read_error.rb +1 -0
- data/lib/mechanize/robots_disallowed_error.rb +1 -0
- data/lib/mechanize/test_case.rb +34 -29
- data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
- data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
- data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
- data/lib/mechanize/test_case/form_servlet.rb +1 -0
- data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
- data/lib/mechanize/test_case/header_servlet.rb +1 -0
- data/lib/mechanize/test_case/http_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
- data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
- data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/referer_servlet.rb +1 -0
- data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
- data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
- data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
- data/lib/mechanize/test_case/robots_txt_servlet.rb +15 -0
- data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/server.rb +1 -0
- data/lib/mechanize/test_case/servlets.rb +4 -0
- data/lib/mechanize/test_case/verb_servlet.rb +5 -6
- data/lib/mechanize/unauthorized_error.rb +2 -1
- data/lib/mechanize/unsupported_scheme_error.rb +1 -0
- data/lib/mechanize/util.rb +5 -3
- data/lib/mechanize/version.rb +2 -1
- data/lib/mechanize/xml_file.rb +1 -0
- data/mechanize.gemspec +39 -31
- data/test/htdocs/dir with spaces/foo.html +1 -0
- data/test/htdocs/find_link.html +1 -4
- data/test/htdocs/tc_links.html +1 -1
- data/test/test_mechanize.rb +57 -15
- data/test/test_mechanize_cookie.rb +75 -60
- data/test/test_mechanize_cookie_jar.rb +112 -59
- data/test/test_mechanize_download.rb +13 -1
- data/test/test_mechanize_file.rb +10 -0
- data/test/test_mechanize_file_connection.rb +21 -3
- data/test/test_mechanize_file_response.rb +26 -2
- data/test/test_mechanize_form.rb +27 -11
- data/test/test_mechanize_form_check_box.rb +10 -0
- data/test/test_mechanize_form_encoding.rb +1 -1
- 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 +116 -8
- 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 +35 -1
- data/test/test_mechanize_http_www_authenticate_parser.rb +16 -0
- data/test/test_mechanize_link.rb +47 -4
- data/test/test_mechanize_page.rb +29 -1
- data/test/test_mechanize_page_encoding.rb +23 -1
- data/test/test_mechanize_page_image.rb +1 -1
- data/test/test_mechanize_page_link.rb +3 -3
- data/test/test_mechanize_page_meta_refresh.rb +1 -1
- data/test/test_mechanize_parser.rb +12 -2
- data/test/test_mechanize_util.rb +1 -1
- metadata +105 -81
- data/.travis.yml +0 -25
- data/Manifest.txt +0 -204
- data/README.rdoc +0 -77
- data/test/htdocs/robots.txt +0 -2
|
@@ -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
|
|
data/test/test_mechanize_file.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,11 +1,15 @@
|
|
|
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
|
|
4
8
|
|
|
5
9
|
def test_content_type
|
|
6
10
|
Tempfile.open %w[pi .nothtml] do |tempfile|
|
|
7
11
|
res = Mechanize::FileResponse.new tempfile.path
|
|
8
|
-
|
|
12
|
+
assert_nil res['content-type']
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
Tempfile.open %w[pi .xhtml] do |tempfile|
|
|
@@ -19,5 +23,25 @@ class TestMechanizeFileResponse < Mechanize::TestCase
|
|
|
19
23
|
end
|
|
20
24
|
end
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
def test_read_body
|
|
27
|
+
Tempfile.open %w[pi .html] do |tempfile|
|
|
28
|
+
tempfile.write("asdfasdfasdf")
|
|
29
|
+
tempfile.close
|
|
23
30
|
|
|
31
|
+
res = Mechanize::FileResponse.new(tempfile.path)
|
|
32
|
+
res.read_body do |input|
|
|
33
|
+
assert_equal("asdfasdfasdf", input)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_read_body_does_not_allow_command_injection
|
|
39
|
+
skip if windows?
|
|
40
|
+
in_tmpdir do
|
|
41
|
+
FileUtils.touch('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
|
|
42
|
+
res = Mechanize::FileResponse.new('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
|
|
43
|
+
res.read_body { |_| }
|
|
44
|
+
refute_operator(File, :exist?, "vul.txt")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/test/test_mechanize_form.rb
CHANGED
|
@@ -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>
|
|
@@ -214,7 +226,7 @@ class TestMechanizeForm < Mechanize::TestCase
|
|
|
214
226
|
|
|
215
227
|
@form['name'] = 'Aaron'
|
|
216
228
|
|
|
217
|
-
|
|
229
|
+
assert_equal true, @form.has_field?('name')
|
|
218
230
|
end
|
|
219
231
|
|
|
220
232
|
def test_has_value_eh
|
|
@@ -222,7 +234,7 @@ class TestMechanizeForm < Mechanize::TestCase
|
|
|
222
234
|
|
|
223
235
|
@form['name'] = 'Aaron'
|
|
224
236
|
|
|
225
|
-
|
|
237
|
+
assert_equal true, @form.has_value?('Aaron')
|
|
226
238
|
end
|
|
227
239
|
|
|
228
240
|
def test_keys
|
|
@@ -863,15 +875,19 @@ class TestMechanizeForm < Mechanize::TestCase
|
|
|
863
875
|
def test_form_and_fields_dom_id
|
|
864
876
|
# blatant copypasta of test above
|
|
865
877
|
page = @mech.get("http://localhost/form_test.html")
|
|
866
|
-
form = page.form_with(:
|
|
867
|
-
|
|
878
|
+
form = page.form_with(dom_id: 'generic_form')
|
|
879
|
+
|
|
880
|
+
assert_equal(1, form.fields_with(dom_id: 'name_first').length)
|
|
881
|
+
assert_equal('first_name', form.field_with(dom_id: 'name_first').name)
|
|
868
882
|
|
|
869
|
-
assert_equal(
|
|
870
|
-
assert_equal(
|
|
883
|
+
assert_equal(form, page.form_with(id: 'generic_form'))
|
|
884
|
+
assert_equal(form, page.form_with(css: '#generic_form'))
|
|
871
885
|
|
|
872
|
-
|
|
873
|
-
assert_equal(
|
|
874
|
-
assert_equal(
|
|
886
|
+
fields_by_dom_id = form.fields_with(dom_id: 'name_first')
|
|
887
|
+
assert_equal(fields_by_dom_id, form.fields_with(id: 'name_first'))
|
|
888
|
+
assert_equal(fields_by_dom_id, form.fields_with(css: '#name_first'))
|
|
889
|
+
assert_equal(fields_by_dom_id, form.fields_with(xpath: '//*[@id="name_first"]'))
|
|
890
|
+
assert_equal(fields_by_dom_id, form.fields_with(search: '//*[@id="name_first"]'))
|
|
875
891
|
end
|
|
876
892
|
|
|
877
893
|
def test_form_and_fields_dom_class
|
|
@@ -914,9 +930,9 @@ class TestMechanizeForm < Mechanize::TestCase
|
|
|
914
930
|
page = @mech.get("http://localhost/form_multival.html")
|
|
915
931
|
form = page.form_with(:name => 'post_form')
|
|
916
932
|
|
|
917
|
-
|
|
933
|
+
assert_equal false, form.has_field?('intarweb')
|
|
918
934
|
assert form.add_field!('intarweb')
|
|
919
|
-
|
|
935
|
+
assert_equal true, form.has_field?('intarweb')
|
|
920
936
|
end
|
|
921
937
|
|
|
922
938
|
def test_fill_unexisting_form
|
|
@@ -8,6 +8,16 @@ class TestMechanizeFormCheckBox < Mechanize::TestCase
|
|
|
8
8
|
@page = @mech.get('http://localhost/tc_checkboxes.html')
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def test_search
|
|
12
|
+
form = @page.forms.first
|
|
13
|
+
|
|
14
|
+
checkbox = form.checkbox_with(name: 'green')
|
|
15
|
+
assert_equal('green', checkbox.name)
|
|
16
|
+
|
|
17
|
+
assert_equal(checkbox, form.checkbox_with('green'))
|
|
18
|
+
assert_equal(checkbox, form.checkbox_with(search: 'input[@type=checkbox][@name=green]'))
|
|
19
|
+
end
|
|
20
|
+
|
|
11
21
|
def test_check
|
|
12
22
|
form = @page.forms.first
|
|
13
23
|
|
|
@@ -67,7 +67,7 @@ class TestMechanizeFormEncoding < Mechanize::TestCase
|
|
|
67
67
|
node['enctype'] = 'application/x-www-form-urlencoded'
|
|
68
68
|
form = Mechanize::Form.new(node)
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
assert_nil form.encoding
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def test_post_form_with_form_encoding
|
|
@@ -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
|
|
@@ -32,9 +32,13 @@ class TestMechanizeFormMultiSelectList < Mechanize::TestCase
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def test_option_with
|
|
35
|
-
option = @select.option_with :
|
|
35
|
+
option = @select.option_with value: '1'
|
|
36
36
|
|
|
37
37
|
assert_equal '1', option.value
|
|
38
|
+
|
|
39
|
+
option = @select.option_with search: 'option[@selected]'
|
|
40
|
+
|
|
41
|
+
assert_equal '2', option.value
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
def test_options_with
|
|
@@ -16,11 +16,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
16
16
|
@res.instance_variable_set :@code, 200
|
|
17
17
|
@res.instance_variable_set :@header, {}
|
|
18
18
|
|
|
19
|
-
@headers =
|
|
20
|
-
%w[accept accept-encoding user-agent]
|
|
21
|
-
else
|
|
22
|
-
%w[accept user-agent]
|
|
23
|
-
end
|
|
19
|
+
@headers = %w[accept accept-encoding user-agent]
|
|
24
20
|
end
|
|
25
21
|
|
|
26
22
|
def auth_realm uri, scheme, type
|
|
@@ -205,7 +201,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
205
201
|
|
|
206
202
|
page = @agent.fetch uri
|
|
207
203
|
|
|
208
|
-
assert_equal File.read(foo), page.body
|
|
204
|
+
assert_equal File.read(foo), page.body.gsub(/\r\n/, "\n")
|
|
209
205
|
assert_kind_of Mechanize::Page, page
|
|
210
206
|
end
|
|
211
207
|
|
|
@@ -682,6 +678,14 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
682
678
|
assert_equal 'absolute URL needed (not google)', e.message
|
|
683
679
|
end
|
|
684
680
|
|
|
681
|
+
def test_resolve_uri_without_path
|
|
682
|
+
e = assert_raises ArgumentError do
|
|
683
|
+
@agent.resolve 'http:%5C%5Cfoo'
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
assert_equal 'hierarchical URL needed (not http:%5C%5Cfoo)', e.message
|
|
687
|
+
end
|
|
688
|
+
|
|
685
689
|
def test_resolve_utf8
|
|
686
690
|
uri = 'http://example?q=ü'
|
|
687
691
|
|
|
@@ -927,7 +931,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
927
931
|
body_io = StringIO.new \
|
|
928
932
|
"\037\213\b\0002\002\225M\000\003+H,*\001"
|
|
929
933
|
|
|
930
|
-
|
|
934
|
+
skip if jruby_zlib?
|
|
931
935
|
|
|
932
936
|
e = assert_raises Mechanize::Error do
|
|
933
937
|
@agent.response_content_encoding @res, body_io
|
|
@@ -1057,6 +1061,14 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1057
1061
|
assert_equal 'part', body.read
|
|
1058
1062
|
end
|
|
1059
1063
|
|
|
1064
|
+
def test_response_content_encoding_identity
|
|
1065
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[identity]
|
|
1066
|
+
|
|
1067
|
+
body = @agent.response_content_encoding @res, StringIO.new('part')
|
|
1068
|
+
|
|
1069
|
+
assert_equal 'part', body.read
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1060
1072
|
def test_response_content_encoding_tempfile_7_bit
|
|
1061
1073
|
body_io = tempfile 'part'
|
|
1062
1074
|
|
|
@@ -1492,7 +1504,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1492
1504
|
headers = {
|
|
1493
1505
|
'Range' => 'bytes=0-9999',
|
|
1494
1506
|
'Content-Type' => 'application/x-www-form-urlencoded',
|
|
1495
|
-
'
|
|
1507
|
+
'CONTENT-LENGTH' => '9999',
|
|
1508
|
+
'content-md5' => '14758f1afd44c09b7992073ccf00b43d',
|
|
1496
1509
|
}
|
|
1497
1510
|
|
|
1498
1511
|
page = fake_page
|
|
@@ -1504,6 +1517,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1504
1517
|
assert_match 'range|bytes=0-9999', page.body
|
|
1505
1518
|
refute_match 'content-type|application/x-www-form-urlencoded', page.body
|
|
1506
1519
|
refute_match 'content-length|9999', page.body
|
|
1520
|
+
refute_match 'content-md5|14758f1afd44c09b7992073ccf00b43d', page.body
|
|
1507
1521
|
end
|
|
1508
1522
|
|
|
1509
1523
|
def test_response_redirect_malformed
|
|
@@ -1539,6 +1553,48 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1539
1553
|
end
|
|
1540
1554
|
end
|
|
1541
1555
|
|
|
1556
|
+
def test_response_redirect_to_cross_site_with_credential
|
|
1557
|
+
@agent.redirect_ok = true
|
|
1558
|
+
|
|
1559
|
+
headers = {
|
|
1560
|
+
'Range' => 'bytes=0-9999',
|
|
1561
|
+
'AUTHORIZATION' => 'Basic xxx',
|
|
1562
|
+
'cookie' => 'name=value',
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
page = html_page ''
|
|
1566
|
+
page = @agent.response_redirect({ 'Location' => 'http://trap/http_headers' }, :get,
|
|
1567
|
+
page, 0, headers)
|
|
1568
|
+
|
|
1569
|
+
refute_includes(headers.keys, "AUTHORIZATION")
|
|
1570
|
+
refute_includes(headers.keys, "cookie")
|
|
1571
|
+
|
|
1572
|
+
assert_match 'range|bytes=0-9999', page.body
|
|
1573
|
+
refute_match("authorization|Basic xxx", page.body)
|
|
1574
|
+
refute_match("cookie|name=value", page.body)
|
|
1575
|
+
end
|
|
1576
|
+
|
|
1577
|
+
def test_response_redirect_to_same_site_with_credential
|
|
1578
|
+
@agent.redirect_ok = true
|
|
1579
|
+
|
|
1580
|
+
headers = {
|
|
1581
|
+
'Range' => 'bytes=0-9999',
|
|
1582
|
+
'AUTHORIZATION' => 'Basic xxx',
|
|
1583
|
+
'cookie' => 'name=value',
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
page = html_page ''
|
|
1587
|
+
page = @agent.response_redirect({ 'Location' => '/http_headers' }, :get,
|
|
1588
|
+
page, 0, headers)
|
|
1589
|
+
|
|
1590
|
+
assert_includes(headers.keys, "AUTHORIZATION")
|
|
1591
|
+
assert_includes(headers.keys, "cookie")
|
|
1592
|
+
|
|
1593
|
+
assert_match 'range|bytes=0-9999', page.body
|
|
1594
|
+
assert_match("authorization|Basic xxx", page.body)
|
|
1595
|
+
assert_match("cookie|name=value", page.body)
|
|
1596
|
+
end
|
|
1597
|
+
|
|
1542
1598
|
def test_response_redirect_not_ok
|
|
1543
1599
|
@agent.redirect_ok = false
|
|
1544
1600
|
|
|
@@ -1574,6 +1630,11 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1574
1630
|
end
|
|
1575
1631
|
|
|
1576
1632
|
def test_retry_change_request_equals
|
|
1633
|
+
unless Gem::Requirement.new("< 4.0.0").satisfied_by?(Gem::Version.new(Net::HTTP::Persistent::VERSION))
|
|
1634
|
+
# see https://github.com/drbrain/net-http-persistent/pull/100
|
|
1635
|
+
skip("net-http-persistent 4.0.0 and later does not support retry_change_requests")
|
|
1636
|
+
end
|
|
1637
|
+
|
|
1577
1638
|
refute @agent.http.retry_change_requests
|
|
1578
1639
|
|
|
1579
1640
|
@agent.retry_change_requests = true
|
|
@@ -1604,6 +1665,17 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1604
1665
|
end
|
|
1605
1666
|
end
|
|
1606
1667
|
|
|
1668
|
+
def test_robots_infinite_loop
|
|
1669
|
+
@agent.robots = true
|
|
1670
|
+
@agent.redirect_ok = true
|
|
1671
|
+
|
|
1672
|
+
assert_raises Mechanize::RobotsDisallowedError do
|
|
1673
|
+
@agent.fetch URI('http://301/norobots.html')
|
|
1674
|
+
end
|
|
1675
|
+
|
|
1676
|
+
@agent.fetch URI('http://301/robots.html')
|
|
1677
|
+
end
|
|
1678
|
+
|
|
1607
1679
|
def test_set_proxy
|
|
1608
1680
|
@agent.set_proxy 'www.example.com', 9001, 'joe', 'lol'
|
|
1609
1681
|
|
|
@@ -1639,6 +1711,42 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
|
|
|
1639
1711
|
assert_equal 'invalid value for port: "nonexistent service"', e.message
|
|
1640
1712
|
end
|
|
1641
1713
|
|
|
1714
|
+
def test_set_proxy_with_scheme
|
|
1715
|
+
@agent.set_proxy 'http://www.example.com', 9001, 'joe', 'lol'
|
|
1716
|
+
|
|
1717
|
+
assert_equal @agent.proxy_uri.host, 'www.example.com'
|
|
1718
|
+
assert_equal @agent.proxy_uri.port, 9001
|
|
1719
|
+
assert_equal @agent.proxy_uri.user, 'joe'
|
|
1720
|
+
assert_equal @agent.proxy_uri.password, 'lol'
|
|
1721
|
+
end
|
|
1722
|
+
|
|
1723
|
+
def test_set_proxy_url
|
|
1724
|
+
@agent.set_proxy 'http://joe:lol@www.example.com:9001'
|
|
1725
|
+
|
|
1726
|
+
assert_equal @agent.proxy_uri.host, 'www.example.com'
|
|
1727
|
+
assert_equal @agent.proxy_uri.port, 9001
|
|
1728
|
+
assert_equal @agent.proxy_uri.user, 'joe'
|
|
1729
|
+
assert_equal @agent.proxy_uri.password, 'lol'
|
|
1730
|
+
end
|
|
1731
|
+
|
|
1732
|
+
def test_set_proxy_uri
|
|
1733
|
+
@agent.set_proxy URI('http://joe:lol@www.example.com:9001')
|
|
1734
|
+
|
|
1735
|
+
assert_equal @agent.proxy_uri.host, 'www.example.com'
|
|
1736
|
+
assert_equal @agent.proxy_uri.port, 9001
|
|
1737
|
+
assert_equal @agent.proxy_uri.user, 'joe'
|
|
1738
|
+
assert_equal @agent.proxy_uri.password, 'lol'
|
|
1739
|
+
end
|
|
1740
|
+
|
|
1741
|
+
def test_set_proxy_url_and_credentials
|
|
1742
|
+
@agent.set_proxy 'http://www.example.com:9001', nil, 'joe', 'lol'
|
|
1743
|
+
|
|
1744
|
+
assert_equal @agent.proxy_uri.host, 'www.example.com'
|
|
1745
|
+
assert_equal @agent.proxy_uri.port, 9001
|
|
1746
|
+
assert_equal @agent.proxy_uri.user, 'joe'
|
|
1747
|
+
assert_equal @agent.proxy_uri.password, 'lol'
|
|
1748
|
+
end
|
|
1749
|
+
|
|
1642
1750
|
def test_setting_agent_name
|
|
1643
1751
|
mech = Mechanize.new 'user-set-name'
|
|
1644
1752
|
assert_equal 'user-set-name', mech.agent.http.name
|