picnic 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|