mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
aamine
* lib/net/protocol.rb: rename Protocol.port to default_port. * lib/net/smtp.rb: ditto. * lib/net/pop.rb: ditto. * lib/net/http.rb: ditto. * lib/net/protocol.rb: rename BufferedSocket class to InternetMessageIO. * lib/net/smtp.rb: ditto. * lib/net/pop.rb: ditto. * lib/net/http.rb: ditto. * lib/net/protocol.rb: rename InternetMessageIO#write_pendstr to write_message. * lib/net/smtp.rb: ditto. * lib/net/protocol.rb: new method InternetMessageIO#through_message. * lib/net/smtp.rb: ditto. * lib/net/protocol.rb: rename InternetMessageIO#read_pendstr to read_message_to. * lib/net/pop.rb: ditto. * lib/net/protocol.rb: rename InternetMessageIO#read_pendlist to each_list_item * lib/net/pop.rb: ditto. * lib/net/protocol.rb: Now block size is 1024. * lib/net/smtp.rb: new methods SMTP#esmtp? and #esmtp=. * lib/net/http.rb: Using singleton method syntax instead of singleton class clause, to avoid behavior change of class variables in ruby 1.7. * lib/net/http.rb: HTTPResponse class does not inherit from Net::Response. * lib/net/http.rb: devide HTTP#connecting into {begin,end}_transport. * lib/net/http.rb: unused class Accumulator removed. * lib/net/http.rb: Net::HTTP reads response. not HTTPRequest. * lib/net/http.rb: proxy related class-instance-variables are not initialized correctly. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c1bfef9494
commit
19f7f6ea12
6 changed files with 600 additions and 524 deletions
60
ChangeLog
60
ChangeLog
|
@ -1,3 +1,63 @@
|
|||
Tue Feb 19 21:43:32 2002 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* lib/net/protocol.rb: rename Protocol.port to default_port.
|
||||
|
||||
* lib/net/smtp.rb: ditto.
|
||||
|
||||
* lib/net/pop.rb: ditto.
|
||||
|
||||
* lib/net/http.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: rename BufferedSocket class to
|
||||
InternetMessageIO.
|
||||
|
||||
* lib/net/smtp.rb: ditto.
|
||||
|
||||
* lib/net/pop.rb: ditto.
|
||||
|
||||
* lib/net/http.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: rename InternetMessageIO#write_pendstr to
|
||||
write_message.
|
||||
|
||||
* lib/net/smtp.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: new method
|
||||
InternetMessageIO#through_message.
|
||||
|
||||
* lib/net/smtp.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: rename InternetMessageIO#read_pendstr to
|
||||
read_message_to.
|
||||
|
||||
* lib/net/pop.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: rename InternetMessageIO#read_pendlist to
|
||||
each_list_item
|
||||
|
||||
* lib/net/pop.rb: ditto.
|
||||
|
||||
* lib/net/protocol.rb: Now block size is 1024.
|
||||
|
||||
* lib/net/smtp.rb: new methods SMTP#esmtp? and #esmtp=.
|
||||
|
||||
* lib/net/http.rb: Using singleton method syntax instead of
|
||||
singleton class clause, to avoid behavior change of class
|
||||
variables in ruby 1.7.
|
||||
|
||||
* lib/net/http.rb: HTTPResponse class does not inherit from
|
||||
Net::Response.
|
||||
|
||||
* lib/net/http.rb: devide HTTP#connecting into
|
||||
{begin,end}_transport.
|
||||
|
||||
* lib/net/http.rb: unused class Accumulator removed.
|
||||
|
||||
* lib/net/http.rb: Net::HTTP reads response. not HTTPRequest.
|
||||
|
||||
* lib/net/http.rb: proxy related class-instance-variables are not
|
||||
initialized correctly.
|
||||
|
||||
Tue Feb 19 17:10:25 2002 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
||||
|
||||
* file.c (path_check_1): do not fail on world writable *parent*
|
||||
|
|
|
@ -79,7 +79,7 @@ Net::HTTP
|
|||
|
||||
Net::HTTP.start( 'auth.some.domain' ) {|http|
|
||||
response , = http.get( '/need-auth.cgi',
|
||||
'Authentication' => ["#{account}:#{password}"].pack('m').strip )
|
||||
'Authorization' => 'Basic ' + ["#{account}:#{password}"].pack('m').strip )
|
||||
print response.body
|
||||
}
|
||||
|
||||
|
|
623
lib/net/http.rb
623
lib/net/http.rb
|
@ -2,7 +2,7 @@
|
|||
|
||||
= net/http.rb
|
||||
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2002 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
This file is derived from "http-access.rb".
|
||||
|
@ -97,7 +97,7 @@ URI class will be included in ruby standard library.
|
|||
|
||||
Net::HTTP.start( 'auth.some.domain' ) {|http|
|
||||
response , = http.get( '/need-auth.cgi',
|
||||
'Authentication' => ["#{account}:#{password}"].pack('m').strip )
|
||||
'Authorization' => 'Basic ' + ["#{account}:#{password}"].pack('m').strip )
|
||||
print response.body
|
||||
}
|
||||
|
||||
|
@ -453,51 +453,37 @@ module Net
|
|||
|
||||
class HTTP < Protocol
|
||||
|
||||
#
|
||||
# constructors
|
||||
#
|
||||
|
||||
class << self
|
||||
|
||||
def start( address, port = nil, p_addr = nil, p_port = nil, &block )
|
||||
new( address, port, p_addr, p_port ).start( &block )
|
||||
end
|
||||
|
||||
alias newobj new
|
||||
|
||||
def new( address, port = nil, p_addr = nil, p_port = nil )
|
||||
obj = Proxy(p_addr, p_port).newobj(address, port)
|
||||
setimplversion obj
|
||||
obj
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def initialize( addr, port = nil )
|
||||
super
|
||||
@curr_http_version = HTTPVersion
|
||||
@seems_1_0_server = false
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# connection
|
||||
#
|
||||
|
||||
protocol_param :port, '80'
|
||||
|
||||
HTTPVersion = '1.1'
|
||||
|
||||
private
|
||||
|
||||
def do_start
|
||||
conn_socket
|
||||
#
|
||||
# for backward compatibility
|
||||
#
|
||||
|
||||
if RUBY_VERSION <= '1.6' then
|
||||
@@newimpl = false
|
||||
else
|
||||
@@newimpl = true
|
||||
end
|
||||
|
||||
def do_finish
|
||||
disconn_socket
|
||||
def HTTP.version_1_2
|
||||
@@newimpl = true
|
||||
end
|
||||
|
||||
def HTTP.version_1_1
|
||||
@@newimpl = false
|
||||
end
|
||||
|
||||
def HTTP.is_version_1_2?
|
||||
@@newimpl
|
||||
end
|
||||
|
||||
def HTTP.setimplversion( obj )
|
||||
f = @@newimpl
|
||||
obj.instance_eval { @newimpl = f }
|
||||
end
|
||||
private_class_method :setimplversion
|
||||
|
||||
|
||||
#
|
||||
# short cut methods
|
||||
|
@ -520,32 +506,72 @@ module Net
|
|||
end
|
||||
|
||||
|
||||
#
|
||||
# connection
|
||||
#
|
||||
|
||||
protocol_param :default_port, '80'
|
||||
protocol_param :socket_type, '::Net::InternetMessageIO'
|
||||
|
||||
class << HTTP
|
||||
def start( address, port = nil, p_addr = nil, p_port = nil, &block )
|
||||
new( address, port, p_addr, p_port ).start( &block )
|
||||
end
|
||||
|
||||
alias newobj new
|
||||
|
||||
def new( address, port = nil, p_addr = nil, p_port = nil )
|
||||
obj = Proxy(p_addr, p_port).newobj(address, port)
|
||||
setimplversion obj
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
||||
def initialize( addr, port = nil )
|
||||
super
|
||||
@curr_http_version = HTTPVersion
|
||||
@seems_1_0_server = false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_start
|
||||
conn_socket
|
||||
end
|
||||
|
||||
def do_finish
|
||||
disconn_socket
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# proxy
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
class << self
|
||||
def Proxy( p_addr, p_port = nil )
|
||||
p_addr or return self
|
||||
# no proxy
|
||||
@is_proxy_class = false
|
||||
@proxy_addr = nil
|
||||
@proxy_port = nil
|
||||
|
||||
p_port ||= port()
|
||||
mod = ProxyDelta
|
||||
proxyclass = Class.new(self)
|
||||
proxyclass.module_eval {
|
||||
include mod
|
||||
@is_proxy_class = true
|
||||
@proxy_address = p_addr
|
||||
@proxy_port = p_port
|
||||
}
|
||||
proxyclass
|
||||
end
|
||||
def HTTP.Proxy( p_addr, p_port = nil )
|
||||
p_addr or return self
|
||||
|
||||
@is_proxy_class = false
|
||||
@proxy_addr = nil
|
||||
@proxy_port = nil
|
||||
p_port ||= port()
|
||||
delta = ProxyDelta
|
||||
proxyclass = Class.new(self)
|
||||
proxyclass.module_eval {
|
||||
include delta
|
||||
# with proxy
|
||||
@is_proxy_class = true
|
||||
@proxy_address = p_addr
|
||||
@proxy_port = p_port
|
||||
}
|
||||
proxyclass
|
||||
end
|
||||
|
||||
class << HTTP
|
||||
def proxy_class?
|
||||
@is_proxy_class
|
||||
end
|
||||
|
@ -571,7 +597,7 @@ module Net
|
|||
|
||||
private
|
||||
|
||||
# without proxy
|
||||
# no proxy
|
||||
|
||||
def conn_address
|
||||
address
|
||||
|
@ -604,40 +630,6 @@ module Net
|
|||
end
|
||||
|
||||
|
||||
#
|
||||
# for backward compatibility
|
||||
#
|
||||
|
||||
if Version < '1.2.0' then ###noupdate
|
||||
@@newimpl = false
|
||||
else
|
||||
@@newimpl = true
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
def version_1_2
|
||||
@@newimpl = true
|
||||
end
|
||||
|
||||
def version_1_1
|
||||
@@newimpl = false
|
||||
end
|
||||
|
||||
def is_version_1_2?
|
||||
@@newimpl
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setimplversion( obj )
|
||||
f = @@newimpl
|
||||
obj.instance_eval { @newimpl = f }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# http operations
|
||||
#
|
||||
|
@ -682,6 +674,7 @@ module Net
|
|||
res
|
||||
end
|
||||
|
||||
|
||||
def request_get( path, initheader = nil, &block )
|
||||
request Get.new(path,initheader), &block
|
||||
end
|
||||
|
@ -703,12 +696,14 @@ module Net
|
|||
alias post2 request_post
|
||||
alias put2 request_put
|
||||
|
||||
|
||||
def send_request( name, path, body = nil, header = nil )
|
||||
r = HTTPGenericRequest.new( name, (body ? true : false), true,
|
||||
path, header )
|
||||
request r, body
|
||||
end
|
||||
|
||||
|
||||
def request( req, body = nil, &block )
|
||||
unless active? then
|
||||
start {
|
||||
|
@ -717,17 +712,21 @@ module Net
|
|||
}
|
||||
end
|
||||
|
||||
connecting( req ) {
|
||||
req.__send__( :exec,
|
||||
@socket, @curr_http_version, edit_path(req.path), body )
|
||||
yield req.response if block_given?
|
||||
}
|
||||
req.response
|
||||
begin_transport req
|
||||
req.__send__(:exec,
|
||||
@socket, @curr_http_version, edit_path(req.path), body)
|
||||
begin
|
||||
res = HTTPResponse.read_new(@socket, req.response_body_permitted?)
|
||||
end while HTTPContinue === res
|
||||
yield res if block_given?
|
||||
end_transport req, res
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def connecting( req )
|
||||
def begin_transport( req )
|
||||
if @socket.closed? then
|
||||
reconn_socket
|
||||
end
|
||||
|
@ -735,14 +734,15 @@ module Net
|
|||
req['connection'] = 'close'
|
||||
end
|
||||
req['host'] = addr_port()
|
||||
end
|
||||
|
||||
yield req
|
||||
req.response.__send__ :terminate
|
||||
@curr_http_version = req.response.http_version
|
||||
def end_transport( req, res )
|
||||
res.__send__ :terminate
|
||||
@curr_http_version = res.http_version
|
||||
|
||||
if not req.response.body then
|
||||
if not res.body then
|
||||
@socket.close
|
||||
elsif keep_alive? req, req.response then
|
||||
elsif keep_alive? req, res then
|
||||
D 'Conn keep-alive'
|
||||
if @socket.closed? then # (only) read stream had been closed
|
||||
D 'Conn (but seems 1.0 server)'
|
||||
|
@ -788,71 +788,7 @@ module Net
|
|||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Code
|
||||
|
||||
def http_mkchild( bodyexist = nil )
|
||||
c = mkchild(nil)
|
||||
be = if bodyexist.nil? then @body_exist else bodyexist end
|
||||
c.instance_eval { @body_exist = be }
|
||||
c
|
||||
end
|
||||
|
||||
def body_exist?
|
||||
@body_exist
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
HTTPInformationCode = InformationCode.http_mkchild( false )
|
||||
HTTPSuccessCode = SuccessCode .http_mkchild( true )
|
||||
HTTPRedirectionCode = RetriableCode .http_mkchild( true )
|
||||
HTTPRetriableCode = HTTPRedirectionCode
|
||||
HTTPClientErrorCode = FatalErrorCode .http_mkchild( true )
|
||||
HTTPFatalErrorCode = HTTPClientErrorCode
|
||||
HTTPServerErrorCode = ServerErrorCode.http_mkchild( true )
|
||||
|
||||
|
||||
HTTPSwitchProtocol = HTTPInformationCode.http_mkchild
|
||||
|
||||
HTTPOK = HTTPSuccessCode.http_mkchild
|
||||
HTTPCreated = HTTPSuccessCode.http_mkchild
|
||||
HTTPAccepted = HTTPSuccessCode.http_mkchild
|
||||
HTTPNonAuthoritativeInformation = HTTPSuccessCode.http_mkchild
|
||||
HTTPNoContent = HTTPSuccessCode.http_mkchild( false )
|
||||
HTTPResetContent = HTTPSuccessCode.http_mkchild( false )
|
||||
HTTPPartialContent = HTTPSuccessCode.http_mkchild
|
||||
|
||||
HTTPMultipleChoice = HTTPRedirectionCode.http_mkchild
|
||||
HTTPMovedPermanently = HTTPRedirectionCode.http_mkchild
|
||||
HTTPMovedTemporarily = HTTPRedirectionCode.http_mkchild
|
||||
HTTPNotModified = HTTPRedirectionCode.http_mkchild( false )
|
||||
HTTPUseProxy = HTTPRedirectionCode.http_mkchild( false )
|
||||
|
||||
HTTPBadRequest = HTTPClientErrorCode.http_mkchild
|
||||
HTTPUnauthorized = HTTPClientErrorCode.http_mkchild
|
||||
HTTPPaymentRequired = HTTPClientErrorCode.http_mkchild
|
||||
HTTPForbidden = HTTPClientErrorCode.http_mkchild
|
||||
HTTPNotFound = HTTPClientErrorCode.http_mkchild
|
||||
HTTPMethodNotAllowed = HTTPClientErrorCode.http_mkchild
|
||||
HTTPNotAcceptable = HTTPClientErrorCode.http_mkchild
|
||||
HTTPProxyAuthenticationRequired = HTTPClientErrorCode.http_mkchild
|
||||
HTTPRequestTimeOut = HTTPClientErrorCode.http_mkchild
|
||||
HTTPConflict = HTTPClientErrorCode.http_mkchild
|
||||
HTTPGone = HTTPClientErrorCode.http_mkchild
|
||||
HTTPLengthRequired = HTTPClientErrorCode.http_mkchild
|
||||
HTTPPreconditionFailed = HTTPClientErrorCode.http_mkchild
|
||||
HTTPRequestEntityTooLarge = HTTPClientErrorCode.http_mkchild
|
||||
HTTPRequestURITooLarge = HTTPClientErrorCode.http_mkchild
|
||||
HTTPUnsupportedMediaType = HTTPClientErrorCode.http_mkchild
|
||||
|
||||
HTTPNotImplemented = HTTPServerErrorCode.http_mkchild
|
||||
HTTPBadGateway = HTTPServerErrorCode.http_mkchild
|
||||
HTTPServiceUnavailable = HTTPServerErrorCode.http_mkchild
|
||||
HTTPGatewayTimeOut = HTTPServerErrorCode.http_mkchild
|
||||
HTTPVersionNotSupported = HTTPServerErrorCode.http_mkchild
|
||||
|
||||
HTTPSession = HTTP
|
||||
|
||||
|
||||
###
|
||||
|
@ -1013,7 +949,6 @@ module Net
|
|||
@request_has_body = reqbody
|
||||
@response_has_body = resbody
|
||||
@path = path
|
||||
@response = nil
|
||||
|
||||
@header = tmp = {}
|
||||
return unless initheader
|
||||
|
@ -1029,10 +964,9 @@ module Net
|
|||
|
||||
attr_reader :method
|
||||
attr_reader :path
|
||||
attr_reader :response
|
||||
|
||||
def inspect
|
||||
"\#<#{type}>"
|
||||
"\#<#{self.type} #{@method}>"
|
||||
end
|
||||
|
||||
def request_body_permitted?
|
||||
|
@ -1045,24 +979,19 @@ module Net
|
|||
|
||||
alias body_exist? response_body_permitted?
|
||||
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# write
|
||||
#
|
||||
|
||||
def exec( sock, ver, path, body, &block )
|
||||
private
|
||||
|
||||
def exec( sock, ver, path, body )
|
||||
if body then
|
||||
check_body_premitted
|
||||
check_arg_b body, block
|
||||
sendreq_with_body sock, ver, path, body, &block
|
||||
send_request_with_body sock, ver, path, body
|
||||
else
|
||||
check_arg_n body
|
||||
sendreq_no_body sock, ver, path
|
||||
request sock, ver, path
|
||||
end
|
||||
@response = r = get_response(sock)
|
||||
r
|
||||
end
|
||||
|
||||
def check_body_premitted
|
||||
|
@ -1070,21 +999,7 @@ module Net
|
|||
raise ArgumentError, 'HTTP request body is not premitted'
|
||||
end
|
||||
|
||||
def check_arg_b( data, block )
|
||||
(data and block) and raise ArgumentError, 'both of data and block given'
|
||||
(data or block) or raise ArgumentError, 'str or block required'
|
||||
end
|
||||
|
||||
def check_arg_n( data )
|
||||
data and raise ArgumentError, "data is not permitted for #{@method}"
|
||||
end
|
||||
|
||||
|
||||
def sendreq_no_body( sock, ver, path )
|
||||
request sock, ver, path
|
||||
end
|
||||
|
||||
def sendreq_with_body( sock, ver, path, body )
|
||||
def send_request_with_body( sock, ver, path, body )
|
||||
if block_given? then
|
||||
ac = Accumulator.new
|
||||
yield ac # must be yield, DO NOT USE block.call
|
||||
|
@ -1111,17 +1026,6 @@ module Net
|
|||
end
|
||||
sock.writeline ''
|
||||
end
|
||||
|
||||
#
|
||||
# read
|
||||
#
|
||||
|
||||
def get_response( sock )
|
||||
begin
|
||||
resp = HTTPResponse.new_from_socket(sock, response_body_permitted?)
|
||||
end while ContinueCode === resp
|
||||
resp
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -1138,30 +1042,6 @@ module Net
|
|||
end
|
||||
|
||||
|
||||
class Accumulator
|
||||
|
||||
def initialize
|
||||
@buf = ''
|
||||
end
|
||||
|
||||
def write( s )
|
||||
@buf.concat s
|
||||
end
|
||||
|
||||
def <<( s )
|
||||
@buf.concat s
|
||||
self
|
||||
end
|
||||
|
||||
def terminate
|
||||
ret = @buf
|
||||
@buf = nil
|
||||
ret
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class HTTP
|
||||
|
||||
class Get < HTTPRequest
|
||||
|
@ -1196,20 +1076,164 @@ module Net
|
|||
### response
|
||||
###
|
||||
|
||||
class HTTPResponse < Response
|
||||
class HTTPResponse
|
||||
# predefine HTTPResponse class to allow inheritance
|
||||
|
||||
include HTTPHeader
|
||||
def self.body_permitted?
|
||||
self::HAS_BODY
|
||||
end
|
||||
|
||||
def self.exception_type
|
||||
self::EXCEPTION_TYPE
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class HTTPUnknownResponse < HTTPResponse
|
||||
HAS_BODY = true
|
||||
EXCEPTION_TYPE = ProtocolError
|
||||
end
|
||||
class HTTPInformation < HTTPResponse
|
||||
HAS_BODY = false
|
||||
EXCEPTION_TYPE = ProtocolError
|
||||
end
|
||||
class HTTPSuccess < HTTPResponse
|
||||
HAS_BODY = true
|
||||
EXCEPTION_TYPE = ProtocolError
|
||||
end
|
||||
class HTTPRedirection < HTTPResponse
|
||||
HAS_BODY = true
|
||||
EXCEPTION_TYPE = ProtoRetriableError
|
||||
end
|
||||
class HTTPClientError < HTTPResponse
|
||||
HAS_BODY = true
|
||||
EXCEPTION_TYPE = ProtoFatalError
|
||||
end
|
||||
class HTTPServerError < HTTPResponse
|
||||
HAS_BODY = true
|
||||
EXCEPTION_TYPE = ProtoServerError
|
||||
end
|
||||
class HTTPContinue < HTTPInformation
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPSwitchProtocol < HTTPInformation
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPOK < HTTPSuccess
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPCreated < HTTPSuccess
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPAccepted < HTTPSuccess
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNonAuthoritativeInformation < HTTPSuccess
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNoContent < HTTPSuccess
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPResetContent < HTTPSuccess
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPPartialContent < HTTPSuccess
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPMultipleChoice < HTTPRedirection
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPMovedPermanently < HTTPRedirection
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPMovedTemporarily < HTTPRedirection
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNotModified < HTTPRedirection
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPUseProxy < HTTPRedirection
|
||||
HAS_BODY = false
|
||||
end
|
||||
class HTTPBadRequest < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPUnauthorized < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPPaymentRequired < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPForbidden < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNotFound < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPMethodNotAllowed < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNotAcceptable < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPProxyAuthenticationRequired < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPRequestTimeOut < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPConflict < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPGone < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPLengthRequired < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPPreconditionFailed < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPRequestEntityTooLarge < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPRequestURITooLarge < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPUnsupportedMediaType < HTTPClientError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPInternalServerError < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPNotImplemented < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPBadGateway < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPServiceUnavailable < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPGatewayTimeOut < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
class HTTPVersionNotSupported < HTTPServerError
|
||||
HAS_BODY = true
|
||||
end
|
||||
|
||||
|
||||
class HTTPResponse # redefine
|
||||
|
||||
CODE_CLASS_TO_OBJ = {
|
||||
'1' => HTTPInformationCode,
|
||||
'2' => HTTPSuccessCode,
|
||||
'3' => HTTPRedirectionCode,
|
||||
'4' => HTTPClientErrorCode,
|
||||
'5' => HTTPServerErrorCode
|
||||
'1' => HTTPInformation,
|
||||
'2' => HTTPSuccess,
|
||||
'3' => HTTPRedirection,
|
||||
'4' => HTTPClientError,
|
||||
'5' => HTTPServerError
|
||||
}
|
||||
|
||||
CODE_TO_OBJ = {
|
||||
'100' => ContinueCode,
|
||||
'100' => HTTPContinue,
|
||||
'101' => HTTPSwitchProtocol,
|
||||
|
||||
'200' => HTTPOK,
|
||||
|
@ -1223,7 +1247,6 @@ module Net
|
|||
'300' => HTTPMultipleChoice,
|
||||
'301' => HTTPMovedPermanently,
|
||||
'302' => HTTPMovedTemporarily,
|
||||
'303' => HTTPMovedPermanently,
|
||||
'304' => HTTPNotModified,
|
||||
'305' => HTTPUseProxy,
|
||||
|
||||
|
@ -1238,13 +1261,13 @@ module Net
|
|||
'408' => HTTPRequestTimeOut,
|
||||
'409' => HTTPConflict,
|
||||
'410' => HTTPGone,
|
||||
'411' => HTTPFatalErrorCode,
|
||||
'411' => HTTPLengthRequired,
|
||||
'412' => HTTPPreconditionFailed,
|
||||
'413' => HTTPRequestEntityTooLarge,
|
||||
'414' => HTTPRequestURITooLarge,
|
||||
'415' => HTTPUnsupportedMediaType,
|
||||
|
||||
'500' => HTTPFatalErrorCode,
|
||||
'501' => HTTPInternalServerError,
|
||||
'501' => HTTPNotImplemented,
|
||||
'502' => HTTPBadGateway,
|
||||
'503' => HTTPServiceUnavailable,
|
||||
|
@ -1255,50 +1278,57 @@ module Net
|
|||
|
||||
class << self
|
||||
|
||||
def new_from_socket( sock, hasbody )
|
||||
resp = readnew( sock, hasbody )
|
||||
def read_new( sock, hasbody )
|
||||
httpv, code, msg = read_response_status(sock)
|
||||
res = response_class(code).new( httpv, code, msg, sock, hasbody )
|
||||
read_response_header sock, res
|
||||
res
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read_response_status( sock )
|
||||
str = sock.readline
|
||||
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or
|
||||
raise HTTPBadResponse, "wrong status line: #{str.dump}"
|
||||
return m.to_a[1,3]
|
||||
end
|
||||
|
||||
def response_class( code )
|
||||
CODE_TO_OBJ[code] or
|
||||
CODE_CLASS_TO_OBJ[code[0,1]] or
|
||||
HTTPUnknownResponse
|
||||
end
|
||||
|
||||
def read_response_header( sock, res )
|
||||
while true do
|
||||
line = sock.readuntil( "\n", true ) # ignore EOF
|
||||
line.sub!( /\s+\z/, '' ) # don't use chop!
|
||||
break if line.empty?
|
||||
|
||||
m = /\A([^:]+):\s*/.match( line )
|
||||
m or raise HTTPBadResponse, 'wrong header line format'
|
||||
nm = m[1]
|
||||
m = /\A([^:]+):\s*/.match(line) or
|
||||
raise HTTPBadResponse, 'wrong header line format'
|
||||
name = m[1]
|
||||
line = m.post_match
|
||||
if resp.key? nm then
|
||||
resp[nm] << ', ' << line
|
||||
if res.key? name then
|
||||
res[name] << ', ' << line
|
||||
else
|
||||
resp[nm] = line
|
||||
res[name] = line
|
||||
end
|
||||
end
|
||||
|
||||
resp
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def readnew( sock, hasbody )
|
||||
str = sock.readline
|
||||
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match( str )
|
||||
m or raise HTTPBadResponse, "wrong status line: #{str}"
|
||||
discard, httpv, stat, desc = *m.to_a
|
||||
|
||||
new( stat, desc, sock, hasbody, httpv )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def initialize( stat, msg, sock, be, hv )
|
||||
code = CODE_TO_OBJ[stat] ||
|
||||
CODE_CLASS_TO_OBJ[stat[0,1]] ||
|
||||
UnknownCode
|
||||
super code, stat, msg
|
||||
@socket = sock
|
||||
@body_exist = be
|
||||
@http_version = hv
|
||||
include HTTPHeader
|
||||
|
||||
def initialize( httpv, code, msg, sock, hasbody )
|
||||
@http_version = httpv
|
||||
@code = code
|
||||
@message = msg
|
||||
@socket = sock
|
||||
@body_exist = hasbody
|
||||
|
||||
@header = {}
|
||||
@body = nil
|
||||
|
@ -1306,16 +1336,34 @@ module Net
|
|||
end
|
||||
|
||||
attr_reader :http_version
|
||||
attr_reader :code
|
||||
attr_reader :message
|
||||
alias msg message
|
||||
|
||||
def inspect
|
||||
"#<#{type} #{code}>"
|
||||
"#<#{type} #{@code} readbody=#{@read}>"
|
||||
end
|
||||
|
||||
#
|
||||
# response <-> exception relationship
|
||||
#
|
||||
|
||||
def code_type
|
||||
self.type
|
||||
end
|
||||
|
||||
def error!
|
||||
raise error_type.new(@code + ' ' + @message.dump, self)
|
||||
end
|
||||
|
||||
def error_type
|
||||
type::EXCEPTION_TYPE
|
||||
end
|
||||
|
||||
def value
|
||||
SuccessCode === self or error!
|
||||
HTTPSuccess === self or error!
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# header (for backward compatibility)
|
||||
#
|
||||
|
@ -1340,8 +1388,7 @@ module Net
|
|||
|
||||
to = procdest(dest, block)
|
||||
stream_check
|
||||
|
||||
if @body_exist and code_type.body_exist? then
|
||||
if @body_exist and self.type.body_permitted? then
|
||||
read_body_0 to
|
||||
@body = to
|
||||
else
|
||||
|
@ -1393,7 +1440,7 @@ module Net
|
|||
@socket.read 2 # \r\n
|
||||
end
|
||||
until @socket.readline.empty? do
|
||||
;
|
||||
# none
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1402,11 +1449,10 @@ module Net
|
|||
end
|
||||
|
||||
def procdest( dest, block )
|
||||
if dest and block then
|
||||
raise ArgumentError, 'both of arg and block are given for HTTP method'
|
||||
end
|
||||
(dest and block) and
|
||||
raise ArgumentError, 'both of arg and block are given for HTTP method'
|
||||
if block then
|
||||
ReadAdapter.new block
|
||||
ReadAdapter.new(block)
|
||||
else
|
||||
dest || ''
|
||||
end
|
||||
|
@ -1415,17 +1461,22 @@ module Net
|
|||
end
|
||||
|
||||
|
||||
# for backward compatibility
|
||||
|
||||
HTTPSession = HTTP
|
||||
# for backward compatibility
|
||||
|
||||
module NetPrivate
|
||||
HTTPResponse = ::Net::HTTPResponse
|
||||
HTTPGenericRequest = ::Net::HTTPGenericRequest
|
||||
HTTPRequest = ::Net::HTTPRequest
|
||||
Accumulator = ::Net::Accumulator
|
||||
HTTPHeader = ::Net::HTTPHeader
|
||||
end
|
||||
HTTPInformationCode = HTTPInformation
|
||||
HTTPSuccessCode = HTTPSuccess
|
||||
HTTPRedirectionCode = HTTPRedirection
|
||||
HTTPRetriableCode = HTTPRedirection
|
||||
HTTPClientErrorCode = HTTPClientError
|
||||
HTTPFatalErrorCode = HTTPClientError
|
||||
HTTPServerErrorCode = HTTPServerError
|
||||
HTTPResponceReceiver = HTTPResponse
|
||||
|
||||
end # module Net
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
= net/pop.rb
|
||||
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2002 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
|
@ -334,43 +334,41 @@ module Net
|
|||
|
||||
class POP3 < Protocol
|
||||
|
||||
protocol_param :port, '110'
|
||||
protocol_param :default_port, '110'
|
||||
protocol_param :command_type, '::Net::POP3Command'
|
||||
protocol_param :apop_command_type, '::Net::APOPCommand'
|
||||
protocol_param :mail_type, '::Net::POPMail'
|
||||
protocol_param :socket_type, '::Net::InternetMessageIO'
|
||||
|
||||
class << self
|
||||
|
||||
def APOP( bool )
|
||||
bool ? APOP : POP3
|
||||
end
|
||||
def POP3.APOP( bool )
|
||||
bool ? APOP : POP3
|
||||
end
|
||||
|
||||
def foreach( address, port = nil,
|
||||
account = nil, password = nil, &block )
|
||||
start( address, port, account, password ) do |pop|
|
||||
def POP3.foreach( address, port = nil,
|
||||
account = nil, password = nil, &block )
|
||||
start( address, port, account, password ) {|pop|
|
||||
pop.each_mail( &block )
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def delete_all( address, port = nil,
|
||||
account = nil, password = nil, &block )
|
||||
start( address, port, account, password ) do |pop|
|
||||
def POP3.delete_all( address, port = nil,
|
||||
account = nil, password = nil, &block )
|
||||
start( address, port, account, password ) {|pop|
|
||||
pop.delete_all( &block )
|
||||
end
|
||||
end
|
||||
|
||||
def auth_only( address, port = nil,
|
||||
account = nil, password = nil )
|
||||
new( address, port ).auth_only account, password
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def POP3.auth_only( address, port = nil,
|
||||
account = nil, password = nil )
|
||||
new( address, port ).auth_only account, password
|
||||
end
|
||||
|
||||
|
||||
def auth_only( account, password )
|
||||
active? and raise IOError, 'opening already opened POP session'
|
||||
raise IOError, 'opening already opened POP session' if active?
|
||||
start( account, password ) {
|
||||
;
|
||||
# none
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -450,13 +448,19 @@ module Net
|
|||
|
||||
end
|
||||
|
||||
POP = POP3
|
||||
POP = POP3
|
||||
POPSession = POP3
|
||||
POP3Session = POP3
|
||||
|
||||
|
||||
class APOP < POP3
|
||||
protocol_param :command_type, '::Net::APOPCommand'
|
||||
def APOP.command_type
|
||||
APOPCommand
|
||||
end
|
||||
end
|
||||
|
||||
APOPSession = APOP
|
||||
|
||||
|
||||
class POPMail
|
||||
|
||||
|
@ -476,16 +480,16 @@ module Net
|
|||
|
||||
def pop( dest = '', &block )
|
||||
if block then
|
||||
dest = ReadAdapter.new( block )
|
||||
dest = ReadAdapter.new(block)
|
||||
end
|
||||
@command.retr( @num, dest )
|
||||
@command.retr @num, dest
|
||||
end
|
||||
|
||||
alias all pop
|
||||
alias mail pop
|
||||
|
||||
def top( lines, dest = '' )
|
||||
@command.top( @num, lines, dest )
|
||||
@command.top @num, lines, dest
|
||||
end
|
||||
|
||||
def header( dest = '' )
|
||||
|
@ -533,7 +537,7 @@ module Net
|
|||
arr = []
|
||||
atomic {
|
||||
getok 'LIST'
|
||||
@socket.read_pendlist do |line|
|
||||
@socket.each_list_item do |line|
|
||||
m = /\A(\d+)[ \t]+(\d+)/.match(line) or
|
||||
raise BadResponse, "illegal response: #{line}"
|
||||
arr[ m[1].to_i ] = m[2].to_i
|
||||
|
@ -551,15 +555,15 @@ module Net
|
|||
|
||||
def top( num, lines = 0, dest = '' )
|
||||
atomic {
|
||||
getok sprintf( 'TOP %d %d', num, lines )
|
||||
@socket.read_pendstr dest
|
||||
getok sprintf('TOP %d %d', num, lines)
|
||||
@socket.read_message_to dest
|
||||
}
|
||||
end
|
||||
|
||||
def retr( num, dest = '', &block )
|
||||
def retr( num, dest = '' )
|
||||
atomic {
|
||||
getok sprintf('RETR %d', num)
|
||||
@socket.read_pendstr dest, &block
|
||||
@socket.read_message_to dest
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -571,7 +575,7 @@ module Net
|
|||
|
||||
def uidl( num )
|
||||
atomic {
|
||||
getok( sprintf('UIDL %d', num) ).msg.split(' ')[1]
|
||||
getok( sprintf('UIDL %d', num) ).message.split(' ')[1]
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -624,11 +628,4 @@ module Net
|
|||
|
||||
end
|
||||
|
||||
|
||||
# for backward compatibility
|
||||
|
||||
POPSession = POP3
|
||||
POP3Session = POP3
|
||||
APOPSession = APOP
|
||||
|
||||
end # module Net
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
= net/protocol.rb
|
||||
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2002 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
|
@ -31,6 +31,10 @@ module Net
|
|||
|
||||
class << self
|
||||
|
||||
def port
|
||||
default_port
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def protocol_param( name, val )
|
||||
|
@ -47,9 +51,9 @@ module Net
|
|||
#
|
||||
# --- Configuration Staffs for Sub Classes ---
|
||||
#
|
||||
# protocol_param port
|
||||
# protocol_param command_type
|
||||
# protocol_param socket_type (optional)
|
||||
# class method default_port
|
||||
# class method command_type
|
||||
# class method socket_type
|
||||
#
|
||||
# private method do_start
|
||||
# private method do_finish
|
||||
|
@ -58,27 +62,21 @@ module Net
|
|||
# private method conn_port
|
||||
#
|
||||
|
||||
protocol_param :port, 'nil'
|
||||
protocol_param :command_type, 'nil'
|
||||
protocol_param :socket_type, '::Net::BufferedSocket'
|
||||
|
||||
|
||||
def Protocol.start( address, port = nil, *args )
|
||||
instance = new( address, port )
|
||||
instance = new(address, port)
|
||||
|
||||
if block_given? then
|
||||
ret = nil
|
||||
instance.start( *args ) { ret = yield(instance) }
|
||||
ret
|
||||
instance.start(*args) { return yield(instance) }
|
||||
else
|
||||
instance.start( *args )
|
||||
instance.start(*args)
|
||||
instance
|
||||
end
|
||||
end
|
||||
|
||||
def initialize( addr, port = nil )
|
||||
@address = addr
|
||||
@port = port || type.port
|
||||
@port = port || type.default_port
|
||||
|
||||
@command = nil
|
||||
@socket = nil
|
||||
|
@ -236,7 +234,7 @@ module Net
|
|||
@response = resp
|
||||
end
|
||||
|
||||
attr :response
|
||||
attr_reader :response
|
||||
alias data response
|
||||
|
||||
def inspect
|
||||
|
@ -289,64 +287,6 @@ module Net
|
|||
UnknownCode = ReplyCode.mkchild( ProtoUnknownError )
|
||||
|
||||
|
||||
|
||||
class WriteAdapter
|
||||
|
||||
def initialize( sock, mid )
|
||||
@socket = sock
|
||||
@mid = mid
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{type} socket=#{@socket.inspect}>"
|
||||
end
|
||||
|
||||
def <<( str )
|
||||
@socket.__send__ @mid, str
|
||||
self
|
||||
end
|
||||
|
||||
def write( str )
|
||||
@socket.__send__ @mid, str
|
||||
end
|
||||
|
||||
alias print write
|
||||
|
||||
def puts( str = '' )
|
||||
@socket.__send__ @mid, str.sub(/\n?/, "\n")
|
||||
end
|
||||
|
||||
def printf( *args )
|
||||
@socket.__send__ @mid, sprintf(*args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReadAdapter
|
||||
|
||||
def initialize( block )
|
||||
@block = block
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{type}>"
|
||||
end
|
||||
|
||||
def <<( str )
|
||||
call_block str, &@block if @block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def call_block( str )
|
||||
yield str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Command
|
||||
|
||||
def initialize( sock )
|
||||
|
@ -408,25 +348,10 @@ module Net
|
|||
ret
|
||||
end
|
||||
|
||||
def begin_atomic
|
||||
ret = @atomic
|
||||
@atomic = true
|
||||
not ret
|
||||
end
|
||||
|
||||
def end_atomic
|
||||
@atomic = false
|
||||
end
|
||||
|
||||
alias critical atomic
|
||||
alias begin_critical begin_atomic
|
||||
alias end_critical end_atomic
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class BufferedSocket
|
||||
class InternetMessageIO
|
||||
|
||||
class << self
|
||||
alias open new
|
||||
|
@ -494,10 +419,6 @@ module Net
|
|||
### READ
|
||||
###
|
||||
|
||||
#
|
||||
# basic reader
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def read( len, dest = '', ignore = false )
|
||||
|
@ -557,48 +478,9 @@ module Net
|
|||
ret
|
||||
end
|
||||
|
||||
#
|
||||
# line oriented reader
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def read_pendstr( dest )
|
||||
D_off 'reading text...'
|
||||
|
||||
rsize = 0
|
||||
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||
rsize += str.size
|
||||
str.gsub!( /\A\./, '' )
|
||||
dest << str
|
||||
end
|
||||
|
||||
D_on "read #{rsize} bytes"
|
||||
dest
|
||||
end
|
||||
|
||||
# private use only (can not handle 'break')
|
||||
def read_pendlist
|
||||
# D_off 'reading list...'
|
||||
|
||||
str = nil
|
||||
i = 0
|
||||
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||
i += 1
|
||||
str.chop!
|
||||
yield str
|
||||
end
|
||||
|
||||
# D_on "read #{i} items"
|
||||
end
|
||||
|
||||
#
|
||||
# lib (reader)
|
||||
#
|
||||
|
||||
private
|
||||
|
||||
BLOCK_SIZE = 1024 * 2
|
||||
BLOCK_SIZE = 1024
|
||||
|
||||
def rbuf_fill
|
||||
until IO.select [@socket], nil, nil, @read_timeout do
|
||||
|
@ -617,13 +499,39 @@ module Net
|
|||
len
|
||||
end
|
||||
|
||||
#
|
||||
# message read
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def read_message_to( dest )
|
||||
D_off 'reading text...'
|
||||
|
||||
rsize = 0
|
||||
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||
rsize += str.size
|
||||
dest << str.sub(/\A\./, '')
|
||||
end
|
||||
|
||||
D_on "read #{rsize} bytes"
|
||||
dest
|
||||
end
|
||||
|
||||
# private use only (cannot handle 'break')
|
||||
def each_list_item
|
||||
while (str = readuntil("\r\n")) != ".\r\n" do
|
||||
yield str.chop
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### WRITE
|
||||
###
|
||||
|
||||
#
|
||||
# basic writer
|
||||
# basic write
|
||||
#
|
||||
|
||||
public
|
||||
|
@ -640,33 +548,45 @@ module Net
|
|||
}
|
||||
end
|
||||
|
||||
def write_bin( src, block )
|
||||
writing {
|
||||
if block then
|
||||
block.call WriteAdapter.new(self, :do_write)
|
||||
else
|
||||
src.each do |bin|
|
||||
do_write bin
|
||||
end
|
||||
end
|
||||
}
|
||||
private
|
||||
|
||||
def writing
|
||||
@writtensize = 0
|
||||
@debugout << '<- ' if @debugout
|
||||
yield
|
||||
@socket.flush
|
||||
@debugout << "\n" if @debugout
|
||||
@writtensize
|
||||
end
|
||||
|
||||
def do_write( str )
|
||||
@debugout << str.dump if @debugout
|
||||
@writtensize += (n = @socket.write(str))
|
||||
n
|
||||
end
|
||||
|
||||
#
|
||||
# line oriented writer
|
||||
# message write
|
||||
#
|
||||
|
||||
public
|
||||
|
||||
def write_pendstr( src, &block )
|
||||
def write_message( src )
|
||||
D_off "writing text from #{src.type}"
|
||||
|
||||
wsize = using_each_crlf_line {
|
||||
if block_given? then
|
||||
yield WriteAdapter.new(self, :wpend_in)
|
||||
else
|
||||
wpend_in src
|
||||
end
|
||||
wpend_in src
|
||||
}
|
||||
|
||||
D_on "wrote #{wsize} bytes text"
|
||||
wsize
|
||||
end
|
||||
|
||||
def through_message
|
||||
D_off 'writing text from block'
|
||||
|
||||
wsize = using_each_crlf_line {
|
||||
yield WriteAdapter.new(self, :wpend_in)
|
||||
}
|
||||
|
||||
D_on "wrote #{wsize} bytes text"
|
||||
|
@ -758,27 +678,6 @@ module Net
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# lib (writer)
|
||||
#
|
||||
|
||||
private
|
||||
|
||||
def writing
|
||||
@writtensize = 0
|
||||
@debugout << '<- ' if @debugout
|
||||
yield
|
||||
@socket.flush
|
||||
@debugout << "\n" if @debugout
|
||||
@writtensize
|
||||
end
|
||||
|
||||
def do_write( str )
|
||||
@debugout << str.dump if @debugout
|
||||
@writtensize += (n = @socket.write(str))
|
||||
n
|
||||
end
|
||||
|
||||
###
|
||||
### DEBUG
|
||||
###
|
||||
|
@ -800,17 +699,75 @@ module Net
|
|||
@debugout << msg
|
||||
@debugout << "\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class WriteAdapter
|
||||
|
||||
def initialize( sock, mid )
|
||||
@socket = sock
|
||||
@mid = mid
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{type} socket=#{@socket.inspect}>"
|
||||
end
|
||||
|
||||
def write( str )
|
||||
@socket.__send__ @mid, str
|
||||
end
|
||||
|
||||
alias print write
|
||||
|
||||
def <<( str )
|
||||
write str
|
||||
self
|
||||
end
|
||||
|
||||
def puts( str = '' )
|
||||
write str.sub(/\n?/, "\n")
|
||||
end
|
||||
|
||||
def printf( *args )
|
||||
write sprintf(*args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class ReadAdapter
|
||||
|
||||
def initialize( block )
|
||||
@block = block
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{type}>"
|
||||
end
|
||||
|
||||
def <<( str )
|
||||
call_block str, &@block if @block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def call_block( str )
|
||||
yield str
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# for backward compatibility
|
||||
module NetPrivate
|
||||
Response = ::Net::Response
|
||||
WriteAdapter = ::Net::WriteAdapter
|
||||
ReadAdapter = ::Net::ReadAdapter
|
||||
Command = ::Net::Command
|
||||
Socket = ::Net::BufferedSocket
|
||||
Response = ::Net::Response
|
||||
Command = ::Net::Command
|
||||
Socket = ::Net::InternetMessageIO
|
||||
BufferedSocket = ::Net::InternetMessageIO
|
||||
WriteAdapter = ::Net::WriteAdapter
|
||||
ReadAdapter = ::Net::ReadAdapter
|
||||
end
|
||||
BufferedSocket = ::Net::InternetMessageIO
|
||||
|
||||
end # module Net
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
= net/smtp.rb
|
||||
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2002 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
|
@ -220,15 +220,25 @@ module Net
|
|||
|
||||
class SMTP < Protocol
|
||||
|
||||
protocol_param :port, '25'
|
||||
protocol_param :default_port, '25'
|
||||
protocol_param :command_type, '::Net::SMTPCommand'
|
||||
protocol_param :socket_type, '::Net::InternetMessageIO'
|
||||
|
||||
|
||||
def initialize( addr, port = nil )
|
||||
super
|
||||
@esmtp = true
|
||||
end
|
||||
|
||||
attr :esmtp
|
||||
def esmtp?
|
||||
@esmtp
|
||||
end
|
||||
|
||||
def esmtp=( bool )
|
||||
@esmtp = bool
|
||||
end
|
||||
|
||||
alias esmtp esmtp?
|
||||
|
||||
private
|
||||
|
||||
|
@ -279,29 +289,28 @@ module Net
|
|||
|
||||
def send_mail( mailsrc, from_addr, *to_addrs )
|
||||
do_ready from_addr, to_addrs.flatten
|
||||
command().write_mail mailsrc, nil
|
||||
command().write_mail mailsrc
|
||||
end
|
||||
|
||||
alias sendmail send_mail
|
||||
|
||||
def ready( from_addr, *to_addrs, &block )
|
||||
do_ready from_addr, to_addrs.flatten
|
||||
command().write_mail nil, block
|
||||
command().through_mail &block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_ready( from_addr, to_addrs )
|
||||
if to_addrs.empty? then
|
||||
raise ArgumentError, 'mail destination does not given'
|
||||
end
|
||||
raise ArgumentError, 'mail destination does not given' if to_addrs.empty?
|
||||
command().mailfrom from_addr
|
||||
command().rcpt to_addrs
|
||||
command().data
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
SMTPSession = SMTP
|
||||
|
||||
|
||||
class SMTPCommand < Command
|
||||
|
||||
|
@ -366,15 +375,20 @@ module Net
|
|||
end
|
||||
end
|
||||
|
||||
def data
|
||||
return unless begin_atomic
|
||||
getok 'DATA', ContinueCode
|
||||
def write_mail( src )
|
||||
atomic {
|
||||
getok 'DATA', ContinueCode
|
||||
@socket.write_message src
|
||||
check_reply SuccessCode
|
||||
}
|
||||
end
|
||||
|
||||
def write_mail( mailsrc, block )
|
||||
@socket.write_pendstr mailsrc, &block
|
||||
check_reply SuccessCode
|
||||
end_atomic
|
||||
def through_mail( &block )
|
||||
atomic {
|
||||
getok 'DATA', ContinueCode
|
||||
@socket.through_message(&block)
|
||||
check_reply SuccessCode
|
||||
}
|
||||
end
|
||||
|
||||
def quit
|
||||
|
@ -421,9 +435,6 @@ module Net
|
|||
|
||||
|
||||
# for backward compatibility
|
||||
|
||||
SMTPSession = SMTP
|
||||
|
||||
module NetPrivate
|
||||
SMTPCommand = ::Net::SMTPCommand
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue