зеркало из https://github.com/github/ruby.git
v1.1.11
o all: use "critical" to avoid duplicated command dispatch o http.rb: change get2, post2 usage (HTTPWriter) o http.rb: entity reading algorithm is better o http.rb: more reply code (4xx, 5xx) o protocol.rb: arguments of "connect" can be omitted o protocol.rb: "quit" is not template method (now do_quit is removed) o protocol.rb: ReplyCode.error_type was not work: using module_eval git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
0dcf7498b1
Коммит
9fd5174ef3
355
lib/net/http.rb
355
lib/net/http.rb
|
@ -58,19 +58,18 @@ class HTTPBadResponse < HTTPError; end
|
|||
|
||||
: post( path, data, header = nil, dest = '' )
|
||||
: post( path, data, header = nil ) {|str| .... }
|
||||
post "data"(must be String now) to "path" (and get entity body).
|
||||
post "data"(must be String now) to "path".
|
||||
If body exists, also get entity body.
|
||||
It is written to "dest" by using "<<" method.
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
Data is written to "dest" by using "<<" method.
|
||||
This method returns response header (Hash) and "dest".
|
||||
|
||||
If called as iterator, give a part String of entity body.
|
||||
If called as iterator, gives a part String of entity body.
|
||||
|
||||
ATTENTION: entity body could be empty
|
||||
|
||||
: get2( path, header = nil )
|
||||
: get2( path, header = nil ) {|writer| .... }
|
||||
send GET request for "path".
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
This method returns response header (Hash).
|
||||
This method gives HTTPWriter object to block.
|
||||
|
||||
: get_body( dest = '' )
|
||||
: get_body {|str| .... }
|
||||
|
@ -78,7 +77,31 @@ class HTTPBadResponse < HTTPError; end
|
|||
Data is written in "dest" by using "<<" method.
|
||||
This method returns "dest".
|
||||
|
||||
If called as iterator, give a part String of entity body.
|
||||
If called as iterator, gives a part String of entity body.
|
||||
|
||||
: 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.
|
||||
|
||||
|
||||
= class HTTPWriter
|
||||
|
||||
== Methods
|
||||
|
||||
: header
|
||||
HTTP header.
|
||||
|
||||
: response
|
||||
ReplyCode object.
|
||||
|
||||
: entity( dest = '' )
|
||||
: body( dest = '' )
|
||||
entity body.
|
||||
|
||||
: entity {|str| ... }
|
||||
get entity body by using iterator.
|
||||
If this method is called twice, block is not called.
|
||||
|
||||
=end
|
||||
|
||||
|
@ -87,20 +110,24 @@ class HTTPBadResponse < HTTPError; end
|
|||
protocol_param :port, '80'
|
||||
protocol_param :command_type, '::Net::HTTPCommand'
|
||||
|
||||
def HTTP.procdest( dest, block )
|
||||
if block then
|
||||
return ReadAdapter.new( block ), nil
|
||||
else
|
||||
dest ||= ''
|
||||
return dest, dest
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def get( path, u_header = nil, dest = nil, &block )
|
||||
u_header = procheader( u_header )
|
||||
if block then
|
||||
dest = ReadAdapter.new( block )
|
||||
ret = nil
|
||||
else
|
||||
dest = ret = ''
|
||||
end
|
||||
dest, ret = HTTP.procdest( dest, block )
|
||||
resp = nil
|
||||
connecting( u_header ) {
|
||||
@command.get edit_path(path), u_header
|
||||
resp = @command.get_response
|
||||
@command.try_get_body( resp, dest )
|
||||
@command.get_body( resp, dest )
|
||||
}
|
||||
|
||||
return resp['http-header'], ret
|
||||
|
@ -108,67 +135,82 @@ class HTTPBadResponse < HTTPError; end
|
|||
|
||||
def get2( path, u_header = nil )
|
||||
u_header = procheader( u_header )
|
||||
only_header( :get, path, u_header )
|
||||
connecting( u_header ) {
|
||||
@command.get edit_path(path), u_header
|
||||
tmp = HTTPWriter.new( @command )
|
||||
yield tmp
|
||||
tmp.off
|
||||
}
|
||||
end
|
||||
|
||||
=begin c
|
||||
def get_body( dest = '', &block )
|
||||
if block then
|
||||
dest = ReadAdapter.new( block )
|
||||
end
|
||||
@command.try_get_body @response, dest
|
||||
@command.get_body @response, dest
|
||||
ensure_termination @u_header
|
||||
|
||||
dest
|
||||
end
|
||||
=end
|
||||
|
||||
def head( path, u_header = nil )
|
||||
u_header = procheader( u_header )
|
||||
header = only_header( :head, path, u_header )
|
||||
ensure_termination u_header
|
||||
header
|
||||
resp = nil
|
||||
connecting( u_header ) {
|
||||
@command.head( edit_path(path), u_header )
|
||||
resp = @command.get_response_no_body
|
||||
}
|
||||
|
||||
resp['http-header']
|
||||
end
|
||||
|
||||
def post( path, data, u_header = nil, dest = nil, &block )
|
||||
u_header = procheader( u_header )
|
||||
if block then
|
||||
dest = ReadAdapter.new( block )
|
||||
ret = nil
|
||||
else
|
||||
dest = ret = ''
|
||||
end
|
||||
dest, ret = HTTP.procdest( dest, block )
|
||||
resp = nil
|
||||
connecting( u_header, true ) {
|
||||
@command.post path, u_header, data
|
||||
connecting( u_header ) {
|
||||
@command.post edit_path(path), u_header, data
|
||||
resp = @command.get_response
|
||||
@command.try_get_body( resp, dest )
|
||||
@command.get_body( resp, dest )
|
||||
}
|
||||
|
||||
return resp['http-header'], ret
|
||||
end
|
||||
|
||||
def post2( path, data, u_header = {} )
|
||||
def post2( path, data, u_header = nil )
|
||||
u_header = procheader( u_header )
|
||||
only_header :post, path, u_header, data
|
||||
connecting( u_header ) {
|
||||
@command.post edit_path(path), u_header, data
|
||||
tmp = HTTPWriter.new( @command )
|
||||
yield tmp
|
||||
tmp.off
|
||||
}
|
||||
end
|
||||
|
||||
# not tested because I could not setup apache (__;;;
|
||||
def put( path, src = nil, u_header = nil, &block )
|
||||
def put( path, src, u_header = nil )
|
||||
u_header = procheader( u_header )
|
||||
connecting( u_header, true ) {
|
||||
ret = ''
|
||||
connecting( u_header ) {
|
||||
@command.put path, u_header, src, dest
|
||||
resp = @comman.get_response
|
||||
@command.get_body( resp, ret )
|
||||
}
|
||||
|
||||
header
|
||||
return header, ret
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
=begin c
|
||||
def only_header( mid, path, u_header, data = nil )
|
||||
@u_header = u_header
|
||||
@response = nil
|
||||
ensure_connection u_header
|
||||
connecting u_header
|
||||
if data then
|
||||
@command.send mid, edit_path(path), u_header, data
|
||||
else
|
||||
|
@ -177,6 +219,7 @@ class HTTPBadResponse < HTTPError; end
|
|||
@response = @command.get_response
|
||||
@response['http-header']
|
||||
end
|
||||
=end
|
||||
|
||||
|
||||
# called when connecting
|
||||
|
@ -189,19 +232,19 @@ class HTTPBadResponse < HTTPError; end
|
|||
end
|
||||
end
|
||||
|
||||
def connecting( u_header, putp = false )
|
||||
ensure_connection u_header
|
||||
yield
|
||||
ensure_termination u_header
|
||||
end
|
||||
|
||||
def ensure_connection( u_header )
|
||||
def connecting( u_header )
|
||||
if not @socket then
|
||||
u_header['Connection'] = 'Close'
|
||||
start
|
||||
elsif @socket.closed? then
|
||||
@socket.reopen
|
||||
end
|
||||
|
||||
if iterator? then
|
||||
ret = yield
|
||||
ensure_termination u_header
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_termination( u_header )
|
||||
|
@ -258,18 +301,82 @@ class HTTPBadResponse < HTTPError; end
|
|||
HTTPSession = HTTP
|
||||
|
||||
|
||||
class HTTPSuccessCode < SuccessCode; end
|
||||
class HTTPCreatedCode < SuccessCode; end
|
||||
class HTTPAcceptedCode < SuccessCode; end
|
||||
class HTTPNoContentCode < SuccessCode; end
|
||||
class HTTPResetContentCode < SuccessCode; end
|
||||
class HTTPPartialContentCode < SuccessCode; end
|
||||
class HTTPWriter
|
||||
|
||||
class HTTPMultipleChoiceCode < RetryCode; end
|
||||
class HTTPMovedPermanentlyCode < RetryCode; end
|
||||
class HTTPMovedTemporarilyCode < RetryCode; end
|
||||
class HTTPNotModifiedCode < RetryCode; end
|
||||
class HTTPUseProxyCode < RetryCode; end
|
||||
def initialize( command )
|
||||
@command = command
|
||||
@response = @header = @entity = nil
|
||||
end
|
||||
|
||||
def response
|
||||
unless @resp then
|
||||
@resp = @command.get_response
|
||||
end
|
||||
@resp
|
||||
end
|
||||
|
||||
def header
|
||||
unless @header then
|
||||
@header = response['http-header']
|
||||
end
|
||||
@header
|
||||
end
|
||||
|
||||
def entity( dest = nil, &block )
|
||||
dest, ret = HTTP.procdest( dest, block )
|
||||
unless @entity then
|
||||
@entity = @command.get_body( response, dest )
|
||||
end
|
||||
@entity
|
||||
end
|
||||
alias body entity
|
||||
|
||||
def off
|
||||
entity
|
||||
@command = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class HTTPSwitchProtocol < SuccessCode; end
|
||||
|
||||
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
|
||||
|
||||
class HTTPMultipleChoice < RetryCode; end
|
||||
class HTTPMovedPermanently < RetryCode; end
|
||||
class HTTPMovedTemporarily < RetryCode; end
|
||||
class HTTPNotModified < RetryCode; end
|
||||
class HTTPUseProxy < RetryCode; end
|
||||
|
||||
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
|
||||
|
||||
class HTTPNotImplemented < FatalErrorCode; end
|
||||
class HTTPBadGateway < FatalErrorCode; end
|
||||
class HTTPServiceUnavailable < FatalErrorCode; end
|
||||
class HTTPGatewayTimeOut < FatalErrorCode; end
|
||||
class HTTPVersionNotSupported < FatalErrorCode; end
|
||||
|
||||
|
||||
class HTTPCommand < Command
|
||||
|
@ -292,30 +399,36 @@ class HTTPBadResponse < HTTPError; end
|
|||
|
||||
|
||||
def get( path, u_header )
|
||||
return unless begin_critical
|
||||
request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
|
||||
end
|
||||
|
||||
def head( path, u_header )
|
||||
return unless begin_critical
|
||||
request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
|
||||
end
|
||||
|
||||
def post( path, u_header, data )
|
||||
return unless begin_critical
|
||||
request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
|
||||
@socket.write data
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
# def delete
|
||||
|
||||
# def trace
|
||||
|
||||
# def options
|
||||
|
||||
def quit
|
||||
end
|
||||
|
||||
|
||||
def get_response
|
||||
rep = get_reply
|
||||
|
@ -327,35 +440,47 @@ class HTTPBadResponse < HTTPError; end
|
|||
nm = /\A[^:]+/.match( line )[0].strip.downcase
|
||||
header[nm] = line
|
||||
end
|
||||
|
||||
rep['http-header'] = header
|
||||
reply_must rep, SuccessCode
|
||||
|
||||
rep
|
||||
end
|
||||
|
||||
def get_body( rep, dest )
|
||||
header = rep['http-header']
|
||||
if chunked? header then
|
||||
read_chunked( dest, header )
|
||||
else
|
||||
if clen = content_length( header ) then
|
||||
@socket.read clen, dest
|
||||
else
|
||||
##### "multipart/byteranges" check should be done here ...
|
||||
|
||||
# now, length is designated by closing socket
|
||||
@socket.read_all dest
|
||||
@socket.close
|
||||
end
|
||||
end
|
||||
def check_response( resp )
|
||||
reply_must resp, SuccessCode
|
||||
end
|
||||
|
||||
def try_get_body( rep, dest )
|
||||
rep = get_reply while ContinueCode === rep
|
||||
return nil unless rep['body-exist']
|
||||
def get_body( rep, dest )
|
||||
header = rep['http-header']
|
||||
|
||||
get_body rep, dest
|
||||
if rep['body-exist'] then
|
||||
if chunked? header then
|
||||
read_chunked( dest, header )
|
||||
else
|
||||
if clen = content_length( header ) then
|
||||
@socket.read clen, dest
|
||||
else
|
||||
if false then # "multipart/byteranges" check should be done
|
||||
else
|
||||
if header['Connection'] and
|
||||
/connection:\s*close/i === header['Connection'] then
|
||||
@socket.read_all dest
|
||||
@socket.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end_critical
|
||||
reply_must rep, SuccessCode
|
||||
|
||||
dest
|
||||
end
|
||||
|
||||
def get_response_no_body
|
||||
resp = get_response
|
||||
end_critical
|
||||
reply_must resp, SuccessCode
|
||||
resp
|
||||
end
|
||||
|
||||
|
||||
|
@ -376,6 +501,50 @@ class HTTPBadResponse < HTTPError; end
|
|||
end
|
||||
|
||||
|
||||
CODE_TO_CLASS = {
|
||||
'100' => [ContinueCode, false],
|
||||
'100' => [HTTPSwitchProtocol, false],
|
||||
|
||||
'200' => [HTTPOK, true],
|
||||
'201' => [HTTPCreated, true],
|
||||
'202' => [HTTPAccepted, true],
|
||||
'203' => [HTTPNonAuthoritativeInformation, true],
|
||||
'204' => [HTTPNoContent, false],
|
||||
'205' => [HTTPResetContent, false],
|
||||
'206' => [HTTPPartialContent, true],
|
||||
|
||||
'300' => [HTTPMultipleChoice, true],
|
||||
'301' => [HTTPMovedPermanently, true],
|
||||
'302' => [HTTPMovedTemporarily, true],
|
||||
'303' => [HTTPMovedPermanently, true],
|
||||
'304' => [HTTPNotModified, false],
|
||||
'305' => [HTTPUseProxy, false],
|
||||
|
||||
'400' => [HTTPBadRequest, true],
|
||||
'401' => [HTTPUnauthorized, true],
|
||||
'402' => [HTTPPaymentRequired, true],
|
||||
'403' => [HTTPForbidden, true],
|
||||
'404' => [HTTPNotFound, true],
|
||||
'405' => [HTTPMethodNotAllowed, true],
|
||||
'406' => [HTTPNotAcceptable, true],
|
||||
'407' => [HTTPProxyAuthenticationRequired, true],
|
||||
'408' => [HTTPRequestTimeOut, true],
|
||||
'409' => [HTTPConflict, true],
|
||||
'410' => [HTTPGone, true],
|
||||
'411' => [FatalErrorCode, true],
|
||||
'412' => [HTTPPreconditionFailed, true],
|
||||
'413' => [HTTPRequestEntityTooLarge, true],
|
||||
'414' => [HTTPRequestURITooLarge, true],
|
||||
'415' => [HTTPUnsupportedMediaType, true],
|
||||
|
||||
'500' => [FatalErrorCode, true],
|
||||
'501' => [HTTPNotImplemented, true],
|
||||
'502' => [HTTPBadGateway, true],
|
||||
'503' => [HTTPServiceUnavailable, true],
|
||||
'504' => [HTTPGatewayTimeOut, true],
|
||||
'505' => [HTTPVersionNotSupported, true]
|
||||
}
|
||||
|
||||
def get_reply
|
||||
str = @socket.readline
|
||||
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
|
||||
|
@ -385,41 +554,9 @@ class HTTPBadResponse < HTTPError; end
|
|||
status = $2
|
||||
discrip = $3
|
||||
|
||||
be = false
|
||||
klass = case status[0]
|
||||
when ?1 then
|
||||
case status[2]
|
||||
when ?0 then ContinueCode
|
||||
when ?1 then HTTPSuccessCode
|
||||
else UnknownCode
|
||||
end
|
||||
when ?2 then
|
||||
case status[2]
|
||||
when ?0 then be = true; HTTPSuccessCode
|
||||
when ?1 then be = false; HTTPSuccessCode
|
||||
when ?2 then be = true; HTTPSuccessCode
|
||||
when ?3 then be = true; HTTPSuccessCode
|
||||
when ?4 then be = false; HTTPNoContentCode
|
||||
when ?5 then be = false; HTTPResetContentCode
|
||||
when ?6 then be = true; HTTPPartialContentCode
|
||||
else UnknownCode
|
||||
end
|
||||
when ?3 then
|
||||
case status[2]
|
||||
when ?0 then be = true; HTTPMultipleChoiceCode
|
||||
when ?1 then be = true; HTTPMovedPermanentryCode
|
||||
when ?2 then be = true; HTTPMovedTemporarilyCode
|
||||
when ?3 then be = true; HTTPMovedPermanentryCode
|
||||
when ?4 then be = false; HTTPNotModifiedCode
|
||||
when ?5 then be = false; HTTPUseProxyCode
|
||||
else UnknownCode
|
||||
end
|
||||
when ?4 then ServerBusyCode
|
||||
when ?5 then FatalErrorCode
|
||||
else UnknownCode
|
||||
end
|
||||
klass, bodyexist = CODE_TO_CLASS[status] || [UnknownCode, true]
|
||||
code = klass.new( status, discrip )
|
||||
code['body-exist'] = be
|
||||
code['body-exist'] = bodyexist
|
||||
code
|
||||
end
|
||||
|
||||
|
|
|
@ -71,8 +71,9 @@ Net::Protocol
|
|||
|
||||
def do_start( acnt, pwd )
|
||||
@command.auth( acnt, pwd )
|
||||
t = self.type.mail_type
|
||||
|
||||
@mails = []
|
||||
t = type.mail_type
|
||||
@command.list.each_with_index do |size,idx|
|
||||
if size then
|
||||
@mails.push t.new( idx, size, @command )
|
||||
|
@ -221,72 +222,83 @@ Net::POP3
|
|||
|
||||
def initialize( sock )
|
||||
super
|
||||
check_reply SuccessCode
|
||||
critical {
|
||||
check_reply SuccessCode
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def auth( acnt, pass )
|
||||
@socket.writeline 'USER ' + acnt
|
||||
check_reply_auth
|
||||
critical {
|
||||
@socket.writeline 'USER ' + acnt
|
||||
check_reply_auth
|
||||
|
||||
@socket.writeline( 'PASS ' + pass )
|
||||
ret = check_reply_auth
|
||||
|
||||
return ret
|
||||
@socket.writeline 'PASS ' + pass
|
||||
check_reply_auth
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def list
|
||||
getok 'LIST'
|
||||
|
||||
arr = []
|
||||
@socket.read_pendlist do |line|
|
||||
num, siz = line.split( / +/o )
|
||||
arr[ num.to_i ] = siz.to_i
|
||||
end
|
||||
|
||||
return arr
|
||||
critical {
|
||||
getok 'LIST'
|
||||
@socket.read_pendlist do |line|
|
||||
num, siz = line.split( / +/o )
|
||||
arr[ num.to_i ] = siz.to_i
|
||||
end
|
||||
}
|
||||
arr
|
||||
end
|
||||
|
||||
|
||||
def rset
|
||||
getok 'RSET'
|
||||
critical {
|
||||
getok 'RSET'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def top( num, lines = 0, dest = '' )
|
||||
getok sprintf( 'TOP %d %d', num, lines )
|
||||
@socket.read_pendstr( dest )
|
||||
critical {
|
||||
getok sprintf( 'TOP %d %d', num, lines )
|
||||
@socket.read_pendstr( dest )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def retr( num, dest = '', &block )
|
||||
getok sprintf( 'RETR %d', num )
|
||||
@socket.read_pendstr( dest, &block )
|
||||
critical {
|
||||
getok sprintf( 'RETR %d', num )
|
||||
@socket.read_pendstr( dest, &block )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def dele( num )
|
||||
getok sprintf( 'DELE %d', num )
|
||||
critical {
|
||||
getok sprintf( 'DELE %d', num )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def uidl( num )
|
||||
rep = getok( sprintf 'UIDL %d', num )
|
||||
uid = rep.msg.split(' ')[1]
|
||||
critical {
|
||||
getok( sprintf 'UIDL %d', num ).msg.split(' ')[1]
|
||||
}
|
||||
end
|
||||
|
||||
uid
|
||||
|
||||
def quit
|
||||
critical {
|
||||
getok 'QUIT'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def do_quit
|
||||
getok 'QUIT'
|
||||
end
|
||||
|
||||
|
||||
def check_reply_auth
|
||||
begin
|
||||
cod = check_reply( SuccessCode )
|
||||
|
@ -326,19 +338,17 @@ Net::POP3
|
|||
|
||||
|
||||
def auth( acnt, pass )
|
||||
@socket.writeline( "APOP #{acnt} #{digest(@stamp + pass)}" )
|
||||
return check_reply_auth
|
||||
critical {
|
||||
@socket.writeline( "APOP #{acnt} #{digest(@stamp + pass)}" )
|
||||
check_reply_auth
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def digest( str )
|
||||
temp = MD5.new( str ).digest
|
||||
|
||||
ret = ''
|
||||
temp.each_byte do |i|
|
||||
ret << sprintf( '%02x', i )
|
||||
end
|
||||
return ret
|
||||
MD5.new( str ).digest.each_byte {|i| ret << sprintf('%02x', i) }
|
||||
ret
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@ require 'socket'
|
|||
|
||||
module Net
|
||||
|
||||
Version = '1.1.10'
|
||||
Version = '1.1.11'
|
||||
|
||||
=begin
|
||||
|
||||
|
@ -144,7 +144,7 @@ Object
|
|||
|
||||
def initialize( addr = nil, port = nil )
|
||||
@address = addr || 'localhost'
|
||||
@port = port || self.type.port
|
||||
@port = port || type.port
|
||||
|
||||
@active = false
|
||||
@pipe = nil
|
||||
|
@ -160,11 +160,11 @@ Object
|
|||
|
||||
def start( *args )
|
||||
return false if active?
|
||||
@active = true
|
||||
|
||||
begin
|
||||
connect @address, @port
|
||||
connect
|
||||
do_start *args
|
||||
@active = true
|
||||
yield if iterator?
|
||||
ensure
|
||||
finish if iterator?
|
||||
|
@ -174,7 +174,7 @@ Object
|
|||
def finish
|
||||
ret = active?
|
||||
|
||||
do_finish if @command
|
||||
do_finish
|
||||
disconnect
|
||||
@active = false
|
||||
|
||||
|
@ -201,9 +201,9 @@ Object
|
|||
end
|
||||
|
||||
|
||||
def connect( addr, port )
|
||||
@socket = self.type.socket_type.open( addr, port, @pipe )
|
||||
@command = self.type.command_type.new( @socket )
|
||||
def connect( addr = @address, port = @port )
|
||||
@socket = type.socket_type.open( addr, port, @pipe )
|
||||
@command = type.command_type.new( @socket )
|
||||
end
|
||||
|
||||
def disconnect
|
||||
|
@ -213,7 +213,7 @@ Object
|
|||
end
|
||||
@socket = nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
Session = Protocol
|
||||
|
@ -226,24 +226,17 @@ Object
|
|||
@socket = sock
|
||||
@error_occured = false
|
||||
@last_reply = nil
|
||||
@critical = false
|
||||
end
|
||||
|
||||
attr_reader :socket, :error_occured, :last_reply
|
||||
attr_writer :socket
|
||||
|
||||
def quit
|
||||
if @socket and not @socket.closed? then
|
||||
do_quit
|
||||
@error_occured = false
|
||||
end
|
||||
end
|
||||
# abstract quit
|
||||
|
||||
|
||||
private
|
||||
|
||||
def do_quit
|
||||
end
|
||||
|
||||
# abstract get_reply()
|
||||
|
||||
def check_reply( *oks )
|
||||
|
@ -266,7 +259,30 @@ Object
|
|||
@socket.writeline line
|
||||
check_reply ok
|
||||
end
|
||||
|
||||
|
||||
|
||||
def critical
|
||||
return if @critical
|
||||
@critical = true
|
||||
r = yield
|
||||
@critical = false
|
||||
r
|
||||
end
|
||||
|
||||
def critical?
|
||||
@critical
|
||||
end
|
||||
|
||||
def begin_critical
|
||||
ret = @critical
|
||||
@critical = true
|
||||
not ret
|
||||
end
|
||||
|
||||
def end_critical
|
||||
@critical = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -284,11 +300,11 @@ Object
|
|||
class << self
|
||||
|
||||
def error_type( err )
|
||||
@err = err
|
||||
module_eval "def self.get_error_type() #{err.name} end"
|
||||
end
|
||||
|
||||
def error!( mes )
|
||||
raise @err, mes
|
||||
raise get_error_type, mes
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -121,33 +121,44 @@ Net::Protocol
|
|||
|
||||
def initialize( sock )
|
||||
super
|
||||
check_reply SuccessCode
|
||||
critical {
|
||||
check_reply SuccessCode
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def helo( fromdom )
|
||||
getok sprintf( 'HELO %s', fromdom )
|
||||
critical {
|
||||
getok sprintf( 'HELO %s', fromdom )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def ehlo( fromdom )
|
||||
getok sprintf( 'EHLO %s', fromdom )
|
||||
critical {
|
||||
getok sprintf( 'EHLO %s', fromdom )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def mailfrom( fromaddr )
|
||||
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
||||
critical {
|
||||
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def rcpt( toaddrs )
|
||||
toaddrs.each do |i|
|
||||
getok sprintf( 'RCPT TO:<%s>', i )
|
||||
critical {
|
||||
getok sprintf( 'RCPT TO:<%s>', i )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def data
|
||||
return unless begin_critical
|
||||
getok 'DATA', ContinueCode
|
||||
end
|
||||
|
||||
|
@ -155,18 +166,21 @@ Net::Protocol
|
|||
def write_mail( mailsrc = nil, &block )
|
||||
@socket.write_pendstr mailsrc, &block
|
||||
check_reply SuccessCode
|
||||
end_critical
|
||||
end
|
||||
alias sendmail write_mail
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def do_quit
|
||||
getok 'QUIT'
|
||||
def quit
|
||||
critical {
|
||||
getok 'QUIT'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def get_reply
|
||||
arr = read_reply
|
||||
stat = arr[0][0,3]
|
||||
|
|
Загрузка…
Ссылка в новой задаче