summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwew <wew@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-29 03:52:24 +0000
committerwew <wew@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-29 03:52:24 +0000
commit91f89ed074a0c57b011bf06047e9342cec12270d (patch)
tree6605cba04fac7043d2764b1ab917a1c3dab0fa02
parentde7c82654223f923cdb5c157fb3126e724a8fb32 (diff)
downloadruby-91f89ed074a0c57b011bf06047e9342cec12270d.tar.gz
ruby-91f89ed074a0c57b011bf06047e9342cec12270d.tar.xz
ruby-91f89ed074a0c57b011bf06047e9342cec12270d.zip
Add documentation in RDoc format.
git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@4455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--lib/cgi/session.rb282
1 files changed, 278 insertions, 4 deletions
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index 0ce82b392..4ad6bf2a6 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -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