diamond-mechanize 2.1 → 2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
-