window.__cookie_js__ = 1;

/* The following code is to handle cookies containig complex data structures.


  usage:

  // acccess to a cookie called 'dataName' which is valid for 240 hours (10 days)
  var persistentData = new Cookie(document,'dataName',240); // acccess to a cookie 


  // load data from client
  if ( persistentData.load() ) {
    // access to loaded data
    var date = persistentData.date;
    var any  = persistentData.any;
    ...
  }


  // store data store to client
  persistentData.date = myDate;
  persistentData.any  = my Any;
  ...
  persistentData.store();



  // remove data from client
  persistentData.remove();


  // iterating over all attributes:
  var str = '';
  persistentData.iterateAttributes( function (attr,val) { str += attr+': \''+val+'\'\n'; } );
  

  // determine all attribute names
  var nameArray = persistentData.getAttributeNames();


  // determine all cookie names for a document
  var cookieNameArray = Cookie.getCookieNames( document );

  see cookie.html for an example
*/ 


// Cookie constructor
// hours, path, domain, secure are optional 
// internal object attributes are prefixed by '$'
// timeout may be an integer followed by a s=seconds, m=minutes, h=hours, d=days.
// If just an integer is coded it is interpreted as hours. This is deprecated!
function Cookie(document,name,livetime,path,domain,secure) {
  this.$document = document;
  this.$name     = name;
  this.$timeout  = null;
  if ( livetime ) {
    var now = (new Date()).getTime();
    if ( 'string' != typeof(livetime) )   { seconds =  3600 * livetime;  }
    else if ( livetime.match(/^(\d+)$/ )) { seconds =  3600 * RegExp.$1; }
    else if ( livetime.match(/^(\d+)s$/)) { seconds =     1 * RegExp.$1; }
    else if ( livetime.match(/^(\d+)m$/)) { seconds =    60 * RegExp.$1; }
    else if ( livetime.match(/^(\d+)h$/)) { seconds =  3600 * RegExp.$1; }
    else if ( livetime.match(/^(\d+)d$/)) { seconds = 86400 * RegExp.$1; }
    this.$timeout = new Date( now + 1000 * parseInt(seconds) );
  }
  if ( path )   this.$path   = path;   else this.$path   = null;
  if ( domain ) this.$domain = domain; else this.$domain = null;
  if ( secure ) this.$secure = secure; else this.$secure = null;
}


// just for internal use
// not yet fully tested
Cookie._javascriptEncode = function (value) {
  var type = typeof(value);
  //alert( "typeof("+value+") = "+type );
  if ( 'number' == type ) return ''+value;
  if ( 'string' == type && null != value ) {
    //if ( !value ) alert( "value = '"+value+"'");
    if ( value && value.toSource ) value = value.toSource();
    if ( value && null != value && value.match( /^\(new String\((.*)\)\)$/ ) ) value = RegExp.$1;
    if ( null != value && !value.match( /^"(.*)"$/ ) ) value = '"'+value+'"';
    /*
    // selfmade solution
    var re = /([\\\'\"])/g;
    value = value.replace( re, function(c){ return '\\'+c; } );
    value = '"'+value+'"';
    */
    return value;
  }
  if ( 'object' == type ) {
    if ( null == value ) return 'null';
    return value.toSource();
    /*
    // old implementation follows:
    // check if value is an array
    if ( value[0] == null ) {
      alert( 'value: '+value+' ,toString'+value.toString() );
      alert( 'toSource = '+value.toSource() );
      var arr = [];
      for ( var attribute in value ) {
        arr.push( attribute+': '+_javascriptEncode(value[attribute]) );
      }
      return '{'+arr.join(',')+'}';
    } else {
      alert( 'value: '+value+' ,toString'+value.toString() );
      alert( 'toSource = '+value.toSource() );
      var arr = [];
      for ( var i = 0; i < value.length; i++ ) {
        arr.push( _javascriptEncode(value[i]) );
      }
      return '['+arr.join(',')+']';
    }
    */
  }
  alert( "_javascriptEncode: unhandled type: '"+type+"'");
};



/////////////
// methods //
/////////////


Cookie.prototype.iterateAttributes = function (iterator) {
  for ( var attribute in this ) {
    if ( attribute.charAt(0) == '$' ) continue;
    var value = this[attribute];
    if ( typeof(value) == 'function' || null == value ) continue;
    iterator(attribute,value);
  }
};


Cookie.prototype.getAttributeNames = function () {
  var names = [];
  this.iterateAttributes( function (attr,value) { names.push( attr ); } );
  return names;
};


Cookie.getCookieNames = function ( document ) {
  var strings = document.cookie;
  if ( strings == '' ) return [];

  var names = [];
  strings = strings.split('; ');
  for ( var i = 0; i < strings.length; i++ ) {
    if ( strings[i].match(/^\s*([\w\-\.]+)(=|$|; )/) ) {
      names.push( RegExp.$1 );
    } else {
      alert('Cookie.prototype.getCookieNames: could not parse:\n\n'+document.cookie);
    }
  }
  return names;
}


Cookie.prototype.store = function () {
  var attrs = [];
  this.iterateAttributes( function (attr,value) { attrs.push( attr + ':' + escape(Cookie._javascriptEncode(value) ) ); } );

  var string = this.$name + '=' + attrs.join('&');
  if ( this.$timeout ) string += '; expires=' + this.$timeout.toGMTString();
  if ( this.$path    ) string += '; path='    + this.$path;
  if ( this.$domain  ) string += '; domain='  + this.$domain;
  if ( this.$secure  ) string += '; secure='  + this.$secure;

  //alert( 'cookie = '+string );

  this.$document.cookie = string;
};


Cookie.prototype.load = function () {
  var strings = this.$document.cookie;
  if ( strings == '' ) return false;

  //alert( "loading strings: '"+strings+"'" );

  strings = '; ' + strings + ';';

  var namePat  = '; ' + this.$name + '=';
  var start = strings.indexOf( namePat );
  if ( start == -1 ) return false;
  start += namePat.length;
  var end = strings.indexOf(';', start);
  var string = strings.substr(start,end-start);

  //alert( "loading string: '"+string+"'" );

  var pairs = string.split('&');
  for ( var i = 0; i < pairs.length; i++ ) {
    if ( pairs[i] == '' ) continue;
    var pair = pairs[i].split(':');
    var expr = unescape(pair[1]);
    //alert( 'load: '+pair[0]+' = '+expr );
    var val;
    eval("val = "+expr);
    this[pair[0]] = val;
    //alert( 'loaded: '+pair[0]+' = '+unescape(pair[1]) );
    //alert( 'loaded: '+pair[0]+' = '+this[pair[0]] );
  }

  return true;
};


Cookie.prototype.remove = function () {
  var string = this.$name + '=';
  if ( this.$path   ) string += '; path='   + this.$path;
  if ( this.$domain ) string += '; domain=' + this.$domain;
  if ( this.$secure ) string += '; secure=' + this.$secure;

  var epoch = new Date( 0 );
  string += '; expires=' + epoch.toGMTString();

  //alert( 'cookie = '+string );

  this.$document.cookie = string;
};
