siffer 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +65 -0
  3. data/Rakefile +64 -0
  4. data/bin/siffer +71 -0
  5. data/doc/SIF ImplementationSpecification.pdf +0 -0
  6. data/doc/rdoc/classes/Siffer.html +374 -0
  7. data/doc/rdoc/classes/Siffer/Agent.html +296 -0
  8. data/doc/rdoc/classes/Siffer/Container.html +286 -0
  9. data/doc/rdoc/classes/Siffer/Messages.html +141 -0
  10. data/doc/rdoc/classes/Siffer/Messages/Ack.html +216 -0
  11. data/doc/rdoc/classes/Siffer/Messages/Acl.html +160 -0
  12. data/doc/rdoc/classes/Siffer/Messages/Error.html +248 -0
  13. data/doc/rdoc/classes/Siffer/Messages/Message.html +359 -0
  14. data/doc/rdoc/classes/Siffer/Messages/Message/Header.html +181 -0
  15. data/doc/rdoc/classes/Siffer/Messages/Register.html +257 -0
  16. data/doc/rdoc/classes/Siffer/Messages/RequestBody.html +300 -0
  17. data/doc/rdoc/classes/Siffer/Messages/Status.html +269 -0
  18. data/doc/rdoc/classes/Siffer/Messaging.html +331 -0
  19. data/doc/rdoc/classes/Siffer/Protocol.html +388 -0
  20. data/doc/rdoc/classes/Siffer/Protocol/NonPostRequest.html +111 -0
  21. data/doc/rdoc/classes/Siffer/Protocol/UnknownPath.html +111 -0
  22. data/doc/rdoc/classes/Siffer/Registration.html +391 -0
  23. data/doc/rdoc/classes/Siffer/Request.html +209 -0
  24. data/doc/rdoc/classes/Siffer/RequestLogger.html +211 -0
  25. data/doc/rdoc/classes/Siffer/Response.html +182 -0
  26. data/doc/rdoc/classes/Siffer/Server.html +242 -0
  27. data/doc/rdoc/created.rid +1 -0
  28. data/doc/rdoc/files/LICENSE.html +129 -0
  29. data/doc/rdoc/files/README_rdoc.html +184 -0
  30. data/doc/rdoc/files/lib/agent_rb.html +101 -0
  31. data/doc/rdoc/files/lib/container_rb.html +108 -0
  32. data/doc/rdoc/files/lib/messages/ack_rb.html +101 -0
  33. data/doc/rdoc/files/lib/messages/acl_rb.html +101 -0
  34. data/doc/rdoc/files/lib/messages/error_rb.html +101 -0
  35. data/doc/rdoc/files/lib/messages/message_rb.html +101 -0
  36. data/doc/rdoc/files/lib/messages/register_rb.html +101 -0
  37. data/doc/rdoc/files/lib/messages/request_body_rb.html +101 -0
  38. data/doc/rdoc/files/lib/messages/status_rb.html +101 -0
  39. data/doc/rdoc/files/lib/messages_rb.html +114 -0
  40. data/doc/rdoc/files/lib/messaging_rb.html +101 -0
  41. data/doc/rdoc/files/lib/protocol_rb.html +101 -0
  42. data/doc/rdoc/files/lib/registration_rb.html +101 -0
  43. data/doc/rdoc/files/lib/request_logger_rb.html +101 -0
  44. data/doc/rdoc/files/lib/request_rb.html +101 -0
  45. data/doc/rdoc/files/lib/response_rb.html +101 -0
  46. data/doc/rdoc/files/lib/server_rb.html +101 -0
  47. data/doc/rdoc/files/lib/siffer_rb.html +115 -0
  48. data/doc/rdoc/fr_class_index.html +47 -0
  49. data/doc/rdoc/fr_file_index.html +46 -0
  50. data/doc/rdoc/fr_method_index.html +96 -0
  51. data/doc/rdoc/index.html +24 -0
  52. data/doc/rdoc/rdoc-style.css +208 -0
  53. data/lib/agent.rb +43 -0
  54. data/lib/container.rb +96 -0
  55. data/lib/messages.rb +7 -0
  56. data/lib/messages/ack.rb +43 -0
  57. data/lib/messages/acl.rb +25 -0
  58. data/lib/messages/error.rb +174 -0
  59. data/lib/messages/message.rb +71 -0
  60. data/lib/messages/register.rb +60 -0
  61. data/lib/messages/request_body.rb +66 -0
  62. data/lib/messages/status.rb +55 -0
  63. data/lib/messaging.rb +96 -0
  64. data/lib/protocol.rb +159 -0
  65. data/lib/registration.rb +87 -0
  66. data/lib/request.rb +25 -0
  67. data/lib/request_logger.rb +31 -0
  68. data/lib/response.rb +26 -0
  69. data/lib/server.rb +40 -0
  70. data/lib/siffer.rb +44 -0
  71. data/spec/agent_spec.rb +53 -0
  72. data/spec/cli_spec.rb +40 -0
  73. data/spec/container_spec.rb +103 -0
  74. data/spec/default_agent +6 -0
  75. data/spec/default_server +5 -0
  76. data/spec/message_specs/ack_spec.rb +28 -0
  77. data/spec/message_specs/error_spec.rb +24 -0
  78. data/spec/message_specs/header_spec.rb +25 -0
  79. data/spec/message_specs/message_spec.rb +57 -0
  80. data/spec/message_specs/register_spec.rb +86 -0
  81. data/spec/message_specs/request_body_spec.rb +58 -0
  82. data/spec/message_specs/status_spec.rb +25 -0
  83. data/spec/messaging_spec.rb +88 -0
  84. data/spec/protocol_spec.rb +49 -0
  85. data/spec/registration_spec.rb +33 -0
  86. data/spec/request_logger_spec.rb +15 -0
  87. data/spec/request_spec.rb +10 -0
  88. data/spec/response_spec.rb +24 -0
  89. data/spec/server_spec.rb +35 -0
  90. data/spec/spec_helper.rb +26 -0
  91. metadata +191 -0
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__),"spec_helper")
2
+
3
+ # The messaging is best tested doing a full request/response
4
+ # cycle using both Server and Agent components
5
+
6
+ [Siffer::Server, Siffer::Agent].each do |component|
7
+
8
+ # Stage the component a little bit:
9
+ # Agents require Servers
10
+ # Both require central-admin
11
+ component = component.new("admin" => 'none', "servers" => '')
12
+ msg = Siffer::Messages::Message.new("source")
13
+ msg.content do |xml|
14
+ xml.SIF_BogusType
15
+ end
16
+
17
+ describe component, "Messaging - response" do
18
+ it "should always return Ack for proper SIF_Messages" do
19
+ for_every_path(:on => component, :input => msg) do |res|
20
+ res.body.should match(/SIF_Ack/)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe component, "Messaging - content-type" do
26
+ it "should always respond with application/xml" do
27
+ for_every_path(:on => component, :input => msg) do |res|
28
+ res.content_type.should == Siffer::Messaging::MIME_TYPES["appxml"]
29
+ end
30
+ end
31
+
32
+ it "should only receive application/xml" do
33
+ for_every_path(:on => component,"CONTENT_TYPE" => "x") do |res|
34
+ res.should be_client_error
35
+ res.status.should == 406
36
+ end
37
+ end
38
+ end
39
+
40
+ describe component, "Messaging - validation" do
41
+
42
+ it "should return Xml Error code for bad message (xml)" do
43
+ %w[<Junk>>>> <Junk> </Junk> Junk !@ex].each do |msg|
44
+ for_every_path(:on => component, :input => msg) do |res|
45
+ res.body.should match(/SIF_Error/)
46
+ res.body.should match(/SIF_Category>1<\/SIF_Category/)
47
+ res.body.should match(/SIF_Code>2<\/SIF_Code>/)
48
+ res.body.should match(/Message is not well-formed/)
49
+ # spec says Oringals should be included and empty
50
+ res.body.should match(/SIF_OriginalSourceId\s*\/>/)
51
+ res.body.should match(/SIF_OriginalMsgId\s*\/>/)
52
+ end
53
+ end
54
+ end
55
+
56
+ it "should validaate message is SIF_Message" do
57
+ msg = "<someotherkind><of>XML</of></someotherkind>"
58
+ for_every_path(:on => component, :input => msg) do |res|
59
+ res.body.should match(/SIF_Category>12/)
60
+ res.body.should match(/SIF_Code>2/)
61
+ end
62
+ end
63
+
64
+ it "should validate message xmlns" do
65
+ msg = Siffer::Messages::Register.new(
66
+ "bad-xmlns",
67
+ component.name,
68
+ :xmlns => 'http://bogus.xmlns')
69
+ for_every_path(:on => component, :input => msg) do |res|
70
+ res.body.should match(/SIF_Category>1<\/SIF_Category/)
71
+ res.body.should match(/SIF_Code>4<\/SIF_Code/)
72
+ res.body.should match(/SIF_ExtendedDesc>XMLNS not compatible with SIF/)
73
+ end
74
+ end
75
+
76
+ it "should validate SIF version" do
77
+ msg = Siffer::Messages::Register.new(
78
+ "bad-version",
79
+ component.name,
80
+ :version => '99.99')
81
+ for_every_path(:on => component, :input => msg) do |res|
82
+ res.body.should match(/SIF_Category>12<\/SIF_Category/)
83
+ res.body.should match(/SIF_Code>3<\/SIF_Code>/)
84
+ end
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ [Siffer::Server, Siffer::Agent].each do |component|
4
+
5
+ # Stage the component a little bit:
6
+ # Agents require Servers
7
+ # Both require central-admin
8
+ component = component.new("admin" => 'none', "servers" => '')
9
+ # setup messages to use for mock requests
10
+ ping = "<SIF_Message><SIF_SystemControl><SIF_Ping /></SIF_SystemControl></SIF_Message>"
11
+ status = "<SIF_Message><SIF_SystemControl><SIF_Status /></SIF_SystemControl></SIF_Message>"
12
+ register = "<SIF_Message><SIF_Register /></SIF_Message>"
13
+
14
+ describe component, "Protocol - /unknown_path" do
15
+ it "should return 404" do
16
+ res = Rack::MockRequest.new(component).post("/bad_path")
17
+ res.should be_not_found
18
+ end
19
+ end
20
+
21
+ describe component, "Protocol - Accepted Paths" do
22
+ it "should only allow POST method" do
23
+ Siffer::Protocol::ACCEPTABLE_PATHS.each do |name,path|
24
+ res = Rack::MockRequest.new(component).get(path)
25
+ res.should be_client_error
26
+ end
27
+ end
28
+
29
+ it "should be identified by predicate through body" do
30
+ Siffer::Protocol::ACCEPTABLE_PATHS.each do |name,path|
31
+ unless name == :root
32
+ component.call({"rack.input" => eval(name.to_s)})
33
+ component.should eval("be_#{name.to_s}")
34
+ end
35
+ end
36
+ end
37
+
38
+ it "should be identified by predicate through path-info" do
39
+ Siffer::Protocol::ACCEPTABLE_PATHS.each do |name,path|
40
+ unless name == :root
41
+ component.call({
42
+ "rack.input" => "<SIF_Message><SIF_#{name.to_s} /></SIF_Message>",
43
+ "PATH_INFO" => path})
44
+ component.should eval("be_#{name.to_s}")
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__),"spec_helper")
2
+
3
+ # Registration is best tested through the Siffer::Server component
4
+
5
+ describe Siffer::Registration do
6
+
7
+ before(:each) do
8
+ @server = Siffer::Server.new("admin" => "none")
9
+ end
10
+
11
+ it "should determine agent registration" do
12
+ @server.registered?("Default Agent").should be_false
13
+ @server.agents["Default Agent"] = "http://localhost"
14
+ @server.registered?("Default Agent").should be_true
15
+ end
16
+
17
+ it "should return not registered message for non-registered agents" do
18
+ msg = Siffer::Messages::Message.new("Default Agent")
19
+ msg.content do |xml|
20
+ xml.SIF_Ping
21
+ end
22
+ res = Rack::MockRequest.new(@server).post("/",:input => msg)
23
+ res.body.should match(/SIF_Category>4/)
24
+ res.body.should match(/SIF_Code>9/)
25
+ end
26
+
27
+ it "should return ACL for successful registration" do
28
+ msg = Siffer::Messages::Register.new("Default Agent", "Default Agent")
29
+ res = Rack::MockRequest.new(@server).post("/",:input => msg)
30
+ res.body.should match(/SIF_Ack/)
31
+ res.body.should match(/SIF_Status/)
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__),"spec_helper")
2
+
3
+ describe Siffer::RequestLogger do
4
+ msg = "<SIF_Message><SIF_SystemControl><SIF_Ping /></SIF_SystemControl></SIF_Message>"
5
+
6
+ it "should log requests" do
7
+ log = []
8
+ app = Rack::Builder.new do
9
+ use Siffer::RequestLogger, log
10
+ run Siffer::Server.new("admin" => "none")
11
+ end
12
+ res = Rack::MockRequest.new(app).post("/", :input => msg)
13
+ log.size.should == 1
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Siffer::Request do
4
+ it "should provide access to the body as a SIF_Message (Siffer::Message)" do
5
+ msg = Siffer::Messages::Register.new("register-source","source-name")
6
+ request = Siffer::Request.new('rack.input' => msg)
7
+ request.message.type.should == "Register"
8
+ request.message.source_id.should == "register-source"
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__),"spec_helper")
2
+ require 'webrick'
3
+
4
+ Thread.abort_on_exception = true
5
+
6
+ describe Siffer::Response do
7
+ it "should default content-type to application/xml" do
8
+ response = Siffer::Response.new()
9
+ response.content_type.should == Siffer::Messaging::MIME_TYPES["appxml"]
10
+ end
11
+
12
+ it "should receive response from url,data" do
13
+ with_fake_server do |url|
14
+ response = Siffer::Response.from(url,"Hello World")
15
+ response.should be_successful
16
+ response.body.each { |line| line.should == "Hello World" }
17
+ end
18
+ end
19
+
20
+ it "should return 500 for bad url" do
21
+ response = Siffer::Response.from("http://localhost:9999","Hello World")
22
+ response.should be_server_error
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Siffer::Server do
4
+ it "should instantiate with default host, port, name, min_buffer" do
5
+ server = Siffer::Server.new("admin" => 'none')
6
+ server.host.should == "localhost"
7
+ server.port.should == 8300
8
+ server.name.should == "Default Server"
9
+ server.min_buffer.should == 1024
10
+ end
11
+
12
+ it "should allow defaults to be overriden" do
13
+ server = Siffer::Server.new("admin" => 'none',
14
+ "name" => "name",
15
+ "host" => "test",
16
+ "port" => 222,
17
+ "min_buffer" => 2048)
18
+ server.host.should == "test"
19
+ server.port.should == 222
20
+ server.name.should == "name"
21
+ server.min_buffer.should == 2048
22
+ end
23
+
24
+ it "should require an admin URL" do
25
+ lambda {
26
+ server = Siffer::Server.new
27
+ }.should raise_error("Administration URL required")
28
+ end
29
+
30
+ it "should respond to uri" do
31
+ server = Siffer::Server.new("admin" => 'none')
32
+ server.uri.should == "http://localhost:8300"
33
+ end
34
+
35
+ end
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__),"..", "lib","siffer")
2
+ require 'spec'
3
+
4
+ # Configures a WEBrick server and yields URL. When passed a block
5
+ # starts and stops the server for the context. It returns what it
6
+ # receives from the request.
7
+ def with_fake_server(app = nil)
8
+ fake_app = app || lambda { |env| [200,{},env["rack.input"].read] }
9
+ server = WEBrick::HTTPServer.new(:Host => '0.0.0.0',:Port => 9202)
10
+ server.mount "/", Rack::Handler::WEBrick, fake_app
11
+ Thread.new { server.start }
12
+ trap(:INT) { server.shutdown }
13
+ yield "http://localhost:9202/" if block_given?
14
+ server.shutdown
15
+ end
16
+
17
+ # Helper method to iterate all of the ACCEPTABLE_PATHS
18
+ # on the specified component(Server/Agent). Yields
19
+ # the Response object for each Request.
20
+ def for_every_path(options = {}, &block)
21
+ component = options.delete(:on)
22
+ Siffer::Protocol::ACCEPTABLE_PATHS.each do |name,path|
23
+ res = Rack::MockRequest.new(component).post(path,options)
24
+ yield res
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: siffer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Clint Hill
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: uuid
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hpricot
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: builder
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description:
56
+ email: clint.hill@h3osoftware.com
57
+ executables:
58
+ - siffer
59
+ extensions: []
60
+
61
+ extra_rdoc_files: []
62
+
63
+ files:
64
+ - LICENSE
65
+ - README.rdoc
66
+ - Rakefile
67
+ - spec/agent_spec.rb
68
+ - spec/cli_spec.rb
69
+ - spec/container_spec.rb
70
+ - spec/default_agent
71
+ - spec/default_server
72
+ - spec/message_specs
73
+ - spec/message_specs/ack_spec.rb
74
+ - spec/message_specs/error_spec.rb
75
+ - spec/message_specs/header_spec.rb
76
+ - spec/message_specs/message_spec.rb
77
+ - spec/message_specs/register_spec.rb
78
+ - spec/message_specs/request_body_spec.rb
79
+ - spec/message_specs/status_spec.rb
80
+ - spec/messaging_spec.rb
81
+ - spec/protocol_spec.rb
82
+ - spec/registration_spec.rb
83
+ - spec/request_logger_spec.rb
84
+ - spec/request_spec.rb
85
+ - spec/response_spec.rb
86
+ - spec/server_spec.rb
87
+ - spec/spec_helper.rb
88
+ - lib/agent.rb
89
+ - lib/container.rb
90
+ - lib/messages
91
+ - lib/messages/ack.rb
92
+ - lib/messages/acl.rb
93
+ - lib/messages/error.rb
94
+ - lib/messages/message.rb
95
+ - lib/messages/register.rb
96
+ - lib/messages/request_body.rb
97
+ - lib/messages/status.rb
98
+ - lib/messages.rb
99
+ - lib/messaging.rb
100
+ - lib/protocol.rb
101
+ - lib/registration.rb
102
+ - lib/request.rb
103
+ - lib/request_logger.rb
104
+ - lib/response.rb
105
+ - lib/server.rb
106
+ - lib/siffer.rb
107
+ - doc/rdoc
108
+ - doc/rdoc/classes
109
+ - doc/rdoc/classes/Siffer
110
+ - doc/rdoc/classes/Siffer/Agent.html
111
+ - doc/rdoc/classes/Siffer/Container.html
112
+ - doc/rdoc/classes/Siffer/Messages
113
+ - doc/rdoc/classes/Siffer/Messages/Ack.html
114
+ - doc/rdoc/classes/Siffer/Messages/Acl.html
115
+ - doc/rdoc/classes/Siffer/Messages/Error.html
116
+ - doc/rdoc/classes/Siffer/Messages/Message
117
+ - doc/rdoc/classes/Siffer/Messages/Message/Header.html
118
+ - doc/rdoc/classes/Siffer/Messages/Message.html
119
+ - doc/rdoc/classes/Siffer/Messages/Register.html
120
+ - doc/rdoc/classes/Siffer/Messages/RequestBody.html
121
+ - doc/rdoc/classes/Siffer/Messages/Status.html
122
+ - doc/rdoc/classes/Siffer/Messages.html
123
+ - doc/rdoc/classes/Siffer/Messaging.html
124
+ - doc/rdoc/classes/Siffer/Protocol
125
+ - doc/rdoc/classes/Siffer/Protocol/NonPostRequest.html
126
+ - doc/rdoc/classes/Siffer/Protocol/UnknownPath.html
127
+ - doc/rdoc/classes/Siffer/Protocol.html
128
+ - doc/rdoc/classes/Siffer/Registration.html
129
+ - doc/rdoc/classes/Siffer/Request.html
130
+ - doc/rdoc/classes/Siffer/RequestLogger.html
131
+ - doc/rdoc/classes/Siffer/Response.html
132
+ - doc/rdoc/classes/Siffer/Server.html
133
+ - doc/rdoc/classes/Siffer.html
134
+ - doc/rdoc/created.rid
135
+ - doc/rdoc/files
136
+ - doc/rdoc/files/lib
137
+ - doc/rdoc/files/lib/agent_rb.html
138
+ - doc/rdoc/files/lib/container_rb.html
139
+ - doc/rdoc/files/lib/messages
140
+ - doc/rdoc/files/lib/messages/ack_rb.html
141
+ - doc/rdoc/files/lib/messages/acl_rb.html
142
+ - doc/rdoc/files/lib/messages/error_rb.html
143
+ - doc/rdoc/files/lib/messages/message_rb.html
144
+ - doc/rdoc/files/lib/messages/register_rb.html
145
+ - doc/rdoc/files/lib/messages/request_body_rb.html
146
+ - doc/rdoc/files/lib/messages/status_rb.html
147
+ - doc/rdoc/files/lib/messages_rb.html
148
+ - doc/rdoc/files/lib/messaging_rb.html
149
+ - doc/rdoc/files/lib/protocol_rb.html
150
+ - doc/rdoc/files/lib/registration_rb.html
151
+ - doc/rdoc/files/lib/request_logger_rb.html
152
+ - doc/rdoc/files/lib/request_rb.html
153
+ - doc/rdoc/files/lib/response_rb.html
154
+ - doc/rdoc/files/lib/server_rb.html
155
+ - doc/rdoc/files/lib/siffer_rb.html
156
+ - doc/rdoc/files/LICENSE.html
157
+ - doc/rdoc/files/README_rdoc.html
158
+ - doc/rdoc/fr_class_index.html
159
+ - doc/rdoc/fr_file_index.html
160
+ - doc/rdoc/fr_method_index.html
161
+ - doc/rdoc/index.html
162
+ - doc/rdoc/rdoc-style.css
163
+ - doc/SIF ImplementationSpecification.pdf
164
+ has_rdoc: false
165
+ homepage: http://h3osoftware.com/siffer
166
+ post_install_message:
167
+ rdoc_options: []
168
+
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: "0"
176
+ version:
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: "0"
182
+ version:
183
+ requirements: []
184
+
185
+ rubyforge_project: siffer
186
+ rubygems_version: 1.3.1
187
+ signing_key:
188
+ specification_version: 2
189
+ summary: Siffer - School Interoperability Framework by h3o(software)
190
+ test_files: []
191
+