protocol.rb smtp.rb pop.rb http.rb version 1.1.12

o protocol.rb:  update Net::Protocol::Proxy#connect
o protocol.rb:  ReplyCode is not a class
o http.rb:  header value does not include header name
o http.rb:  header is not a Hash, but HTTPResponse


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 2000-03-31 13:02:40 +00:00
Родитель 9fd5174ef3
Коммит be72d9a5da
4 изменённых файлов: 332 добавлений и 266 удалений

Просмотреть файл

@ -15,10 +15,7 @@ require 'net/protocol'
module Net
class HTTPError < ProtocolError; end
class HTTPBadResponse < HTTPError; end
class HTTPBadResponse < StandardError; end
=begin
@ -43,18 +40,20 @@ class HTTPBadResponse < HTTPError; end
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 response header (Hash) and "dest".
This method returns Net::HTTPResponse object and "dest".
If called as iterator, give a part String of entity body.
: head( path, header = nil )
get only header from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
This method returns header as a Hash like
This method returns Net::HTTPResponse object.
You can http header from this object like:
{ 'content-length' => 'Content-Length: 2554',
'content-type' => 'Content-Type: text/html',
... }
response['content-length'] #-> '2554'
response['content-type'] #-> 'text/html'
response['Content-Type'] #-> 'text/html'
response['CoNtEnT-tYpe'] #-> 'text/html'
: post( path, data, header = nil, dest = '' )
: post( path, data, header = nil ) {|str| .... }
@ -62,42 +61,58 @@ class HTTPBadResponse < HTTPError; end
If body exists, also get entity body.
It is written to "dest" by using "<<" method.
"header" must be a Hash like { 'Accept' => '*/*', ... }.
This method returns response header (Hash) and "dest".
This method returns Net::HTTPResponse object and "dest".
If called as iterator, gives a part String of entity body.
: get2( path, header = nil ) {|writer| .... }
send GET request for "path".
"header" must be a Hash like { 'Accept' => '*/*', ... }.
This method gives HTTPWriter object to block.
: get_body( dest = '' )
: get_body {|str| .... }
gets entity body of forwarded 'get2' or 'post2' methods.
Data is written in "dest" by using "<<" method.
This method returns "dest".
If called as iterator, gives a part String of entity body.
This method gives HTTPReadAdapter object to block.
: post2( path, data, header = nil ) {|writer| .... }
post "data"(must be String now) to "path".
"header" must be a Hash like { 'Accept' => '*/*', ... }.
This method gives HTTPWriter object to block.
This method gives HTTPReadAdapter object to block.
= class HTTPWriter
= class HTTPResponse
== Methods
HTTP response object.
All "key" is case-insensitive.
: code
HTTP result code. ex. '302'
: message
HTTP result message. ex. 'Not Found'
: 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.
: self[ key ] = val
set field value for "key".
: key?( key )
true if key is exist
= class HTTPReadAdapter
== Methods
: header
HTTP header.
: response
ReplyCode object.
Net::HTTPResponse object
: entity( dest = '' )
: body( dest = '' )
entity body.
entity body
: entity {|str| ... }
get entity body by using iterator.
@ -130,30 +145,19 @@ class HTTPBadResponse < HTTPError; end
@command.get_body( resp, dest )
}
return resp['http-header'], ret
return resp, ret
end
def get2( path, u_header = nil )
u_header = procheader( u_header )
connecting( u_header ) {
@command.get edit_path(path), u_header
tmp = HTTPWriter.new( @command )
tmp = HTTPReadAdapter.new( @command )
yield tmp
tmp.off
}
end
=begin c
def get_body( dest = '', &block )
if block then
dest = ReadAdapter.new( block )
end
@command.get_body @response, dest
ensure_termination @u_header
dest
end
=end
def head( path, u_header = nil )
u_header = procheader( u_header )
@ -163,7 +167,7 @@ class HTTPBadResponse < HTTPError; end
resp = @command.get_response_no_body
}
resp['http-header']
resp
end
def post( path, data, u_header = nil, dest = nil, &block )
@ -176,14 +180,14 @@ class HTTPBadResponse < HTTPError; end
@command.get_body( resp, dest )
}
return resp['http-header'], ret
return resp, ret
end
def post2( path, data, u_header = nil )
u_header = procheader( u_header )
connecting( u_header ) {
@command.post edit_path(path), u_header, data
tmp = HTTPWriter.new( @command )
tmp = HTTPReadAdapter.new( @command )
yield tmp
tmp.off
}
@ -193,35 +197,20 @@ class HTTPBadResponse < HTTPError; end
def put( path, src, u_header = nil )
u_header = procheader( u_header )
ret = ''
resp = nil
connecting( u_header ) {
@command.put path, u_header, src, dest
resp = @comman.get_response
@command.get_body( resp, ret )
}
return header, ret
return resp, ret
end
private
=begin c
def only_header( mid, path, u_header, data = nil )
@u_header = u_header
@response = nil
connecting u_header
if data then
@command.send mid, edit_path(path), u_header, data
else
@command.send mid, edit_path(path), u_header
end
@response = @command.get_response
@response['http-header']
end
=end
# called when connecting
def do_finish
unless @socket.closed? then
@ -255,8 +244,8 @@ class HTTPBadResponse < HTTPError; end
end
def keep_alive?( header )
if str = header['Connection'] then
if /\A\s*keep-alive/i === str then
if header.key? 'connection' then
if /\A\s*keep-alive/i === header['connection'] then
return true
end
else
@ -301,82 +290,126 @@ class HTTPBadResponse < HTTPError; end
HTTPSession = HTTP
class HTTPWriter
class HTTPReadAdapter
def initialize( command )
@command = command
@response = @header = @entity = nil
end
def response
unless @resp then
@resp = @command.get_response
end
@resp
@header = @body = nil
end
def header
unless @header then
@header = response['http-header']
@header = @command.get_response
end
@header
end
alias response header
def entity( dest = nil, &block )
def body( dest = nil, &block )
dest, ret = HTTP.procdest( dest, block )
unless @entity then
@entity = @command.get_body( response, dest )
unless @body then
@body = @command.get_body( response, dest )
end
@entity
@body
end
alias body entity
alias entity body
def off
entity
body
@command = nil
end
end
class HTTPSwitchProtocol < SuccessCode; end
class HTTPResponse < Response
class HTTPOK < SuccessCode; end
class HTTPCreated < SuccessCode; end
class HTTPAccepted < SuccessCode; end
class HTTPNonAuthoritativeInformation < SuccessCode; end
class HTTPNoContent < SuccessCode; end
class HTTPResetContent < SuccessCode; end
class HTTPPartialContent < SuccessCode; end
def initialize( code_type, code, msg )
super
@data = {}
@http_body_exist = true
end
class HTTPMultipleChoice < RetryCode; end
class HTTPMovedPermanently < RetryCode; end
class HTTPMovedTemporarily < RetryCode; end
class HTTPNotModified < RetryCode; end
class HTTPUseProxy < RetryCode; end
attr_accessor :http_body_exist
class HTTPBadRequest < RetryCode; end
class HTTPUnauthorized < RetryCode; end
class HTTPPaymentRequired < RetryCode; end
class HTTPForbidden < FatalErrorCode; end
class HTTPNotFound < FatalErrorCode; end
class HTTPMethodNotAllowed < FatalErrorCode; end
class HTTPNotAcceptable < FatalErrorCode; end
class HTTPProxyAuthenticationRequired < RetryCode; end
class HTTPRequestTimeOut < FatalErrorCode; end
class HTTPConflict < FatalErrorCode; end
class HTTPGone < FatalErrorCode; end
class HTTPLengthRequired < FatalErrorCode; end
class HTTPPreconditionFailed < FatalErrorCode; end
class HTTPRequestEntityTooLarge < FatalErrorCode; end
class HTTPRequestURITooLarge < FatalErrorCode; end
class HTTPUnsupportedMediaType < FatalErrorCode; end
def []( key )
@data[ key.downcase ]
end
class HTTPNotImplemented < FatalErrorCode; end
class HTTPBadGateway < FatalErrorCode; end
class HTTPServiceUnavailable < FatalErrorCode; end
class HTTPGatewayTimeOut < FatalErrorCode; end
class HTTPVersionNotSupported < FatalErrorCode; end
def []=( key, val )
@data[ key.downcase ] = val
end
def each( &block )
@data.each( &block )
end
def each_key( &block )
@data.each_key( &block )
end
def each_value( &block )
@data.each_value( &block )
end
def delete( key )
@data.delete key.downcase
end
def key?( key )
@data.key? key.downcase
end
def to_hash
@data.dup
end
end
HTTPSuccessCode = SuccessCode.mkchild
HTTPRetriableCode = RetriableCode.mkchild
HTTPFatalErrorCode = FatalErrorCode.mkchild
HTTPSwitchProtocol = HTTPSuccessCode.mkchild
HTTPOK = HTTPSuccessCode.mkchild
HTTPCreated = HTTPSuccessCode.mkchild
HTTPAccepted = HTTPSuccessCode.mkchild
HTTPNonAuthoritativeInformation = HTTPSuccessCode.mkchild
HTTPNoContent = HTTPSuccessCode.mkchild
HTTPResetContent = HTTPSuccessCode.mkchild
HTTPPartialContent = HTTPSuccessCode.mkchild
HTTPMultipleChoice = HTTPRetriableCode.mkchild
HTTPMovedPermanently = HTTPRetriableCode.mkchild
HTTPMovedTemporarily = HTTPRetriableCode.mkchild
HTTPNotModified = HTTPRetriableCode.mkchild
HTTPUseProxy = HTTPRetriableCode.mkchild
HTTPBadRequest = HTTPRetriableCode.mkchild
HTTPUnauthorized = HTTPRetriableCode.mkchild
HTTPPaymentRequired = HTTPRetriableCode.mkchild
HTTPForbidden = HTTPFatalErrorCode.mkchild
HTTPNotFound = HTTPFatalErrorCode.mkchild
HTTPMethodNotAllowed = HTTPFatalErrorCode.mkchild
HTTPNotAcceptable = HTTPFatalErrorCode.mkchild
HTTPProxyAuthenticationRequired = HTTPRetriableCode.mkchild
HTTPRequestTimeOut = HTTPFatalErrorCode.mkchild
HTTPConflict = HTTPFatalErrorCode.mkchild
HTTPGone = HTTPFatalErrorCode.mkchild
HTTPLengthRequired = HTTPFatalErrorCode.mkchild
HTTPPreconditionFailed = HTTPFatalErrorCode.mkchild
HTTPRequestEntityTooLarge = HTTPFatalErrorCode.mkchild
HTTPRequestURITooLarge = HTTPFatalErrorCode.mkchild
HTTPUnsupportedMediaType = HTTPFatalErrorCode.mkchild
HTTPNotImplemented = HTTPFatalErrorCode.mkchild
HTTPBadGateway = HTTPFatalErrorCode.mkchild
HTTPServiceUnavailable = HTTPFatalErrorCode.mkchild
HTTPGatewayTimeOut = HTTPFatalErrorCode.mkchild
HTTPVersionNotSupported = HTTPFatalErrorCode.mkchild
class HTTPCommand < Command
@ -431,38 +464,48 @@ class HTTPBadResponse < HTTPError; end
def get_response
rep = get_reply
rep = get_reply while ContinueCode === rep
header = {}
resp = get_reply
resp = get_reply while ContinueCode === resp
while true do
line = @socket.readline
break if line.empty?
nm = /\A[^:]+/.match( line )[0].strip.downcase
header[nm] = line
end
rep['http-header'] = header
rep
m = /\A([^:]+):\s*(.*)/p.match( line )
unless m then
raise HTTPBadResponse, 'wrong header line format'
end
nm = m[1]
line = m[2]
if resp.key? nm then
resp[nm] << ', ' << line
else
resp[nm] = line
end
end
resp
end
def check_response( resp )
reply_must resp, SuccessCode
end
def get_body( rep, dest )
header = rep['http-header']
if rep['body-exist'] then
if chunked? header then
read_chunked( dest, header )
def get_body( resp, dest )
if resp.http_body_exist then
if chunked? resp then
read_chunked( dest, resp )
else
if clen = content_length( header ) then
clen = content_length( resp )
if clen then
@socket.read clen, dest
else
if false then # "multipart/byteranges" check should be done
clen = range_length( resp )
if clen then
@socket.read clen, dest
else
if header['Connection'] and
/connection:\s*close/i === header['Connection'] then
tmp = resp['connection']
if tmp and /close/i === tmp then
@socket.read_all dest
@socket.close
end
@ -471,7 +514,7 @@ class HTTPBadResponse < HTTPError; end
end
end
end_critical
reply_must rep, SuccessCode
reply_must resp, SuccessCode
dest
end
@ -501,7 +544,7 @@ class HTTPBadResponse < HTTPError; end
end
CODE_TO_CLASS = {
HTTPCODE_TO_OBJ = {
'100' => [ContinueCode, false],
'100' => [HTTPSwitchProtocol, false],
@ -547,17 +590,18 @@ class HTTPBadResponse < HTTPError; end
def get_reply
str = @socket.readline
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
m = /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i.match( str )
unless m then
raise HTTPBadResponse, "wrong status line format: #{str}"
end
@http_version = $1
status = $2
discrip = $3
@http_version = m[1]
status = m[2]
discrip = m[3]
klass, bodyexist = CODE_TO_CLASS[status] || [UnknownCode, true]
code = klass.new( status, discrip )
code['body-exist'] = bodyexist
code
klass, bodyexist = HTTPCODE_TO_OBJ[status] || [UnknownCode, true]
resp = HTTPResponse.new( klass, status, discrip )
resp.http_body_exist = bodyexist
resp
end
def read_chunked( ret, header )
@ -567,10 +611,11 @@ class HTTPBadResponse < HTTPError; end
while true do
line = @socket.readline
unless /[0-9a-hA-H]+/ === line then
m = /[0-9a-hA-H]+/.match( line )
unless m then
raise HTTPBadResponse, "chunk size not given"
end
len = $&.hex
len = m[0].hex
break if len == 0
@socket.read( len, ret ); total += len
@socket.read 2 # \r\n
@ -581,28 +626,47 @@ class HTTPBadResponse < HTTPError; end
end
header.delete 'transfer-encoding'
header[ 'content-length' ] = "Content-Length: #{total}"
header[ 'content-length' ] = total.to_s
end
def content_length( header )
unless str = header[ 'content-length' ] then
return nil
if header.key? 'content-length' then
m = /\d+/.match( header['content-length'] )
unless m then
raise HTTPBadResponse, 'wrong Content-Length format'
end
unless /\Acontent-length:\s*(\d+)/i === str then
raise HTTPBadResponse, "content-length format error"
m[0].to_i
else
nil
end
$1.to_i
end
def chunked?( header )
if str = header[ 'transfer-encoding' ] then
if /\Atransfer-encoding:\s*chunked/i === str then
return true
str = header[ 'transfer-encoding' ]
if str and /(\A|\s+)chunked(?:\s+|\z)/i === str then
true
else
false
end
end
false
def range_length( header )
if header.key? 'content-range' then
m = %r<bytes\s+(\d+)-(\d+)/\d+>.match( header['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
else
nil
end
end
end

Просмотреть файл

@ -314,9 +314,9 @@ Net::POP3
str = @socket.readline
if /\A\+/ === str then
return SuccessCode.new( str[0,3], str[3, str.size - 3].strip )
return Response.new( SuccessCode, str[0,3], str[3, str.size - 3].strip )
else
return ErrorCode.new( str[0,4], str[4, str.size - 4].strip )
return Response.new( ErrorCode, str[0,4], str[4, str.size - 4].strip )
end
end

Просмотреть файл

@ -15,7 +15,7 @@ require 'socket'
module Net
Version = '1.1.11'
Version = '1.1.12'
=begin
@ -95,7 +95,7 @@ Object
@port = port
end
def connect( addr, port )
def connect( addr = nil, port = nil )
super @proxyaddr, @proxyport
end
private :connect
@ -286,55 +286,21 @@ Object
end
class ProtocolError < StandardError ; end
class ProtoSyntaxError < ProtocolError ; end
class ProtoFatalError < ProtocolError ; end
class ProtoUnknownError < ProtocolError ; end
class ProtoServerError < ProtocolError ; end
class ProtoAuthError < ProtocolError ; end
class ProtoCommandError < ProtocolError ; end
class ProtoRetryError < ProtocolError ; end
class Response
class ReplyCode
class << self
def error_type( err )
module_eval "def self.get_error_type() #{err.name} end"
end
def error!( mes )
raise get_error_type, mes
end
end
def initialize( cod, mes )
@code = cod
@msg = mes
@data = nil
end
attr_reader :code, :msg
def []( key )
if @data then
@data[key]
else
nil
end
end
def []=( key, val )
unless h = @data then
@data = h = {}
end
h[key] = val
def initialize( ctype, cno, msg )
@code_type = ctype
@code = cno
@message = msg
super()
end
attr_reader :code_type, :code, :message
alias msg message
def error!( sending )
mes = <<MES
raise @code_type.error_type,
sprintf( <<MSG, @code, Net.quote(sending), Net.quote(@message) )
status %s
writing string is:
@ -342,43 +308,58 @@ writing string is:
error message from server is:
%s
MES
type.error! sprintf( mes, @code, Net.quote(sending), Net.quote(@msg) )
MSG
end
end
class SuccessCode < ReplyCode
error_type ProtoUnknownError
class ProtocolError < StandardError; end
class ProtoSyntaxError < ProtocolError; end
class ProtoFatalError < ProtocolError; end
class ProtoUnknownError < ProtocolError; end
class ProtoServerError < ProtocolError; end
class ProtoAuthError < ProtocolError; end
class ProtoCommandError < ProtocolError; end
class ProtoRetriableError < ProtocolError; end
ProtocRetryError = ProtoRetriableError
class Code
def initialize( paren, err )
@parents = paren
@err = err
@parents.push self
end
class ContinueCode < SuccessCode
error_type ProtoUnknownError
attr_reader :parents
def error_type
@err
end
class ErrorCode < ReplyCode
error_type ProtocolError
def ===( response )
response.code_type.parents.reverse_each {|i| return true if i == self }
false
end
class SyntaxErrorCode < ErrorCode
error_type ProtoSyntaxError
def mkchild( err = nil )
type.new( @parents + [self], err || @err )
end
class FatalErrorCode < ErrorCode
error_type ProtoFatalError
end
class ServerBusyCode < ErrorCode
error_type ProtoServerError
end
class RetryCode < ReplyCode
error_type ProtoRetryError
end
class UnknownCode < ReplyCode
error_type ProtoUnknownError
end
ReplyCode = Code.new( [], ProtoUnknownError )
SuccessCode = ReplyCode.mkchild( ProtoUnknownError )
ContinueCode = ReplyCode.mkchild( ProtoUnknownError )
ErrorCode = ReplyCode.mkchild( ProtocolError )
SyntaxErrorCode = ErrorCode.mkchild( ProtoSyntaxError )
FatalErrorCode = ErrorCode.mkchild( ProtoFatalError )
ServerErrorCode = ErrorCode.mkchild( ProtoServerError )
RetriableCode = ReplyCode.mkchild( ProtoRetriableError )
UnknownCode = ReplyCode.mkchild( ProtoUnknownError )
@ -415,6 +396,7 @@ MES
@addr = addr
@port = port
@pipe = pipe
@prepipe = nil
@closed = true
@ipaddr = ''
@ -471,47 +453,49 @@ MES
TERMEXP = /\n|\r\n|\r/o
def read( len, ret = '' )
@pipe << "reading #{len} bytes...\n" if pre = @pipe ; @pipe = nil
def read( len, dest = '' )
@pipe << "reading #{len} bytes...\n" if @pipe; pipeoff
rsize = 0
while rsize + @buffer.size < len do
rsize += writeinto( ret, @buffer.size )
rsize += writeinto( dest, @buffer.size )
fill_rbuf
end
writeinto( ret, len - rsize )
writeinto( dest, len - rsize )
@pipe << "read #{len} bytes\n" if @pipe = pre
ret
@pipe << "read #{len} bytes\n" if pipeon
dest
end
def read_all( ret = '' )
@pipe << "reading all...\n" if pre = @pipe; @pipe = nil
def read_all( dest = '' )
@pipe << "reading all...\n" if @pipe; pipeoff
rsize = 0
begin
while true do
rsize += writeinto( ret, @buffer.size )
rsize += writeinto( dest, @buffer.size )
fill_rbuf
end
rescue EOFError
;
end
@pipe << "read #{rsize} bytes\n" if @pipe = pre
ret
@pipe << "read #{rsize} bytes\n" if pipeon
dest
end
def readuntil( target )
until idx = @buffer.index( target ) do
while true do
idx = @buffer.index( target )
break if idx
fill_rbuf
end
ret = ''
writeinto( ret, idx + target.size )
ret
dest = ''
writeinto( dest, idx + target.size )
dest
end
@ -522,8 +506,8 @@ MES
end
def read_pendstr( dest = '' )
@pipe << "reading text...\n" if pre = @pipe ; @pipe = nil
def read_pendstr( dest )
@pipe << "reading text...\n" if @pipe; pipeoff
rsize = 0
@ -533,17 +517,16 @@ MES
dest << str
end
@pipe << "read #{rsize} bytes\n" if @pipe = pre
@pipe << "read #{rsize} bytes\n" if pipeon
dest
end
def read_pendlist
@pipe << "reading list...\n" if pre = @pipe ; @pipe = nil
@pipe << "reading list...\n" if @pipe; pipeoff
arr = []
str = nil
call = iterator?
while (str = readuntil( CRLF )) != D_CRLF do
str.chop!
@ -551,7 +534,7 @@ MES
yield str if iterator?
end
@pipe << "read #{arr.size} lines\n" if @pipe = pre
@pipe << "read #{arr.size} lines\n" if pipeon
arr
end
@ -565,12 +548,12 @@ MES
@buffer << @socket.sysread( READ_BLOCK )
end
def writeinto( ret, len )
def writeinto( dest, len )
bsi = @buffer.size
ret << @buffer[ 0, len ]
dest << @buffer[ 0, len ]
@buffer = @buffer[ len, bsi - len ]
@pipe << %{read "#{Net.quote ret}"\n} if @pipe
@pipe << %{read "#{Net.quote dest}"\n} if @pipe
len
end
@ -593,7 +576,7 @@ MES
end
def write_bin( src, block = nil )
def write_bin( src, block )
do_write_beg
if block then
block.call WriteAdapter.new( self, :do_write_do )
@ -606,12 +589,12 @@ MES
end
def write_pendstr( src )
@pipe << "writing text from #{src.type}\n" if pre = @pipe ; @pipe = nil
def write_pendstr( src, block )
@pipe << "writing text from #{src.type}\n" if @pipe; pipeoff
do_write_beg
if iterator? then
yield WriteAdapter.new( self, :write_pendstr_inner )
if block then
block.call WriteAdapter.new( self, :write_pendstr_inner )
else
write_pendstr_inner src
end
@ -619,7 +602,7 @@ MES
do_write_do D_CRLF
wsize = do_write_fin
@pipe << "wrote #{wsize} bytes text" if @pipe = pre
@pipe << "wrote #{wsize} bytes text" if pipeon
wsize
end
@ -649,11 +632,13 @@ MES
adding( src ) do
beg = 0
buf = @wbuf
while pos = buf.index( TERMEXP, beg ) do
while true do
pos = buf.index( TERMEXP, beg )
break unless pos
s = $&.size
break if pos + s == buf.size - 1 and buf[-1] == ?\r
send mid, buf[ beg, pos - beg ] << CRLF
__send__ mid, buf[ beg, pos - beg ] << CRLF
beg = pos + s
end
@wbuf = buf[ beg, buf.size - beg ] if beg != 0
@ -671,7 +656,9 @@ MES
end
when File
while i = src.read( 512 ) do
while true do
i = src.read( 512 )
break unless i
@wbuf << i
yield
end
@ -691,8 +678,10 @@ MES
buf << "\n" unless /\n|\r/o === buf[-1,1]
beg = 0
while pos = buf.index( TERMEXP, beg ) do
send mid, buf[ beg, pos - beg ] << CRLF
while true do
pos = buf.index( TERMEXP, beg )
break unless pos
__send__ mid, buf[ beg, pos - beg ] << CRLF
beg = pos + $&.size
end
end
@ -727,6 +716,19 @@ MES
@writtensize
end
def pipeoff
@prepipe = @pipe
@pipe = nil
@prepipe
end
def pipeon
@pipe = @prepipe
@prepipe = nil
@pipe
end
end

Просмотреть файл

@ -76,12 +76,12 @@ Net::Protocol
def sendmail( mailsrc, fromaddr, toaddrs )
do_ready fromaddr, toaddrs
@command.write_mail mailsrc
@command.write_mail mailsrc, nil
end
def ready( fromaddr, toaddrs, &block )
do_ready fromaddr, toaddrs
@command.write_mail( &block )
@command.write_mail nil, block
end
@ -163,8 +163,8 @@ Net::Protocol
end
def write_mail( mailsrc = nil, &block )
@socket.write_pendstr mailsrc, &block
def write_mail( mailsrc, block )
@socket.write_pendstr mailsrc, block
check_reply SuccessCode
end_critical
end
@ -189,7 +189,7 @@ Net::Protocol
klass = case stat[0]
when ?2 then SuccessCode
when ?3 then ContinueCode
when ?4 then ServerBusyCode
when ?4 then ServerErrorCode
when ?5 then
case stat[1]
when ?0 then SyntaxErrorCode
@ -197,7 +197,7 @@ Net::Protocol
end
end
klass.new( stat, arr.join('') )
Response.new( klass, stat, arr.join('') )
end