function xDetectbrowser()
{
  //bw = new xDetectbrowser()

//check mmyy!!!
//check if cookie overrides existing cookies!!!


  this.ver = navigator.appVersion.toLowerCase();;
  this.appname = navigator.appName;
  this.agent = navigator.userAgent.toLowerCase();
  this.platform = navigator.platform.toLowerCase();

  this.dom = document.getElementById?1:0;
  this.anchors = document.anchors?1:0;
  this.regexp = window.RegExp?1:0;
  this.option = window.Option?1:0;
  this.all = document.all?1:0;
  this.images = document.images?1:0;
  this.layers = document.layers?1:0;   // gecko m7 bug?
  this.forms = document.forms?1:0;
  this.links = document.links?1:0;
  this.frames = window.frames?1:0;
  this.screen = window.screen?1:0;

  if(!document.cookie)
    document.cookie = 'cookies=true';
  this.cookie = document.cookie?1:0;

  this.webtv = this.agent.indexOf('webtv')>-1;
  this.gecko = this.agent.indexOf('gecko')>-1;
  this.safari = this.agent.indexOf('safari')>-1;
  this.opera = this.agent.indexOf('opera')>-1;
  this.opera5 = this.agent.indexOf('opera 5')>-1;
  this.aol = this.agent.indexOf('aol')>-1;
  this.aol3 = this.aol && this.ie3;
  this.aol4 = this.aol && this.ie4;
  this.ie5 = this.ver.indexOf('msie 5')>-1 && this.dom && !this.opera5;
  this.ie6 = this.ver.indexOf('msie 6')>-1 && this.dom && !this.opera5;
  this.ie4 = document.all && !this.dom && !this.opera5;
  this.ie = this.ie4||this.ie5||this.ie6;
  this.ns6 = this.dom && parseInt(this.ver,10)>=5;
  this.ns4 = document.layers && !this.dom;

  this.mac = this.agent.indexOf('mac')>-1;
  this.mac68k = this.mac && ((this.agent.indexOf('68k')>-1)
                            ||(this.agent.indexOf('68000')>-1));
  this.macppc = this.mac && ((this.agent.indexOf('ppc')>-1)
                            ||(this.agent.indexOf('powerpc')>-1));
  this.win32 = this.agent.indexOf('win95')>-1
               ||this.agent.indexOf('windows 95')>-1
               ||this.agent.indexOf('win98')>-1
               ||this.agent.indexOf('windows 98')>-1
               ||this.agent.indexOf('winnt')>-1
               ||this.agent.indexOf('windows nt')>-1
               ||this.agent.indexOf('windows xp')>-1
               ||this.agent.indexOf('win32')>-1
               ||this.agent.indexOf('32bit')>-1
               ||(parseInt(this.ver)>=4 && this.platform=='win32');
  this.xnix = this.agent.indexOf('sunos')>-1
              || this.agent.indexOf('i86')>-1
              || this.agent.indexOf('irix')>-1
              || this.agent.indexOf('hp-ux')>-1
              || this.agent.indexOf('aix')>-1
              || this.agent.indexOf('inux')>-1
              || this.agent.indexOf('sco')>-1
              || this.agent.indexOf('unix_sv')>-1
              || this.agent.indexOf('unix_system_v')>-1
              || this.agent.indexOf('ncr')>-1
              || this.agent.indexOf('reliantunix')>-1
              || this.agent.indexOf('dec')>-1
              || this.agent.indexOf('osf1')>-1
              || this.agent.indexOf('alpha')>-1
              || this.agent.indexOf('ultrix')>-1
              || this.agent.indexOf('freebsd')>-1
              || this.agent.indexOf('bsd')>-1
              || this.agent.indexOf('x11')>-1;

  // Safari includes Gecko string
  // On Opera 3.0, the userAgent string includes 'Windows 95/NT4' on all
  //   Win32, so you can't distinguish between Win95 and WinNT.
  // Reliable detection of Win32 may not be possible. It appears that:
  //   - On Nav 4.x and before you'll get plain 'Windows' in userAgent.
  //   - On Mercury client, the 32-bit version will return 'Win98', but
  //     the 16-bit version running on Win98 will still return 'Win95'.

  return this;
}

function xIsEmpty(s)
{
  return ((s == null) || (s.length == 0));
}

function xTrim(s)
{
  if(s == null)
    return '';

  while (s.substr(0,1) == ' ') s = s.substr(1);
  while (s.substr(s.length-1,s.length) == ' ') s = s.substr(0,s.length-1);
  return s;
}

function xValidatestr(str, vtype, range, regex)
{
  // see notes in server side function

  if((str == null || vtype == null)
  || (regex != null && regex.length > 0 && str.search(new RegExp(regex)) == -1))
    return false;

  if(range != null && range.length > 0)
  {
    var bound = range.split('-');
    var lbound = isNaN(parseFloat(bound[0])) ? 0 : parseFloat(bound[0]);
    var ubound = isNaN(parseFloat(bound[1])) ? Math.pow(2,64) : parseFloat(bound[1]);

    if((vtype == 'text' || vtype == 'alphanum' || vtype == 'textbox')
    && (str.length < lbound || str.length > ubound))
      return false;

    if(vtype == 'number' || vtype == 'decnum' || vtype == 'intnum' || vtype == 'date' || vtype == 'day' || vtype == 'datetime' || vtype == 'datemmdd' || vtype == 'datemmyy' || vtype == 'time')
    {
      if(str.length == 0)
        str = '0';
      if(parseFloat(str) < lbound || parseFloat(str) > ubound)
        return false;
    }

    if(vtype == 'email')
    {
      var tmp = str.split(',');
      if((lbound > 0 && str.length == 0)
      || tmp.length < lbound || tmp.length > ubound)
        return false;
    }

    if(vtype == 'selectlist' || vtype == 'multiselect')
    {
      var tmp = str.split(',');
      var found = 0;
      for(var i=0; i<tmp.length; i++)
        found += tmp[i].search(/[^0]+/) != -1 ? 1 : 0;
      if(found < lbound || found > ubound)
        return false;
    }
  }

  if(vtype == 'time')
  {
    if((str.length == 0 || parseFloat(str) == 0)
    && (range == null || range.length == 0))
      return true;
    if(str.search(/^.{8}([0-5][0-9]){3}$/) == -1)
      return false;
  }
  if(vtype == 'date' || vtype == 'day' || vtype == 'datetime' || vtype == 'datemmdd')
  {
    if((str.length == 0 || parseFloat(str) == 0)
    && (range == null || range.length == 0))
      return true;

    var yy = parseFloat(str.substr(0,4), 10);

    if(str.search(/^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])([0-5][0-9]){3}$/) == -1
    || str.search(/^.{4}(04|06|09|11)31.{6}$/) != -1
    || str.search(/^.{4}(02)3[01].{6}$/) != -1
    || (str.search(/^.{4}(02)29.{6}$/) != -1 && (yy%4 > 0 || (yy%100 ==0 && yy%400 > 0))))
      return false;

    if(vtype == 'date' || vtype == 'datetime' || vtype == 'datemmdd')
    {
      return true;
    }
    else if(vtype == 'day')
    {
      var mth, day;
      var dd = parseFloat(str.substr(6,2), 10);
      var mm = parseFloat(str.substr(4,2), 10);
      var yr1 = yy - 401;
      var firstday = parseFloat((1 + yr1 + (yr1/4) - (yr1/100) + (yr1/400)) % 7);

      for(mth=1; mth<mm; mth++)
      {
        if(mth == 4 || mth == 6 || mth == 9 || mth == 11)
          firstday += 30;
        else if((mth == 2) && (((yy%4 == 0) && yy%100 != 0) || yy%400 == 0))
          firstday += 29;
        else if(mth == 2)
          firstday += 28;
        else
          firstday += 31;
      }
      return ((firstday + dd - 1) % 7) + 1;
    }
  }
  if(vtype == 'bankcard' || vtype == 'creditcard')
  {
    var digit,check,position;

    str = str.replace(/\-/g, '');

    for(check=0,position=1; position<=str.length; position++)
    {
      if(isNaN(digit=parseInt(str.charAt(str.length-position),10)))
        return false;
      if(!(position % 2))
        digit=parseInt('0246813579'.charAt(digit),10);
      check+=digit;
    }
    if((check % 10) != 0)
      return false;

    if(vtype == 'bankcard')
      return true;
    else if(str.search(/^5[1-5].{14}$/) != -1)
      return 'master';
    else if(str.search(/^4.{15}$|^4.{14}$|^4.{13}$|^4.{12}$/) != -1)
      return 'visa';
    else if(str.search(/^3[47].{13}$/) != -1)
      return 'amex';
    else if(str.search(/^6011.{12}$/) != -1)
      return 'discover';
    else if(str.search(/^30[0-5].{11}$|^3[68].{12}$/) != -1)
      return 'diners';
    else if(str.search(/^2014|2149.{11}$/) != -1)
      return 'enroute';
    else if(str.search(/^3.{15}$|^2131|1800.{11}$/) != -1)
      return 'jcb';
    else
      return 'unknown';
  }

  if((vtype == 'text' && str.search(/^.|\n*$/) == -1)
  || (vtype == 'textbox' && str.search(/^.|\n*$/) == -1)
  || (vtype == 'email' && str.search(/(^(,*[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-.]?[0-9a-zA-Z])*\.(com|edu|biz|org|gov|int|info|mil|net|name|museum|coop|aero|[a-z][a-z]))+$)|(^$)/i) == -1)
  || (vtype == 'alphanum' && str.search(/(^[0-9a-zA-Z]+$)|(^$)/) == -1)
  || (vtype == 'number' && str.search(/(^[0-9]*\.*[0-9]*$)|(^$)/) == -1)
  || (vtype == 'decnum' && str.search(/(^[0-9]*\.[0-9]*$)|(^$)/) == -1)
  || (vtype == 'intnum' && str.search(/(^[0-9]+$)|(^$)/) == -1))
    return false;

  return true;
}

function xPhpserialize(jsvar)
{
  var ret = '';
  var booleanobj = jsvar.constructor.toString().match(/boolean/i);
  var stringobj = jsvar.constructor.toString().match(/string/i);
  var arrayobj = jsvar.constructor.toString().match(/array/i);

  if(typeof(jsvar) == 'number')
  {
    ret += 'i:' + jsvar + ';';
  }
  else if(typeof(jsvar) == 'boolean' || booleanobj != null)
  {
    ret += 'b:' + (jsvar==true ? '1' : '0') + ';';
  }
  else if(typeof(jsvar) == 'string' || stringobj != null)
  {
    var len = 0;
    for(var i=0; i<jsvar.length; i++)
    {
      len++;

      //TODO: actual character length depends on unicode space and page encoding
      if(escape(jsvar.charAt(i)).search(/^%[abcdefABCDEF][a-zA-Z0-9]/) == 0)
      {
        len ++;
      }
      else if(escape(jsvar.charAt(i)).search(/^%u[a-zA-Z0-9]{4}/) == 0)
      {
        len += 2;
      }
      else if(escape(jsvar.charAt(i)) == '%0D'
      && escape(jsvar.charAt(i+1)) == '%0A')
      {
        len++;
        i++;
      }
      else if(escape(jsvar.charAt(i)) == '%0A')
      {
        len++;
      }
      else if(escape(jsvar.charAt(i)).search(/^%[a-fA-F][a-fA-F0-9]/) == 0)
      {
        //TODO: checkout other european characters 
        len ++;
      }
    }
    ret += 's:' + len + ':"' + jsvar + '";';
  }
  else if(typeof(jsvar) == 'object' && arrayobj != null)
  {
    var len = 0;
    for(var i in jsvar)
      len++;

    ret += 'a:' + len + ':{';
    for(var i in jsvar)
    {
      if(isNaN(parseInt(i,10)))
        ret += 's:' + i.length + ':"' + i + '";' + xPhpserialize(jsvar[i]);
      else
        ret += 'i:' + i + ';' + xPhpserialize(jsvar[i]);
    }
    ret += '}';
  }
  else if(typeof(jsvar) == 'undefined')
    ret += 'N;';
  else
    ret += 'N;';

  //TODO: handle date object (toString)

  return ret;
}

function xPrintpage()
{  
  if (window.print)
  {
    window.print() ;  
  }
  else
  {
    var WebBrowser = '<OBJECT ID="WebBrowser1" WIDTH=0 HEIGHT=0 CLASSID="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></OBJECT>';
    document.body.insertAdjacentHTML('beforeEnd', WebBrowser);
    WebBrowser1.ExecWB(6, 2);

    //Use a 1 vs. a 2 for a prompting dialog box    WebBrowser1.outerHTML = "";  
  }
}

function xGetquerystring(index)
{
  var paramExpressions;
  var param;
  var val;

  paramExpressions = window.location.search.substr(1).split('&');

  if(index < paramExpressions.length)
  {
    param = paramExpressions[index]; 
    if(param.length > 0)
      return eval(unescape(param));
  }

  return '';
}
