001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.web.servlet;
007
008import java.util.*;
009import java.io.*;
010import java.security.*;
011import javax.servlet.*;
012import javax.servlet.http.*;
013
014import fc.io.*;
015import fc.util.*;
016
017/**
018Misc utility methods for sessions and cookies.
019
020@author hursh jain
021**/
022public final class SessionUtil 
023{
024static final String TestCookieName = "eikooc";
025  
026/**
027Sets a test cookies. The user should be redirected to this or some other
028page after calling this method and the presence of this cookie can be
029checked via {@link hasTestCookie} from that page. The lifetime of the
030test cookie is set to the browsers lifetime (will be lost when the
031browser exits).
032*/
033public static void setTestCookie(
034  HttpServletRequest req, HttpServletResponse res)
035  {
036  Cookie c = new Cookie(TestCookieName, "scotchAndsoda");
037  c.setMaxAge(-1);
038  res.addCookie(c);
039  }
040
041/**
042Returns true if the browser accepts cookies. The {@link setTestCookie()}
043method must have been invoked by some page prior to calling this method
044AND the user must have been either redirected to that or some other page
045AND this method must be invoked from that redirected page.
046<p>
047<b>Note:</b>
048Test cookies are entirely self contained. They are meant to figure out if
049a browser accepts cookies. Their presence or absence does not mean that
050<b>other</b> cookies will not be sent by the browser. These other cookies
051may point to a expired session in memory or database and a seperate check
052for that should be made.
053*/
054public static boolean hasTestCookie(
055  HttpServletRequest req, HttpServletResponse res)
056  {
057  Cookie[] cookies = req.getCookies();
058  if (cookies == null)
059    return false;
060
061  for (int n = 0; n < cookies.length; n++) {
062    if (cookies[n].getName().equals(TestCookieName))
063      return true;
064    }
065
066  return false;
067  }
068
069/**
070Removes the test cookies if previously set. Normally, the
071test cookie set by the {@link #setTestCookie} method is
072automatically removed when the browser exists, but this
073method allows removing it before such time.
074*/
075public static void deleteTestCookie(
076  HttpServletRequest req, HttpServletResponse res)
077  {
078  Cookie[] cookies = req.getCookies();
079  if (cookies == null)
080    return;
081
082  for (int n = 0; n < cookies.length; n++) 
083    {
084    if (cookies[n].getName().equals(TestCookieName))
085      {
086      cookies[n].setMaxAge(0);
087      res.addCookie(cookies[n]);
088      break;
089      }
090    }
091  }
092
093/**
094Returns a new session identifier.
095<pre>
096See: cookies.lcs.mit.edu
097See: www.across.si
098
099There are 2 issues with generating sessionid's. 
100
1011) uniqueness - 2 or more sessionid's should not end up being 
102   the same.
1032) hard-to-guess - For example, sequential values like 
104   1, 2, 3 are unique but easy to guess and therefore easy
105   to session hijack.
106
107Our sessionid's have 2 parts:
108a) a timestamp for guaranteed uniqueness  (easy to guess)
109b) random data (hard to guess)
110</pre>
111*/
112public static String newSessionID() 
113  {
114  return UUIDUtil.newSessionID();
115  }
116}