ruby-net-nntp 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +38 -1
- data/README +9 -0
- data/lib/net/nntp.rb +31 -9
- data/lib/net/nntp/article.rb +176 -0
- data/lib/net/{nntp_group.rb → nntp/group.rb} +7 -0
- data/lib/net/nntp/version.rb +3 -3
- data/test/functional/test_nntp.rb +7 -7
- data/test/mock/mock_socket.rb +48 -48
- data/test/unit/test_nntp_article.rb +42 -8
- data/test/unit/test_nntp_group.rb +1 -1
- metadata +7 -5
- data/lib/net/nntp_article.rb +0 -28
data/CHANGELOG
CHANGED
@@ -1,4 +1,41 @@
|
|
1
|
-
2007-07-
|
1
|
+
2007-07-14 12:22 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (5de9968582e9 [tip])
|
2
|
+
|
3
|
+
* README, lib/net/nntp.rb, lib/net/nntp/article.rb,
|
4
|
+
lib/net/nntp/group.rb, lib/net/nntp/version.rb,
|
5
|
+
test/mock/mock_socket.rb, test/unit/test_nntp_article.rb,
|
6
|
+
test/unit/test_nntp_group.rb:
|
7
|
+
NNTP can QUIT, Article redesign: parse HEAD, BODY and ARTICLE,
|
8
|
+
renamed 'id' to 'number', headers and body along with proxies added
|
9
|
+
- added QUIT to Net::NNTP
|
10
|
+
- added parse from HEAD, BODY and ARTICLE to Net::NNTP::Article
|
11
|
+
(factory)
|
12
|
+
- redesigned Net::NNTP::Article: + separate headers
|
13
|
+
and body attributes + including proxies to mimick
|
14
|
+
old attributes, deprecated + renamed the conflicting
|
15
|
+
'id' attribute to 'number'
|
16
|
+
- improved documentation
|
17
|
+
|
18
|
+
2007-07-09 14:34 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (d97d95ec735b)
|
19
|
+
|
20
|
+
* lib/net/nntp.rb, lib/net/nntp/article.rb, lib/net/nntp/group.rb,
|
21
|
+
lib/net/nntp/version.rb, lib/net/nntp_article.rb,
|
22
|
+
lib/net/nntp_group.rb, test/functional/test_nntp.rb,
|
23
|
+
test/mock/mock_socket.rb:
|
24
|
+
fixed overview.fmt, fixed logging
|
25
|
+
- fixed overview.fmt bug
|
26
|
+
- fixed logging for autotest/test
|
27
|
+
|
28
|
+
2007-07-02 21:35 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (5ba29ac12969)
|
29
|
+
|
30
|
+
* lib/net/nntp/version.rb:
|
31
|
+
new release;version fix
|
32
|
+
|
33
|
+
2007-07-02 21:34 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (8441de3d244d)
|
34
|
+
|
35
|
+
* lib/net/nntp.rb:
|
36
|
+
bugfix read_response multiline read - introduced with last release
|
37
|
+
|
38
|
+
2007-07-02 20:51 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (4399451e92c0)
|
2
39
|
|
3
40
|
* lib/net/nntp/version.rb:
|
4
41
|
Release 0.0.8, fixed version
|
data/README
CHANGED
@@ -29,3 +29,12 @@ Net::NNTP uses a simple interface to wrap commands to communicate with an NNTP s
|
|
29
29
|
|
30
30
|
* sudo gem install libruby-nntp or
|
31
31
|
* sudo dpkg -r libruby-0.0.1.deb
|
32
|
+
|
33
|
+
= CHANGES
|
34
|
+
|
35
|
+
Version 0.1.0 introduces the Net::NNTP::Article#headers and #body attributes.
|
36
|
+
Due to this, the attribute Net::NNTP::Article#id has been changed to Net::NNTP::Article#number
|
37
|
+
to avoid conflicts with Object#id.
|
38
|
+
|
39
|
+
Additionally, on request, Net::NNTP::Article has been changed from being a mere proxy for Net::NNTP#xover
|
40
|
+
result lines to being able to parse HEAD, BODY and ARTICLE results and return a corresponding instance.
|
data/lib/net/nntp.rb
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
5
5
|
require 'timeout' # :nodoc:
|
6
|
-
require 'net/
|
7
|
-
require 'net/
|
6
|
+
require 'net/nntp/group'
|
7
|
+
require 'net/nntp/article'
|
8
8
|
require 'net/nntp/version.rb'
|
9
9
|
require 'rubygems'
|
10
10
|
require 'log4r'
|
11
11
|
|
12
12
|
|
13
|
+
|
13
14
|
module Net
|
14
15
|
class NNTP
|
15
16
|
include Timeout # :nodoc:
|
@@ -62,6 +63,15 @@ module Net
|
|
62
63
|
@welcome
|
63
64
|
end
|
64
65
|
|
66
|
+
# Sends QUIT command to server and closes the connection (unless force_close is set to false). Returns response.
|
67
|
+
def quit(force_close=true)
|
68
|
+
send_cmd "QUIT"
|
69
|
+
response = read_response
|
70
|
+
close if force_close
|
71
|
+
response
|
72
|
+
end
|
73
|
+
|
74
|
+
|
65
75
|
# Closes connection. If not reconnected, subsequent calls of commands raise exceptions
|
66
76
|
def close
|
67
77
|
debug 'closing connection per request'
|
@@ -195,7 +205,7 @@ module Net
|
|
195
205
|
case keyword
|
196
206
|
when /overview.fmt/
|
197
207
|
@overview_format_raw = list
|
198
|
-
@overview_format = Net::NNTP.parse_overview_format list
|
208
|
+
@overview_format = Net::NNTP.parse_overview_format list
|
199
209
|
else
|
200
210
|
create_grouplist(list)
|
201
211
|
list
|
@@ -208,9 +218,10 @@ module Net
|
|
208
218
|
|
209
219
|
# prepares overview format as read from server, used by Net::NNTP::Article and list()
|
210
220
|
def self.parse_overview_format(format)
|
211
|
-
overview_format = %w{
|
212
|
-
|
213
|
-
|
221
|
+
overview_format = %w{number}
|
222
|
+
lines = format
|
223
|
+
lines.each do |line|
|
224
|
+
next if line[0] == ?2 || line[0] == ?. || line == 'full'
|
214
225
|
ident = line.scan(/\w/).join.downcase
|
215
226
|
unless ident[0..3] == 'xref'
|
216
227
|
overview_format << ident
|
@@ -287,7 +298,7 @@ module Net
|
|
287
298
|
case code
|
288
299
|
when '223'
|
289
300
|
code, id, msgid, what = response.split
|
290
|
-
article.
|
301
|
+
article.number = id
|
291
302
|
article.messageid = msgid
|
292
303
|
else
|
293
304
|
raise CommandFailedError, response
|
@@ -300,6 +311,7 @@ module Net
|
|
300
311
|
last_or_next("last")
|
301
312
|
end
|
302
313
|
|
314
|
+
# Issues the NEXT command to the NNTP server, returning the raw response
|
303
315
|
def next
|
304
316
|
last_or_next("next")
|
305
317
|
end
|
@@ -329,14 +341,24 @@ module Net
|
|
329
341
|
linecnt = 0
|
330
342
|
loop do
|
331
343
|
str = @socket.readline
|
344
|
+
#debug " -> got line: '#{str}'"
|
332
345
|
ra << str.chomp if str
|
333
|
-
break if force_oneline || (str.chomp == "." ||
|
346
|
+
break if force_oneline || (!str || str.chomp == "." || (linecnt == 0 && ONELINE_STATUSES.include?(str[0..2])) )
|
334
347
|
linecnt += 1
|
335
348
|
end
|
336
|
-
debug "Response: '#{ra}'"
|
349
|
+
debug "Response: '#{ra.inspect}'"
|
337
350
|
ra
|
338
351
|
end
|
339
352
|
|
353
|
+
# Parses a hash in the format {:from => int, :to => int} or {:message_id => int}
|
354
|
+
# and returns a string. :to is optional, :from has precedence over :message_id if
|
355
|
+
# both are given
|
356
|
+
#
|
357
|
+
# Examples:
|
358
|
+
# numbers_or_id(:from => 1, :to => 100) #=> returns '1-100'
|
359
|
+
# numbers_or_id(:from => 1) #=> returns '1-'
|
360
|
+
# numbers_or_id(:message_id = '<abc>' #=> returns '<abc>'
|
361
|
+
# numbers_or_id(:from => 5, :message_id = '<abc>' #=> returns 'f-'
|
340
362
|
def numbers_or_id(hash)
|
341
363
|
return nil unless hash
|
342
364
|
suffix = ''
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
# a slightly modified OpenStruct
|
4
|
+
class HeaderStruct < OpenStruct
|
5
|
+
# adds of modifies a new key/value pair
|
6
|
+
def add_pair(key, value)
|
7
|
+
@table[key.to_sym] = value
|
8
|
+
new_ostruct_member(key)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Net
|
13
|
+
class NNTP
|
14
|
+
class Article
|
15
|
+
attr_accessor :group, :headers, :body
|
16
|
+
attr_reader :overview_format
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@overview_format = %w{number}
|
20
|
+
@headers ||= HeaderStruct.new
|
21
|
+
@body = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Former versions attribute proxy
|
25
|
+
#
|
26
|
+
# Deprecated: use corresponding headers attribute instead
|
27
|
+
def number
|
28
|
+
@headers.number
|
29
|
+
end
|
30
|
+
|
31
|
+
# Former versions attribute proxy
|
32
|
+
#
|
33
|
+
# Deprecated: use corresponding headers attribute instead
|
34
|
+
def number=(number)
|
35
|
+
@headers.number = number
|
36
|
+
end
|
37
|
+
|
38
|
+
# Former versions attribute proxy
|
39
|
+
#
|
40
|
+
# Deprecated: use corresponding headers attribute instead
|
41
|
+
def messageid
|
42
|
+
@headers.message_id
|
43
|
+
end
|
44
|
+
|
45
|
+
# Former versions attribute proxy
|
46
|
+
#
|
47
|
+
# Deprecated: use corresponding headers attribute instead
|
48
|
+
def messageid=(id)
|
49
|
+
@headers.message_id = id
|
50
|
+
end
|
51
|
+
|
52
|
+
# Former versions attribute proxy
|
53
|
+
#
|
54
|
+
# Deprecated: use corresponding headers attribute instead
|
55
|
+
def subject
|
56
|
+
@headers.subject
|
57
|
+
end
|
58
|
+
|
59
|
+
# Former versions attribute proxy
|
60
|
+
#
|
61
|
+
# Deprecated: use corresponding headers attribute instead
|
62
|
+
def subject=(subject)
|
63
|
+
@headers.subject=subject
|
64
|
+
end
|
65
|
+
|
66
|
+
# Former versions attribute proxy
|
67
|
+
#
|
68
|
+
# Deprecated: use corresponding headers attribute instead
|
69
|
+
def bytes
|
70
|
+
@headers.bytes
|
71
|
+
end
|
72
|
+
|
73
|
+
# Former versions attribute proxy
|
74
|
+
#
|
75
|
+
# Deprecated: use corresponding headers attribute instead
|
76
|
+
def lines
|
77
|
+
@headers.lines
|
78
|
+
end
|
79
|
+
|
80
|
+
# Former versions attribute proxy
|
81
|
+
#
|
82
|
+
# Deprecated: use corresponding headers attribute instead
|
83
|
+
def xref
|
84
|
+
@headers.xref
|
85
|
+
end
|
86
|
+
|
87
|
+
# Former versions attribute proxy
|
88
|
+
#
|
89
|
+
# Deprecated: use corresponding headers attribute instead
|
90
|
+
def date
|
91
|
+
@headers.date
|
92
|
+
end
|
93
|
+
|
94
|
+
# Former versions attribute proxy
|
95
|
+
#
|
96
|
+
# Deprecated: use corresponding headers attribute instead
|
97
|
+
def from
|
98
|
+
@headers.from
|
99
|
+
end
|
100
|
+
|
101
|
+
# Sets the overview format to use for parsing article from XOVER command results.
|
102
|
+
#
|
103
|
+
#
|
104
|
+
# Takes either a tab separated line as result from 'LIST OVERVIEW.FMT' and
|
105
|
+
# parses it into an array (see Net::NNTP::parse_overview_format) or takes
|
106
|
+
# an already parsed array to set the format directly.
|
107
|
+
def overview_format=(format)
|
108
|
+
if Array === format
|
109
|
+
@overview_format = format
|
110
|
+
else
|
111
|
+
@overview_format = Net::NNTP.parse_overview_format format
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Parses data from XOVER command
|
116
|
+
#
|
117
|
+
# Takes the tab separated line corresponding to an article from the XOVER command
|
118
|
+
# result and sets the header fields accordingly. CAVEAT! The overview format (see
|
119
|
+
# Net::NNTP::Article#overview_format= has to be set prior of attempting this, and
|
120
|
+
# has to actually correspond with the fields.
|
121
|
+
def overview(over)
|
122
|
+
over.split(/\t/).each_with_index do |value, index|
|
123
|
+
ident = @overview_format[index]
|
124
|
+
@headers.add_pair(ident, value)
|
125
|
+
if @headers.messageid
|
126
|
+
@headers.message_id = @headers.messageid
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Sets a header from the result line
|
132
|
+
#
|
133
|
+
# Parses a line of the format "Header: Value" and sets the @headers accordingly.
|
134
|
+
# (Example: "Message-ID: <abc@def.gh>" will become @headers.message_id with the
|
135
|
+
# value '<abc@def.gh>'.
|
136
|
+
def set_header(line)
|
137
|
+
name, value = line.scan(/^(.*)?: (.*)$/).flatten
|
138
|
+
key = name.strip.gsub(/[^\w]/, '_').downcase
|
139
|
+
@headers.add_pair(key, value)
|
140
|
+
@headers
|
141
|
+
end
|
142
|
+
|
143
|
+
# Creates an Net::NNTP::Article from a HEAD, BODY or ARTICLE result
|
144
|
+
#
|
145
|
+
# Takes the full result (including response line and stop marker ".")
|
146
|
+
# and creates a Net::NNTP::Article instance with the headers in @headers and
|
147
|
+
# the body in @body.
|
148
|
+
def self.parse(lines)
|
149
|
+
responsecode = lines[0][0..2]
|
150
|
+
do_header = responsecode == '221'
|
151
|
+
do_body = responsecode == '222'
|
152
|
+
if responsecode == '220'
|
153
|
+
do_header = do_body = true
|
154
|
+
end
|
155
|
+
article = Net::NNTP::Article.new
|
156
|
+
count = 0
|
157
|
+
lines.each do |line|
|
158
|
+
count += 1
|
159
|
+
next if count == 1
|
160
|
+
break if line =~ /^.$/
|
161
|
+
do_header = (do_header && line !~ /^$/)
|
162
|
+
next if line =~ /^$/
|
163
|
+
if do_header
|
164
|
+
article.set_header(line)
|
165
|
+
else
|
166
|
+
if do_body
|
167
|
+
article.body << line
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
article
|
172
|
+
end
|
173
|
+
|
174
|
+
end # class Net::NNTP::Article
|
175
|
+
end
|
176
|
+
end
|
@@ -13,6 +13,9 @@ module Net
|
|
13
13
|
@article_first = @article_last = @article_count = nil
|
14
14
|
end
|
15
15
|
|
16
|
+
# Set article_count, article_first, article_last (from GROUP command)
|
17
|
+
#
|
18
|
+
# Takes an array [count, first, last] as argument
|
16
19
|
def article_info=(art_array)
|
17
20
|
@article_count = art_array[0].to_i
|
18
21
|
@article_first = art_array[1].to_i
|
@@ -27,6 +30,7 @@ module Net
|
|
27
30
|
@articles = articles
|
28
31
|
end
|
29
32
|
|
33
|
+
# Sets hi and lo watermark alont with postingmode (from LIST ACTIVE command)
|
30
34
|
def listinfo(hi, lo, postingmode)
|
31
35
|
@hi = hi
|
32
36
|
@lo = lo
|
@@ -45,6 +49,7 @@ module Net
|
|
45
49
|
@articles ||=[]
|
46
50
|
end
|
47
51
|
|
52
|
+
# Stores articles in group attribute, using Net::NNTP::Article instances
|
48
53
|
def build_from_over(over, format)
|
49
54
|
article = Article.new
|
50
55
|
article.overview_format = format
|
@@ -60,6 +65,8 @@ module Net
|
|
60
65
|
@articles << article
|
61
66
|
end
|
62
67
|
|
68
|
+
# Creates one Net::NNTP::Article instance, sets the group attribute to the
|
69
|
+
# including group instances and adds the article to articles before returning it
|
63
70
|
def create
|
64
71
|
a = Article.new
|
65
72
|
a.group = self.group
|
data/lib/net/nntp/version.rb
CHANGED
@@ -4,18 +4,18 @@ require 'net/nntp.rb'
|
|
4
4
|
require 'mock/mock_socket'
|
5
5
|
|
6
6
|
|
7
|
+
unless defined? log
|
8
|
+
log = Log4r::Logger.new('net::nntp')
|
9
|
+
fileout = Log4r::FileOutputter.new('net::nntp::fileout', :filename => File.join('logs', 'autotest.log'), :trunc => true)
|
10
|
+
fileout.formatter = Log4r::PatternFormatter.new(:pattern => '%d [%5l] : %m')
|
11
|
+
log.add fileout
|
12
|
+
log.level = Log4r::ALL
|
13
|
+
end
|
7
14
|
|
8
15
|
module TestNet
|
9
16
|
class TestNNTP < Test::Unit::TestCase
|
10
17
|
|
11
18
|
def setup
|
12
|
-
unless @log
|
13
|
-
@log = Log4r::Logger.new('net::nntp')
|
14
|
-
fileout = Log4r::FileOutputter.new('net::nntp::fileout', :filename => File.join('logs', 'autotest.log'))
|
15
|
-
fileout.formatter = Log4r::PatternFormatter.new(:pattern => '%d [%5l] : %m')
|
16
|
-
@log.add fileout
|
17
|
-
@log.level = Log4r::ALL
|
18
|
-
end
|
19
19
|
nntp_connect_and_auth('localhost', 119, 'dummy', 'test')
|
20
20
|
end
|
21
21
|
|
data/test/mock/mock_socket.rb
CHANGED
@@ -105,7 +105,7 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
105
105
|
when /^list\b\s*(.*)\r\n$/
|
106
106
|
case $1
|
107
107
|
when /overview.fmt/i
|
108
|
-
@io = ["215 Order of fields in overview database.\r\
|
108
|
+
@io = ["215 Order of fields in overview database.\r\n", "Subject:\r\n", "From:\r\n", "Date:\r\n", "Message-ID:\r\n", "References:\r\n", "Bytes:\r\n", "Lines:\r\n", "Xref:full\r\n", ".\r\n" ]
|
109
109
|
when /active\s*(.*)/
|
110
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
111
|
when /^\s*$/
|
@@ -186,10 +186,10 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
186
186
|
"1374\r\n",
|
187
187
|
"1375\r\n",
|
188
188
|
".\r\n"
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
]
|
190
|
+
else
|
191
|
+
if @group_selected
|
192
|
+
@io = [
|
193
193
|
"211 Article list for at.linux follows\r\n",
|
194
194
|
"1363\r\n",
|
195
195
|
"1364\r\n",
|
@@ -205,31 +205,31 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
205
205
|
"1374\r\n",
|
206
206
|
"1375\r\n",
|
207
207
|
".\r\n"
|
208
|
-
|
208
|
+
]
|
209
|
+
else
|
210
|
+
@io = ['412 No Group selected']
|
211
|
+
end
|
212
|
+
end
|
213
|
+
when "quit\r\n" then
|
214
|
+
@io = ["200 Good bye"]
|
215
|
+
when "authinfo user dummy\r\n"
|
216
|
+
@io = ["381 More authentication details needed"]
|
217
|
+
when "authinfo pass test\r\n"
|
218
|
+
@io = ["281 Welcome to dummytest"]
|
219
|
+
when /^group\s+(.+)\s*\r\n$/
|
220
|
+
case $1
|
221
|
+
when 'at.linux'
|
222
|
+
@io = ["211 12 1363 1375 at.linux"]
|
223
|
+
@group_selected = 'at.linux'
|
209
224
|
else
|
210
|
-
@io = [
|
225
|
+
@io = ["411 No such group"]
|
211
226
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
@io = ["281 Welcome to dummytest"]
|
219
|
-
when /^group\s+(.+)\s*\r\n$/
|
220
|
-
case $1
|
221
|
-
when 'at.linux'
|
222
|
-
@io = ["211 12 1363 1375 at.linux"]
|
223
|
-
@group_selected = 'at.linux'
|
224
|
-
else
|
225
|
-
@io = ["411 No such group"]
|
226
|
-
end
|
227
|
-
when "xhdr subject <slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>\r\n"
|
228
|
-
@io =
|
229
|
-
["1375 Re: Bitte um Meinungen ==> Virtualisierung\r\n"]
|
230
|
-
when "xhdr subject 1363-1375\r\n"
|
231
|
-
if @group_selected
|
232
|
-
@io = [
|
227
|
+
when "xhdr subject <slrnf26akq.ci5.hjp-usenet2@zeno.hjp.at>\r\n"
|
228
|
+
@io =
|
229
|
+
["1375 Re: Bitte um Meinungen ==> Virtualisierung\r\n"]
|
230
|
+
when "xhdr subject 1363-1375\r\n"
|
231
|
+
if @group_selected
|
232
|
+
@io = [
|
233
233
|
"221 Subject header (from overview) for postings 1363-1375\r\n",
|
234
234
|
"1363 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
235
235
|
"1364 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
@@ -245,11 +245,11 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
245
245
|
"1374 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
246
246
|
"1375 Re: Bitte um Meinungen ==> Virtualisierung\r\n",
|
247
247
|
".\r\n"
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
248
|
+
]
|
249
|
+
else
|
250
|
+
@io = ['412 No group selected']
|
251
|
+
end
|
252
|
+
when "xover 1363-1375\r\n"
|
253
253
|
if @group_selected
|
254
254
|
@io = [
|
255
255
|
"224 Overview information for postings 1363-1375:\r\n",
|
@@ -267,9 +267,9 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
267
267
|
"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",
|
268
268
|
"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",
|
269
269
|
".\r\n"
|
270
|
-
|
271
|
-
|
272
|
-
|
270
|
+
]
|
271
|
+
else
|
272
|
+
@io = ["412 No Group selected"]
|
273
273
|
end
|
274
274
|
when /xover \<.+\>/
|
275
275
|
@io = ["502 Usage: OVER first[-[last]]"]
|
@@ -300,11 +300,11 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
300
300
|
"X-Complaints-To: usenet-abuse@arcor.de\r\n",
|
301
301
|
"Xref: sensor.twincode.net at.linux:1430\r\n",
|
302
302
|
".\r\n"
|
303
|
-
|
303
|
+
]
|
304
304
|
|
305
305
|
when /^\s?$/
|
306
|
-
|
307
|
-
|
306
|
+
if @group_selected
|
307
|
+
@io = [
|
308
308
|
"221 1430 <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net> article retrieved - head follows\r\n",
|
309
309
|
"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",
|
310
310
|
"Message-ID: <462dfa6f$0$23135$9b4e6d93@newsspool1.arcor-online.net>\r\n",
|
@@ -326,18 +326,18 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
326
326
|
"X-Complaints-To: usenet-abuse@arcor.de\r\n",
|
327
327
|
"Xref: sensor.twincode.net at.linux:1430\r\n",
|
328
328
|
".\r\n"
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
329
|
+
]
|
330
|
+
else
|
331
|
+
@io = ["412 No Group selected"]
|
332
|
+
end
|
333
333
|
else
|
334
334
|
@io = ["501 Bad Command"]
|
335
335
|
end
|
336
|
-
|
337
|
-
|
338
|
-
end
|
339
|
-
return str.length
|
336
|
+
else
|
337
|
+
@io = ["500 Unknown Command"]
|
340
338
|
end
|
339
|
+
return str.length
|
340
|
+
end
|
341
341
|
|
342
342
|
def readline
|
343
343
|
super
|
@@ -349,4 +349,4 @@ class MockSocket < Test::Unit::MockObject( TCPSocket )
|
|
349
349
|
$stdout.puts x
|
350
350
|
end
|
351
351
|
|
352
|
-
|
352
|
+
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'net/nntp.rb'
|
3
|
-
|
4
1
|
class TestNNTPArticle < Test::Unit::TestCase
|
5
2
|
|
6
3
|
def setup
|
@@ -12,9 +9,9 @@ class TestNNTPArticle < Test::Unit::TestCase
|
|
12
9
|
a = Net::NNTP::Article.new
|
13
10
|
end
|
14
11
|
|
15
|
-
def
|
16
|
-
@article.
|
17
|
-
assert_equal 1, @article.
|
12
|
+
def test_article_number
|
13
|
+
@article.number = 1
|
14
|
+
assert_equal 1, @article.number
|
18
15
|
end
|
19
16
|
|
20
17
|
def test_article_messageid
|
@@ -32,7 +29,7 @@ class TestNNTPArticle < Test::Unit::TestCase
|
|
32
29
|
def test_from_xover
|
33
30
|
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
31
|
@article.overview(over)
|
35
|
-
assert_equal '1', @article.
|
32
|
+
assert_equal '1', @article.number
|
36
33
|
assert_equal '<this.post@is.invalid>', @article.messageid
|
37
34
|
assert_equal 'Testing', @article.subject
|
38
35
|
assert_equal 200, @article.bytes.to_i
|
@@ -41,8 +38,8 @@ class TestNNTPArticle < Test::Unit::TestCase
|
|
41
38
|
end
|
42
39
|
|
43
40
|
def test_overview_fmt=
|
44
|
-
|
45
41
|
@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"
|
42
|
+
assert_equal 'number', @article.overview_format[0]
|
46
43
|
assert_equal 'subject', @article.overview_format[1]
|
47
44
|
assert_equal 'from', @article.overview_format[2]
|
48
45
|
assert_equal 'date', @article.overview_format[3]
|
@@ -53,4 +50,41 @@ class TestNNTPArticle < Test::Unit::TestCase
|
|
53
50
|
assert_equal 'xref', @article.overview_format[8]
|
54
51
|
end
|
55
52
|
|
53
|
+
def test_set_header
|
54
|
+
@article.set_header('Subject: Test')
|
55
|
+
assert_equal 'Test', @article.headers.subject
|
56
|
+
@article.set_header('Message-ID: <this.post@is.invalid>')
|
57
|
+
assert_equal '<this.post@is.invalid>', @article.headers.message_id
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_parse
|
61
|
+
article = Net::NNTP::Article.parse(["220 1 article retrieved - text follows",
|
62
|
+
"Date: 17 Aug 2004 14:00:00 GMT",
|
63
|
+
"From: \"abc\" abc@ide.invalid",
|
64
|
+
"Message-ID: <this.post@is.invalid>",
|
65
|
+
"Subject: ignore test",
|
66
|
+
"",
|
67
|
+
"test please ignore",
|
68
|
+
"test ",
|
69
|
+
"."])
|
70
|
+
assert_equal '17 Aug 2004 14:00:00 GMT', article.headers.date
|
71
|
+
assert_equal '"abc" abc@ide.invalid', article.headers.from
|
72
|
+
assert_equal '<this.post@is.invalid>', article.headers.message_id
|
73
|
+
assert_equal 'ignore test', article.headers.subject
|
74
|
+
assert_equal 2, article.body.size
|
75
|
+
assert_equal 'test please ignore', article.body[0]
|
76
|
+
assert_equal 'test ', article.body[1]
|
77
|
+
article = Net::NNTP::Article.parse(["221 1 article retrieved - head follows", "Date: 17 Aug 2004 14:00:00 GMT", "From: \"abc\" abc@ide.invalid",
|
78
|
+
"Message-ID: <this.post@is.invalid>", "Subject: ignore test", "."])
|
79
|
+
assert_equal '17 Aug 2004 14:00:00 GMT', article.headers.date
|
80
|
+
assert_equal '"abc" abc@ide.invalid', article.headers.from
|
81
|
+
assert_equal '<this.post@is.invalid>', article.headers.message_id
|
82
|
+
assert_equal 'ignore test', article.headers.subject
|
83
|
+
assert_equal 0, article.body.size
|
84
|
+
article = Net::NNTP::Article.parse(["222 1 article retrieved - body follows", "test please ignore", "test ", "."])
|
85
|
+
assert_equal 2, article.body.size
|
86
|
+
assert_equal 'test please ignore', article.body[0]
|
87
|
+
assert_equal 'test ', article.body[1]
|
88
|
+
end
|
89
|
+
|
56
90
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-net-nntp
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0
|
7
|
-
date: 2007-07-
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-07-14 00:00:00 +02:00
|
8
8
|
summary: Net::XXX style NNTP Library for easy access.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,9 +31,9 @@ authors:
|
|
31
31
|
files:
|
32
32
|
- lib/net
|
33
33
|
- lib/net/nntp
|
34
|
+
- lib/net/nntp/article.rb
|
35
|
+
- lib/net/nntp/group.rb
|
34
36
|
- lib/net/nntp/version.rb
|
35
|
-
- lib/net/nntp_article.rb
|
36
|
-
- lib/net/nntp_group.rb
|
37
37
|
- lib/net/nntp.rb
|
38
38
|
- test/functional
|
39
39
|
- test/functional/test_nntp.rb
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- test/unit
|
43
43
|
- test/unit/test_nntp_article.rb
|
44
44
|
- test/unit/test_nntp_group.rb
|
45
|
+
- test/logs
|
45
46
|
- README
|
46
47
|
- CHANGELOG
|
47
48
|
- MIT-LICENSE
|
@@ -53,6 +54,7 @@ test_files:
|
|
53
54
|
- test/unit
|
54
55
|
- test/unit/test_nntp_article.rb
|
55
56
|
- test/unit/test_nntp_group.rb
|
57
|
+
- test/logs
|
56
58
|
rdoc_options:
|
57
59
|
- -S
|
58
60
|
- -N
|
data/lib/net/nntp_article.rb
DELETED
@@ -1,28 +0,0 @@
|
|
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, :from
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@overview_format = %w{id}
|
9
|
-
end
|
10
|
-
|
11
|
-
def overview_format=(format)
|
12
|
-
if Array === format
|
13
|
-
@overview_format = format
|
14
|
-
else
|
15
|
-
@overview_format = Net::NNTP.parse_overview_format format
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def overview(over)
|
20
|
-
over.split(/\t/).each_with_index do |value, index|
|
21
|
-
ident = @overview_format[index]
|
22
|
-
eval "@#{ident} = value;"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|