jruby-openssl 0.9.5-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +218 -0
  3. data/License.txt +30 -0
  4. data/Mavenfile +44 -0
  5. data/README.txt +13 -0
  6. data/Rakefile +7 -0
  7. data/lib/jopenssl.jar +0 -0
  8. data/lib/jopenssl/load.rb +29 -0
  9. data/lib/jopenssl/version.rb +6 -0
  10. data/lib/jopenssl18/openssl.rb +23 -0
  11. data/lib/jopenssl18/openssl/bn.rb +35 -0
  12. data/lib/jopenssl18/openssl/buffering.rb +241 -0
  13. data/lib/jopenssl18/openssl/cipher.rb +65 -0
  14. data/lib/jopenssl18/openssl/config.rb +316 -0
  15. data/lib/jopenssl18/openssl/digest.rb +61 -0
  16. data/lib/jopenssl18/openssl/pkcs7.rb +25 -0
  17. data/lib/jopenssl18/openssl/ssl-internal.rb +179 -0
  18. data/lib/jopenssl18/openssl/ssl.rb +1 -0
  19. data/lib/jopenssl18/openssl/x509-internal.rb +153 -0
  20. data/lib/jopenssl18/openssl/x509.rb +1 -0
  21. data/lib/jopenssl19/openssl.rb +23 -0
  22. data/lib/jopenssl19/openssl/bn.rb +35 -0
  23. data/lib/jopenssl19/openssl/buffering.rb +449 -0
  24. data/lib/jopenssl19/openssl/cipher.rb +65 -0
  25. data/lib/jopenssl19/openssl/config.rb +313 -0
  26. data/lib/jopenssl19/openssl/digest.rb +72 -0
  27. data/lib/jopenssl19/openssl/ssl-internal.rb +177 -0
  28. data/lib/jopenssl19/openssl/ssl.rb +2 -0
  29. data/lib/jopenssl19/openssl/x509-internal.rb +158 -0
  30. data/lib/jopenssl19/openssl/x509.rb +2 -0
  31. data/lib/jopenssl21/openssl.rb +23 -0
  32. data/lib/jopenssl21/openssl/bn.rb +35 -0
  33. data/lib/jopenssl21/openssl/buffering.rb +449 -0
  34. data/lib/jopenssl21/openssl/cipher.rb +65 -0
  35. data/lib/jopenssl21/openssl/config.rb +313 -0
  36. data/lib/jopenssl21/openssl/digest.rb +89 -0
  37. data/lib/jopenssl21/openssl/ssl.rb +237 -0
  38. data/lib/jopenssl21/openssl/x509.rb +162 -0
  39. data/lib/jruby-openssl.rb +5 -0
  40. data/lib/openssl.rb +1 -0
  41. data/lib/openssl/bn.rb +7 -0
  42. data/lib/openssl/buffering.rb +7 -0
  43. data/lib/openssl/cipher.rb +7 -0
  44. data/lib/openssl/config.rb +7 -0
  45. data/lib/openssl/digest.rb +7 -0
  46. data/lib/openssl/pkcs12.rb +106 -0
  47. data/lib/openssl/pkcs7.rb +7 -0
  48. data/lib/openssl/ssl-internal.rb +7 -0
  49. data/lib/openssl/ssl.rb +7 -0
  50. data/lib/openssl/x509-internal.rb +7 -0
  51. data/lib/openssl/x509.rb +7 -0
  52. data/lib/org/bouncycastle/bcpkix-jdk15on/1.47/bcpkix-jdk15on-1.47.jar +0 -0
  53. data/lib/org/bouncycastle/bcprov-jdk15on/1.47/bcprov-jdk15on-1.47.jar +0 -0
  54. metadata +97 -0
@@ -0,0 +1,177 @@
1
+ =begin
2
+ = $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id$
15
+ =end
16
+
17
+ require "openssl/buffering"
18
+ require "fcntl"
19
+
20
+ module OpenSSL
21
+ module SSL
22
+ class SSLContext
23
+ DEFAULT_PARAMS = {
24
+ :ssl_version => "SSLv23",
25
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
26
+ :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
27
+ :options => OpenSSL::SSL::OP_ALL,
28
+ }
29
+
30
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
31
+ DEFAULT_CERT_STORE.set_default_paths
32
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
33
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
34
+ end
35
+
36
+ def set_params(params={})
37
+ params = DEFAULT_PARAMS.merge(params)
38
+ params.each{|name, value| self.__send__("#{name}=", value) }
39
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
40
+ unless self.ca_file or self.ca_path or self.cert_store
41
+ self.cert_store = DEFAULT_CERT_STORE
42
+ end
43
+ end
44
+ return params
45
+ end
46
+ end
47
+
48
+ module SocketForwarder
49
+ def addr
50
+ to_io.addr
51
+ end
52
+
53
+ def peeraddr
54
+ to_io.peeraddr
55
+ end
56
+
57
+ def setsockopt(level, optname, optval)
58
+ to_io.setsockopt(level, optname, optval)
59
+ end
60
+
61
+ def getsockopt(level, optname)
62
+ to_io.getsockopt(level, optname)
63
+ end
64
+
65
+ def fcntl(*args)
66
+ to_io.fcntl(*args)
67
+ end
68
+
69
+ def closed?
70
+ to_io.closed?
71
+ end
72
+
73
+ def do_not_reverse_lookup=(flag)
74
+ to_io.do_not_reverse_lookup = flag
75
+ end
76
+ end
77
+
78
+ module Nonblock
79
+ def initialize(*args)
80
+ flag = File::NONBLOCK
81
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
82
+ @io.fcntl(Fcntl::F_SETFL, flag)
83
+ super
84
+ end
85
+ end
86
+
87
+ def verify_certificate_identity(cert, hostname)
88
+ should_verify_common_name = true
89
+ cert.extensions.each{|ext|
90
+ next if ext.oid != "subjectAltName"
91
+ ext.value.split(/,\s+/).each{|general_name|
92
+ if /\ADNS:(.*)/ =~ general_name
93
+ should_verify_common_name = false
94
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
95
+ return true if /\A#{reg}\z/i =~ hostname
96
+ elsif /\AIP Address:(.*)/ =~ general_name
97
+ should_verify_common_name = false
98
+ return true if $1 == hostname
99
+ end
100
+ }
101
+ }
102
+ if should_verify_common_name
103
+ cert.subject.to_a.each{|oid, value|
104
+ if oid == "CN"
105
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
106
+ return true if /\A#{reg}\z/i =~ hostname
107
+ end
108
+ }
109
+ end
110
+ return false
111
+ end
112
+ module_function :verify_certificate_identity
113
+
114
+ class SSLSocket
115
+ include Buffering
116
+ include SocketForwarder
117
+ include Nonblock
118
+
119
+ def post_connection_check(hostname)
120
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
121
+ raise SSLError, "hostname does not match the server certificate"
122
+ end
123
+ return true
124
+ end
125
+
126
+ def session
127
+ SSL::Session.new(self)
128
+ rescue SSL::Session::SessionError
129
+ nil
130
+ end
131
+ end
132
+
133
+ class SSLServer
134
+ include SocketForwarder
135
+ attr_accessor :start_immediately
136
+
137
+ def initialize(svr, ctx)
138
+ @svr = svr
139
+ @ctx = ctx
140
+ unless ctx.session_id_context
141
+ session_id = OpenSSL::Digest::MD5.hexdigest($0)
142
+ @ctx.session_id_context = session_id
143
+ end
144
+ @start_immediately = true
145
+ end
146
+
147
+ def to_io
148
+ @svr
149
+ end
150
+
151
+ def listen(backlog=5)
152
+ @svr.listen(backlog)
153
+ end
154
+
155
+ def shutdown(how=Socket::SHUT_RDWR)
156
+ @svr.shutdown(how)
157
+ end
158
+
159
+ def accept
160
+ sock = @svr.accept
161
+ begin
162
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
163
+ ssl.sync_close = true
164
+ ssl.accept if @start_immediately
165
+ ssl
166
+ rescue SSLError => ex
167
+ sock.close
168
+ raise ex
169
+ end
170
+ end
171
+
172
+ def close
173
+ @svr.close
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,2 @@
1
+ warn 'deprecated openssl/ssl use: require "openssl" instead of "openssl/ssl"'
2
+ require 'openssl'
@@ -0,0 +1,158 @@
1
+ =begin
2
+ = $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id$
15
+ =end
16
+
17
+ module OpenSSL
18
+ module X509
19
+ class ExtensionFactory
20
+ def create_extension(*arg)
21
+ if arg.size > 1
22
+ create_ext(*arg)
23
+ else
24
+ send("create_ext_from_"+arg[0].class.name.downcase, arg[0])
25
+ end
26
+ end
27
+
28
+ def create_ext_from_array(ary)
29
+ raise ExtensionError, "unexpected array form" if ary.size > 3
30
+ create_ext(ary[0], ary[1], ary[2])
31
+ end
32
+
33
+ def create_ext_from_string(str) # "oid = critical, value"
34
+ oid, value = str.split(/=/, 2)
35
+ oid.strip!
36
+ value.strip!
37
+ create_ext(oid, value)
38
+ end
39
+
40
+ def create_ext_from_hash(hash)
41
+ create_ext(hash["oid"], hash["value"], hash["critical"])
42
+ end
43
+ end
44
+
45
+ class Extension
46
+ def to_s # "oid = critical, value"
47
+ str = self.oid
48
+ str << " = "
49
+ str << "critical, " if self.critical?
50
+ str << self.value.gsub(/\n/, ", ")
51
+ end
52
+
53
+ def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
54
+ {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
55
+ end
56
+
57
+ def to_a
58
+ [ self.oid, self.value, self.critical? ]
59
+ end
60
+ end
61
+
62
+ class Name
63
+ module RFC2253DN
64
+ Special = ',=+<>#;'
65
+ HexChar = /[0-9a-fA-F]/
66
+ HexPair = /#{HexChar}#{HexChar}/
67
+ HexString = /#{HexPair}+/
68
+ Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
69
+ StringChar = /[^#{Special}\\"]/
70
+ QuoteChar = /[^\\"]/
71
+ AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
72
+ AttributeValue = /
73
+ (?!["#])((?:#{StringChar}|#{Pair})*)|
74
+ \#(#{HexString})|
75
+ "((?:#{QuoteChar}|#{Pair})*)"
76
+ /x
77
+ TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
78
+
79
+ module_function
80
+
81
+ def expand_pair(str)
82
+ return nil unless str
83
+ return str.gsub(Pair){
84
+ pair = $&
85
+ case pair.size
86
+ when 2 then pair[1,1]
87
+ when 3 then Integer("0x#{pair[1,2]}").chr
88
+ else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
89
+ end
90
+ }
91
+ end
92
+
93
+ def expand_hexstring(str)
94
+ return nil unless str
95
+ der = str.gsub(HexPair){$&.to_i(16).chr }
96
+ a1 = OpenSSL::ASN1.decode(der)
97
+ return a1.value, a1.tag
98
+ end
99
+
100
+ def expand_value(str1, str2, str3)
101
+ value = expand_pair(str1)
102
+ value, tag = expand_hexstring(str2) unless value
103
+ value = expand_pair(str3) unless value
104
+ return value, tag
105
+ end
106
+
107
+ def scan(dn)
108
+ str = dn
109
+ ary = []
110
+ while true
111
+ if md = TypeAndValue.match(str)
112
+ remain = md.post_match
113
+ type = md[1]
114
+ value, tag = expand_value(md[2], md[3], md[4]) rescue nil
115
+ if value
116
+ type_and_value = [type, value]
117
+ type_and_value.push(tag) if tag
118
+ ary.unshift(type_and_value)
119
+ if remain.length > 2 && remain[0] == ?,
120
+ str = remain[1..-1]
121
+ next
122
+ elsif remain.length > 2 && remain[0] == ?+
123
+ raise OpenSSL::X509::NameError,
124
+ "multi-valued RDN is not supported: #{dn}"
125
+ elsif remain.empty?
126
+ break
127
+ end
128
+ end
129
+ end
130
+ msg_dn = dn[0, dn.length - str.length] + " =>" + str
131
+ raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
132
+ end
133
+ return ary
134
+ end
135
+ end
136
+
137
+ class << self
138
+ def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
139
+ ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
140
+ self.new(ary, template)
141
+ end
142
+
143
+ def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
144
+ ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
145
+ self.new(ary, template)
146
+ end
147
+
148
+ alias parse parse_openssl
149
+ end
150
+ end
151
+
152
+ class StoreContext
153
+ def cleanup
154
+ warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,2 @@
1
+ warn 'deprecated openssl/x509 use: require "openssl" instead of "openssl/x509"'
2
+ require 'openssl'
@@ -0,0 +1,23 @@
1
+ =begin
2
+ = $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id$
15
+ =end
16
+
17
+ require 'openssl/bn'
18
+ require 'openssl/cipher'
19
+ require 'openssl/config'
20
+ require 'openssl/digest'
21
+ require 'openssl/x509'
22
+ require 'openssl/ssl'
23
+ require 'krypt/ossl'
@@ -0,0 +1,35 @@
1
+ #--
2
+ #
3
+ # $RCSfile$
4
+ #
5
+ # = Ruby-space definitions that completes C-space funcs for BN
6
+ #
7
+ # = Info
8
+ # 'OpenSSL for Ruby 2' project
9
+ # Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
10
+ # All rights reserved.
11
+ #
12
+ # = Licence
13
+ # This program is licenced under the same licence as Ruby.
14
+ # (See the file 'LICENCE'.)
15
+ #
16
+ # = Version
17
+ # $Id$
18
+ #
19
+ #++
20
+
21
+ module OpenSSL
22
+ class BN
23
+ include Comparable
24
+ end # BN
25
+ end # OpenSSL
26
+
27
+ ##
28
+ # Add double dispatch to Integer
29
+ #
30
+ class Integer
31
+ def to_bn
32
+ OpenSSL::BN::new(self)
33
+ end
34
+ end # Integer
35
+
@@ -0,0 +1,449 @@
1
+ =begin
2
+ = $RCSfile$ -- Buffering mix-in module.
3
+
4
+ = Info
5
+ 'OpenSSL for Ruby 2' project
6
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
7
+ All rights reserved.
8
+
9
+ = Licence
10
+ This program is licenced under the same licence as Ruby.
11
+ (See the file 'LICENCE'.)
12
+
13
+ = Version
14
+ $Id$
15
+ =end
16
+
17
+ ##
18
+ # OpenSSL IO buffering mix-in module.
19
+ #
20
+ # This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
21
+
22
+ module OpenSSL::Buffering
23
+ include Enumerable
24
+
25
+ ##
26
+ # The "sync mode" of the SSLSocket.
27
+ #
28
+ # See IO#sync for full details.
29
+
30
+ attr_accessor :sync
31
+
32
+ ##
33
+ # Default size to read from or write to the SSLSocket for buffer operations.
34
+
35
+ BLOCK_SIZE = 1024*16
36
+
37
+ def initialize(*args)
38
+ @eof = false
39
+ @rbuffer = ""
40
+ @sync = @io.sync
41
+ end
42
+
43
+ #
44
+ # for reading.
45
+ #
46
+ private
47
+
48
+ ##
49
+ # Fills the buffer from the underlying SSLSocket
50
+
51
+ def fill_rbuff
52
+ begin
53
+ @rbuffer << self.sysread(BLOCK_SIZE)
54
+ rescue Errno::EAGAIN
55
+ retry
56
+ rescue EOFError
57
+ @eof = true
58
+ end
59
+ end
60
+
61
+ ##
62
+ # Consumes +size+ bytes from the buffer
63
+
64
+ def consume_rbuff(size=nil)
65
+ if @rbuffer.empty?
66
+ nil
67
+ else
68
+ size = @rbuffer.size unless size
69
+ ret = @rbuffer[0, size]
70
+ @rbuffer[0, size] = ""
71
+ ret
72
+ end
73
+ end
74
+
75
+ public
76
+
77
+ ##
78
+ # Reads +size+ bytes from the stream. If +buf+ is provided it must
79
+ # reference a string which will receive the data.
80
+ #
81
+ # See IO#read for full details.
82
+
83
+ def read(size=nil, buf=nil)
84
+ if size == 0
85
+ if buf
86
+ buf.clear
87
+ return buf
88
+ else
89
+ return ""
90
+ end
91
+ end
92
+ until @eof
93
+ break if size && size <= @rbuffer.size
94
+ fill_rbuff
95
+ end
96
+ ret = consume_rbuff(size) || ""
97
+ if buf
98
+ buf.replace(ret)
99
+ ret = buf
100
+ end
101
+ (size && ret.empty?) ? nil : ret
102
+ end
103
+
104
+ ##
105
+ # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it
106
+ # must reference a string which will receive the data.
107
+ #
108
+ # See IO#readpartial for full details.
109
+
110
+ def readpartial(maxlen, buf=nil)
111
+ if maxlen == 0
112
+ if buf
113
+ buf.clear
114
+ return buf
115
+ else
116
+ return ""
117
+ end
118
+ end
119
+ if @rbuffer.empty?
120
+ begin
121
+ return sysread(maxlen, buf)
122
+ rescue Errno::EAGAIN
123
+ retry
124
+ end
125
+ end
126
+ ret = consume_rbuff(maxlen)
127
+ if buf
128
+ buf.replace(ret)
129
+ ret = buf
130
+ end
131
+ raise EOFError if ret.empty?
132
+ ret
133
+ end
134
+
135
+ ##
136
+ # Reads at most +maxlen+ bytes in the non-blocking manner.
137
+ #
138
+ # When no data can be read without blocking it raises
139
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
140
+ #
141
+ # IO::WaitReadable means SSL needs to read internally so read_nonblock
142
+ # should be called again when the underlying IO is readable.
143
+ #
144
+ # IO::WaitWritable means SSL needs to write internally so read_nonblock
145
+ # should be called again after the underlying IO is writable.
146
+ #
147
+ # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
148
+ #
149
+ # # emulates blocking read (readpartial).
150
+ # begin
151
+ # result = ssl.read_nonblock(maxlen)
152
+ # rescue IO::WaitReadable
153
+ # IO.select([io])
154
+ # retry
155
+ # rescue IO::WaitWritable
156
+ # IO.select(nil, [io])
157
+ # retry
158
+ # end
159
+ #
160
+ # Note that one reason that read_nonblock writes to the underlying IO is
161
+ # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for
162
+ # more details. http://www.openssl.org/support/faq.html
163
+
164
+ def read_nonblock(maxlen, buf=nil, exception: true)
165
+ if maxlen == 0
166
+ if buf
167
+ buf.clear
168
+ return buf
169
+ else
170
+ return ""
171
+ end
172
+ end
173
+ if @rbuffer.empty?
174
+ return sysread_nonblock(maxlen, buf, exception: exception)
175
+ end
176
+ ret = consume_rbuff(maxlen)
177
+ if buf
178
+ buf.replace(ret)
179
+ ret = buf
180
+ end
181
+ raise EOFError if ret.empty?
182
+ ret
183
+ end
184
+
185
+ ##
186
+ # Reads the next "line+ from the stream. Lines are separated by +eol+. If
187
+ # +limit+ is provided the result will not be longer than the given number of
188
+ # bytes.
189
+ #
190
+ # +eol+ may be a String or Regexp.
191
+ #
192
+ # Unlike IO#gets the line read will not be assigned to +$_+.
193
+ #
194
+ # Unlike IO#gets the separator must be provided if a limit is provided.
195
+
196
+ def gets(eol=$/, limit=nil)
197
+ idx = @rbuffer.index(eol)
198
+ until @eof
199
+ break if idx
200
+ fill_rbuff
201
+ idx = @rbuffer.index(eol)
202
+ end
203
+ if eol.is_a?(Regexp)
204
+ size = idx ? idx+$&.size : nil
205
+ else
206
+ size = idx ? idx+eol.size : nil
207
+ end
208
+ if limit and limit >= 0
209
+ size = [size, limit].min
210
+ end
211
+ consume_rbuff(size)
212
+ end
213
+
214
+ ##
215
+ # Executes the block for every line in the stream where lines are separated
216
+ # by +eol+.
217
+ #
218
+ # See also #gets
219
+
220
+ def each(eol=$/)
221
+ while line = self.gets(eol)
222
+ yield line
223
+ end
224
+ end
225
+ alias each_line each
226
+
227
+ ##
228
+ # Reads lines from the stream which are separated by +eol+.
229
+ #
230
+ # See also #gets
231
+
232
+ def readlines(eol=$/)
233
+ ary = []
234
+ while line = self.gets(eol)
235
+ ary << line
236
+ end
237
+ ary
238
+ end
239
+
240
+ ##
241
+ # Reads a line from the stream which is separated by +eol+.
242
+ #
243
+ # Raises EOFError if at end of file.
244
+
245
+ def readline(eol=$/)
246
+ raise EOFError if eof?
247
+ gets(eol)
248
+ end
249
+
250
+ ##
251
+ # Reads one character from the stream. Returns nil if called at end of
252
+ # file.
253
+
254
+ def getc
255
+ read(1)
256
+ end
257
+
258
+ ##
259
+ # Calls the given block once for each byte in the stream.
260
+
261
+ def each_byte # :yields: byte
262
+ while c = getc
263
+ yield(c.ord)
264
+ end
265
+ end
266
+
267
+ ##
268
+ # Reads a one-character string from the stream. Raises an EOFError at end
269
+ # of file.
270
+
271
+ def readchar
272
+ raise EOFError if eof?
273
+ getc
274
+ end
275
+
276
+ ##
277
+ # Pushes character +c+ back onto the stream such that a subsequent buffered
278
+ # character read will return it.
279
+ #
280
+ # Unlike IO#getc multiple bytes may be pushed back onto the stream.
281
+ #
282
+ # Has no effect on unbuffered reads (such as #sysread).
283
+
284
+ def ungetc(c)
285
+ @rbuffer[0,0] = c.chr
286
+ end
287
+
288
+ ##
289
+ # Returns true if the stream is at file which means there is no more data to
290
+ # be read.
291
+
292
+ def eof?
293
+ fill_rbuff if !@eof && @rbuffer.empty?
294
+ @eof && @rbuffer.empty?
295
+ end
296
+ alias eof eof?
297
+
298
+ #
299
+ # for writing.
300
+ #
301
+ private
302
+
303
+ ##
304
+ # Writes +s+ to the buffer. When the buffer is full or #sync is true the
305
+ # buffer is flushed to the underlying socket.
306
+
307
+ def do_write(s)
308
+ @wbuffer = "" unless defined? @wbuffer
309
+ @wbuffer << s
310
+ @wbuffer.force_encoding(Encoding::BINARY)
311
+ @sync ||= false
312
+ if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
313
+ remain = idx ? idx + $/.size : @wbuffer.length
314
+ nwritten = 0
315
+ while remain > 0
316
+ str = @wbuffer[nwritten,remain]
317
+ begin
318
+ nwrote = syswrite(str)
319
+ rescue Errno::EAGAIN
320
+ retry
321
+ end
322
+ remain -= nwrote
323
+ nwritten += nwrote
324
+ end
325
+ @wbuffer[0,nwritten] = ""
326
+ end
327
+ end
328
+
329
+ public
330
+
331
+ ##
332
+ # Writes +s+ to the stream. If the argument is not a string it will be
333
+ # converted using String#to_s. Returns the number of bytes written.
334
+
335
+ def write(s)
336
+ do_write(s)
337
+ s.bytesize
338
+ end
339
+
340
+ ##
341
+ # Writes +str+ in the non-blocking manner.
342
+ #
343
+ # If there is buffered data, it is flushed first. This may block.
344
+ #
345
+ # write_nonblock returns number of bytes written to the SSL connection.
346
+ #
347
+ # When no data can be written without blocking it raises
348
+ # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
349
+ #
350
+ # IO::WaitReadable means SSL needs to read internally so write_nonblock
351
+ # should be called again after the underlying IO is readable.
352
+ #
353
+ # IO::WaitWritable means SSL needs to write internally so write_nonblock
354
+ # should be called again after underlying IO is writable.
355
+ #
356
+ # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows.
357
+ #
358
+ # # emulates blocking write.
359
+ # begin
360
+ # result = ssl.write_nonblock(str)
361
+ # rescue IO::WaitReadable
362
+ # IO.select([io])
363
+ # retry
364
+ # rescue IO::WaitWritable
365
+ # IO.select(nil, [io])
366
+ # retry
367
+ # end
368
+ #
369
+ # Note that one reason that write_nonblock reads from the underlying IO
370
+ # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ
371
+ # for more details. http://www.openssl.org/support/faq.html
372
+
373
+ def write_nonblock(s, exception: true)
374
+ flush
375
+ syswrite_nonblock(s, exception: exception)
376
+ end
377
+
378
+ ##
379
+ # Writes +s+ to the stream. +s+ will be converted to a String using
380
+ # String#to_s.
381
+
382
+ def << (s)
383
+ do_write(s)
384
+ self
385
+ end
386
+
387
+ ##
388
+ # Writes +args+ to the stream along with a record separator.
389
+ #
390
+ # See IO#puts for full details.
391
+
392
+ def puts(*args)
393
+ s = ""
394
+ if args.empty?
395
+ s << "\n"
396
+ end
397
+ args.each{|arg|
398
+ s << arg.to_s
399
+ if $/ && /\n\z/ !~ s
400
+ s << "\n"
401
+ end
402
+ }
403
+ do_write(s)
404
+ nil
405
+ end
406
+
407
+ ##
408
+ # Writes +args+ to the stream.
409
+ #
410
+ # See IO#print for full details.
411
+
412
+ def print(*args)
413
+ s = ""
414
+ args.each{ |arg| s << arg.to_s }
415
+ do_write(s)
416
+ nil
417
+ end
418
+
419
+ ##
420
+ # Formats and writes to the stream converting parameters under control of
421
+ # the format string.
422
+ #
423
+ # See Kernel#sprintf for format string details.
424
+
425
+ def printf(s, *args)
426
+ do_write(s % args)
427
+ nil
428
+ end
429
+
430
+ ##
431
+ # Flushes buffered data to the SSLSocket.
432
+
433
+ def flush
434
+ osync = @sync
435
+ @sync = true
436
+ do_write ""
437
+ return self
438
+ ensure
439
+ @sync = osync
440
+ end
441
+
442
+ ##
443
+ # Closes the SSLSocket and flushes any unwritten data.
444
+
445
+ def close
446
+ flush rescue nil
447
+ sysclose
448
+ end
449
+ end