diamond-mechanize 2.1 → 2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. metadata +222 -167
  2. data/Rakefile +0 -49
  3. data/lib/mechanize/content_type_error.rb +0 -13
  4. data/lib/mechanize/cookie.rb +0 -232
  5. data/lib/mechanize/cookie_jar.rb +0 -194
  6. data/lib/mechanize/download.rb +0 -59
  7. data/lib/mechanize/element_matcher.rb +0 -36
  8. data/lib/mechanize/file.rb +0 -65
  9. data/lib/mechanize/file_connection.rb +0 -17
  10. data/lib/mechanize/file_request.rb +0 -26
  11. data/lib/mechanize/file_response.rb +0 -74
  12. data/lib/mechanize/file_saver.rb +0 -39
  13. data/lib/mechanize/form/button.rb +0 -6
  14. data/lib/mechanize/form/check_box.rb +0 -12
  15. data/lib/mechanize/form/field.rb +0 -54
  16. data/lib/mechanize/form/file_upload.rb +0 -21
  17. data/lib/mechanize/form/hidden.rb +0 -3
  18. data/lib/mechanize/form/image_button.rb +0 -19
  19. data/lib/mechanize/form/keygen.rb +0 -34
  20. data/lib/mechanize/form/multi_select_list.rb +0 -94
  21. data/lib/mechanize/form/option.rb +0 -50
  22. data/lib/mechanize/form/radio_button.rb +0 -55
  23. data/lib/mechanize/form/reset.rb +0 -3
  24. data/lib/mechanize/form/select_list.rb +0 -44
  25. data/lib/mechanize/form/submit.rb +0 -3
  26. data/lib/mechanize/form/text.rb +0 -3
  27. data/lib/mechanize/form/textarea.rb +0 -3
  28. data/lib/mechanize/form.rb +0 -543
  29. data/lib/mechanize/headers.rb +0 -23
  30. data/lib/mechanize/history.rb +0 -82
  31. data/lib/mechanize/http/agent.rb +0 -1004
  32. data/lib/mechanize/http/auth_challenge.rb +0 -59
  33. data/lib/mechanize/http/auth_realm.rb +0 -31
  34. data/lib/mechanize/http/content_disposition_parser.rb +0 -188
  35. data/lib/mechanize/http/www_authenticate_parser.rb +0 -155
  36. data/lib/mechanize/http.rb +0 -8
  37. data/lib/mechanize/monkey_patch.rb +0 -16
  38. data/lib/mechanize/page/base.rb +0 -7
  39. data/lib/mechanize/page/frame.rb +0 -27
  40. data/lib/mechanize/page/image.rb +0 -30
  41. data/lib/mechanize/page/label.rb +0 -20
  42. data/lib/mechanize/page/link.rb +0 -98
  43. data/lib/mechanize/page/meta_refresh.rb +0 -68
  44. data/lib/mechanize/page.rb +0 -440
  45. data/lib/mechanize/parser.rb +0 -173
  46. data/lib/mechanize/pluggable_parsers.rb +0 -144
  47. data/lib/mechanize/redirect_limit_reached_error.rb +0 -19
  48. data/lib/mechanize/redirect_not_get_or_head_error.rb +0 -21
  49. data/lib/mechanize/response_code_error.rb +0 -21
  50. data/lib/mechanize/response_read_error.rb +0 -27
  51. data/lib/mechanize/robots_disallowed_error.rb +0 -28
  52. data/lib/mechanize/test_case.rb +0 -663
  53. data/lib/mechanize/unauthorized_error.rb +0 -3
  54. data/lib/mechanize/unsupported_scheme_error.rb +0 -6
  55. data/lib/mechanize/util.rb +0 -101
  56. data/lib/mechanize.rb +0 -1079
  57. data/test/data/htpasswd +0 -1
  58. data/test/data/server.crt +0 -16
  59. data/test/data/server.csr +0 -12
  60. data/test/data/server.key +0 -15
  61. data/test/data/server.pem +0 -15
  62. data/test/htdocs/alt_text.html +0 -10
  63. data/test/htdocs/bad_form_test.html +0 -9
  64. data/test/htdocs/button.jpg +0 -0
  65. data/test/htdocs/canonical_uri.html +0 -9
  66. data/test/htdocs/dir with spaces/foo.html +0 -1
  67. data/test/htdocs/empty_form.html +0 -6
  68. data/test/htdocs/file_upload.html +0 -26
  69. data/test/htdocs/find_link.html +0 -41
  70. data/test/htdocs/form_multi_select.html +0 -16
  71. data/test/htdocs/form_multival.html +0 -37
  72. data/test/htdocs/form_no_action.html +0 -18
  73. data/test/htdocs/form_no_input_name.html +0 -16
  74. data/test/htdocs/form_order_test.html +0 -11
  75. data/test/htdocs/form_select.html +0 -16
  76. data/test/htdocs/form_set_fields.html +0 -14
  77. data/test/htdocs/form_test.html +0 -188
  78. data/test/htdocs/frame_referer_test.html +0 -10
  79. data/test/htdocs/frame_test.html +0 -30
  80. data/test/htdocs/google.html +0 -13
  81. data/test/htdocs/index.html +0 -6
  82. data/test/htdocs/link with space.html +0 -5
  83. data/test/htdocs/meta_cookie.html +0 -11
  84. data/test/htdocs/no_title_test.html +0 -6
  85. data/test/htdocs/noindex.html +0 -9
  86. data/test/htdocs/rails_3_encoding_hack_form_test.html +0 -27
  87. data/test/htdocs/relative/tc_relative_links.html +0 -21
  88. data/test/htdocs/robots.html +0 -8
  89. data/test/htdocs/robots.txt +0 -2
  90. data/test/htdocs/tc_bad_charset.html +0 -9
  91. data/test/htdocs/tc_bad_links.html +0 -5
  92. data/test/htdocs/tc_base_link.html +0 -8
  93. data/test/htdocs/tc_blank_form.html +0 -11
  94. data/test/htdocs/tc_charset.html +0 -6
  95. data/test/htdocs/tc_checkboxes.html +0 -19
  96. data/test/htdocs/tc_encoded_links.html +0 -5
  97. data/test/htdocs/tc_field_precedence.html +0 -11
  98. data/test/htdocs/tc_follow_meta.html +0 -8
  99. data/test/htdocs/tc_form_action.html +0 -48
  100. data/test/htdocs/tc_links.html +0 -19
  101. data/test/htdocs/tc_meta_in_body.html +0 -9
  102. data/test/htdocs/tc_pretty_print.html +0 -17
  103. data/test/htdocs/tc_referer.html +0 -16
  104. data/test/htdocs/tc_relative_links.html +0 -19
  105. data/test/htdocs/tc_textarea.html +0 -23
  106. data/test/htdocs/test_click.html +0 -11
  107. data/test/htdocs/unusual______.html +0 -5
  108. data/test/test_mechanize.rb +0 -1164
  109. data/test/test_mechanize_cookie.rb +0 -451
  110. data/test/test_mechanize_cookie_jar.rb +0 -483
  111. data/test/test_mechanize_download.rb +0 -43
  112. data/test/test_mechanize_file.rb +0 -61
  113. data/test/test_mechanize_file_connection.rb +0 -21
  114. data/test/test_mechanize_file_request.rb +0 -19
  115. data/test/test_mechanize_file_saver.rb +0 -21
  116. data/test/test_mechanize_form.rb +0 -875
  117. data/test/test_mechanize_form_check_box.rb +0 -38
  118. data/test/test_mechanize_form_encoding.rb +0 -114
  119. data/test/test_mechanize_form_field.rb +0 -63
  120. data/test/test_mechanize_form_file_upload.rb +0 -20
  121. data/test/test_mechanize_form_image_button.rb +0 -12
  122. data/test/test_mechanize_form_keygen.rb +0 -32
  123. data/test/test_mechanize_form_multi_select_list.rb +0 -84
  124. data/test/test_mechanize_form_option.rb +0 -55
  125. data/test/test_mechanize_form_radio_button.rb +0 -78
  126. data/test/test_mechanize_form_select_list.rb +0 -76
  127. data/test/test_mechanize_form_textarea.rb +0 -52
  128. data/test/test_mechanize_headers.rb +0 -35
  129. data/test/test_mechanize_history.rb +0 -103
  130. data/test/test_mechanize_http_agent.rb +0 -1225
  131. data/test/test_mechanize_http_auth_challenge.rb +0 -39
  132. data/test/test_mechanize_http_auth_realm.rb +0 -49
  133. data/test/test_mechanize_http_content_disposition_parser.rb +0 -118
  134. data/test/test_mechanize_http_www_authenticate_parser.rb +0 -146
  135. data/test/test_mechanize_link.rb +0 -80
  136. data/test/test_mechanize_page.rb +0 -118
  137. data/test/test_mechanize_page_encoding.rb +0 -182
  138. data/test/test_mechanize_page_frame.rb +0 -16
  139. data/test/test_mechanize_page_link.rb +0 -390
  140. data/test/test_mechanize_page_meta_refresh.rb +0 -127
  141. data/test/test_mechanize_parser.rb +0 -289
  142. data/test/test_mechanize_pluggable_parser.rb +0 -52
  143. data/test/test_mechanize_redirect_limit_reached_error.rb +0 -24
  144. data/test/test_mechanize_redirect_not_get_or_head_error.rb +0 -14
  145. data/test/test_mechanize_subclass.rb +0 -22
  146. data/test/test_mechanize_util.rb +0 -103
  147. data/test/test_multi_select.rb +0 -119
@@ -1,173 +0,0 @@
1
- ##
2
- # The parser module provides standard methods for accessing the headers and
3
- # content of a response that are shared across pluggable parsers.
4
-
5
- module Mechanize::Parser
6
-
7
- extend Forwardable
8
-
9
- special_filenames = Regexp.union %w[
10
- AUX
11
- COM1
12
- COM2
13
- COM3
14
- COM4
15
- COM5
16
- COM6
17
- COM7
18
- COM8
19
- COM9
20
- CON
21
- LPT1
22
- LPT2
23
- LPT3
24
- LPT4
25
- LPT5
26
- LPT6
27
- LPT7
28
- LPT8
29
- LPT9
30
- NUL
31
- PRN
32
- ]
33
-
34
- ##
35
- # Special filenames that must be escaped
36
-
37
- SPECIAL_FILENAMES = /\A#{special_filenames}/i
38
-
39
- ##
40
- # The URI this file was retrieved from
41
-
42
- attr_accessor :uri
43
-
44
- ##
45
- # The Mechanize::Headers for this file
46
-
47
- attr_accessor :response
48
-
49
- alias header response
50
-
51
- ##
52
- # The HTTP response code
53
-
54
- attr_accessor :code
55
-
56
- ##
57
- # :method: [](header)
58
- #
59
- # Access HTTP +header+ by name
60
-
61
- def_delegator :header, :[], :[]
62
-
63
- ##
64
- # :method: []=(header, value)
65
- #
66
- # Set HTTP +header+ to +value+
67
-
68
- def_delegator :header, :[]=, :[]=
69
-
70
- ##
71
- # :method: key?(header)
72
- #
73
- # Is the named +header+ present?
74
-
75
- def_delegator :header, :key?, :key?
76
-
77
- ##
78
- # :method: each
79
- #
80
- # Enumerate HTTP headers
81
-
82
- def_delegator :header, :each, :each
83
-
84
- ##
85
- # :method: each
86
- #
87
- # Enumerate HTTP headers in capitalized (canonical) form
88
-
89
- def_delegator :header, :canonical_each, :canonical_each
90
-
91
- ##
92
- # Extracts the filename from a Content-Disposition header in the #response
93
- # or from the URI. If +full_path+ is true the filename will include the
94
- # host name and path to the resource, otherwise a filename in the current
95
- # directory is given.
96
-
97
- def extract_filename full_path = @full_path
98
- handled = false
99
-
100
- if @uri then
101
- uri = @uri
102
- uri += 'index.html' if uri.path.end_with? '/'
103
-
104
- path = uri.path.split(/\//)
105
- filename = path.pop || 'index.html'
106
- else
107
- path = []
108
- filename = 'index.html'
109
- end
110
-
111
- # Set the filename
112
- if disposition = @response['content-disposition'] then
113
- content_disposition =
114
- Mechanize::HTTP::ContentDispositionParser.parse disposition
115
-
116
- if content_disposition then
117
- filename = content_disposition.filename
118
- filename = filename.split(/[\\\/]/).last
119
- handled = true
120
- end
121
- end
122
-
123
- if not handled and @uri then
124
- filename << '.html' unless filename =~ /\./
125
- filename << "?#{@uri.query}" if @uri.query
126
- end
127
-
128
- if SPECIAL_FILENAMES =~ filename then
129
- filename = "_#{filename}"
130
- end
131
-
132
- filename = filename.tr "\x00-\x20<>:\"/\\|?*", '_'
133
-
134
- @filename = if full_path then
135
- File.join @uri.host, path, filename
136
- else
137
- filename
138
- end
139
- end
140
-
141
- ##
142
- # Creates a Mechanize::Header from the Net::HTTPResponse +response+.
143
- #
144
- # This allows the Net::HTTPResponse to be garbage collected sooner.
145
-
146
- def fill_header response
147
- @response = Mechanize::Headers.new
148
-
149
- response.each { |k,v|
150
- @response[k] = v
151
- } if response
152
-
153
- @response
154
- end
155
-
156
- ##
157
- # Finds a free filename based on +filename+, but is not race-free
158
-
159
- def find_free_name filename
160
- filename = @filename unless filename
161
-
162
- number = 1
163
-
164
- while File.exist? filename do
165
- filename = "#{@filename}.#{number}"
166
- number += 1
167
- end
168
-
169
- filename
170
- end
171
-
172
- end
173
-
@@ -1,144 +0,0 @@
1
- require 'mechanize/file'
2
- require 'mechanize/file_saver'
3
- require 'mechanize/page'
4
-
5
- ##
6
- # This class is used to register and maintain pluggable parsers for Mechanize
7
- # to use.
8
- #
9
- # Mechanize allows different parsers for different content types. Mechanize
10
- # uses PluggableParser to determine which parser to use for any content type.
11
- # To use your own pluggable parser or to change the default pluggable parsers,
12
- # register them with this class.
13
- #
14
- # The default parser for unregistered content types is Mechanize::File.
15
- #
16
- # The module Mechanize::Parser provides basic functionality for any content
17
- # type, so you may use it in custom parsers you write. For small files you
18
- # wish to perform in-memory operations on, you should subclass
19
- # Mechanize::File. For large files you should subclass Mechanize::Download as
20
- # the content is only loaded into memory in small chunks.
21
- #
22
- # == Example
23
- #
24
- # To create your own parser, just create a class that takes four parameters in
25
- # the constructor. Here is an example of registering a pluggable parser that
26
- # handles CSV files:
27
- #
28
- # require 'csv'
29
- #
30
- # class CSVParser < Mechanize::File
31
- # attr_reader :csv
32
- #
33
- # def initialize uri = nil, response = nil, body = nil, code = nil
34
- # super uri, response, body, code
35
- # @csv = CSV.parse body
36
- # end
37
- # end
38
- #
39
- # agent = Mechanize.new
40
- # agent.pluggable_parser.csv = CSVParser
41
- # agent.get('http://example.com/test.csv') # => CSVParser
42
- #
43
- # Now any response with a content type of 'text/csv' will initialize a
44
- # CSVParser and return that object to the caller.
45
- #
46
- # To register a pluggable parser for a content type that pluggable parser does
47
- # not know about, use the hash syntax:
48
- #
49
- # agent.pluggable_parser['text/something'] = SomeClass
50
- #
51
- # To set the default parser, use #default:
52
- #
53
- # agent.pluggable_parser.default = Mechanize::Download
54
- #
55
- # Now all unknown content types will be saved to disk and not loaded into
56
- # memory.
57
-
58
- class Mechanize::PluggableParser
59
-
60
- CONTENT_TYPES = {
61
- :html => 'text/html',
62
- :wap => 'application/vnd.wap.xhtml+xml',
63
- :xhtml => 'application/xhtml+xml',
64
- :pdf => 'application/pdf',
65
- :csv => 'text/csv',
66
- :xml => 'text/xml',
67
- }
68
-
69
- attr_accessor :default
70
-
71
- def initialize
72
- @parsers = {
73
- CONTENT_TYPES[:html] => Mechanize::Page,
74
- CONTENT_TYPES[:xhtml] => Mechanize::Page,
75
- CONTENT_TYPES[:wap] => Mechanize::Page,
76
- }
77
-
78
- @default = Mechanize::File
79
- end
80
-
81
- ##
82
- # Returns the parser registered for the given +content_type+
83
-
84
- def parser(content_type)
85
- content_type.nil? ? default : @parsers[content_type] || default
86
- end
87
-
88
- def register_parser(content_type, klass) # :nodoc:
89
- @parsers[content_type] = klass
90
- end
91
-
92
- ##
93
- # Registers +klass+ as the parser for text/html and application/xhtml+xml
94
- # content
95
-
96
- def html=(klass)
97
- register_parser(CONTENT_TYPES[:html], klass)
98
- register_parser(CONTENT_TYPES[:xhtml], klass)
99
- end
100
-
101
- ##
102
- # Registers +klass+ as the parser for application/xhtml+xml content
103
-
104
- def xhtml=(klass)
105
- register_parser(CONTENT_TYPES[:xhtml], klass)
106
- end
107
-
108
- ##
109
- # Registers +klass+ as the parser for application/pdf content
110
-
111
- def pdf=(klass)
112
- register_parser(CONTENT_TYPES[:pdf], klass)
113
- end
114
-
115
- ##
116
- # Registers +klass+ as the parser for text/csv content
117
-
118
- def csv=(klass)
119
- register_parser(CONTENT_TYPES[:csv], klass)
120
- end
121
-
122
- ##
123
- # Registers +klass+ as the parser for text/xml content
124
-
125
- def xml=(klass)
126
- register_parser(CONTENT_TYPES[:xml], klass)
127
- end
128
-
129
- ##
130
- # Retrieves the parser for +content_type+ content
131
-
132
- def [](content_type)
133
- @parsers[content_type]
134
- end
135
-
136
- ##
137
- # Sets the parser for +content_type+ content to +klass+
138
-
139
- def []=(content_type, klass)
140
- @parsers[content_type] = klass
141
- end
142
-
143
- end
144
-
@@ -1,19 +0,0 @@
1
- ##
2
- # Raised when too many redirects are sent
3
-
4
- class Mechanize::RedirectLimitReachedError < Mechanize::Error
5
-
6
- attr_reader :page
7
- attr_reader :redirects
8
- attr_reader :response_code
9
-
10
- def initialize page, redirects
11
- @page = page
12
- @redirects = redirects
13
- @response_code = page.code
14
-
15
- super "Redirect limit of #{redirects} reached"
16
- end
17
-
18
- end
19
-
@@ -1,21 +0,0 @@
1
- ##
2
- # Raised when a POST, PUT, or DELETE request results in a redirect
3
- # see RFC 2616 10.3.2, 10.3.3 http://www.ietf.org/rfc/rfc2616.txt
4
-
5
- class Mechanize::RedirectNotGetOrHeadError < Mechanize::Error
6
- attr_reader :page, :response_code, :verb, :uri
7
- def initialize(page, verb)
8
- @page = page
9
- @verb = verb
10
- @uri = page.uri
11
- @response_code = page.code
12
- end
13
-
14
- def to_s
15
- method = @verb.to_s.upcase
16
- "#{@response_code} redirect received after a #{method} request"
17
- end
18
-
19
- alias :inspect :to_s
20
- end
21
-
@@ -1,21 +0,0 @@
1
- # This error is raised when Mechanize encounters a response code it does not
2
- # know how to handle. Currently, this exception will be thrown if Mechanize
3
- # encounters response codes other than 200, 301, or 302. Any other response
4
- # code is up to the user to handle.
5
-
6
- class Mechanize::ResponseCodeError < Mechanize::Error
7
- attr_reader :response_code
8
- attr_reader :page
9
-
10
- def initialize(page)
11
- @page = page
12
- @response_code = page.code.to_s
13
- end
14
-
15
- def to_s
16
- "#{@response_code} => #{Net::HTTPResponse::CODE_TO_OBJ[@response_code]}"
17
- end
18
-
19
- alias inspect to_s
20
- end
21
-
@@ -1,27 +0,0 @@
1
- ##
2
- # Raised when Mechanize encounters an error while reading the response body
3
- # from the server. Contains the response headers and the response body up to
4
- # the error along with the initial error.
5
-
6
- class Mechanize::ResponseReadError < Mechanize::Error
7
-
8
- attr_reader :body_io
9
- attr_reader :error
10
- attr_reader :response
11
-
12
- ##
13
- # Creates a new ResponseReadError with the +error+ raised, the +response+
14
- # and the +body_io+ for content read so far.
15
-
16
- def initialize error, response, body_io
17
- @error = error
18
- @response = response
19
- @body_io = body_io
20
- end
21
-
22
- def message # :nodoc:
23
- "#{@error.message} (#{self.class})"
24
- end
25
-
26
- end
27
-
@@ -1,28 +0,0 @@
1
- # Exception that is raised when an access to a resource is disallowed by
2
- # robots.txt or by HTML document itself.
3
-
4
- class Mechanize::RobotsDisallowedError < Mechanize::Error
5
- def initialize(url)
6
- if url.is_a?(URI)
7
- @url = url.to_s
8
- @uri = url
9
- else
10
- @url = url.to_s
11
- end
12
- end
13
-
14
- # Returns the URL (string) of the resource that caused this error.
15
- attr_reader :url
16
-
17
- # Returns the URL (URI object) of the resource that caused this
18
- # error. URI::InvalidURIError may be raised if the URL happens to
19
- # be invalid or not understood by the URI library.
20
- def uri
21
- @uri ||= URI.parse(url)
22
- end
23
-
24
- def to_s
25
- "Robots access is disallowed for URL: #{url}"
26
- end
27
- alias :inspect :to_s
28
- end
@@ -1,663 +0,0 @@
1
- require 'mechanize'
2
- require 'logger'
3
- require 'tempfile'
4
- require 'tmpdir'
5
- require 'webrick'
6
- require 'zlib'
7
-
8
- require 'rubygems'
9
-
10
- begin
11
- gem 'minitest'
12
- rescue Gem::LoadError
13
- end
14
-
15
- require 'minitest/autorun'
16
-
17
- class Mechanize::TestCase < MiniTest::Unit::TestCase
18
-
19
- TEST_DIR = File.expand_path '../../../test', __FILE__
20
- REQUESTS = []
21
-
22
- def setup
23
- super
24
-
25
- REQUESTS.clear
26
- @mech = Mechanize.new
27
- @ssl_private_key = nil
28
- @ssl_certificate = nil
29
- end
30
-
31
- def fake_page agent = @mech
32
- uri = URI 'http://fake.example/'
33
- html = <<-END
34
- <html>
35
- <body>
36
- <form><input type="submit" value="submit" /></form>
37
- </body>
38
- </html>
39
- END
40
-
41
- response = { 'content-type' => 'text/html' }
42
-
43
- Mechanize::Page.new uri, response, html, 200, agent
44
- end
45
-
46
- def have_encoding?
47
- Object.const_defined? :Encoding
48
- end
49
-
50
- def html_page body
51
- uri = URI 'http://example/'
52
- Mechanize::Page.new uri, { 'content-type' => 'text/html' }, body, 200, @mech
53
- end
54
-
55
- def in_tmpdir
56
- Dir.mktmpdir do |dir|
57
- Dir.chdir dir do
58
- yield
59
- end
60
- end
61
- end
62
-
63
- def node element, attributes = {}
64
- doc = Nokogiri::HTML::Document.new
65
-
66
- node = Nokogiri::XML::Node.new element, doc
67
-
68
- attributes.each do |name, value|
69
- node[name] = value
70
- end
71
-
72
- node
73
- end
74
-
75
- def page uri, content_type = 'text/html', body = '', code = 200
76
- uri = URI uri unless URI::Generic === uri
77
-
78
- Mechanize::Page.new(uri, { 'content-type' => content_type }, body, code,
79
- @mech)
80
- end
81
-
82
- def requests
83
- REQUESTS
84
- end
85
-
86
- def ssl_private_key
87
- @ssl_private_key ||= OpenSSL::PKey::RSA.new <<-KEY
88
- -----BEGIN RSA PRIVATE KEY-----
89
- MIG7AgEAAkEA8pmEfmP0Ibir91x6pbts4JmmsVZd3xvD5p347EFvBCbhBW1nv1Gs
90
- bCBEFlSiT1q2qvxGb5IlbrfdhdgyqdTXUQIBAQIBAQIhAPumXslvf6YasXa1hni3
91
- p80joKOug2UUgqOLD2GUSO//AiEA9ssY6AFxjHWuwo/+/rkLmkfO2s1Lz3OeUEWq
92
- 6DiHOK8CAQECAQECIQDt8bc4vS6wh9VXApNSKIpVygtxSFe/IwLeX26n77j6Qg==
93
- -----END RSA PRIVATE KEY-----
94
- KEY
95
- end
96
-
97
- def ssl_certificate
98
- @ssl_certificate ||= OpenSSL::X509::Certificate.new <<-CERT
99
- -----BEGIN CERTIFICATE-----
100
- MIIBQjCB7aADAgECAgEAMA0GCSqGSIb3DQEBBQUAMCoxDzANBgNVBAMMBm5vYm9k
101
- eTEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwIBcNMTExMTAzMjEwODU5WhgPOTk5
102
- OTEyMzExMjU5NTlaMCoxDzANBgNVBAMMBm5vYm9keTEXMBUGCgmSJomT8ixkARkW
103
- B2V4YW1wbGUwWjANBgkqhkiG9w0BAQEFAANJADBGAkEA8pmEfmP0Ibir91x6pbts
104
- 4JmmsVZd3xvD5p347EFvBCbhBW1nv1GsbCBEFlSiT1q2qvxGb5IlbrfdhdgyqdTX
105
- UQIBATANBgkqhkiG9w0BAQUFAANBAAAB////////////////////////////////
106
- //8AMCEwCQYFKw4DAhoFAAQUePiv+QrJxyjtEJNnH5pB9OTWIqA=
107
- -----END CERTIFICATE-----
108
- CERT
109
- end
110
-
111
- end
112
-
113
- class BasicAuthServlet < WEBrick::HTTPServlet::AbstractServlet
114
- def do_GET(req,res)
115
- htpd = WEBrick::HTTPAuth::Htpasswd.new('dot.htpasswd')
116
- htpd.set_passwd('Blah', 'user', 'pass')
117
- authenticator = WEBrick::HTTPAuth::BasicAuth.new({
118
- :UserDB => htpd,
119
- :Realm => 'Blah',
120
- :Logger => Logger.new(nil)
121
- }
122
- )
123
- begin
124
- authenticator.authenticate(req,res)
125
- res.body = 'You are authenticated'
126
- rescue WEBrick::HTTPStatus::Unauthorized
127
- res.status = 401
128
- end
129
- FileUtils.rm('dot.htpasswd')
130
- end
131
- alias :do_POST :do_GET
132
- end
133
-
134
- class ContentTypeServlet < WEBrick::HTTPServlet::AbstractServlet
135
- def do_GET(req, res)
136
- ct = req.query['ct'] || "text/html; charset=utf-8"
137
- res['Content-Type'] = ct
138
- res.body = "Hello World"
139
- end
140
- end
141
-
142
- class DigestAuthServlet < WEBrick::HTTPServlet::AbstractServlet
143
- htpd = WEBrick::HTTPAuth::Htdigest.new('digest.htpasswd')
144
- htpd.set_passwd('Blah', 'user', 'pass')
145
- @@authenticator = WEBrick::HTTPAuth::DigestAuth.new({
146
- :UserDB => htpd,
147
- :Realm => 'Blah',
148
- :Algorithm => 'MD5',
149
- :Logger => Logger.new(nil)
150
- }
151
- )
152
- def do_GET(req,res)
153
- def req.request_time; Time.now; end
154
- def req.request_uri; '/digest_auth'; end
155
- def req.request_method; "GET"; end
156
-
157
- begin
158
- @@authenticator.authenticate(req,res)
159
- res.body = 'You are authenticated'
160
- rescue WEBrick::HTTPStatus::Unauthorized
161
- res.status = 401
162
- end
163
- FileUtils.rm('digest.htpasswd') if File.exists?('digest.htpasswd')
164
- end
165
- alias :do_POST :do_GET
166
- end
167
-
168
- class FileUploadServlet < WEBrick::HTTPServlet::AbstractServlet
169
- def do_POST(req, res)
170
- res.body = req.body
171
- end
172
- end
173
-
174
- class FormServlet < WEBrick::HTTPServlet::AbstractServlet
175
- def do_GET(req, res)
176
- res.body = "<HTML><body>"
177
- req.query.each_key { |k|
178
- req.query[k].each_data { |data|
179
- res.body << "<a href=\"#\">#{WEBrick::HTTPUtils.unescape(k)}:#{WEBrick::HTTPUtils.unescape(data)}</a><br />"
180
- }
181
- }
182
- res.body << "<div id=\"query\">#{res.query}</div></body></HTML>"
183
- res['Content-Type'] = "text/html"
184
- end
185
-
186
- def do_POST(req, res)
187
- res.body = "<HTML><body>"
188
-
189
- req.query.each_key { |k|
190
- req.query[k].each_data { |data|
191
- res.body << "<a href=\"#\">#{k}:#{data}</a><br />"
192
- }
193
- }
194
-
195
- res.body << "<div id=\"query\">#{req.body}</div></body></HTML>"
196
- res['Content-Type'] = "text/html"
197
- end
198
- end
199
-
200
- class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
201
- def do_GET(req, res)
202
- if req['Accept-Encoding'] =~ /gzip/
203
- if name = req.query['file'] then
204
- open("#{Mechanize::TestCase::TEST_DIR}/htdocs/#{name}", 'r') do |io|
205
- string = ""
206
- zipped = StringIO.new string, 'w'
207
- Zlib::GzipWriter.wrap zipped do |gz|
208
- gz.write io.read
209
- end
210
- res.body = string
211
- end
212
- else
213
- res.body = ''
214
- end
215
- res['Content-Encoding'] = req['X-ResponseContentEncoding'] || 'gzip'
216
- res['Content-Type'] = "text/html"
217
- else
218
- res.code = 400
219
- res.body = 'no gzip'
220
- end
221
- end
222
- end
223
-
224
- class HeaderServlet < WEBrick::HTTPServlet::AbstractServlet
225
- def do_GET(req, res)
226
- res['Content-Type'] = "text/html"
227
-
228
- req.query.each do |x,y|
229
- res[x] = y
230
- end
231
-
232
- body = ''
233
- req.each_header do |k,v|
234
- body << "#{k}|#{v}\n"
235
- end
236
- res.body = body
237
- end
238
- end
239
-
240
- class HttpRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
241
- def do_GET(req, res)
242
- res['Content-Type'] = req.query['ct'] || "text/html"
243
- refresh_time = req.query['refresh_time'] || 0
244
- refresh_url = req.query['refresh_url'] || '/index.html'
245
- res['Refresh'] = " #{refresh_time};url=#{refresh_url}\r\n";
246
- end
247
- end
248
-
249
- class InfiniteRedirectServlet < WEBrick::HTTPServlet::AbstractServlet
250
- def do_GET(req, res)
251
- res['Content-Type'] = req.query['ct'] || "text/html"
252
- res.status = req.query['code'] ? req.query['code'].to_i : '302'
253
- number = req.query['q'] ? req.query['q'].to_i : 0
254
- res['Location'] = "/infinite_redirect?q=#{number + 1}"
255
- end
256
- alias :do_POST :do_GET
257
- end
258
-
259
- class InfiniteRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
260
- def do_GET(req, res)
261
- res['Content-Type'] = req.query['ct'] || "text/html"
262
- res.status = req.query['code'] ? req.query['code'].to_i : '302'
263
- number = req.query['q'] ? req.query['q'].to_i : 0
264
- res['Refresh'] = " 0;url=http://localhost/infinite_refresh?q=#{number + 1}\r\n";
265
- end
266
- end
267
-
268
- class ManyCookiesAsStringServlet < WEBrick::HTTPServlet::AbstractServlet
269
- def do_GET(req, res)
270
- cookies = []
271
- name_cookie = WEBrick::Cookie.new("name", "Aaron")
272
- name_cookie.path = "/"
273
- name_cookie.expires = Time.now + 86400
274
- name_cookie.domain = 'localhost'
275
- cookies << name_cookie
276
- cookies << name_cookie
277
- cookies << name_cookie
278
- cookies << "#{name_cookie}; HttpOnly"
279
-
280
- expired_cookie = WEBrick::Cookie.new("expired", "doh")
281
- expired_cookie.path = "/"
282
- expired_cookie.expires = Time.now - 86400
283
- cookies << expired_cookie
284
-
285
- different_path_cookie = WEBrick::Cookie.new("a_path", "some_path")
286
- different_path_cookie.path = "/some_path"
287
- different_path_cookie.expires = Time.now + 86400
288
- cookies << different_path_cookie
289
-
290
- no_path_cookie = WEBrick::Cookie.new("no_path", "no_path")
291
- no_path_cookie.expires = Time.now + 86400
292
- cookies << no_path_cookie
293
-
294
- no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope")
295
- no_exp_path_cookie.path = "/"
296
- cookies << no_exp_path_cookie
297
-
298
- res['Set-Cookie'] = cookies.join(', ')
299
-
300
- res['Content-Type'] = "text/html"
301
- res.body = "<html><body>hello</body></html>"
302
- end
303
- end
304
-
305
- class ManyCookiesServlet < WEBrick::HTTPServlet::AbstractServlet
306
- def do_GET(req, res)
307
- name_cookie = WEBrick::Cookie.new("name", "Aaron")
308
- name_cookie.path = "/"
309
- name_cookie.expires = Time.now + 86400
310
- res.cookies << name_cookie
311
- res.cookies << name_cookie
312
- res.cookies << name_cookie
313
- res.cookies << name_cookie
314
-
315
- expired_cookie = WEBrick::Cookie.new("expired", "doh")
316
- expired_cookie.path = "/"
317
- expired_cookie.expires = Time.now - 86400
318
- res.cookies << expired_cookie
319
-
320
- different_path_cookie = WEBrick::Cookie.new("a_path", "some_path")
321
- different_path_cookie.path = "/some_path"
322
- different_path_cookie.expires = Time.now + 86400
323
- res.cookies << different_path_cookie
324
-
325
- no_path_cookie = WEBrick::Cookie.new("no_path", "no_path")
326
- no_path_cookie.expires = Time.now + 86400
327
- res.cookies << no_path_cookie
328
-
329
- no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope")
330
- no_exp_path_cookie.path = "/"
331
- res.cookies << no_exp_path_cookie
332
-
333
- res['Content-Type'] = "text/html"
334
- res.body = "<html><body>hello</body></html>"
335
- end
336
- end
337
-
338
- class ModifiedSinceServlet < WEBrick::HTTPServlet::AbstractServlet
339
- def do_GET(req, res)
340
- s_time = 'Fri, 04 May 2001 00:00:38 GMT'
341
-
342
- my_time = Time.parse(s_time)
343
-
344
- if req['If-Modified-Since']
345
- your_time = Time.parse(req['If-Modified-Since'])
346
- if my_time > your_time
347
- res.body = 'This page was updated since you requested'
348
- else
349
- res.status = 304
350
- end
351
- else
352
- res.body = 'You did not send an If-Modified-Since header'
353
- end
354
-
355
- res['Last-Modified'] = s_time
356
- end
357
- end
358
-
359
- class NTLMServlet < WEBrick::HTTPServlet::AbstractServlet
360
-
361
- def do_GET(req, res)
362
- if req['Authorization'] =~ /^NTLM (.*)/ then
363
- authorization = $1.unpack('m*').first
364
-
365
- if authorization =~ /^NTLMSSP\000\001/ then
366
- type_2 = 'TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mr' \
367
- 'ze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4A' \
368
- 'AgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUA' \
369
- 'UgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIA' \
370
- 'cwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMA' \
371
- 'bwBtAAAAAAA='
372
-
373
- res['WWW-Authenticate'] = "NTLM #{type_2}"
374
- res.status = 401
375
- elsif authorization =~ /^NTLMSSP\000\003/ then
376
- res.body = 'ok'
377
- else
378
- res['WWW-Authenticate'] = 'NTLM'
379
- res.status = 401
380
- end
381
- else
382
- res['WWW-Authenticate'] = 'NTLM'
383
- res.status = 401
384
- end
385
- end
386
-
387
- end
388
-
389
- class OneCookieNoSpacesServlet < WEBrick::HTTPServlet::AbstractServlet
390
- def do_GET(req, res)
391
- cookie = WEBrick::Cookie.new("foo", "bar")
392
- cookie.path = "/"
393
- cookie.expires = Time.now + 86400
394
- res.cookies << cookie.to_s.gsub(/; /, ';')
395
- res['Content-Type'] = "text/html"
396
- res.body = "<html><body>hello</body></html>"
397
- end
398
- end
399
-
400
- class OneCookieServlet < WEBrick::HTTPServlet::AbstractServlet
401
- def do_GET(req, res)
402
- cookie = WEBrick::Cookie.new("foo", "bar")
403
- cookie.path = "/"
404
- cookie.expires = Time.now + 86400
405
- res.cookies << cookie
406
- res['Content-Type'] = "text/html"
407
- res.body = "<html><body>hello</body></html>"
408
- end
409
- end
410
-
411
- class QuotedValueCookieServlet < WEBrick::HTTPServlet::AbstractServlet
412
- def do_GET(req, res)
413
- cookie = WEBrick::Cookie.new("quoted", "\"value\"")
414
- cookie.path = "/"
415
- cookie.expires = Time.now + 86400
416
- res.cookies << cookie
417
- res['Content-Type'] = "text/html"
418
- res.body = "<html><body>hello</body></html>"
419
- end
420
- end
421
-
422
- class RedirectServlet < WEBrick::HTTPServlet::AbstractServlet
423
- def do_GET(req, res)
424
- res['Content-Type'] = req.query['ct'] || "text/html"
425
- res.status = req.query['code'] ? req.query['code'].to_i : '302'
426
- res['Location'] = "/verb"
427
- end
428
-
429
- alias :do_POST :do_GET
430
- alias :do_HEAD :do_GET
431
- alias :do_PUT :do_GET
432
- alias :do_DELETE :do_GET
433
- end
434
-
435
- class RefererServlet < WEBrick::HTTPServlet::AbstractServlet
436
- def do_GET(req, res)
437
- res['Content-Type'] = "text/html"
438
- res.body = req['Referer'] || ''
439
- end
440
-
441
- def do_POST(req, res)
442
- res['Content-Type'] = "text/html"
443
- res.body = req['Referer'] || ''
444
- end
445
- end
446
-
447
- class RefreshWithoutUrl < WEBrick::HTTPServlet::AbstractServlet
448
- @@count = 0
449
- def do_GET(req, res)
450
- res['Content-Type'] = "text/html"
451
- @@count += 1
452
- if @@count > 1
453
- res['Refresh'] = "0; url=http://localhost/index.html";
454
- else
455
- res['Refresh'] = "0";
456
- end
457
- end
458
- end
459
-
460
- class RefreshWithEmptyUrl < WEBrick::HTTPServlet::AbstractServlet
461
- @@count = 0
462
- def do_GET(req, res)
463
- res['Content-Type'] = "text/html"
464
- @@count += 1
465
- if @@count > 1
466
- res['Refresh'] = "0; url=http://localhost/index.html";
467
- else
468
- res['Refresh'] = "0; url=";
469
- end
470
- end
471
- end
472
-
473
- class ResponseCodeServlet < WEBrick::HTTPServlet::AbstractServlet
474
- def do_GET(req, res)
475
- res['Content-Type'] = req.query['ct'] || "text/html"
476
- if req.query['code']
477
- code = req.query['code'].to_i
478
- case code
479
- when 300, 301, 302, 303, 304, 305, 307
480
- res['Location'] = "/index.html"
481
- end
482
- res.status = code
483
- else
484
- end
485
- end
486
- end
487
-
488
- class SendCookiesServlet < WEBrick::HTTPServlet::AbstractServlet
489
- def do_GET(req, res)
490
- res['Content-Type'] = "text/html"
491
- res.body = "<html><body>"
492
- req.cookies.each { |c|
493
- res.body << "<a href=\"#\">#{c.name}:#{c.value}</a>"
494
- }
495
- res.body << "</body></html>"
496
- end
497
- end
498
-
499
- class VerbServlet < WEBrick::HTTPServlet::AbstractServlet
500
- %w(HEAD GET POST PUT DELETE).each do |verb|
501
- eval(<<-eomethod)
502
- def do_#{verb}(req, res)
503
- res.header['X-Request-Method'] = #{verb.dump}
504
- end
505
- eomethod
506
- end
507
- end
508
-
509
- class Net::HTTP
510
- alias :old_do_start :do_start
511
-
512
- def do_start
513
- @started = true
514
- end
515
-
516
- SERVLETS = {
517
- '/gzip' => GzipServlet,
518
- '/form_post' => FormServlet,
519
- '/basic_auth' => BasicAuthServlet,
520
- '/form post' => FormServlet,
521
- '/response_code' => ResponseCodeServlet,
522
- '/http_refresh' => HttpRefreshServlet,
523
- '/content_type_test' => ContentTypeServlet,
524
- '/referer' => RefererServlet,
525
- '/file_upload' => FileUploadServlet,
526
- '/one_cookie' => OneCookieServlet,
527
- '/one_cookie_no_space' => OneCookieNoSpacesServlet,
528
- '/many_cookies' => ManyCookiesServlet,
529
- '/many_cookies_as_string' => ManyCookiesAsStringServlet,
530
- '/ntlm' => NTLMServlet,
531
- '/send_cookies' => SendCookiesServlet,
532
- '/quoted_value_cookie' => QuotedValueCookieServlet,
533
- '/if_modified_since' => ModifiedSinceServlet,
534
- '/http_headers' => HeaderServlet,
535
- '/infinite_redirect' => InfiniteRedirectServlet,
536
- '/infinite_refresh' => InfiniteRefreshServlet,
537
- '/redirect' => RedirectServlet,
538
- '/refresh_without_url' => RefreshWithoutUrl,
539
- '/refresh_with_empty_url' => RefreshWithEmptyUrl,
540
- '/digest_auth' => DigestAuthServlet,
541
- '/verb' => VerbServlet,
542
- }
543
-
544
- PAGE_CACHE = {}
545
-
546
- alias :old_request :request
547
-
548
- def request(req, *data, &block)
549
- url = URI.parse(req.path)
550
- path = WEBrick::HTTPUtils.unescape(url.path)
551
-
552
- path = '/index.html' if path == '/'
553
-
554
- res = ::Response.new
555
- res.query_params = url.query
556
-
557
- req.query = if 'POST' != req.method && url.query then
558
- WEBrick::HTTPUtils.parse_query url.query
559
- elsif req['content-type'] =~ /www-form-urlencoded/ then
560
- WEBrick::HTTPUtils.parse_query req.body
561
- elsif req['content-type'] =~ /boundary=(.+)/ then
562
- boundary = WEBrick::HTTPUtils.dequote $1
563
- WEBrick::HTTPUtils.parse_form_data req.body, boundary
564
- else
565
- {}
566
- end
567
-
568
- req.cookies = WEBrick::Cookie.parse(req['Cookie'])
569
-
570
- Mechanize::TestCase::REQUESTS << req
571
-
572
- if servlet_klass = SERVLETS[path]
573
- servlet = servlet_klass.new({})
574
- servlet.send "do_#{req.method}", req, res
575
- else
576
- filename = "htdocs#{path.gsub(/[^\/\\.\w\s]/, '_')}"
577
- unless PAGE_CACHE[filename]
578
- open("#{Mechanize::TestCase::TEST_DIR}/#{filename}", 'rb') { |io|
579
- PAGE_CACHE[filename] = io.read
580
- }
581
- end
582
-
583
- res.body = PAGE_CACHE[filename]
584
- case filename
585
- when /\.txt$/
586
- res['Content-Type'] = 'text/plain'
587
- when /\.jpg$/
588
- res['Content-Type'] = 'image/jpeg'
589
- end
590
- end
591
-
592
- res['Content-Type'] ||= 'text/html'
593
- res.code ||= "200"
594
-
595
- response_klass = Net::HTTPResponse::CODE_TO_OBJ[res.code.to_s]
596
- response = response_klass.new res.http_version, res.code, res.message
597
-
598
- res.header.each do |k,v|
599
- v = v.first if v.length == 1
600
- response[k] = v
601
- end
602
-
603
- res.cookies.each do |cookie|
604
- response.add_field 'Set-Cookie', cookie.to_s
605
- end
606
-
607
- response['Content-Type'] ||= 'text/html'
608
- response['Content-Length'] = res['Content-Length'] || res.body.length.to_s
609
-
610
- io = StringIO.new(res.body)
611
- response.instance_variable_set :@socket, io
612
- def io.read clen, dest, _
613
- dest << string[0, clen]
614
- end
615
-
616
- body_exist = req.response_body_permitted? &&
617
- response_klass.body_permitted?
618
-
619
- response.instance_variable_set :@body_exist, body_exist
620
-
621
- yield response if block_given?
622
-
623
- response
624
- end
625
- end
626
-
627
- class Net::HTTPRequest
628
- attr_accessor :query, :body, :cookies, :user
629
- end
630
-
631
- class Response
632
- include Net::HTTPHeader
633
-
634
- attr_reader :code
635
- attr_accessor :body, :query, :cookies
636
- attr_accessor :query_params, :http_version
637
- attr_accessor :header
638
-
639
- def code=(c)
640
- @code = c.to_s
641
- end
642
-
643
- alias :status :code
644
- alias :status= :code=
645
-
646
- def initialize
647
- @header = {}
648
- @body = ''
649
- @code = nil
650
- @query = nil
651
- @cookies = []
652
- @http_version = '1.1'
653
- end
654
-
655
- def read_body
656
- yield body
657
- end
658
-
659
- def message
660
- ''
661
- end
662
- end
663
-