// + RPC + =====================================================================
function requestFunc(){
 var tryThese = [
  function(){ return new XMLHttpRequest();                      },
  function(){ return new ActiveXObject ( 'Microsoft.XMLHTTP' ); },
  function(){ return new ActiveXObject ( 'Msxml2.XMLHTTP' );    },
  function(){ return new ActiveXObject ( 'Msxml2.XMLHTTP.4.0' );}
 ];
 for( var i = 0, len = tryThese.length; i < len; ++i ){
  var func = tryThese[ i ];
  try {
   var x = func();
   if( typeof x != 'undefined' ){
    return func;
   }
  }catch( e ){}
 }
 return doNothing;
}
var newXMLHttpRequest = requestFunc();

function rpc( uri ){
 this.uri  = uri;
 this.proc = new Array();
 this.count = 0;
}
if( newXMLHttpRequest === doNothing ){
 rpc.prototype.send = doNothing;
}else{
 rpc.prototype.send = function( func, param, respFunc, respFuncParams ){
  ++ this.count;
  if( this.send_fn ) this.send_fn();
  var req               = newXMLHttpRequest();
  var respFuncReq       = respFunc;
  var respFuncParamsReq = respFuncParams;
  var xml               = ob2sdxml( func, param );  
  req.open( 'POST', this.uri, true );
  req.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );  
  var thisOb             = this;  
  req.onreadystatechange = function(){                     
   if( responseReady( req ) ){             
    var resp =  rpc2ob( req ) ;    
    respFuncReq( resp, respFuncParamsReq );
    respFuncReq = doNothing;                // IE 5.0
//     thisOb.proc.rm( req );   
   }
   if( req.readyState == 4 ){
    -- thisOb.count;
    if( thisOb.re_fn ){
      thisOb.re_fn( resp, respFuncParamsReq );      
    }    
   }
  }

  this.proc.push( req );
//   if( typeof console !== 'undefined' ){ console.info( xml ) }
  req.send( toUrl(xml) );
  return true;
 }
}

function responseReady( req ){  
 if( req.readyState == 4 ){
  if( req.status == 200 ){
  //console.info( req.getResponseHeader( 'Set-Cookie' ) );
   return true;
  }else{
   alert( 'Error while retrieving XML data:\n' + 'status:' + req.status + '\nresponse:\n' + req.statusText );
   return false;
  }
 }
 return false;
}

// - RPC - =====================================================================

// + SDXML2Ob + ================================================================
function XMLfirstChildVal( val ){
 var re = '';
 var node; 
 for( var it = 0; node = val.childNodes[ it ]; ++it ){
  if( node.nodeType == 3 ) re += node.nodeValue;
 }
 if( re != '' ) return { nodeValue:re }; 
 return false;
}

function ob2sdxml( func, param ){
 return '<root><method>' + func + '</method>' + toSdxml(param) + '</root>';
}

function toSdxml( arr ){
 var re = '';
 for(key in arr){
  var tag = ( typeof key == 'undefined' || isInt(key) ) ? 'l' : toXml(key);
  re += '<' + tag + '>' + (isArray(arr[key]) ? toSdxml(arr[key]) : toXml(arr[key])) + '</' + tag + '>';
 }
 return re;
}

function dom2txt( dom ){
 var txt = '';
 var child;
 if( dom.childNodes ){
  var it = 0;
  while( child = dom.childNodes[ it++ ] ){
   txt += child.nodeType + ':' + child.nodeName + ':' + child.nodeValue + ' ';
   if( child.attributes ){
    var jt = 0;
    while( att = child.attributes[ jt++ ] ){
     txt += att.nodeType + ':' + att.nodeName + ':' + att.nodeValue + ' ';
    }
   }
   txt += '\n';
   txt += dom2txt( child );
  }
 }
 return txt;
}

function rpc2ob( rpc ){
 var arr = new Array();
 if( rpc.responseXML.normalize ) rpc.responseXML.normalize();
 var nod = rpc.responseXML.firstChild;
 if(!nod.childNodes[0]) return arr;
 if(nod.childNodes[0].nodeType == 3) {
  arr.push(nod.childNodes[0].nodeValue);
  return arr;
 }
 arr = dom2ob( nod ); 
 return arr;
}

function dom2ob( nod ){
 var tmp = new Array();
 for(var i=0; i<nod.childNodes.length; i++){
  var child = nod.childNodes[i];
  if(child.childNodes[0].nodeType == 3){
   if(child.nodeName == 'l') tmp.push(child.childNodes[0].nodeValue);
   else tmp[child.nodeName] = child.childNodes[0].nodeValue;
  }
  else {
   if(child.nodeName == 'l'){
    tmp[child.nodeName] = new Array();
    tmp[child.nodeName].push(dom2ob(child));
   }
   else {
    tmp[child.nodeName] = new Array();
    tmp[child.nodeName] = dom2ob(child);
   }  
  }
 }
 return tmp;
}

// function dom2ob( nod ){
//  var tmp = new Array(); 
//  for(var i=0; i<nod.childNodes.length; i++){
//   var child = nod.childNodes[i];  
//   if(child.childNodes[0].nodeType == 3){
//    tmp[child.nodeName] = child.childNodes[0].nodeValue;
//   }
//   else {
//    tmp[child.nodeName] = new Array(); 
//    for(var j=0; j<child.childNodes.length; j++){    
//     var grandChild = child.childNodes[j];
//     var tmp2 = new Array();
//     tmp2[grandChild.nodeName] = grandChild.childNodes[0].nodeValue; 
//     tmp[child.nodeName].push(tmp2);       
//    }
//   }
//  }  
//  return tmp;
// }

function dom2key( nod ){
 var attr = nod.getAttribute( 'k' );
 if( attr ){
  return attr;
 }
 return false;
}
// - SDXML2Ob - ================================================================

// + SYS + =====================================================================

function toXml(par){
 if(isInt(par)) return par;
 return par.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}

function isInt(s) {
  return (s.toString().search(/^-?[0-9]+$/) == 0);
}

function isArray(arr) {
  return arr.constructor == Array;
}

function doNothing(){}
if( typeof console == 'undefined' ){
 var console = { info:doNothing, error:doNothing, warn:doNothing };
}

function toUrl(par){
 return par.replace(/%/g,'%25').replace(/\+/g,'%2B').replace(/&/g,'%26');
}

// - SYS - =====================================================================

