diff options
author | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-02-19 12:33:52 +0000 |
---|---|---|
committer | aamine <aamine@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-02-19 12:33:52 +0000 |
commit | 19f7f6ea122df49a54c0fe40791feab1a53f6cd9 (patch) | |
tree | 89d99ac69ec027324c5844faaed269f95b8a5753 /lib/net | |
parent | c1bfef949450c0ad55024670af2245a7833a59b4 (diff) | |
download | ruby-19f7f6ea122df49a54c0fe40791feab1a53f6cd9.tar.gz |
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
Diffstat (limited to 'lib/net')
-rw-r--r-- | lib/net/http.rb | 617 | ||||
-rw-r--r-- | lib/net/pop.rb | 79 | ||||
-rw-r--r-- | lib/net/protocol.rb | 311 | ||||
-rw-r--r-- | lib/net/smtp.rb | 49 |
4 files changed, 536 insertions, 520 deletions
diff --git a/lib/net/http.rb b/lib/net/http.rb index e1bda208fa..536c924355 100644 --- a/lib/net/http.rb +++ b/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,50 +453,36 @@ 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 + HTTPVersion = '1.1' # - # connection + # for backward compatibility # - protocol_param :port, '80' + if RUBY_VERSION <= '1.6' then + @@newimpl = false + else + @@newimpl = true + end - HTTPVersion = '1.1' + def HTTP.version_1_2 + @@newimpl = true + end - private + def HTTP.version_1_1 + @@newimpl = false + end - def do_start - conn_socket + def HTTP.is_version_1_2? + @@newimpl end - def do_finish - disconn_socket + def HTTP.setimplversion( obj ) + f = @@newimpl + obj.instance_eval { @newimpl = f } end + private_class_method :setimplversion # @@ -521,31 +507,71 @@ module Net # - # proxy + # connection # - public + protocol_param :default_port, '80' + protocol_param :socket_type, '::Net::InternetMessageIO' - class << self - def Proxy( p_addr, p_port = nil ) - p_addr or return self - - 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 + class << HTTP + def start( address, port = nil, p_addr = nil, p_port = nil, &block ) + new( address, port, p_addr, p_port ).start( &block ) end - @is_proxy_class = false - @proxy_addr = nil - @proxy_port = nil + 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 + + # 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() + 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 @@ -605,40 +631,6 @@ module Net # - # 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,15 +1336,33 @@ 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 - def value - SuccessCode === self or error! + # + # 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 + 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 diff --git a/lib/net/pop.rb b/lib/net/pop.rb index 1dbbc9aeb0..af32e8835a 100644 --- a/lib/net/pop.rb +++ b/lib/net/pop.rb @@ -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 diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index 1cf1cfdb09..e0ad521f88 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -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 diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index 363fc39088..8652f0f5d0 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -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 |