picnic 0.5.0 → 0.6.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.txt +15 -0
- data/Rakefile +2 -2
- data/lib/picnic/authentication.rb +179 -47
- data/lib/picnic/controllers.rb +0 -27
- data/lib/picnic/postambles.rb +25 -7
- data/lib/picnic/version.rb +1 -1
- data/lib/picnic.rb +22 -13
- metadata +52 -37
data/CHANGELOG.txt
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
=== 0.6.0 :: 2007-02-26
|
2
|
+
|
3
|
+
* Added support for CAS authentication. See picnic/authentication.rb for
|
4
|
+
details.
|
5
|
+
* Webrick and Mongrel can now be made to bind to a specific IP address using
|
6
|
+
the :bind_address option. If no :bind_address is specified, the server will
|
7
|
+
listen on all addresses (i.e. '0.0.0.0').
|
8
|
+
* The Public controller for serving the '/public' directory is gone. It has
|
9
|
+
been replaced by respective Webrick and Mongrel mechanisms for serving
|
10
|
+
directory contents, since these are much faster. If you're using CGI/FastCGI,
|
11
|
+
you'll have to manually configure your web server (i.e. probably Apache)
|
12
|
+
to serve your public directory contents.
|
13
|
+
* The gem package now correctly recognizes markaby as a required
|
14
|
+
dependency.
|
15
|
+
|
1
16
|
=== 0.5.0 :: 2007-12-20
|
2
17
|
|
3
18
|
* First public release.
|
data/Rakefile
CHANGED
@@ -53,6 +53,6 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
|
53
53
|
#p.extra_deps - An array of rubygem dependencies.
|
54
54
|
#p.spec_extras - A hash of extra values to set in the gemspec.
|
55
55
|
|
56
|
-
#
|
57
|
-
|
56
|
+
# note that camping-1.5.0.180 is now bundled with picnic the vendor directory,
|
57
|
+
p.extra_deps = ['markaby']
|
58
58
|
end
|
@@ -2,48 +2,48 @@ module Picnic #:nodoc:
|
|
2
2
|
# These modules (currently only one module, but more in the future) provide authentication
|
3
3
|
# for your Camping app.
|
4
4
|
#
|
5
|
-
# This code is based on Camping::BasicAuth written by Manfred Stienstra
|
6
|
-
# (see http://www.fngtps.com/2006/05/basic-authentication-for-camping).
|
7
|
-
#
|
8
|
-
# ----
|
9
|
-
#
|
10
|
-
# Picnic::Authentication::Basic can be mixed into a camping application to get Basic Authentication
|
11
|
-
# support in the application. The module defines a <tt>service</tt> method that only continues
|
12
|
-
# the request chain when proper credentials are given.
|
13
|
-
#
|
14
|
-
# == Getting Started
|
15
|
-
#
|
16
|
-
# To activate Basic Authentication for your application:
|
17
|
-
#
|
18
|
-
# 1. Picnic-fy your Camping app (e.g: <tt>Camping.goes :your_app; YourApp.picnic!</tt>)
|
19
|
-
# 2. Call <tt>authenticate_using <module></tt> (e.g: <tt>YourApp.authenticate_using :basic</tt>)
|
20
|
-
# 3. Define an <tt>authenticate</tt> method on your application module that takes a hash.
|
21
|
-
# The hash contains credentials like <tt>:username</tt>, <tt>:password</tt>, and <tt>:hostname</tt>,
|
22
|
-
# although future authentication modules may submit other credentials.
|
23
|
-
# The <tt>authenticate</tt> method should return true when the credentials are valid.
|
24
|
-
# Examples:
|
25
|
-
#
|
26
|
-
# module Blog
|
27
|
-
# def authenticate(credentials)
|
28
|
-
# credentials[:username] == 'admin' &&
|
29
|
-
# credentials[:password] == 'flapper30'
|
30
|
-
# end
|
31
|
-
# module_function :authenticate
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# or
|
35
|
-
#
|
36
|
-
# module Wiki
|
37
|
-
# def authenticate(credentials)
|
38
|
-
# u = credentials[:username]
|
39
|
-
# p = credentials[:password]
|
40
|
-
# Models::User.find_by_username_and_password u, p
|
41
|
-
# end
|
42
|
-
# module_function :authenticate
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# 4. <tt>service</tt> sets <tt>@credentials</tt> to the credentials of the person who logged in.
|
46
5
|
module Authentication
|
6
|
+
# Picnic::Authentication::Basic provides Basic HTTP Authentication for your Camping app.
|
7
|
+
# The module defines a <tt>service</tt> method that only continues the request chain when
|
8
|
+
# proper credentials are provided by the client (browser).
|
9
|
+
#
|
10
|
+
# == Getting Started
|
11
|
+
#
|
12
|
+
# To activate Basic Authentication for your application:
|
13
|
+
#
|
14
|
+
# 1. Picnic-fy your Camping app (e.g: <tt>Camping.goes :your_app; YourApp.picnic!</tt>)
|
15
|
+
# 2. Call <tt>YourApp.authenticate_using :basic</tt>.
|
16
|
+
# 3. Define an <tt>authenticate</tt> method on your application module that takes a hash.
|
17
|
+
# The hash contains credentials like <tt>:username</tt>, <tt>:password</tt>, and <tt>:hostname</tt>,
|
18
|
+
# although future authentication modules may submit other credentials.
|
19
|
+
# The <tt>authenticate</tt> method should return true when the credentials are valid.
|
20
|
+
# Examples:
|
21
|
+
#
|
22
|
+
# module Blog
|
23
|
+
# def authenticate(credentials)
|
24
|
+
# credentials[:username] == 'admin' &&
|
25
|
+
# credentials[:password] == 'flapper30'
|
26
|
+
# end
|
27
|
+
# module_function :authenticate
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# or
|
31
|
+
#
|
32
|
+
# module Wiki
|
33
|
+
# def authenticate(credentials)
|
34
|
+
# u = credentials[:username]
|
35
|
+
# p = credentials[:password]
|
36
|
+
# Models::User.find_by_username_and_password u, p
|
37
|
+
# end
|
38
|
+
# module_function :authenticate
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# 4. <tt>service</tt> sets <tt>@credentials</tt> to the credentials of the person who logged in.
|
42
|
+
#
|
43
|
+
# ----
|
44
|
+
#
|
45
|
+
# This code is based on Camping::BasicAuth written by Manfred Stienstra
|
46
|
+
# (see http://www.fngtps.com/2006/05/basic-authentication-for-camping).
|
47
47
|
module Basic
|
48
48
|
require 'base64'
|
49
49
|
|
@@ -56,14 +56,15 @@ module Picnic #:nodoc:
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
# The <tt>service</tt> method, when mixed into your application module, wraps around the
|
60
|
-
# <tt>service</tt> method defined by Camping. It halts execution of the controllers when
|
61
|
-
# your <tt>authenticate</tt> method returns false. See the module documentation how to
|
62
|
-
# define your own <tt>authenticate</tt> method.
|
63
59
|
def service(*a)
|
60
|
+
app = Kernel.const_get self.class.name.gsub(/^(\w+)::.+$/, '\1')
|
61
|
+
unless app.methods.include? :authenticate
|
62
|
+
raise "Basic authentication is enabled but the 'authenticate' method has not been defined."
|
63
|
+
end
|
64
|
+
|
64
65
|
@credentials = read_credentials || {}
|
65
|
-
|
66
|
-
if
|
66
|
+
|
67
|
+
if app.authenticate(@credentials)
|
67
68
|
s = super(*a)
|
68
69
|
else
|
69
70
|
@status = 401
|
@@ -76,5 +77,136 @@ module Picnic #:nodoc:
|
|
76
77
|
s
|
77
78
|
end
|
78
79
|
end
|
80
|
+
|
81
|
+
|
82
|
+
# Picnic::Authentication::Cas provides basic CAS (Central Authentication System) authentication
|
83
|
+
# for your Camping app.
|
84
|
+
#
|
85
|
+
# To learn more about CAS, see http://rubycas-client.googlecode.com and
|
86
|
+
# http://www.ja-sig.org/products/cas.
|
87
|
+
#
|
88
|
+
# The module defines a <tt>service</tt> method that intercepts every request to check for CAS
|
89
|
+
# authentication. If the user has already been authenticated, the request proceeds as normal
|
90
|
+
# and the authenticated user's username is made available under <tt>@state[:cas_username].
|
91
|
+
# Otherwise the request is redirected to your CAS server for authentication.
|
92
|
+
#
|
93
|
+
# == Getting Started
|
94
|
+
#
|
95
|
+
# To activate CAS authentication for your application:
|
96
|
+
#
|
97
|
+
# 1. Picnic-fy your Camping app (e.g: <tt>Camping.goes :your_app; YourApp.picnic!</tt>)
|
98
|
+
# 2. Call <tt>YourApp.authenticate_using :cas</tt>.
|
99
|
+
# 3. In your app's configuration YAML file add something like this:
|
100
|
+
# authentication:
|
101
|
+
# cas_base_url: https://login.example.com/cas
|
102
|
+
# Where the value for </tt>cas_base_url</tt> is the URL of your CAS server.
|
103
|
+
# 4. That's it. Now whenever a user tries to access any of your controller's actions,
|
104
|
+
# the request will be checked for CAS authentication. If the user is authenticated,
|
105
|
+
# their username is availabe in @state[:cas_username]. Note that there is currently
|
106
|
+
# no way to apply CAS authentication only to certain controllers or actions. When
|
107
|
+
# enabled, CAS authentication applies to your entire application, except for items
|
108
|
+
# placed in the /public subdirectory (CSS files, JavaScripts, images, etc.). The
|
109
|
+
# public directory does not require CAS authentication, so anyone can access its
|
110
|
+
# contents.
|
111
|
+
#
|
112
|
+
module Cas
|
113
|
+
require 'camping/db'
|
114
|
+
require 'camping/session'
|
115
|
+
|
116
|
+
|
117
|
+
$: << File.dirname(File.expand_path(__FILE__))+"/../../../rubycas-client2/lib" # for development
|
118
|
+
require 'rubycas-client'
|
119
|
+
|
120
|
+
# app = Kernel.const_get self.name.gsub(/^(\w+)::.+$/, '\1')
|
121
|
+
# raise "Cannot enable CAS authentication because your Camping app does not extend Camping::Session." unless
|
122
|
+
# app.ancestors.include?(Camping::Session)
|
123
|
+
|
124
|
+
# There must be a smarter way to do this... but for now, we just re-implement
|
125
|
+
# the Camping::Session method here to provide session support for CAS.
|
126
|
+
module Session
|
127
|
+
# This doesn't work :( MySQL connection is not carried over.
|
128
|
+
#define_method(:service, Camping::Session.instance_method(:service))
|
129
|
+
|
130
|
+
def service(*a)
|
131
|
+
Camping::Models::Session.create_schema
|
132
|
+
|
133
|
+
session = Camping::Models::Session.persist @cookies
|
134
|
+
app = self.class.name.gsub(/^(\w+)::.+$/, '\1')
|
135
|
+
@state = (session[app] ||= Camping::H[])
|
136
|
+
hash_before = Marshal.dump(@state).hash
|
137
|
+
s = super(*a)
|
138
|
+
if session
|
139
|
+
hash_after = Marshal.dump(@state).hash
|
140
|
+
unless hash_before == hash_after
|
141
|
+
session[app] = @state
|
142
|
+
session.save
|
143
|
+
end
|
144
|
+
end
|
145
|
+
s
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.included(mod)
|
150
|
+
mod.module_eval do
|
151
|
+
include Cas::Session
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def service(*a)
|
156
|
+
$LOG.debug "Running CAS filter for request #{a.inspect}..."
|
157
|
+
|
158
|
+
if @env['PATH_INFO'] =~ /^\/public\/.*/
|
159
|
+
$LOG.debug "Access to items in /public subdirectory does not require CAS authentication."
|
160
|
+
return super(*a)
|
161
|
+
end
|
162
|
+
if @state[:cas_username]
|
163
|
+
$LOG.debug "Local CAS session exists for user #{@state[:cas_username]}."
|
164
|
+
return super(*a)
|
165
|
+
end
|
166
|
+
|
167
|
+
client = CASClient::Client.new($CONF[:authentication].merge(:logger => $LOG))
|
168
|
+
|
169
|
+
ticket = @input[:ticket]
|
170
|
+
|
171
|
+
cas_login_url = client.add_service_to_login_url(read_service_url(@env))
|
172
|
+
|
173
|
+
if ticket
|
174
|
+
if ticket =~ /^PT-/
|
175
|
+
st = CASClient::ProxyTicket.new(ticket, read_service_url(@env), @input[:renew])
|
176
|
+
else
|
177
|
+
st = CASClient::ServiceTicket.new(ticket, read_service_url(@env), @input[:renew])
|
178
|
+
end
|
179
|
+
|
180
|
+
$LOG.debug "Got CAS ticket: #{st.inspect}"
|
181
|
+
|
182
|
+
client.validate_service_ticket(st)
|
183
|
+
if st.is_valid?
|
184
|
+
$LOG.info "CAS ticket #{st.ticket.inspect} is valid. Opening local CAS session for user #{st.response.user.inspect}."
|
185
|
+
@state[:cas_username] = st.response.user
|
186
|
+
return super(*a)
|
187
|
+
else
|
188
|
+
$LOG.warn "CAS ticket #{st.ticket.inspect} is INVALID. Redirecting back to CAS server at #{cas_login_url.inspect} for authentication."
|
189
|
+
@state[:cas_username] = nil
|
190
|
+
redirect cas_login_url
|
191
|
+
s = self
|
192
|
+
end
|
193
|
+
else
|
194
|
+
$LOG.info "User is unauthenticated and no CAS ticket found. Redirecting to CAS server at #{cas_login_url.inspect} for authentication."
|
195
|
+
@state[:cas_username] = nil
|
196
|
+
redirect cas_login_url
|
197
|
+
s = self
|
198
|
+
end
|
199
|
+
s
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
def read_service_url(env)
|
204
|
+
if $CONF[:authentication][:service_url]
|
205
|
+
$CONF[:authentication][:service_url]
|
206
|
+
else
|
207
|
+
env['REQUEST_URI'].gsub(/service=[^&]*[&]?/,'').gsub(/ticket=[^&]*[&]?/,'')
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
79
211
|
end
|
80
212
|
end
|
data/lib/picnic/controllers.rb
CHANGED
@@ -1,31 +1,4 @@
|
|
1
1
|
module Picnic
|
2
2
|
module Controllers
|
3
|
-
# Provides a controller for serving up static content from your app's <tt>/public</tt> directory.
|
4
|
-
# This can be used to serve css, js, jpg, png, and gif files. Anything you put in your app's
|
5
|
-
# '/public' directory will be served up under the '/public' path.
|
6
|
-
#
|
7
|
-
# That is, say you have:
|
8
|
-
# /srv/www/camping/my_app/public/test.jpg
|
9
|
-
# This should be availabe at:
|
10
|
-
# http://myapp.com/public/test.jpg
|
11
|
-
#
|
12
|
-
# This controller is automatically enabled for all Picnic-enabled apps.
|
13
|
-
class Public < Camping::Controllers::R '/public/(.+)'
|
14
|
-
BASE_PATH = ("#{$APP_PATH}/.." || File.expand_path(File.dirname(__FILE__)))+'/lib/public'
|
15
|
-
|
16
|
-
MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript',
|
17
|
-
'.jpg' => 'image/jpeg', '.png' => 'image/png',
|
18
|
-
'.gif' => 'image/gif'}
|
19
|
-
|
20
|
-
def get(path)
|
21
|
-
@headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
|
22
|
-
unless path.include? ".." # prevent directory traversal attacks
|
23
|
-
@headers['X-Sendfile'] = "#{BASE_PATH}/#{path}"
|
24
|
-
else
|
25
|
-
@status = "403"
|
26
|
-
"403 - Invalid path"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
3
|
end
|
31
4
|
end
|
data/lib/picnic/postambles.rb
CHANGED
@@ -39,7 +39,7 @@ module Picnic
|
|
39
39
|
|
40
40
|
begin
|
41
41
|
s = WEBrick::HTTPServer.new(
|
42
|
-
:BindAddress => "0.0.0.0",
|
42
|
+
:BindAddress => Picnic::Conf.bind_address || "0.0.0.0",
|
43
43
|
:Port => Picnic::Conf.port
|
44
44
|
)
|
45
45
|
rescue Errno::EACCES
|
@@ -49,6 +49,14 @@ module Picnic
|
|
49
49
|
|
50
50
|
self.create
|
51
51
|
s.mount "#{Picnic::Conf.uri_path}", WEBrick::CampingHandler, self
|
52
|
+
|
53
|
+
public_dirs = Picnic::Conf.public_dirs || Picnic::Conf.public_dir
|
54
|
+
public_dirs = [public_dirs] unless public_dirs.kind_of? Array
|
55
|
+
|
56
|
+
public_dirs.each do |d|
|
57
|
+
s.mount "#{Picnic::Conf.uri_path}#{d[:path]}", WEBrick::HTTPServlet::FileHandler, d[:dir]
|
58
|
+
end
|
59
|
+
|
52
60
|
|
53
61
|
# This lets Ctrl+C shut down your server
|
54
62
|
trap(:INT) do
|
@@ -124,18 +132,28 @@ module Picnic
|
|
124
132
|
|
125
133
|
puts "\n** #{self} is starting. Look in #{Picnic::Conf.log[:file].inspect} for further notices."
|
126
134
|
|
127
|
-
settings = {
|
135
|
+
settings = {
|
136
|
+
:host => Picnic::Conf.bind_address || "0.0.0.0",
|
137
|
+
:log_file => Picnic::Conf.log[:file],
|
138
|
+
:cwd => $APP_PATH
|
139
|
+
}
|
128
140
|
|
129
141
|
# need to close all IOs before daemonizing
|
130
142
|
$LOG.close if $DAEMONIZE
|
131
143
|
|
144
|
+
public_dirs = Picnic::Conf.public_dirs || Picnic::Conf.public_dir
|
145
|
+
public_dirs = [public_dirs] unless public_dirs.kind_of? Array
|
146
|
+
|
132
147
|
begin
|
133
148
|
app_mod = self
|
134
|
-
|
149
|
+
mongrel = Mongrel::Configurator.new settings do
|
135
150
|
daemonize :log_file => Picnic::Conf.log[:file], :cwd => $APP_PATH if $DAEMONIZE
|
136
|
-
|
151
|
+
puts Picnic::Conf.uri_path
|
137
152
|
listener :port => Picnic::Conf.port do
|
138
153
|
uri Picnic::Conf.uri_path, :handler => Mongrel::Camping::CampingHandler.new(app_mod)
|
154
|
+
public_dirs.each do |d|
|
155
|
+
uri "#{Picnic::Conf.uri_path}#{d[:path]}", :handler => Mongrel::DirHandler.new(d[:dir])
|
156
|
+
end
|
139
157
|
setup_signals
|
140
158
|
end
|
141
159
|
end
|
@@ -143,8 +161,7 @@ module Picnic
|
|
143
161
|
exit 1
|
144
162
|
end
|
145
163
|
|
146
|
-
|
147
|
-
config.run
|
164
|
+
mongrel.run
|
148
165
|
|
149
166
|
self.init_logger
|
150
167
|
#self.init_db_logger
|
@@ -159,8 +176,9 @@ module Picnic
|
|
159
176
|
|
160
177
|
puts "\n** #{self} is running at http://#{ENV['HOSTNAME'] || 'localhost'}:#{Picnic::Conf.port}#{Picnic::Conf.uri_path} and logging to '#{Picnic::Conf.log[:file]}'"
|
161
178
|
|
179
|
+
|
162
180
|
self.prestart if self.respond_to? :prestart
|
163
|
-
|
181
|
+
mongrel.join
|
164
182
|
|
165
183
|
clear_pid_file
|
166
184
|
|
data/lib/picnic/version.rb
CHANGED
data/lib/picnic.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
$: << File.dirname(File.expand_path(__FILE__))
|
2
2
|
$: << File.dirname(File.expand_path(__FILE__))+"/../vendor/camping-1.5.180/lib"
|
3
3
|
|
4
|
-
require 'camping'
|
5
|
-
require 'camping/db'
|
6
|
-
require 'camping/session'
|
7
4
|
|
8
|
-
|
5
|
+
unless Object.const_defined?(:ActiveSupport)
|
6
|
+
begin
|
7
|
+
require 'active_support'
|
8
|
+
rescue LoadError
|
9
|
+
require 'rubygems'
|
10
|
+
require 'active_support'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'camping'
|
9
15
|
|
10
16
|
require 'picnic/utils'
|
11
17
|
require 'picnic/conf'
|
12
18
|
require 'picnic/postambles'
|
13
|
-
require 'picnic/controllers'
|
14
19
|
|
15
20
|
|
16
21
|
class Module
|
@@ -34,8 +39,8 @@ class Module
|
|
34
39
|
# See <tt>config.example.yml</tt> for info on configuring the logger.
|
35
40
|
def init_logger
|
36
41
|
puts "Initializing #{self} logger..."
|
37
|
-
$LOG =
|
38
|
-
$LOG.level = "
|
42
|
+
$LOG = Picnic::Utils::Logger.new(self::Conf.log[:file])
|
43
|
+
$LOG.level = "Picnic::Utils::Logger::#{self::Conf.log[:level]}".constantize
|
39
44
|
end
|
40
45
|
module_function :init_logger
|
41
46
|
|
@@ -62,14 +67,18 @@ class Module
|
|
62
67
|
# Blog.picnic!
|
63
68
|
#
|
64
69
|
# $CONF[:authentication] ||= {:username => 'admin', :password => 'picnic'}
|
65
|
-
# Blog.authenticate_using :basic
|
70
|
+
# Blog.authenticate_using :basic
|
71
|
+
#
|
72
|
+
# module Blog
|
73
|
+
# def self.authenticate(credentials)
|
74
|
+
# credentials[:username] == Taskr::Conf[:authentication][:username] &&
|
75
|
+
# credentials[:password] == Taskr::Conf[:authentication][:password]
|
76
|
+
# end
|
77
|
+
# end
|
66
78
|
#
|
67
79
|
# Note that in the above example we use the authentication configuration from
|
68
|
-
# your app's conf file.
|
69
|
-
# conf file doesn't define them.
|
80
|
+
# your app's conf file.
|
70
81
|
#
|
71
|
-
# Currently only HTTP Basic authentication is available. See Picnic::Authentication
|
72
|
-
# for more info.
|
73
82
|
def authenticate_using(mod)
|
74
83
|
require 'picnic/authentication'
|
75
84
|
mod = "#{self}::Authentication::#{mod.to_s.camelize}".constantize unless mod.kind_of? Module
|
@@ -119,4 +128,4 @@ class Module
|
|
119
128
|
self::Conf.load(self)
|
120
129
|
init_logger
|
121
130
|
end
|
122
|
-
end
|
131
|
+
end
|
metadata
CHANGED
@@ -1,33 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.2
|
3
|
-
specification_version: 1
|
4
2
|
name: picnic
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-12-21 00:00:00 -05:00
|
8
|
-
summary: Camping for sissies
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: matt@roughest.net
|
12
|
-
homepage: http://picnic.rubyforge.org
|
13
|
-
rubyforge_project: picnic
|
14
|
-
description: Camping for sissies
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.6.0
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Matt Zukowski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-26 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: markaby
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: Camping for sissies
|
25
|
+
email: matt@roughest.net
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- CHANGELOG.txt
|
32
|
+
- LICENSE.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
31
35
|
files:
|
32
36
|
- CHANGELOG.txt
|
33
37
|
- LICENSE.txt
|
@@ -57,21 +61,32 @@ files:
|
|
57
61
|
- vendor/camping-1.5.180/lib/camping/reloader.rb
|
58
62
|
- vendor/camping-1.5.180/lib/camping/session.rb
|
59
63
|
- vendor/camping-1.5.180/lib/camping/webrick.rb
|
60
|
-
|
61
|
-
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://picnic.rubyforge.org
|
66
|
+
post_install_message:
|
62
67
|
rdoc_options:
|
63
68
|
- --main
|
64
69
|
- README.txt
|
65
|
-
|
66
|
-
-
|
67
|
-
|
68
|
-
|
69
|
-
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
74
84
|
requirements: []
|
75
85
|
|
76
|
-
|
77
|
-
|
86
|
+
rubyforge_project: picnic
|
87
|
+
rubygems_version: 1.0.1
|
88
|
+
signing_key:
|
89
|
+
specification_version: 2
|
90
|
+
summary: Camping for sissies
|
91
|
+
test_files:
|
92
|
+
- test/picnic_test.rb
|