  <section id="session_package">
    <title>Session Package</title>
    <section>
      <title>Introduction</title>
      <para>
	This is session management code.  It provides an interface
	to allow you to generate and track a browser's visit as a
	"session", giving you a unique session ID and an interface
	for storing and retrieving data for that session on the
	server.
      </para>

      <para>
	This is an alpha/beta release -- documentation is not in
	final form, but everything you need should be in this file.
      </para>

      <para>
	Using sessions and their included ability to store and
	retrieve session-related data on the server, programmers can
	generate more secure and higher-performance websites.  For
	example, hidden fields do not have to be included in forms
	(and the risk of them being manipulated by the user
	mitigated) since data that would be stored in hidden fields
	can now be stored in the session cache on the server.  Forms
	are then faster since no hidden data is transmitted --
	hidden fields must be sent twice, once in the form to the
	broswer and once in the response from it.
      </para>

      <para>
	Robust login systems, etc, can be built on top of this code.
      </para>
    </section>

    <section id="requirements">
      <title>Requirements</title>
	<para>
	  Currently has only been tested with Postgresql, MySql and Oracle.
	  All DB interfacing is done through DIO, though, so it
	  should be relatively easy to add support for other
	  databases.
	</para>
      </section>

      <section>
	<title>Preparing To Use It</title>

	<para>Create the tables in your SQL server.  With Postgres,
	  do a <command>psql www</command> or whatever DB you
	  connect as, then a backslash-i on
	  <filename>session-create.sql</filename></para>

	<para>(If you need to delete the tables, use <filename>session-drop.sql</filename>)</para>

	<para>The session code by default requires a DIO handle
	  called <varname>DIO</varname> (the name of which can be
	  overridden).  We get it by doing a</para>

	    <programlisting>RivetServerConf ChildInitScript "package require DIO"
RivetServerConf ChildInitScript "::DIO::handle Postgresql DIO -user www"</programlisting>

      </section>

      <section>
	<title>Example Usage</title>

	<para>In your httpd.conf, add:</para>

	<programlisting>RivetServerConf ChildInitScript "package require Session; Session SESSION"</programlisting>

	<para>
	  This tells Rivet you want to create a session object named
	  SESSION in every child process Apache creates.</para>

	<para>
	  You can configure the session at this point using numerous
	  key-value pairs (which are defined later in this doc).
	  Here's a quick example:</para>

	<programlisting>RivetServerConf ChildInitScript "package require Session; Session SESSION \
  -cookieLifetime 120 -debugMode 1"</programlisting>

	<para>
	  Turn debugging on <option>-debugMode 1</option> to figure
	  out what's going on -- it's really useful, if
	  verbose.</para>

	<para>
	  In your .rvt file, when you're generating the &lt;HEAD&gt;
	  section:
	</para>

	<programlisting>SESSION activate</programlisting>

	<para>
	  Activate handles everything for you with respect to
	  creating new sessions, and for locating, validating, and
	  updating existing sessions.  Activate will either locate
	  an existing session, or create a new one.  Sessions will
	  automatically be refreshed (their lifetimes extended) as
	  additional requests are received during the session, all
	  under the control of the key-value pairs controlling the
	  session object.
	</para>
      </section>

      <section>
	<title>Using Sessions From Your Code</title>

	<para>The main methods your code will use are:</para>

	<variablelist>
	  <varlistentry>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION</command> <command>id</command>
	      </cmdsynopsis>
	      <para>
		After doing a <command>SESSION activate</command>,
		this will return a 32-byte ASCII-encoded random
		hexadecimal string.  Every time this browser comes
		to us with a request within the timeout period, this
		same string will be returned (assuming they have
		cookies enabled).
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION</command>
		<command>is_new_session</command>
	      </cmdsynopsis>
	      <para>returns 1 if it's a new session or 0 if it has
		previously existed (i.e. it's a zero if this request
		represents a "return" or subsequent visit to a
		current session.)</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION new_session_reason</command></cmdsynopsis>
	      <para>
		This will return why this request is the first
		request of a new session, either "no_cookie" saying
		the browser didn't give us a session cookie,
		"no_session" indicating we got a cookie but couldn't
		find it in our session table, or "timeout" where
		they had a cookie and we found the matching session
		but the session has timed out.
	      </para>
	    </listitem>
	  </varlistentry>
	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION store</command>
		<arg><replaceable>packageName</replaceable></arg>
		<arg><replaceable>key</replaceable></arg>
		<arg><replaceable>data</replaceable></arg>
	      </cmdsynopsis>
	      <para>
		Given the name of a package, a key, and some data.
		Stores the data in the rivet session cache table.
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION fetch</command>
		<arg><replaceable>packageName</replaceable></arg>
		<arg><replaceable>key</replaceable></arg>
	      </cmdsynopsis>
	      <para>
		Given a package name and a key, return the data
		stored by the store method, or an empty string if
		none was set.  (Status is set to the DIO error that
		occurred, it can be fetched using the status
		method.)
	      </para>
	    </listitem>
	  </varlistentry>
	</variablelist>
      </section>

      <section>
	<title>Session Configuration Options</title>

	<para>The following key-value pairs can be specified when a
	  session object (like SESSION above) is created:</para>

	<variablelist>

	  <varlistentry>
	    <term><option>sessionLifetime</option></term>

	    <listitem>
	      <para>how many seconds the session will live for.
		7200 == 2 hours
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term>sessionRefreshInterval</term>
	    <listitem>
	      <para>
		If a request is processed for a browser that
		currently has a session and this long has elapsed
		since the session update time was last updated,
		update it.  900 == 15 minutes.  so if at least 15
		minutes has elapsed and we've gotten a new request
		for a page, update the session update time,
		extending the session lifetime (sessions that are in
		use keep getting extended).
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term>cookieName</term>
	    <listitem>
	      <para></para>
	      name of the cookie stored on the user's web browser
	      default rivetSession
	    </listitem>
	  </varlistentry>

	  <varlistentry><term>dioObject</term> 
	    <listitem>
	      <para>
		The name of the DIO object we'll use to access the
		database (default DIO)
	      </para>
	    </listitem></varlistentry>

	  <varlistentry><term>gcProbability</term>
	    <listitem>
	      <para>
		The probability that garbage collection will occur
		in percent.  (default 1%, i.e. 1)</para></listitem></varlistentry>

	  <varlistentry><term>gcMaxLifetime</term>
		<listitem><para>the number of seconds after which
		data will be seen as "garbage" and cleaned up --
		defaults to 1 day (86400)</para></listitem></varlistentry>

	  <varlistentry><term>refererCheck</term>
		<listitem><para>The substring you want to check each
		HTTP referer for.  If the referer was sent by the
		browser and the substring is not found, the session
		will be deleted. (not coded yet)</para></listitem></varlistentry>

	  <varlistentry><term>entropyFile</term> <listitem><para>The
		name of a file that random binary data can be read
		from.  (<filename>/dev/urandom</filename>) Data will
		be used from this file to help generate a
		super-hard-to-guess session ID.</para></listitem></varlistentry>

	  <varlistentry><term>entropyLength</term>
		<listitem><para>The number of bytes which will be
		read from the entropy file.  If 0, the entropy file
		will not be read (default 0)</para></listitem></varlistentry>

	  <varlistentry><term>scrambleCode</term> <listitem><para>
		Set the scramble code to something unique for the
		site or your app or whatever, to slightly increase
		the unguessability of session ids (default "some
		random string")</para></listitem></varlistentry>

	  <varlistentry><term>cookieLifetime</term>
		<listitem><para>The lifetime of the cookie in
		minutes.  0 means until the browser is closed (I
		think). (default 0)</para></listitem></varlistentry>

	  <varlistentry><term>cookiePath</term> <listitem><para>The
		webserver subpath that the session cookie applies to
		(defaults to
		<filename>/</filename>)</para></listitem></varlistentry>

	  <!--varlistentry><term>cookieDomain</term>
	  <listitem><para>The domain to set in the session cookie
	  (FIXME - not coded yet)</para></listitem></varlistentry-->

	  <varlistentry><term>cookieSecure</term>
		<listitem><para>Specifies whether the cookie should
		only be sent over secure connections, 0 = any, 1 =
		secure connections only (default
		0)</para></listitem></varlistentry>

	  <varlistentry><term>sessionTable</term>
		<listitem><para>The name of the table that session
		info will be stored in (default
		<varname>rivet_session</varname>)</para></listitem></varlistentry>

	  <varlistentry><term>sessionCacheTable</term>
		<listitem><para>The name of the table that contains
		cached session data (default
		<varname>rivet_session_cache</varname>)</para></listitem></varlistentry>

	  <varlistentry><term>debugMode</term> <listitem><para>Set
		debug mode to 1 to trace through and see the session
		object do its thing (default 0)</para></listitem></varlistentry>

	  <varlistentry><term>debugFile</term> <listitem><para>The
		file handle that debugging messages will be written
		to (default
		<varname>stdout</varname>)
	      </para>
	    </listitem>
	  </varlistentry>

	</variablelist>
      </section>

      <section>
	<title>Session Methods</title>

	<para>
	  The following methods can be invoked to find out
	  information about the current session, store and fetch
	  server data identified with this session, etc:
	</para>

	<variablelist>
	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION status</command></cmdsynopsis>
	      <para>
		Return the status of the last operation
	      </para>
	    </listitem>
	  </varlistentry>


	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION id</command></cmdsynopsis>
	      <para>
		Get the session ID of the current browser.  Returns
		an empty string if there's no session (will not
		happen is SESSION activate has been issued.)
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION new_session_reason</command>
	      </cmdsynopsis>
	      <para>
		Returns the reason why there wasn't a previous
		session, either "no_cookie" saying the browser
		didn't give us a session cookie, "no_session"
		indicating we got a cookie but couldn't find it in
		the session table, or "timeout" when we had a cookie
		and a session but the session had timed out.
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION store</command>
		<arg><replaceable>packageName</replaceable></arg>
		<arg><replaceable>key</replaceable></arg>
		<arg><replaceable>data</replaceable></arg>
	      </cmdsynopsis>
	      <para>
		Given a package name, a key string, and a data
		string, store the data in the rivet session
		cache.
	      </para>
	    </listitem>
	  </varlistentry>


	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION fetch</command>
		<arg><replaceable>packageName</replaceable></arg>
		<arg><replaceable>key</replaceable></arg>
	      </cmdsynopsis>
	      <para>
		Given a package name and a key, return the data
		stored by the store method, or an empty string if
		none was set.  Status is set to the DIO error that
		occurred, it can be fetched using the status
		method.
	      </para>
	    </listitem></varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION delete</command></cmdsynopsis>

	      <para>
		Given a user ID and looking at their IP address we
		inherited from the environment (thanks, Apache),
		remove them from the session table.  (the session
		table is how the server remembers stuff about
		sessions). If the session ID was not specified the
		current session is deleted.
	      </para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term></term>
	    <listitem>
	      <cmdsynopsis>
		<command>SESSION activate</command></cmdsynopsis>

	      <para>
		Find and validate the session ID if they have one.
		If they don't have one or it isn't valid (timed out,
		etc), create a session and drop a cookie on
		them.
	      </para>
	    </listitem>
	  </varlistentry></variablelist>
      </section>

      <section>
	<title>Getting Additional Randomness From The Entropy File</title>

	<programlisting>RivetServerConf ChildInitScript "Session SESSION -entropyFile /dev/urandom \
  -entropyLength 10 -debugMode 1"</programlisting>

	<para>
	  This options say we want to get randomness from an entropy
	  file (random data pseudo-device) of /dev/urandom, to get ten
	  bytes of random data from that entropy device, and to turn
	  on debug mode, which will cause the SESSION object to output
	  all manner of debugging information as it does stuff.  This
	  has been tested on FreeBSD and appears to work.
      </para>
    </section>
  </section>


