Suche

lichtschattenblog

Monat

Dezember 2015

Citrix XenApp 6.0 – Vorblenden von Anmeldeinformationen

Standardmäßig ist es bei Citrix XenApp 6.0 nicht möglich, Anmeldedaten von Benutzern vorzublenden. Eine mögliche Lösung ist hierbei die Abfrage von Client-Namen via DNS Reverse Lookup Zone und Ermittlung von Username via ActiveX-Unterstützung unter Windows. Bei der Lösung wird ein Windows Server 2008R2 mit IIS und aspx-Dateien verwendet. Über die aspx-Dateien werden diverse js-Dateien eingebunden. Hier empfiehlt sich ggf. die Verwendung von festen IPs von Thin Clients auf Linux-Basis. Bei Clients unter Windows muss Active X-Unterstützung für den Web Browser und dem jeweils verwendeten Server/URL-Pfad aktiviert sein. Zusätzlich besteht die Möglichkeit zur Verwendung von URL-Parametern, wobei dies nicht besonders elegant ist.

Ganz wichtig: Unbedingt die Originale login.js sichern. Jeder Fehler sorgt dafür, dass die gesamte Anmeldung nicht mehr möglich ist.

Ich übernehme keine Verantwortung für eventuelle Probleme.

Im Verzeichnis inetpub\wwwroot\Citrix\XenApp\auth\clientscripts des Servers, für die Verwaltung der Sitzungen, befindet sich die Datei login.js mit folgender Funktion onLoadLayout (Zeile 81 bis 104).

function onLoadLayout() {
    <% // Properly display the login button if high contrast mode is enabled. %>
    maintainAccessibility("LoginButton");

    var frame = getTopFrame(window);
    if (frame != null) {
        frame.location.href = "<%=Constants.PAGE_LOGGEDOUT%>";
        return false;
    }

    var form = document.forms[0];
    if (form) {
        setFocus(form);
<% // ensure that the domain is greyed out if appropriate %>
        onUsernameTextEntry(form);
    }

    var accountSSlink = document.getElementById("<%=Constants.ID_ACCOUNTSS%>");

    if (accountSSlink != null) {
        showAccountSelfServiceIfEnabled(accountSSlink);
    }
    return;
}

Diese Datei können wir über entsprechend notwendige Funktionen erweitern (einfach oberhalb der Funktion onLoadLayout):

function onLoadLayout_loginextension () {

    clientIP = '<%= Request.ServerVariables["REMOTE_ADDR"]%>';

    try {
    
        //Pruefe auf Variablen Computername, Clientname, Username via ActiveX - Voraussetzung: Windows-Client mit Browser-Unterstützung fuer Active X-Elemente
        
        WshShell = new ActiveXObject("WScript.Shell");
        ComputerName = WshShell.ExpandEnvironmentStrings("%computername%");
        ClientName = WshShell.ExpandEnvironmentStrings("%clientname%");
        UserName = WshShell.ExpandEnvironmentStrings("%username%");

        // Pruefe auf Computer beginnend auf Name "pc-" und verwende diesen, sonst verwende Username
        if (ComputerName.toLowerCase().substring(0,3) == "pc-") {
            document.forms[0].<%=Constants.ID_USER%>.value = ComputerName;
            } else { document.forms[0].<%=Constants.ID_USER%>.value = UserName; }

        } catch (e) {

            //Wenn nicht erfolgreich über Active X, dann frage DNS des Servers ab
        
            clientUserName = '';

            try {

            //Abfrage Variable HostName bzw IP-Adresse
            clientDNS = '<%=""+System.Net.Dns.GetHostEntry(Convert.ToString(Request.ServerVariables["remote_addr"])).HostName%>';
            clientDNSParts = clientDNS.split (".");
            clientUserName = clientDNSParts[0];
            
            //Beispiel: Pruefe auf IP4-Netzwerk beginnend mit 192, dann verwende '',
            //Sonst pruefe auf DNS-Clientname test, dann verwende '',
            //Sonst pruefe auf DNS-Clientname beginnend "pc-", dann verwende ''
            
            if (clientUserName == "192") {clientUserName = ''}
                else if (clientUserName.toLowerCase() == "test") {clientUserName = ''}
                    else if (clientUserName.toLowerCase().substring(0,3) == "pc-") {clientUserName = ''}
            } catch (e) {}

            document.forms[0].<%=Constants.ID_USER%>.value = clientUserName;
    
        }

    }

Innerhalb der Funktion onLoadLayout_loginextension wird über

document.forms[0].<%=Constants.ID_USER%>.value = ...

die Zuweisung innerhalb der aspx-Datei durchgeführt. Zusätzlich wird in der Funktion onLoadLayout zu Beginn:

onLoadLayout_loginextension ();

eingefügt.

XenApp_loginjs_01

Die zusätzliche Zeile

clientIP += '<%= Request.ServerVariables["REMOTE_ADDR"]%>';

dient für weitere mögliche Auswertungen auf Basis der IP-Adresse, zum Beispiel, damit bei lokalem Zugriff auf den Server, die Funktion nicht verwendet wird. Diese kann in der Funktion onLoadLayout entfallen. Beispiel bei Verwendung:

if (clientIP == '192.1.2.3') {clientUserName = 'administrator';}

Anmerkung:

clientIP += '<%= Request.ServerVariables["REMOTE_HOST"]%>';

funktioniert nicht.

Wenn jetzt jedoch, zum Beispiel weil der Client kein Active X unterstützt und die IP dynamisch vergeben wird oder andere Probleme vorliegen, besteht die Möglichkeit den Usernamen als Variable zum Auruf zu übergeben. Voraussetzung ist die Verwendung des Aufrufs über:

http://servername/Citrix/XenApp/auth/login.aspx?username=test12345

und dass die login.js statt der oben aufgeführten Funktion onLoadLayout_loginextension um die folgenden erweitert wird. Der Aufruf muss auch hier, wie beschrieben, über die Funktion onLoadLayout erfolgen.

function getUrlVars_loginextension()
{
    //Lese alle URL-Parameter in ein Array
    
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    
    return vars;

}

function createCookie_loginextension(name,value,seconds) {

    //Erzeuge ein Cookie mit ausreichender Lebenszeit

    if (seconds) {
        var date = new Date();
        date.setTime(date.getTime()+(seconds*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie_loginextension(name) {

    //Lese das Cookie aus

    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function onLoadLayout_loginextension () {

    clientIP = '<%= Request.ServerVariables["REMOTE_ADDR"]%>';
    
    var UrlVar_UserName = ''
        
    //Lese Cookie aus
    COOKIE_USERNAME = 'loginextension_username'
    var CookieUserName = readCookie_loginextension(COOKIE_USERNAME)
    if (CookieUserName) {
        UrlVar_UserName = CookieUserName;
    }
    
    //Wenn URL-Parameter username uebergeben wurde, dann lese diesen und schreibe ihn in das Cookie
    var UrlVars = getUrlVars_loginextension()
    if ('username' in UrlVars) {
        UrlVar_UserName = UrlVars["username"].toString();
        createCookie_loginextension(COOKIE_USERNAME,UrlVar_UserName,300);
        }

    try {
    
        //Pruefe auf Variablen Computername, Clientname, Username via ActiveX - Voraussetzung: Windows-Client mit Browser-Unterstützung fuer Active X-Elemente
        
        WshShell = new ActiveXObject("WScript.Shell");
        ComputerName = WshShell.ExpandEnvironmentStrings("%computername%");
        ClientName = WshShell.ExpandEnvironmentStrings("%clientname%");
        UserName = WshShell.ExpandEnvironmentStrings("%username%");

        // Pruefe auf Computer beginnend auf Name "pc-" und verwende diesen, sonst verwende Username
        if (ComputerName.toLowerCase().substring(0,3) == "pc-") {
            document.forms[0].<%=Constants.ID_USER%>.value = ComputerName;
            } else { document.forms[0].<%=Constants.ID_USER%>.value = UserName; }

        } catch (e) {

            //Wenn nicht erfolgreich über Active X, dann frage DNS des Servers ab
        
            clientUserName = '';

            try {

            //Abfrage Variable HostName bzw IP-Adresse
            clientDNS = '<%=""+System.Net.Dns.GetHostEntry(Convert.ToString(Request.ServerVariables["remote_addr"])).HostName%>';
            clientDNSParts = clientDNS.split (".");
            clientUserName = clientDNSParts[0];
            
            //Beispiel: Pruefe auf IP4-Netzwerk beginnend mit 192, dann verwende '',
            //Sonst pruefe auf DNS-Clientname test, dann verwende '',
            //Sonst pruefe auf DNS-Clientname beginnend "pc-", dann verwende ''
            
            if (clientUserName == "192") {clientUserName = ''}
                else if (clientUserName.toLowerCase() == "test") {clientUserName = ''}
                    else if (clientUserName.toLowerCase().substring(0,3) == "pc-") {clientUserName = ''}
            } catch (e) {}

            document.forms[0].<%=Constants.ID_USER%>.value = clientUserName;
    
        }
    
    //Wenn UrlVar_UserName durch Parameteruebergabe oder Auslesen des Cookie vorliegt, dann verwende diesen (alle Werte davor werden ueberschrieben)
    if (UrlVar_UserName != '') {
        document.forms[0].<%=Constants.ID_USER%>.value = UrlVar_UserName;
        }

    }

Die Variante über Cookies ist nicht besonders elegant, jedoch hatte ich keine Lösung gefunden, wie die Parameter sonst übergeben werden können, da immer mehrere Skripte für ClientDetection etc. ausgeführt werden und die entsprechenden Parameter immer erneut übergeben werden müssen.

Im Ergebnis sieht es dann in etwa so aus:

XenApp_loginjs_02

 

 

 

HTML5 und JavaScript – Lesen von Dateien mit ANSI-Kodierung und Umlaute im Text

Beim Lesen von Dateien über die FileReader-Methode via HTML5 und JavaScript kann es vorkommen, dass die zu lesende und auszugebende Datei Umlaute enthält und die Datei ANSI kodiert ist. Mit folgendem kurzen Code für eine HTML-Datei und einem Browser mit HTML5-Support wird die Darstellung korrekt durchgeführt.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8"/>
</head>
<body>

<input type="file" id="files" name="files[]" />
<p>
<output id="filecontent"></output>



    function handleFileSelect(evt) {

        var files = evt.target.files;
        file = files[0];

    var fileReader = new FileReader();
    
    fileReader.addEventListener("load", function(event) {

        var textFile = event.target;
        fileContent = textFile.result;
        lines = fileContent.split('\n');
        
        document.getElementById('filecontent').innerHTML = '' + lines.join('
') + '';         });          fileReader.readAsText(file, 'windows-1252');          }     document.getElementById('files').addEventListener('change', handleFileSelect, false);   </body> </html>

Kurzinfo zum Code:

  • Lesen einer ANSI kodierten Datei
    fileReader.readAsText(file, 'windows-1252');
  • Der Code
    fileReader.addEventListener

    wird erst aktiv, wenn die Datei vollständig gelesen wurde

  • Unterstützung der Kodierung für deutsche Zeichen aktivieren
    <html lang="de">
    ...
    <meta charset="utf-8"/>

Sofern zusätzlich Dateiinformationen benötigt werden:

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8"/>
</head>
<body>

<input type="file" id="files" name="files[]" />

<output id="fileinfo"></output>
<output id="filecontent"></output>



    function handleFileSelect(evt) {

        var files = evt.target.files;
        file = files[0];

        fileInfo = 'file name: ' + escape(file.name) + ', file type: ' + file.type + ', file size: ' + file.size + ' bytes, last modified: ' + file.lastModifiedDate.toLocaleDateString();
        
    var fileReader = new FileReader();
    
    fileReader.addEventListener("load", function(event) {

        var textFile = event.target;
        fileContent = textFile.result;
        lines = fileContent.split('\n');
        
        document.getElementById('filecontent').innerHTML = '' + lines.join('
') + '';         });          fileReader.readAsText(file, 'windows-1252');          document.getElementById('fileinfo').innerHTML = '
    ' + fileInfo + '
';     }     document.getElementById('files').addEventListener('change', handleFileSelect, false);   </body> </html>

Beispiel-Ausgabe:

htmlcode01

 

Lustiges im Internet

  • Sie haben das Internet kaputt gemacht
    lustig01
    Gesehen Dezember 2015

Notepad++ – Löschen von doppelten Zeilen in Textdatei

Wer hin und wieder Dateien mit sehr vielen Einträgen hat und doppelte Einträge bei Bedarf löschen muss, kann dies mittels Notepad++ durchführen.

Hierzu über Erweiterungen -> Plugin Manager -> Show Plugin Manager den Plugin Manager öffnen. Im Aktenreiter Available TextFX Character, bzw. TextFX auswählen, installieren und Notepad++ neu starten.

notepadplusplus01

Nach dem Neustart gibt es im Notepad++ einen neuen Menüpunkt TextFX. In diesem Menüpunkt müssen folgende Elemente aktiviert werden:

  • TextFX -> TextFX Tools -> +Sort ascending
  • TextFX -> TextFX Tools -> +Sort outputs only UNIQUE (at column) lines

Anschließend mittels TextFX -> TextFX Tools -> Sort lines case sensitive (at column) alle doppelte Einträge löschen.

notepadplusplus02

Sollten zusätzlich Leerzeilen vorliegen, können diese über Bearbeiten -> Zeilenoperationen -> Leerzeilen (auch mit Whitespace) löschen, entfernt werden.

notepadplusplus03

Erstelle kostenlos eine Website oder ein Blog auf WordPress.com.

Nach oben ↑