Net version 1.1.3

o  http.rb rd
o  Session -> Protocol


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 1999-12-29 11:14:04 +00:00
parent 0c00050f84
commit a1d1b15167
4 changed files with 419 additions and 372 deletions

View File

@ -5,6 +5,9 @@
maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp> maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This file is derived from http-access.rb This file is derived from http-access.rb
This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this library.
=end =end
require 'net/session' require 'net/session'
@ -17,36 +20,98 @@ class HTTPError < ProtocolError; end
class HTTPBadResponse < HTTPError; end class HTTPBadResponse < HTTPError; end
class HTTPSession < Session =begin
Version = '1.1.2' = HTTP class
session_setvar :port, '80' == Class Methods
session_setvar :command_type, 'Net::HTTPCommand'
: new( address, port = 80 )
create new HTTP object.
: port
returns HTTP default port, 80
: command_type
returns Command class, HTTPCommand
def get( path = '/', header = nil, ret = '' ) == Methods
confirm_connection
@proto.get edit_path(path), header, ret : get( path, header = nil, ret = '' )
get data from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
The data will be written to "ret" using "<<" method.
This method returns response header (Hash) and "ret".
: head( path, header = nil )
get only header from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
This method returns header as a Hash like
{ 'content-length' => 'Content-Length: 2554',
'content-type' => 'Content-Type: text/html',
... }
=end
class HTTP < Protocol
Version = '1.1.3'
protocol_param :port, '80'
protocol_param :command_type, '::Net::HTTPCommand'
def get( path, u_header = nil, ret = '' )
header = connecting {
@command.get ret, edit_path(path), u_header
}
return header, ret
end end
def head( path = '/', header = nil ) def head( path, u_header = nil )
confirm_connection connecting {
@proto.head edit_path(path), header @command.head edit_path(path), u_header
}
end end
private private
def confirm_connection def connecting
if @socket.closed? then if @socket.closed? then
@socket.reopen @socket.reopen
end end
header = yield
@socket.close unless keep_alive? header
header
end end
def keep_alive?( header )
if str = header[ 'connection' ] then
if /\Aconnection:\s*keep-alive/i === str then
return true
end
else
if @http_version == '1.1' then
return true
end
end
false
end
def do_finish def do_finish
unless @proto.error_occured or @socket.closed? then unless @command.error_occured or @socket.closed? then
head '/', { 'Connection' => 'Close' } head '/', { 'Connection' => 'Close' }
end end
end end
@ -57,11 +122,12 @@ class HTTPSession < Session
end end
class << self class << self
def Proxy( addr, port ) def Proxy( p_addr, p_port )
klass = super klass = super
klass.module_eval %- klass.module_eval %-
def edit_path( path ) def edit_path( path )
'http://' + address + (port == self.port ? '' : ":\#{port}") + path 'http://' + address +
(@port == #{self.port} ? '' : ':' + @port.to_s) + path
end end
- -
klass klass
@ -70,7 +136,7 @@ class HTTPSession < Session
end end
HTTP = HTTPSession HTTPSession = HTTP
class HTTPCommand < Command class HTTPCommand < Command
@ -82,7 +148,6 @@ class HTTPCommand < Command
@in_header = {} @in_header = {}
@in_header[ 'Host' ] = sock.addr @in_header[ 'Host' ] = sock.addr
#@in_header[ 'User-Agent' ] = "Ruby http version #{HTTPSession::Version}"
@in_header[ 'Connection' ] = 'keep-alive' @in_header[ 'Connection' ] = 'keep-alive'
@in_header[ 'Accept' ] = '*/*' @in_header[ 'Accept' ] = '*/*'
@ -92,7 +157,7 @@ class HTTPCommand < Command
attr :http_version attr :http_version
def get( path, u_header = nil, ret = '' ) def get( ret, path, u_header = nil )
header = get_response( header = get_response(
sprintf( 'GET %s HTTP/%s', path, HTTPVersion ), u_header ) sprintf( 'GET %s HTTP/%s', path, HTTPVersion ), u_header )
@ -103,18 +168,13 @@ class HTTPCommand < Command
else else
@socket.read content_length( header ), ret @socket.read content_length( header ), ret
end end
@socket.close unless keep_alive? header
return header, ret header
end end
def head( path, u_header = nil ) def head( path, u_header = nil )
header = get_response( get_response sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header
sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header )
@socket.close unless keep_alive? header
header
end end
@ -182,20 +242,6 @@ class HTTPCommand < Command
$1.to_i $1.to_i
end end
def keep_alive?( header )
if str = header[ 'connection' ] then
if /\Aconnection:\s*keep-alive/i === str then
return true
end
else
if @http_version == '1.1' then
return true
end
end
false
end
def chunked?( header ) def chunked?( header )
if str = header[ 'transfer-encoding' ] then if str = header[ 'transfer-encoding' ] then
if /\Atransfer-encoding:\s*chunked/i === str then if /\Atransfer-encoding:\s*chunked/i === str then

View File

@ -4,8 +4,8 @@
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -19,17 +19,17 @@ module Net
=begin =begin
== Net::POP3Session == Net::POP3
=== Super Class === Super Class
Net::Session Net::Protocol
=== Class Methods === Class Methods
: new( address = 'localhost', port = 110 ) : new( address = 'localhost', port = 110 )
This method create a new POP3Session object. This method create a new POP3 object.
This will not open connection yet. This will not open connection yet.
@ -37,11 +37,11 @@ Net::Session
: start( account, password ) : start( account, password )
This method start POP session. This method start POP3.
: each{|popmail| ...} : each{|popmail| ...}
This method is equals to "pop3session.mails.each" This method is equals to "pop3.mails.each"
: mails : mails
@ -50,12 +50,19 @@ Net::Session
=end =end
class POP3Session < Session class POP3 < Protocol
Version = '1.1.2' Version = '1.1.3'
session_setvar :port, '110' protocol_param :port, '110'
session_setvar :command_type, 'Net::POP3Command' protocol_param :command_type, '::Net::POP3Command'
protocol_param :mail_type, '::Net::POPMail'
def initialize( addr = nil, port = nil )
super
@mails = [].freeze
end
attr :mails attr :mails
@ -68,25 +75,23 @@ Net::Session
private private
def proto_initialize
@mails = [].freeze
end
def do_start( acnt, pwd ) def do_start( acnt, pwd )
@proto.auth( acnt, pwd ) @command.auth( acnt, pwd )
t = self.type.mail_type
@mails = [] @mails = []
@proto.list.each_with_index do |size,idx| @command.list.each_with_index do |size,idx|
if size then if size then
@mails.push POPMail.new( idx, size, @proto ) @mails.push t.new( idx, size, @command )
end end
end end
@mails.freeze @mails.freeze
end end
end # POP3Session end
POPSession = POP3Session POP = POP3
POP3 = POP3Session POPSession = POP3
POP3Session = POP3
=begin =begin
@ -133,10 +138,10 @@ Object
class POPMail class POPMail
def initialize( idx, siz, pro ) def initialize( n, s, cmd )
@num = idx @num = n
@size = siz @size = s
@proto = pro @command = cmd
@deleted = false @deleted = false
end end
@ -145,13 +150,13 @@ Object
attr :size attr :size
def all( dest = '' ) def all( dest = '' )
@proto.retr( @num, dest ) @command.retr( @num, dest )
end end
alias pop all alias pop all
alias mail all alias mail all
def top( lines, dest = '' ) def top( lines, dest = '' )
@proto.top( @num, lines, dest ) @command.top( @num, lines, dest )
end end
def header( dest = '' ) def header( dest = '' )
@ -159,7 +164,7 @@ Object
end end
def delete def delete
@proto.dele( @num ) @command.dele( @num )
@deleted = true @deleted = true
end end
alias delete! delete alias delete! delete
@ -169,7 +174,7 @@ Object
end end
def uidl def uidl
@proto.uidl @num @command.uidl @num
end end
end end
@ -177,30 +182,30 @@ Object
=begin =begin
== Net::APOP3Session == Net::APOP
This class has no new methods. Only way of authetication is changed. This class has no new methods. Only way of authetication is changed.
=== Super Class === Super Class
Net::POP3Session Net::POP3
=end =end
class APOPSession < POP3Session class APOP < POP3
session_setvar :command_type, 'Net::APOPCommand' protocol_param :command_type, 'Net::APOPCommand'
end end
APOP = APOPSession APOPSession = APOP
=begin =begin
== Net::POP3Command == Net::POP3Command
POP3 protocol class. POP3 command class.
=== Super Class === Super Class
@ -240,7 +245,7 @@ Net::Command
: quit : quit
This method finishes POP3 session. This method ends POP using 'QUIT' commmand.
: rset : rset
@ -276,7 +281,7 @@ Net::Command
def auth( acnt, pass ) def auth( acnt, pass )
@socket.writeline( 'USER ' + acnt ) @socket.writeline 'USER ' + acnt
check_reply_auth check_reply_auth
@socket.writeline( 'PASS ' + pass ) @socket.writeline( 'PASS ' + pass )
@ -287,8 +292,7 @@ Net::Command
def list def list
@socket.writeline( 'LIST' ) getok 'LIST'
check_reply( SuccessCode )
arr = [] arr = []
@socket.read_pendlist do |line| @socket.read_pendlist do |line|
@ -301,36 +305,29 @@ Net::Command
def rset def rset
@socket.writeline( 'RSET' ) getok 'RSET'
check_reply( SuccessCode )
end end
def top( num, lines = 0, dest = '' ) def top( num, lines = 0, dest = '' )
@socket.writeline( sprintf( 'TOP %d %d', num, lines ) ) getok sprintf( 'TOP %d %d', num, lines )
check_reply( SuccessCode ) @socket.read_pendstr( dest )
return @socket.read_pendstr( dest )
end end
def retr( num, dest = '', &block ) def retr( num, dest = '', &block )
@socket.writeline( sprintf( 'RETR %d', num ) ) getok sprintf( 'RETR %d', num )
check_reply( SuccessCode ) @socket.read_pendstr( dest, &block )
return @socket.read_pendstr( dest, &block )
end end
def dele( num ) def dele( num )
@socket.writeline( 'DELE ' + num.to_s ) getok sprintf( 'DELE %d', num )
check_reply( SuccessCode )
end end
def uidl( num ) def uidl( num )
@socket.writeline( 'UIDL ' + num.to_s ) rep = getok( sprintf 'UIDL %d', num )
rep = check_reply( SuccessCode )
uid = rep.msg.split(' ')[1] uid = rep.msg.split(' ')[1]
uid uid
@ -341,8 +338,7 @@ Net::Command
def do_quit def do_quit
@socket.writeline( 'QUIT' ) getok 'QUIT'
check_reply( SuccessCode )
end end

View File

@ -1,11 +1,11 @@
=begin =begin
= net/session.rb version 1.1.2 = net/session.rb version 1.1.3
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby style license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -18,9 +18,9 @@ module Net
=begin =begin
== Net::Session == Net::Protocol
the abstruct class for Internet protocol session the abstruct class for Internet protocol
=== Super Class === Super Class
@ -30,22 +30,27 @@ Object
: Version : Version
The version of Session class. It is a string like "1.1.2". The version of Session class. It is a string like "1.1.3".
=== Class Methods === Class Methods
: new( address = 'localhost', port = nil ) : new( address = 'localhost', port = nil )
This method Create a new Session object. This method Creates a new Session object.
: start( address = 'localhost', port = nil, *args ) : start( address = 'localhost', port = nil, *args )
: start( address = 'localhost', port = nil, *args ){|session| .... } : start( address = 'localhost', port = nil, *args ){|session| .... }
This method create a new Session object and start session. This method creates a new Session object and start session.
If you call this method with block, Session object give itself If you call this method with block, Session object give itself
to block and finish session when block returns. to block and finish session when block returns.
: Proxy( address, port )
This method creates a proxy class of its protocol.
Arguments are address/port of proxy host.
=== Methods === Methods
@ -59,14 +64,14 @@ Object
: start( *args ) : start( *args )
This method start session. If you call this method when the session This method start protocol. If you call this method when the protocol
is already started, this only returns false without doing anything. is already started, this only returns false without doing anything.
'*args' are specified in subclasses. '*args' are specified in subclasses.
: finish : finish
This method finish session. If you call this method before session starts, This method ends protocol. If you call this method before protocol starts,
it only return false without doing anything. it only return false without doing anything.
: active? : active?
@ -75,20 +80,20 @@ Object
=end =end
class Session class Protocol
Version = '1.1.2' Version = '1.1.3'
class << self class << self
def start( address = 'localhost', port = nil, *args ) def start( address = 'localhost', port = nil, *args )
session = new( address, port ) instance = new( address, port )
if iterator? then if iterator? then
session.start( *args ) { yield session } instance.start( *args ) { yield instance }
else else
session.start *args instance.start *args
session instance
end end
end end
@ -104,11 +109,8 @@ Object
@port = port @port = port
end end
def connect def connect( addr, port )
tmpa, tmpp = @address, @port super @proxyaddr, @proxyport
@address, @port = @proxyaddr, @proxyport
super
@address, @port = tmpa, tmpp
end end
private :connect private :connect
@ -129,7 +131,7 @@ Object
private private
def session_setvar( name, val ) def protocol_param( name, val )
module_eval %- module_eval %-
def self.#{name.id2name} def self.#{name.id2name}
#{val} #{val}
@ -143,26 +145,26 @@ Object
# #
# sub-class requirements # sub-class requirements
# #
# session_setvar command_type # protocol_param command_type
# session_setvar port # protocol_param port
# #
# private method do_start (optional) # private method do_start (optional)
# private method do_finish (optional) # private method do_finish (optional)
# #
session_setvar :port, 'nil' protocol_param :port, 'nil'
session_setvar :command_type, 'nil' protocol_param :command_type, 'nil'
session_setvar :socket_type, 'Net::ProtocolSocket' protocol_param :socket_type, '::Net::ProtocolSocket'
def initialize( addr = 'localhost', port = nil ) def initialize( addr = nil, port = nil )
@address = addr @address = addr || 'localhost'
@port = port || self.type.port @port = port || self.type.port
@active = false @active = false
@pipe = nil @pipe = nil
@proto = nil @command = nil
@socket = nil @socket = nil
end end
@ -170,6 +172,7 @@ Object
attr :address attr :address
attr :port attr :port
attr :command
attr :socket attr :socket
@ -178,7 +181,7 @@ Object
@active = true @active = true
begin begin
connect connect @address, @port
do_start *args do_start *args
yield if iterator? yield if iterator?
ensure ensure
@ -187,7 +190,7 @@ Object
end end
def finish def finish
if @proto then if @command then
do_finish do_finish
disconnect disconnect
end end
@ -225,19 +228,21 @@ Object
end end
def connect def connect( addr, port )
@socket = self.type.socket_type.open( @address, @port, @pipe ) @socket = self.type.socket_type.open( addr, port, @pipe )
@proto = self.type.command_type.new( @socket ) @command = self.type.command_type.new( @socket )
end end
def disconnect def disconnect
@proto.quit @command.quit
@proto = nil @command = nil
@socket = nil @socket = nil
end end
end end
Session = Protocol
=begin =begin
@ -259,7 +264,7 @@ Object
: quit : quit
This method finishes protocol. This method dispatch command which ends the protocol.
=end =end
@ -302,6 +307,11 @@ Object
rep.error! @socket.sending rep.error! @socket.sending
end end
def getok( line, ok = SuccessCode )
@socket.writeline line
check_reply ok
end
end end

View File

@ -4,8 +4,8 @@
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -18,57 +18,57 @@ module Net
=begin =begin
== Net::SMTPSession == Net::SMTP
=== Super Class === Super Class
Net::Session Net::Protocol
=== Class Methods === Class Methods
: new( address = 'localhost', port = 25 ) : new( address = 'localhost', port = 25 )
This method create new SMTPSession object. This method create new SMTP object.
=== Methods === Methods
: start( helo_domain = ENV['HOSTNAME'] ) : start( helo_domain = ENV['HOSTNAME'] )
This method opens TCP connection and start SMTP session. This method opens TCP connection and start SMTP.
If session had been started, do nothing and return false. If protocol had been started, do nothing and return false.
: sendmail( mailsrc, from_domain, to_addrs ) : sendmail( mailsrc, from_domain, to_addrs )
This method sends 'mailsrc' as mail. SMTPSession read strings from 'mailsrc' This method sends 'mailsrc' as mail. SMTPSession read strings from 'mailsrc'
by calling 'each' iterator, and convert them into "\r\n" terminated string when write. by calling 'each' iterator, and convert them into "\r\n" terminated string when write.
SMTPSession's Exceptions are: Exceptions which SMTP raises are:
* Protocol::ProtoSyntaxError: syntax error (errno.500) * Net::ProtoSyntaxError: syntax error (errno.500)
* Protocol::ProtoFatalError: fatal error (errno.550) * Net::ProtoFatalError: fatal error (errno.550)
* Protocol::ProtoUnknownError: unknown error * Net::ProtoUnknownError: unknown error
* Protocol::ProtoServerBusy: temporary error (errno.420/450) * Net::ProtoServerBusy: temporary error (errno.420/450)
: finish : finish
This method closes SMTP session. This method ends SMTP.
If session had not started, do nothind and return false. If protocol had not started, do nothind and return false.
=end =end
class SMTPSession < Session class SMTP < Protocol
Version = '1.1.2' Version = '1.1.3'
session_setvar :port, '25' protocol_param :port, '25'
session_setvar :command_type, 'Net::SMTPCommand' protocol_param :command_type, '::Net::SMTPCommand'
def sendmail( mailsrc, fromaddr, toaddrs ) def sendmail( mailsrc, fromaddr, toaddrs )
@proto.mailfrom fromaddr @command.mailfrom fromaddr
@proto.rcpt toaddrs @command.rcpt toaddrs
@proto.data @command.data
@proto.sendmail mailsrc @command.sendmail mailsrc
end end
@ -79,12 +79,12 @@ Net::Session
unless helodom then unless helodom then
raise ArgumentError, "cannot get hostname" raise ArgumentError, "cannot get hostname"
end end
@proto.helo helodom @command.helo helodom
end end
end end
SMTP = SMTPSession SMTPSession = SMTP
=begin =begin
@ -99,14 +99,14 @@ Net::Command
: new( socket ) : new( socket )
This method creates new SMTPCommand object, and open SMTP session. This method creates new SMTPCommand object, and open SMTP.
=== Methods === Methods
: helo( helo_domain ) : helo( helo_domain )
This method send "HELO" command and start SMTP session. This method send "HELO" command and start SMTP.
helo_domain is localhost's FQDN. helo_domain is localhost's FQDN.
: mailfrom( from_addr ) : mailfrom( from_addr )
@ -139,34 +139,30 @@ Net::Command
def helo( fromdom ) def helo( fromdom )
@socket.writeline( 'HELO ' << fromdom ) getok sprintf( 'HELO %s', fromdom )
check_reply( SuccessCode )
end end
def mailfrom( fromaddr ) def mailfrom( fromaddr )
@socket.writeline( 'MAIL FROM:<' + fromaddr + '>' ) getok sprintf( 'MAIL FROM:<%s>', fromaddr )
check_reply( SuccessCode )
end end
def rcpt( toaddrs ) def rcpt( toaddrs )
toaddrs.each do |i| toaddrs.each do |i|
@socket.writeline( 'RCPT TO:<' + i + '>' ) getok sprintf( 'RCPT TO:<%s>', i )
check_reply( SuccessCode )
end end
end end
def data def data
@socket.writeline( 'DATA' ) getok 'DATA', ContinueCode
check_reply( ContinueCode )
end end
def writemail( mailsrc ) def writemail( mailsrc )
@socket.write_pendstr( mailsrc ) @socket.write_pendstr mailsrc
check_reply( SuccessCode ) check_reply SuccessCode
end end
alias sendmail writemail alias sendmail writemail
@ -175,8 +171,7 @@ Net::Command
def do_quit def do_quit
@socket.writeline( 'QUIT' ) getok 'QUIT'
check_reply( SuccessCode )
end end
@ -184,19 +179,19 @@ Net::Command
arr = read_reply arr = read_reply
stat = arr[0][0,3] stat = arr[0][0,3]
cls = UnknownCode klass = UnknownCode
case stat[0] klass = case stat[0]
when ?2 then cls = SuccessCode when ?2 then SuccessCode
when ?3 then cls = ContinueCode when ?3 then ContinueCode
when ?4 then cls = ServerBusyCode when ?4 then ServerBusyCode
when ?5 then when ?5 then
case stat[1] case stat[1]
when ?0 then cls = SyntaxErrorCode when ?0 then SyntaxErrorCode
when ?5 then cls = FatalErrorCode when ?5 then FatalErrorCode
end end
end end
return cls.new( stat, arr.join('') ) klass.new( stat, arr.join('') )
end end