// IO Wrapper (C).2007 by KjM <kjm@inline.de>
function xrq() {

  // Globale Flags und Settings
  this.ismsie  = 0;
  this.msindex = -1;
  this.connections = new Array();

  // XMLHTTPRequest ist vorhanden
  this.xmlavail = false;
  try {
    var x = new XMLHttpRequest();
    this.xmlavail = true;
  } catch (e) {  }

  // MSIE/Opera Prüfung 
  if (!window.opera && this.xmlavail == false && navigator.userAgent.indexOf("MSIE")!=-1) {
    this.msindex = -1; this.ismsie = 1;

    // XML Library auswählen
    this.picklib = function() {

      // Mögliche Libs
      var l = new Array("Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP");

      // Alle möglichen Libs testen
      for (var i = 0; i < l.length; i++) {
        try {
          var t = new ActiveXObject(l[i]);
          return l[i];
        } catch (e) { }
      }

      // Nichts gefunden
      return null;
    }
  } else if (navigator.userAgent.indexOf("MSIE")!=-1) {
    this.ismsie = -1;
  }

  // Neues Element anhängen od. Existenz prüfen
  this.newconn = function(name) {

    // Datumsobjekt initialisieren
    var d = new Date();

    // Wurde kein Name angegeben, wird eine eindeutige Verbindung erstellt
    var a = new Array((name==null)?d.getTime():name,null,true,null);
    for (var i=0;i<this.connections.length;i++) {
      var c = this.connections[i];
      if (c[0] == a[0]) return null;
    }

    // Neues Element einfügen
    var l = this.connections.length;
    this.connections[l] = a; 
    return l;
  }

  // Neues XHTTP Handle erstellen
  this.gethandle = function() {

    // ID Prüfung
    if (this.ismsie <= 0) return new XMLHttpRequest();

    // XML Lib auswählen
    this.msindex = this.picklib(); 
    if (this.msindex==null) return null;
    return new ActiveXObject(this.msindex);
  }

  // Aktuellen Fehler anzeigen
  this.lasterror = function(id,show) {

    // Existiert dieses Handle
    if (id >= this.connections.length) return null;

    // Fehler anzeigen od. übergeben?
    var e = this.connections[id];
    if (show==null || show==false) return e[3];
    alert((e[3]==null)?"-= Unknown error =-":e[3]);
  }

  // Eine URL Anforderung senden
  this.fetch = function(id,get,url,param,callback,cachable) {

    // Existiert dieses Handle
    if (id >= this.connections.length) return null;

    // Fehlerhafte od. nicht existierende Callback Funktion
    var e = this.connections[id];
    if (callback == null || !callback) {
      e[3] = "Missing or not existend callback entry";
      return null;
    }

    // Dieses Object ist noch im Request
    if (e[2]==false) {
      e[3] = "Object is not ready yet for fetching url '"+url+"'";
      return null;
    }

    // Element suchen
    if (e[1]==null || (this.ismsie==-1 || this.ismsie==1)) 
      e[1] = this.gethandle();
    if (e[1] == null) {
      e[3] = "Unable to get XHTTP handle";
      return null;
    }

    // Zeitobjekt initialisieren
    var d = new Date();

    // Callback Funktion registrieren
    try {
      e[1].onreadystatechange = callback;
    } catch (x) { 
      e[3] = "Unable to register callback function";
      return null;
    }

    // GET oder POST vorbereiten
    if (get) {
      try {
        e[2] = false;
        e[1].open("GET",url+"?t="+((cachable==null || cachable==false)?d.getTime():"")+"&"+((param==null)?"":param),true); 
        e[1].send(null);
        return true;
      } catch (x) {
        e[3] = "Unable to fetch data via HTTP GET";
        return null;
      }
    } else {
      try {
        e[2] = false;
        e[1].open("POST",url,true); 
        e[1].setRequestHeader("Method","POST "+url+" HTTP/1.1");
        e[1].setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        e[1].send(param);
        return true;
      } catch (x) {
        e[3] = "Unable to fetch data via HTTP POST";
        return null;
      }
    }
  }

  // Request abbrechen
  this.abort = function(id) {
  
    // Diesen Handler gibt es nicht!
    if (id >= this.connections.length) return null;

    var e = this.connections[id];
    if (e[1] == null || e[2]==true) return;
    e[1].abort();
    
    // ReInit für die MSIE Variante
    if (this.ismsie == 1) e[1] = new ActiveXObject(this.msindex);
    else if (this.msie == -1) e[1] = new XMLHttpRequest();
    e[2] = true; e[3] = null;
  }

  // Dieser Handler kann einen neuen Request ausführen?
  this.isready = function(id) {

    // Diesen Handler gibt es nicht!
    if (id >= this.connections.length) return null;

    var e = this.connections[id];
    return e[2];
  }

  // Request wurde bearbeitet und steht zur Verfügung?
  this.isfetched = function(id) {

    // Connection ID prüfen
    if (id >= this.connections.length) return null;

    // Übertragung ist abgeschlossen?
    var e = this.connections[id];
    if (e[1] == null) {
      e[3] = "No known XHTTP handler for this object";
      return null;
    }

    // Es wird nur TRUE übergeben wenn das Element sich auch
    // innerhalb eines Requests befindet und readyState gesetzt ist
    return (e[1].readyState == 4 && e[2]==false)?true:false;
  }

  // Webserver Statuscode auslesen
  this.httpresponse = function(id) {

    // ID prüfen
    if (id >= this.connections.length) return null;
    var e = this.connections[id];
    if (e[1] == null) {
      e[3] = "No known XHTTP handler for this object";
      return null;
    }
    return (e[1]==null)?0:e[1].status;
  }

  // Ergebnis des Requests als XML od. TEXT ausgeben
  this.getresponse = function(id,astext) {

    // ID prüfen
    if (id >= this.connections.length) return null;
    var e = this.connections[id];
    if (e[1] == null) {
      e[3] = "No known XHTTP handler for this object";
      return null;
    }

    // Text oder XML Ausgabe
    var r = (astext!=null && astext==true)?e[1].responseText:e[1].responseXML;

    // ReInit für die MSIE Variante
    if (this.ismsie == 1) e[1] = new ActiveXObject(this.msindex);
    else if (this.msie == -1) e[1] = new XMLHttpRequest();
    e[2] = true; e[3] = null;
    return r;
  }

  // Aktueller Verbindungsstatus
  return true;
}

