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 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
+