mechanize 2.4 → 2.5
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.
Potentially problematic release.
This version of mechanize might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/CHANGELOG.rdoc +30 -4
- data/EXAMPLES.rdoc +2 -2
- data/GUIDE.rdoc +13 -13
- data/Manifest.txt +30 -0
- data/README.rdoc +19 -2
- data/lib/mechanize.rb +30 -7
- data/lib/mechanize/chunked_termination_error.rb +7 -0
- data/lib/mechanize/form.rb +7 -5
- data/lib/mechanize/form/radio_button.rb +14 -0
- data/lib/mechanize/http/agent.rb +54 -24
- data/lib/mechanize/http/auth_store.rb +6 -0
- data/lib/mechanize/http/content_disposition_parser.rb +1 -1
- data/lib/mechanize/monkey_patch.rb +3 -2
- data/lib/mechanize/page.rb +0 -2
- data/lib/mechanize/parser.rb +2 -2
- data/lib/mechanize/test_case.rb +70 -435
- data/lib/mechanize/test_case/.document +1 -0
- data/lib/mechanize/test_case/bad_chunking_servlet.rb +14 -0
- data/lib/mechanize/test_case/basic_auth_servlet.rb +24 -0
- data/lib/mechanize/test_case/content_type_servlet.rb +8 -0
- data/lib/mechanize/test_case/digest_auth_servlet.rb +33 -0
- data/lib/mechanize/test_case/file_upload_servlet.rb +20 -0
- data/lib/mechanize/test_case/form_servlet.rb +55 -0
- data/lib/mechanize/test_case/gzip_servlet.rb +32 -0
- data/lib/mechanize/test_case/header_servlet.rb +14 -0
- data/lib/mechanize/test_case/http_refresh_servlet.rb +9 -0
- data/lib/mechanize/test_case/infinite_redirect_servlet.rb +10 -0
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +10 -0
- data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +37 -0
- data/lib/mechanize/test_case/many_cookies_servlet.rb +33 -0
- data/lib/mechanize/test_case/modified_since_servlet.rb +21 -0
- data/lib/mechanize/test_case/ntlm_servlet.rb +30 -0
- data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +11 -0
- data/lib/mechanize/test_case/one_cookie_servlet.rb +11 -0
- data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +11 -0
- data/lib/mechanize/test_case/redirect_servlet.rb +13 -0
- data/lib/mechanize/test_case/referer_servlet.rb +12 -0
- data/lib/mechanize/test_case/refresh_with_empty_url.rb +15 -0
- data/lib/mechanize/test_case/refresh_without_url.rb +14 -0
- data/lib/mechanize/test_case/response_code_servlet.rb +15 -0
- data/lib/mechanize/test_case/send_cookies_servlet.rb +19 -0
- data/lib/mechanize/test_case/server.rb +36 -0
- data/lib/mechanize/test_case/servlets.rb +55 -0
- data/lib/mechanize/test_case/verb_servlet.rb +11 -0
- data/test/test_mechanize.rb +12 -12
- data/test/test_mechanize_file.rb +11 -0
- data/test/test_mechanize_file_response.rb +23 -0
- data/test/test_mechanize_form.rb +34 -0
- data/test/test_mechanize_form_radio_button.rb +19 -2
- data/test/test_mechanize_http_agent.rb +104 -26
- data/test/test_mechanize_http_auth_store.rb +23 -0
- data/test/test_mechanize_http_content_disposition_parser.rb +6 -0
- data/test/test_mechanize_page.rb +3 -5
- data/test/test_mechanize_page_link.rb +0 -32
- metadata +39 -8
- metadata.gz.sig +2 -2
@@ -0,0 +1 @@
|
|
1
|
+
# Don't document this directory
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class BadChunkingServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET req, res
|
3
|
+
res.keep_alive = false if res.respond_to? :keep_alive=
|
4
|
+
|
5
|
+
res['Transfer-Encoding'] = 'chunked'
|
6
|
+
|
7
|
+
res.body = <<-BODY
|
8
|
+
a\r
|
9
|
+
0123456789\r
|
10
|
+
0\r
|
11
|
+
BODY
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class BasicAuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req,res)
|
3
|
+
htpd = nil
|
4
|
+
Tempfile.open 'dot.htpasswd' do |io|
|
5
|
+
htpd = WEBrick::HTTPAuth::Htpasswd.new(io.path)
|
6
|
+
htpd.set_passwd('Blah', 'user', 'pass')
|
7
|
+
end
|
8
|
+
|
9
|
+
authenticator = WEBrick::HTTPAuth::BasicAuth.new({
|
10
|
+
:UserDB => htpd,
|
11
|
+
:Realm => 'Blah',
|
12
|
+
:Logger => Logger.new(nil)
|
13
|
+
})
|
14
|
+
|
15
|
+
begin
|
16
|
+
authenticator.authenticate(req,res)
|
17
|
+
res.body = 'You are authenticated'
|
18
|
+
rescue WEBrick::HTTPStatus::Unauthorized
|
19
|
+
res.status = 401
|
20
|
+
end
|
21
|
+
end
|
22
|
+
alias :do_POST :do_GET
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class DigestAuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
4
|
+
htpd = nil
|
5
|
+
|
6
|
+
Tempfile.open 'digest.htpasswd' do |io|
|
7
|
+
htpd = WEBrick::HTTPAuth::Htdigest.new(io.path)
|
8
|
+
htpd.set_passwd('Blah', 'user', 'pass')
|
9
|
+
end
|
10
|
+
|
11
|
+
@@authenticator = WEBrick::HTTPAuth::DigestAuth.new({
|
12
|
+
:UserDB => htpd,
|
13
|
+
:Realm => 'Blah',
|
14
|
+
:Algorithm => 'MD5',
|
15
|
+
:Logger => Logger.new(nil)
|
16
|
+
})
|
17
|
+
|
18
|
+
def do_GET(req,res)
|
19
|
+
def req.request_time; Time.now; end
|
20
|
+
def req.request_uri; '/digest_auth'; end
|
21
|
+
def req.request_method; "GET"; end
|
22
|
+
|
23
|
+
begin
|
24
|
+
@@authenticator.authenticate(req,res)
|
25
|
+
res.body = 'You are authenticated'
|
26
|
+
rescue WEBrick::HTTPStatus::Unauthorized
|
27
|
+
res.status = 401
|
28
|
+
end
|
29
|
+
FileUtils.rm('digest.htpasswd') if File.exists?('digest.htpasswd')
|
30
|
+
end
|
31
|
+
alias :do_POST :do_GET
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class FileUploadServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_POST req, res
|
3
|
+
res.body = req.body
|
4
|
+
end
|
5
|
+
|
6
|
+
def do_GET req, res
|
7
|
+
res.content_type = 'text/html'
|
8
|
+
res.body = <<-BODY
|
9
|
+
<!DOCTYPE html>
|
10
|
+
<title>Fill in this form</title>
|
11
|
+
<p>You can POST anything to this endpoint, though
|
12
|
+
|
13
|
+
<form method="POST">
|
14
|
+
<textarea name="text"></textarea>
|
15
|
+
<input type="submit">
|
16
|
+
</form>
|
17
|
+
BODY
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class FormServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
res.content_type = 'text/html'
|
4
|
+
|
5
|
+
query = []
|
6
|
+
|
7
|
+
req.query.each_key { |k|
|
8
|
+
key = WEBrick::HTTPUtils.unescape k
|
9
|
+
|
10
|
+
req.query[k].each_data { |data|
|
11
|
+
value = WEBrick::HTTPUtils.unescape data
|
12
|
+
query << "<li><a href=\"#\">#{key}:#{value}</a>"
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
res.body = <<-BODY
|
17
|
+
<!DOCTYPE html>
|
18
|
+
<title>GET results</title>
|
19
|
+
|
20
|
+
<ul>
|
21
|
+
#{query.join "\n"}
|
22
|
+
</ul>
|
23
|
+
|
24
|
+
<div id=\"query\">#{req.query}</div>
|
25
|
+
BODY
|
26
|
+
end
|
27
|
+
|
28
|
+
def do_POST(req, res)
|
29
|
+
res.content_type = 'text/html'
|
30
|
+
|
31
|
+
query = []
|
32
|
+
|
33
|
+
req.query.each_key { |k|
|
34
|
+
key = WEBrick::HTTPUtils.unescape k
|
35
|
+
|
36
|
+
req.query[k].each_data { |data|
|
37
|
+
value = WEBrick::HTTPUtils.unescape data
|
38
|
+
query << "<li><a href=\"#\">#{key}:#{value}</a>"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
res.body = <<-BODY
|
43
|
+
<!DOCTYPE html>
|
44
|
+
<title>POST results</title>
|
45
|
+
|
46
|
+
<ul>
|
47
|
+
#{query.join "\n"}
|
48
|
+
</ul>
|
49
|
+
|
50
|
+
<div id=\"query\">#{req.body}</div>
|
51
|
+
BODY
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
|
5
|
+
|
6
|
+
TEST_DIR = File.expand_path '../../../../test', __FILE__
|
7
|
+
|
8
|
+
def do_GET(req, res)
|
9
|
+
if req['Accept-Encoding'] !~ /gzip/ then
|
10
|
+
res.code = 400
|
11
|
+
res.body = 'Content-Encoding: gzip is not supported by your user-agent'
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
if name = req.query['file'] then
|
16
|
+
open "#{TEST_DIR}/htdocs/#{name}" do |io|
|
17
|
+
string = ""
|
18
|
+
zipped = StringIO.new string, 'w'
|
19
|
+
Zlib::GzipWriter.wrap zipped do |gz|
|
20
|
+
gz.write io.read
|
21
|
+
end
|
22
|
+
res.body = string
|
23
|
+
end
|
24
|
+
else
|
25
|
+
res.body = ''
|
26
|
+
end
|
27
|
+
|
28
|
+
res['Content-Encoding'] = req['X-ResponseContentEncoding'] || 'gzip'
|
29
|
+
res['Content-Type'] = "text/html"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class HttpRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
res['Content-Type'] = req.query['ct'] || "text/html"
|
4
|
+
refresh_time = req.query['refresh_time'] || 0
|
5
|
+
refresh_url = req.query['refresh_url'] || '/'
|
6
|
+
res['Refresh'] = " #{refresh_time};url=#{refresh_url}\r\n";
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class InfiniteRedirectServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
res['Content-Type'] = req.query['ct'] || "text/html"
|
4
|
+
res.status = req.query['code'] ? req.query['code'].to_i : '302'
|
5
|
+
number = req.query['q'] ? req.query['q'].to_i : 0
|
6
|
+
res['Location'] = "/infinite_redirect?q=#{number + 1}"
|
7
|
+
end
|
8
|
+
alias :do_POST :do_GET
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class InfiniteRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
address = "#{req.host}:#{req.port}"
|
4
|
+
res['Content-Type'] = req.query['ct'] || "text/html"
|
5
|
+
res.status = req.query['code'] ? req.query['code'].to_i : '302'
|
6
|
+
number = req.query['q'] ? req.query['q'].to_i : 0
|
7
|
+
res['Refresh'] = "0;url=http://#{address}/infinite_refresh?q=#{number + 1}\r\n";
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class ManyCookiesAsStringServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
cookies = []
|
4
|
+
name_cookie = WEBrick::Cookie.new("name", "Aaron")
|
5
|
+
name_cookie.path = "/"
|
6
|
+
name_cookie.expires = Time.now + 86400
|
7
|
+
name_cookie.domain = 'localhost'
|
8
|
+
cookies << name_cookie
|
9
|
+
cookies << name_cookie
|
10
|
+
cookies << name_cookie
|
11
|
+
cookies << "#{name_cookie}; HttpOnly"
|
12
|
+
|
13
|
+
expired_cookie = WEBrick::Cookie.new("expired", "doh")
|
14
|
+
expired_cookie.path = "/"
|
15
|
+
expired_cookie.expires = Time.now - 86400
|
16
|
+
cookies << expired_cookie
|
17
|
+
|
18
|
+
different_path_cookie = WEBrick::Cookie.new("a_path", "some_path")
|
19
|
+
different_path_cookie.path = "/some_path"
|
20
|
+
different_path_cookie.expires = Time.now + 86400
|
21
|
+
cookies << different_path_cookie
|
22
|
+
|
23
|
+
no_path_cookie = WEBrick::Cookie.new("no_path", "no_path")
|
24
|
+
no_path_cookie.expires = Time.now + 86400
|
25
|
+
cookies << no_path_cookie
|
26
|
+
|
27
|
+
no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope")
|
28
|
+
no_exp_path_cookie.path = "/"
|
29
|
+
cookies << no_exp_path_cookie
|
30
|
+
|
31
|
+
res['Set-Cookie'] = cookies.join(', ')
|
32
|
+
|
33
|
+
res['Content-Type'] = "text/html"
|
34
|
+
res.body = "<html><body>hello</body></html>"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class ManyCookiesServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
name_cookie = WEBrick::Cookie.new("name", "Aaron")
|
4
|
+
name_cookie.path = "/"
|
5
|
+
name_cookie.expires = Time.now + 86400
|
6
|
+
res.cookies << name_cookie
|
7
|
+
res.cookies << name_cookie
|
8
|
+
res.cookies << name_cookie
|
9
|
+
res.cookies << name_cookie
|
10
|
+
|
11
|
+
expired_cookie = WEBrick::Cookie.new("expired", "doh")
|
12
|
+
expired_cookie.path = "/"
|
13
|
+
expired_cookie.expires = Time.now - 86400
|
14
|
+
res.cookies << expired_cookie
|
15
|
+
|
16
|
+
different_path_cookie = WEBrick::Cookie.new("a_path", "some_path")
|
17
|
+
different_path_cookie.path = "/some_path"
|
18
|
+
different_path_cookie.expires = Time.now + 86400
|
19
|
+
res.cookies << different_path_cookie
|
20
|
+
|
21
|
+
no_path_cookie = WEBrick::Cookie.new("no_path", "no_path")
|
22
|
+
no_path_cookie.expires = Time.now + 86400
|
23
|
+
res.cookies << no_path_cookie
|
24
|
+
|
25
|
+
no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope")
|
26
|
+
no_exp_path_cookie.path = "/"
|
27
|
+
res.cookies << no_exp_path_cookie
|
28
|
+
|
29
|
+
res['Content-Type'] = "text/html"
|
30
|
+
res.body = "<html><body>hello</body></html>"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ModifiedSinceServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
s_time = 'Fri, 04 May 2001 00:00:38 GMT'
|
4
|
+
|
5
|
+
my_time = Time.parse(s_time)
|
6
|
+
|
7
|
+
if req['If-Modified-Since']
|
8
|
+
your_time = Time.parse(req['If-Modified-Since'])
|
9
|
+
if my_time > your_time
|
10
|
+
res.body = 'This page was updated since you requested'
|
11
|
+
else
|
12
|
+
res.status = 304
|
13
|
+
end
|
14
|
+
else
|
15
|
+
res.body = 'You did not send an If-Modified-Since header'
|
16
|
+
end
|
17
|
+
|
18
|
+
res['Last-Modified'] = s_time
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class NTLMServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
|
3
|
+
def do_GET(req, res)
|
4
|
+
if req['Authorization'] =~ /^NTLM (.*)/ then
|
5
|
+
authorization = $1.unpack('m*').first
|
6
|
+
|
7
|
+
if authorization =~ /^NTLMSSP\000\001/ then
|
8
|
+
type_2 = 'TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mr' \
|
9
|
+
'ze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4A' \
|
10
|
+
'AgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUA' \
|
11
|
+
'UgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIA' \
|
12
|
+
'cwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMA' \
|
13
|
+
'bwBtAAAAAAA='
|
14
|
+
|
15
|
+
res['WWW-Authenticate'] = "NTLM #{type_2}"
|
16
|
+
res.status = 401
|
17
|
+
elsif authorization =~ /^NTLMSSP\000\003/ then
|
18
|
+
res.body = 'ok'
|
19
|
+
else
|
20
|
+
res['WWW-Authenticate'] = 'NTLM'
|
21
|
+
res.status = 401
|
22
|
+
end
|
23
|
+
else
|
24
|
+
res['WWW-Authenticate'] = 'NTLM'
|
25
|
+
res.status = 401
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class OneCookieNoSpacesServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
cookie = WEBrick::Cookie.new("foo", "bar")
|
4
|
+
cookie.path = "/"
|
5
|
+
cookie.expires = Time.now + 86400
|
6
|
+
res.cookies << cookie.to_s.gsub(/; /, ';')
|
7
|
+
res['Content-Type'] = "text/html"
|
8
|
+
res.body = "<html><body>hello</body></html>"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class OneCookieServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
cookie = WEBrick::Cookie.new("foo", "bar")
|
4
|
+
cookie.path = "/"
|
5
|
+
cookie.expires = Time.now + 86400
|
6
|
+
res.cookies << cookie
|
7
|
+
res['Content-Type'] = "text/html"
|
8
|
+
res.body = "<html><body>hello</body></html>"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class QuotedValueCookieServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
cookie = WEBrick::Cookie.new("quoted", "\"value\"")
|
4
|
+
cookie.path = "/"
|
5
|
+
cookie.expires = Time.now + 86400
|
6
|
+
res.cookies << cookie
|
7
|
+
res['Content-Type'] = "text/html"
|
8
|
+
res.body = "<html><body>hello</body></html>"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class RedirectServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
res['Content-Type'] = req.query['ct'] || 'text/html'
|
4
|
+
res.status = req.query['code'] ? req.query['code'].to_i : '302'
|
5
|
+
res['Location'] = req['X-Location'] || '/verb'
|
6
|
+
end
|
7
|
+
|
8
|
+
alias :do_POST :do_GET
|
9
|
+
alias :do_HEAD :do_GET
|
10
|
+
alias :do_PUT :do_GET
|
11
|
+
alias :do_DELETE :do_GET
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class RefererServlet < WEBrick::HTTPServlet::AbstractServlet
|
2
|
+
def do_GET(req, res)
|
3
|
+
res['Content-Type'] = "text/html"
|
4
|
+
res.body = req['Referer'] || ''
|
5
|
+
end
|
6
|
+
|
7
|
+
def do_POST(req, res)
|
8
|
+
res['Content-Type'] = "text/html"
|
9
|
+
res.body = req['Referer'] || ''
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|