* 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> 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* * 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| Net::HTTP.start( 'auth.some.domain' ) {|http|
response , = http.get( '/need-auth.cgi', response , = http.get( '/need-auth.cgi',
'Authentication' => ["#{account}:#{password}"].pack('m').strip ) 'Authorization' => 'Basic ' + ["#{account}:#{password}"].pack('m').strip )
print response.body print response.body
} }

View File

@ -2,7 +2,7 @@
= net/http.rb = net/http.rb
Copyright (c) 1999-2001 Yukihiro Matsumoto Copyright (c) 1999-2002 Yukihiro Matsumoto
written & maintained by Minero Aoki <aamine@loveruby.net> written & maintained by Minero Aoki <aamine@loveruby.net>
This file is derived from "http-access.rb". 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| Net::HTTP.start( 'auth.some.domain' ) {|http|
response , = http.get( '/need-auth.cgi', response , = http.get( '/need-auth.cgi',
'Authentication' => ["#{account}:#{password}"].pack('m').strip ) 'Authorization' => 'Basic ' + ["#{account}:#{password}"].pack('m').strip )
print response.body print response.body
} }
@ -453,51 +453,37 @@ module Net
class HTTP < Protocol 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' HTTPVersion = '1.1'
private
def do_start #
conn_socket # for backward compatibility
#
if RUBY_VERSION <= '1.6' then
@@newimpl = false
else
@@newimpl = true
end end
def do_finish def HTTP.version_1_2
disconn_socket @@newimpl = true
end 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 # short cut methods
@ -520,32 +506,72 @@ module Net
end 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 # proxy
# #
public public
class << self # no proxy
def Proxy( p_addr, p_port = nil ) @is_proxy_class = false
p_addr or return self @proxy_addr = nil
@proxy_port = nil
p_port ||= port() def HTTP.Proxy( p_addr, p_port = nil )
mod = ProxyDelta p_addr or return self
proxyclass = Class.new(self)
proxyclass.module_eval {
include mod
@is_proxy_class = true
@proxy_address = p_addr
@proxy_port = p_port
}
proxyclass
end
@is_proxy_class = false p_port ||= port()
@proxy_addr = nil delta = ProxyDelta
@proxy_port = nil 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? def proxy_class?
@is_proxy_class @is_proxy_class
end end
@ -571,7 +597,7 @@ module Net
private private
# without proxy # no proxy
def conn_address def conn_address
address address
@ -604,40 +630,6 @@ module Net
end 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 # http operations
# #
@ -682,6 +674,7 @@ module Net
res res
end end
def request_get( path, initheader = nil, &block ) def request_get( path, initheader = nil, &block )
request Get.new(path,initheader), &block request Get.new(path,initheader), &block
end end
@ -703,12 +696,14 @@ module Net
alias post2 request_post alias post2 request_post
alias put2 request_put alias put2 request_put
def send_request( name, path, body = nil, header = nil ) def send_request( name, path, body = nil, header = nil )
r = HTTPGenericRequest.new( name, (body ? true : false), true, r = HTTPGenericRequest.new( name, (body ? true : false), true,
path, header ) path, header )
request r, body request r, body
end end
def request( req, body = nil, &block ) def request( req, body = nil, &block )
unless active? then unless active? then
start { start {
@ -717,17 +712,21 @@ module Net
} }
end end
connecting( req ) { begin_transport req
req.__send__( :exec, req.__send__(:exec,
@socket, @curr_http_version, edit_path(req.path), body ) @socket, @curr_http_version, edit_path(req.path), body)
yield req.response if block_given? begin
} res = HTTPResponse.read_new(@socket, req.response_body_permitted?)
req.response end while HTTPContinue === res
yield res if block_given?
end_transport req, res
res
end end
private private
def connecting( req ) def begin_transport( req )
if @socket.closed? then if @socket.closed? then
reconn_socket reconn_socket
end end
@ -735,14 +734,15 @@ module Net
req['connection'] = 'close' req['connection'] = 'close'
end end
req['host'] = addr_port() req['host'] = addr_port()
end
yield req def end_transport( req, res )
req.response.__send__ :terminate res.__send__ :terminate
@curr_http_version = req.response.http_version @curr_http_version = res.http_version
if not req.response.body then if not res.body then
@socket.close @socket.close
elsif keep_alive? req, req.response then elsif keep_alive? req, res then
D 'Conn keep-alive' D 'Conn keep-alive'
if @socket.closed? then # (only) read stream had been closed if @socket.closed? then # (only) read stream had been closed
D 'Conn (but seems 1.0 server)' D 'Conn (but seems 1.0 server)'
@ -788,71 +788,7 @@ module Net
end end
HTTPSession = HTTP
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
### ###
@ -1013,7 +949,6 @@ module Net
@request_has_body = reqbody @request_has_body = reqbody
@response_has_body = resbody @response_has_body = resbody
@path = path @path = path
@response = nil
@header = tmp = {} @header = tmp = {}
return unless initheader return unless initheader
@ -1029,10 +964,9 @@ module Net
attr_reader :method attr_reader :method
attr_reader :path attr_reader :path
attr_reader :response
def inspect def inspect
"\#<#{type}>" "\#<#{self.type} #{@method}>"
end end
def request_body_permitted? def request_body_permitted?
@ -1045,24 +979,19 @@ module Net
alias body_exist? response_body_permitted? alias body_exist? response_body_permitted?
private
# #
# write # write
# #
def exec( sock, ver, path, body, &block ) private
def exec( sock, ver, path, body )
if body then if body then
check_body_premitted check_body_premitted
check_arg_b body, block send_request_with_body sock, ver, path, body
sendreq_with_body sock, ver, path, body, &block
else else
check_arg_n body request sock, ver, path
sendreq_no_body sock, ver, path
end end
@response = r = get_response(sock)
r
end end
def check_body_premitted def check_body_premitted
@ -1070,21 +999,7 @@ module Net
raise ArgumentError, 'HTTP request body is not premitted' raise ArgumentError, 'HTTP request body is not premitted'
end end
def check_arg_b( data, block ) def send_request_with_body( sock, ver, path, body )
(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 )
if block_given? then if block_given? then
ac = Accumulator.new ac = Accumulator.new
yield ac # must be yield, DO NOT USE block.call yield ac # must be yield, DO NOT USE block.call
@ -1111,17 +1026,6 @@ module Net
end end
sock.writeline '' sock.writeline ''
end end
#
# read
#
def get_response( sock )
begin
resp = HTTPResponse.new_from_socket(sock, response_body_permitted?)
end while ContinueCode === resp
resp
end
end end
@ -1138,30 +1042,6 @@ module Net
end 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 HTTP
class Get < HTTPRequest class Get < HTTPRequest
@ -1196,20 +1076,164 @@ module Net
### response ### 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 = { CODE_CLASS_TO_OBJ = {
'1' => HTTPInformationCode, '1' => HTTPInformation,
'2' => HTTPSuccessCode, '2' => HTTPSuccess,
'3' => HTTPRedirectionCode, '3' => HTTPRedirection,
'4' => HTTPClientErrorCode, '4' => HTTPClientError,
'5' => HTTPServerErrorCode '5' => HTTPServerError
} }
CODE_TO_OBJ = { CODE_TO_OBJ = {
'100' => ContinueCode, '100' => HTTPContinue,
'101' => HTTPSwitchProtocol, '101' => HTTPSwitchProtocol,
'200' => HTTPOK, '200' => HTTPOK,
@ -1223,7 +1247,6 @@ module Net
'300' => HTTPMultipleChoice, '300' => HTTPMultipleChoice,
'301' => HTTPMovedPermanently, '301' => HTTPMovedPermanently,
'302' => HTTPMovedTemporarily, '302' => HTTPMovedTemporarily,
'303' => HTTPMovedPermanently,
'304' => HTTPNotModified, '304' => HTTPNotModified,
'305' => HTTPUseProxy, '305' => HTTPUseProxy,
@ -1238,13 +1261,13 @@ module Net
'408' => HTTPRequestTimeOut, '408' => HTTPRequestTimeOut,
'409' => HTTPConflict, '409' => HTTPConflict,
'410' => HTTPGone, '410' => HTTPGone,
'411' => HTTPFatalErrorCode, '411' => HTTPLengthRequired,
'412' => HTTPPreconditionFailed, '412' => HTTPPreconditionFailed,
'413' => HTTPRequestEntityTooLarge, '413' => HTTPRequestEntityTooLarge,
'414' => HTTPRequestURITooLarge, '414' => HTTPRequestURITooLarge,
'415' => HTTPUnsupportedMediaType, '415' => HTTPUnsupportedMediaType,
'500' => HTTPFatalErrorCode, '501' => HTTPInternalServerError,
'501' => HTTPNotImplemented, '501' => HTTPNotImplemented,
'502' => HTTPBadGateway, '502' => HTTPBadGateway,
'503' => HTTPServiceUnavailable, '503' => HTTPServiceUnavailable,
@ -1255,50 +1278,57 @@ module Net
class << self class << self
def new_from_socket( sock, hasbody ) def read_new( sock, hasbody )
resp = readnew( 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 while true do
line = sock.readuntil( "\n", true ) # ignore EOF line = sock.readuntil( "\n", true ) # ignore EOF
line.sub!( /\s+\z/, '' ) # don't use chop! line.sub!( /\s+\z/, '' ) # don't use chop!
break if line.empty? break if line.empty?
m = /\A([^:]+):\s*/.match( line ) m = /\A([^:]+):\s*/.match(line) or
m or raise HTTPBadResponse, 'wrong header line format' raise HTTPBadResponse, 'wrong header line format'
nm = m[1] name = m[1]
line = m.post_match line = m.post_match
if resp.key? nm then if res.key? name then
resp[nm] << ', ' << line res[name] << ', ' << line
else else
resp[nm] = line res[name] = line
end end
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
end end
def initialize( stat, msg, sock, be, hv ) include HTTPHeader
code = CODE_TO_OBJ[stat] ||
CODE_CLASS_TO_OBJ[stat[0,1]] || def initialize( httpv, code, msg, sock, hasbody )
UnknownCode @http_version = httpv
super code, stat, msg @code = code
@socket = sock @message = msg
@body_exist = be @socket = sock
@http_version = hv @body_exist = hasbody
@header = {} @header = {}
@body = nil @body = nil
@ -1306,16 +1336,34 @@ module Net
end end
attr_reader :http_version attr_reader :http_version
attr_reader :code
attr_reader :message
alias msg message
def inspect 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 end
def value def value
SuccessCode === self or error! HTTPSuccess === self or error!
end end
# #
# header (for backward compatibility) # header (for backward compatibility)
# #
@ -1340,8 +1388,7 @@ module Net
to = procdest(dest, block) to = procdest(dest, block)
stream_check stream_check
if @body_exist and self.type.body_permitted? then
if @body_exist and code_type.body_exist? then
read_body_0 to read_body_0 to
@body = to @body = to
else else
@ -1393,7 +1440,7 @@ module Net
@socket.read 2 # \r\n @socket.read 2 # \r\n
end end
until @socket.readline.empty? do until @socket.readline.empty? do
; # none
end end
end end
@ -1402,11 +1449,10 @@ module Net
end end
def procdest( dest, block ) 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' raise ArgumentError, 'both of arg and block are given for HTTP method'
end
if block then if block then
ReadAdapter.new block ReadAdapter.new(block)
else else
dest || '' dest || ''
end end
@ -1415,17 +1461,22 @@ module Net
end end
# for backward compatibility
HTTPSession = HTTP # for backward compatibility
module NetPrivate module NetPrivate
HTTPResponse = ::Net::HTTPResponse HTTPResponse = ::Net::HTTPResponse
HTTPGenericRequest = ::Net::HTTPGenericRequest HTTPGenericRequest = ::Net::HTTPGenericRequest
HTTPRequest = ::Net::HTTPRequest HTTPRequest = ::Net::HTTPRequest
Accumulator = ::Net::Accumulator
HTTPHeader = ::Net::HTTPHeader HTTPHeader = ::Net::HTTPHeader
end end
HTTPInformationCode = HTTPInformation
HTTPSuccessCode = HTTPSuccess
HTTPRedirectionCode = HTTPRedirection
HTTPRetriableCode = HTTPRedirection
HTTPClientErrorCode = HTTPClientError
HTTPFatalErrorCode = HTTPClientError
HTTPServerErrorCode = HTTPServerError
HTTPResponceReceiver = HTTPResponse HTTPResponceReceiver = HTTPResponse
end # module Net end # module Net

View File

@ -2,7 +2,7 @@
= net/pop.rb = net/pop.rb
Copyright (c) 1999-2001 Yukihiro Matsumoto Copyright (c) 1999-2002 Yukihiro Matsumoto
written & maintained by Minero Aoki <aamine@loveruby.net> written & maintained by Minero Aoki <aamine@loveruby.net>
@ -334,43 +334,41 @@ module Net
class POP3 < Protocol class POP3 < Protocol
protocol_param :port, '110' protocol_param :default_port, '110'
protocol_param :command_type, '::Net::POP3Command' protocol_param :command_type, '::Net::POP3Command'
protocol_param :apop_command_type, '::Net::APOPCommand' protocol_param :apop_command_type, '::Net::APOPCommand'
protocol_param :mail_type, '::Net::POPMail' protocol_param :mail_type, '::Net::POPMail'
protocol_param :socket_type, '::Net::InternetMessageIO'
class << self
def APOP( bool ) def POP3.APOP( bool )
bool ? APOP : POP3 bool ? APOP : POP3
end end
def foreach( address, port = nil, def POP3.foreach( address, port = nil,
account = nil, password = nil, &block ) account = nil, password = nil, &block )
start( address, port, account, password ) do |pop| start( address, port, account, password ) {|pop|
pop.each_mail( &block ) pop.each_mail( &block )
end }
end end
def delete_all( address, port = nil, def POP3.delete_all( address, port = nil,
account = nil, password = nil, &block ) account = nil, password = nil, &block )
start( address, port, account, password ) do |pop| start( address, port, account, password ) {|pop|
pop.delete_all( &block ) pop.delete_all( &block )
end }
end end
def auth_only( address, port = nil,
account = nil, password = nil )
new( address, port ).auth_only account, password
end
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 ) 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 ) { start( account, password ) {
; # none
} }
end end
@ -450,13 +448,19 @@ module Net
end end
POP = POP3 POP = POP3
POPSession = POP3
POP3Session = POP3
class APOP < POP3 class APOP < POP3
protocol_param :command_type, '::Net::APOPCommand' def APOP.command_type
APOPCommand
end
end end
APOPSession = APOP
class POPMail class POPMail
@ -476,16 +480,16 @@ module Net
def pop( dest = '', &block ) def pop( dest = '', &block )
if block then if block then
dest = ReadAdapter.new( block ) dest = ReadAdapter.new(block)
end end
@command.retr( @num, dest ) @command.retr @num, dest
end end
alias all pop alias all pop
alias mail pop alias mail pop
def top( lines, dest = '' ) def top( lines, dest = '' )
@command.top( @num, lines, dest ) @command.top @num, lines, dest
end end
def header( dest = '' ) def header( dest = '' )
@ -533,7 +537,7 @@ module Net
arr = [] arr = []
atomic { atomic {
getok 'LIST' getok 'LIST'
@socket.read_pendlist do |line| @socket.each_list_item do |line|
m = /\A(\d+)[ \t]+(\d+)/.match(line) or m = /\A(\d+)[ \t]+(\d+)/.match(line) or
raise BadResponse, "illegal response: #{line}" raise BadResponse, "illegal response: #{line}"
arr[ m[1].to_i ] = m[2].to_i arr[ m[1].to_i ] = m[2].to_i
@ -551,15 +555,15 @@ module Net
def top( num, lines = 0, dest = '' ) def top( num, lines = 0, dest = '' )
atomic { atomic {
getok sprintf( 'TOP %d %d', num, lines ) getok sprintf('TOP %d %d', num, lines)
@socket.read_pendstr dest @socket.read_message_to dest
} }
end end
def retr( num, dest = '', &block ) def retr( num, dest = '' )
atomic { atomic {
getok sprintf('RETR %d', num) getok sprintf('RETR %d', num)
@socket.read_pendstr dest, &block @socket.read_message_to dest
} }
end end
@ -571,7 +575,7 @@ module Net
def uidl( num ) def uidl( num )
atomic { atomic {
getok( sprintf('UIDL %d', num) ).msg.split(' ')[1] getok( sprintf('UIDL %d', num) ).message.split(' ')[1]
} }
end end
@ -624,11 +628,4 @@ module Net
end end
# for backward compatibility
POPSession = POP3
POP3Session = POP3
APOPSession = APOP
end # module Net end # module Net

View File

@ -2,7 +2,7 @@
= net/protocol.rb = net/protocol.rb
Copyright (c) 1999-2001 Yukihiro Matsumoto Copyright (c) 1999-2002 Yukihiro Matsumoto
written & maintained by Minero Aoki <aamine@loveruby.net> written & maintained by Minero Aoki <aamine@loveruby.net>
@ -31,6 +31,10 @@ module Net
class << self class << self
def port
default_port
end
private private
def protocol_param( name, val ) def protocol_param( name, val )
@ -47,9 +51,9 @@ module Net
# #
# --- Configuration Staffs for Sub Classes --- # --- Configuration Staffs for Sub Classes ---
# #
# protocol_param port # class method default_port
# protocol_param command_type # class method command_type
# protocol_param socket_type (optional) # class method socket_type
# #
# private method do_start # private method do_start
# private method do_finish # private method do_finish
@ -58,27 +62,21 @@ module Net
# private method conn_port # 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 ) def Protocol.start( address, port = nil, *args )
instance = new( address, port ) instance = new(address, port)
if block_given? then if block_given? then
ret = nil instance.start(*args) { return yield(instance) }
instance.start( *args ) { ret = yield(instance) }
ret
else else
instance.start( *args ) instance.start(*args)
instance instance
end end
end end
def initialize( addr, port = nil ) def initialize( addr, port = nil )
@address = addr @address = addr
@port = port || type.port @port = port || type.default_port
@command = nil @command = nil
@socket = nil @socket = nil
@ -236,7 +234,7 @@ module Net
@response = resp @response = resp
end end
attr :response attr_reader :response
alias data response alias data response
def inspect def inspect
@ -289,64 +287,6 @@ module Net
UnknownCode = ReplyCode.mkchild( ProtoUnknownError ) 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 class Command
def initialize( sock ) def initialize( sock )
@ -408,25 +348,10 @@ module Net
ret ret
end 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 end
class InternetMessageIO
class BufferedSocket
class << self class << self
alias open new alias open new
@ -494,10 +419,6 @@ module Net
### READ ### READ
### ###
#
# basic reader
#
public public
def read( len, dest = '', ignore = false ) def read( len, dest = '', ignore = false )
@ -557,48 +478,9 @@ module Net
ret ret
end 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 private
BLOCK_SIZE = 1024 * 2 BLOCK_SIZE = 1024
def rbuf_fill def rbuf_fill
until IO.select [@socket], nil, nil, @read_timeout do until IO.select [@socket], nil, nil, @read_timeout do
@ -617,13 +499,39 @@ module Net
len len
end 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 ### WRITE
### ###
# #
# basic writer # basic write
# #
public public
@ -640,33 +548,45 @@ module Net
} }
end end
def write_bin( src, block ) private
writing {
if block then def writing
block.call WriteAdapter.new(self, :do_write) @writtensize = 0
else @debugout << '<- ' if @debugout
src.each do |bin| yield
do_write bin @socket.flush
end @debugout << "\n" if @debugout
end @writtensize
} end
def do_write( str )
@debugout << str.dump if @debugout
@writtensize += (n = @socket.write(str))
n
end end
# #
# line oriented writer # message write
# #
public public
def write_pendstr( src, &block ) def write_message( src )
D_off "writing text from #{src.type}" D_off "writing text from #{src.type}"
wsize = using_each_crlf_line { wsize = using_each_crlf_line {
if block_given? then wpend_in src
yield WriteAdapter.new(self, :wpend_in) }
else
wpend_in src D_on "wrote #{wsize} bytes text"
end 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" D_on "wrote #{wsize} bytes text"
@ -758,27 +678,6 @@ module Net
end end
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 ### DEBUG
### ###
@ -800,17 +699,75 @@ module Net
@debugout << msg @debugout << msg
@debugout << "\n" @debugout << "\n"
end 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 end
# for backward compatibility # for backward compatibility
module NetPrivate module NetPrivate
Response = ::Net::Response Response = ::Net::Response
WriteAdapter = ::Net::WriteAdapter Command = ::Net::Command
ReadAdapter = ::Net::ReadAdapter Socket = ::Net::InternetMessageIO
Command = ::Net::Command BufferedSocket = ::Net::InternetMessageIO
Socket = ::Net::BufferedSocket WriteAdapter = ::Net::WriteAdapter
ReadAdapter = ::Net::ReadAdapter
end end
BufferedSocket = ::Net::InternetMessageIO
end # module Net end # module Net

View File

@ -2,7 +2,7 @@
= net/smtp.rb = net/smtp.rb
Copyright (c) 1999-2001 Yukihiro Matsumoto Copyright (c) 1999-2002 Yukihiro Matsumoto
written & maintained by Minero Aoki <aamine@loveruby.net> written & maintained by Minero Aoki <aamine@loveruby.net>
@ -220,15 +220,25 @@ module Net
class SMTP < Protocol class SMTP < Protocol
protocol_param :port, '25' protocol_param :default_port, '25'
protocol_param :command_type, '::Net::SMTPCommand' protocol_param :command_type, '::Net::SMTPCommand'
protocol_param :socket_type, '::Net::InternetMessageIO'
def initialize( addr, port = nil ) def initialize( addr, port = nil )
super super
@esmtp = true @esmtp = true
end end
attr :esmtp def esmtp?
@esmtp
end
def esmtp=( bool )
@esmtp = bool
end
alias esmtp esmtp?
private private
@ -279,29 +289,28 @@ module Net
def send_mail( mailsrc, from_addr, *to_addrs ) def send_mail( mailsrc, from_addr, *to_addrs )
do_ready from_addr, to_addrs.flatten do_ready from_addr, to_addrs.flatten
command().write_mail mailsrc, nil command().write_mail mailsrc
end end
alias sendmail send_mail alias sendmail send_mail
def ready( from_addr, *to_addrs, &block ) def ready( from_addr, *to_addrs, &block )
do_ready from_addr, to_addrs.flatten do_ready from_addr, to_addrs.flatten
command().write_mail nil, block command().through_mail &block
end end
private private
def do_ready( from_addr, to_addrs ) def do_ready( from_addr, to_addrs )
if to_addrs.empty? then raise ArgumentError, 'mail destination does not given' if to_addrs.empty?
raise ArgumentError, 'mail destination does not given'
end
command().mailfrom from_addr command().mailfrom from_addr
command().rcpt to_addrs command().rcpt to_addrs
command().data
end end
end end
SMTPSession = SMTP
class SMTPCommand < Command class SMTPCommand < Command
@ -366,15 +375,20 @@ module Net
end end
end end
def data def write_mail( src )
return unless begin_atomic atomic {
getok 'DATA', ContinueCode getok 'DATA', ContinueCode
@socket.write_message src
check_reply SuccessCode
}
end end
def write_mail( mailsrc, block ) def through_mail( &block )
@socket.write_pendstr mailsrc, &block atomic {
check_reply SuccessCode getok 'DATA', ContinueCode
end_atomic @socket.through_message(&block)
check_reply SuccessCode
}
end end
def quit def quit
@ -421,9 +435,6 @@ module Net
# for backward compatibility # for backward compatibility
SMTPSession = SMTP
module NetPrivate module NetPrivate
SMTPCommand = ::Net::SMTPCommand SMTPCommand = ::Net::SMTPCommand
end end