summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
author(no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-03-20 14:50:43 +0000
committer(no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-03-20 14:50:43 +0000
commit3ed1979de25fad04b2b74bd4e4de13d7edd94b3d (patch)
tree5872d29df610f402c7ce21654261d7861b0021b4 /lib
parent99020d6e50702eb371111d73280eb80b4b29ba5b (diff)
This commit was manufactured by cvs2svn to create tag 'v1_6_3'.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_6_3@1265 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/Env.rb14
-rw-r--r--lib/cgi.rb232
-rw-r--r--lib/cgi/session.rb15
-rw-r--r--lib/date.rb38
-rw-r--r--lib/debug.rb210
-rw-r--r--lib/delegate.rb2
-rw-r--r--lib/importenv.rb6
-rw-r--r--lib/irb/ruby-lex.rb2
-rw-r--r--lib/mkmf.rb24
-rw-r--r--lib/monitor.rb53
-rw-r--r--lib/net/http.rb1118
-rw-r--r--lib/net/imap.rb6
-rw-r--r--lib/net/pop.rb13
-rw-r--r--lib/net/protocol.rb309
-rw-r--r--lib/net/smtp.rb29
-rw-r--r--lib/net/telnet.rb217
-rw-r--r--lib/observer.rb2
-rw-r--r--lib/parsedate.rb11
-rw-r--r--lib/ping.rb2
-rw-r--r--lib/thread.rb2
20 files changed, 1191 insertions, 1114 deletions
diff --git a/lib/Env.rb b/lib/Env.rb
index 7101b84c91..452a28659e 100644
--- a/lib/Env.rb
+++ b/lib/Env.rb
@@ -6,19 +6,7 @@
# $USER = "matz"
# p ENV["USER"]
-for k,v in ENV
- next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
- eval <<EOS
- $#{k} = %q!#{v}!
- trace_var "$#{k}", proc{|v|
- ENV[%q!#{k}!] = v;
- $#{k} = %q!#{v}!
- if v == nil
- untrace_var "$#{k}"
- end
- }
-EOS
-end
+require 'importenv'
if __FILE__ == $0
p $TERM
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 7d27cecd67..fcf8c006e5 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -4,7 +4,7 @@
cgi.rb - cgi support library
-Version 2.1.2
+Version 2.1.4
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
@@ -185,12 +185,13 @@ class CGI
CR = "\015"
LF = "\012"
EOL = CR + LF
- VERSION = "2.1.2"
- RELEASE_DATE = "2000-12-25"
- VERSION_CODE = 212
- RELEASE_CODE = 20001225
+ VERSION = '2.1.3'
+ RELEASE_DATE = '2001-03-18'
+ VERSION_CODE = 214
+ RELEASE_CODE = 20010318
+ REVISION = '$Id$'
- NEEDS_BINMODE = true if /WIN/ni === RUBY_PLATFORM
+ NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM)
PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
HTTP_STATUS = {
@@ -350,11 +351,11 @@ class CGI
=begin
=== MAKE RFC1123 DATE STRING
CGI::rfc1123_date(Time.now)
- # Sat, 1 Jan 2000 00:00:00 GMT
+ # Sat, 01 Jan 2000 00:00:00 GMT
=end
def CGI::rfc1123_date(time)
t = time.clone.gmtime
- return format("%s, %d %s %d %.2d:%.2d:%.2d GMT",
+ return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
t.hour, t.min, t.sec)
end
@@ -423,7 +424,8 @@ status:
options["type"].concat( options.delete("charset") )
end
- if options.delete("nph") or (/IIS/n === env_table['SERVER_SOFTWARE'])
+ options.delete("nph") if defined?(MOD_RUBY)
+ if options.delete("nph") or /IIS/n.match(env_table['SERVER_SOFTWARE'])
buf.concat( (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " )
buf.concat( (HTTP_STATUS[options["status"]] or
options["status"] or
@@ -446,7 +448,9 @@ status:
end
if options.has_key?("status")
- buf.concat("Status: " + options.delete("status") + EOL)
+ status = (HTTP_STATUS[options["status"]] or options["status"])
+ buf.concat("Status: " + status + EOL)
+ options.delete("status")
end
if options.has_key?("server")
@@ -496,8 +500,21 @@ status:
}
if defined?(MOD_RUBY)
- buf.scan(/([^:]+): (.+)#{EOL}/n){
- Apache::request[$1] = $2
+ table = Apache::request.headers_out
+ buf.scan(/([^:]+): (.+)#{EOL}/n){ |name, value|
+ $stderr.printf("name:%s value:%s\n", name, value) if $DEBUG
+ case name
+ when 'Set-Cookie'
+ table.add($1, $2)
+ when /^status$/ni
+ Apache::request.status_line = value
+ when /^content-type$/ni
+ Apache::request.content_type = value
+ when /^content-encoding$/ni
+ Apache::request.content_encoding = value
+ else
+ Apache::request.headers_out[name] = value
+ end
}
Apache::request.send_http_header
''
@@ -793,9 +810,9 @@ convert string charset, and set language to "ja".
body = Tempfile.new("CGI")
body.binmode
- until head and (/#{boundary}(?:#{EOL}|--)/n === buf)
+ until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
- if (not head) and (/#{EOL}#{EOL}/n === buf)
+ if (not head) and /#{EOL}#{EOL}/n.match(buf)
buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
head = $1.dup
""
@@ -834,14 +851,14 @@ convert string charset, and set language to "ja".
end
END
- /Content-Disposition:.* filename="?([^\";]*)"?/ni === head
+ /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
eval <<-END
def body.original_filename
#{
filename = ($1 or "").dup
- if (/Mac/ni === env_table['HTTP_USER_AGENT']) and
- (/Mozilla/ni === env_table['HTTP_USER_AGENT']) and
- (not /MSIE/ni === env_table['HTTP_USER_AGENT'])
+ if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
+ /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
+ (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
CGI::unescape(filename)
else
filename
@@ -850,14 +867,14 @@ convert string charset, and set language to "ja".
end
END
- /Content-Type: (.*)/ni === head
+ /Content-Type: (.*)/ni.match(head)
eval <<-END
def body.content_type
#{($1 or "").dump.untaint}.taint
end
END
- /Content-Disposition:.* name="?([^\";]*)"?/ni === head
+ /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
name = $1.dup
if params.has_key?(name)
@@ -889,7 +906,7 @@ convert string charset, and set language to "ja".
words = Shellwords.shellwords(string)
- if words.find{|x| /=/n === x }
+ if words.find{|x| /=/n.match(x) }
words.join('&')
else
words.join('+')
@@ -899,8 +916,7 @@ convert string charset, and set language to "ja".
def initialize_query()
if ("POST" == env_table['REQUEST_METHOD']) and
- (%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n ===
- env_table['CONTENT_TYPE'])
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE'])
boundary = $1.dup
@params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
else
@@ -975,8 +991,8 @@ convert string charset, and set language to "ja".
cgi = CGI.new("html3") # add HTML generation methods
cgi.element
cgi.element{ "string" }
- cgi.element({ "ATTRILUTE1" => "value1", "ATTRIBUTE2" => "value2" })
- cgi.element({ "ATTRILUTE1" => "value1", "ATTRIBUTE2" => "value2" }){ "string" }
+ cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" })
+ cgi.element({ "ATTRIBUTE1" => "value1", "ATTRIBUTE2" => "value2" }){ "string" }
# add HTML generation methods
CGI.new("html3") # html3.2
@@ -1235,8 +1251,10 @@ convert string charset, and set language to "ja".
form("get", "url"){ "string" }
# <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- form({"METHOD" => "post", ENCTYPE => "enctype"}){ "string" }
+ form({"METHOD" => "post", "ENCTYPE" => "enctype"}){ "string" }
# <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
+
+The hash keys are case sensitive. Ask the samples.
=end
def form(method = "post", action = nil, enctype = "application/x-www-form-urlencoded")
attributes = if method.kind_of?(String)
@@ -1244,7 +1262,7 @@ convert string charset, and set language to "ja".
"ENCTYPE" => enctype }
else
unless method.has_key?("METHOD")
- method["METHOD"] = method
+ method["METHOD"] = "post"
end
unless method.has_key?("ENCTYPE")
method["ENCTYPE"] = enctype
@@ -1935,161 +1953,7 @@ end
== HISTORY
-* Mon Dec 25 05:02:27 JST 2000 - wakou
- * version 2.1.2
- * bug fix: CGI::escapeElement(): didn't accept empty element.
- * bug fix: CGI::unescapeElement(): ditto.
- * bug fix: CGI::unescapeHTML(): support for "&copy;, &hearts;, ..."
- thanks to YANAGAWA Kazuhisa <kjana@os.xaxon.ne.jp>
- * bug fix: CGI::unescapeHTML(): support for "&#09;"
- thanks to OHSHIMA Ryunosuke <ryu@jaist.ac.jp>
- * Regexp::last_match[0] --> $&
- * Regexp::last_match[1] --> $1
- * Regexp::last_match[2] --> $2
- * add: CGI#param(): test implement. undocumented.
-
-* Mon Dec 11 00:16:51 JST 2000 - wakou
- * version 2.1.1
- * support -T1 on ruby 1.6.2
- * body.original_filename: eval(str.dump.untaint).taint
- * body.content_type: eval(str.dump.untaint).taint
- * $& --> Regexp::last_match[0]
- * $1 --> Regexp::last_match[1]
- * $2 --> Regexp::last_match[2]
-
-* Thu Oct 12 01:16:59 JST 2000 - wakou
- * version 2.1.0
- * bug fix: CGI::html(): PRETTY option didn't work.
- thanks to akira yamada <akira@ruby-lang.org>
-
-* Wed Sep 13 06:09:26 JST 2000 - wakou
- * version 2.0.1
- * bug fix: CGI::header(): output status header.
- thanks to Yasuhiro Fukuma <yasuf@bsdclub.org>
-
-* Tue Sep 12 06:56:51 JST 2000 - wakou
- * version 2.0.0
- * require ruby1.5.4 or later. (ruby1.4 doesn't have block_given? method.)
- * improvement: CGI::escape(), CGI::unescape().
- thanks to WATANABE Hirofumi <eban@os.rim.or.jp>
- * bug fix: CGI::escapeElement().
- * improvement: CGI::unescapeHTML().
- thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
-
-* 2000/08/09 04:32:22 - matz
- * improvement: CGI::pretty()
-
-* 2000/06/23 07:01:34 - matz
- * change: iterator? --> block_given?
-
-* Sun Jun 18 23:31:44 JST 2000 - wakou
- * version 1.7.0
- * change: version syntax. old: x.yz, now: x.y.z
-
-* 2000/06/13 15:49:27 - wakou
- * version 1.61
- * read_multipart(): if no content body then raise EOFError.
-
-* 2000/06/03 18:16:17 - wakou
- * version 1.60
- * improve: CGI::pretty()
-
-* 2000/05/30 19:04:08 - wakou
- * version 1.50
- * CGI#out(): if "HEAD" == REQUEST_METHOD then output only HTTP header.
-
-* 2000/05/24 06:58:51 - wakou
- * version 1.40
- * typo: CGI::Cookie::new()
- * bug fix: CGI::escape(): bad: " " --> "%2B"; true: " " --> "+";
- thanks to Ryunosuke Ohshima <ryu@jaist.ac.jp>
-
-* 2000/05/08 21:51:30 - wakou
- * version 1.31
- * improvement of time forming new CGI object accompanied with HTML generation methods.
-
-* 2000/05/07 21:51:14 - wakou
- * version 1.30
- * require English.rb
- * improvement of load time.
-
-* 2000/05/02 21:44:12 - wakou
- * version 1.21
- * support for ruby 1.5.3 (2000-05-01) (Array#filter --> Array#collect!)
-
-* 2000/04/03 18:31:42 - wakou
- * version 1.20
- * bug fix: CGI#image_button() can't get Hash option.
- thanks to Takashi Ikeda <ikeda@auc.co.jp>
- * CGI::unescapeHTML(): simple support for "&#12345;"
- * CGI::Cookie::new(): simple support for IE
- * CGI::escape(): ' ' replaced by '+'
-
-* 1999/12/06 20:16:34 - wakou
- * version 1.10
- * can make many CGI objects.
- * if use mod_ruby, then require ruby1.4.3 or later.
-
-* 1999/11/29 21:35:58 - wakou
- * version 1.01
- * support for ruby 1.5.0 (1999-11-20)
-
-* 1999/09/13 23:00:58 - wakou
- * version 1.00
- * COUTION! name change. CGI.rb --> cgi.rb
- * CGI#auth_type, CGI#content_length, CGI#content_type, ...
- if not ENV included it, then return nil.
- * CGI#content_length and CGI#server_port return Integer.
- * if not CGI#params.include?('name'), then CGI#params['name'] return [].
- * if not CGI#cookies.include?('name'), then CGI#cookies['name'] return [].
-
-* 1999/08/05 18:04:59 - wakou
- * version 0.41
- * typo. thanks to MJ Ray <markj@altern.org>
- HTTP_STATUS["NOT_INPLEMENTED"] --> HTTP_STATUS["NOT_IMPLEMENTED"]
-
-* 1999/07/20 20:44:31 - wakou
- * version 0.40
- * COUTION! incompatible change.
- sorry, but probably this change is last big incompatible change.
- * CGI::print --> CGI#out
- cgi = CGI.new
- cgi.out{"string"} # old: CGI::print{"string"}
- * CGI::cookie --> CGI::Cookie::new
- cookie1 = CGI::Cookie::new # old: CGI::cookie
- * CGI::header --> CGI#header
-
-* 1999/06/29 06:50:21 - wakou
- * version 0.30
- * COUTION! incompatible change.
- query = CGI.new
- cookies = query.cookies # old: query.cookie
- values = query.cookies[name] # old: query.cookie[name]
-
-* 1999/06/21 21:05:57 - wakou
- * version 0.24
- * CGI::Cookie::parse() return { name => CGI::Cookie object } pairs.
-
-* 1999/06/20 23:29:12 - wakou
- * version 0.23
- * modified a bit to clear module separation.
-
-* Mon Jun 14 17:49:32 JST 1999 - matz
- * version 0.22
- * Cookies are now CGI::Cookie objects.
- * Cookie modeled after CGI::Cookie.pm.
-
-* Fri Jun 11 11:19:11 JST 1999 - matz
- * version 0.21
- * modified a bit to clear module separation.
-
-* 1999/06/03 06:48:15 - wakou
- * version 0.20
- * support for multipart form.
-
-* 1999/05/24 07:05:41 - wakou
- * version 0.10
- * first release.
-
-$Date$
+delete. see cvs log.
+
+
=end
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index 48f3496939..1120fb50f0 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -1,3 +1,4 @@
+# Copyright (C) 2001 Yukihiro "Matz" Matsumoto
# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright (C) 2000 Information-technology Promotion Agency, Japan
@@ -15,23 +16,22 @@ class CGI
}
end
- def create_new_id
+ def Session::create_new_id
require 'md5'
md5 = MD5::new
md5.update(String(Time::now))
md5.update(String(rand(0)))
md5.update(String($$))
md5.update('foobar')
- @session_id = md5.hexdigest[0,16]
+ md5.hexdigest[0,16]
end
- private :create_new_id
def initialize(request, option={})
session_key = option['session_key'] || '_session_id'
id, = option['session_id']
unless id
if option['new_session']
- id = create_new_id
+ id = Session::create_new_id
end
end
unless id
@@ -43,7 +43,7 @@ class CGI
if option.key?('new_session') and not option['new_session']
raise ArgumentError, "session_key `%s' should be supplied"%session_key
end
- id = create_new_id
+ id = Session::create_new_id
end
end
@session_id = id
@@ -54,7 +54,9 @@ class CGI
@output_cookies = [
Cookie::new("name" => session_key,
"value" => id,
- "path" => if ENV["SCRIPT_NAME"] then
+ "path" => if option['session_path'] then
+ option['session_path']
+ elsif ENV["SCRIPT_NAME"] then
File::dirname(ENV["SCRIPT_NAME"])
else
""
@@ -132,6 +134,7 @@ class CGI
end
def close
+ return if @f.closed?
update
@f.close
end
diff --git a/lib/date.rb b/lib/date.rb
index 58179a7153..3422121298 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -1,5 +1,5 @@
-# date.rb: Written by Tadayoshi Funaba 1998-2000
-# $Id: date.rb,v 1.22 2000-07-16 10:23:40+09 tadf Exp $
+# date2.rb: Written by Tadayoshi Funaba 1998-2001
+# $Id: date2.rb,v 1.23 2001-01-18 12:09:47+09 tadf Exp $
class Date
@@ -128,16 +128,15 @@ class Date
end
if d < 0
ny, nm = clfloor(y * 12 + m, 12)
- nm, = clfloor(m + 1, 1)
- la = nil
- 31.downto 1 do |z|
- break if la = exist3?(y, m, z, sg)
- end
- ns = ns?(la, sg)
- d = jd_to_civil(civil_to_jd(ny, nm, 1, ns) + d, ns)[-1]
+ nm, = clfloor(nm + 1, 1)
+ jd = civil_to_jd(ny, nm, d + 1, sg)
+ ns = ns?(jd, sg)
+ return unless [y, m] == jd_to_civil(jd, sg)[0..1]
+ return unless [ny, nm, 1] == jd_to_civil(jd - d, ns)
+ else
+ jd = civil_to_jd(y, m, d, sg)
+ return unless [y, m, d] == jd_to_civil(jd, sg)
end
- jd = civil_to_jd(y, m, d, sg)
- return unless [y, m, d] == jd_to_civil(jd, sg)
jd
end
@@ -154,16 +153,15 @@ class Date
def exist2? (y, d, sg=ITALY)
if d < 0
- ny = y + 1
- la = nil
- 366.downto 1 do |z|
- break if la = exist2?(y, z, sg)
- end
- ns = ns?(la, sg)
- d = jd_to_ordinal(ordinal_to_jd(ny, 1, ns) + d, ns)[-1]
+ ny, = clfloor(y + 1, 1)
+ jd = ordinal_to_jd(ny, d + 1, sg)
+ ns = ns?(jd, sg)
+ return unless [y] == jd_to_ordinal(jd, sg)[0..0]
+ return unless [ny, 1] == jd_to_ordinal(jd - d, ns)
+ else
+ jd = ordinal_to_jd(y, d, sg)
+ return unless [y, d] == jd_to_ordinal(jd, sg)
end
- jd = ordinal_to_jd(y, d, sg)
- return unless [y, d] == jd_to_ordinal(jd, sg)
jd
end
diff --git a/lib/debug.rb b/lib/debug.rb
index b6968cc338..220b68d2c9 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -91,22 +91,70 @@ class DEBUGGER__
@finish_pos = 0
@trace = false
@catch = "StandardError"
+ @suspend_next = false
end
def stop_next(n=1)
@stop_next = n
end
+ def set_suspend
+ @suspend_next = true
+ end
+
+ def clear_suspend
+ @suspend_next = false
+ end
+
+ def suspend_all
+ DEBUGGER__.suspend
+ end
+
+ def resume_all
+ DEBUGGER__.resume
+ end
+
+ def check_suspend
+ while (Thread.critical = true; @suspend_next)
+ DEBUGGER__.waiting.push Thread.current
+ @suspend_next = false
+ Thread.stop
+ end
+ Thread.critical = false
+ end
+
+ def trace?
+ @trace
+ end
+
+ def set_trace(arg)
+ @trace = arg
+ end
+
def stdout
DEBUGGER__.stdout
end
+
def break_points
DEBUGGER__.break_points
end
+
def display
DEBUGGER__.display
end
+ def context(th)
+ DEBUGGER__.context(th)
+ end
+
+ def set_trace_all(arg)
+ DEBUGGER__.set_trace(arg)
+ end
+
+ def set_last_thread(th)
+ DEBUGGER__.set_last_thread(th)
+ end
+
def debug_eval(str, binding)
begin
val = eval(str, binding)
@@ -205,7 +253,7 @@ class DEBUGGER__
def debug_command(file, line, id, binding)
MUTEX.lock
- DEBUGGER__.set_last_thread(Thread.current)
+ set_last_thread(Thread.current)
frame_pos = 0
binding_file = file
binding_line = line
@@ -218,7 +266,8 @@ class DEBUGGER__
end
@frames[0] = [binding, file, line, id]
display_expressions(binding)
- while input = readline("(rdb:%d) "%thnum(), true)
+ prompt = true
+ while prompt and input = readline("(rdb:%d) "%thnum(), true)
catch(:debug_error) do
if input == ""
input = DEBUG_LAST_CMD[0]
@@ -228,18 +277,24 @@ class DEBUGGER__
end
case input
- when /^\s*tr(?:ace)?(?:\s+(on|off))?$/
- if defined?( $1 )
+ when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
+ if defined?( $2 )
if $1 == 'on'
- @trace = true
+ set_trace_all true
else
- @trace = false
+ set_trace_all false
+ end
+ elsif defined?( $1 )
+ if $1 == 'on'
+ set_trace true
+ else
+ set_trace false
end
end
- if @trace
- stdout.print "Trace on\n"
+ if trace?
+ stdout.print "Trace on.\n"
else
- stdout.print "Trace off\n"
+ stdout.print "Trace off.\n"
end
when /^\s*b(?:reak)?\s+((?:.*?+:)?.+)$/
@@ -336,8 +391,7 @@ class DEBUGGER__
end
when /^\s*c(?:ont)?$/
- MUTEX.unlock
- return
+ prompt = false
when /^\s*s(?:tep)?(?:\s+(\d+))?$/
if $1
@@ -346,7 +400,7 @@ class DEBUGGER__
lev = 1
end
@stop_next = lev
- return
+ prompt = false
when /^\s*n(?:ext)?(?:\s+(\d+))?$/
if $1
@@ -356,7 +410,7 @@ class DEBUGGER__
end
@stop_next = lev
@no_step = @frames.size - frame_pos
- return
+ prompt = false
when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
display_frames(frame_pos)
@@ -417,8 +471,7 @@ class DEBUGGER__
else
@finish_pos = @frames.size - frame_pos
frame_pos = 0
- MUTEX.unlock
- return
+ prompt = false
end
when /^\s*cat(?:ch)?(?:\s+(.+))?$/
@@ -440,8 +493,10 @@ class DEBUGGER__
end
when /^\s*q(?:uit)?$/
- input = readline("really quit? (y/n) ", false)
- exit if input == "y"
+ input = readline("Really quit? (y/n) ", false)
+ if input == "y"
+ exit! # exit -> exit!: No graceful way to stop threads...
+ end
when /^\s*v(?:ar)?\s+/
debug_variable_info($', binding)
@@ -451,8 +506,7 @@ class DEBUGGER__
when /^\s*th(?:read)?\s+/
if DEBUGGER__.debug_thread_info($', binding) == :cont
- MUTEX.unlock
- return
+ prompt = false
end
when /^\s*p\s+/
@@ -467,6 +521,8 @@ class DEBUGGER__
end
end
end
+ MUTEX.unlock
+ resume_all
end
def debug_print_help
@@ -492,7 +548,8 @@ Commands
up[ nn] move to higher frame
down[ nn] move to lower frame
fin[ish] return to outer frame
- tr[ace][ (on|off)] set trace mode
+ tr[ace] (on|off) set trace mode of current thread
+ tr[ace] (on|off) all set trace mode of all threads
q[uit] exit from debugger
v[ar] g[lobal] show global variables
v[ar] l[ocal] show local variables
@@ -501,11 +558,10 @@ Commands
m[ethod] i[nstance] <obj> show methods of object
m[ethod] <class|module> show instance methods of class or module
th[read] l[ist] list all threads
- th[read] c[ur[rent]] show current threads
- th[read] <nnn> stop thread nnn
- th[read] stop <nnn> alias for th[read] <nnn>
- th[read] c[ur[rent]] <nnn> alias for th[read] <nnn>
- th[read] resume <nnn> run thread nnn
+ th[read] c[ur[rent]] show current thread
+ th[read] [sw[itch]] <nnn> switch thread context to nnn
+ th[read] stop <nnn> stop thread nnn
+ th[read] resume <nnn> resume thread nnn
p expression evaluate expression and print its value
h[elp] print this help
<everything else> evaluate
@@ -587,7 +643,7 @@ EOHELP
end
def check_break_points(file, pos, binding, id)
- MUTEX.lock # Stop all threads before 'line' and 'call'.
+ return false if break_points.empty?
file = File.basename(file)
n = 1
for b in break_points
@@ -604,7 +660,6 @@ EOHELP
end
n += 1
end
- MUTEX.unlock
return false
end
@@ -616,7 +671,6 @@ EOHELP
end
if @catch and ($!.type.ancestors.find { |e| e.to_s == @catch })
- MUTEX.lock
fs = @frames.size
tb = caller(0)[-fs..-1]
if tb
@@ -624,12 +678,14 @@ EOHELP
stdout.printf "\tfrom %s\n", i
end
end
+ suspend_all
debug_command(file, line, id, binding)
end
end
def trace_func(event, file, line, id, binding, klass)
- Tracer.trace_func(event, file, line, id, binding) if @trace
+ Tracer.trace_func(event, file, line, id, binding, klass) if trace?
+ context(Thread.current).check_suspend
@file = file
@line = line
case event
@@ -647,6 +703,7 @@ EOHELP
@stop_next = 1
else
@no_step = nil
+ suspend_all
debug_command(file, line, id, binding)
@last = [file, line]
end
@@ -656,6 +713,7 @@ EOHELP
@frames.unshift [binding, file, line, id]
if check_break_points(file, id.id2name, binding, id) or
check_break_points(klass.to_s, id.id2name, binding, id)
+ suspend_all
debug_command(file, line, id, binding)
end
@@ -668,6 +726,7 @@ EOHELP
when 'return', 'end'
if @frames.size == @finish_pos
@stop_next = 1
+ @finish_pos = 0
end
@frames.shift
@@ -682,19 +741,20 @@ EOHELP
end
end
- trap("INT") { DEBUGGER__.interrupt }
-# $DEBUG = true
+ trap("INT") { DEBUGGER__.interrupt }
@last_thread = Thread::main
@max_thread = 1
@thread_list = {Thread::main => 1}
@break_points = []
@display = []
+ @waiting = []
@stdout = STDOUT
class <<DEBUGGER__
def stdout
@stdout
end
+
def stdout=(s)
@stdout = s
end
@@ -707,10 +767,51 @@ EOHELP
@break_points
end
+ def waiting
+ @waiting
+ end
+
+ def set_trace( arg )
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ context(th[0]).set_trace arg
+ end
+ Thread.critical = false
+ end
+
def set_last_thread(th)
@last_thread = th
end
+ def suspend
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ next if th[0] == Thread.current
+ context(th[0]).set_suspend
+ end
+ Thread.critical = false
+ # Schedule other threads to suspend as soon as possible.
+ Thread.pass
+ end
+
+ def resume
+ Thread.critical = true
+ make_thread_list
+ for th in @thread_list
+ next if th[0] == Thread.current
+ context(th[0]).clear_suspend
+ end
+ waiting.each do |th|
+ th.run
+ end
+ waiting.clear
+ Thread.critical = false
+ # Schedule other threads to restart as soon as possible.
+ Thread.pass
+ end
+
def context(thread=Thread.current)
c = thread[:__debugger_data__]
unless c
@@ -726,7 +827,7 @@ EOHELP
def get_thread(num)
th = @thread_list.index(num)
unless th
- @stdout.print "no thread no.", num, "\n"
+ @stdout.print "No thread ##{num}\n"
throw :debug_error
end
th
@@ -773,31 +874,52 @@ EOHELP
make_thread_list
thread_list_all
- when /^c(?:ur(?:rent)?)?\s+(\d+)/, /^stop\s+(\d+)/, /^(\d+)/
+ when /^c(?:ur(?:rent)?)?$/
+ make_thread_list
+ thread_list(@thread_list[Thread.current])
+
+ when /^(?:sw(?:itch)?\s+)?(\d+)/
make_thread_list
th = get_thread($1.to_i)
- thread_list(@thread_list[th])
- context(th).stop_next
- th.run
- return :cont
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ else
+ thread_list(@thread_list[th])
+ context(th).stop_next
+ th.run
+ return :cont
+ end
- when /^c(?:ur(?:rent)?)?$/
+ when /^stop\s+(\d+)/
make_thread_list
- thread_list(@thread_list[Thread.current])
+ th = get_thread($1.to_i)
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ elsif th.stop?
+ @stdout.print "Already stopped.\n"
+ else
+ thread_list(@thread_list[th])
+ context(th).suspend
+ end
when /^resume\s+(\d+)/
make_thread_list
th = get_thread($1.to_i)
- thread_list(@thread_list[th])
- th.run
- return :cont
+ if th == Thread.current
+ @stdout.print "It's the current thread.\n"
+ elsif !th.stop?
+ @stdout.print "Already running."
+ else
+ thread_list(@thread_list[th])
+ th.run
+ end
end
end
end
stdout.printf "Debug.rb\n"
stdout.printf "Emacs support available.\n\n"
- set_trace_func proc{|event, file, line, id, binding,klass,*rest|
- DEBUGGER__.context.trace_func event, file, line, id, binding,klass
+ set_trace_func proc { |event, file, line, id, binding, klass, *rest|
+ DEBUGGER__.context.trace_func event, file, line, id, binding, klass
}
end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 480e1ef6b8..a72ea943ba 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -8,7 +8,7 @@
# Usage:
# foo = Object.new
# foo2 = SimpleDelegator.new(foo)
-# foo.hash == foo2.hash # => true
+# foo.hash == foo2.hash # => false
#
# Foo = DelegateClass(Array)
#
diff --git a/lib/importenv.rb b/lib/importenv.rb
index fcf306a9ab..586f37661b 100644
--- a/lib/importenv.rb
+++ b/lib/importenv.rb
@@ -10,10 +10,10 @@
for k,v in ENV
next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
eval <<EOS
- $#{k} = %q!#{v}!
+ $#{k} = v
trace_var "$#{k}", proc{|v|
- ENV[%q!#{k}!] = v;
- $#{k} = %q!#{v}!
+ ENV[%q!#{k}!] = v
+ $#{k} = v
if v == nil
untrace_var "$#{k}"
end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index 4c7a3b1002..534870e329 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -608,7 +608,7 @@ class RubyLex
identify_quotation
elsif peek(0) == '='
getc
- Token(OP_ASGIN, "%")
+ Token(TkOPASGN, :%)
elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
identify_quotation
else
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 317200ba79..eb3cb74e16 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -43,7 +43,7 @@ else
$null = open('test.log', 'w')
end
-LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
+LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
CPP = "#{CONFIG['CPP']} -E %s -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s conftest.c"
def rm_f(*files)
@@ -155,7 +155,9 @@ def install_rb(mfile, dest, srcdir = nil)
mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' %s/%s\n", dest, f
end
for f in path
- mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' lib/%s %s/%s\n", f, dest, f
+ d = '/' + File::dirname(f)
+ d = '' if d == '/.'
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' %s/%s %s%s\n", libdir, f, dest, d
end
end
@@ -352,6 +354,8 @@ def dir_config(target, idefault=nil, ldefault=nil)
end
def create_makefile(target, srcdir = File.dirname($0))
+ save_libs = $libs.dup
+ save_libpath = $LIBPATH.dup
print "creating Makefile\n"
rm_f "conftest*"
STDOUT.flush
@@ -370,10 +374,9 @@ def create_makefile(target, srcdir = File.dirname($0))
end
$DLDFLAGS = CONFIG["DLDFLAGS"]
- if $configure_args['--enable-shared'] or CONFIG['LIBRUBY'] != CONFIG['LIBRUBY_A']
- $libs = CONFIG["LIBRUBYARG"] + " " + $libs
- $LIBPATH |= ["$(topdir)", CONFIG["libdir"]]
- end
+ $libs = CONFIG["LIBRUBYARG"] + " " + $libs
+ $configure_args['--enable-shared'] or $LIBPATH |= [$topdir]
+ $LIBPATH |= [CONFIG["libdir"]]
defflag = ''
if RUBY_PLATFORM =~ /cygwin|mingw/
@@ -474,7 +477,7 @@ $(archdir)/$(DLLIB): $(DLLIB)
@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(archdir)
@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(archdir)/$(DLLIB)
EOMF
- install_rb(mfile, "$(libdir)")
+ install_rb(mfile, "$(libdir)", srcdir)
mfile.printf "\n"
mfile.printf <<EOMF
@@ -482,7 +485,7 @@ $(sitearchdir)/$(DLLIB): $(DLLIB)
@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(sitearchdir)
@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(sitearchdir)/$(DLLIB)
EOMF
- install_rb(mfile, "$(sitelibdir)")
+ install_rb(mfile, "$(sitelibdir)", srcdir)
mfile.printf "\n"
if /mswin32/ !~ RUBY_PLATFORM
@@ -504,6 +507,9 @@ EOMF
.c.#{$OBJEXT}:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
+
+.cc.#{$OBJEXT} .cpp.#{$OBJEXT} .cxx.#{$OBJEXT} .C.#{$OBJEXT}:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
"
end
@@ -536,6 +542,8 @@ EOMF
dfile.close
end
mfile.close
+ $libs = save_libs
+ $LIBPATH = save_libpath
end
$OBJEXT = CONFIG["OBJEXT"]
diff --git a/lib/monitor.rb b/lib/monitor.rb
index 75d9c35821..7cca6e871e 100644
--- a/lib/monitor.rb
+++ b/lib/monitor.rb
@@ -1,27 +1,44 @@
=begin
-monitor.rb
-Author: Shugo Maeda <shugo@netlab.co.jp>
-Version: 1.2.1
+= monitor.rb
-USAGE:
+Copyright (C) 2001 Shugo Maeda <shugo@ruby-lang.org>
- foo = Foo.new
- foo.extend(MonitorMixin)
- cond = foo.new_cond
+This library is distributed under the terms of the Ruby license.
+You can freely distribute/modify this library.
- thread1:
- foo.synchronize {
- ...
- cond.wait_until { foo.done? }
- ...
- }
+== example
- thread2:
- foo.synchronize {
- foo.do_something
- cond.signal
- }
+This is a simple example.
+
+ require 'monitor.rb'
+
+ buf = []
+ buf.extend(MonitorMixin)
+ empty_cond = buf.new_cond
+
+ # consumer
+ Thread.start do
+ loop do
+ buf.synchronize do
+ empty_cond.wait_while { buf.empty? }
+ print buf.shift
+ end
+ end
+ end
+
+ # producer
+ while line = ARGF.gets
+ buf.synchronize do
+ buf.push(line)
+ empty_cond.signal
+ end
+ end
+
+The consumer thread waits for the producer thread to push a line
+to buf while buf.empty?, and the producer thread (main thread)
+reads a line from ARGF and push it to buf, then call
+empty_cond.signal.
=end
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 3900ed6c68..26e5285525 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -1,8 +1,9 @@
=begin
-= net/http.rb version 1.1.32
+= net/http.rb version 1.1.34
+
+written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
-maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This file is derived from "http-access.rb".
This program is free software.
@@ -14,9 +15,34 @@ You can get it from RAA
(Ruby Application Archive: http://www.ruby-lang.org/en/raa.html).
-= class HTTP
+== http.rb version 1.2 features
+
+You can use 1.2 features by calling HTTP.version_1_2. And
+calling Net::HTTP.version_1_1 allows to use 1.1 features.
+
+ # example
+ HTTP.start {|http1| ...(http1 has 1.1 features)... }
+
+ HTTP.version_1_2
+ HTTP.start {|http2| ...(http2 has 1.2 features)... }
+
+ HTTP.version_1_1
+ HTTP.start {|http3| ...(http3 has 1.1 features)... }
+
+Changes are:
-== Class Methods
+ * HTTP#get, head, post does not raise ProtocolError
+ * HTTP#get, head, post returns only one object, a HTTPResponse object
+ * HTTPResponseReceiver is joined into HTTPResponse
+ * request object: HTTP::Get, Head, Post; and HTTP#request(req)
+
+WARNING: These features are not definite yet.
+They will change without notice!
+
+
+== class HTTP
+
+=== Class Methods
: new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
creates a new Net::HTTP object.
@@ -49,7 +75,7 @@ You can get it from RAA
HTTP default port (80).
-== Methods
+=== Methods
: start
: start {|http| .... }
@@ -72,7 +98,7 @@ You can get it from RAA
get data from "path" on connecting host.
"header" must be a Hash like { 'Accept' => '*/*', ... }.
Data is written to "dest" by using "<<" method.
- This method returns Net::HTTPResponse object, and "dest".
+ This method returns HTTPResponse object, and "dest".
# example
response, body = http.get( '/index.html' )
@@ -95,7 +121,7 @@ You can get it from RAA
: head( path, header = nil )
gets only header from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
- This method returns a Net::HTTPResponse object.
+ This method returns a HTTPResponse object.
You can http header from this object like:
response['content-length'] #-> '2554'
@@ -109,7 +135,7 @@ You can get it from RAA
If the body exists, also gets entity body.
Data is written to "dest" by using "<<" method.
"header" must be a Hash like { 'Accept' => '*/*', ... }.
- This method returns Net::HTTPResponse object and "dest".
+ This method returns HTTPResponse object and "dest".
If called with block, gives a part of entity body string.
@@ -181,21 +207,21 @@ You can get it from RAA
response.body
-= class HTTPResponse
+== class HTTPResponse
HTTP response object.
All "key" is case-insensitive.
-== Methods
+=== Methods
: body
- the entity body. ("dest" argument for HTTP#get, post, put)
+ the entity body (String).
: self[ key ]
returns header field for "key".
for HTTP, value is a string like 'text/plain'(for Content-Type),
- '2045'(for Content-Length), 'bytes 0-1024/10024'(for Content-Range).
- Multiple header had be joined by HTTP1.1 scheme.
+ '2045'(for Content-Length), 'bytes 0-1023/10024'(for Content-Range).
+ If there's some fields which has same name, they are joined with ','.
: self[ key ] = val
set field value for "key".
@@ -204,88 +230,92 @@ All "key" is case-insensitive.
true if key exists
: each {|name,value| .... }
- iterates for each field name and value pair
+ iterates for each field name and value pair.
: code
- HTTP result code string. For example, '302'
+ HTTP result code string. For example, '302'.
: message
- HTTP result message. For example, 'Not Found'
+ HTTP result message. For example, 'Not Found'.
-= class HTTPResponseReceiver
+== class HTTPResponseReceiver
-== Methods
+=== Methods
: header
: response
- Net::HTTPResponse object
+ HTTPResponse object
-: body( dest = '' )
-: entity( dest = '' )
- entity body. A body is written to "dest" using "<<" method.
+: read_body( dest = '' )
+ reads entity body into DEST by calling "<<" method and
+ returns DEST.
-: body {|str| ... }
- gets entity body with block.
- If this method is called twice, block is not executed and
- returns first "dest".
+: read_body {|string| ... }
+ reads entity body little by little and gives it to block
+ until entity ends.
+: body
+: entity
+ entity body. If #read_body is called already, returns its
+ argument DEST. Else returns entity body as String.
-= http.rb version 1.2 features
+ Calling this method any times causes returning same
+ object (does not read entity again).
-You can use 1.2 features by calling HTTP.version_1_2. And
-calling Net::HTTP.version_1_1 allows to use 1.1 features.
+=end
- # example
- HTTP.start {|http1| ...(http1 has 1.1 features)... }
+require 'net/protocol'
- HTTP.version_1_2
- HTTP.start {|http2| ...(http2 has 1.2 features)... }
- HTTP.version_1_1
- HTTP.start {|http3| ...(http3 has 1.1 features)... }
+module Net
-== Method (only diff to 1.1)
+ class HTTPBadResponse < StandardError; end
+ class HTTPHeaderSyntaxError < StandardError; end
-: get( path, u_header = nil )
-: get( path, u_header = nil ) {|str| .... }
- gets document from "path".
- returns HTTPResponse object.
-: head( path, u_header = nil )
- gets only document header from "path".
- returns HTTPResponse object.
+ class HTTP < Protocol
-: post( path, data, u_header = nil )
-: post( path, data, u_header = nil ) {|str| .... }
- posts "data" to "path" entity and gets document.
- returns HTTPResponse object.
+ HTTPVersion = '1.1'
-=end
+ #
+ # connection
+ #
-require 'net/protocol'
+ protocol_param :port, '80'
-module Net
+ def initialize( addr = nil, port = nil )
+ super
- class HTTPBadResponse < StandardError; end
+ @proxy_address = nil
+ @proxy_port = nil
+ @curr_http_version = HTTPVersion
+ @seems_1_0_server = false
+ end
- class HTTP < Protocol
- protocol_param :port, '80'
- protocol_param :command_type, '::Net::NetPrivate::HTTPCommand'
+ private
+ def conn_command( sock )
+ end
+
+ def do_finish
+ end
+
+
+ #
+ # proxy
+ #
+
+ public
- ###
- ### proxy
- ###
class << self
def Proxy( p_addr, p_port = nil )
- ::Net::NetPrivate::HTTPProxy.create_proxy_class(
- p_addr, p_port || self.port )
+ ProxyMod.create_proxy_class( p_addr, p_port || self.port )
end
alias orig_new new
@@ -293,7 +323,7 @@ module Net
def new( address = nil, port = nil, p_addr = nil, p_port = nil )
c = p_addr ? self::Proxy(p_addr, p_port) : self
i = c.orig_new( address, port )
- setimplv i
+ setvar i
i
end
@@ -332,385 +362,230 @@ module Net
end
- ###
- ### 1.2 implementation
- ###
+ module ProxyMod
- @@newimpl = false
+ class << self
- #class << self
+ def create_proxy_class( p_addr, p_port )
+ mod = self
+ klass = Class.new( HTTP )
+ klass.module_eval {
+ include mod
+ @proxy_address = p_addr
+ @proxy_port = p_port
+ }
+ def klass.proxy_class?
+ true
+ end
- def self.version_1_2
- @@newimpl = true
- end
+ def klass.proxy_address
+ @proxy_address
+ end
- def self.version_1_1
- @@newimpl = false
- end
+ def klass.proxy_port
+ @proxy_port
+ end
- #private
+ klass
+ end
- def self.setimplv( obj )
- f = @@newimpl
- obj.instance_eval { @newimpl = f }
end
- #end
-
-
- ###
- ### http operations
- ###
-
- def get( path, u_header = nil, dest = nil, &block )
- resp = get2( path, u_header ) {|f| f.body( dest, &block ) }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+ def initialize( addr, port )
+ super
+ @proxy_address = type.proxy_address
+ @proxy_port = type.proxy_port
end
- end
-
- def get2( path, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.get edit_path(path), uh
- }
- end
+
+ attr_reader :proxy_address, :proxy_port
+ alias proxyaddr proxy_address
+ alias proxyport proxy_port
- def head( path, u_header = nil )
- resp = head2( path, u_header )
- unless @newimpl then
- resp.value
+ def proxy?
+ true
end
- resp
- end
-
- def head2( path, u_header = nil, &block )
- common_oper( u_header, false, block ) {|uh|
- @command.head edit_path(path), uh
- }
- end
-
-
- def post( path, data, u_header = nil, dest = nil, &block )
- resp = post2( path, data, u_header ) {|f| f.body( dest, &block ) }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+
+ private
+
+ def conn_socket( addr, port )
+ super @proxy_address, @proxy_port
end
- end
-
- def post2( path, data, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.post edit_path(path), uh, data
- }
- end
-
- # not tested because I could not setup apache (__;;;
- def put( path, src, u_header = nil )
- resp = put2( path, src, u_header ) {|f| f.body }
- if @newimpl then
- resp
- else
- resp.value
- return resp, resp.body
+ def edit_path( path )
+ 'http://' + addr_port + path
end
- end
+
+ end # module ProxyMod
- def put2( path, src, u_header = nil, &block )
- common_oper( u_header, true, block ) {|uh|
- @command.put path, uh, src
- }
- end
-
-
- private
-
-
- def common_oper( u_header, body_exist, block )
- header = procheader( u_header )
- recv = err = nil
-
- connecting( header ) {
- recv = HTTPResponseReceiver.new( @command, body_exist )
- yield header
- begin
- block.call recv if block
- rescue Exception => err
- ;
- end
- recv.terminate
-
- recv.response
- }
- raise err if err
- recv.response
- end
+ #
+ # for backward compatibility
+ #
- def connecting( header )
- if not @socket then
- header['Connection'] = 'close'
- start
- elsif @socket.closed? then
- @socket.reopen
- end
+ @@newimpl = false
- resp = yield
+ class << self
- unless keep_alive? header, resp then
- @socket.close
+ def version_1_2
+ @@newimpl = true
end
- end
- def keep_alive?( header, resp )
- if resp.key? 'connection' then
- if /keep-alive/i === resp['connection'] then
- return true
- end
- elsif resp.key? 'proxy-connection' then
- if /keep-alive/i === resp['proxy-connection'] then
- return true
- end
- elsif header.key? 'Connection' then
- if /keep-alive/i === header['Connection'] then
- return true
- end
- else
- if @command.http_version == '1.1' then
- return true
- end
+ def version_1_1
+ @@newimpl = false
end
- false
- end
-
- def procheader( h )
- ret = {}
- ret[ 'Host' ] = address +
- ((port == HTTP.port) ? '' : ":#{port}")
- ret[ 'Connection' ] = 'Keep-Alive'
- ret[ 'Accept' ] = '*/*'
+ private
- return ret unless h
- tmp = {}
- h.each do |k,v|
- key = k.split('-').collect {|i| i.capitalize }.join('-')
- if tmp[key] then
- $stderr.puts "'#{key}' http header appered twice" if $VERBOSE
- end
- tmp[key] = v
+ def setvar( obj )
+ f = @@newimpl
+ obj.instance_eval { @newimpl = f }
end
- ret.update tmp
- ret
end
- def do_finish
- end
+ #
+ # http operations
+ #
- end
-
- HTTPSession = HTTP
-
-
- module NetPrivate
-
- module HTTPProxy
-
- class << self
-
- def create_proxy_class( p_addr, p_port )
- klass = Class.new( HTTP )
- klass.module_eval {
- include HTTPProxy
- @proxy_address = p_addr
- @proxy_port = p_port
- }
- def klass.proxy_class?
- true
- end
+ public
- def klass.proxy_address
- @proxy_address
+ def self.def_http_method( nm, hasdest, hasdata )
+ name = nm.id2name.downcase
+ cname = nm.id2name
+ lineno = __LINE__ + 2
+ src = <<" ----"
+
+ def #{name}( path, #{hasdata ? 'data,' : ''}
+ u_header = nil #{hasdest ? ',dest = nil, &block' : ''} )
+ resp = nil
+ request(
+ #{cname}.new( path, u_header ) #{hasdata ? ',data' : ''}
+ ) do |resp|
+ resp.read_body( #{hasdest ? 'dest, &block' : ''} )
+ end
+ if @newimpl then
+ resp
+ else
+ resp.value
+ #{hasdest ? 'return resp, resp.body' : 'resp'}
+ end
end
- def klass.proxy_port
- @proxy_port
+ def #{name}2( path, #{hasdata ? 'data,' : ''}
+ u_header = nil, &block )
+ request( #{cname}.new(path, u_header),
+ #{hasdata ? 'data,' : ''} &block )
end
-
- klass
- end
-
- end
-
-
- def initialize( addr, port )
- super
- @proxy_address = type.proxy_address
- @proxy_port = type.proxy_port
+ ----
+ module_eval src, __FILE__, lineno
end
- attr_reader :proxy_address, :proxy_port
+ def_http_method :Get, true, false
+ def_http_method :Head, false, false
+ def_http_method :Post, true, true
+ def_http_method :Put, false, true
- alias proxyaddr proxy_address
- alias proxyport proxy_port
-
- def proxy?
- true
- end
-
- def connect( addr = nil, port = nil )
- super @proxy_address, @proxy_port
- end
-
- def edit_path( path )
- 'http://' + address + (port == type.port ? '' : ":#{port}") + path
+ def request( req, *args )
+ common_oper( req ) {
+ req.__send__( :exec,
+ @socket, @curr_http_version, edit_path(req.path), *args )
+ yield req.response if block_given?
+ }
+ req.response
end
-
- end
-
- end # net private
+ private
- class HTTPResponseReceiver
-
- def initialize( command, body_exist )
- @command = command
- @body_exist = body_exist
- @header = @body = nil
- end
-
- def inspect
- "#<#{type}>"
- end
- def read_header
- unless @header then
- stream_check
- @header = @command.get_response
+ def common_oper( req )
+ req['connection'] ||= 'keep-alive'
+ if not @socket then
+ start
+ req['connection'] = 'close'
+ elsif @socket.closed? then
+ re_connect
end
- @header
- end
-
- alias header read_header
- alias response read_header
-
- def read_body( dest = nil, &block )
- unless @body then
- read_header
-
- to = procdest( dest, block )
- stream_check
-
- if @body_exist and @header.code_type.body_exist? then
- @command.get_body @header, to
- @header.body = @body = to
- else
- @command.no_body
- @header.body = nil
- @body = 1
- end
+ if not req.body_exist? or @seems_1_0_server then
+ req['connection'] = 'close'
end
- @body == 1 ? nil : @body
- end
-
- alias body read_body
- alias entity read_body
+ req['host'] = addr_port
- def terminate
- read_header
- read_body
- @command = nil
- end
+ yield req
+ req.response.__send__ :terminate
+ @curr_http_version = req.response.http_version
-
- private
-
- def stream_check
- unless @command then
- raise IOError, 'receiver was used out of block'
- end
- end
-
- def procdest( dest, block )
- if dest and block then
- raise ArgumentError,
- 'both of arg and block are given for HTTP method'
- end
- if block then
- NetPrivate::ReadAdapter.new block
+ if not req.response.body then
+ @socket.close
+ elsif keep_alive? req, req.response then
+ D 'Conn keep-alive'
+ if @socket.closed? then # (only) read stream had been closed
+ D 'Conn (but seems 1.0 server)'
+ @seems_1_0_server = true
+ @socket.close
+ end
else
- dest or ''
+ D 'Conn close'
+ @socket.close
end
- end
-
- end
-
- HTTPReadAdapter = HTTPResponseReceiver
-
- class HTTPResponse < Response
-
- def initialize( code_type, code, msg )
- super
- @data = {}
- @body = nil
+ req.response
end
- attr_accessor :body
+ def keep_alive?( req, res )
+ /close/i === req['connection'].to_s and return false
+ @seems_1_0_server and return false
- def inspect
- "#<#{type.name} #{code}>"
- end
+ /keep-alive/i === res['connection'].to_s and return true
+ /close/i === res['connection'].to_s and return false
+ /keep-alive/i === res['proxy-connection'].to_s and return true
+ /close/i === res['proxy-connection'].to_s and return false
- def []( key )
- @data[ key.downcase ]
+ @curr_http_version == '1.1' and return true
+ false
end
- def []=( key, val )
- @data[ key.downcase ] = val
- end
- def each( &block )
- @data.each( &block )
- end
+ #
+ # utils
+ #
- def each_key( &block )
- @data.each_key( &block )
- end
+ public
- def each_value( &block )
- @data.each_value( &block )
+ def self.get( addr, path, port = nil )
+ req = Get.new( path )
+ resp = nil
+ new( addr, port || HTTP.port ).start {|http|
+ resp = http.request( req )
+ }
+ resp.body
end
- def delete( key )
- @data.delete key.downcase
+ def self.get_print( addr, path, port = nil )
+ print get( addr, path, port )
end
- def key?( key )
- @data.key? key.downcase
- end
- def to_hash
- @data.dup
+ private
+
+ def addr_port
+ address + (port == HTTP.port ? '' : ":#{port}")
end
- def value
- unless SuccessCode === self then
- error! self
+ def D( msg )
+ if @dout then
+ @dout << msg
+ @dout << "\n"
end
end
end
+ HTTPSession = HTTP
+
+
class Code
@@ -776,101 +651,246 @@ module Net
HTTPVersionNotSupported = HTTPServerErrorCode.http_mkchild
- module NetPrivate
+ ###
+ ### header
+ ###
- class HTTPCommand < Command
+ net_private {
- HTTPVersion = '1.1'
+ module HTTPHeader
- def initialize( sock )
- @http_version = HTTPVersion
- super sock
+ def size
+ @header.size
end
- attr_reader :http_version
+ alias length size
- def inspect
- "#<Net::HTTPCommand>"
+ def []( key )
+ @header[ key.downcase ]
end
+ def []=( key, val )
+ @header[ key.downcase ] = val
+ end
- ###
- ### request
- ###
+ def each( &block )
+ @header.each( &block )
+ end
- public
+ def each_key( &block )
+ @header.each_key( &block )
+ end
- def get( path, u_header )
- return unless begin_critical
- request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
+ def each_value( &block )
+ @header.each_value( &block )
end
-
- def head( path, u_header )
- return unless begin_critical
- request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
+
+ def delete( key )
+ @header.delete key.downcase
+ end
+
+ def key?( key )
+ @header.key? key.downcase
+ end
+
+ def to_hash
+ @header.dup
end
- def post( path, u_header, data )
- return unless begin_critical
- u_header[ 'Content-Length' ] = data.size.to_s
- request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
- @socket.write data
+ def canonical_each
+ @header.each do |k,v|
+ yield canonical(k), v
+ end
end
- def put( path, u_header, src )
- return unless begin_critical
- request sprintf('PUT %s HTTP/%s', path, HTTPVersion), u_header
- @socket.write_bin src
+ def canonical( k )
+ k.split('-').collect {|i| i.capitalize }.join('-')
end
- # def delete
+ def range
+ s = @header['range']
+ s or return nil
- # def trace
+ arr = []
+ s.split(',').each do |spec|
+ m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match( spec )
+ m or raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
- # def options
+ d1 = m[1].to_i
+ d2 = m[2].to_i
+ if m[1] and m[2] then arr.push (d1 .. d2)
+ elsif m[1] then arr.push (d1 .. -1)
+ elsif m[2] then arr.push (-d2 .. -1)
+ else
+ raise HTTPHeaderSyntaxError, 'range is not specified'
+ end
+ end
- def quit
+ return *arr
end
+ def range=( r, fin = nil )
+ if fin then
+ r = r ... r+fin
+ end
- private
+ case r
+ when Numeric
+ s = r > 0 ? "0-#{r - 1}" : "-#{-r}"
+ when Range
+ first = r.first
+ last = r.last
+ if r.exclude_end? then
+ last -= 1
+ end
- def request( req, u_header )
- @socket.writeline req
- u_header.each do |n,v|
- @socket.writeline n + ': ' + v
+ if last == -1 then
+ s = first > 0 ? "#{first}-" : "-#{-first}"
+ else
+ first >= 0 or raise HTTPHeaderSyntaxError, 'range.first is negative'
+ last > 0 or raise HTTPHeaderSyntaxError, 'range.last is negative'
+ first < last or raise HTTPHeaderSyntaxError, 'must be .first < .last'
+ s = "#{first}-#{last}"
+ end
+ else
+ raise TypeError, 'Range/Integer is required'
end
- @socket.writeline ''
+
+ @header['range'] = "bytes=#{s}"
+ r
end
+ alias set_range range=
- ###
- ### response line & header
- ###
+ def content_length
+ s = @header['content-length']
+ s or return nil
- public
+ m = /\d+/.match(s)
+ m or raise HTTPHeaderSyntaxError, 'wrong Content-Length format'
+ m[0].to_i
+ end
- def get_response
- resp = get_resp0
- resp = get_resp0 while ContinueCode === resp
- resp
+ def chunked?
+ s = @header['transfer-encoding']
+ (s and /(?:\A|[^\-\w])chunked(?:[^\-\w]|\z)/i === s) ? true : false
+ end
+
+ def content_range
+ s = @header['content-range']
+ s or return nil
+
+ m = %r<bytes\s+(\d+)-(\d+)/(?:\d+|\*)>i.match( s )
+ m or raise HTTPHeaderSyntaxError, 'wrong Content-Range format'
+
+ m[1].to_i .. m[2].to_i + 1
+ end
+
+ def range_length
+ r = content_range
+ r and r.length
+ end
+
+ def basic_auth( acc, pass )
+ @header['authorization'] =
+ 'Basic ' + ["#{acc}:#{pass}"].pack('m').gsub(/\s+/, '')
+ end
+
+ end
+
+ }
+
+
+ ###
+ ### request
+ ###
+
+ net_private {
+
+ class HTTPRequest
+
+ include ::Net::NetPrivate::HTTPHeader
+
+ def initialize( path, uhead = nil )
+ @path = path
+ @header = tmp = {}
+ return unless uhead
+ uhead.each do |k,v|
+ key = k.downcase
+ if tmp.key? key then
+ $stderr.puts "WARNING: duplicated HTTP header: #{k}" if $VERBOSE
+ end
+ tmp[ key ] = v.strip
+ end
+ tmp['accept'] ||= '*/*'
+
+ @socket = nil
+ @response = nil
+ end
+
+ attr_reader :path
+ attr_reader :response
+
+ def inspect
+ "\#<#{type}>"
+ end
+
+ def body_exist?
+ type::HAS_BODY
end
private
- def get_resp0
- resp = get_reply
+ #
+ # write
+ #
+
+ def exec( sock, ver, path )
+ ready( sock ) {
+ request ver, path
+ }
+ @response
+ end
+
+ def ready( sock )
+ @response = nil
+ @socket = sock
+ yield
+ @response = get_response
+ @socket = nil
+ end
+
+ def request( ver, path )
+ @socket.writeline sprintf('%s %s HTTP/%s', type::METHOD, path, ver)
+ canonical_each do |k,v|
+ @socket.writeline k + ': ' + v
+ end
+ @socket.writeline ''
+ end
+
+ #
+ # read
+ #
+
+ def get_response
+ begin
+ resp = read_response
+ end while ContinueCode === resp
+ resp
+ end
+
+ def read_response
+ resp = get_resline
while true do
- line = @socket.readline
+ line = @socket.readuntil( "\n", true ) # ignore EOF
+ line.sub!( /\s+\z/, '' ) # don't use chop!
break if line.empty?
m = /\A([^:]+):\s*/.match( line )
- unless m then
- raise HTTPBadResponse, 'wrong header line format'
- end
+ m or raise HTTPBadResponse, 'wrong header line format'
nm = m[1]
line = m.post_match
if resp.key? nm then
@@ -883,23 +903,117 @@ module Net
resp
end
- def get_reply
+ def get_resline
str = @socket.readline
- m = /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i.match( str )
- unless m then
- raise HTTPBadResponse, "wrong status line: #{str}"
- end
- @http_version = m[1]
+ m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/i.match( str )
+ m or raise HTTPBadResponse, "wrong status line: #{str}"
+ httpver = m[1]
status = m[2]
discrip = m[3]
- code = HTTPCODE_TO_OBJ[status] ||
- HTTPCODE_CLASS_TO_OBJ[status[0,1]] ||
- UnknownCode
- HTTPResponse.new( code, status, discrip )
+ ::Net::NetPrivate::HTTPResponse.new(
+ status, discrip, @socket, type::HAS_BODY, httpver )
+ end
+
+ end
+
+
+ class HTTPRequestWithBody < HTTPRequest
+
+ private
+
+ def exec( sock, ver, path, str = nil )
+ check_arg str, block_given?
+
+ if block_given? then
+ ac = Accumulator.new
+ yield ac # must be yield, DO NOT USE block.call
+ data = ac.terminate
+ else
+ data = str
+ end
+ @header['content-length'] = data.size.to_s
+ @header.delete 'transfer-encoding'
+
+ ready( sock ) {
+ request ver, path
+ @socket.write data
+ }
+ @response
+ end
+
+ def check_arg( data, blkp )
+ if data and blkp then
+ raise ArgumentError, 'both of data and block given'
+ end
+ unless data or blkp then
+ raise ArgumentError, 'str or block required'
+ end
+ end
+
+ end
+
+
+ class Accumulator
+
+ def initialize
+ @buf = ''
+ end
+
+ def write( s )
+ @buf.concat s
+ end
+
+ alias << write
+
+ def terminate
+ ret = @buf
+ @buf = nil
+ ret
+ end
+
+ end
+
+ }
+
+
+ class HTTP
+
+ class Get < ::Net::NetPrivate::HTTPRequest
+ HAS_BODY = true
+ METHOD = 'GET'
+ end
+
+ class Head < ::Net::NetPrivate::HTTPRequest
+ HAS_BODY = false
+ METHOD = 'HEAD'
+ end
+
+ class Post < ::Net::NetPrivate::HTTPRequestWithBody
+ HAS_BODY = true
+ METHOD = 'POST'
+ end
+
+ class Put < ::Net::NetPrivate::HTTPRequestWithBody
+ HAS_BODY = true
+ METHOD = 'PUT'
end
- HTTPCODE_CLASS_TO_OBJ = {
+ end
+
+
+
+ ###
+ ### response
+ ###
+
+ net_private {
+
+ class HTTPResponse < Response
+
+ include ::Net::NetPrivate::HTTPHeader
+
+ CODE_CLASS_TO_OBJ = {
'1' => HTTPInformationCode,
'2' => HTTPSuccessCode,
'3' => HTTPRedirectionCode,
@@ -907,7 +1021,7 @@ module Net
'5' => HTTPServerErrorCode
}
- HTTPCODE_TO_OBJ = {
+ CODE_TO_OBJ = {
'100' => ContinueCode,
'101' => HTTPSwitchProtocol,
@@ -951,22 +1065,87 @@ module Net
'505' => HTTPVersionNotSupported
}
+ def initialize( stat, msg, sock, be, hv )
+ code = CODE_TO_OBJ[stat] ||
+ CODE_CLASS_TO_OBJ[stat[0,1]] ||
+ UnknownCode
+ super code, stat, msg
+ @socket = sock
+ @body_exist = be
+ @http_version = hv
- ###
- ### body
- ###
+ @header = {}
+ @body = nil
+ @read = false
+ end
- public
+ attr_reader :http_version
+
+ def inspect
+ "#<#{type} #{code}>"
+ end
+
+ def value
+ SuccessCode === self or error! self
+ end
- def get_body( resp, dest )
- if chunked? resp then
+
+ #
+ # header (for backward compatibility)
+ #
+
+ def read_header
+ self
+ end
+
+ alias header read_header
+ alias response read_header
+
+ #
+ # body
+ #
+
+ def read_body( dest = nil, &block )
+ if @read and (dest or block) then
+ raise IOError, "#{type}\#read_body called twice with argument"
+ end
+
+ unless @read then
+ to = procdest( dest, block )
+ stream_check
+
+ if @body_exist and code_type.body_exist? then
+ read_body_0 to
+ @body = to
+ else
+ @body = nil
+ end
+ @read = true
+ end
+
+ @body
+ end
+
+ alias body read_body
+ alias entity read_body
+
+
+ private
+
+
+ def terminate
+ read_body
+ end
+
+ def read_body_0( dest )
+ if chunked? then
read_chunked dest
else
- clen = content_length( resp )
+ clen = content_length
if clen then
- @socket.read clen, dest
+ @socket.read clen, dest, true # ignore EOF
else
- clen = range_length( resp )
+ clen = range_length
if clen then
@socket.read clen, dest
else
@@ -974,16 +1153,8 @@ module Net
end
end
end
- end_critical
- end
-
- def no_body
- end_critical
end
-
- private
-
def read_chunked( dest )
len = nil
total = 0
@@ -991,9 +1162,7 @@ module Net
while true do
line = @socket.readline
m = /[0-9a-fA-F]+/.match( line )
- unless m then
- raise HTTPBadResponse, "wrong chunk size line: #{line}"
- end
+ m or raise HTTPBadResponse, "wrong chunk size line: #{line}"
len = m[0].hex
break if len == 0
@socket.read( len, dest ); total += len
@@ -1004,44 +1173,27 @@ module Net
end
end
- def content_length( resp )
- if resp.key? 'content-length' then
- m = /\d+/.match( resp['content-length'] )
- unless m then
- raise HTTPBadResponse, 'wrong Content-Length format'
- end
- m[0].to_i
- else
- nil
- end
+ def stream_check
+ @socket.closed? and raise IOError, 'try to read body out of block'
end
- def chunked?( resp )
- tmp = resp['transfer-encoding']
- tmp and /(?:\A|\s+)chunked(?:\s+|\z)/i === tmp
- end
-
- def range_length( resp )
- if resp.key? 'content-range' then
- m = %r<bytes\s+(\d+)-(\d+)/\d+>.match( resp['content-range'] )
- unless m then
- raise HTTPBadResponse, 'wrong Content-Range format'
- end
- l = m[2].to_i
- u = m[1].to_i
- if l > u then
- nil
- else
- u - l
- end
+ def procdest( dest, block )
+ if dest and block then
+ raise ArgumentError, 'both of arg and block are given for HTTP method'
+ end
+ if block then
+ ::Net::NetPrivate::ReadAdapter.new block
else
- nil
+ dest || ''
end
end
end
+ }
+
- end # module Net::NetPrivate
+ HTTPResponse = NetPrivate::HTTPResponse
+ HTTPResponseReceiver = NetPrivate::HTTPResponse
end # module Net
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 34d324ed12..23b22c0282 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -1475,6 +1475,12 @@ module Net
when /\A(?:UIDVALIDITY|UIDNEXT|UNSEEN)\z/n
match(T_SPACE)
result = ResponseCode.new(name, number)
+ else
+ match(T_SPACE)
+ @lex_state = EXPR_CTEXT
+ token = match(T_TEXT)
+ @lex_state = EXPR_BEG
+ result = ResponseCode.new(name, token.value)
end
match(T_RBRA)
@lex_state = EXPR_RTEXT
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 4f6eb930a4..8f3f978e8c 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -1,6 +1,6 @@
=begin
-= net/pop.rb version 1.1.32
+= net/pop.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -184,6 +184,7 @@ module Net
protocol_param :port, '110'
protocol_param :command_type, '::Net::NetPrivate::POP3Command'
+ protocol_param :apop_command_type, '::Net::NetPrivate::APOPCommand'
protocol_param :mail_type, '::Net::POPMail'
@@ -206,9 +207,10 @@ module Net
end
- def initialize( addr = nil, port = nil )
- super
+ def initialize( addr = nil, port = nil, apop = false )
+ super addr, port
@mails = nil
+ @apop = false
end
attr :mails
@@ -238,6 +240,11 @@ module Net
private
+ def conn_command( sock )
+ @command =
+ (@apop ? type.apop_command_type : type.command_type).new(sock)
+ end
+
def do_start( acnt, pwd )
@command.auth( acnt, pwd )
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index 161024cfe2..343721add3 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -1,6 +1,6 @@
=begin
-= net/protocol.rb version 1.1.32
+= net/protocol.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -59,13 +59,22 @@ Object
=end
require 'socket'
+require 'timeout'
module Net
+ module NetPrivate
+ end
+
+ def self.net_private( &block )
+ ::Net::NetPrivate.module_eval( &block )
+ end
+
+
class Protocol
- Version = '1.1.32'
+ Version = '1.1.34'
class << self
@@ -116,8 +125,12 @@ module Net
@command = nil
@socket = nil
- @active = false
- @pipe = nil
+ @active = false
+
+ @open_timeout = nil
+ @read_timeout = nil
+
+ @dout = nil
end
attr_reader :address
@@ -126,10 +139,26 @@ module Net
attr_reader :command
attr_reader :socket
+ attr_accessor :open_timeout
+ attr_accessor :read_timeout
+
+ def active?
+ @active
+ end
+
+ def set_debug_output( arg ) # un-documented
+ @dout = arg
+ end
+
+ alias set_pipe set_debug_output
+
def inspect
"#<#{type} #{address}:#{port} open=#{active?}>"
end
+ #
+ # open session
+ #
def start( *args )
return false if active?
@@ -146,45 +175,59 @@ module Net
end
end
+ private
+
def _start( args )
connect
do_start( *args )
@active = true
end
- private :_start
-
- def finish
- return false unless active?
- do_finish unless @command.critical?
- disconnect
- @active = false
- true
+ def connect
+ conn_socket @address, @port
+ conn_command @socket
+ on_connect
end
- def active?
- @active
+ def re_connect
+ @socket.reopen @open_timeout
+ on_connect
end
- def set_pipe( arg ) # un-documented
- @pipe = arg
+ def conn_socket( addr, port )
+ @socket = type.socket_type.open(
+ addr, port, @open_timeout, @read_timeout, @dout )
end
+ def conn_command( sock )
+ @command = type.command_type.new( sock )
+ end
- private
-
+ def on_connect
+ end
def do_start
end
- def do_finish
- @command.quit
+ #
+ # close session
+ #
+
+ public
+
+ def finish
+ return false unless active?
+
+ do_finish if @command and not @command.critical?
+ disconnect
+ @active = false
+ true
end
+ private
- def connect( addr = @address, port = @port )
- @socket = type.socket_type.open( addr, port, @pipe )
- @command = type.command_type.new( @socket )
+ def do_finish
+ @command.quit
end
def disconnect
@@ -192,7 +235,11 @@ module Net
if @socket and not @socket.closed? then
@socket.close
end
- @socket = nil
+ @socket = nil
+ on_disconnect
+ end
+
+ def on_disconnect
end
end
@@ -200,6 +247,7 @@ module Net
Session = Protocol
+ net_private {
class Response
@@ -223,6 +271,8 @@ module Net
end
+ }
+
class ProtocolError < StandardError; end
class ProtoSyntaxError < ProtocolError; end
@@ -294,8 +344,7 @@ module Net
- module NetPrivate
-
+ net_private {
class WriteAdapter
@@ -311,7 +360,11 @@ module Net
def write( str )
@sock.__send__ @mid, str
end
- alias << write
+
+ def <<( str )
+ @sock.__send__ @mid, str
+ self
+ end
end
@@ -407,6 +460,7 @@ module Net
@critical = false
end
+
private
def critical
@@ -431,22 +485,30 @@ module Net
class Socket
- def initialize( addr, port, pipe = nil )
+ def initialize( addr, port, otime = nil, rtime = nil, dout = nil )
@addr = addr
@port = port
- @pipe = pipe
- @prepipe = nil
- @closed = true
- @ipaddr = ''
+ @read_timeout = rtime
+
+ @debugout = dout
+
+ @socket = nil
@sending = ''
@buffer = ''
- @socket = TCPsocket.new( addr, port )
- @closed = false
- @ipaddr = @socket.addr[3]
+ connect otime
+ D 'opened'
end
+ def connect( otime )
+ D "opening connection to #{@addr}..."
+ timeout( otime ) {
+ @socket = TCPsocket.new( @addr, @port )
+ }
+ end
+ private :connect
+
attr :pipe, true
class << self
@@ -454,27 +516,31 @@ module Net
end
def inspect
- "#<#{type} open=#{!@closed}>"
+ "#<#{type} #{closed? ? 'closed' : 'opened'}>"
end
- def reopen
- unless closed? then
- close
- @buffer = ''
- end
- @socket = TCPsocket.new( @addr, @port )
- @closed = false
+ def reopen( otime = nil )
+ D 'reopening...'
+ close
+ connect otime
+ D 'reopened'
end
attr :socket, true
def close
- @socket.close
- @closed = true
+ if @socket then
+ @socket.close
+ D 'closed'
+ else
+ D 'close call for already closed socket'
+ end
+ @socket = nil
+ @buffer = ''
end
def closed?
- @closed
+ not @socket
end
def address
@@ -486,7 +552,8 @@ module Net
attr_reader :port
def ip_address
- @ipaddr.dup
+ @socket or return ''
+ @socket.addr[3]
end
alias ipaddr ip_address
@@ -494,57 +561,64 @@ module Net
attr_reader :sending
- ###
- ### read
- ###
+ #
+ # read
+ #
+
+ public
CRLF = "\r\n"
- def read( len, dest = '' )
- @pipe << "reading #{len} bytes...\n" if @pipe; pipeoff
+ def read( len, dest = '', ignerr = false )
+ D_off "reading #{len} bytes..."
rsize = 0
- while rsize + @buffer.size < len do
- rsize += writeinto( dest, @buffer.size )
- fill_rbuf
+ begin
+ while rsize + @buffer.size < len do
+ rsize += rbuf_moveto( dest, @buffer.size )
+ rbuf_fill
+ end
+ rbuf_moveto dest, len - rsize
+ rescue EOFError
+ raise unless igneof
end
- writeinto( dest, len - rsize )
- @pipe << "read #{len} bytes\n" if pipeon
+ D_on "read #{len} bytes"
dest
end
-
def read_all( dest = '' )
- @pipe << "reading all...\n" if @pipe; pipeoff
+ D_off 'reading all...'
rsize = 0
begin
while true do
- rsize += writeinto( dest, @buffer.size )
- fill_rbuf
+ rsize += rbuf_moveto( dest, @buffer.size )
+ rbuf_fill
end
rescue EOFError
;
end
- @pipe << "read #{rsize} bytes\n" if pipeon
+ D_on "read #{rsize} bytes"
dest
end
-
- def readuntil( target )
- while true do
- idx = @buffer.index( target )
- break if idx
- fill_rbuf
- end
-
+ def readuntil( target, igneof = false )
dest = ''
- writeinto( dest, idx + target.size )
+ begin
+ while true do
+ idx = @buffer.index( target )
+ break if idx
+ rbuf_fill
+ end
+ rbuf_moveto dest, idx + target.size
+ rescue EOFError
+ raise unless igneof
+ rbuf_moveto dest, @buffer.size
+ end
dest
end
-
def readline
ret = readuntil( "\n" )
@@ -552,9 +626,8 @@ module Net
ret
end
-
def read_pendstr( dest )
- @pipe << "reading text...\n" if @pipe; pipeoff
+ D_off 'reading text...'
rsize = 0
while (str = readuntil("\r\n")) != ".\r\n" do
@@ -563,14 +636,13 @@ module Net
dest << str
end
- @pipe << "read #{rsize} bytes\n" if pipeon
+ D_on "read #{rsize} bytes"
dest
end
-
# private use only (can not handle 'break')
def read_pendlist
- @pipe << "reading list...\n" if @pipe; pipeoff
+ D_off 'reading list...'
str = nil
i = 0
@@ -580,55 +652,59 @@ module Net
yield str
end
- @pipe << "read #{i} items\n" if pipeon
+ D_on "read #{i} items"
end
private
- READ_BLOCK = 1024 * 8
+ READ_SIZE = 1024 * 4
- def fill_rbuf
- @buffer << @socket.sysread( READ_BLOCK )
+ def rbuf_fill
+ unless IO.select [@socket], nil, nil, @read_timeout then
+ on_read_timeout
+ end
+ @buffer << @socket.sysread( READ_SIZE )
end
- def writeinto( dest, len )
+ def on_read_timeout
+ raise TimeoutError, "socket read timeout (#{@read_timeout} sec)"
+ end
+
+ def rbuf_moveto( dest, len )
bsi = @buffer.size
- dest << @buffer[ 0, len ]
+ s = @buffer[ 0, len ]
+ dest << s
@buffer = @buffer[ len, bsi - len ]
- @pipe << %{read "#{Net.quote dest}"\n} if @pipe
+ @debugout << %<read "#{Net.quote s}"\n> if @debugout
len
end
- ###
- ### write
- ###
+ #
+ # write interfece
+ #
public
-
def write( str )
writing {
do_write str
}
end
-
def writeline( str )
writing {
- do_write str
- do_write "\r\n"
+ do_write str + "\r\n"
}
end
-
def write_bin( src, block )
writing {
if block then
- block.call WriteAdapter.new( self, :do_write )
+ block.call ::Net::NetPrivate::WriteAdapter.new( self, :do_write )
else
src.each do |bin|
do_write bin
@@ -637,19 +713,18 @@ module Net
}
end
-
def write_pendstr( src, block )
- @pipe << "writing text from #{src.type}\n" if @pipe; pipeoff
+ D_off "writing text from #{src.type}"
wsize = use_each_crlf_line {
if block then
- block.call WriteAdapter.new( self, :wpend_in )
+ block.call ::Net::NetPrivate::WriteAdapter.new( self, :wpend_in )
else
wpend_in src
end
}
- @pipe << "wrote #{wsize} bytes text\n" if pipeon
+ D_on "wrote #{wsize} bytes text"
wsize
end
@@ -696,17 +771,17 @@ module Net
beg = 0
buf = @wbuf
while buf.index( /\n|\r\n|\r/, beg ) do
- m = $~
+ m = Regexp.last_match
if m.begin(0) == buf.size - 1 and buf[-1] == ?\r then
# "...\r" : can follow "\n..."
break
end
- str = buf[ beg, m.begin(0) - beg ]
+ str = buf[ beg ... m.begin(0) ]
str.concat "\r\n"
yield str
beg = m.end(0)
end
- @wbuf = buf[ beg, buf.size - beg ]
+ @wbuf = buf[ beg ... buf.size ]
end
end
@@ -736,6 +811,7 @@ module Net
yield
end
end
+ yield unless @wbuf.empty?
end
end
@@ -746,17 +822,17 @@ module Net
yield
- if @pipe then
- @pipe << 'write "'
- @pipe << @sending
- @pipe << "\"\n"
+ if @debugout then
+ @debugout << 'write "'
+ @debugout << @sending
+ @debugout << "\"\n"
end
@socket.flush
@writtensize
end
def do_write( arg )
- if @pipe or @sending.size < 128 then
+ if @debugout or @sending.size < 128 then
@sending << Net.quote( arg )
else
@sending << '...' unless @sending[-1] == ?.
@@ -768,22 +844,25 @@ module Net
end
- def pipeoff
- @prepipe = @pipe
- @pipe = nil
- @prepipe
+ def D_off( msg )
+ D msg
+ @savedo, @debugout = @debugout, nil
end
- def pipeon
- @pipe = @prepipe
- @prepipe = nil
- @pipe
+ def D_on( msg )
+ @debugout = @savedo
+ D msg
end
- end
+ def D( msg )
+ @debugout or return
+ @debugout << msg
+ @debugout << "\n"
+ end
+ end
- end # module Net::NetPrivate
+ }
def Net.quote( str )
diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb
index 9679984e2c..befc1adf03 100644
--- a/lib/net/smtp.rb
+++ b/lib/net/smtp.rb
@@ -1,6 +1,6 @@
=begin
-= net/smtp.rb version 1.1.32
+= net/smtp.rb version 1.1.34
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
@@ -30,10 +30,8 @@ Net::Protocol
=== Methods
-: start( helo_domain = Socket.gethostname, \
- account = nil, password = nil, authtype = nil )
-: start( helo_domain = Socket.gethostname, \
- account = nil, password = nil, authtype = nil ) {|smtp| .... }
+: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil )
+: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil ) {|smtp| .... }
opens TCP connection and starts SMTP session.
If protocol had been started, do nothing and return false.
@@ -53,10 +51,10 @@ Net::Protocol
to_addrs must be a String(s) or an Array of String.
Exceptions which SMTP raises are:
- * Net::ProtoSyntaxError: syntax error (errno.500)
- * Net::ProtoFatalError: fatal error (errno.550)
- * Net::ProtoUnknownError: unknown error
- * Net::ProtoServerBusy: temporary error (errno.420/450)
+ * Net::ProtoSyntaxError: syntax error (errno.500)
+ * Net::ProtoFatalError: fatal error (errno.550)
+ * Net::ProtoUnknownError: unknown error
+ * Net::ProtoServerBusy: temporary error (errno.420/450)
# usage example
@@ -153,12 +151,15 @@ module Net
end
end
- if user and secret then
+ if user or secret then
+ (user and secret) or
+ raise ArgumentError, 'both of account and password are required'
+
mid = 'auth_' + (authtype || 'cram_md5').to_s
- unless @command.respond_to? mid then
- raise ArgumentError, "wrong auth type #{authtype.to_s}"
- end
- @command.send mid, user, secret
+ @command.respond_to? mid or
+ raise ArgumentError, "wrong auth type #{authtype.to_s}"
+
+ @command.__send__ mid, user, secret
end
end
diff --git a/lib/net/telnet.rb b/lib/net/telnet.rb
index 87790c0300..380e834bea 100644
--- a/lib/net/telnet.rb
+++ b/lib/net/telnet.rb
@@ -4,7 +4,7 @@
net/telnet.rb - simple telnet client library
-Version 1.6.2
+Version 1.6.3
Wakou Aoyama <wakou@fsinet.or.jp>
@@ -239,10 +239,11 @@ module Net
CR = "\015"
LF = "\012"
EOL = CR + LF
- VERSION = "1.6.2"
- RELEASE_DATE = "2000-12-25"
- VERSION_CODE = 162
- RELEASE_CODE = 20001225
+ VERSION = '1.6.3'
+ RELEASE_DATE = '2001-02-26'
+ VERSION_CODE = 163
+ RELEASE_CODE = 20010226
+ REVISION = '$Id$'
def initialize(options)
@options = options
@@ -346,14 +347,13 @@ module Net
attr :sock
def telnetmode(mode = nil)
- if mode
- if (true == mode or false == mode)
- @options["Telnetmode"] = mode
- else
- raise ArgumentError, "required true or false"
- end
- else
+ case mode
+ when nil
@options["Telnetmode"]
+ when true, false
+ @options["Telnetmode"] = mode
+ else
+ raise ArgumentError, "required true or false"
end
end
@@ -366,14 +366,13 @@ module Net
end
def binmode(mode = nil)
- if mode
- if (true == mode or false == mode)
- @options["Binmode"] = mode
- else
- raise ArgumentError, "required true or false"
- end
- else
+ case mode
+ when nil
@options["Binmode"]
+ when true, false
+ @options["Binmode"] = mode
+ else
+ raise ArgumentError, "required true or false"
end
end
@@ -599,181 +598,7 @@ end
== HISTORY
-* Mon Dec 25 01:37:43 JST 2000 - wakou
- * version 1.6.2
- * Regexp::last_match[1] --> $1
-
-* Mon Dec 11 00:16:51 JST 2000 - wakou
- * version 1.6.1
- * $1 --> Regexp::last_match[1]
-
-* 2000/09/12 05:37:35 - matz
- * change: iterator? --> block_given?
-
-* Tue Sep 12 06:52:48 JST 2000 - wakou
- * version 1.6.0
- * correct: document.
- thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
- * add: Telnet#puts().
-
-* Sun Jun 18 23:31:44 JST 2000 - wakou
- * version 1.5.0
- * change: version syntax. old: x.yz, now: x.y.z
-
-* 2000/05/24 06:57:38 - wakou
- * version 1.40
- * improve: binmode(), telnetmode() interface.
- thanks to Dave Thomas <Dave@thomases.com>
-
-* 2000/05/09 22:02:56 - wakou
- * version 1.32
- * require English.rb
-
-* 2000/05/02 21:48:39 - wakou
- * version 1.31
- * Proxy option: can receive IO object.
-
-* 2000/04/03 18:27:02 - wakou
- * version 1.30
- * telnet.rb --> net/telnet.rb
-
-* 2000/01/24 17:02:57 - wakou
- * version 1.20
- * respond to "IAC WILL x" with "IAC DONT x"
- * respond to "IAC WONT x" with "IAC DONT x"
- * better dumplog format.
- thanks to WATANABE Hirofumi <Hirofumi.Watanabe@jp.sony.com>
-
-* 2000/01/18 17:47:31 - wakou
- * version 1.10
- * bug fix: write method
- * respond to "IAC WILL BINARY" with "IAC DO BINARY"
-
-* 1999/10/04 22:51:26 - wakou
- * version 1.00
- * bug fix: waitfor(preprocess) method.
- thanks to Shin-ichiro Hara <sinara@blade.nagaokaut.ac.jp>
- * add simple support for AO, DM, IP, NOP, SB, SE
- * COUTION! TimeOut --> TimeoutError
-
-* 1999/09/21 21:24:07 - wakou
- * version 0.50
- * add write method
-
-* 1999/09/17 17:41:41 - wakou
- * version 0.40
- * bug fix: preprocess method
-
-* 1999/09/14 23:09:05 - wakou
- * version 0.30
- * change prompt check order.
- not IO::select([@sock], nil, nil, waittime) and prompt === line
- --> prompt === line and not IO::select([@sock], nil, nil, waittime)
-
-* 1999/09/13 22:28:33 - wakou
- * version 0.24
- * Telnet#login: if ommit password, then not require password prompt.
-
-* 1999/08/10 05:20:21 - wakou
- * version 0.232
- * STATUS OUTPUT sample code typo.
- thanks to Tadayoshi Funaba <tadf@kt.rim.or.jp>
- host = Telnet.new({"Hosh" => "localhost"){|c| print c }
- --> host = Telnet.new({"Host" => "localhost"){|c| print c }
-
-* 1999/07/16 13:39:42 - wakou
- * version 0.231
- * TRUE --> true, FALSE --> false
-
-* 1999/07/15 22:32:09 - wakou
- * version 0.23
- * waitfor: if end of file reached, then return nil.
-
-* 1999/06/29 09:08:51 - wakou
- * version 0.22
- * new, waitfor, cmd: {"Timeout" => false} # ignore timeout
-
-* 1999/06/28 18:18:55 - wakou
- * version 0.21
- * waitfor: not rescue (EOFError)
-
-* 1999/06/04 06:24:58 - wakou
- * version 0.20
- * waitfor: support for divided telnet command
-
-* 1999/05/22 - wakou
- * version 0.181
- * bug fix: print method
-
-* 1999/05/14 - wakou
- * version 0.18
- * respond to "IAC WON'T SGA" with "IAC DON'T SGA"
- * DON'T SGA : end of line --> CR + LF
- * bug fix: preprocess method
-
-* 1999/04/30 - wakou
- * version 0.17
- * bug fix: $! + "\n" --> $!.to_s + "\n"
-
-* 1999/04/11 - wakou
- * version 0.163
- * STDOUT.write(message) --> yield(message) if iterator?
-
-* 1999/03/17 - wakou
- * version 0.162
- * add "Proxy" option
- * required timeout.rb
-
-* 1999/02/03 - wakou
- * version 0.161
- * select --> IO::select
-
-* 1998/10/09 - wakou
- * version 0.16
- * preprocess method change for the better
- * add binmode method.
- * change default Binmode. TRUE --> FALSE
-
-* 1998/10/04 - wakou
- * version 0.15
- * add telnetmode method.
-
-* 1998/09/22 - wakou
- * version 0.141
- * change default prompt. /[$%#>] $/ --> /[$%#>] \Z/
-
-* 1998/09/01 - wakou
- * version 0.14
- * IAC WILL SGA send EOL --> CR+NULL
- * IAC WILL SGA IAC DO BIN send EOL --> CR
- * NONE send EOL --> LF
- * add Dump_log option.
-
-* 1998/08/25 - wakou
- * version 0.13
- * add print method.
-
-* 1998/08/05 - wakou
- * version 0.122
- * support for HP-UX 10.20.
- thanks to WATANABE Tetsuya <tetsu@jpn.hp.com>
- * socket.<< --> socket.write
-
-* 1998/07/15 - wakou
- * version 0.121
- * string.+= --> string.concat
-
-* 1998/06/01 - wakou
- * version 0.12
- * add timeout, waittime.
-
-* 1998/04/21 - wakou
- * version 0.11
- * add realtime output.
-
-* 1998/04/13 - wakou
- * version 0.10
- * first release.
-
-$Date$
+delete. see cvs log.
+
+
=end
diff --git a/lib/observer.rb b/lib/observer.rb
index 08e75f5125..e1b249e885 100644
--- a/lib/observer.rb
+++ b/lib/observer.rb
@@ -5,7 +5,7 @@
module Observable
def add_observer(observer)
@observer_peers = [] unless defined? @observer_peers
- unless defined? observer.update
+ unless observer.respond_to? :update
raise NameError, "observer needs to respond to `update'"
end
@observer_peers.push observer
diff --git a/lib/parsedate.rb b/lib/parsedate.rb
index eee114acb2..7fc75cf0c2 100644
--- a/lib/parsedate.rb
+++ b/lib/parsedate.rb
@@ -1,5 +1,5 @@
-# parsedate.rb: Written by Tadayoshi Funaba 2000
-# $Id: parsedate.rb,v 1.2 2000-04-01 12:16:56+09 tadf Exp $
+# parsedate3.rb: Written by Tadayoshi Funaba 2000, 2001
+# $Id: parsedate3.rb,v 1.3 2001-01-18 12:09:47+09 tadf Exp $
module ParseDate
@@ -46,7 +46,12 @@ module ParseDate
hour = $1.to_i
min = $2.to_i
sec = $3.to_i if $3
- hour += 12 if $4 and $4.downcase == 'p'
+ if $4
+ hour %= 12
+ if $4.downcase == 'p'
+ hour += 12
+ end
+ end
zone = $5
end
diff --git a/lib/ping.rb b/lib/ping.rb
index 48657818cc..d698dd0c52 100644
--- a/lib/ping.rb
+++ b/lib/ping.rb
@@ -47,6 +47,8 @@ module Ping
s = TCPsocket.new(host, service)
s.close
end
+ rescue Errno::ECONNREFUSED
+ return true
rescue
return false
end
diff --git a/lib/thread.rb b/lib/thread.rb
index d4b6ad6ec1..559cd95a8a 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -185,7 +185,7 @@ class Queue
end
end
def shift(non_block=false)
- pop(non_block=false)
+ pop(non_block)
end
alias deq shift