minter-raccdoc 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 H. Wade Minter
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,8 @@
1
+ lib/raccdoc.rb
2
+ LICENSE
3
+ Manifest
4
+ raccdoc.gemspec
5
+ Rakefile
6
+ README
7
+ test/raccdoc_connection_test.rb
8
+ test/test_helper.rb
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ gem 'echoe', '~> 3.0.1'
3
+ require 'echoe'
4
+ require './lib/raccdoc.rb'
5
+
6
+ echoe = Echoe.new("raccdoc") do |p|
7
+ p.author = "H. Wade Minter"
8
+ p.email = "minter@lunenburg.org"
9
+ p.summary = "A Ruby interface into the Raccdoc protocol"
10
+ p.runtime_dependencies = ["socket", "time"]
11
+ p.version = Raccdoc::VERSION
12
+ p.ignore_pattern = ["tmp/*", "doc/*"]
13
+ end
14
+
15
+ desc 'Generate the .gemspec file in the root directory'
16
+ task :gemspec do
17
+ File.open("#{echoe.name}.gemspec", "w") {|f| f << echoe.spec.to_ruby }
18
+ end
19
+ task :package => :gemspec
20
+
21
+ namespace :test do
22
+ desc 'Check test coverage'
23
+ task :coverage do
24
+ rm_f "coverage"
25
+ system("rcov -x '/Library/Ruby/Gems/1.8/gems/' --sort coverage #{File.join(File.dirname(__FILE__), 'test/*_test.rb')}")
26
+ show_test_coverage_results
27
+ end
28
+
29
+ def show_test_coverage_results
30
+ system("open #{File.join(File.dirname(__FILE__), 'coverage/index.html')}") if PLATFORM['darwin']
31
+ end
32
+
33
+ desc 'Remove coverage products'
34
+ task :clobber_coverage do
35
+ rm_r 'coverage' rescue nil
36
+ end
37
+
38
+ end
39
+
data/lib/raccdoc.rb ADDED
@@ -0,0 +1,361 @@
1
+ module Raccdoc
2
+
3
+ VERSION = '0.0.1'
4
+ require 'socket'
5
+ require 'time'
6
+
7
+ class Connection
8
+
9
+ attr_reader :host
10
+
11
+ # Creates a new Raccdoc connection. By default, it connects to bbs.iscabbs.com, port 6145, which is the
12
+ # ISCABBS server.
13
+ #
14
+ # If a :user and :password is not supplied, a guest/anonymous login is done. Most, if not all, posting is
15
+ # restricted under this account.
16
+ #
17
+ # If the TCP connection fails, or the login is rejected, and exception is raised.
18
+ def initialize(param_args = {:host => 'bbs.iscabbs.com', :port => '6145', :user => nil, :password => nil})
19
+ args = {:host => 'bbs.iscabbs.com', :port => '6145', :user => nil, :password => nil }
20
+
21
+ args.merge!(param_args)
22
+ begin
23
+ @socket = TCPSocket.new(args[:host],args[:port])
24
+ rescue Errno::ECONNREFUSED
25
+ raise RuntimeError, "Could not connect to #{args[:host]}, port #{args[:port]}\n"
26
+ end
27
+
28
+ response = @socket.readline.chomp
29
+ unless response.match(/^2/)
30
+ raise RuntimeError, response
31
+ end
32
+
33
+ if (args[:user] && args[:password])
34
+ @socket.puts("LOGIN #{args[:user]}\t#{args[:password]}")
35
+ response = @socket.readline.chomp
36
+ unless response.match(/^2/)
37
+ raise RuntimeError, response
38
+ end
39
+ end
40
+ @host = args[:host]
41
+ end
42
+
43
+ # Closes the Raccdoc connection, then closes the socket.
44
+ def logout
45
+ unless @socket.closed?
46
+ @socket.puts "QUIT"
47
+
48
+ response = @socket.readline.chomp
49
+ unless response.match(/^2/)
50
+ raise RuntimeError, response
51
+ end
52
+ @socket.close
53
+ end
54
+ end
55
+
56
+ # Tests the TCP socket to make sure that it's still connected to the remote server.
57
+ def connected?
58
+ @socket.closed? ? false : true
59
+ end
60
+
61
+ # Sets the active forum on the server to the specified forum name or ID, and returns a new Raccdoc::Forum object.
62
+ #
63
+ # The forum can be specified by number (0), or name ("Lobby" or "Program")
64
+ def jump(forum = 0)
65
+ Raccdoc::Forum.new(@socket, forum.to_s)
66
+ end
67
+
68
+ # Returns a hash of forum information. The key is the forum ID number, and the value is a hash containing the following data:
69
+ #
70
+ # * name - The forum name
71
+ # * lastnote - The earliest post ID number in the forum
72
+ # * admin - The handle of the forum admin
73
+ #
74
+ # Note that this does not return actual Raccdoc::Forum objects in the interest of saving resources, so you'll need to jump to the forum that you want.
75
+ def forums(type="all")
76
+ @socket.puts "LIST #{type}"
77
+ forums = Hash.new
78
+
79
+ response = @socket.readline.chomp
80
+ unless response.match(/^3/)
81
+ raise RuntimeError, response
82
+ end
83
+
84
+ while line = @socket.readline.chomp
85
+ break if line.match(/^\.$/)
86
+ tmp = Hash.new
87
+ line.split(/\t/).each do |pair|
88
+ (key, value) = pair.split(/:/)
89
+ if key == "admin"
90
+ value = value.split('/')[1]
91
+ end
92
+ tmp[key.to_sym] = value
93
+ end
94
+ id = tmp[:topic].to_i
95
+ forums[id] = tmp
96
+ end
97
+
98
+ return forums
99
+ end
100
+
101
+ end
102
+
103
+ class Forum
104
+
105
+ attr_reader :id
106
+ attr_reader :name
107
+ attr_reader :admin
108
+
109
+ # Sets the active forum on the server to the specified forum number (0) or name (Lobby, Program), then returns a new Raccdoc::Forum object.
110
+ #
111
+ # There are three variables exposed through attr_reader:
112
+ #
113
+ # * id - The forum ID number
114
+ # * name - The forum name
115
+ # * admin - The name of the forum administrator
116
+ def initialize(socket, forum = 0)
117
+ @socket = socket
118
+ @socket.puts "TOPIC #{forum.to_s}"
119
+ response = @socket.readline.chomp
120
+ unless response.match(/^2/)
121
+ raise RuntimeError, response
122
+ end
123
+
124
+ @headers = {}
125
+ tuples = response.split(/\t/)
126
+ tuples.delete_at(0)
127
+ tuples.each do |pair|
128
+ (key, value) = pair.split(/:/)
129
+ @headers[key.downcase.to_sym] = value
130
+ end
131
+
132
+ @id = @headers[:topic]
133
+ @name = @headers[:name]
134
+ @admin = @headers[:admin]
135
+ end
136
+
137
+ # Returns an array of all current post IDs in the forum.
138
+ def noteids
139
+ noteids = Array.new
140
+ @socket.puts("XHDR noteno")
141
+ response = @socket.readline.chomp
142
+ unless response.match(/^3/)
143
+ raise RuntimeError, response
144
+ end
145
+
146
+ while line = @socket.readline.chomp
147
+ break if line.match(/^\.$/)
148
+ (tag,noteid) = line.split(/:/)
149
+ noteids.push(noteid.to_i)
150
+ end
151
+
152
+ return noteids
153
+ end
154
+
155
+ # Returns a hash of the forum information. Keys are:
156
+ #
157
+ # * from - The username of the user who last updated the FI
158
+ # * date - The date the forum information was last updated (a Time object)
159
+ # * body - The actual text of the FI
160
+ def forum_information
161
+ fi = Hash.new
162
+ @socket.puts("SHOW info")
163
+ response = @socket.readline.chomp
164
+ unless response.match(/^3/)
165
+ raise RuntimeError, response
166
+ end
167
+
168
+ # Get header information
169
+ while line = @socket.readline.chomp
170
+ break if line.match(/^$/)
171
+ (key, value) = line.split(/: /)
172
+ if key.downcase == "date"
173
+ value = Time.parse(value)
174
+ end
175
+ fi[key.downcase.to_sym] = value
176
+ end
177
+
178
+ body = ""
179
+ while line = @socket.readline
180
+ break if line.match(/^\.$/)
181
+ body << line
182
+ end
183
+ fi[:body] = body
184
+
185
+ return fi
186
+ end
187
+
188
+ # Sets the current user's first-unread pointer to the specified number. Any posts greater than that number will be listed as unread.
189
+ def first_unread=(postid = 0)
190
+ @socket.puts("SETRC #{postid.to_s}")
191
+ response = @socket.readline.chomp
192
+ unless response.match(/^2/)
193
+ raise RuntimeError, response
194
+ end
195
+ end
196
+
197
+ # Returns the post ID number of the last read post in the forum. Any posts greater than that number can be considered unread.
198
+ def first_unread
199
+ @socket.puts("SHOW rcval")
200
+ response = @socket.readline.chomp
201
+ unless response.match(/^2/)
202
+ raise RuntimeError, response
203
+ end
204
+ response.match(/\d+.*?:\s+(\d+)/)
205
+ return $1
206
+ end
207
+
208
+ # Returns a hash of information about the posts in the forum. The hash is keyed off of the post ID, and the value is a hash containing the following information:
209
+ #
210
+ # * author - The username of the user who created the post
211
+ # * date - The date the post was created or, if the post is anonymous, the current date in UTC
212
+ # * subject - The first line of the post
213
+ # * size - The size of the post in bytes
214
+ # * authority - If the post was made with Sysop or Forum Manager status, this is set
215
+ #
216
+ # You may provide an optional range (in the form "start_id-end_id") to limit the number of posts returned. The default is to return all posts in the forum.
217
+ def post_headers(range = "")
218
+ @socket.puts("XHDR ALL #{range}")
219
+ response = @socket.readline.chomp
220
+ unless response.match(/^3/)
221
+ raise RuntimeError, response
222
+ end
223
+
224
+ posts = Hash.new
225
+
226
+ while (line = @socket.readline.chomp)
227
+ break if line.match(/^\.$/)
228
+ tmpdata = Hash.new
229
+ line.split(/\t/).each do |tuple|
230
+ (key, value) = tuple.split(/:/, 2)
231
+ tmpdata[key.downcase.to_sym] = value
232
+ end
233
+ tmpdata[:date] = tmpdata[:date] ? Time.parse(tmpdata[:date]) : Time.new.getgm
234
+ tmpdata[:author] = tmpdata[:"formal-author"] ? tmpdata[:"formal-author"].split('/')[1] : 'Anonymous'
235
+ posts[tmpdata[:noteno]] = tmpdata
236
+ end
237
+ return posts
238
+ end
239
+
240
+ # Returns a new Raccdoc::Post object for the specified post ID in the current forum.
241
+ def read(postid)
242
+ Post.new(@socket,postid)
243
+ end
244
+
245
+ # Creates a new post in the current forum using the text provided in the argument.
246
+ #
247
+ # Returns a new Raccdoc::Post object that results from reading the newly created post.
248
+ def post(body)
249
+ @socket.puts("POST")
250
+ response = @socket.readline.chomp
251
+ unless response.match(/^3/)
252
+ raise RuntimeError, response
253
+ end
254
+
255
+ @socket.puts(body)
256
+ @socket.puts(".")
257
+
258
+ response = @socket.readline.chomp
259
+ if response.match(/^2/)
260
+ postid = response.split(/:\s+/)[1]
261
+ return Post.new(@socket,postid)
262
+ else
263
+ raise RuntimeError, response
264
+ end
265
+ end
266
+
267
+ # Checks to see if the currently logged in user has permission to post in the current forum.
268
+ #
269
+ # Returns true or false.
270
+ def post?
271
+ @socket.puts("OKAY POST")
272
+ response = @socket.readline.chomp
273
+ if response.match(/^2/)
274
+ return true
275
+ elsif response.match(/^4/)
276
+ return false
277
+ else
278
+ raise RuntimeError, response
279
+ end
280
+ end
281
+ end
282
+
283
+ class Post
284
+
285
+ attr_reader :id
286
+ attr_reader :date
287
+ attr_reader :author
288
+ attr_reader :body
289
+
290
+ # Creates a new Raccdoc::Post object by reading the specified post.
291
+ #
292
+ # Useful information returned:
293
+ #
294
+ # * id - The numerical post ID
295
+ # * date - The date the post was made (or the current date in UTC if the post is anonymous)
296
+ # * author - The username of the user that created the post
297
+ # * body - The textual body of the post.
298
+ def initialize(socket,postid)
299
+ @socket = socket
300
+ @socket.puts "READ #{postid}"
301
+ response = @socket.readline.chomp
302
+ unless response.match(/^3/)
303
+ raise RuntimeError, response
304
+ end
305
+
306
+ # Get header information
307
+ post = Hash.new
308
+
309
+ while line = @socket.readline.chomp
310
+ break if line.match(/^$/)
311
+ (key,value) = line.split(/: /)
312
+ post[key.downcase.to_sym] = value
313
+ end
314
+ post[:id] = postid
315
+ post[:date] = post[:date] ? Time.parse(post[:date]) : Time.new.getgm
316
+ post[:author] = post[:'formal-author'] ? post[:'formal-author'].split('/')[1] : 'Anonymous'
317
+
318
+ post[:body] = ""
319
+ while (line = @socket.readline)
320
+ break if line.match(/^\.$/)
321
+ post[:body] << line
322
+ end
323
+
324
+ @id = post[:id]
325
+ @date = post[:date]
326
+ @author = post[:author]
327
+ @body = post[:body]
328
+ return post
329
+ end
330
+
331
+ # Checks to see if the currently-logged-in user has permission to delete the current post.
332
+ #
333
+ # Returns true or false
334
+ def delete?
335
+ @socket.puts("OKAY DELETE NOTE #{self.id}")
336
+ response = @socket.readline.chomp
337
+ if response.match(/^2/)
338
+ return true
339
+ elsif response.match(/^4/)
340
+ return false
341
+ else
342
+ raise RuntimeError, response
343
+ end
344
+ end
345
+
346
+ # Attempts to delete the current post.
347
+ #
348
+ # Returns true or false
349
+ def delete
350
+ @socket.puts("DELETE NOTE #{self.id}")
351
+ response = @socket.readline.chomp
352
+ if response.match(/^2/)
353
+ return true
354
+ elsif response.match(/^4/)
355
+ return false
356
+ else response.match(/^2/)
357
+ raise RuntimeError, response
358
+ end
359
+ end
360
+ end
361
+ end
data/raccdoc.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{raccdoc}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["H. Wade Minter"]
9
+ s.date = %q{2009-01-12}
10
+ s.description = %q{A Ruby interface into the Raccdoc protocol}
11
+ s.email = %q{minter@lunenburg.org}
12
+ s.extra_rdoc_files = ["lib/raccdoc.rb", "LICENSE", "README"]
13
+ s.files = ["lib/raccdoc.rb", "LICENSE", "Manifest", "raccdoc.gemspec", "Rakefile", "README", "test/raccdoc_connection_test.rb", "test/test_helper.rb"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Raccdoc", "--main", "README"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{raccdoc}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{A Ruby interface into the Raccdoc protocol}
21
+ s.test_files = ["test/raccdoc_connection_test.rb", "test/test_helper.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_runtime_dependency(%q<socket>, [">= 0"])
29
+ s.add_runtime_dependency(%q<time>, [">= 0"])
30
+ s.add_development_dependency(%q<echoe>, [">= 0"])
31
+ else
32
+ s.add_dependency(%q<socket>, [">= 0"])
33
+ s.add_dependency(%q<time>, [">= 0"])
34
+ s.add_dependency(%q<echoe>, [">= 0"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<socket>, [">= 0"])
38
+ s.add_dependency(%q<time>, [">= 0"])
39
+ s.add_dependency(%q<echoe>, [">= 0"])
40
+ end
41
+ end
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RaccdocConnectionTest < Test::Unit::TestCase
4
+ def setup
5
+ @socket = mock()
6
+ end
7
+
8
+ def test_valid_anonymous_connection
9
+ TCPSocket.expects(:new).returns(@socket)
10
+ @socket.expects(:readline).returns("200 Server started seed:Ci0B2YeMio8ftYjElTa+EQ==")
11
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
12
+ assert_equal bbs.class, Raccdoc::Connection
13
+ assert_equal bbs.host, "test.bbs.example"
14
+ end
15
+
16
+ def test_connection_refused_anonymous
17
+ TCPSocket.expects(:new).with('test.bbs.example', '6145').raises(Errno::ECONNREFUSED)
18
+ assert_raise(RuntimeError, 'Could not connect to test.bbs.example, port 6145') do
19
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
20
+ end
21
+ end
22
+
23
+ def test_connection_bad_login
24
+ socket = mock()
25
+ socket.stubs(:readline).returns("200 Server started seed:Ci0B2YeMio8ftYjElTa+EQ==").then.returns("405 Cannot process login Invalid password")
26
+ socket.stubs(:puts)
27
+ TCPSocket.expects(:new).returns(socket)
28
+ assert_raise(RuntimeError, '404 User does not exist') do
29
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example', :user => 'Bugcrusher', :password => 'BadPassword')
30
+ end
31
+ end
32
+
33
+ def test_connection_that_returns_unknown_status
34
+ socket = mock()
35
+ TCPSocket.expects(:new).returns(socket)
36
+ socket.expects(:readline).returns("999 Stuff is messed up")
37
+ assert_raise(RuntimeError) do
38
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
39
+ end
40
+ end
41
+
42
+ def test_logout_succeeds
43
+ @socket.stubs(:puts)
44
+ @socket.stubs(:close)
45
+ @socket.stubs(:closed?).returns(false)
46
+ TCPSocket.expects(:new).returns(@socket)
47
+ @socket.stubs(:readline).returns("200 Server started seed:Ci0B2YeMio8ftYjElTa+EQ==").then.returns("201 Session ended")
48
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
49
+ bbs.logout
50
+ end
51
+
52
+ def test_logout_fails
53
+ @socket.stubs(:puts)
54
+ @socket.stubs(:close)
55
+ @socket.stubs(:closed?).returns(false)
56
+ TCPSocket.expects(:new).returns(@socket)
57
+ @socket.stubs(:readline).returns("200 Server started seed:Ci0B2YeMio8ftYjElTa+EQ==").then.returns("999 Something Broke")
58
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
59
+ assert_raise(RuntimeError) do
60
+ bbs.logout
61
+ end
62
+ end
63
+
64
+ def test_connected
65
+ @socket.stubs(:puts)
66
+ @socket.stubs(:closed?).returns(false)
67
+ TCPSocket.expects(:new).returns(@socket)
68
+ @socket.stubs(:readline).returns("200 Server started seed:Ci0B2YeMio8ftYjElTa+EQ==").then.returns("999 Something Broke")
69
+ bbs = Raccdoc::Connection.new(:host => 'test.bbs.example')
70
+ assert_equal bbs.connected?, true
71
+ end
72
+
73
+ end
@@ -0,0 +1,5 @@
1
+ require 'test/unit'
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+ require 'raccdoc'
4
+ require 'rubygems'
5
+ require 'mocha'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minter-raccdoc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - H. Wade Minter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-12 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: socket
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: time
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: echoe
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ description: A Ruby interface into the Raccdoc protocol
43
+ email: minter@lunenburg.org
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - lib/raccdoc.rb
50
+ - LICENSE
51
+ - README
52
+ files:
53
+ - lib/raccdoc.rb
54
+ - LICENSE
55
+ - Manifest
56
+ - raccdoc.gemspec
57
+ - Rakefile
58
+ - README
59
+ - test/raccdoc_connection_test.rb
60
+ - test/test_helper.rb
61
+ has_rdoc: true
62
+ homepage: ""
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --line-numbers
66
+ - --inline-source
67
+ - --title
68
+ - Raccdoc
69
+ - --main
70
+ - README
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "1.2"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project: raccdoc
88
+ rubygems_version: 1.2.0
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: A Ruby interface into the Raccdoc protocol
92
+ test_files:
93
+ - test/raccdoc_connection_test.rb
94
+ - test/test_helper.rb