MediaWiki:Common.js: Unterschied zwischen den Versionen

Aus IT.S-Wiki
Wechseln zu: Navigation, Suche
(USS: trim strings before checking and submission)
(Spam-Hinweis hinzugefügt)
 
Zeile 226: Zeile 226:
 
         'en': 'Processing your request...',
 
         'en': 'Processing your request...',
 
         'de': 'Ihre Anfrage wird bearbeitet...'
 
         'de': 'Ihre Anfrage wird bearbeitet...'
 +
      },
 +
    'hint_recovery_email_sent': {
 +
        'en': 'Note that message delivery might take several minutes. Please check your spam folder, too, before contacting IT.Services.',
 +
        'de': 'Die Zustellung dieser E-Mail kann ein paar Minuten in Anspruch nehmen. Überprüfen Sie bitte auch Ihren Spam-Ordner bevor Sie sich an IT.Services wenden.'
 
       },
 
       },
 
     'hint_try_again_later': {
 
     'hint_try_again_later': {
Zeile 886: Zeile 890:
 
         form.innerHTML = '\
 
         form.innerHTML = '\
 
                 <div style="width: 100%; margin-top: 1em;">' + ussTranslations.msg_recovery_email_sent[language] + '</div>\
 
                 <div style="width: 100%; margin-top: 1em;">' + ussTranslations.msg_recovery_email_sent[language] + '</div>\
 +
                <div style="width: 100%; margin-top: 1em;">' + ussTranslations.hint_recovery_email_sent[language] + '</div>\
 
                 <div style="width: 100%; text-align: right; margin-top: 1em;">\
 
                 <div style="width: 100%; text-align: right; margin-top: 1em;">\
 
                     <input type="button" value="' + ussTranslations.btn_next[language] + '" onclick="ussSetPasswordPage(\'' + language + '\')">\
 
                     <input type="button" value="' + ussTranslations.btn_next[language] + '" onclick="ussSetPasswordPage(\'' + language + '\')">\

Aktuelle Version vom 10. Oktober 2019, 17:38 Uhr

/* Any JavaScript here will be loaded for all users on every page load. */


function sophosShowError(msg, clr) {
    var errstr = document.getElementById('sophos-password-error');
    if( errstr ) {
        errstr.innerHTML = msg;
        errstr.style.backgroundColor = clr;
    } else {
        console.log('Error: Unable to display error message "' + msg + '".');
    }

    var overlay = document.getElementById('sophos-password-overlay');
    if( overlay ) {
        overlay.style.display = 'none';
    }
}

function sophosSubmitCredentialsRequest() {
    var overlay = document.getElementById('sophos-password-overlay');
    if( overlay ) {
        overlay.style.display = 'flex';
    }

    var username = document.getElementById('sophos-password-username').value;
    if( !username ) {
        sophosShowError('Bitte geben Sie Ihren Benutzernamen ein.', 'red');
        return false;
    }

    var captcha = document.getElementById('sophos-password-captcha').value;
    if( !captcha || (captcha.length != 6) ) {
        sophosShowError('Bitte geben Sie die obigen sechs Buchstaben ein.', 'red');
        return false;
    }

    var data = new FormData();
    data.append('username', username);
    data.append('captcha', captcha);

    var request = new XMLHttpRequest();
    request.open('POST', 'https://su2.dhbw-loerrach.de/api/credentials/request');
    request.withCredentials = true;
    request.onreadystatechange = function()  {
        if( this.readyState === XMLHttpRequest.DONE ) {
            switch( this.status ) {
            case 200:
                sophosShowError('Eine E-Mail mit Ihren Zugangsdaten wurde erfolgreich versandt.', 'green');
                break;
            case 400:
                sophosShowError('Bitte geben Sie Ihren Benutzernamen ein.', 'red');
                break;
            case 403:
                sophosShowError('Bitte versuchen Sie erneut, die obigen sechs Buchstaben einzugeben.', 'red');
                break;
            default:
                sophosShowError('Ihre Anfrage konnte nicht übermittelt werden.', 'red');
            }
        }
    }
    request.send(data);

    return false;
}


var ussPublicKey = {
    e: "AQAB",
    kid: "D279A_nnBS5T_WvE4yVv4uoxkQqAkQ6ZapRdhJcxaPQ",
    kty: "RSA",
    n: "5Fpb4HByjJaOb_KeQ2QnC6AIujF3yoPppURWsIJPN9dn7AL3aO4acgF23P3OSwtK6RA4d1jJ44J48xeoBIAqH8fzT3y1Avs5oiWBonT309YGc9eE-bx7p47rS7o9gD9boxB7s4DlNmjcq6cWDT2b3OHGD76v3ltN_JYI_SPAWv2Y7d1QWwsQXDayehChoHKy52v1yISBVae6dRwB3A-Sqlb9gCPEGLGT6Bx60KGBL-YHuB-P5KH9aHFQlWryV4T2B5Tz70oDPoO4YFPRta1gYsYzbW8TwYmODKehqaCrRdFbVCuI4-UIPzM4Jbww0hssEHJewLvIQKvFKriTXzQUvQqrI8ZOEY21E65pO1MijrgnMiAtgMBFwobHdKhOuYuzb0IQF6HIA_ukeE0tjhEAWmyCIQSUmLhUwA4tZxlOwvONuGN-ie9tr6_NEJQkFOyCSkL-xaOIeTpSr2pdIh4GQ-mtsMcQNKtxZGmOaF-RvFkT7V_Bvz4IpjrBKkJZg5Hjp6KRGm1Uu2Yt4cvySLFjJJV9_sk8yn7PGy8VNKsh3yfenKDGU3qU3xtjSxBFS0hHPnilYbwQe7VDuQd-DZDWTN1kh9IPEOIxs0VeRpAT0sJXN1xVnLCfe30vTMRoG9Gw9SFC_0xqdRAdLG_fx7VUm5_W84TS7o0VRR7bwdIqqkc"
  };


var ussUrlTermsOfService = 'https://www.dhbw-loerrach.de/fileadmin/dh_upload/itservices/downloads/Benutzungsordnung_IT-Infrastruktur_Lehre.pdf';
var ussUrlApi = 'https://uss.dhbw-loerrach.de/api';


var ussLanguages = [
    {'tag': 'de', 'label': 'Deutsch'},
    {'tag': 'en', 'label': 'English'}
  ];

var ussTranslations = {
    'btn_cancel': {
        'en': 'Cancel',
        'de': 'Abbruch'
      },
    'btn_done': {
        'en': 'Done',
        'de': 'Fertig'
      },
    'btn_new_image': {
        'en': 'New Image',
        'de': 'Neues Bild'
      },
    'btn_next': {
        'en': 'Next',
        'de': 'Weiter'
      },
    'error_already_activated': {
        'en': 'Your DHBW account has already been activated.',
        'de': 'Ihr DHBW Konto wurde bereits aktiviert.'
      },
    'error_in_ascii_encoding': {
        'en': 'Your data cannot be transmitted in ASCII.',
        'de': 'Ihre Daten können in ASCII übertragen werden.'
      },
    'error_in_encryption': {
        'en': 'Your data could not be encrypted properly.',
        'de': 'Beim Verschlüsseln der Daten ist ein Fehler aufgetreten.'
      },
    'error_internal_error': {
        'en': 'Your request could not be processed.',
        'de': 'Ihre Anfrage konnte nicht verarbeitet werden.'
      },
    'error_invalid_recovery_code': {
        'en': 'Please enter the recovery code you received via email.',
        'de': 'Bitte geben Sie den Wiederherstellungscode ein, den Sie per E-Mail erhalten haben.'
      },
    'error_invalid_credentials': {
        'en': 'The user credentials are not valid.',
        'de': 'Die Login-Daten sind ungültig.'
      },
    'error_invalid_email': {
        'en:': 'Please enter a valid email address.',
        'de': 'Bitte geben Sie eine gültige E-Mail Adresse ein.'
      },
    'error_invalid_password': {
        'en': 'The new password does not follow the guidelines mentioned above.',
        'de': 'Das neue Passwort entspricht nicht den o.g. Vorgaben.'
      },
    'error_pwned_password': {
        'en': 'The new password is contained in the "have i been pwned?" list.',
        'de': 'Das neue Passwort ist in der "have i been pwned?" Liste enthalten.'
      },
    'error_invalid_password_chars': {
        'en': 'Your new password contains illegal characters.',
        'de': 'Das neue Passwort enthält ungültige Zeichen.'
      },
    'error_missing_captcha': {
        'en': 'Please enter the six letters from the picture above.',
        'de': 'Bitte geben Sie die obigen sechs Buchstaben ein.'
      },
    'error_missing_activation_code': {
        'en': 'Please enter your activation code. You will find it on the Document you have recieved from IT.Services.',
        'de': 'Bitte geben Sie das Aktivierungskennwort ein, das Sie auf dem Informationsschreiben von IT.Services erhalten haben.'
      },
    'error_missing_id': {
        'en': 'Please provide your personal identification number.',
        'de': 'Bitte geben Sie Ihr Matrikel- oder Personalnummer ein.'
      },
    'error_missing_new_email': {
        'en': 'Please enter a private email address.',
        'de': 'Bitte geben Sie eine private E-Mail Adresse ein.'
      },
    'error_missing_new_password': {
        'en': 'Please provide a new password.',
        'de': 'Bitte geben Sie ein neues Passwort ein.'
      },
    'error_missing_password': {
        'en': 'Please enter your current DHBW password.',
        'de': 'Bitte geben Sie Ihr aktuelles DHBW Passwort ein.'
      },
    'error_missing_password_chars': {
        'en': 'Your new password does not contain all required character types.',
        'de': 'Das neue Passwort enthält nicht alle geforderten Zeichentypen.'
      },
    'error_missing_username': {
        'en': 'Please enter your username.',
        'de': 'Bitte geben Sie einen Benutzernamen an.'
      },
    'error_must_accept_terms_of_use': {
        'en': 'You have to accept the terms of use for the IT infrastructore of the DHBW Lörrach to activate your account.',
        'de': 'Sie müssen die Benutzungsordung für die IT-Infrastuktur der DHBW Lörrach akzeptieren, um Ihr Konto zu aktivieren.'
      },
    'error_no_permission': {
        'en': 'You do not have permission to use the User Self Service.',
        'de': 'Sie sind nicht berechtigt, den User Self Service zu verwenden.'
      },
    'error_password_contains_username': {
        'en': 'The new password contains your username.',
        'de': 'Das neue Passwort enthält den Benutzernamen.'
      },
    'error_repeat_new_email': {
        'en': 'You did not repeat your private email address correctly. Please type both copies again.',
        'de': 'Die neue E-Mail Adresse und ihre Wiederholung stimmen nicht überein. Bitte geben Sie beides erneut ein.'
      },
    'error_repeat_new_password': {
        'en': 'You did not repeat your new password correctly. Please type both copies again.',
        'de': 'Das neue Passwort und seine Wiederholung stimmen nicht überein. Bitte geben Sie beides erneut ein.'
      },
    'error_request_gone': {
        'en': 'The status of your request could not be determined.',
        'de': 'Der Status Ihrer Anfrage konnte nicht ermittelt werden.'
      },
    'error_transmission_failed': {
        'en': 'Your request could not be transmitted.',
        'de': 'Ihre Anfrage konnte nicht übermittelt werden.'
      },
    'error_too_frequent_use': {
        'en': 'Access to your DHBW account can only be recovered once a day.',
        'de': 'Die Wiederherstellung Ihres Zugangs oder das Setzen Ihrer privaten E-Mail Adresse ist nur einmal täglich möglich.'
      },
    'error_wrong_captcha': {
        'en': 'Please reenter the six letters from the picture above.',
        'de': 'Bitte geben Sie die obigen sechs Buchstaben erneut ein.'
      },
    'hint_already_activated': {
        'en': 'If you did not activate the account yourself, please contact IT.Services (<a href="mailto:helpdesk@dhbw-loerrach.de">helpdesk@dhbw-loerrach.de</a>).',
        'de': 'Falls Sie Ihr Konto nicht selbst aktiviert haben, wenden Sie sich bitte an IT.Services (<a href="mailto:helpdesk@dhbw-loerrach.de">helpdesk@dhbw-loerrach.de</a>).'
      },
    'hint_confirmation_email_sent': {
        'en': 'A confirmation email has been sent to the email adress you provided.',
        'de': 'Zur Bestätigung wurde eine E-Mail an die von Ihnen hinterlegte Adresse gesandt.'
      },
    'hint_contact_its': {
        'en': 'Please contact IT.Services (<a href="mailto:helpdesk@dhbw-loerrach.de">helpdesk@dhbw-loerrach.de</a>).',
        'de': 'Bitte wenden Sie sich an IT.Services (<a href="mailto:helpdesk@dhbw-loerrach.de">helpdesk@dhbw-loerrach.de</a>).'
      },
    'hint_guard_private_mailbox': {
        'en': 'Please notice that anyone with access to this mail box can reset the password to your DHBW account.',
        'de': 'Bitte beachten Sie, dass jede Person, die Zugriff auf dieses Postfach hat, Ihr DHBW Passwort zurücksetzen kann.'
      },
    'hint_processing_request': {
        'en': 'Processing your request...',
        'de': 'Ihre Anfrage wird bearbeitet...'
      },
    'hint_recovery_email_sent': {
        'en': 'Note that message delivery might take several minutes. Please check your spam folder, too, before contacting IT.Services.',
        'de': 'Die Zustellung dieser E-Mail kann ein paar Minuten in Anspruch nehmen. Überprüfen Sie bitte auch Ihren Spam-Ordner bevor Sie sich an IT.Services wenden.'
      },
    'hint_try_again_later': {
        'en': 'Please try again later.',
        'de': 'Bitte versuchen Sie es später erneut.'
      },
    'hint_update_devices': {
        'en': 'If the password is stored in your devices, please update these soon to avoid being locked out of your account.',
        'de': 'Wenn Sie das Passwort in Ihren Geräten speichern, denken Sie bitte daran dieses zeitnah anzupassen um eine Sperrung Ihres Kontos zu verhindern.'
      },
    'label_accept_terms': {
        'en': 'I have read the <a href="' + ussUrlTermsOfService + '" target="_blank">terms of use for the IT infrastucture of the DHBW Lörrach</a> and accept these.',
        'de': 'Ich habe die <a href="' + ussUrlTermsOfService + '" target="_blank">Benutzungsordnung für die IT-Infrastruktur der DHBW Lörrach</a> gelesen und akzeptiere diese.'
      },
    'label_activation_code': {
        'en': 'Activation code',
        'de': 'Aktivierungskennwort'
      },
    'label_password': {
        'en': 'DHBW Password',
        'de': 'DHBW Passwort'
      },
    'label_new_email': {
        'en': 'Private email address',
        'de': 'Private E-Mail Adresse'
      },
    'label_new_password': {
        'en': 'New DHBW Password',
        'de': 'Neues DHBW Passwort'
      },
    'label_recovery_code': {
        'en': 'Recovery code',
        'de': 'Wiederherstellungscode'
      },
    'label_repeat_email': {
        'en': 'Repeat private email address',
        'de': 'Private E-Mail Adresse wiederholen'
      },
    'label_repeat_password': {
        'en': 'Repeat new DHBW Password',
        'de': 'Neues DHBW Passwort wiederholen'
      },
    'label_personid': {
        'en': 'Identification number or last 6 digits of DHBW card number',
        'de': 'Matrikel-/Personalnummer oder letzten 6 Stellen der DHBW Kartennummer'
      },
    'label_username': {
        'en': 'Username',
        'de': 'Benutzername'
      },
    'msg_activate_account_successful': {
        'en': 'Your DHBW account has been activated succesfully.',
        'de': 'Ihr DHBW Konto wurde erfolgreich aktiviert.'
      },
    'msg_change_password_successful': {
        'en': 'You have successfully changed your DHBW password. Your new password will be valid immediately.',
        'de': 'Sie haben Ihr DHBW-Passwort erfolgreich geändert. Das neue Passwort ist ab sofort gültig.'
      },
    'msg_set_email_successful': {
        'en': 'The recovery email adress to your DHBW account has been updated successfully.',
        'de': 'Die E-Mail Adresse zur Authentifikation bei der Wiederherstellung Ihres Zugangs wurde erfolgreich geändert.'
      },
    'msg_recovery_email_sent': {
        'en': 'A recovery code has been sent to your private email address. Please check this mailbox.',
        'de': 'Es wurde ein Wiederherstellungscode an die von Ihnen hinterlegte E-Mail Adresse gesandt. Bitte überprüfen Sie dieses Postfach.'
      },
    'msg_set_password_successful': {
        'en': 'Access to your DHBW account has successfully been restored.',
        'de': 'Der Zugang zu Ihrem DHBW Konto wurde erfolgreich wiederhergestellt.'
      },
    'text_captcha': {
        'en': 'Please enter the following six greenish, yellowish, or reddish letters.',
        'de': 'Geben Sie bitte die folgenden sechs grün-, gelb- oder rötlichen Buchstaben ein.'
      },
    'text_intro_activate_account': {
        'en': 'Prior to using your DHBW account for the first time, it has to be activated.\
               You received a letter from IT.Services providing all necessary information for this step.',
        'de': 'Vor der ersten Verwendung muss Ihr DHBW Konto einmalig aktiviert werden.\
               Die dazu notwendigen Informationen finden Sie im Informationsschreiben, das Sie von IT.Services erhalten haben.'
      },
    'text_intro_change_password': {
        'en': 'This is where you change your DHBW password.\
               In case you are locked out of your account, please use the form to reset your password.',
        'de': 'Hier können Sie Ihr DHBW Passwort ändern.\
               Falls Ihr Konto gesperrt ist verwenden Sie bitte das Formular zur Rücksetzung Ihres Passwortes.'
      },
    'text_intro_reset_password': {
        'en': 'This page allows you to restore access to your DHBW account in case you have forgotten your DHBW password or have been locked out of your account.\
               During the process your password will be reset and your account will be unlocked.',
        'de': 'Falls Sie Ihr DHBW Passwort vergessen haben oder Ihr Konto gesperrt wurde können Sie hier den Zugang wiederherstellen.\
               Im Zuge der Wiederherstellung wird Ihr Passwort neu gesetzt und das Konto entsperrt.'
      },
    'text_intro_set_email': {
        'en': 'If you ever need to recover access to your DHBW account you will be authenticated via email.\
               This is where you set the email address, to which recovery codes for your account are sent.',
        'de': 'Im Falle der Wiederherstellung Ihres Zugangs werden Sie über den Empfang einer E-Mail authentifiziert.\
               Hier können Sie die E-Mail Adresse setzen, an die Ihnen der Wiederherstellungscode gesendet wird.'
      },
    'text_intro_set_password': {
        'en': 'You requested restoration of access to your DHBW account and received a recovery code via email.\
               This is where you set a new DHBW password and unlock your account.',
        'de': 'Sie haben die Wiederherstellung Ihres DHBW Zugangs beantragt und per E-Mail einen Wiederherstellungscode erhalten.\
               Hier können Sie ein neues DHBW Passwort setzen und Ihr Konto entsperren.'
      },
    'text_password_rules': {
        'en': 'Please choose a password for future authenticatation to the DHBW.\
               It has to comply with the following password guidelines:<br>\
               <ul style="padding-left: 1em; margin: 0.25em 0;">\
                 <li>The password must contain between 8 and 20 characters.</li>\
                 <li>The password must contain at least 1 upper case letter (A-Z), 1 lower case letter (a-z), and one digit (0-9).</li>\
                 <li>The following special characters are permitted: <tt>! ( ) + - . , ; : ?</tt></li>\
                 <li>All other characters are <strong>prohibited</strong>, e.g., accents, spaces, currency symbols, etc.</li>\
                 <li>The password may not contain any parts of your name or username.</li>\
                 <li>The password may not have been used for your DHBW account before.</li>\
                 <li>\
                   The password must not be contained in the list of compromised passwords maintained by <a href="https://haveibeenpwned.com" target="_blank">haveibeenpwned.com</a>.\
                   <em>Note:</em> Validation is executed on a local server at DHBW Lörrach; your password is not exposed to third parties.\
                 </li>\
               </ul>',
        'de': 'Bitte wählen Sie ein Passwort, mit dem Sie sich in Zukunft an der DHBW authentifizieren wollen.\
               Beachten Sie dabei die folgenden Richtlinien:<br>\
               <ul style="padding-left: 1em; margin: 0.25em 0;">\
                 <li>Das Passwort muss zwischen 8 und 20 Zeichen lang sein.</li>\
                 <li>Das Passwort muss mindestens 1 Großbuchstaben (A-Z), 1 Kleinbuchstaben (a-z) und eine Ziffer (0-9) enthalten.</li>\
                 <li>Erlaubte Sonderzeichen sind: <tt>! ( ) + - . , ; : ?</tt></li>\
                 <li><strong>Nicht erlaubt</strong> sind alle anderen Zeichen, z.B. Umlaute, Leerzeichen, Währungszeichen, etc.</li>\
                 <li>Das Passwort darf keine Bestandteile Ihres Namens oder Benutzernamens enthalten.</li>\
                 <li>Das Passwort darf noch nicht für Ihr DHBW Konto verwendet worden sein.</li>\
                 <li>\
                   Das Passwort darf nicht in der Liste kompromittierter Passwörter, die von <a href="https://haveibeenpwned.com" target="_blank">haveibeenpwned.com</a> gepflegt wird, enthalten sein.\
                   <em>Hinweis:</em> Die Überprüfung findet lokal an der DHBW Lörrach statt. Ihr Passwort wird nicht an Dritte weitergegeben.\
                 </li>\
               </ul>'
      },
    'text_private_email': {
        'en': 'Please enter a private email address.\
               This email account will be used for authentication should you ever need to recover access to your DHBW account.',
        'de': 'Bitte geben Sie eine private E-Mail Adresse an.\
               Mit Hilfe dieses E-Mail Kontos können Sie ggf. den Zugang zu Ihrem DHBW Konto wiederherstellen.'
      },
    'title_activate_account': {
        'en': 'Activate DHBW Account',
        'de': 'DHBW Konto aktivieren'
      },
    'title_change_password': {
        'en': 'Change DHBW Password',
        'de': 'DHBW Passwort ändern'
      },
    'title_reset_password': {
        'en': 'Restore Access to DHBW Account',
        'de': 'Zugang zum DHBW Konto wiederherstellen'
      },
    'title_set_email': {
        'en': 'Set Recovery Email Address',
        'de': 'Private E-Mail Adresse hinterlegen'
      },
    'title_set_password': {
        'en': 'Set DHBW Password',
        'de': 'DHBW Passwort setzen'
      }
  };


function ussCaptchaImgTag() {
    return '<img style="width: 400px; height: 100px;" src="' + ussUrlApi + '/captcha?now=' + Date.now() + '">';
}


function ussReloadCaptchaImg() {
    var captchaImg = document.getElementById('uss-form-captcha-img');
    if( captchaImg ) {
        captchaImg.innerHTML = ussCaptchaImgTag();
    }
}


function ussShowError(msg) {
    var errstr = document.getElementById('uss-form-error');
    if( errstr ) {
        errstr.innerHTML = msg;
        errstr.style.backgroundColor = "red";
    } else {
        console.log('Error: Unable to display error message "' + msg + '".');
    }

    var overlay = document.getElementById('uss-form-overlay');
    if( overlay ) {
        overlay.style.display = "none";
    }

    ussReloadCaptchaImg();
    var captcha = document.getElementById('uss-form-captcha');
    if( captcha ) {
        captcha.value = '';
    }
}


function ussSetTitle(language, title, onLanguage) {
    var div = document.getElementById('uss-title');
    if( div ) {
        var langSelect = '';
        if( (ussLanguages.length > 1) && onLanguage ) {
            langSelect = '<select id="uss-language" style="width: auto; font-size: small; padding: 0; border-style: none;" onchange="' + onLanguage + '(document.getElementById(\'uss-language\').value);">';
            for( i = 0; i < ussLanguages.length; i++ ) {
                langSelect += '<option' +  (language == ussLanguages[ i ].tag ? ' selected="true"' : '') + ' value="' + ussLanguages[ i ].tag + '">' + ussLanguages[ i ].label + '</option>';
            }
            langSelect += '</select>';
        }
        div.innerHTML = '\
                <table style="width: 100%; padding: 0; margin: 0; border: 0 none; border-collapse: collapse; table-layout: auto;"><tr>\
                  <td style="font-size: larger; vertical-align: bottom; padding: 0; border: 0 none;">' + title + '</td>\
                  <td style="text-align: right; padding: 0 0 1px 0; border: 0 none;">' + langSelect + '</td>\
                </tr></table>';
    }
}


function ussWaitResponse(location, language, onSuccess) {
    var request = new XMLHttpRequest();
    request.open('GET', ussUrlApi + location, true);
    request.onreadystatechange = function() {
            if( this.readyState === XMLHttpRequest.DONE ) {
                switch( this.status ) {
                case 200:
                    switch( request.response.trim() ) {
                    case "new":
                        setTimeout(function() { ussWaitResponse(location, language, onSuccess); }, 1000);
                        break;
                    case "successful":
                        onSuccess(language);
                        break;
                    case "invalid-credentials":
                        ussShowError(ussTranslations.error_invalid_credentials[language]);
                        break;
                    case "no-permission":
                        ussRequestFailedPage(language, [ussTranslations.error_no_permission[language], ussTranslations.hint_contact_its[language]]);
                        break;
                    case "invalid-password":
                        ussShowError(ussTranslations.error_invalid_password[language]);
                        break;
                    case "pwned-password":
                        ussShowError(ussTranslations.error_pwned_password[language]);
                        break;
                    case "invalid-email":
                        ussShowError(ussTranslations.error_invalid_email[language]);
                        break;
                    case "too-frequent-use":
                        ussRequestFailedPage(language, [ussTranslations.error_too_frequent_use[language]]);
                        break;
                    case "already-activated":
                        ussRequestFailedPage(language, [ussTranslations.error_already_activated[language], ussTranslations.hint_already_activated[language]]);
                        break;
                    case "internal-error":
                    default:
                        ussRequestFailedPage(language, [ussTranslations.error_internal_error[language], ussTranslations.hint_try_again_later[language]]);
                        break;
                    }
                    break;
                default:
                    ussRequestFailedPage(language, [ussTranslations.error_request_gone[language], ussTranslations.hint_try_again_later[language]]);
                    break;
                }
            }
        };
    request.send();
}


function ussSendData(language, location, data, onSuccess, captcha) {
    var request = new XMLHttpRequest();
    request.open('POST', ussUrlApi + location, true);
    request.withCredentials = true;
    if( captcha ) {
        request.setRequestHeader('captcha', captcha);
    }
    request.onreadystatechange = function() {
            if( this.readyState === XMLHttpRequest.DONE ) {
                switch( this.status ) {
                case 200:
                    ussWaitResponse(location + '/' + request.response.trim(), language, onSuccess);
                    break;
                case 403:
                    ussShowError(ussTranslations.error_wrong_captcha[language]);
                    break;
                default:
                    ussRequestFailedPage(language, [ussTranslations.error_transmission_failed[language], ussTranslations.hint_try_again_later[language]]);
                    break;
                }
            }
        };
    request.send(data);
}


function ussEncodeASCII(s) {
    var n = s.length;
    b = new Uint8Array(n);
    for(var i = 0; i < n; ++i) {
        var c = s.charCodeAt(i);
        if( (c < 0) || (c >= 0x80) ) {
            return null;
        }
        b[i] = c;
    }
    return b;
}


function ussEncrypt(data, onComplete, onError) {
    var algorithm = { name: "RSA-OAEP", hash: { name: "SHA-256" } };
    if( window.crypto ) {
        var onImport = function(key) {
            window.crypto.subtle.encrypt(algorithm, key, data)['then'](onComplete)['catch'](onError);
          };
        window.crypto.subtle.importKey("jwk", ussPublicKey, algorithm, false, ["encrypt"])['then'](onImport)['catch'](onError);
    } else if( window.msCrypto ) {
        var jsonPublicKey = ussEncodeASCII(JSON.stringify(ussPublicKey));

        var onImport = function(e) {
            var key = e.target.result;
            var keyOp = window.msCrypto.subtle.encrypt(algorithm, key, data);
            keyOp.onerror = onError;
            keyOp.oncomplete = function(e) { onComplete(e.target.result); }
          };

        var keyOp = window.msCrypto.subtle.importKey("jwk", jsonPublicKey, algorithm, false, ["encrypt"]);
        keyOp.onerror = onError;
        keyOp.oncomplete = onImport;
    } else {
        onError();
    }
}


function ussSendEncryptedData(location, data, onSuccess, captcha) {
    var overlay = document.getElementById('uss-form-overlay');
    if( overlay ) {
        overlay.style.display = "flex";
    }

    if( (typeof captcha == "string") && (captcha.length != 6) ) {
        ussShowError(ussTranslations.error_missing_captcha[data.lang]);
        return;
    }

    var json = ussEncodeASCII(JSON.stringify(data));
    if( !json ) {
        ussRequestFailedPage(data.lang, [ussTranslations.error_in_ascii_encoding[data.lang], ussTranslations.hint_try_again_later[data.lang]]);
        return;
    }

    var onComplete = function(encrypted) { ussSendData(data.lang, location, encrypted, onSuccess, captcha); };
    var onError = function(err) { ussRequestFailedPage(data.lang, [ussTranslations.error_in_encryption[data.lang], ussTranslations.hint_try_again_later[data.lang]]); };
    ussEncrypt(json, onComplete, onError);
}


function ussValidateUser(data) {
    if( !data.user ) {
        ussShowError(ussTranslations.error_missing_username[data.lang]);
        return false;
    }
    return true;
}


function ussValidateActivationCode(data) {
    if( !data.pwd ) {
        ussShowError(ussTranslations.error_missing_activation_code[data.lang]);
        return false;
    }
    return true;
}


function ussValidateAcceptTerms(data) {
    if( !data.accept ) {
        ussShowError(ussTranslations.error_must_accept_terms_of_use[data.lang]);
        return false;
    }
    return true;
}


function ussValidatePassword(data) {
    if( !data.pwd ) {
        ussShowError(ussTranslations.error_missing_password[data.lang]);
        return false;
    }
    return true;
}


function ussValidateId(data) {
    if( !data.id || !data.id.match("^[0-9]+$") ) {
        ussShowError(ussTranslations.error_missing_id[data.lang]);
        return false;
    }
    return true;
}


function ussValidateCode(data) {
    if( !data.code || !data.code.match("^[a-fA-F0-9]{16}$") ) {
        ussShowError(ussTranslations.error_invalid_recovery_code[data.lang]);
        return false;
    }
    return true;
}


function ussValidateNewPassword(data, repeat) {
    if( !data.newpwd ) {
        ussShowError(ussTranslations.error_missing_new_password[data.lang]);
        return false;
    }
    if( data.newpwd != repeat ) {
        ussShowError(ussTranslations.error_repeat_new_password[data.lang]);
        return false;
    }

    if( !data.newpwd.match('^[a-zA-Z0-9!().,;:?+-]{8,20}$') ) {
        ussShowError(ussTranslations.error_invalid_password_chars[data.lang]);
        return false;
    }
    if( !data.newpwd.match('[a-z]') || !data.newpwd.match('[A-Z]') || !data.newpwd.match('[0-9]') ) {
        ussShowError(ussTranslations.error_missing_password_chars[data.lang]);
        return false;
    }
    if( data.user && data.newpwd.toUpperCase().indexOf(data.user.toUpperCase()) >= 0 ) {
        ussShowError(ussTranslations.error_password_contains_username[data.lang]);
        return false;
    }
    return true;
}


function ussValidateNewEmail(data, repeat) {
    if( !data.neweml ) {
        ussShowError(ussTranslations.error_missing_new_email[data.lang]);
        return false;
    }
    if( data.neweml != repeat) {
        ussShowError(ussTranslations.error_repeat_new_email[data.lang]);
        return false;
    }
    if( !data.neweml.match("^[a-zA-Z0-9.!£#$%&'^_`{}~+-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$") ) {
        ussShowError(ussTranslations.error_invalid_email[data.lang]);
        return false;
    }
    return true;
}


function ussSubmitActivateAccountRequest(event, language, onSuccess) {
    event.preventDefault();
    var data  = {
      "lang": language,
      "user": document.getElementById('uss-form-user').value.trim(),
      "id": document.getElementById('uss-form-id').value.trim(),
      "pwd": document.getElementById('uss-form-password').value,
      "newpwd": document.getElementById('uss-form-new-password').value,
      "neweml": document.getElementById('uss-form-new-address').value.trim(),
      "accept": document.getElementById('uss-form-accept-terms').checked
    };
    var captcha = document.getElementById('uss-form-captcha').value;

    rptpwd = document.getElementById('uss-form-repeat-password').value;
    rpteml = document.getElementById('uss-form-repeat-address').value.trim();
    if( ussValidateUser(data) && ussValidateId(data) && ussValidateActivationCode(data) && ussValidateNewPassword(data, rptpwd) && ussValidateNewEmail(data, rpteml) && ussValidateAcceptTerms(data) ) {
        data.id = parseInt(data.id);
        ussSendEncryptedData('/activate-account', data, onSuccess, captcha);
    }

    return false;
}


function ussSubmitResetPasswordRequest(event, language, onSuccess) {
    event.preventDefault();
    var data  = {
      "lang": language,
      "user": document.getElementById('uss-form-user').value.trim(),
      "id": document.getElementById('uss-form-id').value.trim()
    };
    var captcha = document.getElementById('uss-form-captcha').value;

    if( ussValidateUser(data) && ussValidateId(data) ) {
        data.id = parseInt(data.id);
        ussSendEncryptedData('/reset-password', data, onSuccess, captcha);
    }

    return false;
}


function ussSubmitSetPasswordRequest(event, language, onSuccess) {
    event.preventDefault();
    var data  = {
      "lang": language,
      "user": document.getElementById('uss-form-user').value.trim(),
      "code": document.getElementById('uss-form-code').value.trim(),
      "newpwd": document.getElementById('uss-form-new-password').value
    };

    repeat = document.getElementById('uss-form-repeat-password').value;
    if( ussValidateUser(data) && ussValidateCode(data) && ussValidateNewPassword(data, repeat) ) {
        ussSendEncryptedData('/set-password', data, onSuccess);
    }

    return false;
}


function ussSubmitChangePasswordRequest(event, language, onSuccess) {
    event.preventDefault();
    var data  = {
      "lang": language,
      "user": document.getElementById('uss-form-user').value.trim(),
      "pwd": document.getElementById('uss-form-password').value,
      "newpwd": document.getElementById('uss-form-new-password').value
    };
    var captcha = document.getElementById('uss-form-captcha').value;

    repeat = document.getElementById('uss-form-repeat-password').value;
    if( ussValidateUser(data) && ussValidatePassword(data) && ussValidateNewPassword(data, repeat) ) {
        ussSendEncryptedData('/change-password', data, onSuccess, captcha);
    }

    return false;
}


function ussSubmitSetEmailRequest(event, language, onSuccess) {
    event.preventDefault();
    var data  = {
      "lang": language,
      "user": document.getElementById('uss-form-user').value.trim(),
      "pwd": document.getElementById('uss-form-password').value,
      "neweml": document.getElementById('uss-form-new-address').value.trim()
    };
    var captcha = document.getElementById('uss-form-captcha').value;

    repeat = document.getElementById('uss-form-repeat-address').value.trim();
    if( ussValidateUser(data) && ussValidatePassword(data) && ussValidateNewEmail(data, repeat) ) {
        ussSendEncryptedData('/set-email', data, onSuccess, captcha);
    }

    return false;
}


function ussRequestFailedPage(language, message) {
    language = language ? language : 'de';
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = message.map(function (s) { return '<div style="width: 100%; margin-top: 1em;">' + s + '</div>'; }).join('') + '\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
            ';
    }
}


function ussRequestSuccessfulPage(language, message) {
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = message.map(function (s) { return '<div style="width: 100%; margin-top: 1em;">' + s + '</div>'; }).join('') + '\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="button" value="' + ussTranslations.btn_done[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
            ';
    }
}


function ussActivateAccountPage(language, user) {
    ussSetTitle(language, ussTranslations.title_activate_account[language]);
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <form id="uss-form-real" style="position: relative; margin: 0em;" onsubmit="return ussSubmitActivateAccountRequest(event, \'' + language + '\', ussActivateAccountSuccessful)">\
                <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_activate_account[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_username[language] + ':</div>\
                <input id="uss-form-user" type="text" name="username" value="' + (user ? user : '') + '">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_personid[language] + ':</div>\
                <input id="uss-form-id" type="text">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_activation_code[language] + ':</div>\
                <input id="uss-form-password" type="password">\
                <div style="margin-top: 1.5em; width: 100%;">' + ussTranslations.text_password_rules[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_new_password[language] + ':</div>\
                <input id="uss-form-new-password" type="password" autocomplete="off">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_repeat_password[language] + ':</div>\
                <input id="uss-form-repeat-password" type="password" autocomplete="off">\
                <div style="margin-top: 1.5em; width: 100%;">' + ussTranslations.text_private_email[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_new_email[language] + ':</div>\
                <input id="uss-form-new-address" type="text" autocomplete="off">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_repeat_email[language] + ':</div>\
                <input id="uss-form-repeat-address" type="text" autocomplete="off">\
                <div style="margin-top: 1.5em;"><input id="uss-form-accept-terms" type="checkbox">' + ussTranslations.label_accept_terms[language] + '</div>\
                <div style="text-align: justify; margin-top: 1.5em;">' + ussTranslations.text_captcha[language] + '</div>\
                <div id="uss-form-captcha-img" style="width: 100%; text-align: center; margin-top: 0.5em; margin-bottom: 0.5em;">' + ussCaptchaImgTag() + '</div>\
                <div style="display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch;"> \
                    <input id="uss-form-captcha" type="text" name="captcha" style="width: 100%; box-sizing: border-box;" autocomplete="off">\
                    <div style="width: 0.5em;"></div>\
                    <input type="button" style="margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;" value="' + ussTranslations.btn_new_image[language] + '" onclick="ussReloadCaptchaImg()">\
                </div>\
                <div id="uss-form-error"></div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="submit" value="' + ussTranslations.btn_next[language] + '">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
                <div id="uss-form-overlay">' + ussTranslations.hint_processing_request[language] + '</div>\
                </form>\
            ';
    }
}


function ussActivateAccountSuccessful(language) {
    ussRequestSuccessfulPage(language, [ussTranslations.msg_activate_account_successful[language], ussTranslations.hint_confirmation_email_sent[language]]);
}


function ussResetPasswordPage(language, user, id) {
    ussSetTitle(language, ussTranslations.title_reset_password[language]);
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <form id="uss-form-real" style="position: relative; margin: 0em;" onsubmit="return ussSubmitResetPasswordRequest(event, \'' + language + '\', ussResetPasswortSuccessful)">\
                <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_reset_password[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_username[language] + ':</div>\
                <input id="uss-form-user" type="text" name="username" value="' + (user ? user : '') + '">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_personid[language] + ':</div>\
                <input id="uss-form-id" type="text" value="' + (id ? id : '') + '">\
                <div style="text-align: justify; margin-top: 1.5em;">' + ussTranslations.text_captcha[language] + '</div>\
                <div id="uss-form-captcha-img" style="width: 100%; text-align: center; margin-top: 0.5em; margin-bottom: 0.5em;">' + ussCaptchaImgTag() + '</div>\
                <div style="display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch;"> \
                    <input id="uss-form-captcha" type="text" name="captcha" style="width: 100%; box-sizing: border-box;" autocomplete="off">\
                    <div style="width: 0.5em;"></div>\
                    <input type="button" style="margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;" value="' + ussTranslations.btn_new_image[language] + '" onclick="ussReloadCaptchaImg()">\
                </div>\
                <div id="uss-form-error"></div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="submit" value="' + ussTranslations.btn_next[language] + '">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
                <div id="uss-form-overlay">' + ussTranslations.hint_processing_request[language] + '</div>\
                </form>\
            ';
    }
}


function ussResetPasswortSuccessful(language) {
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <div style="width: 100%; margin-top: 1em;">' + ussTranslations.msg_recovery_email_sent[language] + '</div>\
                <div style="width: 100%; margin-top: 1em;">' + ussTranslations.hint_recovery_email_sent[language] + '</div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="button" value="' + ussTranslations.btn_next[language] + '" onclick="ussSetPasswordPage(\'' + language + '\')">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
            ';
    }
}


function ussSetPasswordPage(language, user, code) {
    ussSetTitle(language, ussTranslations.title_set_password[language]);
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <form id="uss-form-real" style="position: relative; margin: 0em;" onsubmit="return ussSubmitSetPasswordRequest(event, \'' + language + '\', ussSetPasswordSuccessful)">\
                <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_set_password[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_username[language] + ':</div>\
                <input id="uss-form-user" type="text" value="' + (user ? user : '') + '">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_recovery_code[language] + ':</div>\
                <input id="uss-form-code" type="text" value="' + (code ? code : '') + '" autocomplete="off">\
                <div style="margin-top: 1.5em; width: 100%;">' + ussTranslations.text_password_rules[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_new_password[language] + ':</div>\
                <input id="uss-form-new-password" type="password" autocomplete="off">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_repeat_password[language] + ':</div>\
                <input id="uss-form-repeat-password" type="password" autocomplete="off">\
                <div id="uss-form-error"></div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="submit" value="' + ussTranslations.btn_next[language] + '">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
                <div id="uss-form-overlay">' + ussTranslations.hint_processing_request[language] + '</div>\
                </form>\
            ';
    }
}


function ussSetPasswordSuccessful(language) {
    ussRequestSuccessfulPage(language, [ussTranslations.msg_set_password_successful[language], ussTranslations.hint_update_devices[language]]);
}


function ussChangePasswordPage (language, user) {
    ussSetTitle(language, ussTranslations.title_change_password[language]);
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <form id="uss-form-real" style="position: relative; margin: 0em;" onsubmit="return ussSubmitChangePasswordRequest(event, \'' + language + '\', ussChangePasswordSuccessful);">\
                <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_change_password[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_username[language] + ':</div>\
                <input id="uss-form-user" type="text" value="' + (user ? user : '') + '">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_password[language] + ':</div>\
                <input id="uss-form-password" type="password">\
                <div style="margin-top: 1.5em; width: 100%;">' + ussTranslations.text_password_rules[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_new_password[language] + ':</div>\
                <input id="uss-form-new-password" type="password" autocomplete="off">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_repeat_password[language] + ':</div>\
                <input id="uss-form-repeat-password" type="password" autocomplete="off">\
                <div style="text-align: justify; margin-top: 1.5em;">' + ussTranslations.text_captcha[language] + '</div>\
                <div id="uss-form-captcha-img" style="width: 100%; text-align: center; margin-top: 0.5em; margin-bottom: 0.5em;">' + ussCaptchaImgTag() + '</div>\
                <div style="display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch;"> \
                    <input id="uss-form-captcha" type="text" name="captcha" style="width: 100%; box-sizing: border-box;" autocomplete="off">\
                    <div style="width: 0.5em;"></div>\
                    <input type="button" style="margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;" value="' + ussTranslations.btn_new_image[language] + '" onclick="ussReloadCaptchaImg()">\
                </div>\
                <div id="uss-form-error"></div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="submit" value="' + ussTranslations.btn_next[language] + '">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
                <div id="uss-form-overlay">' + ussTranslations.hint_processing_request[language] + '</div>\
                </form>\
            ';
    }
}


function ussChangePasswordSuccessful(language) {
    ussRequestSuccessfulPage(language, [ussTranslations.msg_change_password_successful[language], ussTranslations.hint_update_devices[language]]);
}


function ussSetEmailPage (language, user) {
    ussSetTitle(language, ussTranslations.title_set_email[language]);
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <form id="uss-form-real" style="position: relative; margin: 0em;" onsubmit="return ussSubmitSetEmailRequest(event, \'' + language + '\', ussSetEmailSuccessful)">\
                <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_set_email[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_username[language] + ':</div>\
                <input id="uss-form-user" type="text" value="' + (user ? user : '') + '">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_password[language] + ':</div>\
                <input id="uss-form-password" type="password">\
                <div style="margin-top: 1.5em; width: 100%;">' + ussTranslations.text_private_email[language] + '</div>\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_new_email[language] + ':</div>\
                <input id="uss-form-new-address" type="text" autocomplete="off">\
                <div style="margin-top: 0.5em;">' + ussTranslations.label_repeat_email[language] + ':</div>\
                <input id="uss-form-repeat-address" type="text" autocomplete="off">\
                <div style="text-align: justify; margin-top: 1.5em;">' + ussTranslations.text_captcha[language] + '</div>\
                <div id="uss-form-captcha-img" style="width: 100%; text-align: center; margin-top: 0.5em; margin-bottom: 0.5em;">' + ussCaptchaImgTag() + '</div>\
                <div style="display: flex; flex-direction: row; flex-wrap: nowrap; align-items: stretch;"> \
                    <input id="uss-form-captcha" type="text" name="captcha" style="width: 100%; box-sizing: border-box;" autocomplete="off">\
                    <div style="width: 0.5em;"></div>\
                    <input type="button" style="margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;" value="' + ussTranslations.btn_new_image[language] + '" onclick="ussReloadCaptchaImg()">\
                </div>\
                <div id="uss-form-error"></div>\
                <div style="width: 100%; text-align: right; margin-top: 1em;">\
                    <input type="submit" value="' + ussTranslations.btn_next[language] + '">\
                    <input type="button" value="' + ussTranslations.btn_cancel[language] + '" onclick="ussDefaultPage(\'' + language + '\')">\
                </div>\
                <div id="uss-form-overlay">' + ussTranslations.hint_processing_request[language] + '</div>\
                </form>\
            ';
    }
}


function ussSetEmailSuccessful(language) {
    ussRequestSuccessfulPage(language, [ussTranslations.msg_set_email_successful[language], ussTranslations.hint_guard_private_mailbox[language]]);
}


function ussDefaultPage(language) {
    ussSetTitle(language, 'User Self Service', 'ussDefaultPage');
    var form = document.getElementById('uss-form');
    if( form ) {
        form.innerHTML = '\
                <div class="ussLargeButton" onclick="ussActivateAccountPage(\'' + language + '\')">\
                  <div style="color: #EE0000; font-size: large;">' + ussTranslations.title_activate_account[language] + '</div>\
                  <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_activate_account[language] + '</div>\
                </div>\
                <div class="ussLargeButton" onclick="ussChangePasswordPage(\'' + language + '\')">\
                  <div style="color: #EE0000; font-size: large;">' + ussTranslations.title_change_password[language] + '</div>\
                  <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_change_password[language] + '</div>\
                </div>\
                <div class="ussLargeButton" onclick="ussResetPasswordPage(\'' + language + '\')">\
                  <div style="color: #EE0000; font-size: large;">' + ussTranslations.title_reset_password[language] + '</div>\
                  <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_change_password[language] + '</div>\
                </div>\
                <div class="ussLargeButton" onclick="ussSetEmailPage(\'' + language + '\')">\
                  <div style="color: #EE0000; font-size: large;">' + ussTranslations.title_set_email[language] + '</div>\
                  <div style="margin-top: 0.5em;">' + ussTranslations.text_intro_set_email[language] + '</div>\
                </div>\
            ';
    }
}


function ussGetURLParam(name) {
    var pattern = new RegExp('[?&]' + name + '=([^&#]*)');
    var match = pattern.exec(window.location.search);
    return match === null ? null : decodeURIComponent(match[1].replace(/\+/g, ' '));
}


function ussFindIndex(array, predicate) {
    for( i = 0; i < array.length; i++ ) {
        if( predicate( array[ i ] ) )
            return i;
    }
    return -1;
}


function ussOnLoad(language) {
    if( !language ) {
        language = ussGetURLParam('lang');
    }
    var index = ussFindIndex( ussLanguages, function (e) { return (e.tag == language); } );
    if( index >= 0 ) {
        console.log(index);
        ussLanguages = [ussLanguages[index]];
    } else {
        language = ussLanguages[0].tag;
    }
    switch( ussGetURLParam('uss') ) {
    case 'activate-account':
        ussActivateAccountPage(language, ussGetURLParam('user'));
        break;

    case 'change-password':
        ussChangePasswordPage(language, ussGetURLParam('user'));
        break;

    case 'reset-password':
        ussResetPasswordPage(language, ussGetURLParam('user'), ussGetURLParam('id'));
        break;

    case 'set-password':
        ussSetPasswordPage(language, ussGetURLParam('user'), ussGetURLParam('code'));
        break;

    case 'set-email':
        ussSetEmailPage(language, ussGetURLParam('user'));
        break;

    default:
        ussDefaultPage(language);
    }
}


$(function () {
    var form = document.getElementById('sophos-update-password-form');
    if( form ) {
        form.innerHTML = '\
                <form onsubmit="return sophosSubmitCredentialsRequest()"> \
                <div style="margin-top: 0.5em;">Benutzername:</div>\
                <input id="sophos-password-username" type="text" style="width: 100%; box-sizing: border-box;">\
                <div style="text-align: justify; margin-top: 1em;">Geben Sie bitte die folgenden sechs grün-, gelb- oder rötlichen Buchstaben ein.</div>\
                <div style="text-align: center; margin-top: 0.5em; margin-bottom: 0.5em;"><img style="width: 400px; height: 100px;" src="https://su2.dhbw-loerrach.de/api/captcha"></div>\
                <input id="sophos-password-captcha" type="text" style="width: 100%; box-sizing: border-box;">\
                <div id="sophos-password-error" style="width: 100%; background-color: transparent; color: white; margin-top: 0.5em; padding: 2px;"></div>\
                <div style="width: 100%; text-align: right; margin-top: 0.5em;"><input type="submit" value="Zusenden"></div>\
                </form>\
            ';
    }

    /** USS **/
    if(document.getElementById("uss-form") != null) {
        ussOnLoad();
    }
}());