4e14ccc74d
Instiki now runs on the Rails 2.3.0 Candidate Release. Among other improvements, this means that it now automagically selects between WEBrick and Mongrel. Just run ./instiki --daemon
90 lines
2.7 KiB
Ruby
90 lines
2.7 KiB
Ruby
require 'openssl'
|
|
|
|
module Rack
|
|
|
|
module Session
|
|
|
|
# Rack::Session::Cookie provides simple cookie based session management.
|
|
# The session is a Ruby Hash stored as base64 encoded marshalled data
|
|
# set to :key (default: rack.session).
|
|
# When the secret key is set, cookie data is checked for data integrity.
|
|
#
|
|
# Example:
|
|
#
|
|
# use Rack::Session::Cookie, :key => 'rack.session',
|
|
# :domain => 'foo.com',
|
|
# :path => '/',
|
|
# :expire_after => 2592000,
|
|
# :secret => 'change_me'
|
|
#
|
|
# All parameters are optional.
|
|
|
|
class Cookie
|
|
|
|
def initialize(app, options={})
|
|
@app = app
|
|
@key = options[:key] || "rack.session"
|
|
@secret = options[:secret]
|
|
@default_options = {:domain => nil,
|
|
:path => "/",
|
|
:expire_after => nil}.merge(options)
|
|
end
|
|
|
|
def call(env)
|
|
load_session(env)
|
|
status, headers, body = @app.call(env)
|
|
commit_session(env, status, headers, body)
|
|
end
|
|
|
|
private
|
|
|
|
def load_session(env)
|
|
request = Rack::Request.new(env)
|
|
session_data = request.cookies[@key]
|
|
|
|
if @secret && session_data
|
|
session_data, digest = session_data.split("--")
|
|
session_data = nil unless digest == generate_hmac(session_data)
|
|
end
|
|
|
|
begin
|
|
session_data = session_data.unpack("m*").first
|
|
session_data = Marshal.load(session_data)
|
|
env["rack.session"] = session_data
|
|
rescue
|
|
env["rack.session"] = Hash.new
|
|
end
|
|
|
|
env["rack.session.options"] = @default_options.dup
|
|
end
|
|
|
|
def commit_session(env, status, headers, body)
|
|
session_data = Marshal.dump(env["rack.session"])
|
|
session_data = [session_data].pack("m*")
|
|
|
|
if @secret
|
|
session_data = "#{session_data}--#{generate_hmac(session_data)}"
|
|
end
|
|
|
|
if session_data.size > (4096 - @key.size)
|
|
env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.")
|
|
[status, headers, body]
|
|
else
|
|
options = env["rack.session.options"]
|
|
cookie = Hash.new
|
|
cookie[:value] = session_data
|
|
cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil?
|
|
response = Rack::Response.new(body, status, headers)
|
|
response.set_cookie(@key, cookie.merge(options))
|
|
response.to_a
|
|
end
|
|
end
|
|
|
|
def generate_hmac(data)
|
|
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, @secret, data)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|