mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add documentation in RDoc format.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
11f521b98e
commit
22a5aec4b3
1 changed files with 278 additions and 4 deletions
|
@ -1,21 +1,175 @@
|
|||
#
|
||||
# cgi/session.rb - session support for cgi scripts
|
||||
#
|
||||
# Copyright (C) 2001 Yukihiro "Matz" Matsumoto
|
||||
# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
||||
# Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
||||
#
|
||||
# Author: Yukihiro "Matz" Matsumoto
|
||||
#
|
||||
# Documentation: William Webber (william@williamwebber.com)
|
||||
#
|
||||
# == Overview
|
||||
#
|
||||
# This file provides the +CGI::Session+ class, which provides session
|
||||
# support for CGI scripts. A session is a sequence of HTTP requests
|
||||
# and responses linked together and associated with a single client.
|
||||
# Information associated with the session is stored
|
||||
# on the server between requests. A session id is passed between client
|
||||
# and server with every request and response, transparently
|
||||
# to the user. This adds state information to the otherwise stateless
|
||||
# HTTP request/response protocol.
|
||||
#
|
||||
# See the documentation to the +CGI::Session+ class for more details
|
||||
# and examples of usage. See cgi.rb for the +CGI+ class itself.
|
||||
|
||||
require 'cgi'
|
||||
require 'tmpdir'
|
||||
|
||||
class CGI
|
||||
|
||||
# Class representing an HTTP session. See documentation for the file
|
||||
# cgi/session.rb for an introduction to HTTP sessions.
|
||||
#
|
||||
# == Lifecycle
|
||||
#
|
||||
# A CGI::Session instance is created from a CGI object. By default,
|
||||
# this CGI::Session instance will start a new session if none currently
|
||||
# exists, or continue the current session for this client if one does
|
||||
# exist. The +new_session+ option can be used to either always or
|
||||
# never create a new session. See #new() for more details.
|
||||
#
|
||||
# #delete() deletes a session from session storage. It
|
||||
# does not however remove the session id from the client. If the client
|
||||
# makes another request with the same id, the effect will be to start
|
||||
# a new session with the old session's id.
|
||||
#
|
||||
# == Setting and retrieving session data.
|
||||
#
|
||||
# The Session class associates data with a session as key-value pairs.
|
||||
# This data can be set and retrieved by indexing the Session instance
|
||||
# using '[]', much the same as hashes (although other hash methods
|
||||
# are not supported).
|
||||
#
|
||||
# When session processing has been completed for a request, the
|
||||
# session should be closed using the close() method. This will
|
||||
# store the session's state to persistent storage. If you want
|
||||
# to store the session's state to persistent storage without
|
||||
# finishing session processing for this request, call the update()
|
||||
# method.
|
||||
#
|
||||
# == Storing session state
|
||||
#
|
||||
# The caller can specify what form of storage to use for the session's
|
||||
# data with the +database_manager+ option to CGI::Session::new. The
|
||||
# following storage classes are provided as part of the standard library:
|
||||
#
|
||||
# CGI::Session::FileStore:: stores data as plain text in a flat file. Only
|
||||
# works with String data. This is the default
|
||||
# storage type.
|
||||
# CGI::Session::MemoryStore:: stores data in an in-memory hash. The data
|
||||
# only persists for as long as the current ruby
|
||||
# interpreter instance does.
|
||||
# CGI::Session::PStore:: stores data in Marshalled format. Provided by
|
||||
# cgi/session/pstore.rb. Supports data of any type,
|
||||
# and provides file-locking and transaction support.
|
||||
#
|
||||
# Custom storage types can also be created by defining a class with
|
||||
# the following methods:
|
||||
#
|
||||
# new(session, options)
|
||||
# restore # returns hash of session data.
|
||||
# update
|
||||
# close
|
||||
# delete
|
||||
#
|
||||
# Changing storage type mid-session does not work. Note in particular
|
||||
# that by default the FileStore and PStore session data files have the
|
||||
# same name. If your application switches from one to the other without
|
||||
# making sure that filenames will be different
|
||||
# and clients still have old sessions lying around in cookies, then
|
||||
# things will break nastily!
|
||||
#
|
||||
# == Maintaining the session id.
|
||||
#
|
||||
# Most session state is maintained on the server. However, a session
|
||||
# id must be passed backwards and forwards between client and server
|
||||
# to maintain a reference to this session state.
|
||||
#
|
||||
# The simplest way to do this is via cookies. The CGI::Session class
|
||||
# provides transparent support for session id communication via cookies
|
||||
# if the client has cookies enabled.
|
||||
#
|
||||
# If the client has cookies disabled, the session id must be included
|
||||
# as a parameter of all requests sent by the client to the server. The
|
||||
# CGI::Session class in conjunction with the CGI class will transparently
|
||||
# add the session id as a hidden input field to all forms generated
|
||||
# using the CGI#form() HTML generation method. No built-in support is
|
||||
# provided for other mechanisms, such as URL re-writing. The caller is
|
||||
# responsible for extracting the session id from the session_id
|
||||
# attribute and manually encoding it in URLs and adding it as a hidden
|
||||
# input to HTML forms created by other mechanisms. Also, session expiry
|
||||
# is not automatically handled.
|
||||
#
|
||||
# == Examples of use
|
||||
#
|
||||
# === Setting the user's name
|
||||
#
|
||||
# require 'cgi'
|
||||
# require 'cgi/session'
|
||||
# require 'cgi/session/pstore' # provides CGI::Session::PStore
|
||||
#
|
||||
# cgi = CGI.new("html4")
|
||||
#
|
||||
# session = CGI::Session.new(cgi,
|
||||
# 'database_manager' => CGI::Session::PStore, # use PStore
|
||||
# 'session_key' => '_rb_sess_id', # custom session key
|
||||
# 'session_expires' => Time.now + 30 * 60, # 30 minute timeout
|
||||
# 'prefix' => 'pstore_sid_') # PStore option
|
||||
# if cgi.has_key?('user_name') and cgi['user_name'] != ''
|
||||
# # coerce to String: cgi[] returns the
|
||||
# # string-like CGI::QueryExtension::Value
|
||||
# session['user_name'] = cgi['user_name'].to_s
|
||||
# elsif !session['user_name']
|
||||
# session['user_name'] = "guest"
|
||||
# end
|
||||
# session.close
|
||||
#
|
||||
# === Creating a new session safely
|
||||
#
|
||||
# require 'cgi'
|
||||
# require 'cgi/session'
|
||||
#
|
||||
# cgi = CGI.new("html4")
|
||||
#
|
||||
# # We make sure to delete an old session if one exists,
|
||||
# # not just to free resources, but to prevent the session
|
||||
# # from being maliciously hijacked later on.
|
||||
# begin
|
||||
# session = CGI::Session.new(cgi, 'new_session' => false)
|
||||
# session.delete
|
||||
# rescue ArgumentError # if no old session
|
||||
# end
|
||||
# session = CGI::Session.new(cgi, 'new_session' => true)
|
||||
# session.close
|
||||
#
|
||||
class Session
|
||||
|
||||
# The id of this session.
|
||||
attr_reader :session_id
|
||||
|
||||
def Session::callback(dbman)
|
||||
def Session::callback(dbman) #:nodoc:
|
||||
lambda{
|
||||
dbman[0].close unless dbman.empty?
|
||||
}
|
||||
end
|
||||
|
||||
# Create a new session id.
|
||||
#
|
||||
# The session id is an MD5 hash based upon the time,
|
||||
# a random number, and a constant string. This routine
|
||||
# is used internally for automatically generated
|
||||
# session ids.
|
||||
def Session::create_new_id
|
||||
require 'digest/md5'
|
||||
md5 = Digest::MD5::new
|
||||
|
@ -26,6 +180,62 @@ class CGI
|
|||
md5.hexdigest[0,16]
|
||||
end
|
||||
|
||||
# Create a new CGI::Session object for +request+.
|
||||
#
|
||||
# +request+ is an instance of the +CGI+ class (see cgi.rb).
|
||||
# +option+ is a hash of options for initialising this
|
||||
# CGI::Session instance. The following options are
|
||||
# recognised:
|
||||
#
|
||||
# session_key:: the parameter name used for the session id.
|
||||
# Defaults to '_session_id'.
|
||||
# session_id:: the session id to use. If not provided, then
|
||||
# it is retrieved from the +session_key+ parameter
|
||||
# of the request, or automatically generated for
|
||||
# a new session.
|
||||
# new_session:: if true, force creation of a new session. If not set,
|
||||
# a new session is only created if none currently
|
||||
# exists. If false, a new session is never created,
|
||||
# and if none currently exists and the +session_id+
|
||||
# option is not set, an ArgumentError is raised.
|
||||
# database_manager:: the name of the class providing storage facilities
|
||||
# for session state persistence. Built-in support
|
||||
# is provided for +FileStore+ (the default),
|
||||
# +MemoryStore+, and +PStore+ (from
|
||||
# cgi/session/pstore.rb). See the documentation for
|
||||
# these classes for more details.
|
||||
#
|
||||
# The following options are also recognised, but only apply if the
|
||||
# session id is stored in a cookie.
|
||||
#
|
||||
# session_expires:: the time the current session expires, as a
|
||||
# +Time+ object. If not set, the session will continue
|
||||
# indefinitely.
|
||||
# session_domain:: the hostname domain for which this session is valid.
|
||||
# If not set, defaults to the hostname of the server.
|
||||
# session_secure:: if +true+, this session will only work over HTTPS.
|
||||
# session_path:: the path for which this session applies. Defaults
|
||||
# to the directory of the CGI script.
|
||||
#
|
||||
# +option+ is also passed on to the session storage class initialiser; see
|
||||
# the documentation for each session storage class for the options
|
||||
# they support.
|
||||
#
|
||||
# The retrieved or created session is automatically added to +request+
|
||||
# as a cookie, and also to its +output_hidden+ table, which is used
|
||||
# to add hidden input elements to forms.
|
||||
#
|
||||
# *WARNING* the +output_hidden+
|
||||
# fields are surrounded by a <fieldset> tag in HTML 4 generation, which
|
||||
# is _not_ invisible on many browsers; you may wish to disable the
|
||||
# use of fieldsets with code similar to the following
|
||||
# (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805)
|
||||
#
|
||||
# cgi = CGI.new("html4")
|
||||
# class << cgi
|
||||
# undef_method :fieldset
|
||||
# end
|
||||
#
|
||||
def initialize(request, option={})
|
||||
session_key = option['session_key'] || '_session_id'
|
||||
id = option['session_id']
|
||||
|
@ -73,6 +283,7 @@ class CGI
|
|||
ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
|
||||
end
|
||||
|
||||
# Retrieve the session data for key +key+.
|
||||
def [](key)
|
||||
unless @data
|
||||
@data = @dbman.restore
|
||||
|
@ -80,6 +291,7 @@ class CGI
|
|||
@data[key]
|
||||
end
|
||||
|
||||
# Set the session date for key +key+.
|
||||
def []=(key, val)
|
||||
unless @write_lock
|
||||
@write_lock = true
|
||||
|
@ -90,25 +302,61 @@ class CGI
|
|||
@data[key] = val
|
||||
end
|
||||
|
||||
def update
|
||||
# Store session data on the server. For some session storage types,
|
||||
# this is a no-op.
|
||||
def update
|
||||
@dbman.update
|
||||
end
|
||||
|
||||
# Store session data on the server and close the session storage.
|
||||
# For some session storage types, this is a no-op.
|
||||
def close
|
||||
@dbman.close
|
||||
@dbprot.clear
|
||||
end
|
||||
|
||||
# Delete the session from storage. Also closes the storage.
|
||||
#
|
||||
# Note that the session's data is _not_ automatically deleted
|
||||
# upon the session expiring.
|
||||
def delete
|
||||
@dbman.delete
|
||||
@dbprot.clear
|
||||
end
|
||||
|
||||
# File-based session storage class.
|
||||
#
|
||||
# Implements session storage as a flat file of 'key=value' values.
|
||||
# This storage type only works directly with String values; the
|
||||
# user is responsible for converting other types to Strings when
|
||||
# storing and from Strings when retrieving.
|
||||
class FileStore
|
||||
def check_id(id)
|
||||
def check_id(id) #:nodoc:
|
||||
/[^0-9a-zA-Z]/ =~ id.to_s ? false : true
|
||||
end
|
||||
|
||||
# Create a new FileStore instance.
|
||||
#
|
||||
# This constructor is used internally by CGI::Session. The
|
||||
# user does not generally need to call it directly.
|
||||
#
|
||||
# +session+ is the session for which this instance is being
|
||||
# created. The session id must only contain alphanumeric
|
||||
# characters; automatically generated session ids observe
|
||||
# this requirement.
|
||||
#
|
||||
# +option+ is a hash of options for the initialiser. The
|
||||
# following options are recognised:
|
||||
#
|
||||
# tmpdir:: the directory to use for storing the FileStore
|
||||
# file. Defaults to Dir::tmpdir (generally "/tmp"
|
||||
# on Unix systems).
|
||||
# prefix:: the prefix to add to the session id when generating
|
||||
# the filename for this session's FileStore file.
|
||||
# Defaults to the empty string.
|
||||
#
|
||||
# This session's FileStore file will be created if it does
|
||||
# not exist, or opened if it does.
|
||||
def initialize(session, option={})
|
||||
dir = option['tmpdir'] || Dir::tmpdir
|
||||
prefix = option['prefix'] || ''
|
||||
|
@ -128,6 +376,9 @@ class CGI
|
|||
end
|
||||
end
|
||||
|
||||
# Restore session state from the session's FileStore file.
|
||||
#
|
||||
# Returns the session state as a hash.
|
||||
def restore
|
||||
unless @hash
|
||||
@hash = {}
|
||||
|
@ -142,6 +393,7 @@ class CGI
|
|||
@hash
|
||||
end
|
||||
|
||||
# Save session state to the session's FileStore file.
|
||||
def update
|
||||
return unless @hash
|
||||
@f.rewind
|
||||
|
@ -151,12 +403,14 @@ class CGI
|
|||
@f.truncate @f.tell
|
||||
end
|
||||
|
||||
# Update and close the session's FileStore file.
|
||||
def close
|
||||
return if @f.closed?
|
||||
update
|
||||
@f.close
|
||||
end
|
||||
|
||||
# Close and delete the session's FileStore file.
|
||||
def delete
|
||||
path = @f.path
|
||||
@f.close
|
||||
|
@ -164,26 +418,46 @@ class CGI
|
|||
end
|
||||
end
|
||||
|
||||
# In-memory session storage class.
|
||||
#
|
||||
# Implements session storage as a global in-memory hash. Session
|
||||
# data will only persist for as long as the ruby interpreter
|
||||
# instance does.
|
||||
class MemoryStore
|
||||
GLOBAL_HASH_TABLE = {}
|
||||
GLOBAL_HASH_TABLE = {} #:nodoc:
|
||||
|
||||
# Create a new MemoryStore instance.
|
||||
#
|
||||
# +session+ is the session this instance is associated with.
|
||||
# +option+ is a list of initialisation options. None are
|
||||
# currently recognised.
|
||||
def initialize(session, option=nil)
|
||||
@session_id = session.session_id
|
||||
GLOBAL_HASH_TABLE[@session_id] ||= {}
|
||||
end
|
||||
|
||||
# Restore session state.
|
||||
#
|
||||
# Returns session data as a hash.
|
||||
def restore
|
||||
GLOBAL_HASH_TABLE[@session_id]
|
||||
end
|
||||
|
||||
# Update session state.
|
||||
#
|
||||
# A no-op.
|
||||
def update
|
||||
# don't need to update; hash is shared
|
||||
end
|
||||
|
||||
# Close session storage.
|
||||
#
|
||||
# A no-op.
|
||||
def close
|
||||
# don't need to close
|
||||
end
|
||||
|
||||
# Delete the session state.
|
||||
def delete
|
||||
GLOBAL_HASH_TABLE.delete(@session_id)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue