Net/pop.rb: APOP$B$N@H<e@-BP1~(B

e$B@>;3OB9-$G$9!#e(B

e$B0lEYe([email protected]$B$KAw$j$^$7$?$,!"4{$K8x3+$5$l$F$$$k@H<e@-$Ke(B

e$B$D$$$F$NOC$J$N$G!"e(Bruby-deve$B$G$$$$$N$G$O$J$$$+$H$$$&$3$H$N$h$&$J$N$Ge(B

ruby-deve$B$KAw$jD>$7$F$$$^$9!#e(B

http://sylpheed.sraoss.jp/diary/?date=20080926#p01
e$B$r$_$F!“e(Bnet/pop.rbe$B$be(Bsylpheede$B$HF1$8$h$&$JBP1~$re(B
e$B$9$l$P$$$$$N$G$O$J$$$+$H;W$C$?$N$G$9$,!”$I$&$G$7$g$&$+e(B?

1.8e$B$G$Oe(BNet::POP3Command#apope$B$Ge(B
if /[^!-~]/n =~ @apop_stamp || /@/ !~ @apop_stamp
raise POPAuthenticationError, ‘Invalid APOP server; cannot
login’
end
e$B$N$h$&$J%A%'%C%/$K$J$k$H;W$$$^$9!#e(B
(1.9e$B$G$Oe(Bne$B$r$O$:$9$@$1e(B?)

e$B0J2<$Oe(Btest/net/imap/test_imap.rbe$B$r;29M$K$7$F:n@.$7$?%F%9%H$G$9!#e(B

require ‘net/pop’
require ‘test/unit’
require ‘digest/md5’

class TestPOP < Test::Unit::TestCase
def setup
@users = {‘user’ => ‘pass’ }
@ok_user = ‘user’
@stamp_base = “#{$$}.#{Time.now.to_i}@localhost
end

def test_pop_auth_ok
pop_test(false) do |pop|
assert_instance_of Net::POP3, pop
assert_nothing_raised do
pop.start(@ok_user, @users[@ok_user])
end
end
end

def test_pop_auth_ng
pop_test(false) do |pop|
assert_instance_of Net::POP3, pop
assert_raise Net::POPAuthenticationError do
pop.start(@ok_user, ‘bad password’)
end
end
end

def test_apop_ok
pop_test(@stamp_base) do |pop|
assert_instance_of Net::APOP, pop
assert_nothing_raised do
pop.start(@ok_user, @users[@ok_user])
end
end
end

def test_apop_ng
pop_test(@stamp_base) do |pop|
assert_instance_of Net::APOP, pop
assert_raise Net::POPAuthenticationError do
pop.start(@ok_user, ‘bad password’)
end
end
end

def test_apop_invalid
pop_test(“\x80”+@stamp_base) do |pop|
assert_instance_of Net::APOP, pop
assert_raise Net::POPAuthenticationError do
pop.start(@ok_user, @users[@ok_user])
end
end
end

def test_apop_invalid_at
pop_test(@stamp_base.sub(‘@’, ‘.’)) do |pop|
assert_instance_of Net::APOP, pop
assert_raise Net::POPAuthenticationError do
pop.start(@ok_user, @users[@ok_user])
end
end
end

def pop_test(apop=false)
host = ‘localhost’
server = TCPServer.new(host, 0)
port = server.addr[1]
thread = Thread.start do
sock = server.accept
begin
pop_server_loop(sock, apop)
ensure
sock.close
end
end
begin
pop = Net::POP3::APOP(apop).new(host, port)
#pop.set_debug_output $stderr
yield pop
ensure
begin
pop.finish
rescue IOError
raise unless $!.message == “POP session not yet started”
end
end
ensure
server.close
thread.value
end

def pop_server_loop(sock, apop)
if apop
sock.print “+OK ready <#{apop}>\r\n”
else
sock.print “+OK ready\r\n”
end
user = nil
while line = sock.gets
case line
when /^USER (.+)\r\n/
user = $1
if @users.key?(user)
sock.print “+OK\r\n”
else
sock.print “-ERR unknown user\r\n”
end
when /^PASS (.+)\r\n/
if @users[user] == $1
sock.print “+OK\r\n”
else
sock.print “-ERR invalid password\r\n”
end
when /^APOP (.+) (.+)\r\n/
user = $1
if apop && Digest::MD5.hexdigest(“<#{apop}>#{@users[user]}”) ==
$2
sock.print “+OK\r\n”
else
sock.print “-ERR authentication failed\r\n”
end
when /^QUIT/
sock.print “+OK bye\r\n”
return
else
sock.print “-ERR command not recognized\r\n”
return
end
end
end
end

END
module Net
class POP3Command
def apop(account, password)
raise POPAuthenticationError, ‘not APOP server; cannot login’
unless @apop_stamp
if /[^!-~]/n =~ @apop_stamp || /@/ !~ @apop_stamp
raise POPAuthenticationError, ‘Invalid APOP server; cannot
login’
end
check_response_auth(critical {
get_response(‘APOP %s %s’,
account,
Digest::MD5.hexdigest(@apop_stamp + password))
})
end
end
end

e$BA0ED$G$9!#e(B

2008/09/30 15:28 Kazuhiro NISHIYAMA [email protected]:

http://sylpheed.sraoss.jp/diary/?date=20080926#p01
e$B$r$_$F!“e(Bnet/pop.rbe$B$be(Bsylpheede$B$HF1$8$h$&$JBP1~$re(B
e$B$9$l$P$$$$$N$G$O$J$$$+$H;W$C$?$N$G$9$,!”$I$&$G$7$g$&$+e(B?

1.8e$B$G$Oe(BNet::POP3Command#apope$B$Ge(B
if /[^!-~]/n =~ @apop_stamp || /@/ !~ @apop_stamp
raise POPAuthenticationError, ‘Invalid APOP server; cannot login’
end
e$B$N$h$&$J%A%'%C%/$K$J$k$H;W$$$^$9!#e(B

e$BF1$8$h$&$J$3$H$G$9$,!"e(BPOP3Command#initializee$B$Ge(Btimestampe$B$K%^%C%A$5$;$ke(B
e$B@55,I=8=<+BN$r0J2<$N$h$&$KJQ$($F$7$^$C$F$O$I$&$G$7$g$&$+!#e(B

def initialize(sock)
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
@apop_stamp = res.slice(/<[!-~]+@[!-~]+>/)
end

RFC1939e$B$K$h$k$H!"e(B"The syntax of the timestamp corresponds to the
`msg-id’ in
[RFC822]"e$B$H$N$3$H$J$N$G!"e(B(e$B$A$g$C$H@55,I=8=$,4K$$$G$9$,e(B)
e$BLdBj$J$$5$$,$7$^$9!#e(B

e$B:,K\E*$JBP:v$H$7$F$O!"$A$c$s$H$7$?>ZL@=q$Ge(BPOP over
SSLe$B$r;H$&$N$,$h$$e(B
e$B$N$G$7$g$&$M!#e(B

e$B@>;3OB9-$G$9!#e(B

At Tue, 30 Sep 2008 19:25:19 +0900,
Shugo M. wrote:

RFC1939e$B$K$h$k$H!"e(B"The syntax of the timestamp corresponds to the
`msg-id’ in [RFC822]"e$B$H$N$3$H$J$N$G!"e(B(e$B$A$g$C$H@55,I=8=$,4K$$$G$9$,e(B)
e$BLdBj$J$$5$$,$7$^$9!#e(B

initializee$B$r87$7$/$9$k$N$@$H967b$5$l$F$$$k2DG=@-$,$"$k$H$$$&$3$H$,e(B
e$B$o$+$j$K$/$$$+$H;W$C$FJL%a%C%;!<%8$NNc30$K$J$kJ}$,$$$$$+$He(B
e$B;W$C$?$N$G$9$,!"9M$(D>$7$F$_$k$H!“e(BAPOPe$B$N$O$:$J$N$Ke(B
#<Net::POPAuthenticationError: not APOP server; cannot login>
e$B$K$J$k$N$OB>$N2DG=@-$b4^$a$F$*$+$7$$$N$G!”$=$l$GNI$5$=$&$K;W$$$^$7$?!#e(B

e$B:,K\E*$JBP:v$H$7$F$O!"$A$c$s$H$7$?>ZL@=q$Ge(BPOP over SSLe$B$r;H$&$N$,$h$$e(B
e$B$N$G$7$g$&$M!#e(B

e$B%5!<%PB&$b4^$a$FBP:v$G$-$k>l9g$J$i$=$&$9$k$N$,0lHV$$$$$G$9$M!#e(B

At Wed, 1 Oct 2008 10:18:38 +0900,
Shugo M. wrote:

しばらく他に意見がなければruby_1_8に取り込むということでよいでしょうか?

武者さん
timestampのチェックが緩かったのを少し厳しくしただけで、APIの変更はあり
ません。

 はい、問題ないと思います。お願いします。

e$B@>;3OB9-$G$9!#e(B

At Wed, 1 Oct 2008 10:18:38 +0900,
Shugo M. wrote:

commite$B$O@DLZ$5$s$K$7$F$$$?$@$/$N$,$h$$$H;W$&$N$G$9$,!"K;$7$=$&$J$N$G!"e(B
e$B@DLZ$5$s$NH?1~$,$J$+$C$?$i@>;3$5$s$K$*4j$$$9$k$N$,$h$$$G$7$g$&$+!#e(B

e$BH?1~$,$J$$$h$&$J$N$Ge(Btrunke$B$He(Bruby_1_8e$B$Ke(Bcommite$B$7$F$*$-$^$9!#e(B

e$BA0ED$G$9!#e(B

2008/09/30 23:27 Kazuhiro NISHIYAMA [email protected]:

initializee$B$r87$7$/$9$k$N$@$H967b$5$l$F$$$k2DG=@-$,$"$k$H$$$&$3$H$,e(B
e$B$o$+$j$K$/$$$+$H;W$C$FJL%a%C%;!<%8$NNc30$K$J$kJ}$,$$$$$+$He(B
e$B;W$C$?$N$G$9$,!"9M$(D>$7$F$_$k$H!“e(BAPOPe$B$N$O$:$J$N$Ke(B
#<Net::POPAuthenticationError: not APOP server; cannot login>
e$B$K$J$k$N$OB>$N2DG=@-$b4^$a$F$*$+$7$$$N$G!”$=$l$GNI$5$=$&$K;W$$$^$7$?!#e(B

e$B$=$&$G$9$M!"$A$c$s$H@_Dj$5$l$F$$$k4D6-$G$O!"IaDL$O$3$NNc30$,H/@8$9$k$3$H$Oe(B
e$B$J$$$s$8$c$J$$$+$H;W$$$^$9!#e(B

e$B$7$P$i$/B>$K0U8+$,$J$1$l$Pe(Bruby_1_8e$B$K<h$j9~$`$H$$$&$3$H$G$h$$$G$7$g$&$+e(B?

e$BIp<T$5$se(B
timestampe$B$N%A%'%C%/$,4K$+$C$?$N$r>/$787$7$/$7$?$@$1$G!“e(BAPIe$B$NJQ99$O$”$je(B
e$B$^$;$s!#e(B

commite$B$O@DLZ$5$s$K$7$F$$$?$@$/$N$,$h$$$H;W$&$N$G$9$,!"K;$7$=$&$J$N$G!"e(B
e$B@DLZ$5$s$NH?1~$,$J$+$C$?$i@>;3$5$s$K$*4j$$$9$k$N$,$h$$$G$7$g$&$+!#e(B