var Cookie = {
    // Функция установки значения cookie.
    // name      - имя cookie
    // value     - значение cookie
    // [path]    - путь, для которого cookie действительно (по умолчанию - /)
    // [expires] - дата окончания действия cookie (по умолчанию - до конца сессии)
    // [domain]  - домен, для которого cookie действительно (по умолчанию - домен, 
    //             в котором значение было установлено)
    // [secure]  - логическое значение, показывающее требуется ли защищенная 
    //             передача значения cookie
    setCookie : function (name, value, path, expires, domain, secure) {
      var curCookie = name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "; path=/") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
      document.cookie = curCookie;
    },
    
    // Функция чтения значения cookie.
    // name - имя считываемого cookie
    getCookie : function (name) {
      var prefix = name + "=";
      var cookieStartIndex = document.cookie.indexOf(prefix);
      if(cookieStartIndex == -1) return null;
      var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex + prefix.length);
      if(cookieEndIndex == -1) cookieEndIndex = document.cookie.length;
      return unescape(document.cookie.substring(cookieStartIndex + prefix.length, cookieEndIndex));
    },
    
    // Функция удаления значения cookie
    // name - имя cookie
    // [path] - путь, для которого cookie действительно
    // [domain] - домен, для которого cookie действительно
    delCookie : function (name, path, domain) {
      if(Cookie.getCookie(name)) {
        document.cookie = name + "=" + 
        ((path) ? "; path=" + path : "; path=/") +
        ((domain) ? "; domain=" + domain : "") +
        "; expires=Thu, 01-Jan-70 00:00:01 GMT";
      }
    },
    
    // Устанавливает Cookie сложной структуры.
    setCookieEx : function (name, value, path, expires, domain, secure)
    { value=Serialize(value);
    //  alert(value);
      return setCookie(name, value, path, expires, domain, secure);
    },
    
    // Читает Cookie сложной структуры.
    getCookieEx : function (name)
    { var v=getCookie(name);
      return Unserialize(v);
    }
}


// Разделители для сериализации (те же, что в CGI::WebIn)
var Div1 = '.';
var Div2 = '.';

// Функция сериализации, совместимая с CGI::WebIn::Serialize
// Вложенные ссылки игнорируются.
function Serialize(v)
{ return "L1"+Div1+SerializeWO(v);
}

// Функция десериализации.
// Вложенные ссылки игнорируются.
function Unserialize(v)
{ var sb=new StringBuffer(v);
  if(sb.first(1)=='L') sb.shiftTill(Div2);
  return UnserializeWO(sb);
}

function SerializeWO(v)
{ 
  if (v==null || typeof v=='number' || typeof v=='string') {
    if(v==null) v="";
    return (""+v).length+Div1+(""+v);
  } else if(v instanceof Array) {
    var s="rL"+v.length+Div2;

    for(var i=0; i<v.length; i++) {
      s+=SerializeWO(v[i]);
    }
    return s;
  } else {
    var a=new Array();
    for(var k in v) {
      if(v[k]==null) continue;
      a[a.length++]=k;
      a[a.length++]=v[k];
    }
    var s="rHL"+a.length+Div2;
    for(var i=0; i<a.length; i++) {
      s+=SerializeWO(a[i]);
    }
    return s;
  }
}

function UnserializeWO(sb)
{ 
  if(sb.first(1)=='r') sb.shift(1);
  var type=sb.first(1);
  if(type=='L' || type=='H') {
    // Массив
    sb.shift(1);
    if(sb.first(1)=='L') sb.shift(1);
    var n=sb.shiftTill(Div2);
    var len = parseInt(n);
    var a=new Array(len);
    for(var i=0; i<len; i++) {
      a[i]=UnserializeWO(sb);
    }
    // если хэш, то преобразуем
    if(type=='H') {
      var h=new Hashtable();
      for(var i=0; i<a.length; i+=2) h[a[i]]=a[i+1];
      return h;
    } else {
      return a;
    }
  } else {
    // Строка
    var n=sb.shiftTill(Div1);
    var len = parseInt(n);
    var s=sb.shift(len);
    return s;
  }
  
}

// Строковой буфер с возможностью сдвига влево.
function StringBuffer(s) 
{        this.s=''+s;
        this.shift=StringBuffer_shift;
        this.shiftTill=StringBuffer_shiftTill;
        this.first=StringBuffer_first;
}

function StringBuffer_shift(n)
{        var s=this.s.substr(0,n);
        this.s=this.s.substr(n);
        return s;
}

function StringBuffer_shiftTill(s)
{        var p=this.s.indexOf(s);
        var r=this.shift(p);
        this.shift((""+s).length);
        return r;
}

function StringBuffer_first(n)
{        return this.s.substr(0,n);
}