<!-- This example is from the book _JavaScript: The Definitive Guide_.     -->
<!-- Written by David Flanagan.  Copyright (c) 1996 O'Reilly & Associates. -->
<!-- This example is provided WITHOUT WARRANTY either expressed or implied.-->
<!-- You may study, use, modify, and distribute it for any purpose.        -->

<!-- Not the way to do it, but gotta deliver something    -->
<!-- Using generic library in a specific way,             -->
<!-- change to be open-ended.   -Paul                     -->

// The constructor function.  Creates a cookie object for the specified
// document,  with a specified name. 
// attributes.  
// Arguments:
//   document: the Document object that the cookie is stored for.  Required.
//   name: a string that specifies a name for the cookie.  Required.
//   hours: an optional number that specifies the number of hours from now
//          that the cookie should expire.
//   path: an optional string that specifies the cookie path attribute.
//   domain: an optional string that specifies the cookie domain attribute.
//   secure: an optional boolean value that, if true, requests a secure cookie.
//

function Cookie(document, name, hours, path, domain, secure)
{
    // All the predefined properties of this object begin with '_'
    // to distinguish them from other properties which are the values to
    // be stored in the cookie.
    this._document = document;
    this._name = name;
    if (hours)
        this._expiration = new Date((new Date()).getTime() + hours*3600000);
    else this._expiration = null;
    if (path) this._path = path; else this._path = null;
    if (domain) this._domain = domain; else this._domain = null;
    if (secure) this._secure = true; else this._secure = false;
}

// This function is the store() method of the Cookie object
function _Cookie_store()
{
    // First, loop through the properties of the Cookie object and
    // put together the value of the cookie.  Since cookies use the
    // equals sign and semicolons as separators, we'll use colons
    // and ampersands for the individual state variables we store 
    // within a single cookie value.  Note that we escape the value
    // of each state variable, in case it contains punctuation or other
    // illegal characters.
    var cookieval = "";
    for(var prop in this) {
        // ignore properties with names that begin with '_' and also methods
        if ((prop.charAt(0) == '_') || ((typeof this[prop]) == 'function')) 
            continue;
        if (cookieval != "") cookieval += '&';
        cookieval += prop + ':' + escape(this[prop]);
    }

    // Now that we have the value of the cookie, put together the 
    // complete cookie string, which includes the name, and the various
    // attributes specified when the Cookie object was created.
    var cookie = this._name + '=' + cookieval;
    if (this._expiration)
        cookie += '; expires=' + this._expiration.toGMTString();
    if (this._path) cookie += '; path=' + this._path;
    if (this._domain) cookie += '; domain=' + this._domain;
    if (this._secure) cookie += '; secure';

    // Now store the cookie by setting the magic Document.cookie property
    this._document.cookie = cookie;
}

// This function is the load() method of the Cookie object
function _Cookie_load()
{
    // First, get a list of all cookies that pertain to this document.
    // We do this by reading the magic Document.cookie property
    var allcookies = this._document.cookie;
    if (allcookies == "") return false;

    // Now extract just the named cookie from that list.
    var start = allcookies.indexOf(this._name + '=');
    if (start == -1) return false;   // cookie not defined for this page.
    start += this._name.length + 1;  // skip name and equals sign.
    var end = allcookies.indexOf(';', start);
    if (end == -1) end = allcookies.length;
    var cookieval = allcookies.substring(start, end);

    // Now that we've extracted the value of the named cookie, we've
    // got to break that value down into individual state variable 
    // names and values.  The name/value pairs are separated from each
    // other with ampersands, and the individual names and values are
    // separated from each other with colons.  We use the split method
    // to parse everything.
    // var a = cookieval.split('&');  // break it into array of name/value pairs
    var a = new newSplit(cookieval, '&');  // break it into array of name/value pairs
    for(var i=0; i < a.length; i++)  // break each pair into an array
        // a[i] = a[i].split(':');
        a[i] = new newSplit(a[i], ':');

    // Now that we've parsed the cookie value, set all the names and values
    // of the state variables in this Cookie object.  Note that we unescape()
    // the property value, because we called escape() when we stored it.
    for(var i = 0; i < a.length; i++) {
        this[a[i][0]] = unescape(a[i][1]);
    }

    // We're done, so return the success code
    return true;
}

// This function is the remove() method of the Cookie object.
function _Cookie_remove()
{
    var cookie;
    cookie = this._name + '=';
    if (this._path) cookie += '; path=' + this._path;
    if (this._domain) cookie += '; domain=' + this._domain;
    cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

    this._document.cookie = cookie;
}

function newSplit(theString,theSplitter)
{
   this.length=0;
   while (theString.indexOf(theSplitter) != -1) { 
     this.length++;
     this[this.length-1] = theString.substring(0,theString.indexOf(theSplitter));
     theString = theString.substring(theString.indexOf(theSplitter)+1, theString.length);
   }
   this.length++;
   this[this.length-1]=theString;
}

// Create a dummy Cookie object, so we can use the prototype object to make
// the functions above into methods.
new Cookie();
Cookie.prototype.store = _Cookie_store;
Cookie.prototype.load = _Cookie_load;
Cookie.prototype.remove = _Cookie_remove;


/* begin esource code */

var e_source = "";
var query_string = "";
var visitor = new Cookie(document, "ESource", 24, "/");

// generic main function to get and/or set esource
function esource() {
   query_esource();
   set_esource();
}
 
function make_cookie() {

   // if no cookie then set initialize a new one
   if (!visitor.load()) {
      visitor.visits  = 0;
   } 

   cookie_esource = visitor.esource;

   // First priority is an esource in the query string 
   // otherwise, we use the cookie's esource
   if ((e_source == null) || (e_source == "")) {
      if ((visitor.esource != null) && (visitor.esource != ""))
         e_source = visitor.esource;
      return;
   }

   visitor.esource = e_source;
   
   // how many times have we been here?
   visitor.visits++;

   // save the cookie if we got anything new
   if (visitor.esource != cookie_esource) visitor.store();
}

// parse query for esource
// todo: modify to use "generic" split function
function query_esource() {
  query_string = location.search.substring(1, location.search.length);
  e_start = query_string.indexOf("esource=");
  if (e_start >= 0) {
    e_start += 8;
    e_stop  = query_string.indexOf("&", e_start);
    // IE3 bug returns "" instead of -1 if start > length of test string
    if (e_stop == "") e_stop = 0;
    if (e_stop < e_start) e_stop = query_string.length;
    q_source = query_string.substring(e_start, e_stop);
    if (q_source > "") e_source = q_source;

  }
  // okay, stash esource in a cookie
   make_cookie();

  // for visual confirmation that it took...
  if (e_source != null) defaultStatus = "eSource = " + e_source;

}

function set_esource() {
  query_esource();
  if (e_source == null) e_source = "";
  for (i = 0; i < document.forms.length; i++) {
     // verify that the form element exists before assigning to it
     if (document.forms[i].esource != null)
        document.forms[i].esource.value = e_source;
  }
  // the following 2 lines can be commented out if desired...
  if (e_source > "") 
  defaultStatus = "eSource = " + e_source;
}

