mechanize 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mechanize might be problematic. Click here for more details.

@@ -0,0 +1,171 @@
1
+ =begin
2
+
3
+ = $RCSfile: https.rb,v $ -- SSL/TLS enhancement for Net::HTTP.
4
+
5
+ == Info
6
+ 'OpenSSL for Ruby 2' project
7
+ Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org>
8
+ All rights reserved.
9
+
10
+ == Licence
11
+ This program is licenced under the same licence as Ruby.
12
+ (See the file 'LICENCE'.)
13
+
14
+ == Requirements
15
+ This program requires Net 1.2.0 or higher version.
16
+ You can get it from RAA or Ruby's CVS repository.
17
+
18
+ == Version
19
+ $Id: https.rb,v 1.3 2004/12/20 05:46:45 gotoyuzo Exp $
20
+
21
+ 2001-11-06: Contiributed to Ruby/OpenSSL project.
22
+ 2004-03-06: Some code is merged in to net/http.
23
+
24
+ == Example
25
+
26
+ Here is a simple HTTP client:
27
+
28
+ require 'net/http'
29
+ require 'uri'
30
+
31
+ uri = URI.parse(ARGV[0] || 'http://localhost/')
32
+ http = Net::HTTP.new(uri.host, uri.port)
33
+ http.start {
34
+ http.request_get(uri.path) {|res|
35
+ print res.body
36
+ }
37
+ }
38
+
39
+ It can be replaced by the following code:
40
+
41
+ require 'net/https'
42
+ require 'uri'
43
+
44
+ uri = URI.parse(ARGV[0] || 'https://localhost/')
45
+ http = Net::HTTP.new(uri.host, uri.port)
46
+ http.use_ssl = true if uri.scheme == "https" # enable SSL/TLS
47
+ http.start {
48
+ http.request_get(uri.path) {|res|
49
+ print res.body
50
+ }
51
+ }
52
+
53
+ == class Net::HTTP
54
+
55
+ === Instance Methods
56
+
57
+ : use_ssl?
58
+ returns true if use SSL/TLS with HTTP.
59
+
60
+ : use_ssl=((|true_or_false|))
61
+ sets use_ssl.
62
+
63
+ : peer_cert
64
+ return the X.509 certificates the server presented.
65
+
66
+ : key, key=((|key|))
67
+ Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
68
+ (This method is appeared in Michal Rokos's OpenSSL extention.)
69
+
70
+ : cert, cert=((|cert|))
71
+ Sets an OpenSSL::X509::Certificate object as client certificate
72
+ (This method is appeared in Michal Rokos's OpenSSL extention).
73
+
74
+ : ca_file, ca_file=((|path|))
75
+ Sets path of a CA certification file in PEM format.
76
+ The file can contrain several CA certificats.
77
+
78
+ : ca_path, ca_path=((|path|))
79
+ Sets path of a CA certification directory containing certifications
80
+ in PEM format.
81
+
82
+ : verify_mode, verify_mode=((|mode|))
83
+ Sets the flags for server the certification verification at
84
+ begining of SSL/TLS session.
85
+ OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
86
+
87
+ : verify_callback, verify_callback=((|proc|))
88
+ Sets the verify callback for the server certification verification.
89
+
90
+ : verify_depth, verify_depth=((|num|))
91
+ Sets the maximum depth for the certificate chain verification.
92
+
93
+ : cert_store, cert_store=((|store|))
94
+ Sets the X509::Store to verify peer certificate.
95
+
96
+ : ssl_timeout, ssl_timeout=((|sec|))
97
+ Sets the SSL timeout seconds.
98
+
99
+ =end
100
+
101
+ require 'net/http'
102
+ require 'openssl'
103
+
104
+ module Net
105
+
106
+ class HTTP
107
+ remove_method :use_ssl?
108
+ def use_ssl?
109
+ @use_ssl
110
+ end
111
+
112
+ alias use_ssl use_ssl? # for backward compatibility
113
+
114
+ # Turn on/off SSL.
115
+ # This flag must be set before starting session.
116
+ # If you change use_ssl value after session started,
117
+ # a Net::HTTP object raises IOError.
118
+ def use_ssl=(flag)
119
+ flag = (flag ? true : false)
120
+ raise IOError, "use_ssl value changed, but session already started" \
121
+ if started? and @use_ssl != flag
122
+ if flag and not @ssl_context
123
+ @ssl_context = OpenSSL::SSL::SSLContext.new
124
+ end
125
+ @use_ssl = flag
126
+ end
127
+
128
+ def self.ssl_context_accessor(name)
129
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
130
+ def #{name}
131
+ return nil unless @ssl_context
132
+ @ssl_context.#{name}
133
+ end
134
+
135
+ def #{name}=(val)
136
+ @ssl_context ||= OpenSSL::SSL::SSLContext.new
137
+ @ssl_context.#{name} = val
138
+ end
139
+ End
140
+ end
141
+
142
+ ssl_context_accessor :key
143
+ ssl_context_accessor :cert
144
+ ssl_context_accessor :ca_file
145
+ ssl_context_accessor :ca_path
146
+ ssl_context_accessor :verify_mode
147
+ ssl_context_accessor :verify_callback
148
+ ssl_context_accessor :verify_depth
149
+ ssl_context_accessor :cert_store
150
+
151
+ def ssl_timeout
152
+ return nil unless @ssl_context
153
+ @ssl_context.timeout
154
+ end
155
+
156
+ def ssl_timeout=(sec)
157
+ raise ArgumentError, 'Net::HTTP#ssl_timeout= called but use_ssl=false' \
158
+ unless use_ssl?
159
+ @ssl_context ||= OpenSSL::SSL::SSLContext.new
160
+ @ssl_context.timeout = sec
161
+ end
162
+
163
+ alias timeout= ssl_timeout= # for backward compatibility
164
+
165
+ def peer_cert
166
+ return nil if not use_ssl? or not @socket
167
+ @socket.io.peer_cert
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,380 @@
1
+ #
2
+ # = net/protocol.rb
3
+ #
4
+ #--
5
+ # Copyright (c) 1999-2004 Yukihiro Matsumoto
6
+ # Copyright (c) 1999-2004 Minero Aoki
7
+ #
8
+ # written and maintained by Minero Aoki <aamine@loveruby.net>
9
+ #
10
+ # This program is free software. You can re-distribute and/or
11
+ # modify this program under the same terms as Ruby itself,
12
+ # Ruby Distribute License or GNU General Public License.
13
+ #
14
+ # $Id: protocol.rb,v 1.78 2004/08/18 14:44:41 aamine Exp $
15
+ #++
16
+ #
17
+ # WARNING: This file is going to remove.
18
+ # Do not rely on the implementation written in this file.
19
+ #
20
+
21
+ require 'socket'
22
+ require 'timeout'
23
+
24
+ module Net # :nodoc:
25
+
26
+ class Protocol #:nodoc: internal use only
27
+ private
28
+ def Protocol.protocol_param(name, val)
29
+ module_eval(<<-End, __FILE__, __LINE__ + 1)
30
+ def #{name}
31
+ #{val}
32
+ end
33
+ End
34
+ end
35
+ end
36
+
37
+
38
+ class ProtocolError < StandardError; end
39
+ class ProtoSyntaxError < ProtocolError; end
40
+ class ProtoFatalError < ProtocolError; end
41
+ class ProtoUnknownError < ProtocolError; end
42
+ class ProtoServerError < ProtocolError; end
43
+ class ProtoAuthError < ProtocolError; end
44
+ class ProtoCommandError < ProtocolError; end
45
+ class ProtoRetriableError < ProtocolError; end
46
+ ProtocRetryError = ProtoRetriableError
47
+
48
+
49
+ class BufferedIO #:nodoc: internal use only
50
+ def initialize(io)
51
+ @io = io
52
+ @read_timeout = 60
53
+ @debug_output = nil
54
+ @rbuf = ''
55
+ end
56
+
57
+ attr_reader :io
58
+ attr_accessor :read_timeout
59
+ attr_accessor :debug_output
60
+
61
+ def inspect
62
+ "#<#{self.class} io=#{@io}>"
63
+ end
64
+
65
+ def closed?
66
+ @io.closed?
67
+ end
68
+
69
+ def close
70
+ @io.close
71
+ end
72
+
73
+ #
74
+ # Read
75
+ #
76
+
77
+ public
78
+
79
+ def read(len, dest = '', ignore_eof = false)
80
+ LOG "reading #{len} bytes..."
81
+ read_bytes = 0
82
+ begin
83
+ while read_bytes + @rbuf.size < len
84
+ dest << (s = rbuf_consume(@rbuf.size))
85
+ read_bytes += s.size
86
+ rbuf_fill
87
+ end
88
+ dest << (s = rbuf_consume(len - read_bytes))
89
+ read_bytes += s.size
90
+ rescue EOFError
91
+ raise unless ignore_eof
92
+ end
93
+ LOG "read #{read_bytes} bytes"
94
+ dest
95
+ end
96
+
97
+ def read_all(dest = '')
98
+ LOG 'reading all...'
99
+ read_bytes = 0
100
+ begin
101
+ while true
102
+ dest << (s = rbuf_consume(@rbuf.size))
103
+ read_bytes += s.size
104
+ rbuf_fill
105
+ end
106
+ rescue EOFError
107
+ ;
108
+ end
109
+ LOG "read #{read_bytes} bytes"
110
+ dest
111
+ end
112
+
113
+ def readuntil(terminator, ignore_eof = false)
114
+ begin
115
+ until idx = @rbuf.index(terminator)
116
+ rbuf_fill
117
+ end
118
+ return rbuf_consume(idx + terminator.size)
119
+ rescue EOFError
120
+ raise unless ignore_eof
121
+ return rbuf_consume(@rbuf.size)
122
+ end
123
+ end
124
+
125
+ def readline
126
+ readuntil("\n").chop
127
+ end
128
+
129
+ private
130
+
131
+ def rbuf_fill
132
+ timeout(@read_timeout) {
133
+ @rbuf << @io.sysread(1024)
134
+ }
135
+ end
136
+
137
+ def rbuf_consume(len)
138
+ s = @rbuf.slice!(0, len)
139
+ @debug_output << %Q[-> #{s.dump}\n] if @debug_output
140
+ s
141
+ end
142
+
143
+ #
144
+ # Write
145
+ #
146
+
147
+ public
148
+
149
+ def write(str)
150
+ writing {
151
+ write0 str
152
+ }
153
+ end
154
+
155
+ def writeline(str)
156
+ writing {
157
+ write0 str + "\r\n"
158
+ }
159
+ end
160
+
161
+ private
162
+
163
+ def writing
164
+ @written_bytes = 0
165
+ @debug_output << '<- ' if @debug_output
166
+ yield
167
+ @debug_output << "\n" if @debug_output
168
+ bytes = @written_bytes
169
+ @written_bytes = nil
170
+ bytes
171
+ end
172
+
173
+ def write0(str)
174
+ @debug_output << str.dump if @debug_output
175
+ len = @io.write(str)
176
+ @written_bytes += len
177
+ len
178
+ end
179
+
180
+ #
181
+ # Logging
182
+ #
183
+
184
+ private
185
+
186
+ def LOG_off
187
+ @save_debug_out = @debug_output
188
+ @debug_output = nil
189
+ end
190
+
191
+ def LOG_on
192
+ @debug_output = @save_debug_out
193
+ end
194
+
195
+ def LOG(msg)
196
+ return unless @debug_output
197
+ @debug_output << msg + "\n"
198
+ end
199
+ end
200
+
201
+
202
+ class InternetMessageIO < BufferedIO #:nodoc: internal use only
203
+ def initialize(io)
204
+ super
205
+ @wbuf = nil
206
+ end
207
+
208
+ #
209
+ # Read
210
+ #
211
+
212
+ def each_message_chunk
213
+ LOG 'reading message...'
214
+ LOG_off()
215
+ read_bytes = 0
216
+ while (line = readuntil("\r\n")) != ".\r\n"
217
+ read_bytes += line.size
218
+ yield line.sub(/\A\./, '')
219
+ end
220
+ LOG_on()
221
+ LOG "read message (#{read_bytes} bytes)"
222
+ end
223
+
224
+ # *library private* (cannot handle 'break')
225
+ def each_list_item
226
+ while (str = readuntil("\r\n")) != ".\r\n"
227
+ yield str.chop
228
+ end
229
+ end
230
+
231
+ def write_message_0(src)
232
+ prev = @written_bytes
233
+ each_crlf_line(src) do |line|
234
+ write0 line.sub(/\A\./, '..')
235
+ end
236
+ @written_bytes - prev
237
+ end
238
+
239
+ #
240
+ # Write
241
+ #
242
+
243
+ def write_message(src)
244
+ LOG "writing message from #{src.class}"
245
+ LOG_off()
246
+ len = writing {
247
+ using_each_crlf_line {
248
+ write_message_0 src
249
+ }
250
+ }
251
+ LOG_on()
252
+ LOG "wrote #{len} bytes"
253
+ len
254
+ end
255
+
256
+ def write_message_by_block(&block)
257
+ LOG 'writing message from block'
258
+ LOG_off()
259
+ len = writing {
260
+ using_each_crlf_line {
261
+ begin
262
+ block.call(WriteAdapter.new(self, :write_message_0))
263
+ rescue LocalJumpError
264
+ # allow `break' from writer block
265
+ end
266
+ }
267
+ }
268
+ LOG_on()
269
+ LOG "wrote #{len} bytes"
270
+ len
271
+ end
272
+
273
+ private
274
+
275
+ def using_each_crlf_line
276
+ @wbuf = ''
277
+ yield
278
+ if not @wbuf.empty? # unterminated last line
279
+ write0 @wbuf.chomp + "\r\n"
280
+ elsif @written_bytes == 0 # empty src
281
+ write0 "\r\n"
282
+ end
283
+ write0 ".\r\n"
284
+ @wbuf = nil
285
+ end
286
+
287
+ def each_crlf_line(src)
288
+ buffer_filling(@wbuf, src) do
289
+ while line = @wbuf.slice!(/\A.*(?:\n|\r\n|\r(?!\z))/n)
290
+ yield line.chomp("\n") + "\r\n"
291
+ end
292
+ end
293
+ end
294
+
295
+ def buffer_filling(buf, src)
296
+ case src
297
+ when String # for speeding up.
298
+ 0.step(src.size - 1, 1024) do |i|
299
+ buf << src[i, 1024]
300
+ yield
301
+ end
302
+ when File # for speeding up.
303
+ while s = src.read(1024)
304
+ buf << s
305
+ yield
306
+ end
307
+ else # generic reader
308
+ src.each do |s|
309
+ buf << s
310
+ yield if buf.size > 1024
311
+ end
312
+ yield unless buf.empty?
313
+ end
314
+ end
315
+ end
316
+
317
+
318
+ #
319
+ # The writer adapter class
320
+ #
321
+ class WriteAdapter
322
+ def initialize(socket, method)
323
+ @socket = socket
324
+ @method_id = method
325
+ end
326
+
327
+ def inspect
328
+ "#<#{self.class} socket=#{@socket.inspect}>"
329
+ end
330
+
331
+ def write(str)
332
+ @socket.__send__(@method_id, str)
333
+ end
334
+
335
+ alias print write
336
+
337
+ def <<(str)
338
+ write str
339
+ self
340
+ end
341
+
342
+ def puts(str = '')
343
+ write str.chomp("\n") + "\n"
344
+ end
345
+
346
+ def printf(*args)
347
+ write sprintf(*args)
348
+ end
349
+ end
350
+
351
+
352
+ class ReadAdapter #:nodoc: internal use only
353
+ def initialize(block)
354
+ @block = block
355
+ end
356
+
357
+ def inspect
358
+ "#<#{self.class}>"
359
+ end
360
+
361
+ def <<(str)
362
+ call_block(str, &@block) if @block
363
+ end
364
+
365
+ private
366
+
367
+ # This method is needed because @block must be called by yield,
368
+ # not Proc#call. You can see difference when using `break' in
369
+ # the block.
370
+ def call_block(str)
371
+ yield str
372
+ end
373
+ end
374
+
375
+
376
+ module NetPrivate #:nodoc: obsolete
377
+ Socket = ::Net::InternetMessageIO
378
+ end
379
+
380
+ end # module Net