jruby-openssl-maven 0.7.4.1
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.
- data/History.txt +171 -0
- data/License.txt +30 -0
- data/Manifest.txt +115 -0
- data/README.txt +13 -0
- data/Rakefile +79 -0
- data/lib/jopenssl.jar +0 -0
- data/lib/jopenssl/version.rb +5 -0
- data/lib/openssl.rb +76 -0
- data/lib/openssl/bn.rb +35 -0
- data/lib/openssl/buffering.rb +239 -0
- data/lib/openssl/cipher.rb +65 -0
- data/lib/openssl/config.rb +316 -0
- data/lib/openssl/digest.rb +61 -0
- data/lib/openssl/dummy.rb +33 -0
- data/lib/openssl/dummyssl.rb +14 -0
- data/lib/openssl/pkcs7.rb +25 -0
- data/lib/openssl/ssl.rb +179 -0
- data/lib/openssl/x509.rb +154 -0
- data/test/cert_with_ec_pk.cer +27 -0
- data/test/fixture/ca-bundle.crt +2794 -0
- data/test/fixture/ca_path/72fa7371.0 +19 -0
- data/test/fixture/ca_path/verisign.pem +19 -0
- data/test/fixture/cacert.pem +23 -0
- data/test/fixture/cert_localhost.pem +19 -0
- data/test/fixture/common.pem +48 -0
- data/test/fixture/imaps/cacert.pem +60 -0
- data/test/fixture/imaps/server.crt +61 -0
- data/test/fixture/imaps/server.key +15 -0
- data/test/fixture/key_then_cert.pem +34 -0
- data/test/fixture/keypair.pem +27 -0
- data/test/fixture/localhost_keypair.pem +18 -0
- data/test/fixture/max.pem +29 -0
- data/test/fixture/purpose/b70a5bc1.0 +24 -0
- data/test/fixture/purpose/ca/PASSWD_OF_CA_KEY_IS_1234 +0 -0
- data/test/fixture/purpose/ca/ca_config.rb +37 -0
- data/test/fixture/purpose/ca/cacert.pem +24 -0
- data/test/fixture/purpose/ca/newcerts/2_cert.pem +19 -0
- data/test/fixture/purpose/ca/newcerts/3_cert.pem +19 -0
- data/test/fixture/purpose/ca/private/cakeypair.pem +30 -0
- data/test/fixture/purpose/ca/serial +1 -0
- data/test/fixture/purpose/cacert.pem +24 -0
- data/test/fixture/purpose/scripts/gen_cert.rb +127 -0
- data/test/fixture/purpose/scripts/gen_csr.rb +50 -0
- data/test/fixture/purpose/scripts/init_ca.rb +66 -0
- data/test/fixture/purpose/sslclient.pem +19 -0
- data/test/fixture/purpose/sslclient/csr.pem +10 -0
- data/test/fixture/purpose/sslclient/keypair.pem +15 -0
- data/test/fixture/purpose/sslclient/sslclient.pem +19 -0
- data/test/fixture/purpose/sslserver.pem +19 -0
- data/test/fixture/purpose/sslserver/csr.pem +10 -0
- data/test/fixture/purpose/sslserver/keypair.pem +15 -0
- data/test/fixture/purpose/sslserver/sslserver.pem +19 -0
- data/test/fixture/selfcert.pem +23 -0
- data/test/fixture/verisign.pem +19 -0
- data/test/fixture/verisign_c3.pem +14 -0
- data/test/java/pkcs7_mime_enveloped.message +19 -0
- data/test/java/pkcs7_mime_signed.message +30 -0
- data/test/java/pkcs7_multipart_signed.message +45 -0
- data/test/java/test_java_attribute.rb +25 -0
- data/test/java/test_java_bio.rb +42 -0
- data/test/java/test_java_mime.rb +173 -0
- data/test/java/test_java_pkcs7.rb +772 -0
- data/test/java/test_java_smime.rb +177 -0
- data/test/openssl/ssl_server.rb +99 -0
- data/test/openssl/test_asn1.rb +197 -0
- data/test/openssl/test_cipher.rb +193 -0
- data/test/openssl/test_config.rb +290 -0
- data/test/openssl/test_digest.rb +88 -0
- data/test/openssl/test_ec.rb +128 -0
- data/test/openssl/test_hmac.rb +46 -0
- data/test/openssl/test_ns_spki.rb +59 -0
- data/test/openssl/test_pair.rb +141 -0
- data/test/openssl/test_pkcs7.rb +489 -0
- data/test/openssl/test_pkey_rsa.rb +49 -0
- data/test/openssl/test_ssl.rb +1035 -0
- data/test/openssl/test_x509cert.rb +277 -0
- data/test/openssl/test_x509crl.rb +253 -0
- data/test/openssl/test_x509ext.rb +99 -0
- data/test/openssl/test_x509name.rb +290 -0
- data/test/openssl/test_x509req.rb +195 -0
- data/test/openssl/test_x509store.rb +246 -0
- data/test/openssl/utils.rb +144 -0
- data/test/ref/a.out +0 -0
- data/test/ref/compile.rb +8 -0
- data/test/ref/pkcs1 +0 -0
- data/test/ref/pkcs1.c +21 -0
- data/test/test_all.rb +1 -0
- data/test/test_certificate.rb +123 -0
- data/test/test_cipher.rb +197 -0
- data/test/test_imaps.rb +107 -0
- data/test/test_integration.rb +144 -0
- data/test/test_java.rb +98 -0
- data/test/test_openssl.rb +4 -0
- data/test/test_parse_certificate.rb +27 -0
- data/test/test_pkcs7.rb +40 -0
- data/test/test_pkey.rb +204 -0
- data/test/test_ssl.rb +97 -0
- data/test/test_x509store.rb +160 -0
- data/test/ut_eof.rb +128 -0
- metadata +161 -0
data/lib/openssl/bn.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for BN
|
|
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: bn.rb 11708 2007-02-12 23:01:19Z shyouhei $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Should we care what if somebody require this file directly?
|
|
19
|
+
#require 'openssl'
|
|
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,239 @@
|
|
|
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: buffering.rb 13706 2007-10-15 08:29:08Z usa $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
module Buffering
|
|
18
|
+
include Enumerable
|
|
19
|
+
attr_accessor :sync
|
|
20
|
+
BLOCK_SIZE = 1024*16
|
|
21
|
+
|
|
22
|
+
def initialize(*args)
|
|
23
|
+
@eof = false
|
|
24
|
+
@rbuffer = ""
|
|
25
|
+
@sync = @io.sync
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# for reading.
|
|
30
|
+
#
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def fill_rbuff
|
|
34
|
+
begin
|
|
35
|
+
@rbuffer << self.sysread(BLOCK_SIZE)
|
|
36
|
+
rescue Errno::EAGAIN
|
|
37
|
+
retry
|
|
38
|
+
rescue EOFError
|
|
39
|
+
@eof = true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def consume_rbuff(size=nil)
|
|
44
|
+
if @rbuffer.empty?
|
|
45
|
+
nil
|
|
46
|
+
else
|
|
47
|
+
size = @rbuffer.size unless size
|
|
48
|
+
ret = @rbuffer[0, size]
|
|
49
|
+
@rbuffer[0, size] = ""
|
|
50
|
+
ret
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
public
|
|
55
|
+
|
|
56
|
+
def read(size=nil, buf=nil)
|
|
57
|
+
if size == 0
|
|
58
|
+
if buf
|
|
59
|
+
buf.clear
|
|
60
|
+
else
|
|
61
|
+
buf = ""
|
|
62
|
+
end
|
|
63
|
+
return @eof ? nil : buf
|
|
64
|
+
end
|
|
65
|
+
until @eof
|
|
66
|
+
break if size && size <= @rbuffer.size
|
|
67
|
+
fill_rbuff
|
|
68
|
+
end
|
|
69
|
+
ret = consume_rbuff(size) || ""
|
|
70
|
+
if buf
|
|
71
|
+
buf.replace(ret)
|
|
72
|
+
ret = buf
|
|
73
|
+
end
|
|
74
|
+
(size && ret.empty?) ? nil : ret
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def readpartial(maxlen, buf=nil)
|
|
78
|
+
if maxlen == 0
|
|
79
|
+
if buf
|
|
80
|
+
buf.clear
|
|
81
|
+
else
|
|
82
|
+
buf = ""
|
|
83
|
+
end
|
|
84
|
+
return @eof ? nil : buf
|
|
85
|
+
end
|
|
86
|
+
if @rbuffer.empty?
|
|
87
|
+
begin
|
|
88
|
+
return sysread(maxlen, buf)
|
|
89
|
+
rescue Errno::EAGAIN
|
|
90
|
+
retry
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
ret = consume_rbuff(maxlen)
|
|
94
|
+
if buf
|
|
95
|
+
buf.replace(ret)
|
|
96
|
+
ret = buf
|
|
97
|
+
end
|
|
98
|
+
raise EOFError if ret.empty?
|
|
99
|
+
ret
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def gets(eol=$/)
|
|
103
|
+
idx = @rbuffer.index(eol)
|
|
104
|
+
until @eof
|
|
105
|
+
break if idx
|
|
106
|
+
fill_rbuff
|
|
107
|
+
idx = @rbuffer.index(eol)
|
|
108
|
+
end
|
|
109
|
+
if eol.is_a?(Regexp)
|
|
110
|
+
size = idx ? idx+$&.size : nil
|
|
111
|
+
else
|
|
112
|
+
size = idx ? idx+eol.size : nil
|
|
113
|
+
end
|
|
114
|
+
consume_rbuff(size)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def each(eol=$/)
|
|
118
|
+
while line = self.gets(eol)
|
|
119
|
+
yield line
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
alias each_line each
|
|
123
|
+
|
|
124
|
+
def readlines(eol=$/)
|
|
125
|
+
ary = []
|
|
126
|
+
while line = self.gets(eol)
|
|
127
|
+
ary << line
|
|
128
|
+
end
|
|
129
|
+
ary
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def readline(eol=$/)
|
|
133
|
+
raise EOFError if eof?
|
|
134
|
+
gets(eol)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def getc
|
|
138
|
+
c = read(1)
|
|
139
|
+
c ? c[0] : nil
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def each_byte
|
|
143
|
+
while c = getc
|
|
144
|
+
yield(c)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def readchar
|
|
149
|
+
raise EOFError if eof?
|
|
150
|
+
getc
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def ungetc(c)
|
|
154
|
+
@rbuffer[0,0] = c.chr
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def eof?
|
|
158
|
+
fill_rbuff if !@eof && @rbuffer.empty?
|
|
159
|
+
@eof && @rbuffer.empty?
|
|
160
|
+
end
|
|
161
|
+
alias eof eof?
|
|
162
|
+
|
|
163
|
+
#
|
|
164
|
+
# for writing.
|
|
165
|
+
#
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
def do_write(s)
|
|
169
|
+
@wbuffer = "" unless defined? @wbuffer
|
|
170
|
+
@wbuffer << s
|
|
171
|
+
@sync ||= false
|
|
172
|
+
if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
|
|
173
|
+
remain = idx ? idx + $/.size : @wbuffer.length
|
|
174
|
+
nwritten = 0
|
|
175
|
+
while remain > 0
|
|
176
|
+
str = @wbuffer[nwritten,remain]
|
|
177
|
+
begin
|
|
178
|
+
nwrote = syswrite(str)
|
|
179
|
+
rescue Errno::EAGAIN
|
|
180
|
+
retry
|
|
181
|
+
end
|
|
182
|
+
remain -= nwrote
|
|
183
|
+
nwritten += nwrote
|
|
184
|
+
end
|
|
185
|
+
@wbuffer[0,nwritten] = ""
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
public
|
|
190
|
+
|
|
191
|
+
def write(s)
|
|
192
|
+
do_write(s)
|
|
193
|
+
s.length
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def << (s)
|
|
197
|
+
do_write(s)
|
|
198
|
+
self
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def puts(*args)
|
|
202
|
+
s = ""
|
|
203
|
+
if args.empty?
|
|
204
|
+
s << "\n"
|
|
205
|
+
end
|
|
206
|
+
args.each{|arg|
|
|
207
|
+
s << arg.to_s
|
|
208
|
+
if $/ && /\n\z/ !~ s
|
|
209
|
+
s << "\n"
|
|
210
|
+
end
|
|
211
|
+
}
|
|
212
|
+
do_write(s)
|
|
213
|
+
nil
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def print(*args)
|
|
217
|
+
s = ""
|
|
218
|
+
args.each{ |arg| s << arg.to_s }
|
|
219
|
+
do_write(s)
|
|
220
|
+
nil
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def printf(s, *args)
|
|
224
|
+
do_write(s % args)
|
|
225
|
+
nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def flush
|
|
229
|
+
osync = @sync
|
|
230
|
+
@sync = true
|
|
231
|
+
do_write ""
|
|
232
|
+
@sync = osync
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def close
|
|
236
|
+
flush rescue nil
|
|
237
|
+
sysclose
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= $RCSfile$ -- Ruby-space predefined Cipher 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: cipher.rb 12496 2007-06-08 15:02:04Z technorama $
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Should we care what if somebody require this file directly?
|
|
19
|
+
#require 'openssl'
|
|
20
|
+
|
|
21
|
+
module OpenSSL
|
|
22
|
+
class Cipher
|
|
23
|
+
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
|
|
24
|
+
klass = Class.new(Cipher){
|
|
25
|
+
define_method(:initialize){|*args|
|
|
26
|
+
cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
|
|
27
|
+
super(cipher_name)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const_set(name, klass)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
%w(128 192 256).each{|keylen|
|
|
34
|
+
klass = Class.new(Cipher){
|
|
35
|
+
define_method(:initialize){|mode|
|
|
36
|
+
mode ||= "CBC"
|
|
37
|
+
cipher_name = "AES-#{keylen}-#{mode}"
|
|
38
|
+
super(cipher_name)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const_set("AES#{keylen}", klass)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Generate, set, and return a random key.
|
|
45
|
+
# You must call cipher.encrypt or cipher.decrypt before calling this method.
|
|
46
|
+
def random_key
|
|
47
|
+
str = OpenSSL::Random.random_bytes(self.key_len)
|
|
48
|
+
self.key = str
|
|
49
|
+
return str
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Generate, set, and return a random iv.
|
|
53
|
+
# You must call cipher.encrypt or cipher.decrypt before calling this method.
|
|
54
|
+
def random_iv
|
|
55
|
+
str = OpenSSL::Random.random_bytes(self.iv_len)
|
|
56
|
+
self.iv = str
|
|
57
|
+
return str
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
|
|
61
|
+
class Cipher < Cipher
|
|
62
|
+
# add warning
|
|
63
|
+
end
|
|
64
|
+
end # Cipher
|
|
65
|
+
end # OpenSSL
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
= Ruby-space definitions that completes C-space funcs for Config
|
|
3
|
+
|
|
4
|
+
= Info
|
|
5
|
+
Copyright (C) 2010 Hiroshi Nakamura <nahi@ruby-lang.org>
|
|
6
|
+
|
|
7
|
+
= Licence
|
|
8
|
+
This program is licenced under the same licence as Ruby.
|
|
9
|
+
(See the file 'LICENCE'.)
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Should we care what if somebody require this file directly?
|
|
15
|
+
#require 'openssl'
|
|
16
|
+
require 'stringio'
|
|
17
|
+
|
|
18
|
+
module OpenSSL
|
|
19
|
+
class Config
|
|
20
|
+
include Enumerable
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def parse(str)
|
|
24
|
+
c = new()
|
|
25
|
+
parse_config(StringIO.new(str)).each do |section, hash|
|
|
26
|
+
c[section] = hash
|
|
27
|
+
end
|
|
28
|
+
c
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
alias load new
|
|
32
|
+
|
|
33
|
+
def parse_config(io)
|
|
34
|
+
begin
|
|
35
|
+
parse_config_lines(io)
|
|
36
|
+
rescue ConfigError => e
|
|
37
|
+
e.message.replace("error in line #{io.lineno}: " + e.message)
|
|
38
|
+
raise
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_key_string(data, section, key) # :nodoc:
|
|
43
|
+
if v = data[section] && data[section][key]
|
|
44
|
+
return v
|
|
45
|
+
elsif section == 'ENV'
|
|
46
|
+
if v = ENV[key]
|
|
47
|
+
return v
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
if v = data['default'] && data['default'][key]
|
|
51
|
+
return v
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def parse_config_lines(io)
|
|
58
|
+
section = 'default'
|
|
59
|
+
data = {section => {}}
|
|
60
|
+
while definition = get_definition(io)
|
|
61
|
+
definition = clear_comments(definition)
|
|
62
|
+
next if definition.empty?
|
|
63
|
+
if definition[0] == ?[
|
|
64
|
+
if /\[([^\]]*)\]/ =~ definition
|
|
65
|
+
section = $1.strip
|
|
66
|
+
data[section] ||= {}
|
|
67
|
+
else
|
|
68
|
+
raise ConfigError, "missing close square bracket"
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition
|
|
72
|
+
if $2
|
|
73
|
+
section = $1
|
|
74
|
+
key = $2
|
|
75
|
+
else
|
|
76
|
+
key = $1
|
|
77
|
+
end
|
|
78
|
+
value = unescape_value(data, section, $3)
|
|
79
|
+
(data[section] ||= {})[key] = value.strip
|
|
80
|
+
else
|
|
81
|
+
raise ConfigError, "missing equal sign"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
data
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# escape with backslash
|
|
89
|
+
QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/
|
|
90
|
+
# escape with backslash and doubled dq
|
|
91
|
+
QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/
|
|
92
|
+
# escaped char map
|
|
93
|
+
ESCAPE_MAP = {
|
|
94
|
+
"r" => "\r",
|
|
95
|
+
"n" => "\n",
|
|
96
|
+
"b" => "\b",
|
|
97
|
+
"t" => "\t",
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
def unescape_value(data, section, value)
|
|
101
|
+
scanned = []
|
|
102
|
+
while m = value.match(/['"\\$]/)
|
|
103
|
+
scanned << m.pre_match
|
|
104
|
+
c = m[0]
|
|
105
|
+
value = m.post_match
|
|
106
|
+
case c
|
|
107
|
+
when "'"
|
|
108
|
+
if m = value.match(QUOTE_REGEXP_SQ)
|
|
109
|
+
scanned << m[1].gsub(/\\(.)/, '\\1')
|
|
110
|
+
value = m.post_match
|
|
111
|
+
else
|
|
112
|
+
break
|
|
113
|
+
end
|
|
114
|
+
when '"'
|
|
115
|
+
if m = value.match(QUOTE_REGEXP_DQ)
|
|
116
|
+
scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1')
|
|
117
|
+
value = m.post_match
|
|
118
|
+
else
|
|
119
|
+
break
|
|
120
|
+
end
|
|
121
|
+
when "\\"
|
|
122
|
+
c = value.slice!(0, 1)
|
|
123
|
+
scanned << (ESCAPE_MAP[c] || c)
|
|
124
|
+
when "$"
|
|
125
|
+
ref, value = extract_reference(value)
|
|
126
|
+
refsec = section
|
|
127
|
+
if ref.index('::')
|
|
128
|
+
refsec, ref = ref.split('::', 2)
|
|
129
|
+
end
|
|
130
|
+
if v = get_key_string(data, refsec, ref)
|
|
131
|
+
scanned << v
|
|
132
|
+
else
|
|
133
|
+
raise ConfigError, "variable has no value"
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
raise 'must not reaced'
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
scanned << value
|
|
140
|
+
scanned.join
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def extract_reference(value)
|
|
144
|
+
rest = ''
|
|
145
|
+
if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/)
|
|
146
|
+
value = m[1] || m[2]
|
|
147
|
+
rest = m.post_match
|
|
148
|
+
elsif [?(, ?{].include?(value[0])
|
|
149
|
+
raise ConfigError, "no close brace"
|
|
150
|
+
end
|
|
151
|
+
if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/)
|
|
152
|
+
return m[0], m.post_match + rest
|
|
153
|
+
else
|
|
154
|
+
raise
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def clear_comments(line)
|
|
159
|
+
# FCOMMENT
|
|
160
|
+
if m = line.match(/\A([\t\n\f ]*);.*\z/)
|
|
161
|
+
return m[1]
|
|
162
|
+
end
|
|
163
|
+
# COMMENT
|
|
164
|
+
scanned = []
|
|
165
|
+
while m = line.match(/[#'"\\]/)
|
|
166
|
+
scanned << m.pre_match
|
|
167
|
+
c = m[0]
|
|
168
|
+
line = m.post_match
|
|
169
|
+
case c
|
|
170
|
+
when '#'
|
|
171
|
+
line = nil
|
|
172
|
+
break
|
|
173
|
+
when "'", '"'
|
|
174
|
+
regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ
|
|
175
|
+
scanned << c
|
|
176
|
+
if m = line.match(regexp)
|
|
177
|
+
scanned << m[0]
|
|
178
|
+
line = m.post_match
|
|
179
|
+
else
|
|
180
|
+
scanned << line
|
|
181
|
+
line = nil
|
|
182
|
+
break
|
|
183
|
+
end
|
|
184
|
+
when "\\"
|
|
185
|
+
scanned << c
|
|
186
|
+
scanned << line.slice!(0, 1)
|
|
187
|
+
else
|
|
188
|
+
raise 'must not reaced'
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
scanned << line
|
|
192
|
+
scanned.join
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def get_definition(io)
|
|
196
|
+
if line = get_line(io)
|
|
197
|
+
while /[^\\]\\\z/ =~ line
|
|
198
|
+
if extra = get_line(io)
|
|
199
|
+
line += extra
|
|
200
|
+
else
|
|
201
|
+
break
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
return line.strip
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def get_line(io)
|
|
209
|
+
if line = io.gets
|
|
210
|
+
line.gsub(/[\r\n]*/, '')
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def initialize(filename = nil)
|
|
216
|
+
@data = {}
|
|
217
|
+
if filename
|
|
218
|
+
File.open(filename.to_s) do |file|
|
|
219
|
+
Config.parse_config(file).each do |section, hash|
|
|
220
|
+
self[section] = hash
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def get_value(section, key)
|
|
227
|
+
if section.nil?
|
|
228
|
+
raise TypeError.new('nil not allowed')
|
|
229
|
+
end
|
|
230
|
+
section = 'default' if section.empty?
|
|
231
|
+
get_key_string(section, key)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def value(arg1, arg2 = nil)
|
|
235
|
+
warn('Config#value is deprecated; use Config#get_value')
|
|
236
|
+
if arg2.nil?
|
|
237
|
+
section, key = 'default', arg1
|
|
238
|
+
else
|
|
239
|
+
section, key = arg1, arg2
|
|
240
|
+
end
|
|
241
|
+
section ||= 'default'
|
|
242
|
+
section = 'default' if section.empty?
|
|
243
|
+
get_key_string(section, key)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def add_value(section, key, value)
|
|
247
|
+
check_modify
|
|
248
|
+
(@data[section] ||= {})[key] = value
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def [](section)
|
|
252
|
+
@data[section] || {}
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def section(name)
|
|
256
|
+
warn('Config#section is deprecated; use Config#[]')
|
|
257
|
+
@data[name] || {}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def []=(section, pairs)
|
|
261
|
+
check_modify
|
|
262
|
+
@data[section] ||= {}
|
|
263
|
+
pairs.each do |key, value|
|
|
264
|
+
self.add_value(section, key, value)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def sections
|
|
269
|
+
@data.keys
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def to_s
|
|
273
|
+
ary = []
|
|
274
|
+
@data.keys.sort.each do |section|
|
|
275
|
+
ary << "[ #{section} ]\n"
|
|
276
|
+
@data[section].keys.each do |key|
|
|
277
|
+
ary << "#{key}=#{@data[section][key]}\n"
|
|
278
|
+
end
|
|
279
|
+
ary << "\n"
|
|
280
|
+
end
|
|
281
|
+
ary.join
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def each
|
|
285
|
+
@data.each do |section, hash|
|
|
286
|
+
hash.each do |key, value|
|
|
287
|
+
yield [section, key, value]
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def inspect
|
|
293
|
+
"#<#{self.class.name} sections=#{sections.inspect}>"
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
protected
|
|
297
|
+
|
|
298
|
+
def data
|
|
299
|
+
@data
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
private
|
|
303
|
+
|
|
304
|
+
def initialize_copy(other)
|
|
305
|
+
@data = other.data.dup
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def check_modify
|
|
309
|
+
raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen?
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def get_key_string(section, key)
|
|
313
|
+
Config.get_key_string(@data, section, key)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
end
|