ruby-net-nntp 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,41 @@
1
- 2007-07-02 20:51 +0200 Anton 'tony' Bangratz <anton.bangratz@gmail.com> (4399451e92c0 [tip])
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/nntp_group'
7
- require 'net/nntp_article'
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.join
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{id}
212
- format.split(/\r?\n/).each do |line|
213
- next if line[0] == ?2 || line[0] == ?.
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.id = id
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 == "." || !str || (linecnt == 0 && ONELINE_STATUSES.include?(str[0..2])) )
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
@@ -1,5 +1,5 @@
1
1
  module Net
2
- class NNTP
3
- VERSION = "0.0.9"
4
- end
2
+ class NNTP
3
+ VERSION = "0.1.0"
4
+ end
5
5
  end
@@ -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
 
@@ -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\nSubject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n.\r\n" ]
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
- else
191
- if @group_selected
192
- @io = [
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 = ['412 No Group selected']
225
+ @io = ["411 No such group"]
211
226
  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'
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
- else
250
- @io = ['412 No group selected']
251
- end
252
- when "xover 1363-1375\r\n"
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
- else
272
- @io = ["412 No Group selected"]
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
- if @group_selected
307
- @io = [
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
- else
331
- @io = ["412 No Group selected"]
332
- end
329
+ ]
330
+ else
331
+ @io = ["412 No Group selected"]
332
+ end
333
333
  else
334
334
  @io = ["501 Bad Command"]
335
335
  end
336
- else
337
- @io = ["500 Unknown Command"]
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
- end
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 test_article_id
16
- @article.id = 1
17
- assert_equal 1, @article.id
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.id
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
@@ -56,5 +56,5 @@ class TestNNTPGroup< Test::Unit::TestCase
56
56
  assert_kind_of String, @group.inspect
57
57
  end
58
58
 
59
-
59
+
60
60
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
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.9
7
- date: 2007-07-02 00:00:00 +02:00
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
@@ -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