JaVa ScriPt Panic

Manchmal wenn besonders viele- besonders Intelligente Menschen sich zusammen finden, kommen unglaublich komplizierte Lösungen heraus. Sicherheitskonzepte im Web Umfeld hinterlassen manchmal diesen Eindruck. Doch der Reihe nach.

Immer wenn ich Panic habe, brauche ich einen Knopf, den Panic Button. Auf allen Devices, natürlich im Browser. Auch wenn im Flugzeug (Airline Modus) muss im Falle eines Absturzes oder geringerer Übel jederzeit Panic möglich sein. Folgendes wohl Designtes UI als Frontend.

image

Am anderen Ende wartet ein Service meine Panic entgegen zu nehmen. Da mein Leben von Pragmatismus geprägt wird, einfach als entkernte ASPX Seite. Der Service nimmt die Parameter User, Computer Name und Datum entgegen und speichert dies in einer Datei.

   1:  <%@ Page Language="VB" AutoEventWireup="false" Theme="" %>
   2:   
   3:  <%@ Import Namespace="System.IO" %>
   4:   
   5:   
   6:  <script runat="server">
   7:      Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
   8:          If Request.QueryString("u") <> "" Then
   9:              File.AppendAllText(HttpContext.Current.Server.MapPath(
  10:                                "app_data/panic.txt"), Request.QueryString("u") +
  11:                                    "," + Request.QueryString("c") +
  12:                                    "," + Request.QueryString("d") +
  13:                                Environment.NewLine)
  14:              Response.AppendHeader("Access-Control-Allow-Origin", "*")
  15:              Response.StatusCode = "200"
  16:          Else
  17:              Response.StatusCode = "420"
  18:          End If
  19:      End Sub
  20:  </script>

Wie kommt man nun an den angemeldeten Benutzer bei einer Browser Anwendung? Gar nicht. Nur der Internet Explorer unterstützt die Verwendung von ActiveX Komponenten  die die nötige Information liefern.

   1:  var ws = new ActiveXObject("wscript.shell");
   2:  var username = ws.ExpandEnvironmentStrings("%username%");
   3:  var network = new ActiveXObject('WScript.Network');
   4:  var computer = (network.computerName);

So was funktioniert unter Umständen im IISExpress auf Localhost. Spätestens wenn die Seite im Web liegt, wird es Fehlermeldungen hageln ala

Can not create object Active X
Fehler: Automatisierungsserver kann Objekt nicht erstellen.

Die guten Rechte. Die Website muss der als “Vertraut” vom Benutzer hinzugefügt werden.

image

Und dort müssen die Rechte entsprechend konfiguriert werden. Außerdem muss die Site per https abgerufen werden können, weil sonst wird das mit dem hinzufügen zu den vertrauenswürdigen Sites nicht.

image

Aus irgendeinem unbekannten Grund läuft die Webseite auf dem Server im IE Kompatibilitätsmodus, so das urplötzlich Teile der verwendeten JavaScript Syntax nicht mehr funktionieren.

Das Objekt unterstützt die Eigenschaft oder Methode "addEventListener" nicht  

Abhilfe für IE 11 schafft ein Meta Element.

   1:    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

Fühlst Du schon Panic aufkommen? Nein- dann noch mehr.

Um das “oh wir stürzen ab und werden alle sterben” offline Szenario abzudecken, werden die Daten in den HTML5 localstorage gelegt. Da hat man so ca 5-10MB Platz. So genau weis man das nie. Wer mehrere Abstürze überlebt, speichert dann ein Array von JSON Objekten abgelegt (Zeile 13). Vorher muss man allerdings sich erst ein Datum zusammenstöpseln. Mangels Format Funktion muss man den Typ zusammen bauen. Wie allgemein üblich ist der Monat 0 Januar (oder Jänner) und führende Nullen bei einstelligen Werten gibt es auch nur nach Handarbeit. Zeile 9 und 10 –>Panic.

   1:    function clickme() {
   2:              
   3:              var ws = new ActiveXObject("wscript.shell");
   4:              var username = ws.ExpandEnvironmentStrings("%username%");
   5:              var network = new ActiveXObject('WScript.Network');
   6:              var computer = (network.computerName);
   7:              var d = new Date();
   8:              var log = {};
   9:              log.datum = d.getFullYear() + ":" + (d.getMonth() + 1) + ":" 
+ d.getDate() +
  10:                  ":" + d.getHours() + ":" + d.getMinutes();
  11:              log.username = username;
  12:              log.computer = computer;
  13:              localStorage.setItem("lastpanic", d.toGMTString());
  14:              if (navigator.onLine == true) {
  15:                  var xhr2 = new XMLHttpRequest();
  16:                  xhr2.open('GET',
  17: 'https://www.ppedv.de/panic.aspx?u=' + log.username + "&c=" + log.computer + 
"&d=" + log.datum);
  18:                  xhr2.onload = function (e) {
  19:                      if (this.status != 200) {
  20:                          localStorage.setItem("data", 
localStorage.getItem("data") + "," + JSON.stringify(log));
  21:                      }
  22:   
  23:                  }
  24:                  document.getElementById('lastpanic').innerHTML = d.getUTCDate;
  25:                  xhr2.send();
  26:              }
  27:              else {
  28:                  localStorage.setItem("data", localStorage.getItem("data") +
"," + JSON.stringify(log));
  29:              }
  30:   
  31:   
  32:   
  33:          }

In Zeile 14 wird der Offline Fall geprüft. Um die HTML Datei offline auch gespeichert zu bekommen, haben die genialen HTML5 Geister das Application Caching erfunden. Erst muss man eine Datei anlegen, die üblicherweise auf appcache endet. Zeile 5 wird später noch relevant.

   1:  CACHE MANIFEST
   2:  alarm.html
   3:  htmlpage.html
   4:   
   5:  NETWORK:
   6:  *

Dann muss der Content Type passend im IIS angelegt werden.

   1:  <system.webServer>
   2:      <staticContent>
   3:            <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest"/>   
   4:      </staticContent>
   5:    </system.webServer>

Wer bisher noch nicht laut schreiend aus dem Fenster gesprungen ist, darf weiterlesen. Alle anderen einfach mehrfach auf Panic clicken.

Im HTML Teil wird dann das Cache Manifest referenziert.

   1:  <!DOCTYPE html>
   2:  <html  manifest="panic.appcache">

Wie war das mit Zeile 5? Wenn dieser Eintrag fehlt, dann wird vom Browser der XMLHTTPRequest abgebrochen in der Send() (Zeile 25) Methode. Daran habe ich 3 Stunden gesucht. Die Fehlermeldung sind ähnlich vielsagend wie Simplified Chinese mit einem Sin Hala Character Set.

Wie sieht das dann im Browser aus? Einfach F12 drücken

image

Natürlich nur im Internet Explorer und auch nur in einer Version so ab 10 und nur https und nur wenn die Rechte alle 100% passen.

Um den offline Fall abzuhandeln, kann man sich an das Event für Online oder Offline hängen und auch den Status über das Navigator Objekt auslesen.

   1:   document.getElementById('status').innerHTML = 
navigator.onLine ? 'online' : 'offline';
   2:          document.getElementById('lastpanic').innerHTML = 
localStorage.getItem("lastpanic");
   3:   
   4:   
   5:          window.addEventListener("online", function (e) {
   6:              localStorage.setItem("data", "");
   7:          }, false);

 

image

Das funktioniert bei mir aber nur solange ich den Browser nicht schließe. Warum auch immer.

Das gleiche Szenario hatte ich vor Jahren in 10-15 Minuten zuverlässig übrigens mit Silverlight gebaut. Ganz ohne Panik.

Kommentare sind geschlossen