* 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:
aamine 2002-02-19 12:33:52 +00:00
parent c1bfef9494
commit 19f7f6ea12
6 changed files with 600 additions and 524 deletions

View File

@ -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*

View File

@ -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
}

View File

@ -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,21 +506,64 @@ 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 )
# no proxy
@is_proxy_class = false
@proxy_addr = nil
@proxy_port = nil
def HTTP.Proxy( p_addr, p_port = nil )
p_addr or return self
p_port ||= port()
mod = ProxyDelta
delta = ProxyDelta
proxyclass = Class.new(self)
proxyclass.module_eval {
include mod
include delta
# with proxy
@is_proxy_class = true
@proxy_address = p_addr
@proxy_port = p_port
@ -542,10 +571,7 @@ module Net
proxyclass
end
@is_proxy_class = false
@proxy_addr = nil
@proxy_port = nil
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
@ -1112,17 +1027,6 @@ module Net
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
include HTTPHeader
def initialize( httpv, code, msg, sock, hasbody )
@http_version = httpv
@code = code
@message = msg
@socket = sock
@body_exist = be
@http_version = hv
@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
(dest and block) and
raise ArgumentError, 'both of arg and block are given for HTTP method'
end
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

View File

@ -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 )
def POP3.APOP( bool )
bool ? APOP : POP3
end
def foreach( address, port = nil,
def POP3.foreach( address, port = nil,
account = nil, password = nil, &block )
start( address, port, account, password ) do |pop|
start( address, port, account, password ) {|pop|
pop.each_mail( &block )
end
}
end
def delete_all( address, port = nil,
def POP3.delete_all( address, port = nil,
account = nil, password = nil, &block )
start( address, port, account, password ) do |pop|
start( address, port, account, password ) {|pop|
pop.delete_all( &block )
end
}
end
def auth_only( address, port = nil,
def POP3.auth_only( address, port = nil,
account = nil, password = nil )
new( address, port ).auth_only account, password
end
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
@ -451,11 +449,17 @@ module Net
end
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

View File

@ -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
private
def writing
@writtensize = 0
@debugout << '<- ' if @debugout
yield
@socket.flush
@debugout << "\n" if @debugout
@writtensize
end
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
}
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
###
@ -804,13 +703,71 @@ module Net
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
Command = ::Net::Command
Socket = ::Net::InternetMessageIO
BufferedSocket = ::Net::InternetMessageIO
WriteAdapter = ::Net::WriteAdapter
ReadAdapter = ::Net::ReadAdapter
Command = ::Net::Command
Socket = ::Net::BufferedSocket
end
BufferedSocket = ::Net::InternetMessageIO
end # module Net

View File

@ -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
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
def through_mail( &block )
atomic {
getok 'DATA', ContinueCode
@socket.through_message(&block)
check_reply SuccessCode
end_atomic
}
end
def quit
@ -421,9 +435,6 @@ module Net
# for backward compatibility
SMTPSession = SMTP
module NetPrivate
SMTPCommand = ::Net::SMTPCommand
end