mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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:
parent
0dcf7498b1
commit
9fd5174ef3
4 changed files with 355 additions and 178 deletions
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, dest = '' )
|
||||||
: post( path, data, header = nil ) {|str| .... }
|
: 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' => '*/*', ... }.
|
"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 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 ) {|writer| .... }
|
||||||
|
|
||||||
: get2( path, header = nil )
|
|
||||||
send GET request for "path".
|
send GET request for "path".
|
||||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
"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( dest = '' )
|
||||||
: get_body {|str| .... }
|
: get_body {|str| .... }
|
||||||
|
@ -78,7 +77,31 @@ class HTTPBadResponse < HTTPError; end
|
||||||
Data is written in "dest" by using "<<" method.
|
Data is written in "dest" by using "<<" method.
|
||||||
This method returns "dest".
|
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
|
=end
|
||||||
|
|
||||||
|
@ -87,20 +110,24 @@ class HTTPBadResponse < HTTPError; end
|
||||||
protocol_param :port, '80'
|
protocol_param :port, '80'
|
||||||
protocol_param :command_type, '::Net::HTTPCommand'
|
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 )
|
def get( path, u_header = nil, dest = nil, &block )
|
||||||
u_header = procheader( u_header )
|
u_header = procheader( u_header )
|
||||||
if block then
|
dest, ret = HTTP.procdest( dest, block )
|
||||||
dest = ReadAdapter.new( block )
|
|
||||||
ret = nil
|
|
||||||
else
|
|
||||||
dest = ret = ''
|
|
||||||
end
|
|
||||||
resp = nil
|
resp = nil
|
||||||
connecting( u_header ) {
|
connecting( u_header ) {
|
||||||
@command.get edit_path(path), u_header
|
@command.get edit_path(path), u_header
|
||||||
resp = @command.get_response
|
resp = @command.get_response
|
||||||
@command.try_get_body( resp, dest )
|
@command.get_body( resp, dest )
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp['http-header'], ret
|
return resp['http-header'], ret
|
||||||
|
@ -108,67 +135,82 @@ class HTTPBadResponse < HTTPError; end
|
||||||
|
|
||||||
def get2( path, u_header = nil )
|
def get2( path, u_header = nil )
|
||||||
u_header = procheader( u_header )
|
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
|
end
|
||||||
|
|
||||||
|
=begin c
|
||||||
def get_body( dest = '', &block )
|
def get_body( dest = '', &block )
|
||||||
if block then
|
if block then
|
||||||
dest = ReadAdapter.new( block )
|
dest = ReadAdapter.new( block )
|
||||||
end
|
end
|
||||||
@command.try_get_body @response, dest
|
@command.get_body @response, dest
|
||||||
ensure_termination @u_header
|
ensure_termination @u_header
|
||||||
|
|
||||||
dest
|
dest
|
||||||
end
|
end
|
||||||
|
=end
|
||||||
|
|
||||||
def head( path, u_header = nil )
|
def head( path, u_header = nil )
|
||||||
u_header = procheader( u_header )
|
u_header = procheader( u_header )
|
||||||
header = only_header( :head, path, u_header )
|
resp = nil
|
||||||
ensure_termination u_header
|
connecting( u_header ) {
|
||||||
header
|
@command.head( edit_path(path), u_header )
|
||||||
|
resp = @command.get_response_no_body
|
||||||
|
}
|
||||||
|
|
||||||
|
resp['http-header']
|
||||||
end
|
end
|
||||||
|
|
||||||
def post( path, data, u_header = nil, dest = nil, &block )
|
def post( path, data, u_header = nil, dest = nil, &block )
|
||||||
u_header = procheader( u_header )
|
u_header = procheader( u_header )
|
||||||
if block then
|
dest, ret = HTTP.procdest( dest, block )
|
||||||
dest = ReadAdapter.new( block )
|
|
||||||
ret = nil
|
|
||||||
else
|
|
||||||
dest = ret = ''
|
|
||||||
end
|
|
||||||
resp = nil
|
resp = nil
|
||||||
connecting( u_header, true ) {
|
connecting( u_header ) {
|
||||||
@command.post path, u_header, data
|
@command.post edit_path(path), u_header, data
|
||||||
resp = @command.get_response
|
resp = @command.get_response
|
||||||
@command.try_get_body( resp, dest )
|
@command.get_body( resp, dest )
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp['http-header'], ret
|
return resp['http-header'], ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def post2( path, data, u_header = {} )
|
def post2( path, data, u_header = nil )
|
||||||
u_header = procheader( u_header )
|
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
|
end
|
||||||
|
|
||||||
# not tested because I could not setup apache (__;;;
|
# 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 )
|
u_header = procheader( u_header )
|
||||||
connecting( u_header, true ) {
|
ret = ''
|
||||||
|
connecting( u_header ) {
|
||||||
@command.put path, u_header, src, dest
|
@command.put path, u_header, src, dest
|
||||||
|
resp = @comman.get_response
|
||||||
|
@command.get_body( resp, ret )
|
||||||
}
|
}
|
||||||
|
|
||||||
header
|
return header, ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
|
=begin c
|
||||||
def only_header( mid, path, u_header, data = nil )
|
def only_header( mid, path, u_header, data = nil )
|
||||||
@u_header = u_header
|
@u_header = u_header
|
||||||
@response = nil
|
@response = nil
|
||||||
ensure_connection u_header
|
connecting u_header
|
||||||
if data then
|
if data then
|
||||||
@command.send mid, edit_path(path), u_header, data
|
@command.send mid, edit_path(path), u_header, data
|
||||||
else
|
else
|
||||||
|
@ -177,6 +219,7 @@ class HTTPBadResponse < HTTPError; end
|
||||||
@response = @command.get_response
|
@response = @command.get_response
|
||||||
@response['http-header']
|
@response['http-header']
|
||||||
end
|
end
|
||||||
|
=end
|
||||||
|
|
||||||
|
|
||||||
# called when connecting
|
# called when connecting
|
||||||
|
@ -189,19 +232,19 @@ class HTTPBadResponse < HTTPError; end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def connecting( u_header, putp = false )
|
def connecting( u_header )
|
||||||
ensure_connection u_header
|
|
||||||
yield
|
|
||||||
ensure_termination u_header
|
|
||||||
end
|
|
||||||
|
|
||||||
def ensure_connection( u_header )
|
|
||||||
if not @socket then
|
if not @socket then
|
||||||
u_header['Connection'] = 'Close'
|
u_header['Connection'] = 'Close'
|
||||||
start
|
start
|
||||||
elsif @socket.closed? then
|
elsif @socket.closed? then
|
||||||
@socket.reopen
|
@socket.reopen
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if iterator? then
|
||||||
|
ret = yield
|
||||||
|
ensure_termination u_header
|
||||||
|
ret
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_termination( u_header )
|
def ensure_termination( u_header )
|
||||||
|
@ -258,18 +301,82 @@ class HTTPBadResponse < HTTPError; end
|
||||||
HTTPSession = HTTP
|
HTTPSession = HTTP
|
||||||
|
|
||||||
|
|
||||||
class HTTPSuccessCode < SuccessCode; end
|
class HTTPWriter
|
||||||
class HTTPCreatedCode < SuccessCode; end
|
|
||||||
class HTTPAcceptedCode < SuccessCode; end
|
|
||||||
class HTTPNoContentCode < SuccessCode; end
|
|
||||||
class HTTPResetContentCode < SuccessCode; end
|
|
||||||
class HTTPPartialContentCode < SuccessCode; end
|
|
||||||
|
|
||||||
class HTTPMultipleChoiceCode < RetryCode; end
|
def initialize( command )
|
||||||
class HTTPMovedPermanentlyCode < RetryCode; end
|
@command = command
|
||||||
class HTTPMovedTemporarilyCode < RetryCode; end
|
@response = @header = @entity = nil
|
||||||
class HTTPNotModifiedCode < RetryCode; end
|
end
|
||||||
class HTTPUseProxyCode < RetryCode; 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
|
class HTTPCommand < Command
|
||||||
|
@ -292,30 +399,36 @@ class HTTPBadResponse < HTTPError; end
|
||||||
|
|
||||||
|
|
||||||
def get( path, u_header )
|
def get( path, u_header )
|
||||||
|
return unless begin_critical
|
||||||
request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
|
request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
end
|
end
|
||||||
|
|
||||||
def head( path, u_header )
|
def head( path, u_header )
|
||||||
|
return unless begin_critical
|
||||||
request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
|
request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
end
|
end
|
||||||
|
|
||||||
def post( path, u_header, data )
|
def post( path, u_header, data )
|
||||||
|
return unless begin_critical
|
||||||
request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
|
request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
@socket.write data
|
@socket.write data
|
||||||
end
|
end
|
||||||
|
|
||||||
def put( path, u_header, src )
|
def put( path, u_header, src )
|
||||||
|
return unless begin_critical
|
||||||
request sprintf('PUT %s HTTP/%s', path, HTTPVersion), u_header
|
request sprintf('PUT %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
@socket.write_bin src
|
@socket.write_bin src
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# def delete
|
# def delete
|
||||||
|
|
||||||
# def trace
|
# def trace
|
||||||
|
|
||||||
# def options
|
# def options
|
||||||
|
|
||||||
|
def quit
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def get_response
|
def get_response
|
||||||
rep = get_reply
|
rep = get_reply
|
||||||
|
@ -327,35 +440,47 @@ class HTTPBadResponse < HTTPError; end
|
||||||
nm = /\A[^:]+/.match( line )[0].strip.downcase
|
nm = /\A[^:]+/.match( line )[0].strip.downcase
|
||||||
header[nm] = line
|
header[nm] = line
|
||||||
end
|
end
|
||||||
|
|
||||||
rep['http-header'] = header
|
rep['http-header'] = header
|
||||||
reply_must rep, SuccessCode
|
|
||||||
|
|
||||||
rep
|
rep
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_body( rep, dest )
|
def check_response( resp )
|
||||||
header = rep['http-header']
|
reply_must resp, SuccessCode
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def try_get_body( rep, dest )
|
def get_body( rep, dest )
|
||||||
rep = get_reply while ContinueCode === rep
|
header = rep['http-header']
|
||||||
return nil unless rep['body-exist']
|
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -376,6 +501,50 @@ class HTTPBadResponse < HTTPError; end
|
||||||
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
|
def get_reply
|
||||||
str = @socket.readline
|
str = @socket.readline
|
||||||
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
|
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
|
||||||
|
@ -385,41 +554,9 @@ class HTTPBadResponse < HTTPError; end
|
||||||
status = $2
|
status = $2
|
||||||
discrip = $3
|
discrip = $3
|
||||||
|
|
||||||
be = false
|
klass, bodyexist = CODE_TO_CLASS[status] || [UnknownCode, true]
|
||||||
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
|
|
||||||
code = klass.new( status, discrip )
|
code = klass.new( status, discrip )
|
||||||
code['body-exist'] = be
|
code['body-exist'] = bodyexist
|
||||||
code
|
code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,9 @@ Net::Protocol
|
||||||
|
|
||||||
def do_start( acnt, pwd )
|
def do_start( acnt, pwd )
|
||||||
@command.auth( acnt, pwd )
|
@command.auth( acnt, pwd )
|
||||||
t = self.type.mail_type
|
|
||||||
@mails = []
|
@mails = []
|
||||||
|
t = type.mail_type
|
||||||
@command.list.each_with_index do |size,idx|
|
@command.list.each_with_index do |size,idx|
|
||||||
if size then
|
if size then
|
||||||
@mails.push t.new( idx, size, @command )
|
@mails.push t.new( idx, size, @command )
|
||||||
|
@ -221,72 +222,83 @@ Net::POP3
|
||||||
|
|
||||||
def initialize( sock )
|
def initialize( sock )
|
||||||
super
|
super
|
||||||
check_reply SuccessCode
|
critical {
|
||||||
|
check_reply SuccessCode
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def auth( acnt, pass )
|
def auth( acnt, pass )
|
||||||
@socket.writeline 'USER ' + acnt
|
critical {
|
||||||
check_reply_auth
|
@socket.writeline 'USER ' + acnt
|
||||||
|
check_reply_auth
|
||||||
|
|
||||||
@socket.writeline( 'PASS ' + pass )
|
@socket.writeline 'PASS ' + pass
|
||||||
ret = check_reply_auth
|
check_reply_auth
|
||||||
|
}
|
||||||
return ret
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def list
|
def list
|
||||||
getok 'LIST'
|
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
@socket.read_pendlist do |line|
|
critical {
|
||||||
num, siz = line.split( / +/o )
|
getok 'LIST'
|
||||||
arr[ num.to_i ] = siz.to_i
|
@socket.read_pendlist do |line|
|
||||||
end
|
num, siz = line.split( / +/o )
|
||||||
|
arr[ num.to_i ] = siz.to_i
|
||||||
return arr
|
end
|
||||||
|
}
|
||||||
|
arr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def rset
|
def rset
|
||||||
getok 'RSET'
|
critical {
|
||||||
|
getok 'RSET'
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def top( num, lines = 0, dest = '' )
|
def top( num, lines = 0, dest = '' )
|
||||||
getok sprintf( 'TOP %d %d', num, lines )
|
critical {
|
||||||
@socket.read_pendstr( dest )
|
getok sprintf( 'TOP %d %d', num, lines )
|
||||||
|
@socket.read_pendstr( dest )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def retr( num, dest = '', &block )
|
def retr( num, dest = '', &block )
|
||||||
getok sprintf( 'RETR %d', num )
|
critical {
|
||||||
@socket.read_pendstr( dest, &block )
|
getok sprintf( 'RETR %d', num )
|
||||||
|
@socket.read_pendstr( dest, &block )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def dele( num )
|
def dele( num )
|
||||||
getok sprintf( 'DELE %d', num )
|
critical {
|
||||||
|
getok sprintf( 'DELE %d', num )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def uidl( num )
|
def uidl( num )
|
||||||
rep = getok( sprintf 'UIDL %d', num )
|
critical {
|
||||||
uid = rep.msg.split(' ')[1]
|
getok( sprintf 'UIDL %d', num ).msg.split(' ')[1]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
uid
|
|
||||||
|
def quit
|
||||||
|
critical {
|
||||||
|
getok 'QUIT'
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
def do_quit
|
|
||||||
getok 'QUIT'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def check_reply_auth
|
def check_reply_auth
|
||||||
begin
|
begin
|
||||||
cod = check_reply( SuccessCode )
|
cod = check_reply( SuccessCode )
|
||||||
|
@ -326,19 +338,17 @@ Net::POP3
|
||||||
|
|
||||||
|
|
||||||
def auth( acnt, pass )
|
def auth( acnt, pass )
|
||||||
@socket.writeline( "APOP #{acnt} #{digest(@stamp + pass)}" )
|
critical {
|
||||||
return check_reply_auth
|
@socket.writeline( "APOP #{acnt} #{digest(@stamp + pass)}" )
|
||||||
|
check_reply_auth
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def digest( str )
|
def digest( str )
|
||||||
temp = MD5.new( str ).digest
|
|
||||||
|
|
||||||
ret = ''
|
ret = ''
|
||||||
temp.each_byte do |i|
|
MD5.new( str ).digest.each_byte {|i| ret << sprintf('%02x', i) }
|
||||||
ret << sprintf( '%02x', i )
|
ret
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@ require 'socket'
|
||||||
|
|
||||||
module Net
|
module Net
|
||||||
|
|
||||||
Version = '1.1.10'
|
Version = '1.1.11'
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ Object
|
||||||
|
|
||||||
def initialize( addr = nil, port = nil )
|
def initialize( addr = nil, port = nil )
|
||||||
@address = addr || 'localhost'
|
@address = addr || 'localhost'
|
||||||
@port = port || self.type.port
|
@port = port || type.port
|
||||||
|
|
||||||
@active = false
|
@active = false
|
||||||
@pipe = nil
|
@pipe = nil
|
||||||
|
@ -160,11 +160,11 @@ Object
|
||||||
|
|
||||||
def start( *args )
|
def start( *args )
|
||||||
return false if active?
|
return false if active?
|
||||||
@active = true
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
connect @address, @port
|
connect
|
||||||
do_start *args
|
do_start *args
|
||||||
|
@active = true
|
||||||
yield if iterator?
|
yield if iterator?
|
||||||
ensure
|
ensure
|
||||||
finish if iterator?
|
finish if iterator?
|
||||||
|
@ -174,7 +174,7 @@ Object
|
||||||
def finish
|
def finish
|
||||||
ret = active?
|
ret = active?
|
||||||
|
|
||||||
do_finish if @command
|
do_finish
|
||||||
disconnect
|
disconnect
|
||||||
@active = false
|
@active = false
|
||||||
|
|
||||||
|
@ -201,9 +201,9 @@ Object
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def connect( addr, port )
|
def connect( addr = @address, port = @port )
|
||||||
@socket = self.type.socket_type.open( addr, port, @pipe )
|
@socket = type.socket_type.open( addr, port, @pipe )
|
||||||
@command = self.type.command_type.new( @socket )
|
@command = type.command_type.new( @socket )
|
||||||
end
|
end
|
||||||
|
|
||||||
def disconnect
|
def disconnect
|
||||||
|
@ -213,7 +213,7 @@ Object
|
||||||
end
|
end
|
||||||
@socket = nil
|
@socket = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Session = Protocol
|
Session = Protocol
|
||||||
|
@ -226,24 +226,17 @@ Object
|
||||||
@socket = sock
|
@socket = sock
|
||||||
@error_occured = false
|
@error_occured = false
|
||||||
@last_reply = nil
|
@last_reply = nil
|
||||||
|
@critical = false
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :socket, :error_occured, :last_reply
|
attr_reader :socket, :error_occured, :last_reply
|
||||||
attr_writer :socket
|
attr_writer :socket
|
||||||
|
|
||||||
def quit
|
# abstract quit
|
||||||
if @socket and not @socket.closed? then
|
|
||||||
do_quit
|
|
||||||
@error_occured = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def do_quit
|
|
||||||
end
|
|
||||||
|
|
||||||
# abstract get_reply()
|
# abstract get_reply()
|
||||||
|
|
||||||
def check_reply( *oks )
|
def check_reply( *oks )
|
||||||
|
@ -266,7 +259,30 @@ Object
|
||||||
@socket.writeline line
|
@socket.writeline line
|
||||||
check_reply ok
|
check_reply ok
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -284,11 +300,11 @@ Object
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
def error_type( err )
|
def error_type( err )
|
||||||
@err = err
|
module_eval "def self.get_error_type() #{err.name} end"
|
||||||
end
|
end
|
||||||
|
|
||||||
def error!( mes )
|
def error!( mes )
|
||||||
raise @err, mes
|
raise get_error_type, mes
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -121,33 +121,44 @@ Net::Protocol
|
||||||
|
|
||||||
def initialize( sock )
|
def initialize( sock )
|
||||||
super
|
super
|
||||||
check_reply SuccessCode
|
critical {
|
||||||
|
check_reply SuccessCode
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def helo( fromdom )
|
def helo( fromdom )
|
||||||
getok sprintf( 'HELO %s', fromdom )
|
critical {
|
||||||
|
getok sprintf( 'HELO %s', fromdom )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def ehlo( fromdom )
|
def ehlo( fromdom )
|
||||||
getok sprintf( 'EHLO %s', fromdom )
|
critical {
|
||||||
|
getok sprintf( 'EHLO %s', fromdom )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def mailfrom( fromaddr )
|
def mailfrom( fromaddr )
|
||||||
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
critical {
|
||||||
|
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def rcpt( toaddrs )
|
def rcpt( toaddrs )
|
||||||
toaddrs.each do |i|
|
toaddrs.each do |i|
|
||||||
getok sprintf( 'RCPT TO:<%s>', i )
|
critical {
|
||||||
|
getok sprintf( 'RCPT TO:<%s>', i )
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def data
|
def data
|
||||||
|
return unless begin_critical
|
||||||
getok 'DATA', ContinueCode
|
getok 'DATA', ContinueCode
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -155,18 +166,21 @@ Net::Protocol
|
||||||
def write_mail( mailsrc = nil, &block )
|
def write_mail( mailsrc = nil, &block )
|
||||||
@socket.write_pendstr mailsrc, &block
|
@socket.write_pendstr mailsrc, &block
|
||||||
check_reply SuccessCode
|
check_reply SuccessCode
|
||||||
|
end_critical
|
||||||
end
|
end
|
||||||
alias sendmail write_mail
|
alias sendmail write_mail
|
||||||
|
|
||||||
|
|
||||||
private
|
def quit
|
||||||
|
critical {
|
||||||
|
getok 'QUIT'
|
||||||
def do_quit
|
}
|
||||||
getok 'QUIT'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
|
||||||
def get_reply
|
def get_reply
|
||||||
arr = read_reply
|
arr = read_reply
|
||||||
stat = arr[0][0,3]
|
stat = arr[0][0,3]
|
||||||
|
|
Loading…
Add table
Reference in a new issue