ruby-net-nntp 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +14 -0
- data/MIT-LICENSE +23 -0
- data/README +31 -0
- data/lib/net/nntp.rb +286 -0
- data/lib/net/nntp_article.rb +24 -0
- data/lib/net/nntp_group.rb +76 -0
- data/test/functional/test_nntp.rb +249 -0
- data/test/mock/mock_socket.rb +330 -0
- data/test/unit/test_nntp_article.rb +56 -0
- data/test/unit/test_nntp_group.rb +60 -0
- metadata +70 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
2007-05-17 08:09 +0200 Anton 'tony' Bangratz <tony@twincode.net> (702e55388bb4 [tip])
|
2
|
+
|
3
|
+
* .hgtags:
|
4
|
+
tags fix
|
5
|
+
|
6
|
+
2007-05-17 08:00 +0200 Anton 'tony' Bangratz <tony@twincode.net> (63ed2815f13f)
|
7
|
+
|
8
|
+
* .autotest, .hgignore, .hgtags, .in.vim, MIT-LICENSE, README,
|
9
|
+
Rakefile, lib/net/nntp.rb, lib/net/nntp_article.rb,
|
10
|
+
lib/net/nntp_group.rb, tags, test/functional/test_nntp.rb,
|
11
|
+
test/mock/mock_socket.rb, test/unit/test_nntp_article.rb,
|
12
|
+
test/unit/test_nntp_group.rb:
|
13
|
+
Safe commit
|
14
|
+
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2007 Anton Bangratz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
libruby-nntp
|
2
|
+
by Anton Bangratz
|
3
|
+
|
4
|
+
== DESCRIPTION
|
5
|
+
|
6
|
+
The Net::NNTP library provides a simple communication layer for the NNTP (Network News Transfer Protocol).
|
7
|
+
|
8
|
+
== FEATURES
|
9
|
+
|
10
|
+
The Net::NNTP library provides a communication layer in Net::XXX style for NNTP.
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
== SYNOPSIS
|
15
|
+
|
16
|
+
Net::NNTP uses a simple interface to wrap commands to communicate with an NNTP server.
|
17
|
+
|
18
|
+
=== Example
|
19
|
+
|
20
|
+
nntp = Net::NNTP.new('localhost')
|
21
|
+
if nntp.authenticate('user', 'xxxx')
|
22
|
+
nntp.group 'alt.test'
|
23
|
+
if nntp.next
|
24
|
+
article = nntp.article
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
== INSTALL
|
29
|
+
|
30
|
+
* sudo gem install libruby-nntp or
|
31
|
+
* sudo dpkg -r libruby-0.0.1.deb
|
data/lib/net/nntp.rb
ADDED
@@ -0,0 +1,286 @@
|
|
1
|
+
# = Net::NNTP class
|
2
|
+
# Author:: Anton Bangratz
|
3
|
+
require 'socket'
|
4
|
+
require 'thread'
|
5
|
+
require 'timeout' # :nodoc:
|
6
|
+
require 'net/nntp_group'
|
7
|
+
require 'net/nntp_article'
|
8
|
+
|
9
|
+
|
10
|
+
module Net
|
11
|
+
class NNTP
|
12
|
+
VERSION = "0.0.2"
|
13
|
+
include Timeout # :nodoc:
|
14
|
+
|
15
|
+
# Error to indicate that NNTP Command failed gracefully
|
16
|
+
class CommandFailedError < StandardError
|
17
|
+
end
|
18
|
+
# Error to indicate that a Protocol Error occured during NNTP command execution
|
19
|
+
class ProtocolError < StandardError
|
20
|
+
end
|
21
|
+
attr_reader :socket, :grouplist, :overview_format
|
22
|
+
|
23
|
+
# initializes NNTP class with host and port
|
24
|
+
def initialize(host, port = 119)
|
25
|
+
@host = host
|
26
|
+
@port = port
|
27
|
+
@socket_class = TCPSocket
|
28
|
+
@group = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Actually connects to NNTP host and port given in new()
|
32
|
+
def connect
|
33
|
+
@socket = @socket_class.new(@host, @port)
|
34
|
+
@welcome = @socket.recv 1024
|
35
|
+
end
|
36
|
+
|
37
|
+
# Uses authinfo commands to authenticate. Timeout for first command is set to 10 seconds.
|
38
|
+
#
|
39
|
+
# Returns true on success, false on failure.
|
40
|
+
def authenticate(user, pass)
|
41
|
+
cmd = "authinfo user #{user}"
|
42
|
+
send_cmd cmd
|
43
|
+
response = nil
|
44
|
+
timeout(10) do
|
45
|
+
response = @socket.recv 1024
|
46
|
+
end
|
47
|
+
if response[0..2] == '381' then
|
48
|
+
cmd = "authinfo pass #{pass}"
|
49
|
+
send_cmd cmd
|
50
|
+
response = @socket.recv 1024
|
51
|
+
end
|
52
|
+
return response && response[0..2] == '281'
|
53
|
+
end
|
54
|
+
|
55
|
+
# Issues 'GROUP' command to NNTP Server and creates new active group from returning data.
|
56
|
+
#
|
57
|
+
# Throws CommandFailedError
|
58
|
+
#
|
59
|
+
def group(group)
|
60
|
+
send_cmd "group #{group}"
|
61
|
+
response = @socket.readline
|
62
|
+
responsecode, cnt, first, last, name = response.split
|
63
|
+
if responsecode == '211'
|
64
|
+
@group = Group.new(name)
|
65
|
+
@group.article_info = [cnt, first, last]
|
66
|
+
@group
|
67
|
+
else
|
68
|
+
raise CommandFailedError, response
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Issues 'HELP' command to NNTP Server, and returns raw response.
|
73
|
+
def help
|
74
|
+
send_cmd("help")
|
75
|
+
read_response()
|
76
|
+
end
|
77
|
+
|
78
|
+
# Issues 'XHDR' command to NNTP Server, and returns raw response. Checks if group has been selected, selects group
|
79
|
+
# otherwise.
|
80
|
+
#
|
81
|
+
# TODO:: Implement XHDR header <message-id>
|
82
|
+
def xhdr(groupname, header, rest)
|
83
|
+
group(groupname) unless (@group && @group.name == groupname)
|
84
|
+
cmd = "xhdr #{header}"
|
85
|
+
suffix = numbers_or_id(rest)
|
86
|
+
send_cmd([cmd, suffix].join(' '))
|
87
|
+
read_response()
|
88
|
+
end
|
89
|
+
|
90
|
+
# Issues 'XOVER' command to NNTP Server, and returns raw response. Checks if group has been selected, selects group
|
91
|
+
# otherwise.
|
92
|
+
#
|
93
|
+
def xover(groupname, rest)
|
94
|
+
group(groupname) unless (@group && @group.name == groupname)
|
95
|
+
prefix = "xover"
|
96
|
+
suffix = numbers_or_id(rest)
|
97
|
+
cmd = [prefix, suffix].join ' '
|
98
|
+
send_cmd(cmd)
|
99
|
+
read_response()
|
100
|
+
end
|
101
|
+
|
102
|
+
# Issues 'LISTGROUP' command to NNTP Server, and returns raw response. Checks if group has been selected, selects group
|
103
|
+
# otherwise.
|
104
|
+
#
|
105
|
+
def listgroup(groupname)
|
106
|
+
group(groupname) unless (@group && @group.name == groupname)
|
107
|
+
send_cmd('listgroup')
|
108
|
+
read_response()
|
109
|
+
end
|
110
|
+
|
111
|
+
# Issues 'LIST' command to NNTP Server. Depending on server capabilities and given keyword, can either set overview
|
112
|
+
# format (if called with 'overview.fmt') or create a grouplist (see Attributes)
|
113
|
+
#
|
114
|
+
# Throws CommandFailedError
|
115
|
+
|
116
|
+
def list(keyword=nil, pattern=nil)
|
117
|
+
cmd = ['list', keyword, pattern].join ' '
|
118
|
+
send_cmd(cmd)
|
119
|
+
list = read_response()
|
120
|
+
responsecode = list[0][0..2]
|
121
|
+
case responsecode
|
122
|
+
when '215'
|
123
|
+
case keyword
|
124
|
+
when /overview.fmt/
|
125
|
+
@overview_format_raw = list
|
126
|
+
@overview_format = Net::NNTP.parse_overview_format list.join
|
127
|
+
else
|
128
|
+
create_grouplist(list)
|
129
|
+
end
|
130
|
+
|
131
|
+
when '501', '503', '500'
|
132
|
+
raise CommandFailedError, list
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# prepares overview format as read from server, used by Net::NNTP::Article and list()
|
137
|
+
def self.parse_overview_format(format)
|
138
|
+
overview_format = %w{id}
|
139
|
+
format.split(/\r?\n/).each do |line|
|
140
|
+
next if line[0] == ?2 || line[0] == ?.
|
141
|
+
ident = line.scan(/\w/).join.downcase
|
142
|
+
unless ident[0..3] == 'xref'
|
143
|
+
overview_format << ident
|
144
|
+
else
|
145
|
+
overview_format << 'xref'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
overview_format
|
149
|
+
end
|
150
|
+
|
151
|
+
# TODO: complete implementation
|
152
|
+
def stat
|
153
|
+
end
|
154
|
+
|
155
|
+
# Issues 'HEAD' command to NNTP server, returning raw response
|
156
|
+
#
|
157
|
+
# Throws CommandFailedError
|
158
|
+
def head(args=nil)
|
159
|
+
suffix = numbers_or_id(args)
|
160
|
+
cmd = 'head'
|
161
|
+
cmd = ['head', suffix].join " " if suffix
|
162
|
+
send_cmd(cmd)
|
163
|
+
response = read_response()
|
164
|
+
case response[0][0..2]
|
165
|
+
when '221'
|
166
|
+
return response
|
167
|
+
else
|
168
|
+
raise CommandFailedError, response
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Issues 'BODY' command to NNTP server, returning raw response.
|
173
|
+
# options:: messageid|id
|
174
|
+
#
|
175
|
+
# Throws CommandFailedError
|
176
|
+
def body(args=nil)
|
177
|
+
suffix = args
|
178
|
+
cmd = 'body'
|
179
|
+
cmd = ['body', suffix].join " " if suffix
|
180
|
+
send_cmd(cmd)
|
181
|
+
response = read_response()
|
182
|
+
case response[0][0..2]
|
183
|
+
when '222'
|
184
|
+
return response
|
185
|
+
else
|
186
|
+
raise CommandFailedError, response
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Issues 'ARTICLE' command to NNTP server, returning raw response.
|
191
|
+
# options:: messageid|id
|
192
|
+
#
|
193
|
+
# Throws CommandFailedError
|
194
|
+
def article(args=nil)
|
195
|
+
suffix = args
|
196
|
+
cmd = 'article'
|
197
|
+
cmd = ['article', suffix].join " " if suffix
|
198
|
+
send_cmd(cmd)
|
199
|
+
response = read_response()
|
200
|
+
case response[0][0..2]
|
201
|
+
when '220'
|
202
|
+
return response
|
203
|
+
else
|
204
|
+
raise CommandFailedError, response
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def last_or_next(cmd)
|
209
|
+
raise ProtocolError, "No group selected" unless @group
|
210
|
+
send_cmd(cmd)
|
211
|
+
response = read_response()[0]
|
212
|
+
code = response[0..2]
|
213
|
+
article = @group.articles.create
|
214
|
+
case code
|
215
|
+
when '223'
|
216
|
+
code, id, msgid, what = response.split
|
217
|
+
article.id = id
|
218
|
+
article.messageid = msgid
|
219
|
+
else
|
220
|
+
raise CommandFailedError, response
|
221
|
+
end
|
222
|
+
response
|
223
|
+
end
|
224
|
+
|
225
|
+
# Issues the LAST command to the NNTP server, returning the raw response
|
226
|
+
def last
|
227
|
+
last_or_next("last")
|
228
|
+
end
|
229
|
+
|
230
|
+
def next
|
231
|
+
last_or_next("next")
|
232
|
+
end
|
233
|
+
|
234
|
+
def create_grouplist(response)
|
235
|
+
@grouplist = {}
|
236
|
+
response.each do |line|
|
237
|
+
next if line[0..2] == '215'
|
238
|
+
break if line =~ /^\.\r\n$/
|
239
|
+
groupinfo = line.split
|
240
|
+
group = Group.new groupinfo.shift
|
241
|
+
group.article_info = groupinfo
|
242
|
+
@grouplist[group.name] = group
|
243
|
+
end
|
244
|
+
@grouplist
|
245
|
+
end
|
246
|
+
|
247
|
+
def send_cmd(cmd)
|
248
|
+
@socket.write(cmd+"\r\n")
|
249
|
+
end
|
250
|
+
|
251
|
+
def read_response
|
252
|
+
response = ''
|
253
|
+
queue = Queue.new
|
254
|
+
str = ''
|
255
|
+
ra = []
|
256
|
+
loop do
|
257
|
+
str = @socket.readline
|
258
|
+
queue << str
|
259
|
+
ra << str
|
260
|
+
break if str == ".\r\n" || !str
|
261
|
+
end
|
262
|
+
ra
|
263
|
+
end
|
264
|
+
|
265
|
+
def numbers_or_id(hash)
|
266
|
+
return nil unless hash
|
267
|
+
suffix = ''
|
268
|
+
from = hash[:from]
|
269
|
+
to = hash[:to]
|
270
|
+
msgid = hash[:message_id]
|
271
|
+
if from
|
272
|
+
suffix = "#{from}-"
|
273
|
+
suffix += "#{to}" if to
|
274
|
+
elsif msgid
|
275
|
+
suffix = "#{msgid}"
|
276
|
+
end
|
277
|
+
suffix
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
private :read_response, :numbers_or_id, :send_cmd, :last_or_next, :create_grouplist
|
282
|
+
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# vim:sts=2:ts=2:sw=2:sta:noet
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Net
|
2
|
+
class NNTP
|
3
|
+
class Article
|
4
|
+
attr_accessor :id, :messageid, :subject, :group
|
5
|
+
attr_reader :overview_format, :bytes, :lines, :xref, :date
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@overview_format = %w{id}
|
9
|
+
end
|
10
|
+
|
11
|
+
def overview_format=(format)
|
12
|
+
@overview_format = Net::NNTP.parse_overview_format format
|
13
|
+
end
|
14
|
+
|
15
|
+
def overview(over)
|
16
|
+
over.split(/\t/).each_with_index do |value, index|
|
17
|
+
ident = @overview_format[index]
|
18
|
+
eval "@#{ident} = value;"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Net
|
2
|
+
|
3
|
+
class NNTP
|
4
|
+
|
5
|
+
class Group
|
6
|
+
attr_reader :name, :article_count, :article_first, :article_last
|
7
|
+
attr_reader :hi, :lo, :postingmode
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@articles ||= Articles.new(self)
|
12
|
+
#@articles.group = self
|
13
|
+
@article_first = @article_last = @article_count = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def article_info=(art_array)
|
17
|
+
@article_count = art_array[0].to_i
|
18
|
+
@article_first = art_array[1].to_i
|
19
|
+
@article_last = art_array[2].to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
def articles
|
23
|
+
@articles
|
24
|
+
end
|
25
|
+
|
26
|
+
def articles=(articles)
|
27
|
+
@articles = articles
|
28
|
+
end
|
29
|
+
|
30
|
+
def listinfo(hi, lo, postingmode)
|
31
|
+
@hi = hi
|
32
|
+
@lo = lo
|
33
|
+
@postingmode = postingmode
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
"Group: #{@name} #{@article_count} #{@article_first} #{@article_last}"
|
38
|
+
end
|
39
|
+
|
40
|
+
class Articles
|
41
|
+
|
42
|
+
attr_accessor :group
|
43
|
+
|
44
|
+
def initialize(group)
|
45
|
+
@articles ||=[]
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_from_over(over, format)
|
49
|
+
article = Article.new
|
50
|
+
article.overview_format = format
|
51
|
+
article.overview(over)
|
52
|
+
@articles << article
|
53
|
+
end
|
54
|
+
|
55
|
+
def length
|
56
|
+
@articles.length
|
57
|
+
end
|
58
|
+
|
59
|
+
def <<(article)
|
60
|
+
@articles << article
|
61
|
+
end
|
62
|
+
|
63
|
+
def create
|
64
|
+
a = Article.new
|
65
|
+
a.group = self.group
|
66
|
+
@articles << a
|
67
|
+
a
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'net/nntp.rb'
|
4
|
+
require 'mock/mock_socket'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
module TestNet
|
9
|
+
class TestNNTP < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
nntp_connect_and_auth('localhost', 119, 'dummy', 'test')
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_new
|
16
|
+
host = 'localhost'
|
17
|
+
port = '119'
|
18
|
+
assert_nothing_raised do
|
19
|
+
@nntp = Net::NNTP.new(host)
|
20
|
+
end
|
21
|
+
assert_nothing_raised do
|
22
|
+
nntp_new(host, port)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_connect
|
27
|
+
assert_nothing_raised do
|
28
|
+
@nntp.connect
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_help
|
33
|
+
help = @nntp.help.join
|
34
|
+
assert_equal '100', help[0..2]
|
35
|
+
assert_equal 39, help.length
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_authenticate
|
39
|
+
assert_nothing_raised do
|
40
|
+
assert nntp_connect_and_auth('localhost', 119, 'dummy', 'test')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_group
|
45
|
+
assert_nothing_raised do
|
46
|
+
group = @nntp.group('at.linux')
|
47
|
+
assert_kind_of Net::NNTP::Group, group
|
48
|
+
assert_equal 'at.linux', group.name
|
49
|
+
assert_equal 12, group.article_count
|
50
|
+
assert_equal 1363, group.article_first
|
51
|
+
assert_equal 1375, group.article_last
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_xhdr
|
56
|
+
headers = @nntp.xhdr('at.linux', 'subject', :from => 1363, :to => 1375)
|
57
|
+
assert_equal 15, headers.length
|
58
|
+
assert_equal '221', headers[0][0..2]
|
59
|
+
assert_equal "1364", headers[2].split[0]
|
60
|
+
header = @nntp.xhdr('at.linux', 'subject', :message_id => "<slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>").join
|
61
|
+
assert_equal 49, header.length
|
62
|
+
assert_equal "1375", header.split[0]
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_xhdr_fails
|
66
|
+
header = @nntp.xhdr('at.linux', '', {}).join
|
67
|
+
assert_equal '502', header[0..2]
|
68
|
+
assert_raise(Net::NNTP::CommandFailedError) do
|
69
|
+
header = @nntp.xhdr('at.xxx', 'subject', {})
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def test_group_fails
|
75
|
+
assert_raise(Net::NNTP::CommandFailedError) do
|
76
|
+
group = @nntp.group('at.xxx')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_xover
|
81
|
+
overviews = @nntp.xover('at.linux', :from => 1363, :to => 1375)
|
82
|
+
assert_equal 15, overviews.length
|
83
|
+
assert_equal '224', overviews[0][0..2]
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_xover_fails
|
87
|
+
over = @nntp.xover('at.linux', :from => 1363, :to => 1375)
|
88
|
+
over = @nntp.xover('at.linux', :message_id => "<slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>").join
|
89
|
+
assert_equal '502', over[0..2]
|
90
|
+
assert_raises(Net::NNTP::CommandFailedError) do
|
91
|
+
over = @nntp.xover('at.xxx', :message_id => "<slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_listgroup
|
96
|
+
list = @nntp.listgroup('at.linux')
|
97
|
+
assert_equal 15, list.length
|
98
|
+
match = /(\d{3}).*for\s+(\S+)\s/.match(list[0])
|
99
|
+
assert_equal "211", match[1]
|
100
|
+
assert_equal "at.linux", match[2]
|
101
|
+
assert_equal "1365\r\n", list[3]
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_list
|
105
|
+
assert_respond_to @nntp, :list
|
106
|
+
assert_nothing_raised do
|
107
|
+
@nntp.list('overview.fmt')
|
108
|
+
assert_equal 9, @nntp.overview_format.length
|
109
|
+
@nntp.list()
|
110
|
+
assert_not_equal 0, @nntp.grouplist.length
|
111
|
+
assert_not_nil @nntp.grouplist
|
112
|
+
assert_equal 'at.test', @nntp.grouplist['at.test'].name
|
113
|
+
@nntp.list('active')
|
114
|
+
assert_equal 'at.test', @nntp.grouplist['at.test'].name
|
115
|
+
@nntp.list('active.times')
|
116
|
+
@nntp.list('active.times', 'at.*')
|
117
|
+
end
|
118
|
+
assert_raise Net::NNTP::CommandFailedError do
|
119
|
+
@nntp.list('distrib.pat', 'at.*')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_article
|
124
|
+
assert_raises Net::NNTP::CommandFailedError do
|
125
|
+
article = @nntp.article
|
126
|
+
end
|
127
|
+
article = @nntp.article("<5d6be$4625ae23$51df8a12$32566@news.inode.at>")
|
128
|
+
response, id, msgid = article[0].split
|
129
|
+
assert_equal '220', response
|
130
|
+
assert_equal '1392', id
|
131
|
+
assert_equal "<5d6be$4625ae23$51df8a12$32566@news.inode.at>", msgid
|
132
|
+
group = @nntp.group 'at.linux'
|
133
|
+
article = @nntp.article '1392'
|
134
|
+
response, id, msgid = article[0].split
|
135
|
+
assert_equal '220', response
|
136
|
+
assert_equal '1392', id
|
137
|
+
assert_equal "<5d6be$4625ae23$51df8a12$32566@news.inode.at>", msgid
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_head
|
141
|
+
nntp_connect_and_auth('localhost', 119, 'dummy', 'test')
|
142
|
+
assert_nothing_raised do
|
143
|
+
assert_respond_to @nntp, :head
|
144
|
+
end
|
145
|
+
assert_raise Net::NNTP::CommandFailedError do
|
146
|
+
head = @nntp.head
|
147
|
+
end
|
148
|
+
@nntp.group 'at.linux'
|
149
|
+
@io = [
|
150
|
+
"221 1430 <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net> article retrieved - head follows\r\n",
|
151
|
+
"Path: vietwist00.chello.at!newsfeed02.chello.at!newsfeed01.chello.at!newsfeed.arcor.de!newsspool1.arcor-online.net!news.arcor.de.POSTED!not-for-mail\r\n",
|
152
|
+
"Message-ID: <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>\r\n",
|
153
|
+
"From: Gerhard Engler <gerhard.engler@gmx.de>\r\n",
|
154
|
+
"Newsgroups: at.linux\r\n",
|
155
|
+
"Subject: Re: udev_node_mknod: /dev/capi Operation not permitted\r\n",
|
156
|
+
"Date: Tue, 24 Apr 2007 14:39:11 +0200\r\n",
|
157
|
+
"References: <4629ee10$0$10187$9b4e6d93@newsspool4.arcor-online.net> <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
158
|
+
"Lines: 26\r\n",
|
159
|
+
"User-Agent: Thunderbird 1.5.0.10 (Windows/20070221)\r\n",
|
160
|
+
"MIME-Version: 1.0\r\n",
|
161
|
+
"In-Reply-To: <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
162
|
+
"Content-Type: text/plain; charset=ISO-8859-15; format=flowed\r\n",
|
163
|
+
"Content-Transfer-Encoding: 7bit\r\n",
|
164
|
+
"Organization: Arcor\r\n",
|
165
|
+
"NNTP-Posting-Date: 24 Apr 2007 14:39:11 CEST\r\n",
|
166
|
+
"NNTP-Posting-Host: 6cf11d8c.newsspool1.arcor-online.net\r\n",
|
167
|
+
"X-Trace: DXC=Cd=D_AR>:`a^Y=RbYBPl4`ic==]BZ:afn4Fo<]lROoRaFl8W>\BH3Yb7K@fQgPi`FgUTEAfnAR\Ta@JWJ8E:^d<ob]cIfD6hVgh<SdIn0f]3?i\r\n",
|
168
|
+
"X-Complaints-To: usenet-abuse@arcor.de\r\n",
|
169
|
+
"Xref: sensor.twincode.net at.linux:1430\r\n",
|
170
|
+
".\r\n"
|
171
|
+
]
|
172
|
+
head = @nntp.head
|
173
|
+
assert_kind_of Array, head
|
174
|
+
response, id, msgid = head[0].split
|
175
|
+
assert_equal '221', response
|
176
|
+
assert_equal '1430', id
|
177
|
+
assert_equal '<462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>', msgid
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_body
|
181
|
+
assert_raises Net::NNTP::CommandFailedError do
|
182
|
+
body = @nntp.body
|
183
|
+
end
|
184
|
+
body = @nntp.body("<5d6be$4625ae23$51df8a12$32566@news.inode.at>")
|
185
|
+
response, id, msgid = body[0].split
|
186
|
+
assert_equal '222', response
|
187
|
+
assert_equal '1392', id
|
188
|
+
assert_equal "<5d6be$4625ae23$51df8a12$32566@news.inode.at>", msgid
|
189
|
+
group = @nntp.group 'at.linux'
|
190
|
+
body = @nntp.body '1392'
|
191
|
+
response, id, msgid = body[0].split
|
192
|
+
assert_equal '222', response
|
193
|
+
assert_equal '1392', id
|
194
|
+
assert_equal "<5d6be$4625ae23$51df8a12$32566@news.inode.at>", msgid
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_stat
|
198
|
+
assert_nothing_raised do
|
199
|
+
assert_respond_to @nntp, :stat
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_last
|
204
|
+
assert_raise Net::NNTP::ProtocolError do
|
205
|
+
last = @nntp.last
|
206
|
+
end
|
207
|
+
@nntp.group 'at.linux'
|
208
|
+
assert_raise Net::NNTP::CommandFailedError do
|
209
|
+
last = @nntp.last
|
210
|
+
end
|
211
|
+
@nntp.next
|
212
|
+
@nntp.next
|
213
|
+
last = @nntp.last
|
214
|
+
assert_kind_of String, last
|
215
|
+
response, article, msgid, rest = last.split
|
216
|
+
assert_equal "223", response
|
217
|
+
assert_equal "1363", article
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_next
|
221
|
+
assert_raise Net::NNTP::ProtocolError do
|
222
|
+
anext = @nntp.next
|
223
|
+
end
|
224
|
+
@nntp.group 'at.linux'
|
225
|
+
anext = @nntp.next
|
226
|
+
assert_kind_of String, anext
|
227
|
+
response, article, msgid, rest = anext.split
|
228
|
+
assert_equal "223", response
|
229
|
+
assert_equal "1363", article
|
230
|
+
assert_equal "<example.msgid@fake.host>", msgid
|
231
|
+
anext = @nntp.next
|
232
|
+
response, article, msgid, rest = anext.split
|
233
|
+
assert_equal "1364", article
|
234
|
+
end
|
235
|
+
|
236
|
+
private
|
237
|
+
def nntp_new(host, port=119)
|
238
|
+
@nntp = Net::NNTP.new(host, port)
|
239
|
+
end
|
240
|
+
def nntp_connect_and_auth(host, port, user, pass)
|
241
|
+
@nntp = Net::NNTP.new(host, port)
|
242
|
+
@nntp.instance_variable_set :@socket_class, MockSocket
|
243
|
+
@nntp.connect
|
244
|
+
@nntp.socket.activate
|
245
|
+
@nntp.authenticate(user, pass)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
@@ -0,0 +1,330 @@
|
|
1
|
+
require 'mock'
|
2
|
+
class MockSocket < Test::Unit::MockObject( TCPSocket )
|
3
|
+
def initialize(host, port)
|
4
|
+
super
|
5
|
+
@io = ["200 Welcome\r\n"]
|
6
|
+
@authenticated = false
|
7
|
+
@group_selected = nil
|
8
|
+
@last_article = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def alive?
|
12
|
+
super
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def recv(len)
|
17
|
+
return readline
|
18
|
+
end
|
19
|
+
|
20
|
+
def read( len )
|
21
|
+
super # Call the mocked method to record the call
|
22
|
+
rval = @io[0,len]
|
23
|
+
@io[0,len] = ''
|
24
|
+
return %w{ you should never reach this }
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts(stuff)
|
28
|
+
super
|
29
|
+
stuff += "\r\n"
|
30
|
+
write stuff
|
31
|
+
end
|
32
|
+
|
33
|
+
def write( str )
|
34
|
+
super # Call the mocked method to record the call
|
35
|
+
@io = []
|
36
|
+
case str.downcase
|
37
|
+
when /^body(.*)/
|
38
|
+
body = [
|
39
|
+
"222 1392 <5d6be$4625ae23$51df8a12$32566@news.inode.at> article retrieved - body follows\r\n",
|
40
|
+
"Hi,\r\n",
|
41
|
+
"\r\n",
|
42
|
+
"kennt ihr eine Moeglichkeit den maximalen Speicherbedarf eines Programms \r\n",
|
43
|
+
"ueber dessen gesamte Laufzeit zu ermitteln? Also keine Momentaufnahme \r\n",
|
44
|
+
"wie mit ps, top & Co?\r\n",
|
45
|
+
"\r\n",
|
46
|
+
"Danke & vG\r\n",
|
47
|
+
"Franz Hollerer\r\n",
|
48
|
+
".\r\n"
|
49
|
+
]
|
50
|
+
case $1
|
51
|
+
when /^\s+1392/, /^\s*$/
|
52
|
+
if @group_selected
|
53
|
+
@io = body
|
54
|
+
else
|
55
|
+
@io = ["412 No Group selected"]
|
56
|
+
end
|
57
|
+
when /^\s*<5d6be\$4625ae23\$51df8a12\$32566@news\.inode\.at>/
|
58
|
+
@io = body
|
59
|
+
else
|
60
|
+
@io = ["No such article"]
|
61
|
+
end
|
62
|
+
when /^article(.*)/
|
63
|
+
article = [
|
64
|
+
"220 1392 <5d6be$4625ae23$51df8a12$32566@news.inode.at> article retrieved - text follows\r\n",
|
65
|
+
"Path: vietwist00.chello.at!newsfeed02.chello.at!news.inode.at.POSTED!not-for-mail\r\n",
|
66
|
+
"Message-ID: <5d6be$4625ae23$51df8a12$32566@news.inode.at>\r\n",
|
67
|
+
"From: Franz Hollerer <franz.hollerer@ims.co.at>\r\n",
|
68
|
+
"Newsgroups: at.linux\r\n",
|
69
|
+
"Subject: Q: maximalen Speicherbedarfs eines Programms ueber dessen gesamte\r\n",
|
70
|
+
" Laufzeit\r\n",
|
71
|
+
"Date: Wed, 18 Apr 2007 07:34:56 +0200\r\n",
|
72
|
+
"Lines: 8\r\n",
|
73
|
+
"User-Agent: Thunderbird 1.5.0.10 (Windows/20070221)\r\n",
|
74
|
+
"MIME-Version: 1.0\r\n",
|
75
|
+
"Content-Type: text/plain; charset=ISO-8859-15; format=flowed\r\n",
|
76
|
+
"Content-Transfer-Encoding: 7bit\r\n",
|
77
|
+
"X-Complaints-To: abuse@inode.at\r\n",
|
78
|
+
"NNTP-Posting-Host: 81.223.138.18 (81.223.138.18)\r\n",
|
79
|
+
"NNTP-Posting-Date: Wed, 18 Apr 2007 07:35:31 +0200\r\n",
|
80
|
+
"X-Trace: 5d6be4625ae23f47a2fb732566\r\n",
|
81
|
+
"Xref: sensor.twincode.net at.linux:1392\r\n",
|
82
|
+
"\r\n",
|
83
|
+
"Hi,\r\n",
|
84
|
+
"\r\n",
|
85
|
+
"kennt ihr eine Moeglichkeit den maximalen Speicherbedarf eines Programms \r\n",
|
86
|
+
"ueber dessen gesamte Laufzeit zu ermitteln? Also keine Momentaufnahme \r\n",
|
87
|
+
"wie mit ps, top & Co?\r\n",
|
88
|
+
"\r\n",
|
89
|
+
"Danke & vG\r\n",
|
90
|
+
"Franz Hollerer\r\n",
|
91
|
+
".\r\n"
|
92
|
+
]
|
93
|
+
case $1
|
94
|
+
when /\s*1392/
|
95
|
+
if @group_selected
|
96
|
+
@io = article
|
97
|
+
else
|
98
|
+
@io = ["412 No Group selected"]
|
99
|
+
end
|
100
|
+
when /^\s*<5d6be\$4625ae23\$51df8a12\$32566@news\.inode\.at>/
|
101
|
+
@io = article
|
102
|
+
else
|
103
|
+
@io = ["430 No such article"]
|
104
|
+
end
|
105
|
+
when /^list\b\s*(.*)\r\n$/
|
106
|
+
case $1
|
107
|
+
when /overview.fmt/i
|
108
|
+
@io = ["215 Order of fields in overview database.\r\nSubject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n.\r\n" ]
|
109
|
+
when /active\s*(.*)/
|
110
|
+
@io = ["215 Newsgroups in form \"group high low flags\".", "at.test 200 100 y\r\n", "at.linux 100 90 n\r\n", ".\r\n"]
|
111
|
+
when /^\s*$/
|
112
|
+
@io = ["215 Newsgroups in form \"group high low flags\".", "at.test 200 100 y\r\n", "at.linux 100 90 n\r\n", ".\r\n"]
|
113
|
+
else
|
114
|
+
@io = ["501 Bad Command Usage"]
|
115
|
+
end
|
116
|
+
when "help\r\n" then
|
117
|
+
@io = ["100 Legal commands on THIS server:\r\n", ".\r\n"]
|
118
|
+
when /^next/i
|
119
|
+
if @group_selected
|
120
|
+
if @last_article
|
121
|
+
if @last_article < 1375
|
122
|
+
@last_article += 1
|
123
|
+
else
|
124
|
+
@last_article = nil
|
125
|
+
end
|
126
|
+
else
|
127
|
+
@last_article = 1363
|
128
|
+
end
|
129
|
+
@io = @last_article ? ["223 #{@last_article} <example.msgid@fake.host> retrieved"] : ['421 No next article in group']
|
130
|
+
else
|
131
|
+
@io = ['412 No Group selected']
|
132
|
+
end
|
133
|
+
when /^last/i
|
134
|
+
if @group_selected
|
135
|
+
if @last_article
|
136
|
+
if @last_article > 1363
|
137
|
+
@last_article -= 1
|
138
|
+
else
|
139
|
+
@last_article = nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
@io = @last_article ? ["223 #{@last_article} <example.msgid@fake.host> retrieved"] : ['421 No next article in group']
|
143
|
+
else
|
144
|
+
@io = ['412 No Group selected']
|
145
|
+
end
|
146
|
+
when /^mode reader/i
|
147
|
+
@io = ["200 Welcome"]
|
148
|
+
when /^listgroup\s*(.*)\s*/i
|
149
|
+
case $1
|
150
|
+
when 'at.linux'
|
151
|
+
@io = [
|
152
|
+
"211 Article list for at.linux follows\r\n",
|
153
|
+
"1363\r\n",
|
154
|
+
"1364\r\n",
|
155
|
+
"1365\r\n",
|
156
|
+
"1366\r\n",
|
157
|
+
"1367\r\n",
|
158
|
+
"1368\r\n",
|
159
|
+
"1369\r\n",
|
160
|
+
"1370\r\n",
|
161
|
+
"1371\r\n",
|
162
|
+
"1372\r\n",
|
163
|
+
"1373\r\n",
|
164
|
+
"1374\r\n",
|
165
|
+
"1375\r\n",
|
166
|
+
".\r\n"
|
167
|
+
]
|
168
|
+
else
|
169
|
+
if @group_selected
|
170
|
+
@io = [
|
171
|
+
"211 Article list for at.linux follows\r\n",
|
172
|
+
"1363\r\n",
|
173
|
+
"1364\r\n",
|
174
|
+
"1365\r\n",
|
175
|
+
"1366\r\n",
|
176
|
+
"1367\r\n",
|
177
|
+
"1368\r\n",
|
178
|
+
"1369\r\n",
|
179
|
+
"1370\r\n",
|
180
|
+
"1371\r\n",
|
181
|
+
"1372\r\n",
|
182
|
+
"1373\r\n",
|
183
|
+
"1374\r\n",
|
184
|
+
"1375\r\n",
|
185
|
+
".\r\n"
|
186
|
+
]
|
187
|
+
else
|
188
|
+
@io = ['412 No Group selected']
|
189
|
+
end
|
190
|
+
end
|
191
|
+
when "quit\r\n" then
|
192
|
+
@io = ["200 Good bye"]
|
193
|
+
when "authinfo user dummy\r\n"
|
194
|
+
@io = ["381 More authentication details needed"]
|
195
|
+
when "authinfo pass test\r\n"
|
196
|
+
@io = ["281 Welcome to dummytest"]
|
197
|
+
when /^group\s+(.+)\s*\r\n$/
|
198
|
+
case $1
|
199
|
+
when 'at.linux'
|
200
|
+
@io = ["211 12 1363 1375 at.linux"]
|
201
|
+
@group_selected = 'at.linux'
|
202
|
+
else
|
203
|
+
@io = ["411 No such group"]
|
204
|
+
end
|
205
|
+
when "xhdr subject <slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>\r\n"
|
206
|
+
@io =
|
207
|
+
["1375 Re: Bitte um Meinungen ==> Virtualisierung\r\n"]
|
208
|
+
when "xhdr subject 1363-1375\r\n"
|
209
|
+
if @group_selected
|
210
|
+
@io = [
|
211
|
+
"221 Subject header (from overview) for postings 1363-1375\r\n",
|
212
|
+
"1363 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
213
|
+
"1364 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
214
|
+
"1365 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
215
|
+
"1366 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
216
|
+
"1367 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
217
|
+
"1368 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
218
|
+
"1369 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
219
|
+
"1370 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
220
|
+
"1371 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
221
|
+
"1372 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
222
|
+
"1373 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
223
|
+
"1374 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
224
|
+
"1375 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
225
|
+
".\r\n"
|
226
|
+
]
|
227
|
+
else
|
228
|
+
@io = ['412 No group selected']
|
229
|
+
end
|
230
|
+
when "xover 1363-1375\r\n"
|
231
|
+
if @group_selected
|
232
|
+
@io = [
|
233
|
+
"224 Overview information for postings 1363-1375:\r\n",
|
234
|
+
"1363 Re: Bitte um Meinungen ==> Virtualisierung \"Igo Besser\" <i.besser@aon.at> Sun, 15 Apr 2007 14:09:46 +0200 <46221541$0$2299$91cee783@newsreader01.highway.telekom.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <evt242$1jc7$1@geiz-ist-geil.priv.at> 1165 9 Xref: sensor.twincode.net at.linux:1363\r\n",
|
235
|
+
"1364 Re: Bitte um Meinungen ==> Virtualisierung \"Igo Besser\" <i.besser@aon.at> Sun, 15 Apr 2007 14:14:12 +0200 <4622164b$0$25611$91cee783@newsreader02.highway.telekom.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <4621fc17$0$2315$91cee783@newsreader01.highway.telekom.at> <evt1p1$1jar$1@geiz-ist-geil.priv.at> 1229 13 Xref: sensor.twincode.net at.linux:1364\r\n",
|
236
|
+
"1365 Re: Bitte um Meinungen ==> Virtualisierung \"Peter J. Holzer\" <hjp-usenet2@hjp.at> Sun, 15 Apr 2007 16:39:56 +0200 <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> 2643 42 Xref: sensor.twincode.net at.linux:1365\r\n",
|
237
|
+
"1366 Re: Bitte um Meinungen ==> Virtualisierung \"Igo Besser\" <i.besser@aon.at> Sun, 15 Apr 2007 19:14:08 +0200 <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> 1344 13 Xref: sensor.twincode.net at.linux:1366\r\n",
|
238
|
+
"1367 Re: Bitte um Meinungen ==> Virtualisierung \"Peter J. Holzer\" <hjp-usenet2@hjp.at> Sun, 15 Apr 2007 21:35:27 +0200 <slrnf24vjv.7pk.hjp-usenet2@zeno.hjp.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> 1851 24 Xref: sensor.twincode.net at.linux:1367\r\n",
|
239
|
+
"1368 Re: Bitte um Meinungen ==> Virtualisierung Wolfgang Steger <wolfgangs-spambox@utanet.at> Sun, 15 Apr 2007 21:48:48 +0200 <16caf4-581.ln1@swws1.dyndns.org> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> 2248 20 Xref: sensor.twincode.net at.linux:1368\r\n",
|
240
|
+
"1369 Re: Bitte um Meinungen ==> Virtualisierung Michael Prokop <devnull@michael-prokop.at> Sun, 15 Apr 2007 22:22:46 +0200 <2007-04-15T22-19-44@devnull.michael-prokop.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> <slrnf24vjv.7pk.hjp-usenet2@zeno.hjp.at> 2022 23 Xref: sensor.twincode.net at.linux:1369\r\n",
|
241
|
+
"1370 Re: Bitte um Meinungen ==> Virtualisierung Robert Annessi <robert@annessi.at> Sun, 15 Apr 2007 22:52:36 +0200 <46229089$0$10578$3b214f66@tunews.univie.ac.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> <16caf4-581.ln1@swws1.dyndns.org> 1807 27 Xref: sensor.twincode.net at.linux:1370\r\n",
|
242
|
+
"1371 Re: Bitte um Meinungen ==> Virtualisierung \"Thomas Spachinger\" <t.spachinger@gmx.at> Sun, 15 Apr 2007 22:58:17 +0200 <58fi18F2gdp4eU1@mid.individual.net> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <4621fc17$0$2315$91cee783@newsreader01.highway.telekom.at> <evt1p1$1jar$1@geiz-ist-geil.priv.at> <4622164b$0$25611$91cee783@newsreader02.highway.telekom.at> 1427 18 Xref: sensor.twincode.net at.linux:1371\r\n",
|
243
|
+
"1372 Re: Bitte um Meinungen ==> Virtualisierung Bernd Haug <haug@berndhaug.net> Sun, 15 Apr 2007 23:54:05 +0200 <tgjaf4-lt9.ln1@this.is.a.news.server.you.goddamn.stupid.program> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> <slrnf24vjv.7pk.hjp-usenet2@zeno.hjp.at> 1721 10 Xref: sensor.twincode.net at.linux:1372\r\n",
|
244
|
+
"1373 Re: Bitte um Meinungen ==> Virtualisierung Wolfgang Fuschlberger <usenet-2006-05@fuschlberger.net> Sun, 15 Apr 2007 23:58:07 +0200 <fojaf4-kcj.ln1@window.dtdns.net> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <slrnf24e9s.dtb.hjp-usenet2@zeno.hjp.at> <46225c97$0$25626$91cee783@newsreader02.highway.telekom.at> <16caf4-581.ln1@swws1.dyndns.org> <46229089$0$10578$3b214f66@tunews.univie.ac.at> 1800 17 Xref: sensor.twincode.net at.linux:1373\r\n",
|
245
|
+
"1374 Re: Bitte um Meinungen ==> Virtualisierung Andreas Labres <al-nospam0310&bounce@labres.at> Mon, 16 Apr 2007 08:57:43 +0200 <1tnru1ccirb05.dlg@al.lab.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> 1702 19 Xref: sensor.twincode.net at.linux:1374\r\n",
|
246
|
+
"1375 Re: Bitte um Meinungen ==> Virtualisierung \"Peter J. Holzer\" <hjp-usenet2@hjp.at> Mon, 16 Apr 2007 09:49:46 +0200 <slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at> <4621dbb8$0$2310$91cee783@newsreader01.highway.telekom.at> <dh49f4-qem.ln1@this.is.a.news.server.you.goddamn.stupid.program> <slrnf23snh.dfm.hjp-usenet2@zeno.hjp.at> <4621ff58$0$2307$91cee783@newsreader01.highway.telekom.at> <1tnru1ccirb05.dlg@al.lab.at> 2127 33 Xref: sensor.twincode.net at.linux:1375\r\n",
|
247
|
+
".\r\n"
|
248
|
+
]
|
249
|
+
else
|
250
|
+
@io = ["412 No Group selected"]
|
251
|
+
end
|
252
|
+
when /xover \<.+\>/
|
253
|
+
@io = ["502 Usage: OVER first[-[last]]"]
|
254
|
+
when /^xhdr\s*$/
|
255
|
+
@io = ["502 Usage: HDR header [first[-last]]|[message-id]"]
|
256
|
+
when /^head(.*)$/
|
257
|
+
case $1
|
258
|
+
when /^\s+(1430|<462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>)/
|
259
|
+
@io = [
|
260
|
+
"221 1430 <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net> article retrieved - head follows\r\n",
|
261
|
+
"Path: vietwist00.chello.at!newsfeed02.chello.at!newsfeed01.chello.at!newsfeed.arcor.de!newsspool1.arcor-online.net!news.arcor.de.POSTED!not-for-mail\r\n",
|
262
|
+
"Message-ID: <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>\r\n",
|
263
|
+
"From: Gerhard Engler <gerhard.engler@gmx.de>\r\n",
|
264
|
+
"Newsgroups: at.linux\r\n",
|
265
|
+
"Subject: Re: udev_node_mknod: /dev/capi Operation not permitted\r\n",
|
266
|
+
"Date: Tue, 24 Apr 2007 14:39:11 +0200\r\n",
|
267
|
+
"References: <4629ee10$0$10187$9b4e6d93@newsspool4.arcor-online.net> <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
268
|
+
"Lines: 26\r\n",
|
269
|
+
"User-Agent: Thunderbird 1.5.0.10 (Windows/20070221)\r\n",
|
270
|
+
"MIME-Version: 1.0\r\n",
|
271
|
+
"In-Reply-To: <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
272
|
+
"Content-Type: text/plain; charset=ISO-8859-15; format=flowed\r\n",
|
273
|
+
"Content-Transfer-Encoding: 7bit\r\n",
|
274
|
+
"Organization: Arcor\r\n",
|
275
|
+
"NNTP-Posting-Date: 24 Apr 2007 14:39:11 CEST\r\n",
|
276
|
+
"NNTP-Posting-Host: 6cf11d8c.newsspool1.arcor-online.net\r\n",
|
277
|
+
"X-Trace: DXC=Cd=D_AR>:`a^Y=RbYBPl4`ic==]BZ:afn4Fo<]lROoRaFl8W>\BH3Yb7K@fQgPi`FgUTEAfnAR\Ta@JWJ8E:^d<ob]cIfD6hVgh<SdIn0f]3?i\r\n",
|
278
|
+
"X-Complaints-To: usenet-abuse@arcor.de\r\n",
|
279
|
+
"Xref: sensor.twincode.net at.linux:1430\r\n",
|
280
|
+
".\r\n"
|
281
|
+
]
|
282
|
+
|
283
|
+
when /^\s?$/
|
284
|
+
if @group_selected
|
285
|
+
@io = [
|
286
|
+
"221 1430 <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net> article retrieved - head follows\r\n",
|
287
|
+
"Path: vietwist00.chello.at!newsfeed02.chello.at!newsfeed01.chello.at!newsfeed.arcor.de!newsspool1.arcor-online.net!news.arcor.de.POSTED!not-for-mail\r\n",
|
288
|
+
"Message-ID: <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>\r\n",
|
289
|
+
"From: Gerhard Engler <gerhard.engler@gmx.de>\r\n",
|
290
|
+
"Newsgroups: at.linux\r\n",
|
291
|
+
"Subject: Re: udev_node_mknod: /dev/capi Operation not permitted\r\n",
|
292
|
+
"Date: Tue, 24 Apr 2007 14:39:11 +0200\r\n",
|
293
|
+
"References: <4629ee10$0$10187$9b4e6d93@newsspool4.arcor-online.net> <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
294
|
+
"Lines: 26\r\n",
|
295
|
+
"User-Agent: Thunderbird 1.5.0.10 (Windows/20070221)\r\n",
|
296
|
+
"MIME-Version: 1.0\r\n",
|
297
|
+
"In-Reply-To: <slrnf2np7k.a8e.tom-usenet@eristoteles.iwoars.net>\r\n",
|
298
|
+
"Content-Type: text/plain; charset=ISO-8859-15; format=flowed\r\n",
|
299
|
+
"Content-Transfer-Encoding: 7bit\r\n",
|
300
|
+
"Organization: Arcor\r\n",
|
301
|
+
"NNTP-Posting-Date: 24 Apr 2007 14:39:11 CEST\r\n",
|
302
|
+
"NNTP-Posting-Host: 6cf11d8c.newsspool1.arcor-online.net\r\n",
|
303
|
+
"X-Trace: DXC=Cd=D_AR>:`a^Y=RbYBPl4`ic==]BZ:afn4Fo<]lROoRaFl8W>\BH3Yb7K@fQgPi`FgUTEAfnAR\Ta@JWJ8E:^d<ob]cIfD6hVgh<SdIn0f]3?i\r\n",
|
304
|
+
"X-Complaints-To: usenet-abuse@arcor.de\r\n",
|
305
|
+
"Xref: sensor.twincode.net at.linux:1430\r\n",
|
306
|
+
".\r\n"
|
307
|
+
]
|
308
|
+
else
|
309
|
+
@io = ["412 No Group selected"]
|
310
|
+
end
|
311
|
+
else
|
312
|
+
@io = ["501 Bad Command"]
|
313
|
+
end
|
314
|
+
else
|
315
|
+
@io = ["500 Unknown Command"]
|
316
|
+
end
|
317
|
+
return str.length
|
318
|
+
end
|
319
|
+
|
320
|
+
def readline
|
321
|
+
super
|
322
|
+
@io.shift
|
323
|
+
end
|
324
|
+
|
325
|
+
private
|
326
|
+
def dp(x)
|
327
|
+
$stdout.puts x
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'net/nntp.rb'
|
3
|
+
|
4
|
+
class TestNNTPArticle < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@article = Net::NNTP::Article.new
|
8
|
+
@article.overview_format = "215 Order of fields in overview database.\r\nSubject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n.\r\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_article_new
|
12
|
+
a = Net::NNTP::Article.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_article_id
|
16
|
+
@article.id = 1
|
17
|
+
assert_equal 1, @article.id
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_article_messageid
|
21
|
+
m = '<bla.foo@some.host>'
|
22
|
+
@article.messageid = m
|
23
|
+
assert_equal m, @article.messageid
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_article_subject
|
27
|
+
s = 'bla'
|
28
|
+
@article.subject = s
|
29
|
+
assert_equal s, @article.subject
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_from_xover
|
33
|
+
over = "1\tTesting\t\"abc\" abc@ide.invalid\t17 Aug 2004 14:00:00 GMT\t<this.post@is.invalid>\t\t200\t2\tXref: this.host.invalid alt.test:1"
|
34
|
+
@article.overview(over)
|
35
|
+
assert_equal '1', @article.id
|
36
|
+
assert_equal '<this.post@is.invalid>', @article.messageid
|
37
|
+
assert_equal 'Testing', @article.subject
|
38
|
+
assert_equal 200, @article.bytes.to_i
|
39
|
+
assert_equal 2, @article.lines.to_i
|
40
|
+
assert_equal '17 Aug 2004 14:00:00 GMT', @article.date
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_overview_fmt=
|
44
|
+
|
45
|
+
@article.overview_format = "215 Order of fields in overview database.\r\nSubject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n.\r\n"
|
46
|
+
assert_equal 'subject', @article.overview_format[1]
|
47
|
+
assert_equal 'from', @article.overview_format[2]
|
48
|
+
assert_equal 'date', @article.overview_format[3]
|
49
|
+
assert_equal 'messageid', @article.overview_format[4]
|
50
|
+
assert_equal 'references', @article.overview_format[5]
|
51
|
+
assert_equal 'bytes', @article.overview_format[6]
|
52
|
+
assert_equal 'lines', @article.overview_format[7]
|
53
|
+
assert_equal 'xref', @article.overview_format[8]
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'net/nntp'
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class TestNNTPGroup< Test::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@group = Net::NNTP::Group.new 'at.test'
|
11
|
+
@group = Net::NNTP::Group.new 'at.test'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_init
|
15
|
+
assert_nothing_raised do
|
16
|
+
setup
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_name
|
21
|
+
assert_equal 'at.test', @group.name
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_first
|
25
|
+
@group.article_info = [100, 1, 101]
|
26
|
+
assert_equal 100, @group.article_count
|
27
|
+
assert_equal 1, @group.article_first
|
28
|
+
assert_equal 101, @group.article_last
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_listinfo
|
32
|
+
assert_nothing_raised do
|
33
|
+
@group.listinfo(10,20,'y')
|
34
|
+
assert_equal 10, @group.hi
|
35
|
+
assert_equal 20, @group.lo
|
36
|
+
assert_equal 'y', @group.postingmode
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_article
|
41
|
+
assert_equal 0, @group.articles.length
|
42
|
+
over = "1\tTesting\t\"abc\" abc@ide.invalid\t17 Aug 2004 14:00:00 GMT\t<this.post@is.invalid>\t\t200\t2\tXref: this.host.invalid alt.test:1"
|
43
|
+
@group.articles << Net::NNTP::Article.new
|
44
|
+
assert_equal 1, @group.articles.length
|
45
|
+
overview_format = "215 Order of fields in overview database.\r\nSubject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n.\r\n"
|
46
|
+
@group.articles.build_from_over(over, overview_format)
|
47
|
+
@group.articles = []
|
48
|
+
assert_equal 0, @group.articles.size
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_create
|
52
|
+
assert_kind_of Net::NNTP::Article, @group.articles.create
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_inspect
|
56
|
+
assert_kind_of String, @group.inspect
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: ruby-net-nntp
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2007-05-17 00:00:00 +02:00
|
8
|
+
summary: Net::XXX style NNTP Library for easy access.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: anton.bangratz@gmail.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: ""
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Anton Bangratz
|
31
|
+
files:
|
32
|
+
- lib/net
|
33
|
+
- lib/net/nntp.rb
|
34
|
+
- lib/net/nntp_article.rb
|
35
|
+
- lib/net/nntp_group.rb
|
36
|
+
- test/functional
|
37
|
+
- test/functional/test_nntp.rb
|
38
|
+
- test/mock
|
39
|
+
- test/mock/mock_socket.rb
|
40
|
+
- test/unit
|
41
|
+
- test/unit/test_nntp_article.rb
|
42
|
+
- test/unit/test_nntp_group.rb
|
43
|
+
- README
|
44
|
+
- CHANGELOG
|
45
|
+
- MIT-LICENSE
|
46
|
+
test_files:
|
47
|
+
- test/functional
|
48
|
+
- test/functional/test_nntp.rb
|
49
|
+
- test/mock
|
50
|
+
- test/mock/mock_socket.rb
|
51
|
+
- test/unit
|
52
|
+
- test/unit/test_nntp_article.rb
|
53
|
+
- test/unit/test_nntp_group.rb
|
54
|
+
rdoc_options:
|
55
|
+
- -S
|
56
|
+
- -N
|
57
|
+
- --main
|
58
|
+
- README
|
59
|
+
extra_rdoc_files:
|
60
|
+
- README
|
61
|
+
- CHANGELOG
|
62
|
+
- MIT-LICENSE
|
63
|
+
executables: []
|
64
|
+
|
65
|
+
extensions: []
|
66
|
+
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
dependencies: []
|
70
|
+
|