summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-25 06:51:21 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-25 06:51:21 +0000
commit74efef0be85061c3c9e24ee0cfdf5f83c2af9a22 (patch)
tree2db7641808ab4f14daf322ee4eae9786b372dc35
parent23de09d6bb2005efe55b08e90875ff6a6c6f8976 (diff)
Merge from ruby_1_8.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@16193 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog49
-rw-r--r--NEWS4
-rw-r--r--array.c2
-rw-r--r--dln.c41
-rw-r--r--eval.c32
-rw-r--r--ext/openssl/lib/openssl/ssl.rb84
-rw-r--r--ext/openssl/ossl_ssl.c106
-rw-r--r--ext/tk/lib/tk.rb13
-rw-r--r--ext/tk/lib/tk/scale.rb13
-rw-r--r--ext/tk/lib/tk/scrollbar.rb13
-rw-r--r--ext/tk/lib/tkextlib/blt/ted.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/unix_dnd.rb6
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb8
-rw-r--r--ext/tk/lib/tkextlib/version.rb2
-rw-r--r--ext/tk/sample/ttk_wrapper.rb4
-rw-r--r--lib/net/pop.rb228
-rw-r--r--test/gdbm/test_gdbm.rb4
-rw-r--r--test/openssl/test_ssl.rb343
-rw-r--r--version.h6
19 files changed, 752 insertions, 208 deletions
diff --git a/ChangeLog b/ChangeLog
index 0ae1cd89ba..1ce27b6aab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+Fri Apr 25 15:46:37 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/scrollbar.rb, ext/tk/lib/tk/scale.rb:
+ improve unknonw-option check when create a widget.
+
+ * ext/tk/lib/tkextlib/blt/unix_dnd.rb, ext/tk/lib/tkextlib/blt/ted.rb,
+ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix on 'cget'.
+
+ * ext/tk/lib/tk/menuspec.rb: option check will fail when
+ TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ is true.
+
+ * ext/tk/lib/tk/palette.rb: bug fix.
+
+Fri Apr 25 12:37:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): returns an instance of same class.
+ [ruby-core:16554]
+
+Thu Apr 24 23:47:50 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: backported from 1.9. bug#19003
+
+ * ext/openssl/lib/openssl/ssl.rb: set_params; backported from 1.9.
+ bug#19552, [ruby-dev:34402]
+
+ * ext/openssl/ossl_ssl.c: ditto.
+
+ * test/openssl/test_ssl.rb: ditto.
+
+Thu Apr 24 17:06:34 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_SAVE_CONTEXT): remove unnecessary
+ FLUSH_REGISTER_WINDOWS before calling setjmp(). [ruby-core:16285]
+
+Thu Apr 24 14:15:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dln.c (dln_find_1): prior files with extensions to files sans
+ extensions. [ruby-core:16517]
+
+Wed Apr 23 15:39:31 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (bind_eval): Add Binding#eval, a shorthand method for
+ eval(str, binding, ..); backported from 1.9.
+
+Wed Apr 23 15:28:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/gdbm/test_gdbm.rb (TestGDBM#test_s_open_no_create): failed
+ notice moved from comment to assertion message. [ruby-dev:29127]
+
Wed Apr 23 14:00:05 2008 Akinori MUSHA <knu@iDaemons.org>
* lib/mkmf.rb (create_makefile): Add a missing dependency on the
diff --git a/NEWS b/NEWS
index 568debf36c..6e3de72a37 100644
--- a/NEWS
+++ b/NEWS
@@ -73,6 +73,10 @@ with all sufficient information, see the ChangeLog file.
New methods.
+ * Binding#eval
+
+ New method.
+
* Dir#each
* Dir#foreach
diff --git a/array.c b/array.c
index 3789e4f6d9..423030ac41 100644
--- a/array.c
+++ b/array.c
@@ -3082,7 +3082,7 @@ flatten(ary, level, modified)
st_data_t id;
stack = rb_ary_new();
- result = rb_ary_new();
+ result = ary_new(rb_class_of(ary), RARRAY_LEN(ary));
memo = st_init_numtable();
st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
*modified = 0;
diff --git a/dln.c b/dln.c
index 5a96626411..5b99425141 100644
--- a/dln.c
+++ b/dln.c
@@ -1781,26 +1781,9 @@ dln_find_1(fname, path, exe_flag)
}
memcpy(bp, fname, i + 1);
-#ifndef __MACOS__
- if (stat(fbuf, &st) == 0) {
- if (exe_flag == 0) return fbuf;
- /* looking for executable */
- if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
- return fbuf;
- }
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
- if (exe_flag == 0) return mac_fullpath;
- /* looking for executable */
- if (stat(mac_fullpath, &st) == 0) {
- if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
- return mac_fullpath;
- }
- }
-#endif
#if defined(DOSISH)
if (exe_flag) {
- static const char *const extension[] = {
+ static const char extension[][5] = {
#if defined(MSDOS)
".com", ".exe", ".bat",
#if defined(DJGPP)
@@ -1813,11 +1796,10 @@ dln_find_1(fname, path, exe_flag)
".r", ".R", ".x", ".X", ".bat", ".BAT",
/* __human68k__ */
#endif
- (char *) NULL
};
int j;
- for (j = 0; extension[j]; j++) {
+ for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
if (fspace < strlen(extension[j])) {
fprintf(stderr, "openpath: pathname too long (ignored)\n");
fprintf(stderr, "\tDirectory \"%.*s\"\n", (int) (bp - fbuf), fbuf);
@@ -1834,9 +1816,28 @@ dln_find_1(fname, path, exe_flag)
#endif
}
+ goto next;
}
#endif /* MSDOS or _WIN32 or __human68k__ or __EMX__ */
+#ifndef __MACOS__
+ if (stat(fbuf, &st) == 0) {
+ if (exe_flag == 0) return fbuf;
+ /* looking for executable */
+ if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
+ return fbuf;
+ }
+#else
+ if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
+ if (exe_flag == 0) return mac_fullpath;
+ /* looking for executable */
+ if (stat(mac_fullpath, &st) == 0) {
+ if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
+ return mac_fullpath;
+ }
+ }
+#endif
+
next:
/* if not, and no other alternatives, life is bleak */
if (*ep == '\0') {
diff --git a/eval.c b/eval.c
index 9994015cf5..f691514c26 100644
--- a/eval.c
+++ b/eval.c
@@ -8471,6 +8471,35 @@ rb_f_binding(self)
return bind;
}
+/*
+ * call-seq:
+ * binding.eval(string [, filename [,lineno]]) => obj
+ *
+ * Evaluates the Ruby expression(s) in <em>string</em>, in the
+ * <em>binding</em>'s context. If the optional <em>filename</em> and
+ * <em>lineno</em> parameters are present, they will be used when
+ * reporting syntax errors.
+ *
+ * def getBinding(param)
+ * return binding
+ * end
+ * b = getBinding("hello")
+ * b.eval("param") #=> "hello"
+ */
+
+static VALUE
+bind_eval(argc, argv, bindval)
+ int argc;
+ VALUE *argv;
+ VALUE bindval;
+{
+ VALUE args[4];
+
+ rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
+ args[1] = bindval;
+ return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
+}
+
#define PROC_TSHIFT (FL_USHIFT+1)
#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
@@ -9899,6 +9928,7 @@ Init_Binding()
rb_undef_method(CLASS_OF(rb_cBinding), "new");
rb_define_method(rb_cBinding, "clone", proc_clone, 0);
rb_define_method(rb_cBinding, "dup", proc_dup, 0);
+ rb_define_method(rb_cBinding, "eval", bind_eval, -1);
rb_define_global_function("binding", rb_f_binding, 0);
}
@@ -10441,7 +10471,7 @@ rb_thread_switch(n)
}
#define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp(rb_thread_save_context(th), (th)->context))))
+ (rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context)))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index ad9559f6b6..f722cb0c45 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -20,6 +20,33 @@ require "fcntl"
module OpenSSL
module SSL
+ class SSLContext
+ DEFAULT_PARAMS = {
+ :ssl_version => "SSLv23",
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
+ :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
+ :options => OpenSSL::SSL::OP_ALL,
+ }
+
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
+ DEFAULT_CERT_STORE.set_default_paths
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+ end
+
+ def set_params(params={})
+ params = DEFAULT_PARAMS.merge(params)
+ self.ssl_version = params.delete(:ssl_version)
+ params.each{|name, value| self.__send__("#{name}=", value) }
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ unless self.ca_file or self.ca_path or self.cert_store
+ self.cert_store = DEFAULT_CERT_STORE
+ end
+ end
+ return params
+ end
+ end
+
module SocketForwarder
def addr
to_io.addr
@@ -59,36 +86,43 @@ module OpenSSL
end
end
+ def verify_certificate_identity(cert, hostname)
+ should_verify_common_name = true
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ext.value.split(/,\s+/).each{|general_name|
+ if /\ADNS:(.*)/ =~ general_name
+ should_verify_common_name = false
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ elsif /\AIP Address:(.*)/ =~ general_name
+ should_verify_common_name = false
+ return true if $1 == hostname
+ end
+ }
+ }
+ if should_verify_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN"
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ end
+ }
+ end
+ return false
+ end
+ module_function :verify_certificate_identity
+
class SSLSocket
include Buffering
include SocketForwarder
include Nonblock
def post_connection_check(hostname)
- check_common_name = true
- cert = peer_cert
- cert.extensions.each{|ext|
- next if ext.oid != "subjectAltName"
- ext.value.split(/,\s+/).each{|general_name|
- if /\ADNS:(.*)/ =~ general_name
- check_common_name = false
- reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- elsif /\AIP Address:(.*)/ =~ general_name
- check_common_name = false
- return true if $1 == hostname
- end
- }
- }
- if check_common_name
- cert.subject.to_a.each{|oid, value|
- if oid == "CN"
- reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- end
- }
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+ raise SSLError, "hostname was not match with the server certificate"
end
- raise SSLError, "hostname was not match with the server certificate"
+ return true
end
def session
@@ -120,6 +154,10 @@ module OpenSSL
@svr.listen(backlog)
end
+ def shutdown(how=Socket::SHUT_RDWR)
+ @svr.shutdown(how)
+ end
+
def accept
sock = @svr.accept
begin
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 98c374b95f..675fe657b0 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -141,31 +141,14 @@ ossl_sslctx_s_alloc(VALUE klass)
return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
}
-/*
- * call-seq:
- * SSLContext.new => ctx
- * SSLContext.new(:TLSv1) => ctx
- * SSLContext.new("SSLv23_client") => ctx
- *
- * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
- */
static VALUE
-ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
- VALUE ssl_method;
SSL_METHOD *method = NULL;
- SSL_CTX *ctx;
- int i;
const char *s;
+ int i;
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
- char buf[32];
- snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
- rb_iv_set(self, buf, Qnil);
- }
- if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
- return self;
- }
+ SSL_CTX *ctx;
if(TYPE(ssl_method) == T_SYMBOL)
s = rb_id2name(SYM2ID(ssl_method));
else
@@ -184,6 +167,33 @@ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
}
+ return ssl_method;
+}
+
+/*
+ * call-seq:
+ * SSLContext.new => ctx
+ * SSLContext.new(:TLSv1) => ctx
+ * SSLContext.new("SSLv23_client") => ctx
+ *
+ * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
+ */
+static VALUE
+ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ssl_method;
+ int i;
+
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
+ char buf[32];
+ snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
+ rb_iv_set(self, buf, Qnil);
+ }
+ if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
+ return self;
+ }
+ ossl_sslctx_set_ssl_version(self, ssl_method);
+
return self;
}
@@ -436,6 +446,14 @@ ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
return i;
}
+/*
+ * call-seq:
+ * ctx.setup => Qtrue # first time
+ * ctx.setup => nil # thereafter
+ *
+ * This method is called automatically when a new SSLSocket is created.
+ * Normally you do not need to call this method (unless you are writing an extension in C).
+ */
static VALUE
ossl_sslctx_setup(VALUE self)
{
@@ -769,18 +787,18 @@ ossl_sslctx_get_session_cache_stats(VALUE self)
Data_Get_Struct(self, SSL_CTX, ctx);
hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("cache_num"), LONG2NUM(SSL_CTX_sess_number(ctx)));
- rb_hash_aset(hash, rb_str_new2("connect"), LONG2NUM(SSL_CTX_sess_connect(ctx)));
- rb_hash_aset(hash, rb_str_new2("connect_good"), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
- rb_hash_aset(hash, rb_str_new2("connect_renegotiate"), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
- rb_hash_aset(hash, rb_str_new2("accept"), LONG2NUM(SSL_CTX_sess_accept(ctx)));
- rb_hash_aset(hash, rb_str_new2("accept_good"), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
- rb_hash_aset(hash, rb_str_new2("accept_renegotiate"), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
- rb_hash_aset(hash, rb_str_new2("cache_hits"), LONG2NUM(SSL_CTX_sess_hits(ctx)));
- rb_hash_aset(hash, rb_str_new2("cb_hits"), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
- rb_hash_aset(hash, rb_str_new2("cache_misses"), LONG2NUM(SSL_CTX_sess_misses(ctx)));
- rb_hash_aset(hash, rb_str_new2("cache_full"), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
- rb_hash_aset(hash, rb_str_new2("timeouts"), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
return hash;
}
@@ -1300,6 +1318,19 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
return arg1;
}
+static VALUE
+ossl_ssl_get_verify_result(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ return INT2FIX(SSL_get_verify_result(ssl));
+}
void
Init_ossl_ssl()
@@ -1330,18 +1361,22 @@ Init_ossl_ssl()
*
* The following attributes are available but don't show up in rdoc.
* All attributes must be set before calling SSLSocket.new(io, ctx).
- * * cert, key, client_ca, ca_file, ca_path, timeout, verify_mode, verify_depth
- * * client_cert_cb, tmp_dh_callback, session_id_context,
- * * session_add_cb, session_new_cb, session_remove_cb
+ * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
+ * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
+ * * session_id_context, session_add_cb, session_new_cb, session_remove_cb
*/
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
+ rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+
rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
@@ -1395,6 +1430,7 @@ Init_ossl_ssl()
rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index a5cb8cb67d..2aafcfecc3 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -4799,8 +4799,15 @@ class TkWindow<TkObject
tk_call_without_enc(cmd, @path)
keys = __check_available_configure_options(keys)
unless keys.empty?
- tk_call_without_enc('destroy', @path)
- tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ end
end
end
end
@@ -5341,7 +5348,7 @@ TkWidget = TkWindow
#Tk.freeze
module Tk
- RELEASE_DATE = '2008-04-15'.freeze
+ RELEASE_DATE = '2008-04-18'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb
index bf2791ec55..7e758d92f4 100644
--- a/ext/tk/lib/tk/scale.rb
+++ b/ext/tk/lib/tk/scale.rb
@@ -26,9 +26,16 @@ class Tk::Scale<TkWindow
tk_call_without_enc(self.class::TkCommandNames[0], @path)
keys = __check_available_configure_options(keys)
unless keys.empty?
- tk_call_without_enc('destroy', @path)
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
end
end
end
diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
index 521fc7e400..87db46a9f9 100644
--- a/ext/tk/lib/tk/scrollbar.rb
+++ b/ext/tk/lib/tk/scrollbar.rb
@@ -31,9 +31,16 @@ class Tk::Scrollbar<TkWindow
tk_call_without_enc(self.class::TkCommandNames[0], @path)
keys = __check_available_configure_options(keys)
unless keys.empty?
- tk_call_without_enc('destroy', @path)
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
end
end
end
diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb
index 39495842b4..8b727c1eec 100644
--- a/ext/tk/lib/tkextlib/blt/ted.rb
+++ b/ext/tk/lib/tkextlib/blt/ted.rb
@@ -34,7 +34,7 @@ module Tk::BLT
private :itemconfiginfo, :current_itemconfiginfo
def cget(master, option)
- itemconfigure(master, slot, value)
+ itemcget(master, option)
end
def configure(master, slot, value=None)
itemconfigure(master, slot, value)
diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
index 3130c1e56f..7a994233a2 100644
--- a/ext/tk/lib/tkextlib/blt/unix_dnd.rb
+++ b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
@@ -34,7 +34,7 @@ module Tk::BLT
private :itemconfiginfo, :current_itemconfiginfo
def cget(win, option)
- itemconfigure(['cget', win], slot, value)
+ itemcget(['cget', win], option)
end
def configure(win, slot, value=None)
itemconfigure(['configure', win], slot, value)
@@ -46,8 +46,8 @@ module Tk::BLT
current_itemconfiginfo(['configure', win], slot)
end
- def tokwn_cget(win, option)
- itemconfigure(['token', 'cget', win], slot, value)
+ def token_cget(win, option)
+ itemcget(['token', 'cget', win], option)
end
def token_configure(win, slot, value=None)
itemconfigure(['token', 'configure', win], slot, value)
diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
index b72b157dcd..d025bc4086 100644
--- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
+++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
@@ -518,7 +518,8 @@ module Tk::TreeCtrl::ConfigMethod
def notify_cget(win, pattern, option)
pattern = "<#{pattern}>"
- itemconfigure(['notify', [win, pattern]], option)
+ # "notify" doesn't have cget subcommand.
+ current_itemconfiginfo(['notify', [win, pattern]])[option.to_s]
end
def notify_configure(win, pattern, slot, value=None)
pattern = "<#{pattern}>"
@@ -528,7 +529,10 @@ module Tk::TreeCtrl::ConfigMethod
pattern = "<#{pattern}>"
itemconfiginfo(['notify', [win, pattern]], slot)
end
- alias current_notify_configinfo notify_configinfo
+ def current_notify_configinfo(tagOrId, slot=nil)
+ pattern = "<#{pattern}>"
+ current_itemconfiginfo(['notify', [win, pattern]], slot)
+ end
def style_cget(tagOrId, option)
itemcget(['style', tagOrId], option)
diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb
index 0fc1136e53..08cccf56c2 100644
--- a/ext/tk/lib/tkextlib/version.rb
+++ b/ext/tk/lib/tkextlib/version.rb
@@ -2,5 +2,5 @@
# release date of tkextlib
#
module Tk
- Tkextlib_RELEASE_DATE = '2008-04-14'.freeze
+ Tkextlib_RELEASE_DATE = '2008-04-18'.freeze
end
diff --git a/ext/tk/sample/ttk_wrapper.rb b/ext/tk/sample/ttk_wrapper.rb
index 4a4491b5bd..8bd818f5c4 100644
--- a/ext/tk/sample/ttk_wrapper.rb
+++ b/ext/tk/sample/ttk_wrapper.rb
@@ -4,7 +4,7 @@
#
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
-version = '0.1'
+version = '0.1.1'
#
##########################################################################
# parse commandline arguments
@@ -144,7 +144,7 @@ setTheme(OPTS[:theme]) if OPTS[:theme]
##########################################################################
# load script
##########################################################################
-if (script = File.expand_path(ARGV.shift))
+if (path = ARGV.shift) && (script = File.expand_path(path))
print "load script \"#{script}\"\n" if OPTS[:verbose]
load(script)
else
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 6d1343eded..82cc9a747b 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -1,8 +1,8 @@
# = net/pop.rb
#
-# Copyright (c) 1999-2003 Yukihiro Matsumoto.
+# Copyright (c) 1999-2007 Yukihiro Matsumoto.
#
-# Copyright (c) 1999-2003 Minero Aoki.
+# Copyright (c) 1999-2007 Minero Aoki.
#
# Written & maintained by Minero Aoki <aamine@loveruby.net>.
#
@@ -10,18 +10,24 @@
#
# This program is free software. You can re-distribute and/or
# modify this program under the same terms as Ruby itself,
-# Ruby Distribute License or GNU General Public License.
+# Ruby Distribute License.
#
-# NOTE: You can find Japanese version of this document in
-# the doc/net directory of the standard ruby interpreter package.
+# NOTE: You can find Japanese version of this document at:
+# http://www.ruby-lang.org/ja/man/html/net_pop.html
#
# $Id$
-#
+#
# See Net::POP3 for documentation.
#
require 'net/protocol'
require 'digest/md5'
+require 'timeout'
+
+begin
+ require "openssl/ssl"
+rescue LoadError
+end
module Net
@@ -196,10 +202,19 @@ module Net
# Class Parameters
#
- # The default port for POP3 connections, port 110
def POP3.default_port
+ default_pop3_port()
+ end
+
+ # The default port for POP3 connections, port 110
+ def POP3.default_pop3_port
110
end
+
+ # The default port for POP3S connections, port 995
+ def POP3.default_pop3s_port
+ 995
+ end
def POP3.socket_type #:nodoc: obsolete
Net::InternetMessageIO
@@ -220,7 +235,7 @@ module Net
# ....
# end
#
- def POP3.APOP( isapop )
+ def POP3.APOP(isapop)
isapop ? APOP : POP3
end
@@ -244,9 +259,9 @@ module Net
# m.delete if $DELETE
# end
#
- def POP3.foreach( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block ) # :yields: message
+ def POP3.foreach(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block) # :yields: message
start(address, port, account, password, isapop) {|pop|
pop.each_mail(&block)
}
@@ -265,9 +280,9 @@ module Net
# file.write m.pop
# end
#
- def POP3.delete_all( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block )
+ def POP3.delete_all(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block)
start(address, port, account, password, isapop) {|pop|
pop.delete_all(&block)
}
@@ -287,16 +302,16 @@ module Net
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword', true)
#
- def POP3.auth_only( address, port = nil,
- account = nil, password = nil,
- isapop = false )
+ def POP3.auth_only(address, port = nil,
+ account = nil, password = nil,
+ isapop = false)
new(address, port, isapop).auth_only account, password
end
# Starts a pop3 session, attempts authentication, and quits.
# This method must not be called while POP3 session is opened.
# This method raises POPAuthenticationError if authentication fails.
- def auth_only( account, password )
+ def auth_only(account, password)
raise IOError, 'opening previously opened POP session' if started?
start(account, password) {
;
@@ -304,6 +319,59 @@ module Net
end
#
+ # SSL
+ #
+
+ @ssl_params = nil
+
+ # call-seq:
+ # Net::POP.enable_ssl(params = {})
+ #
+ # Enable SSL for all new instances.
+ # +params+ is passed to OpenSSL::SSLContext#set_params.
+ def POP3.enable_ssl(*args)
+ @ssl_params = create_ssl_params(*args)
+ end
+
+ def POP3.create_ssl_params(verify_or_params = {}, certs = nil)
+ begin
+ params = verify_or_params.to_hash
+ rescue NoMethodError
+ params = {}
+ params[:verify_mode] = verify_or_params
+ if certs
+ if File.file?(certs)
+ params[:ca_file] = certs
+ elsif File.directory?(certs)
+ params[:ca_path] = certs
+ end
+ end
+ end
+ return params
+ end
+
+ # Disable SSL for all new instances.
+ def POP3.disable_ssl
+ @ssl_params = nil
+ end
+
+ def POP3.ssl_params
+ return @ssl_params
+ end
+
+ def POP3.use_ssl?
+ return !@ssl_params.nil?
+ end
+
+ def POP3.verify
+ return @ssl_params[:verify_mode]
+ end
+
+ def POP3.certs
+ return @ssl_params[:ca_file] || @ssl_params[:ca_path]
+ end
+
+ #
# Session management
#
@@ -323,27 +391,28 @@ module Net
# end
# end
#
- def POP3.start( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block ) # :yield: pop
+ def POP3.start(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block) # :yield: pop
new(address, port, isapop).start(account, password, &block)
end
-
+
# Creates a new POP3 object.
#
# +address+ is the hostname or ip address of your POP3 server.
#
- # The optional +port+ is the port to connect to; it defaults to 110.
+ # The optional +port+ is the port to connect to.
#
# The optional +isapop+ specifies whether this connection is going
# to use APOP authentication; it defaults to +false+.
#
# This method does *not* open the TCP connection.
- def initialize( addr, port = nil, isapop = false )
+ def initialize(addr, port = nil, isapop = false)
@address = addr
- @port = port || self.class.default_port
+ @ssl_params = POP3.ssl_params
+ @port = port
@apop = isapop
-
+
@command = nil
@socket = nil
@started = false
@@ -361,6 +430,32 @@ module Net
@apop
end
+ # does this instance use SSL?
+ def use_ssl?
+ return !@ssl_params.nil?
+ end
+
+ # call-seq:
+ # Net::POP#enable_ssl(params = {})
+ #
+ # Enables SSL for this instance. Must be called before the connection is
+ # established to have any effect.
+ # +params[:port]+ is port to establish the SSL connection on; Defaults to 995.
+ # +params+ (except :port) is passed to OpenSSL::SSLContext#set_params.
+ def enable_ssl(verify_or_params = {}, certs = nil, port = nil)
+ begin
+ @ssl_params = verify_or_params.to_hash.dup
+ @port = @ssl_params.delete(:port) || @port
+ rescue NoMethodError
+ @ssl_params = POP3.create_ssl_params(verify_or_params, certs)
+ @port = port || @port
+ end
+ end
+
+ def disable_ssl
+ @ssl_params = nil
+ end
+
# Provide human-readable stringification of class state.
def inspect
"#<#{self.class} #{@address}:#{@port} open=#{@started}>"
@@ -379,7 +474,7 @@ module Net
# ....
# end
#
- def set_debug_output( arg )
+ def set_debug_output(arg)
@debug_output = arg
end
@@ -387,7 +482,9 @@ module Net
attr_reader :address
# The port number to connect to.
- attr_reader :port
+ def port
+ return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port)
+ end
# Seconds to wait until a connection is opened.
# If the POP3 object cannot open a connection within this time,
@@ -400,7 +497,7 @@ module Net
attr_reader :read_timeout
# Set the read timeout.
- def read_timeout=( sec )
+ def read_timeout=(sec)
@command.socket.read_timeout = sec if @command
@read_timeout = sec
end
@@ -418,9 +515,8 @@ module Net
# closes the session after block call finishes.
#
# This method raises a POPAuthenticationError if authentication fails.
- def start( account, password ) # :yield: pop
+ def start(account, password) # :yield: pop
raise IOError, 'POP session already started' if @started
-
if block_given?
begin
do_start account, password
@@ -434,9 +530,23 @@ module Net
end
end
- def do_start( account, password )
- @socket = self.class.socket_type.old_open(@address, @port,
- @open_timeout, @read_timeout, @debug_output)
+ def do_start(account, password)
+ s = timeout(@open_timeout) { TCPSocket.open(@address, port) }
+ if use_ssl?
+ raise 'openssl library not installed' unless defined?(OpenSSL)
+ context = OpenSSL::SSL::SSLContext.new
+ context.set_params(@ssl_params)
+ s = OpenSSL::SSL::SSLSocket.new(s, context)
+ s.sync_close = true
+ s.connect
+ if context.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ s.post_connection_check(@address)
+ end
+ end
+ @socket = InternetMessageIO.new(s)
+ logging "POP session started: #{@address}:#{@port} (#{@apop ? 'APOP' : 'POP'})"
+ @socket.read_timeout = @read_timeout
+ @socket.debug_output = @debug_output
on_connect
@command = POP3Command.new(@socket)
if apop?
@@ -446,7 +556,12 @@ module Net
end
@started = true
ensure
- do_finish if not @started
+ # Authentication failed, clean up connection.
+ unless @started
+ s.close if s and not s.closed?
+ @socket = nil
+ @command = nil
+ end
end
private :do_start
@@ -526,7 +641,7 @@ module Net
# end
#
# This method raises a POPError if an error occurs.
- def each_mail( &block ) # :yield: message
+ def each_mail(&block) # :yield: message
mails().each(&block)
end
@@ -573,6 +688,10 @@ module Net
end
end
+ def logging(msg)
+ @debug_output << msg + "\n" if @debug_output
+ end
+
end # class POP3
# class aliases
@@ -600,7 +719,7 @@ module Net
#
class POPMail
- def initialize( num, len, pop, cmd ) #:nodoc:
+ def initialize(num, len, pop, cmd) #:nodoc:
@number = num
@length = len
@pop = pop
@@ -679,7 +798,7 @@ module Net
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
- def top( lines, dest = '' )
+ def top(lines, dest = '')
@command.top(@number, lines) do |chunk|
dest << chunk
end
@@ -691,7 +810,7 @@ module Net
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
- def header( dest = '' )
+ def header(dest = '')
top(0, dest)
end
@@ -739,7 +858,7 @@ module Net
alias uidl unique_id
- def uid=( uid ) #:nodoc: internal use only (used from POP3#set_all_uids)
+ def uid=(uid) #:nodoc: internal use only
@uid = uid
end
@@ -748,7 +867,7 @@ module Net
class POP3Command #:nodoc: internal use only
- def initialize( sock )
+ def initialize(sock)
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
@@ -759,14 +878,14 @@ module Net
"#<#{self.class} socket=#{@socket}>"
end
- def auth( account, password )
+ def auth(account, password)
check_response_auth(critical {
check_response_auth(get_response('USER %s', account))
get_response('PASS %s', password)
})
end
- def apop( account, password )
+ def apop(account, password)
raise POPAuthenticationError, 'not APOP server; cannot login' \
unless @apop_stamp
check_response_auth(critical {
@@ -797,28 +916,28 @@ module Net
end
def rset
- check_response(critical { get_response 'RSET' })
+ check_response(critical { get_response('RSET') })
end
- def top( num, lines = 0, &block )
+ def top(num, lines = 0, &block)
critical {
getok('TOP %d %d', num, lines)
@socket.each_message_chunk(&block)
}
end
- def retr( num, &block )
+ def retr(num, &block)
critical {
getok('RETR %d', num)
@socket.each_message_chunk(&block)
}
end
- def dele( num )
+ def dele(num)
check_response(critical { get_response('DELE %d', num) })
end
- def uidl( num = nil )
+ def uidl(num = nil)
if num
res = check_response(critical { get_response('UIDL %d', num) })
return res.split(/ /)[1]
@@ -841,12 +960,12 @@ module Net
private
- def getok( fmt, *fargs )
+ def getok(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
check_response(recv_response())
end
- def get_response( fmt, *fargs )
+ def get_response(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
recv_response()
end
@@ -855,13 +974,13 @@ module Net
@socket.readline
end
- def check_response( res )
- raise POPError, res unless /\A\+OK/i === res
+ def check_response(res)
+ raise POPError, res unless /\A\+OK/i =~ res
res
end
- def check_response_auth( res )
- raise POPAuthenticationError, res unless /\A\+OK/i === res
+ def check_response_auth(res)
+ raise POPAuthenticationError, res unless /\A\+OK/i =~ res
res
end
@@ -878,4 +997,3 @@ module Net
end # class POP3Command
end # module Net
-
diff --git a/test/gdbm/test_gdbm.rb b/test/gdbm/test_gdbm.rb
index b84221e547..5b25497211 100644
--- a/test/gdbm/test_gdbm.rb
+++ b/test/gdbm/test_gdbm.rb
@@ -90,8 +90,8 @@ if defined? GDBM
end
end
def test_s_open_no_create
- # this test is failed on libgdbm 1.8.0
- assert_nil(gdbm = GDBM.open("tmptest_gdbm", nil))
+ assert_nil(gdbm = GDBM.open("tmptest_gdbm", nil),
+ "this test is failed on libgdbm 1.8.0")
ensure
gdbm.close if gdbm
end
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index ec1bf6b8c8..82caa26cff 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -6,14 +6,18 @@ end
require "rbconfig"
require "socket"
require "test/unit"
+begin
+ loadpath = $:.dup
+ $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
+ require 'envutil'
+ensure
+ $:.replace(loadpath)
+end
if defined?(OpenSSL)
class OpenSSL::TestSSL < Test::Unit::TestCase
- RUBY = ENV["RUBY"] || File.join(
- ::Config::CONFIG["bindir"],
- ::Config::CONFIG["ruby_install_name"] + ::Config::CONFIG["EXEEXT"]
- )
+ RUBY = EnvUtil.rubybin
SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb")
PORT = 20443
ITERATIONS = ($0 == __FILE__) ? 100 : 10
@@ -54,28 +58,84 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
OpenSSL::TestUtils.issue_crl(*arg)
end
- def start_server(port0, verify_mode, start_immediately, &block)
- server = nil
+ def readwrite_loop(ctx, ssl)
+ while line = ssl.gets
+ if line =~ /^STARTTLS$/
+ ssl.accept
+ next
+ end
+ ssl.write(line)
+ end
+ rescue OpenSSL::SSL::SSLError
+ rescue IOError
+ ensure
+ ssl.close rescue nil
+ end
+
+ def server_loop(ctx, ssls, server_proc)
+ loop do
+ ssl = nil
+ begin
+ ssl = ssls.accept
+ rescue OpenSSL::SSL::SSLError
+ retry
+ end
+
+ Thread.start do
+ Thread.current.abort_on_exception = true
+ server_proc.call(ctx, ssl)
+ end
+ end
+ rescue Errno::EBADF, IOError
+ end
+
+ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
+ ctx_proc = args[:ctx_proc]
+ server_proc = args[:server_proc]
+ server_proc ||= method(:readwrite_loop)
+
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.cert_store = store
+ #ctx.extra_chain_cert = [ ca_cert ]
+ ctx.cert = @svr_cert
+ ctx.key = @svr_key
+ ctx.verify_mode = verify_mode
+ ctx_proc.call(ctx) if ctx_proc
+
+ Socket.do_not_reverse_lookup = true
+ tcps = nil
+ port = port0
begin
- cmd = [RUBY]
- cmd << "-d" if $DEBUG
- cmd << SSL_SERVER << port0.to_s << verify_mode.to_s
- cmd << (start_immediately ? "yes" : "no")
- server = IO.popen(cmd.join(" "), "w+")
- server.write(@ca_cert.to_pem)
- server.write(@svr_cert.to_pem)
- server.write(@svr_key.to_pem)
- pid = Integer(server.gets)
- if port = server.gets
- if $DEBUG
- $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port)
- end
- block.call(server, port.to_i)
+ tcps = TCPServer.new("127.0.0.1", port)
+ rescue Errno::EADDRINUSE
+ port += 1
+ retry
+ end
+
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+ ssls.start_immediately = start_immediately
+
+ begin
+ server = Thread.new do
+ Thread.current.abort_on_exception = true
+ server_loop(ctx, ssls, server_proc)
end
+
+ $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG
+
+ block.call(server, port.to_i)
ensure
- if server
- Process.kill(:KILL, pid)
- server.close
+ tcps.close if (tcps)
+ if (server)
+ server.join(5)
+ if server.alive?
+ server.kill
+ server.join
+ flunk("TCPServer was closed and SSLServer is still alive") unless $!
+ end
end
end
end
@@ -89,16 +149,22 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
ssl.connect
end
+ def test_ctx_setup
+ ctx = OpenSSL::SSL::SSLContext.new
+ assert_equal(ctx.setup, true)
+ assert_equal(ctx.setup, nil)
+ end
+
def test_connect_and_close
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
assert(ssl.connect)
ssl.close
assert(!sock.closed?)
sock.close
- sock = TCPSocket.new("127.0.0.1", p)
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true # !!
assert(ssl.connect)
@@ -108,8 +174,8 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
end
def test_read_and_write
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
ssl.connect
@@ -127,13 +193,6 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
assert_equal(str, buf)
}
- # puts and gets
- ITERATIONS.times{
- str = "x" * 100 + "\n"
- ssl.puts(str)
- assert_equal(str, ssl.gets)
- }
-
# read and write
ITERATIONS.times{|i|
str = "x" * 100 + "\n"
@@ -153,9 +212,9 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
def test_client_auth
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
- start_server(PORT, vflag, true){|s, p|
+ start_server(PORT, vflag, true){|server, port|
assert_raises(OpenSSL::SSL::SSLError){
- sock = TCPSocket.new("127.0.0.1", p)
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
}
@@ -163,7 +222,7 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = @cli_key
ctx.cert = @cli_cert
- sock = TCPSocket.new("127.0.0.1", p)
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync_close = true
ssl.connect
@@ -173,11 +232,11 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
called = nil
ctx = OpenSSL::SSL::SSLContext.new
- ctx.client_cert_cb = Proc.new{|ssl|
+ ctx.client_cert_cb = Proc.new{ |sslconn|
called = true
[@cli_cert, @cli_key]
}
- sock = TCPSocket.new("127.0.0.1", p)
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync_close = true
ssl.connect
@@ -189,8 +248,8 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
end
def test_starttls
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, false){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, false){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
str = "x" * 1000 + "\n"
@@ -213,10 +272,10 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
def test_parallel
GC.start
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
ssls = []
10.times{
- sock = TCPSocket.new("127.0.0.1", p)
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
ssl.sync_close = true
@@ -233,17 +292,76 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
}
end
+ def test_verify_result
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ssl.verify_result)
+
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(
+ :verify_callback => Proc.new do |preverify_ok, store_ctx|
+ store_ctx.error = OpenSSL::X509::V_OK
+ true
+ end
+ )
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ ssl.connect
+ assert_equal(OpenSSL::X509::V_OK, ssl.verify_result)
+
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(
+ :verify_callback => Proc.new do |preverify_ok, store_ctx|
+ store_ctx.error = OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION
+ false
+ end
+ )
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_APPLICATION_VERIFICATION, ssl.verify_result)
+ }
+ end
+
+ def test_sslctx_set_params
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, ctx.verify_mode)
+ assert_equal(OpenSSL::SSL::OP_ALL, ctx.options)
+ ciphers = ctx.ciphers
+ ciphers_versions = ciphers.collect{|_, v, _, _| v }
+ ciphers_names = ciphers.collect{|v, _, _, _| v }
+ assert(ciphers_names.all?{|v| /ADH/ !~ v })
+ assert(ciphers_versions.all?{|v| /SSLv2/ !~ v })
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+ assert_raise(OpenSSL::SSL::SSLError){ ssl.connect }
+ assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ssl.verify_result)
+ }
+ end
+
def test_post_connection_check
sslerr = OpenSSL::SSL::SSLError
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
assert_raises(sslerr){ssl.post_connection_check("localhost.localdomain")}
assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
assert(ssl.post_connection_check("localhost"))
assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+
+ cert = ssl.peer_cert
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
}
now = Time.now
@@ -254,14 +372,20 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
]
@svr_cert = issue_cert(@svr, @svr_key, 4, now, now+1800, exts,
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
assert(ssl.post_connection_check("localhost.localdomain"))
assert(ssl.post_connection_check("127.0.0.1"))
assert_raises(sslerr){ssl.post_connection_check("localhost")}
assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+
+ cert = ssl.peer_cert
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
}
now = Time.now
@@ -271,16 +395,135 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
]
@svr_cert = issue_cert(@svr, @svr_key, 5, now, now+1800, exts,
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
- start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|s, p|
- sock = TCPSocket.new("127.0.0.1", p)
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true){|server, port|
+ sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
assert(ssl.post_connection_check("localhost.localdomain"))
assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
assert_raises(sslerr){ssl.post_connection_check("localhost")}
assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ cert = ssl.peer_cert
+ assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost"))
+ assert(!OpenSSL::SSL.verify_certificate_identity(cert, "foo.example.com"))
}
end
+
+ def test_client_session
+ last_session = nil
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
+ 2.times do
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ ssl.session = last_session if last_session
+ ssl.connect
+
+ session = ssl.session
+ if last_session
+ assert(ssl.session_reused?)
+
+ if session.respond_to?(:id)
+ assert_equal(session.id, last_session.id)
+ end
+ assert_equal(session.to_pem, last_session.to_pem)
+ assert_equal(session.to_der, last_session.to_der)
+ # Older version of OpenSSL may not be consistent. Look up which versions later.
+ assert_equal(session.to_text, last_session.to_text)
+ else
+ assert(!ssl.session_reused?)
+ end
+ last_session = session
+
+ str = "x" * 100 + "\n"
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+
+ ssl.close
+ end
+ end
+ end
+
+ def test_server_session
+ connections = 0
+ saved_session = nil
+
+ ctx_proc = Proc.new do |ctx, ssl|
+# add test for session callbacks here
+ end
+
+ server_proc = Proc.new do |ctx, ssl|
+ session = ssl.session
+ stats = ctx.session_cache_stats
+
+ case connections
+ when 0
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 0)
+ assert_equal(stats[:cache_misses], 0)
+ assert(!ssl.session_reused?)
+ when 1
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 1)
+ assert_equal(stats[:cache_misses], 0)
+ assert(ssl.session_reused?)
+ ctx.session_remove(session)
+ saved_session = session
+ when 2
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 1)
+ assert_equal(stats[:cache_misses], 1)
+ assert(!ssl.session_reused?)
+ ctx.session_add(saved_session)
+ when 3
+ assert_equal(stats[:cache_num], 2)
+ assert_equal(stats[:cache_hits], 2)
+ assert_equal(stats[:cache_misses], 1)
+ assert(ssl.session_reused?)
+ ctx.flush_sessions(Time.now + 5000)
+ when 4
+ assert_equal(stats[:cache_num], 1)
+ assert_equal(stats[:cache_hits], 2)
+ assert_equal(stats[:cache_misses], 2)
+ assert(!ssl.session_reused?)
+ ctx.session_add(saved_session)
+ end
+ connections += 1
+
+ readwrite_loop(ctx, ssl)
+ end
+
+ first_session = nil
+ start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
+ 10.times do |i|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ ssl.sync_close = true
+ ssl.session = first_session if first_session
+ ssl.connect
+
+ session = ssl.session
+ if first_session
+ case i
+ when 1; assert(ssl.session_reused?)
+ when 2; assert(!ssl.session_reused?)
+ when 3; assert(ssl.session_reused?)
+ when 4; assert(!ssl.session_reused?)
+ when 5..10; assert(ssl.session_reused?)
+ end
+ end
+ first_session ||= session
+
+ str = "x" * 100 + "\n"
+ ssl.puts(str)
+ assert_equal(str, ssl.gets)
+
+ ssl.close
+ end
+ end
+ end
end
end
diff --git a/version.h b/version.h
index f51e4832f8..39e52831aa 100644
--- a/version.h
+++ b/version.h
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.8.7"
-#define RUBY_RELEASE_DATE "2008-04-23"
+#define RUBY_RELEASE_DATE "2008-04-25"
#define RUBY_VERSION_CODE 187
-#define RUBY_RELEASE_CODE 20080423
+#define RUBY_RELEASE_CODE 20080425
#define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_YEAR 2008
#define RUBY_RELEASE_MONTH 4
-#define RUBY_RELEASE_DAY 23
+#define RUBY_RELEASE_DAY 25
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];