mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/net/http.rb: backported from trunk, rev 1.128. [ruby-dev:25673] [ruby-dev:26617]
* lib/net/protocol.rb: backported from trunk, rev 1.78. * lib/net/protocol.rb: new method #old_open to support net/smtp and net/pop. * lib/net/smtp.rb: use #old_open. * lib/net/pop.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9146 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
bf20e3b82e
commit
e99c067d8e
5 changed files with 827 additions and 488 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
Tue Sep 13 16:26:45 2005 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* lib/net/http.rb: backported from trunk, rev 1.128.
|
||||
[ruby-dev:25673] [ruby-dev:26617]
|
||||
|
||||
* lib/net/protocol.rb: backported from trunk, rev 1.78.
|
||||
|
||||
* lib/net/protocol.rb: new method #old_open to support net/smtp
|
||||
and net/pop.
|
||||
|
||||
* lib/net/smtp.rb: use #old_open.
|
||||
|
||||
* lib/net/pop.rb: ditto.
|
||||
|
||||
Tue Sep 13 12:33:05 2005 <why@ruby-lang.org>
|
||||
|
||||
* lib/yaml.rb: reworking YAML::Stream to use the new
|
||||
|
|
845
lib/net/http.rb
845
lib/net/http.rb
File diff suppressed because it is too large
Load diff
|
@ -435,7 +435,7 @@ module Net
|
|||
end
|
||||
|
||||
def do_start( account, password )
|
||||
@socket = self.class.socket_type.open(@address, @port,
|
||||
@socket = self.class.socket_type.old_open(@address, @port,
|
||||
@open_timeout, @read_timeout, @debug_output)
|
||||
on_connect
|
||||
@command = POP3Command.new(@socket)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# = net/protocol.rb
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1999-2004 Yukihiro Matsumoto
|
||||
# Copyright (c) 1999-2004 Minero Aoki
|
||||
# Copyright (c) 1999-2005 Yukihiro Matsumoto
|
||||
# Copyright (c) 1999-2005 Minero Aoki
|
||||
#
|
||||
# written and maintained by Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
@ -25,7 +25,7 @@ module Net # :nodoc:
|
|||
|
||||
class Protocol #:nodoc: internal use only
|
||||
private
|
||||
def Protocol.protocol_param( name, val )
|
||||
def Protocol.protocol_param(name, val)
|
||||
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
||||
def #{name}
|
||||
#{val}
|
||||
|
@ -34,6 +34,7 @@ module Net # :nodoc:
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
class ProtocolError < StandardError; end
|
||||
class ProtoSyntaxError < ProtocolError; end
|
||||
class ProtoFatalError < ProtocolError; end
|
||||
|
@ -45,132 +46,179 @@ module Net # :nodoc:
|
|||
ProtocRetryError = ProtoRetriableError
|
||||
|
||||
|
||||
class InternetMessageIO #:nodoc: internal use only
|
||||
|
||||
class << self
|
||||
alias open new
|
||||
end
|
||||
|
||||
def initialize( addr, port,
|
||||
open_timeout = nil, read_timeout = nil,
|
||||
debug_output = nil )
|
||||
@address = addr
|
||||
@port = port
|
||||
@read_timeout = read_timeout
|
||||
@debug_output = debug_output
|
||||
@socket = nil
|
||||
@rbuf = nil # read buffer
|
||||
@wbuf = nil # write buffer
|
||||
connect open_timeout
|
||||
LOG 'opened'
|
||||
end
|
||||
|
||||
attr_reader :address
|
||||
attr_reader :port
|
||||
|
||||
def ip_address
|
||||
return '' unless @socket
|
||||
@socket.addr[3]
|
||||
class BufferedIO #:nodoc: internal use only
|
||||
def initialize(io)
|
||||
@io = io
|
||||
@read_timeout = 60
|
||||
@debug_output = nil
|
||||
@rbuf = ''
|
||||
end
|
||||
|
||||
attr_reader :io
|
||||
attr_accessor :read_timeout
|
||||
attr_accessor :debug_output
|
||||
|
||||
attr_reader :socket
|
||||
|
||||
def connect( open_timeout )
|
||||
LOG "opening connection to #{@address}..."
|
||||
timeout(open_timeout) {
|
||||
@socket = TCPsocket.new(@address, @port)
|
||||
}
|
||||
@rbuf = ''
|
||||
end
|
||||
private :connect
|
||||
|
||||
def close
|
||||
if @socket
|
||||
@socket.close
|
||||
LOG 'closed'
|
||||
else
|
||||
LOG 'close call for already closed socket'
|
||||
end
|
||||
@socket = nil
|
||||
@rbuf = ''
|
||||
end
|
||||
|
||||
def reopen( open_timeout = nil )
|
||||
LOG 'reopening...'
|
||||
close
|
||||
connect open_timeout
|
||||
LOG 'reopened'
|
||||
def inspect
|
||||
"#<#{self.class} io=#{@io}>"
|
||||
end
|
||||
|
||||
def closed?
|
||||
not @socket
|
||||
@io.closed?
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} #{closed?() ? 'closed' : 'opened'}>"
|
||||
def close
|
||||
@io.close
|
||||
end
|
||||
|
||||
###
|
||||
### READ
|
||||
###
|
||||
#
|
||||
# Read
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def read( len, dest = '', ignore_eof = false )
|
||||
def read(len, dest = '', ignore_eof = false)
|
||||
LOG "reading #{len} bytes..."
|
||||
# LOG_off() # experimental: [ruby-list:38800]
|
||||
read_bytes = 0
|
||||
begin
|
||||
while read_bytes + @rbuf.size < len
|
||||
read_bytes += rbuf_moveto(dest, @rbuf.size)
|
||||
dest << (s = rbuf_consume(@rbuf.size))
|
||||
read_bytes += s.size
|
||||
rbuf_fill
|
||||
end
|
||||
rbuf_moveto dest, len - read_bytes
|
||||
dest << (s = rbuf_consume(len - read_bytes))
|
||||
read_bytes += s.size
|
||||
rescue EOFError
|
||||
raise unless ignore_eof
|
||||
end
|
||||
# LOG_on()
|
||||
LOG "read #{read_bytes} bytes"
|
||||
dest
|
||||
end
|
||||
|
||||
def read_all( dest = '' )
|
||||
def read_all(dest = '')
|
||||
LOG 'reading all...'
|
||||
# LOG_off() # experimental: [ruby-list:38800]
|
||||
read_bytes = 0
|
||||
begin
|
||||
while true
|
||||
read_bytes += rbuf_moveto(dest, @rbuf.size)
|
||||
dest << (s = rbuf_consume(@rbuf.size))
|
||||
read_bytes += s.size
|
||||
rbuf_fill
|
||||
end
|
||||
rescue EOFError
|
||||
;
|
||||
end
|
||||
# LOG_on()
|
||||
LOG "read #{read_bytes} bytes"
|
||||
dest
|
||||
end
|
||||
|
||||
def readuntil( terminator, ignore_eof = false )
|
||||
dest = ''
|
||||
def readuntil(terminator, ignore_eof = false)
|
||||
begin
|
||||
until idx = @rbuf.index(terminator)
|
||||
rbuf_fill
|
||||
end
|
||||
rbuf_moveto dest, idx + terminator.size
|
||||
return rbuf_consume(idx + terminator.size)
|
||||
rescue EOFError
|
||||
raise unless ignore_eof
|
||||
rbuf_moveto dest, @rbuf.size
|
||||
return rbuf_consume(@rbuf.size)
|
||||
end
|
||||
dest
|
||||
end
|
||||
|
||||
def readline
|
||||
readuntil("\n").chop
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rbuf_fill
|
||||
timeout(@read_timeout) {
|
||||
@rbuf << @io.sysread(1024)
|
||||
}
|
||||
end
|
||||
|
||||
def rbuf_consume(len)
|
||||
s = @rbuf.slice!(0, len)
|
||||
@debug_output << %Q[-> #{s.dump}\n] if @debug_output
|
||||
s
|
||||
end
|
||||
|
||||
#
|
||||
# Write
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def write(str)
|
||||
writing {
|
||||
write0 str
|
||||
}
|
||||
end
|
||||
|
||||
def writeline(str)
|
||||
writing {
|
||||
write0 str + "\r\n"
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def writing
|
||||
@written_bytes = 0
|
||||
@debug_output << '<- ' if @debug_output
|
||||
yield
|
||||
@debug_output << "\n" if @debug_output
|
||||
bytes = @written_bytes
|
||||
@written_bytes = nil
|
||||
bytes
|
||||
end
|
||||
|
||||
def write0(str)
|
||||
@debug_output << str.dump if @debug_output
|
||||
len = @io.write(str)
|
||||
@written_bytes += len
|
||||
len
|
||||
end
|
||||
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
|
||||
private
|
||||
|
||||
def LOG_off
|
||||
@save_debug_out = @debug_output
|
||||
@debug_output = nil
|
||||
end
|
||||
|
||||
def LOG_on
|
||||
@debug_output = @save_debug_out
|
||||
end
|
||||
|
||||
def LOG(msg)
|
||||
return unless @debug_output
|
||||
@debug_output << msg + "\n"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class InternetMessageIO < BufferedIO #:nodoc: internal use only
|
||||
def InternetMessageIO.old_open(addr, port,
|
||||
open_timeout = nil, read_timeout = nil, debug_output = nil)
|
||||
debug_output << "opening connection to #{addr}...\n" if debug_output
|
||||
s = timeout(open_timeout) { TCPsocket.new(addr, port) }
|
||||
io = new(s)
|
||||
io.read_timeout = read_timeout
|
||||
io.debug_output = debug_output
|
||||
io
|
||||
end
|
||||
|
||||
def initialize(io)
|
||||
super
|
||||
@wbuf = nil
|
||||
end
|
||||
|
||||
#
|
||||
# Read
|
||||
#
|
||||
|
||||
def each_message_chunk
|
||||
LOG 'reading message...'
|
||||
LOG_off()
|
||||
|
@ -190,190 +238,90 @@ module Net # :nodoc:
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rbuf_fill
|
||||
timeout(@read_timeout) {
|
||||
@rbuf << @socket.sysread(1024)
|
||||
}
|
||||
end
|
||||
|
||||
def rbuf_moveto( dest, len )
|
||||
dest << (s = @rbuf.slice!(0, len))
|
||||
@debug_output << %Q[-> #{s.dump}\n] if @debug_output
|
||||
len
|
||||
end
|
||||
|
||||
###
|
||||
### WRITE
|
||||
###
|
||||
|
||||
public
|
||||
|
||||
def write( str )
|
||||
writing {
|
||||
write0 str
|
||||
}
|
||||
end
|
||||
|
||||
def writeline( str )
|
||||
writing {
|
||||
write0 str + "\r\n"
|
||||
}
|
||||
end
|
||||
|
||||
def write_message( src )
|
||||
LOG "writing message from #{src.class}"
|
||||
LOG_off()
|
||||
len = using_each_crlf_line {
|
||||
write_message_0 src
|
||||
}
|
||||
LOG_on()
|
||||
LOG "wrote #{len} bytes"
|
||||
len
|
||||
end
|
||||
|
||||
def write_message_by_block( &block )
|
||||
LOG 'writing message from block'
|
||||
LOG_off()
|
||||
len = using_each_crlf_line {
|
||||
begin
|
||||
block.call(WriteAdapter.new(self, :write_message_0))
|
||||
rescue LocalJumpError
|
||||
# allow `break' from writer block
|
||||
end
|
||||
}
|
||||
LOG_on()
|
||||
LOG "wrote #{len} bytes"
|
||||
len
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def writing
|
||||
@written_bytes = 0
|
||||
@debug_output << '<- ' if @debug_output
|
||||
yield
|
||||
@socket.flush
|
||||
@debug_output << "\n" if @debug_output
|
||||
bytes = @written_bytes
|
||||
@written_bytes = nil
|
||||
bytes
|
||||
end
|
||||
|
||||
def write0( str )
|
||||
@debug_output << str.dump if @debug_output
|
||||
len = @socket.write(str)
|
||||
@written_bytes += len
|
||||
len
|
||||
end
|
||||
|
||||
#
|
||||
# Reads string from src calling :each, and write to @socket.
|
||||
# Escapes '.' on the each line head.
|
||||
#
|
||||
def write_message_0( src )
|
||||
def write_message_0(src)
|
||||
prev = @written_bytes
|
||||
each_crlf_line(src) do |line|
|
||||
if line[0] == ?.
|
||||
then write0 '.' + line
|
||||
else write0 line
|
||||
end
|
||||
write0 line.sub(/\A\./, '..')
|
||||
end
|
||||
@written_bytes - prev
|
||||
end
|
||||
|
||||
#
|
||||
# setup @wbuf for each_crlf_line.
|
||||
# Write
|
||||
#
|
||||
def using_each_crlf_line
|
||||
writing {
|
||||
@wbuf = ''
|
||||
yield
|
||||
if not @wbuf.empty? # unterminated last line
|
||||
if @wbuf[-1] == ?\r
|
||||
@wbuf.chop!
|
||||
end
|
||||
@wbuf.concat "\r\n"
|
||||
write0 @wbuf
|
||||
elsif @written_bytes == 0 # empty src
|
||||
write0 "\r\n"
|
||||
end
|
||||
write0 ".\r\n"
|
||||
@wbuf = nil
|
||||
|
||||
def write_message(src)
|
||||
LOG "writing message from #{src.class}"
|
||||
LOG_off()
|
||||
len = writing {
|
||||
using_each_crlf_line {
|
||||
write_message_0 src
|
||||
}
|
||||
}
|
||||
LOG_on()
|
||||
LOG "wrote #{len} bytes"
|
||||
len
|
||||
end
|
||||
|
||||
#
|
||||
# extract a CR-LF-terminating-line from @wbuf and yield it.
|
||||
#
|
||||
def each_crlf_line( src )
|
||||
adding(src) do
|
||||
beg = 0
|
||||
buf = @wbuf
|
||||
while buf.index(/\n|\r\n|\r/, beg)
|
||||
m = Regexp.last_match
|
||||
if (m.begin(0) == buf.length - 1) and buf[-1] == ?\r
|
||||
# "...\r" : can follow "\n..."
|
||||
break
|
||||
def write_message_by_block(&block)
|
||||
LOG 'writing message from block'
|
||||
LOG_off()
|
||||
len = writing {
|
||||
using_each_crlf_line {
|
||||
begin
|
||||
block.call(WriteAdapter.new(self, :write_message_0))
|
||||
rescue LocalJumpError
|
||||
# allow `break' from writer block
|
||||
end
|
||||
str = buf[beg ... m.begin(0)]
|
||||
str.concat "\r\n"
|
||||
yield str
|
||||
beg = m.end(0)
|
||||
end
|
||||
@wbuf = buf[beg ... buf.length]
|
||||
end
|
||||
}
|
||||
}
|
||||
LOG_on()
|
||||
LOG "wrote #{len} bytes"
|
||||
len
|
||||
end
|
||||
|
||||
#
|
||||
# Reads strings from SRC and add to @wbuf, then yield.
|
||||
#
|
||||
def adding( src )
|
||||
case src
|
||||
when String # for speeding up.
|
||||
0.step(src.size - 1, 2048) do |i|
|
||||
@wbuf << src[i,2048]
|
||||
yield
|
||||
end
|
||||
|
||||
when File # for speeding up.
|
||||
while s = src.read(2048)
|
||||
s[0,0] = @wbuf
|
||||
@wbuf = s
|
||||
yield
|
||||
end
|
||||
|
||||
else # generic reader
|
||||
src.each do |s|
|
||||
@wbuf << s
|
||||
yield if @wbuf.size > 2048
|
||||
end
|
||||
yield unless @wbuf.empty?
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
### DEBUG
|
||||
###
|
||||
|
||||
private
|
||||
|
||||
def LOG_off
|
||||
@save_debug_out = @debug_output
|
||||
@debug_output = nil
|
||||
def using_each_crlf_line
|
||||
@wbuf = ''
|
||||
yield
|
||||
if not @wbuf.empty? # unterminated last line
|
||||
write0 @wbuf.chomp + "\r\n"
|
||||
elsif @written_bytes == 0 # empty src
|
||||
write0 "\r\n"
|
||||
end
|
||||
write0 ".\r\n"
|
||||
@wbuf = nil
|
||||
end
|
||||
|
||||
def LOG_on
|
||||
@debug_output = @save_debug_out
|
||||
def each_crlf_line(src)
|
||||
buffer_filling(@wbuf, src) do
|
||||
while line = @wbuf.slice!(/\A.*(?:\n|\r\n|\r(?!\z))/n)
|
||||
yield line.chomp("\n") + "\r\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def LOG( msg )
|
||||
return unless @debug_output
|
||||
@debug_output << msg
|
||||
@debug_output << "\n"
|
||||
def buffer_filling(buf, src)
|
||||
case src
|
||||
when String # for speeding up.
|
||||
0.step(src.size - 1, 1024) do |i|
|
||||
buf << src[i, 1024]
|
||||
yield
|
||||
end
|
||||
when File # for speeding up.
|
||||
while s = src.read(1024)
|
||||
buf << s
|
||||
yield
|
||||
end
|
||||
else # generic reader
|
||||
src.each do |s|
|
||||
buf << s
|
||||
yield if buf.size > 1024
|
||||
end
|
||||
yield unless buf.empty?
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -381,41 +329,38 @@ module Net # :nodoc:
|
|||
# The writer adapter class
|
||||
#
|
||||
class WriteAdapter
|
||||
|
||||
def initialize( sock, mid )
|
||||
@socket = sock
|
||||
@method_id = mid
|
||||
def initialize(socket, method)
|
||||
@socket = socket
|
||||
@method_id = method
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class} socket=#{@socket.inspect}>"
|
||||
end
|
||||
|
||||
def write( str )
|
||||
def write(str)
|
||||
@socket.__send__(@method_id, str)
|
||||
end
|
||||
|
||||
alias print write
|
||||
|
||||
def <<( str )
|
||||
def <<(str)
|
||||
write str
|
||||
self
|
||||
end
|
||||
|
||||
def puts( str = '' )
|
||||
def puts(str = '')
|
||||
write str.chomp("\n") + "\n"
|
||||
end
|
||||
|
||||
def printf( *args )
|
||||
def printf(*args)
|
||||
write sprintf(*args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReadAdapter #:nodoc: internal use only
|
||||
|
||||
def initialize( block )
|
||||
def initialize(block)
|
||||
@block = block
|
||||
end
|
||||
|
||||
|
@ -423,21 +368,18 @@ module Net # :nodoc:
|
|||
"#<#{self.class}>"
|
||||
end
|
||||
|
||||
def <<( str )
|
||||
def <<(str)
|
||||
call_block(str, &@block) if @block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# This method is needed because @block must be called by yield,
|
||||
# not Proc#call. You can see difference when using `break' in
|
||||
# the block.
|
||||
#
|
||||
def call_block( str )
|
||||
def call_block(str)
|
||||
yield str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ module Net
|
|||
raise IOError, 'SMTP session already started' if @started
|
||||
check_auth_args user, secret, authtype if user or secret
|
||||
|
||||
@socket = InternetMessageIO.open(@address, @port,
|
||||
@socket = InternetMessageIO.old_open(@address, @port,
|
||||
@open_timeout, @read_timeout,
|
||||
@debug_output)
|
||||
check_response(critical { recv_response() })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue