Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Thu, 8 Jul 2010 04:44:58 +0000 nahi <nahi@b2dd03c8-39d4-4d8f-98ff-823…
…fe69b080e> merge revision(s) 28575,28620:28632: ?\012 * test/openssl/test_config.c: added tests for all Config methods. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28575 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Signed-off-by: URABE, Shyouhei <shyouhei@ruby-lang.org> ?\012 * ext/openssl/ossl_config.c (ossl_config_copy): wrongly updating the given object with uninitialized CONF data. now OpenSSL::Config#clone works as expected; cloning the config instead of SEGV or empty definition. * test/openssl/test_config.rb: added tests for Config#clone. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28621 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Signed-off-by: URABE, Shyouhei <shyouhei@ruby-lang.org> ?\012 * ext/openssl/ossl_config.c, ext/openssl/lib/openssl/config.rb, ext/openssl/lib/openssl.rb: reimplement OpenSSL::Config in Ruby. Now it should work on windows. * test/openssl/test_config.rb: added tests for OpenSSL::Config#dup. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@28632 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Signed-off-by: URABE, Shyouhei <shyouhei@ruby-lang.org> create mode 100644 ext/openssl/lib/openssl/config.rb create mode 100644 test/openssl/test_config.rb git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_7@29856 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
- Loading branch information
Showing
7 changed files
with
649 additions
and
430 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,316 @@ | ||
=begin | ||
= Ruby-space definitions that completes C-space funcs for Config | ||
= Info | ||
Copyright (C) 2010 Hiroshi Nakamura <nahi@ruby-lang.org> | ||
= Licence | ||
This program is licenced under the same licence as Ruby. | ||
(See the file 'LICENCE'.) | ||
=end | ||
|
||
## | ||
# Should we care what if somebody require this file directly? | ||
#require 'openssl' | ||
require 'stringio' | ||
|
||
module OpenSSL | ||
class Config | ||
include Enumerable | ||
|
||
class << self | ||
def parse(str) | ||
c = new() | ||
parse_config(StringIO.new(str)).each do |section, hash| | ||
c[section] = hash | ||
end | ||
c | ||
end | ||
|
||
alias load new | ||
|
||
def parse_config(io) | ||
begin | ||
parse_config_lines(io) | ||
rescue ConfigError => e | ||
e.message.replace("error in line #{io.lineno}: " + e.message) | ||
raise | ||
end | ||
end | ||
|
||
def get_key_string(data, section, key) # :nodoc: | ||
if v = data[section] && data[section][key] | ||
return v | ||
elsif section == 'ENV' | ||
if v = ENV[key] | ||
return v | ||
end | ||
end | ||
if v = data['default'] && data['default'][key] | ||
return v | ||
end | ||
end | ||
|
||
private | ||
|
||
def parse_config_lines(io) | ||
section = 'default' | ||
data = {section => {}} | ||
while definition = get_definition(io) | ||
definition = clear_comments(definition) | ||
next if definition.empty? | ||
if definition[0] == ?[ | ||
if /\[([^\]]*)\]/ =~ definition | ||
section = $1.strip | ||
data[section] ||= {} | ||
else | ||
raise ConfigError, "missing close square bracket" | ||
end | ||
else | ||
if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition | ||
if $2 | ||
section = $1 | ||
key = $2 | ||
else | ||
key = $1 | ||
end | ||
value = unescape_value(data, section, $3) | ||
(data[section] ||= {})[key] = value.strip | ||
else | ||
raise ConfigError, "missing equal sign" | ||
end | ||
end | ||
end | ||
data | ||
end | ||
|
||
# escape with backslash | ||
QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ | ||
# escape with backslash and doubled dq | ||
QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ | ||
# escaped char map | ||
ESCAPE_MAP = { | ||
"r" => "\r", | ||
"n" => "\n", | ||
"b" => "\b", | ||
"t" => "\t", | ||
} | ||
|
||
def unescape_value(data, section, value) | ||
scanned = [] | ||
while m = value.match(/['"\\$]/) | ||
scanned << m.pre_match | ||
c = m[0] | ||
value = m.post_match | ||
case c | ||
when "'" | ||
if m = value.match(QUOTE_REGEXP_SQ) | ||
scanned << m[1].gsub(/\\(.)/, '\\1') | ||
value = m.post_match | ||
else | ||
break | ||
end | ||
when '"' | ||
if m = value.match(QUOTE_REGEXP_DQ) | ||
scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') | ||
value = m.post_match | ||
else | ||
break | ||
end | ||
when "\\" | ||
c = value.slice!(0, 1) | ||
scanned << (ESCAPE_MAP[c] || c) | ||
when "$" | ||
ref, value = extract_reference(value) | ||
refsec = section | ||
if ref.index('::') | ||
refsec, ref = ref.split('::', 2) | ||
end | ||
if v = get_key_string(data, refsec, ref) | ||
scanned << v | ||
else | ||
raise ConfigError, "variable has no value" | ||
end | ||
else | ||
raise 'must not reaced' | ||
end | ||
end | ||
scanned << value | ||
scanned.join | ||
end | ||
|
||
def extract_reference(value) | ||
rest = '' | ||
if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) | ||
value = m[1] || m[2] | ||
rest = m.post_match | ||
elsif [?(, ?{].include?(value[0]) | ||
raise ConfigError, "no close brace" | ||
end | ||
if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) | ||
return m[0], m.post_match + rest | ||
else | ||
raise | ||
end | ||
end | ||
|
||
def clear_comments(line) | ||
# FCOMMENT | ||
if m = line.match(/\A([\t\n\f ]*);.*\z/) | ||
return m[1] | ||
end | ||
# COMMENT | ||
scanned = [] | ||
while m = line.match(/[#'"\\]/) | ||
scanned << m.pre_match | ||
c = m[0] | ||
line = m.post_match | ||
case c | ||
when '#' | ||
line = nil | ||
break | ||
when "'", '"' | ||
regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ | ||
scanned << c | ||
if m = line.match(regexp) | ||
scanned << m[0] | ||
line = m.post_match | ||
else | ||
scanned << line | ||
line = nil | ||
break | ||
end | ||
when "\\" | ||
scanned << c | ||
scanned << line.slice!(0, 1) | ||
else | ||
raise 'must not reaced' | ||
end | ||
end | ||
scanned << line | ||
scanned.join | ||
end | ||
|
||
def get_definition(io) | ||
if line = get_line(io) | ||
while /[^\\]\\\z/ =~ line | ||
if extra = get_line(io) | ||
line += extra | ||
else | ||
break | ||
end | ||
end | ||
return line.strip | ||
end | ||
end | ||
|
||
def get_line(io) | ||
if line = io.gets | ||
line.gsub(/[\r\n]*/, '') | ||
end | ||
end | ||
end | ||
|
||
def initialize(filename = nil) | ||
@data = {} | ||
if filename | ||
File.open(filename.to_s) do |file| | ||
Config.parse_config(file).each do |section, hash| | ||
self[section] = hash | ||
end | ||
end | ||
end | ||
end | ||
|
||
def get_value(section, key) | ||
if section.nil? | ||
raise TypeError.new('nil not allowed') | ||
end | ||
section = 'default' if section.empty? | ||
get_key_string(section, key) | ||
end | ||
|
||
def value(arg1, arg2 = nil) | ||
warn('Config#value is deprecated; use Config#get_value') | ||
if arg2.nil? | ||
section, key = 'default', arg1 | ||
else | ||
section, key = arg1, arg2 | ||
end | ||
section ||= 'default' | ||
section = 'default' if section.empty? | ||
get_key_string(section, key) | ||
end | ||
|
||
def add_value(section, key, value) | ||
check_modify | ||
(@data[section] ||= {})[key] = value | ||
end | ||
|
||
def [](section) | ||
@data[section] || {} | ||
end | ||
|
||
def section(name) | ||
warn('Config#section is deprecated; use Config#[]') | ||
@data[name] || {} | ||
end | ||
|
||
def []=(section, pairs) | ||
check_modify | ||
@data[section] ||= {} | ||
pairs.each do |key, value| | ||
self.add_value(section, key, value) | ||
end | ||
end | ||
|
||
def sections | ||
@data.keys | ||
end | ||
|
||
def to_s | ||
ary = [] | ||
@data.keys.sort.each do |section| | ||
ary << "[ #{section} ]\n" | ||
@data[section].keys.each do |key| | ||
ary << "#{key}=#{@data[section][key]}\n" | ||
end | ||
ary << "\n" | ||
end | ||
ary.join | ||
end | ||
|
||
def each | ||
@data.each do |section, hash| | ||
hash.each do |key, value| | ||
yield(section, key, value) | ||
end | ||
end | ||
end | ||
|
||
def inspect | ||
"#<#{self.class.name} sections=#{sections.inspect}>" | ||
end | ||
|
||
protected | ||
|
||
def data | ||
@data | ||
end | ||
|
||
private | ||
|
||
def initialize_copy(other) | ||
@data = other.data.dup | ||
end | ||
|
||
def check_modify | ||
raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? | ||
end | ||
|
||
def get_key_string(section, key) | ||
Config.get_key_string(@data, section, key) | ||
end | ||
end | ||
end |
Oops, something went wrong.