function Pinger (sessionid, callback) {

   var _cb;
   var _handler;
   var _sessionid;
   var _interval = 10000;
   var _intervalid;

   _cb = callback;
   _sessionid = sessionid;

   this.start = function () {

      if (! _handler) {
         if (window.XMLHttpRequest) _handler = new XMLHttpRequest ();
         else _handler = new ActiveXObject ("Microsoft.XMLHTTP");
      }

      _intervalid = setInterval (ping, _interval);
   }

   function ping  () {

      if (_handler) {

         var hostname = window.location.hostname.toString ();

         _handler.open ("POST", "http://" + hostname + "/perl/mxmd/webchat/session", true);
         _handler.onreadystatechange = onresponse;
         _handler.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

         _handler.send ("<session><task>pingsession</task><sessionid>" + _sessionid + "</sessionid></session>");
      }
   }

   function onresponse () {

      if (_handler.readyState != 4 || _handler.status != 200)
         return;

      var xml = _handler.responseXML;
      if (xml == null) {
         showMsg ('Unexpected error, please try again later');
         return;
      }

      if (! findNode (xml, 'ok')) {
         showMsg ('Unexpected error, please try again later');
         return;
      }

      var interval = findNodeValue (xml, 'interval');
      if (interval && interval != _interval) {

            clearInterval (_intervalid);
            _interval = interval;

            _intervalid = setInterval (ping, _interval);
      }

      var replies = findNode (xml, 'replies');

      var reply = findNode (xml, 'reply');
      var replyfrom;
      var replytext;
      var replycount;

      if (replies) {

         replycount = findAttrValue (replies, 'count');
         if (replycount && replycount > 0) {

            if (reply) {

               replyfrom = findNodeValue (reply, 'from');
               replytext = findNodeValue (reply, 'text');

            }
         }

      }

      var cbobject = new Object ({'isuser': findNodeValue (xml, 'isuser'),
                                  'credits': findNodeValue (xml, 'credits'),
                                  'replycount': replycount});
      if (reply) {
         cbobject.replyfrom = replyfrom;
         cbobject.replytext = replytext;
      }

      var ad = findNode (xml, 'ad');
      if (ad) {
         cbobject.adid = findAttrValue (ad, 'id');
         cbobject.adtext = findNodeValue (ad, 'text');
         cbobject.adonclick = findNodeValue (ad, 'onclick');
         cbobject.adurl = findNodeValue (ad, 'adurl');
      }

      if (_cb)
        _cb (cbobject);
   }

   function findNodeValue (node, tag) { try { return node.getElementsByTagName (tag)[0].firstChild.nodeValue; } catch (err) { return null; } }
   function findAttrValue (node, tag) { try { return node.attributes.getNamedItem (tag).value; } catch (err) { return null; } }
   function findNode (node, tag) { try { return node.getElementsByTagName (tag)[0]; } catch (err) { return null; } }
}

