зеркало из https://github.com/github/ruby.git
Version 1.1.0
o http.rb o support class swap o Net.quote git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@588 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
9d228b13de
Коммит
6f4751f5f6
|
@ -0,0 +1,200 @@
|
|||
=begin
|
||||
|
||||
= net/http.rb
|
||||
|
||||
maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||
This file is derived from http-access.rb
|
||||
|
||||
=end
|
||||
|
||||
require 'net/session'
|
||||
|
||||
|
||||
module Net
|
||||
|
||||
|
||||
class HTTPError < ProtocolError; end
|
||||
class HTTPBadResponse < HTTPError; end
|
||||
|
||||
|
||||
class HTTPSession < Session
|
||||
|
||||
Version = '1.1.0'
|
||||
|
||||
session_setvar :port, '80'
|
||||
session_setvar :command_type, 'HTTPCommand'
|
||||
|
||||
|
||||
def get( path = '/', header = nil, ret = '' )
|
||||
confirm_connection
|
||||
@proto.get path, header, ret
|
||||
end
|
||||
|
||||
def head( path = '/', header = nil )
|
||||
confirm_connection
|
||||
@proto.head path, header
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def confirm_connection
|
||||
if @socket.closed? then
|
||||
@socket.reopen
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
HTTP = HTTPSession
|
||||
|
||||
|
||||
|
||||
class HTTPCommand < Command
|
||||
|
||||
HTTPVersion = '1.1'
|
||||
|
||||
def initialize( sock )
|
||||
@http_version = HTTPVersion
|
||||
|
||||
@in_header = {}
|
||||
@in_header[ 'Host' ] = sock.addr
|
||||
#@in_header[ 'User-Agent' ] = "Ruby http version #{HTTPSession::Version}"
|
||||
#@in_header[ 'Connection' ] = 'Keep-Alive'
|
||||
#@in_header[ 'Accept' ] = '*/*'
|
||||
|
||||
super sock
|
||||
end
|
||||
|
||||
|
||||
attr :http_version
|
||||
|
||||
def get( path, u_header = nil, ret = '' )
|
||||
@socket.writeline sprintf( 'GET %s HTTP/%s', path, HTTPVersion )
|
||||
write_header u_header
|
||||
check_reply SuccessCode
|
||||
header = read_header
|
||||
@socket.read content_length( header ), ret
|
||||
@socket.close unless keep_alive? header
|
||||
|
||||
return header, ret
|
||||
end
|
||||
|
||||
|
||||
def head( path, u_header = nil )
|
||||
@socket.writeline sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion )
|
||||
write_header u_header
|
||||
check_reply SuccessCode
|
||||
header = read_header
|
||||
@socket.close unless keep_alive? header
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
|
||||
# def put
|
||||
|
||||
# def delete
|
||||
|
||||
# def trace
|
||||
|
||||
# def options
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def do_quit
|
||||
unless @socket.closed? then
|
||||
head '/', { 'Connection' => 'Close' }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def get_reply
|
||||
str = @socket.readline
|
||||
/\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s+(.*)\z/i === str
|
||||
@http_version = $1
|
||||
status = $2
|
||||
discrip = $3
|
||||
|
||||
klass = case status[0]
|
||||
when ?1 then
|
||||
case status[2]
|
||||
when ?0 then ContinueCode
|
||||
when ?1 then SuccessCode
|
||||
else UnknownCode
|
||||
end
|
||||
when ?2 then SuccessCode
|
||||
when ?3 then RetryCode
|
||||
when ?4 then ServerBusyCode
|
||||
when ?5 then FatalErrorCode
|
||||
else UnknownCode
|
||||
end
|
||||
klass.new( status, discrip )
|
||||
end
|
||||
|
||||
|
||||
def content_length( header )
|
||||
unless str = header[ 'content-length' ] then
|
||||
raise HTTPBadResponce, "content-length not given"
|
||||
end
|
||||
unless /content-length:\s*(\d+)/i === str then
|
||||
raise HTTPBadResponce, "content-length format error"
|
||||
end
|
||||
$1.to_i
|
||||
end
|
||||
|
||||
def keep_alive?( header )
|
||||
if str = header[ 'connection' ] then
|
||||
if /connection:\s*keep-alive/i === str then
|
||||
return true
|
||||
end
|
||||
else
|
||||
if @http_version == '1.1' then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
def read_header
|
||||
header = {}
|
||||
while true do
|
||||
line = @socket.readline
|
||||
break if line.empty?
|
||||
/\A[^:]+/ === line
|
||||
nm = $&
|
||||
nm.strip!
|
||||
nm.downcase!
|
||||
header[ nm ] = line
|
||||
end
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
def write_header( user )
|
||||
if user then
|
||||
header = @in_header.dup.update user
|
||||
else
|
||||
header = @in_header
|
||||
end
|
||||
header.each do |n,v|
|
||||
@socket.writeline n + ': ' + v
|
||||
end
|
||||
@socket.writeline ''
|
||||
|
||||
if tmp = header['Connection'] then
|
||||
/close/i === tmp
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end # module Net
|
156
lib/net/pop.rb
156
lib/net/pop.rb
|
@ -1,11 +1,11 @@
|
|||
=begin
|
||||
|
||||
= Net module version 1.0.3 reference manual
|
||||
= net/pop.rb
|
||||
|
||||
pop.rb 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.
|
||||
You can freely distribute/modify/copy this file.
|
||||
This library is distributed under the terms of Ruby license.
|
||||
You can freely distribute/modify this file.
|
||||
|
||||
=end
|
||||
|
||||
|
@ -16,6 +16,7 @@ require 'md5'
|
|||
|
||||
module Net
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
== Net::POP3Session
|
||||
|
@ -28,14 +29,9 @@ Net::Session
|
|||
|
||||
: new( address = 'localhost', port = 110 )
|
||||
|
||||
This method create a new POP3Session object but this will not open connection.
|
||||
This method create a new POP3Session object.
|
||||
This will not open connection yet.
|
||||
|
||||
=end
|
||||
|
||||
class POP3Session < Session
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -45,30 +41,35 @@ Net::Session
|
|||
|
||||
: each{|popmail| ...}
|
||||
|
||||
This method is equals to "POP3Session.mails.each"
|
||||
This method is equals to "pop3session.mails.each"
|
||||
|
||||
: mails
|
||||
|
||||
This method returns an array of <a href="#popi">POP3Session::POPMail</a>.
|
||||
This method returns an array of ((URL:#POPMail)).
|
||||
This array is renewed when login.
|
||||
|
||||
=end
|
||||
|
||||
class POP3Session < Session
|
||||
|
||||
session_setvar :port, '110'
|
||||
session_setvar :command_type, 'POP3Command'
|
||||
|
||||
|
||||
attr :mails
|
||||
|
||||
def each() @mails.each{|m| yield m} end
|
||||
def each
|
||||
@mails.each {|m| yield m }
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def proto_initialize
|
||||
@proto_type = POP3Command
|
||||
@port = 110
|
||||
@mails = [].freeze
|
||||
end
|
||||
|
||||
|
||||
def do_start( acnt, pwd )
|
||||
@proto.auth( acnt, pwd )
|
||||
@mails = []
|
||||
|
@ -80,15 +81,15 @@ Net::Session
|
|||
@mails.freeze
|
||||
end
|
||||
|
||||
end # POP3Session
|
||||
|
||||
def do_finish
|
||||
@proto.quit
|
||||
end
|
||||
POPSession = POP3Session
|
||||
POP3 = POP3Session
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
== Net::POP3Session::POPMail
|
||||
== Net::POPMail
|
||||
|
||||
A class of mail which exists on POP server.
|
||||
|
||||
|
@ -96,19 +97,6 @@ A class of mail which exists on POP server.
|
|||
|
||||
Object
|
||||
|
||||
=end
|
||||
|
||||
class POPMail
|
||||
|
||||
def initialize( idx, siz, pro )
|
||||
@num = idx
|
||||
@size = siz
|
||||
@proto = pro
|
||||
|
||||
@deleted = false
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
=== Method
|
||||
|
||||
|
@ -141,42 +129,48 @@ Object
|
|||
|
||||
=end
|
||||
|
||||
attr :size
|
||||
class POPMail
|
||||
|
||||
def all( dest = '' )
|
||||
@proto.retr( @num, dest )
|
||||
end
|
||||
alias pop all
|
||||
alias mail all
|
||||
|
||||
def top( lines, dest = '' )
|
||||
@proto.top( @num, lines, dest )
|
||||
end
|
||||
|
||||
def header( dest = '' )
|
||||
top( 0, dest )
|
||||
end
|
||||
|
||||
def delete
|
||||
@proto.dele( @num )
|
||||
@deleted = true
|
||||
end
|
||||
alias delete! delete
|
||||
|
||||
def deleted?
|
||||
@deleted
|
||||
end
|
||||
|
||||
def uidl
|
||||
@proto.uidl @num
|
||||
end
|
||||
def initialize( idx, siz, pro )
|
||||
@num = idx
|
||||
@size = siz
|
||||
@proto = pro
|
||||
|
||||
@deleted = false
|
||||
end
|
||||
|
||||
end # POP3Session
|
||||
|
||||
POPSession = POP3Session
|
||||
POP3 = POP3Session
|
||||
attr :size
|
||||
|
||||
def all( dest = '' )
|
||||
@proto.retr( @num, dest )
|
||||
end
|
||||
alias pop all
|
||||
alias mail all
|
||||
|
||||
def top( lines, dest = '' )
|
||||
@proto.top( @num, lines, dest )
|
||||
end
|
||||
|
||||
def header( dest = '' )
|
||||
top( 0, dest )
|
||||
end
|
||||
|
||||
def delete
|
||||
@proto.dele( @num )
|
||||
@deleted = true
|
||||
end
|
||||
alias delete! delete
|
||||
|
||||
def deleted?
|
||||
@deleted
|
||||
end
|
||||
|
||||
def uidl
|
||||
@proto.uidl @num
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
|
@ -193,10 +187,7 @@ Net::POP3Session
|
|||
|
||||
class APOPSession < POP3Session
|
||||
|
||||
def proto_initialize
|
||||
super
|
||||
@proto_type = APOPCommand
|
||||
end
|
||||
session_setvar :command_type, 'APOPCommand'
|
||||
|
||||
end
|
||||
|
||||
|
@ -219,17 +210,6 @@ Net::Command
|
|||
|
||||
This method creates new POP3Command object. 'socket' must be ProtocolSocket.
|
||||
|
||||
=end
|
||||
|
||||
class POP3Command < Command
|
||||
|
||||
def initialize( sock )
|
||||
@uidl = nil
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -284,6 +264,15 @@ Net::Command
|
|||
|
||||
=end
|
||||
|
||||
|
||||
class POP3Command < Command
|
||||
|
||||
def initialize( sock )
|
||||
super
|
||||
check_reply SuccessCode
|
||||
end
|
||||
|
||||
|
||||
def auth( acnt, pass )
|
||||
@socket.writeline( 'USER ' + acnt )
|
||||
check_reply_auth
|
||||
|
@ -385,7 +374,7 @@ Net::Command
|
|||
|
||||
=== Super Class
|
||||
|
||||
POP3
|
||||
POP3Command
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -428,9 +417,4 @@ POP3
|
|||
|
||||
end
|
||||
|
||||
|
||||
unless Session::Version == '1.0.3' then
|
||||
$stderr.puts "WARNING: wrong version of session.rb & pop.rb"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
=begin
|
||||
|
||||
= Net module version 1.0.3 reference manual
|
||||
= net/session.rb version 1.1.0
|
||||
|
||||
session.rb 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.
|
||||
You can freely distribute/modify/copy this file.
|
||||
You can freely distribute/modify this file.
|
||||
|
||||
=end
|
||||
|
||||
|
@ -13,16 +13,7 @@ You can freely distribute/modify/copy this file.
|
|||
require 'socket'
|
||||
|
||||
|
||||
class String
|
||||
|
||||
def doquote
|
||||
str = self.gsub( "\n", '\\n' )
|
||||
str.gsub!( "\r", '\\r' )
|
||||
str.gsub!( "\t", '\\t' )
|
||||
return str
|
||||
end
|
||||
|
||||
end
|
||||
module Net
|
||||
|
||||
|
||||
=begin
|
||||
|
@ -39,18 +30,8 @@ Object
|
|||
|
||||
: Version
|
||||
|
||||
The version of Session class. It is a string like "1.0.3".
|
||||
The version of Session class. It is a string like "1.1.0".
|
||||
|
||||
=end
|
||||
|
||||
|
||||
module Net
|
||||
|
||||
class Session
|
||||
|
||||
Version = '1.0.3'
|
||||
|
||||
=begin
|
||||
|
||||
=== Class Methods
|
||||
|
||||
|
@ -65,31 +46,6 @@ module Net
|
|||
If you call this method with block, Session object give itself
|
||||
to block and finish session when block returns.
|
||||
|
||||
=end
|
||||
|
||||
def initialize( addr = 'localhost', port = nil )
|
||||
proto_initialize
|
||||
@address = addr
|
||||
@port = port if port
|
||||
|
||||
@active = false
|
||||
@pipe = nil
|
||||
end
|
||||
|
||||
class << self
|
||||
def start( address = 'localhost', port = nil, *args )
|
||||
inst = new( address, port )
|
||||
ret = inst.start( *args )
|
||||
|
||||
if iterator? then
|
||||
ret = yield( inst )
|
||||
inst.finish
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -101,18 +57,6 @@ module Net
|
|||
|
||||
connecting port number
|
||||
|
||||
=end
|
||||
|
||||
attr :address
|
||||
attr :port
|
||||
|
||||
attr :socket
|
||||
|
||||
attr :proto_type
|
||||
attr :proto, true
|
||||
|
||||
=begin
|
||||
|
||||
: start( *args )
|
||||
|
||||
This method start session. If you call this method when the session
|
||||
|
@ -131,28 +75,96 @@ module Net
|
|||
|
||||
=end
|
||||
|
||||
class Session
|
||||
|
||||
Version = '1.1.0'
|
||||
|
||||
class << self
|
||||
|
||||
def start( address = 'localhost', port = nil, *args )
|
||||
session = new( address, port )
|
||||
|
||||
if iterator? then
|
||||
session.start( *args ) { yield session }
|
||||
else
|
||||
session.start *args
|
||||
session
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def session_setvar( name, val )
|
||||
module_eval %-
|
||||
def self.#{name.id2name}
|
||||
#{val}
|
||||
end
|
||||
-
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# sub-class requirements
|
||||
#
|
||||
# class method command_type
|
||||
# class method port
|
||||
#
|
||||
# private method proto_initialize
|
||||
# private method do_start (optional)
|
||||
# private method do_finish (optional)
|
||||
#
|
||||
|
||||
session_setvar :port, 'nil'
|
||||
session_setvar :command_type, 'nil'
|
||||
session_setvar :socket_type, 'ProtocolSocket'
|
||||
|
||||
|
||||
def initialize( addr = 'localhost', port = nil )
|
||||
@address = addr
|
||||
@port = port || self.type.port
|
||||
|
||||
@active = false
|
||||
@pipe = nil
|
||||
|
||||
@proto = nil
|
||||
@socket = nil
|
||||
end
|
||||
|
||||
|
||||
attr :address
|
||||
attr :port
|
||||
|
||||
attr :socket
|
||||
|
||||
|
||||
def start( *args )
|
||||
return false if active?
|
||||
@active = true
|
||||
|
||||
if Class === args[0] then
|
||||
c = args.shift
|
||||
else
|
||||
c = ProtocolSocket
|
||||
begin
|
||||
connect
|
||||
do_start *args
|
||||
yield if iterator?
|
||||
ensure
|
||||
finish if iterator?
|
||||
end
|
||||
@socket = c.open( @address, @port, @pipe )
|
||||
@pipe = nil
|
||||
|
||||
@proto = @proto_type.new( @socket )
|
||||
do_start( *args )
|
||||
end
|
||||
|
||||
def finish
|
||||
@active = false
|
||||
|
||||
if @proto then
|
||||
do_finish
|
||||
@proto = nil
|
||||
disconnect
|
||||
end
|
||||
|
||||
if @socket and not @socket.closed? then
|
||||
@socket.close
|
||||
@socket = nil
|
||||
end
|
||||
|
||||
if active? then
|
||||
@active = false
|
||||
|
||||
return true
|
||||
else
|
||||
|
@ -160,12 +172,36 @@ module Net
|
|||
end
|
||||
end
|
||||
|
||||
def active?() @active end
|
||||
def active?
|
||||
@active
|
||||
end
|
||||
|
||||
def set_pipe( arg )
|
||||
def set_pipe( arg ) # un-documented
|
||||
@pipe = arg
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def do_start
|
||||
end
|
||||
|
||||
def do_finish
|
||||
end
|
||||
|
||||
|
||||
def connect
|
||||
@socket = self.type.socket_type.open( @address, @port, @pipe )
|
||||
@proto = self.type.command_type.new( @socket )
|
||||
end
|
||||
|
||||
def disconnect
|
||||
@proto.quit
|
||||
@proto = nil
|
||||
@socket = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -197,7 +233,6 @@ Object
|
|||
|
||||
def initialize( sock )
|
||||
@socket = sock
|
||||
check_reply( SuccessCode )
|
||||
end
|
||||
|
||||
attr :socket, true
|
||||
|
@ -248,39 +283,47 @@ Object
|
|||
attr :msg
|
||||
|
||||
def error!( sending )
|
||||
err, tag = Errors[ self.type ]
|
||||
mes = sprintf( <<MES, tag, @code, sending.doquote, @msg.doquote )
|
||||
mes = <<MES
|
||||
|
||||
%s: status %s
|
||||
status %s
|
||||
writing string is:
|
||||
%s
|
||||
|
||||
error message from server is:
|
||||
%s
|
||||
MES
|
||||
raise err, mes
|
||||
raise self.type::Error,
|
||||
sprintf( mes, @code, Net.quote(sending), Net.quote(@msg) )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class SuccessCode < ReplyCode ; end
|
||||
class ContinueCode < SuccessCode ; end
|
||||
class ErrorCode < ReplyCode ; end
|
||||
class SyntaxErrorCode < ErrorCode ; end
|
||||
class FatalErrorCode < ErrorCode ; end
|
||||
class ServerBusyCode < ErrorCode ; end
|
||||
class UnknownCode < ReplyCode ; end
|
||||
class SuccessCode < ReplyCode
|
||||
Error = ProtoUnknownError
|
||||
end
|
||||
|
||||
class ReplyCode
|
||||
Errors = {
|
||||
SuccessCode => [ ProtoUnknownError, 'unknown error' ],
|
||||
ContinueCode => [ ProtoUnknownError, 'unknown error' ],
|
||||
ErrorCode => [ ProtocolError, 'protocol error' ],
|
||||
SyntaxErrorCode => [ ProtoSyntaxError, 'syntax error' ],
|
||||
FatalErrorCode => [ ProtoFatalError, 'fatal error' ],
|
||||
ServerBusyCode => [ ProtoServerError, 'probably server busy' ],
|
||||
UnknownCode => [ ProtoUnknownError, 'unknown error' ]
|
||||
}
|
||||
class ContinueCode < SuccessCode
|
||||
Error = ProtoUnknownError
|
||||
end
|
||||
|
||||
class ErrorCode < ReplyCode
|
||||
Error = ProtocolError
|
||||
end
|
||||
|
||||
class SyntaxErrorCode < ErrorCode
|
||||
Error = ProtoSyntaxError
|
||||
end
|
||||
|
||||
class FatalErrorCode < ErrorCode
|
||||
Error = ProtoFatalError
|
||||
end
|
||||
|
||||
class ServerBusyCode < ErrorCode
|
||||
Error = ProtoServerError
|
||||
end
|
||||
|
||||
class UnknownCode < ReplyCode
|
||||
Error = ProtoUnknownError
|
||||
end
|
||||
|
||||
|
||||
|
@ -298,31 +341,6 @@ Object
|
|||
|
||||
This create new ProtocolSocket object, and connect to server.
|
||||
|
||||
=end
|
||||
|
||||
class ProtocolSocket
|
||||
|
||||
def initialize( addr, port, pipe = nil )
|
||||
@address = addr
|
||||
@port = port
|
||||
@pipe = pipe
|
||||
|
||||
@ipaddr = ''
|
||||
@closed = false
|
||||
@sending = ''
|
||||
@buffer = ''
|
||||
|
||||
@socket = TCPsocket.new( addr, port )
|
||||
@ipaddr = @socket.addr[3]
|
||||
end
|
||||
|
||||
attr :pipe, true
|
||||
|
||||
class << self
|
||||
alias open new
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -330,11 +348,11 @@ Object
|
|||
|
||||
This method closes socket.
|
||||
|
||||
: addr
|
||||
: address, addr
|
||||
|
||||
a FQDN address of server
|
||||
|
||||
: ipaddr
|
||||
: ip_address, ipaddr
|
||||
|
||||
an IP address of server
|
||||
|
||||
|
@ -346,30 +364,6 @@ Object
|
|||
|
||||
true if ProtocolSokcet have been closed already
|
||||
|
||||
=end
|
||||
|
||||
attr :socket, true
|
||||
|
||||
def close
|
||||
@socket.close
|
||||
@closed = true
|
||||
end
|
||||
|
||||
def closed?() @closed end
|
||||
|
||||
def addr() @address.dup end
|
||||
def port() @port end
|
||||
def ipaddr() @ipaddr.dup end
|
||||
|
||||
attr :sending
|
||||
|
||||
|
||||
CRLF = "\r\n"
|
||||
D_CRLF = ".\r\n"
|
||||
TERMEXP = /\n|\r\n|\r/o
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
: read( length )
|
||||
|
||||
|
@ -397,92 +391,6 @@ Object
|
|||
|
||||
When this method was called with block, evaluate it for each reading a line.
|
||||
|
||||
=end
|
||||
|
||||
def read( len, ret = '' )
|
||||
rsize = 0
|
||||
|
||||
while rsize + @buffer.size < len do
|
||||
rsize += @buffer.size
|
||||
ret << fetch_rbuf( @buffer.size )
|
||||
fill_rbuf
|
||||
end
|
||||
ret << fetch_rbuf( len - rsize )
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
def readuntil( target )
|
||||
until idx = @buffer.index( target ) do
|
||||
fill_rbuf
|
||||
end
|
||||
|
||||
return fetch_rbuf( idx + target.size )
|
||||
end
|
||||
|
||||
|
||||
def readline
|
||||
ret = readuntil( CRLF )
|
||||
ret.chop!
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
def read_pendstr( dest = '' )
|
||||
@pipe << "reading text...\n" if pre = @pipe ; @pipe = nil
|
||||
|
||||
rsize = 0
|
||||
|
||||
while (str = readuntil( CRLF )) != D_CRLF do
|
||||
rsize += str.size
|
||||
str.gsub!( /\A\./o, '' )
|
||||
dest << str
|
||||
end
|
||||
|
||||
@pipe << "read #{rsize} bytes\n" if @pipe = pre
|
||||
return dest
|
||||
end
|
||||
|
||||
|
||||
def read_pendlist
|
||||
@pipe << "reading list...\n" if pre = @pipe ; @pipe = nil
|
||||
|
||||
arr = []
|
||||
str = nil
|
||||
call = iterator?
|
||||
|
||||
while (str = readuntil( CRLF )) != D_CRLF do
|
||||
str.chop!
|
||||
arr.push str
|
||||
yield str if iterator?
|
||||
end
|
||||
|
||||
@pipe << "read #{arr.size} lines\n" if @pipe = pre
|
||||
return arr
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
READ_BLOCK = 1024 * 8
|
||||
|
||||
def fill_rbuf
|
||||
@buffer << @socket.sysread( READ_BLOCK )
|
||||
end
|
||||
|
||||
def fetch_rbuf( len )
|
||||
bsi = @buffer.size
|
||||
ret = @buffer[ 0, len ]
|
||||
@buffer = @buffer[ len, bsi - len ]
|
||||
|
||||
@pipe << %{read "#{debugstr ret}"\n} if @pipe
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
: write( src )
|
||||
|
||||
|
@ -506,6 +414,159 @@ Object
|
|||
|
||||
=end
|
||||
|
||||
class ProtocolSocket
|
||||
|
||||
def initialize( addr, port, pipe = nil )
|
||||
@addr = addr
|
||||
@port = port
|
||||
@pipe = pipe
|
||||
|
||||
@closed = true
|
||||
@ipaddr = ''
|
||||
@sending = ''
|
||||
@buffer = ''
|
||||
|
||||
@socket = TCPsocket.new( addr, port )
|
||||
@closed = false
|
||||
@ipaddr = @socket.addr[3]
|
||||
end
|
||||
|
||||
attr :pipe, true
|
||||
|
||||
class << self
|
||||
alias open new
|
||||
end
|
||||
|
||||
def reopen
|
||||
unless closed? then
|
||||
@socket.close
|
||||
flush_rbuf
|
||||
end
|
||||
@socket = TCPsocket.new( @addr, @port )
|
||||
end
|
||||
|
||||
|
||||
attr :socket, true
|
||||
|
||||
def close
|
||||
@socket.close
|
||||
@closed = true
|
||||
end
|
||||
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
def address
|
||||
@addr.dup
|
||||
end
|
||||
alias addr address
|
||||
|
||||
attr :port
|
||||
|
||||
def ip_address
|
||||
@ipaddr.dup
|
||||
end
|
||||
alias ipaddr ip_address
|
||||
|
||||
attr :sending
|
||||
|
||||
|
||||
CRLF = "\r\n"
|
||||
D_CRLF = ".\r\n"
|
||||
TERMEXP = /\n|\r\n|\r/o
|
||||
|
||||
|
||||
def read( len, ret = '' )
|
||||
@pipe << "reading #{len} bytes...\n" if pre = @pipe ; @pipe = nil
|
||||
|
||||
rsize = 0
|
||||
|
||||
while rsize + @buffer.size < len do
|
||||
rsize += @buffer.size
|
||||
ret << fetch_rbuf( @buffer.size )
|
||||
fill_rbuf
|
||||
end
|
||||
ret << fetch_rbuf( len - rsize )
|
||||
|
||||
@pipe << "read #{len} bytes\n" if @pipe = pre
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
def readuntil( target )
|
||||
until idx = @buffer.index( target ) do
|
||||
fill_rbuf
|
||||
end
|
||||
|
||||
fetch_rbuf( idx + target.size )
|
||||
end
|
||||
|
||||
|
||||
def readline
|
||||
ret = readuntil( CRLF )
|
||||
ret.chop!
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
def read_pendstr( dest = '' )
|
||||
@pipe << "reading text...\n" if pre = @pipe ; @pipe = nil
|
||||
|
||||
rsize = 0
|
||||
|
||||
while (str = readuntil( CRLF )) != D_CRLF do
|
||||
rsize += str.size
|
||||
str.gsub!( /\A\./o, '' )
|
||||
dest << str
|
||||
end
|
||||
|
||||
@pipe << "read #{rsize} bytes\n" if @pipe = pre
|
||||
dest
|
||||
end
|
||||
|
||||
|
||||
def read_pendlist
|
||||
@pipe << "reading list...\n" if pre = @pipe ; @pipe = nil
|
||||
|
||||
arr = []
|
||||
str = nil
|
||||
call = iterator?
|
||||
|
||||
while (str = readuntil( CRLF )) != D_CRLF do
|
||||
str.chop!
|
||||
arr.push str
|
||||
yield str if iterator?
|
||||
end
|
||||
|
||||
@pipe << "read #{arr.size} lines\n" if @pipe = pre
|
||||
arr
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
READ_BLOCK = 1024 * 8
|
||||
|
||||
def fill_rbuf
|
||||
@buffer << @socket.sysread( READ_BLOCK )
|
||||
end
|
||||
|
||||
def fetch_rbuf( len )
|
||||
bsi = @buffer.size
|
||||
ret = @buffer[ 0, len ]
|
||||
@buffer = @buffer[ len, bsi - len ]
|
||||
|
||||
@pipe << %{read "#{Net.quote ret}"\n} if @pipe
|
||||
ret
|
||||
end
|
||||
|
||||
def flush_rbuf
|
||||
@buffer = ''
|
||||
end
|
||||
|
||||
|
||||
public
|
||||
|
||||
|
||||
|
@ -514,7 +575,7 @@ Object
|
|||
each_crlf_line( src ) do |line|
|
||||
do_write_do line
|
||||
end
|
||||
return do_write_fin
|
||||
do_write_fin
|
||||
end
|
||||
|
||||
|
||||
|
@ -523,7 +584,7 @@ Object
|
|||
src.each do |bin|
|
||||
do_write_do bin
|
||||
end
|
||||
return do_write_fin
|
||||
do_write_fin
|
||||
end
|
||||
|
||||
|
||||
|
@ -531,7 +592,7 @@ Object
|
|||
do_write_beg
|
||||
do_write_do str
|
||||
do_write_do CRLF
|
||||
return do_write_fin
|
||||
do_write_fin
|
||||
end
|
||||
|
||||
|
||||
|
@ -547,7 +608,7 @@ Object
|
|||
wsize = do_write_fin
|
||||
|
||||
@pipe << "wrote #{wsize} bytes text" if @pipe = pre
|
||||
return wsize
|
||||
wsize
|
||||
end
|
||||
|
||||
|
||||
|
@ -587,48 +648,41 @@ Object
|
|||
|
||||
|
||||
def do_write_beg
|
||||
@wtmp = 'write "' if @pipe
|
||||
|
||||
@writtensize = 0
|
||||
@sending = ''
|
||||
end
|
||||
|
||||
def do_write_do( arg )
|
||||
@wtmp << debugstr( arg ) if @pipe
|
||||
|
||||
if @sending.size < 128 then
|
||||
@sending << arg
|
||||
if @pipe or @sending.size < 128 then
|
||||
@sending << Net.quote( arg )
|
||||
else
|
||||
@sending << '...' unless @sending[-1] == ?.
|
||||
end
|
||||
|
||||
s = @socket.write( arg )
|
||||
@writtensize += s
|
||||
return s
|
||||
s
|
||||
end
|
||||
|
||||
def do_write_fin
|
||||
if @pipe then
|
||||
@wtmp << "\n"
|
||||
@pipe << @wtmp
|
||||
@wtmp = nil
|
||||
@pipe << 'write "'
|
||||
@pipe << @sending
|
||||
@pipe << "\"\n"
|
||||
end
|
||||
|
||||
@socket.flush
|
||||
return @writtensize
|
||||
end
|
||||
|
||||
|
||||
def debugstr( str )
|
||||
ret = ''
|
||||
while str and tmp = str[ 0, 50 ] do
|
||||
str = str[ 50, str.size - 50 ]
|
||||
tmp = tmp.inspect
|
||||
ret << tmp[ 1, tmp.size - 2 ]
|
||||
end
|
||||
ret
|
||||
@writtensize
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def Net.quote( str )
|
||||
str = str.gsub( "\n", '\\n' )
|
||||
str.gsub!( "\r", '\\r' )
|
||||
str.gsub!( "\t", '\\t' )
|
||||
str
|
||||
end
|
||||
|
||||
end # module Net
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
=begin
|
||||
|
||||
= Net module version 1.0.3 reference manual
|
||||
= net/smtp.rb
|
||||
|
||||
smtp.rb 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.
|
||||
You can freely redistribute/modify/copy this file.
|
||||
This library is distributed under the terms of Ruby license.
|
||||
You can freely distribute/modify this file.
|
||||
|
||||
=end
|
||||
|
||||
|
@ -13,6 +13,9 @@ You can freely redistribute/modify/copy this file.
|
|||
require 'net/session'
|
||||
|
||||
|
||||
module Net
|
||||
|
||||
|
||||
=begin
|
||||
|
||||
== Net::SMTPSession
|
||||
|
@ -27,18 +30,6 @@ Net::Session
|
|||
|
||||
This method create new SMTPSession object.
|
||||
|
||||
=end
|
||||
|
||||
module Net
|
||||
|
||||
class SMTPSession < Session
|
||||
|
||||
def proto_initialize
|
||||
@proto_type = SMTPCommand
|
||||
@port = 25
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
=== Methods
|
||||
|
||||
|
@ -65,26 +56,30 @@ module Net
|
|||
|
||||
=end
|
||||
|
||||
class SMTPSession < Session
|
||||
|
||||
Version = '1.1.0'
|
||||
|
||||
session_setvar :port, '25'
|
||||
session_setvar :command_type, 'SMTPCommand'
|
||||
|
||||
|
||||
def sendmail( mailsrc, fromaddr, toaddrs )
|
||||
@proto.mailfrom( fromaddr )
|
||||
@proto.rcpt( toaddrs )
|
||||
@proto.mailfrom fromaddr
|
||||
@proto.rcpt toaddrs
|
||||
@proto.data
|
||||
@proto.sendmail( mailsrc )
|
||||
@proto.sendmail mailsrc
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def do_start( helodom = nil )
|
||||
def do_start( helodom = ENV['HOSTNAME'] )
|
||||
unless helodom then
|
||||
helodom = ENV[ 'HOSTNAME' ]
|
||||
raise ArgumentError, "cannot get hostname"
|
||||
end
|
||||
@proto.helo( helodom )
|
||||
end
|
||||
|
||||
def do_finish
|
||||
@proto.quit
|
||||
@proto.helo helodom
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -111,17 +106,17 @@ Net::Command
|
|||
|
||||
: helo( helo_domain )
|
||||
|
||||
This method send "HELO" command and start SMTP session.<br>
|
||||
This method send "HELO" command and start SMTP session.
|
||||
helo_domain is localhost's FQDN.
|
||||
|
||||
: mailfrom( from_addr )
|
||||
|
||||
This method sends "MAIL FROM" command.<br>
|
||||
This method sends "MAIL FROM" command.
|
||||
from_addr is your mail address(????@????).
|
||||
|
||||
: rcpt( to_addrs )
|
||||
|
||||
This method sends "RCPT TO" command.<br>
|
||||
This method sends "RCPT TO" command.
|
||||
to_addrs is array of mail address(???@???) of destination.
|
||||
|
||||
: data( mailsrc )
|
||||
|
@ -137,6 +132,12 @@ Net::Command
|
|||
|
||||
class SMTPCommand < Command
|
||||
|
||||
def initialize( sock )
|
||||
super
|
||||
check_reply SuccessCode
|
||||
end
|
||||
|
||||
|
||||
def helo( fromdom )
|
||||
@socket.writeline( 'HELO ' << fromdom )
|
||||
check_reply( SuccessCode )
|
||||
|
@ -163,10 +164,11 @@ Net::Command
|
|||
end
|
||||
|
||||
|
||||
def sendmail( mailsrc )
|
||||
def writemail( mailsrc )
|
||||
@socket.write_pendstr( mailsrc )
|
||||
check_reply( SuccessCode )
|
||||
end
|
||||
alias sendmail writemail
|
||||
|
||||
|
||||
private
|
||||
|
@ -211,9 +213,4 @@ Net::Command
|
|||
|
||||
end
|
||||
|
||||
|
||||
unless Session::Version == '1.0.3' then
|
||||
$stderr.puts "WARNING: wrong version of session.rb & smtp.rb"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче