changeset 524:a097dd86cb4d

merged.
author Raimund Renkert <rrenkert@intevation.de>
date Tue, 29 Apr 2014 15:26:43 +0200
parents ca583ffe728a (current diff) fd29ab9cadaf (diff)
children 3edbe1af2c85
files ui/createcertlistdialog.cpp ui/mainwindow.cpp
diffstat 31 files changed, 936 insertions(+), 559 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Apr 29 15:26:02 2014 +0200
+++ b/CMakeLists.txt	Tue Apr 29 15:26:43 2014 +0200
@@ -21,6 +21,15 @@
 
 include(CTest)
 include(GenerateCppcheck)
+include(HGVersion)
+
+if(HG_REVISION)
+   set(PROJECT_VERSION ${HG_REVISION})
+else()
+   set(PROJECT_VERSION unknown)
+endif()
+
+add_definitions(-DVERSION="${PROJECT_VERSION}")
 
 find_package(PolarSSL)
 include_directories(${POLARSSL_INCLUDE_DIR})
@@ -102,3 +111,10 @@
 # Documentation
 configure_file (doc/Doxyfile.in doc/Doxyfile)
 add_subdirectory(doc)
+
+# Configure packaging script for testing
+list(GET NSS_LIBRARIES 1 NSS_BASE_DIR)
+get_filename_component(NSS_BASE_DIR ${NSS_BASE_DIR} PATH)
+
+set(NSS_BASE_DIR "${NSS_BASE_DIR}/..")
+configure_file (packaging/tmp-createpackage.sh.in packaging/tmp-createpackage.sh)
--- a/cinst/main.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/main.c	Tue Apr 29 15:26:43 2014 +0200
@@ -325,7 +325,6 @@
   if (ret != 0)
     {
       ERRORPRINTF ("Failed to write nss stores");
-      DEBUGPRINTF ("Hello World");
     }
 
   /* Make valgrind happy */
--- a/cinst/mozilla.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/mozilla.c	Tue Apr 29 15:26:43 2014 +0200
@@ -381,7 +381,6 @@
   if (!cn_str || !o_str)
     {
       DEBUGPRINTF("FATAL: Could not parse certificate!");
-      DEBUGPRINTF("data len: %u \n", secitemp->len);
       exit(ERR_INVALID_CERT);
     }
   name_len = strlen(cn_str) + strlen(o_str) + 4;
@@ -439,34 +438,27 @@
   char *cert_name = nss_cert_name(dercert);
 
   DEBUGPRINTF("INSTALLING cert: '%s' to: %s\n", cert_name, pdir);
-  if (NSS_Initialize(pdir, "", "", "secmod.db", 0) == SECSuccess)
+  pk11slot = PK11_GetInternalKeySlot();
+  cert = CERT_DecodeCertFromPackage((char *)dercert->data,
+                                    (int)dercert->len);
+  trust = (CERTCertTrust *)xmalloc(sizeof(CERTCertTrust));
+  CERT_DecodeTrustString(trust, "C");
+  if ((PK11_ImportCert(pk11slot, cert, CK_INVALID_HANDLE,
+                       cert_name, PR_FALSE)
+       == SECSuccess) &&
+      (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust)
+       == SECSuccess))
     {
-      pk11slot = PK11_GetInternalKeySlot();
-      cert = CERT_DecodeCertFromPackage((char *)dercert->data,
-                                        (int)dercert->len);
-      trust = (CERTCertTrust *)xmalloc(sizeof(CERTCertTrust));
-      CERT_DecodeTrustString(trust, "C");
-      if ((PK11_ImportCert(pk11slot, cert, CK_INVALID_HANDLE,
-                           cert_name, PR_FALSE)
-           == SECSuccess) &&
-          (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust)
-           == SECSuccess))
-        {
-          success = true;
-        }
-      else
-        {
-          DEBUGPRINTF("Failed to install certificate '%s' to '%s'!\n", cert_name, pdir);
-        }
-      CERT_DestroyCertificate (cert);
-      free(trust);
-      PK11_FreeSlot(pk11slot);
-      NSS_Shutdown();
+      success = true;
     }
   else
     {
-      DEBUGPRINTF("Could not open nss certificate store in %s!\n", pdir);
+      DEBUGPRINTF("Failed to install certificate '%s' to '%s'!\n", cert_name, pdir);
+      ERRORPRINTF("Error installing certificate err: %i\n", PORT_GetError());
     }
+  CERT_DestroyCertificate (cert);
+  free(trust);
+  PK11_FreeSlot(pk11slot);
 
   free(cert_name);
   return success;
@@ -545,18 +537,25 @@
 apply_to_certs_and_profiles(bool fn(char *, SECItem *),
                             seciteml_t **certs, char **pdirs)
 {
-  SECItem *cert;
   bool success = true;
 
-  while ((cert = seciteml_pop(certs)) != NULL)
+  for (int i=0; pdirs[i] != NULL; i++)
     {
-      for (int i=0; pdirs[i] != NULL; i++)
+      seciteml_t *iter = *certs;
+      if (NSS_Initialize(pdirs[i], "", "", "secmod.db", 0) != SECSuccess)
         {
+          DEBUGPRINTF("Could not open nss certificate store in %s!\n", pdirs[i]);
+          continue;
+        }
+
+      while (iter != NULL && iter->item != NULL)
+        {
+          SECItem *cert = iter->item;
           if (! (*fn)(pdirs[i], cert))
             success = false;
+          iter = iter->next;
         }
-      free(cert->data);
-      free(cert);
+      NSS_Shutdown();
     }
 
   return success;
--- a/cinst/nss-secitemlist.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/nss-secitemlist.c	Tue Apr 29 15:26:43 2014 +0200
@@ -20,6 +20,20 @@
   *list = newlelt;
 }
 
+void
+seciteml_free (seciteml_t **list)
+{
+  seciteml_t *oldlelt;
+
+  while (*list != NULL)
+    {
+      oldlelt = *list;
+      *list = oldlelt->next;
+      free(oldlelt->item);
+      free(oldlelt);
+    }
+}
+
 SECItem *seciteml_pop (seciteml_t **list)
 {
   seciteml_t *oldlelt;
--- a/cinst/nss-secitemlist.h	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/nss-secitemlist.h	Tue Apr 29 15:26:43 2014 +0200
@@ -44,4 +44,14 @@
  */
 SECItem *seciteml_pop (seciteml_t **list);
 
+/**
+ * @brief Free a secitem list
+ *
+ * Frees a secitem list
+ *
+ * @param[inout] list pointer to the list which should be freed. set to NULL
+ */
+void seciteml_free (seciteml_t **list);
+
+
 #endif
--- a/cinst/nssstore_win.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/nssstore_win.c	Tue Apr 29 15:26:43 2014 +0200
@@ -61,22 +61,13 @@
 
 #define PROCESS_TIMEOUT 30000
 
-#define PRINTLASTERROR(msg) \
-  char *my_error = getLastErrorMsg(); \
-      if (my_error) { \
-        DEBUGPRINTF(msg " : %s\n", my_error); \
-        ERRORPRINTF(msg" : %s\n", my_error); \
-        free (my_error); \
-      } \
-  DEBUGPRINTF ("Failed to get error information\n");
-
 /**@brief Write strv of instructions to a handle
 *
 * Writes the null terminated list of instructions to
 * the handle.
 *
-* @param [in] base64 encoded der certificates to write
-* @param [in] write_handle to write to
+* @param [in] certificates base64 encoded der certificate to write
+* @param [in] write_handle handle to write to
 * @param [in] remove weather the certificate should be installed or removed
 *
 * @returns true on success, false on failure
@@ -85,38 +76,61 @@
 write_instructions(char **certificates, HANDLE write_handle,
                    bool remove)
 {
+  bool retval = false;
   int i = 0;
-  int cHandle = -1;
-  FILE *write_stream = NULL;
+  const char *line_end = "\r\n";
+  char *line_start = NULL;
 
   if (!certificates)
     {
       return true;
     }
 
-  cHandle = _open_osfhandle ((intptr_t)write_handle, 0);
+  line_start = remove ? "R:" : "I:";
 
-  if (cHandle == -1)
-    {
-      ERRORPRINTF ("Failed to open write handle.\n");
-    }
-
-  write_stream = _fdopen(cHandle, "w");
   for (i = 0; certificates[i]; i++)
     {
-      int ret = 0;
-      if (remove)
-        ret = fprintf (write_stream, "R:%s\n", certificates[i]);
-      else
-        ret = fprintf (write_stream, "I:%s\n", certificates[i]);
-
-      if (ret <= 0)
+      DWORD written = 0;
+      DWORD inst_len = strlen (certificates[i]);
+      retval = WriteFile (write_handle, (LPCVOID) line_start, 2, &written, NULL);
+      if (!retval)
         {
-          DEBUGPRINTF ("Failed to write everything.\n");
-          break;
+          PRINTLASTERROR ("Failed to write line start\n");
+          return false;
+        }
+      if (written != 2)
+        {
+          ERRORPRINTF ("Failed to write line start\n");
+          retval = false;
+          return false;
+        }
+      written = 0;
+      retval = WriteFile (write_handle, (LPCVOID) certificates[i], inst_len, &written, NULL);
+      if (!retval)
+        {
+          PRINTLASTERROR ("Failed to write certificate\n");
+          return false;
+        }
+      if (inst_len != written)
+        {
+          ERRORPRINTF ("Failed to write everything\n");
+          retval = false;
+          return false;
+        }
+      written = 0;
+      retval = WriteFile (write_handle, (LPCVOID) line_end, 2, &written, NULL);
+      if (!retval)
+        {
+          PRINTLASTERROR ("Failed to write line end\n");
+          return false;
+        }
+      if (written != 2)
+        {
+          ERRORPRINTF ("Failed to write full line end\n");
+          retval = false;
+          return false;
         }
     }
-
   return true;
 }
 
@@ -453,13 +467,23 @@
                       GENERIC_WRITE,
                       0, /* don't share */
                       NULL, /* use the security attributes from the folder */
-                      OPEN_ALWAYS,
+                      OPEN_ALWAYS | TRUNCATE_EXISTING,
                       0,
                       NULL);
 
+  if (hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+    {
+      hFile = CreateFileW(path,
+                          GENERIC_WRITE,
+                          0, /* don't share */
+                          NULL, /* use the security attributes from the folder */
+                          CREATE_NEW,
+                          0,
+                          NULL);
+    }
   if (hFile == INVALID_HANDLE_VALUE)
     {
-      ERRORPRINTF ("Failed to create file\n");
+      PRINTLASTERROR ("Failed to create file\n");
       xfree(path);
       return NULL;
     }
--- a/cinst/windowsstore.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/cinst/windowsstore.c	Tue Apr 29 15:26:43 2014 +0200
@@ -192,6 +192,7 @@
 
   if (!hStore)
     {
+      ERRORPRINTF ("Failed to access store.\n");
       return ERR_STORE_ACCESS_DENIED;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/HGVersion.cmake	Tue Apr 29 15:26:43 2014 +0200
@@ -0,0 +1,57 @@
+# Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+# Software engineering by Intevation GmbH
+#
+# This file is Free Software under the GNU GPL (v>=2)
+# and comes with ABSOLUTELY NO WARRANTY!
+# See LICENSE.txt for details.
+
+# This makes some variables available to generate a nice version number for
+# hg managed repositories.
+# It sets HG_REVISION_TAG to the value of the latest tag
+# HG_REVISION_DIST to the differences between the tag and the current tip
+# HG_REVISION_ID to the actual revision
+# based on code found in the lemon graph library https://lemon.cs.elte.hu
+# HG_REVISON to a nice combination of those.
+find_package(Hg)
+if (HG_FOUND)
+  EXECUTE_PROCESS(
+    COMMAND
+    hg log -r. --template "{latesttag}"
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HG_REVISION_TAG
+    ERROR_QUIET
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+  )
+  EXECUTE_PROCESS(
+    COMMAND
+    hg log -r. --template "{latesttagdistance}"
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HG_REVISION_DIST
+    ERROR_QUIET
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+  )
+  EXECUTE_PROCESS(
+    COMMAND
+    hg log -r. --template "{node|short}"
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HG_REVISION_ID
+    ERROR_QUIET
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+  )
+
+  IF(HG_REVISION_TAG STREQUAL "")
+    SET(HG_REVISION_ID "hg-tip")
+  ELSE()
+    IF(HG_REVISION_TAG STREQUAL "null")
+      SET(HG_REVISION_TAG "trunk")
+    ELSEIF(HG_REVISION_TAG MATCHES "^r")
+      STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG)
+    ENDIF()
+    IF(HG_REVISION_DIST STREQUAL "0")
+      SET(HG_REVISION ${HG_REVISION_TAG})
+    ELSE()
+      SET(HG_REVISION
+        "${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}")
+    ENDIF()
+  ENDIF()
+ENDIF()
--- a/common/logging.h	Tue Apr 29 15:26:02 2014 +0200
+++ b/common/logging.h	Tue Apr 29 15:26:43 2014 +0200
@@ -17,6 +17,8 @@
  * @brief Logging and debugging functions
  */
 
+#include <stdio.h>
+
 #ifdef WIN32
 
 #include <windows.h>
@@ -79,8 +81,31 @@
  *
  * Prints an error to stderr
  */
-#define ERRORPRINTF(fmt, ...) fprintf(stderr, DEBUGPREFIX "ERROR: " fmt, ##__VA_ARGS__);
+#ifdef WIN32
+#  define ERRORPRINTF(fmt, ...) \
+  { \
+    char buf[512]; \
+    snprintf(buf, 511, "ERROR: " fmt, ##__VA_ARGS__); \
+    buf[511] = '\0'; \
+    OutputDebugStringA(buf); \
+  }
+#else
+# define ERRORPRINTF(fmt, ...) fprintf(stderr, DEBUGPREFIX "ERROR: " fmt, ##__VA_ARGS__);
+#endif
 
+/**
+ * @def PRINTLASTERROR(msg)
+ * @brief Prints the last windows error with a custom message
+ *
+ * Prints an error to stderr
+ */
+#define PRINTLASTERROR(msg) \
+  char *my_error = getLastErrorMsg(); \
+      if (my_error) { \
+        ERRORPRINTF(msg" : %s\n", my_error); \
+        free (my_error); \
+      } \
+  ERRORPRINTF ("Failed to get error information\n");
 
 
 #ifdef __cplusplus
--- a/common/util.c	Tue Apr 29 15:26:02 2014 +0200
+++ b/common/util.c	Tue Apr 29 15:26:43 2014 +0200
@@ -6,6 +6,8 @@
  * See LICENSE.txt for details.
  */
 #include "util.h"
+#include "logging.h"
+
 #ifndef _WIN32
 #include <unistd.h>
 #include <sys/types.h>
@@ -36,3 +38,82 @@
 #endif
   return ret;
 }
+
+bool is_admin()
+{
+#ifndef _WIN32
+  /* TODO implement */
+  return false;
+#else
+  bool retval = false;
+  BOOL in_admin_group = FALSE;
+  HANDLE hToken = NULL;
+  HANDLE hTokenToCheck = NULL;
+  DWORD cbSize = 0;
+  TOKEN_ELEVATION_TYPE elevation;
+  BYTE admin_id[SECURITY_MAX_SID_SIZE];
+
+  if (!OpenProcessToken(GetCurrentProcess(),
+                        TOKEN_QUERY | TOKEN_DUPLICATE, &hToken))
+    {
+      PRINTLASTERROR ("Failed to duplicate process token.\n");
+      return false;
+    }
+
+  if (!GetTokenInformation(hToken, TokenElevationType, &elevation,
+                           sizeof(elevation), &cbSize))
+    {
+      PRINTLASTERROR ("Failed to get token information.\n");
+      goto done;
+    }
+
+  /* If limited check the the linked token instead */
+  if (TokenElevationTypeLimited == elevation)
+    {
+      if (!GetTokenInformation(hToken, TokenLinkedToken, &hTokenToCheck,
+                               sizeof(hTokenToCheck), &cbSize))
+        {
+          PRINTLASTERROR ("Failed to get the linked token.\n");
+          goto done;
+        }
+    }
+
+  if (!hTokenToCheck) /* The linked token is already of the correct type */
+    {
+      if (!DuplicateToken(hToken, SecurityIdentification, &hTokenToCheck))
+        {
+          PRINTLASTERROR ("Failed to duplicate token for identification.\n");
+          goto done;
+        }
+    }
+
+  /* Do the sid dance for the adminSID */
+  cbSize = sizeof(admin_id);
+  if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &admin_id,
+                          &cbSize))
+    {
+      PRINTLASTERROR ("Failed to get admin sid.\n");
+      goto done;
+    }
+
+  /* The actual check */
+  if (!CheckTokenMembership(hTokenToCheck, &admin_id, &in_admin_group))
+    {
+      PRINTLASTERROR ("Failed to check token membership.\n");
+      goto done;
+    }
+
+  if (in_admin_group)
+    {
+      /* Winbool to standard bool */
+      retval = true;
+    }
+
+done:
+  if (hToken) CloseHandle(hToken);
+  if (hTokenToCheck) CloseHandle(hTokenToCheck);
+
+  return retval;
+#endif
+}
+
--- a/common/util.h	Tue Apr 29 15:26:02 2014 +0200
+++ b/common/util.h	Tue Apr 29 15:26:43 2014 +0200
@@ -12,6 +12,10 @@
  */
 #include <stdbool.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**@brief Check if the current process is running with elevated privileges.
  *
  * Elevates the current process token to check if it is marked as elevated.
@@ -20,4 +24,17 @@
  * @returns true if the current process is elevated.*/
 bool is_elevated();
 
+/**@brief Check if the user is in the administrators group.
+ *
+ * The function checks if the account that startet this process
+ * belongs to a user that is a member of the Administrators group.
+ *
+ * @returns True if the user is in the admin group. False otherwise or on error.
+ */
+bool is_admin();
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif // COMMON_UTIL_H
--- a/packaging/filelist.nsh	Tue Apr 29 15:26:02 2014 +0200
+++ b/packaging/filelist.nsh	Tue Apr 29 15:26:43 2014 +0200
@@ -9,7 +9,7 @@
 ; Keep it updated if you add new things.
 
 File "${files_dir}/cinst.exe"
-File "${files_dir}/m13ui.exe"
+File "${files_dir}/trustbridge.exe"
 File "${files_dir}/mozilla.exe"
 
 ; NSS: This should ultimately be static
--- a/packaging/tmp-createpackage.sh	Tue Apr 29 15:26:02 2014 +0200
+++ b/packaging/tmp-createpackage.sh	Tue Apr 29 15:26:43 2014 +0200
@@ -15,7 +15,7 @@
 
 TMPDIR=$(mktemp -d)
 
-EXEFILES=$(find . -name cinst.exe -o -name m13ui.exe -o -name mozilla.exe)
+EXEFILES=$(find . -name cinst.exe -o -name trustbridge.exe -o -name mozilla.exe)
 
 cp $NSSDIR/*.dll $TMPDIR
 cp $EXEFILES $TMPDIR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packaging/tmp-createpackage.sh.in	Tue Apr 29 15:26:43 2014 +0200
@@ -0,0 +1,29 @@
+# Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+# Software engineering by Intevation GmbH
+#
+# This file is Free Software under the GNU GPL (v>=2)
+# and comes with ABSOLUTELY NO WARRANTY!
+# See LICENSE.txt for details.
+
+#!/bin/bash
+
+#NSSDIR is hackish as this will be replaced by static compiling 
+# anyway
+
+NSSDIR="@NSS_BASE_DIR@/bin/"
+
+TMPDIR=$(mktemp -d)
+
+EXEFILES=$(find . -name cinst.exe -o -name trustbridge.exe -o -name mozilla.exe)
+
+cp $NSSDIR/*.dll $TMPDIR
+cp $EXEFILES $TMPDIR
+
+echo $TMPDIR
+makensis -Dfiles_dir=$TMPDIR \
+    -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \
+    -Dversion_number=@PROJECT_VERSION@ \
+    -Dsetupname="@CMAKE_BINARY_DIR@/TrustBridge-@PROJECT_VERSION@.exe" \
+    -Dproductname="TrustBridge" \
+    -Dproductname_short="TrustBridge" @CMAKE_SOURCE_DIR@/packaging/trustbridge.nsi
+rm -r $TMPDIR
--- a/packaging/trustbridge.nsi	Tue Apr 29 15:26:02 2014 +0200
+++ b/packaging/trustbridge.nsi	Tue Apr 29 15:26:43 2014 +0200
@@ -5,9 +5,6 @@
 ; and comes with ABSOLUTELY NO WARRANTY!
 ; See LICENSE.txt for details.
 
-; renameme.nsi
-; TODO Rename it!
-;
 ; This script creates the installer for renameme it needs the
 ; following definitions to be set when calling makensis:
 ;
@@ -36,7 +33,8 @@
 ;--------------------------------
 ;Version Information (for installer file properties)
 
-VIProductVersion "${version_number}" ;needs integer format: x.x.x.x
+;VIProductVersion "${version_number}" ;needs integer format: x.x.x.x
+VIProductVersion 1.0.0.0
 VIAddVersionKey "ProductName" "${productname_short}"
 VIAddVersionKey "Comments" "${productname_short} ist Freie Software"
 VIAddVersionKey "CompanyName" "${company}"
@@ -71,7 +69,7 @@
 !define MUI_WELCOMEPAGE_TITLE  "Willkommen bei der Installation des ${productname}"
 !define MUI_WELCOMEPAGE_TEXT "Dieser Assistent wird Sie durch die Installation von \
 ${productname} begleiten. $\r$\n$\r$\n\
-Der ${productname} ist eine Anwendung um Wurzelzertifikate auf ihrem System \
+${productname} ist eine Anwendung um Wurzelzertifikate auf ihrem System \
 zu installieren und aktuell zu halten. $\r$\n$\r$\n\
 Klicken Sie auf Weiter, um fortzufahren."
 
@@ -87,12 +85,13 @@
 ; Pages
 
 !define MUI_FINISHPAGE_TITLE  "Die Installation war erfolgreich"
-!define MUI_FINISHPAGE_TEXT  "Der ${productname} wurde auf Ihrem \
+!define MUI_FINISHPAGE_TEXT  "${productname} wurde auf Ihrem \
 Computer installliert. $\r$\n$\r$\n\
 Klicken Sie auf 'Fertig stellen', um den Installations-Assistenten\
 zu schließen."
-!define MUI_FINISHPAGE_RUN $INSTDIR\m13ui.exe
+!define MUI_FINISHPAGE_RUN $INSTDIR\trustbridge.exe
 !define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten"
+!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser
 !define MUI_FINISHPAGE_LINK "Mehr unter http://www.bsi.bund.de" 
 !define MUI_FINISHPAGE_LINK_LOCATION "http://www.bsi.bund.de"
 
@@ -116,6 +115,13 @@
   !insertmacro MULTIUSER_INIT
 FunctionEnd
 
+; If we run elevated we do not want to run
+; the UI elevated as this could be a security
+; problem.
+Function RunAsUser
+  ExecShell "" "$INSTDIR\trustbridge.exe"
+FunctionEnd
+
 ;--------------------------------
 ; UnInstall Functions
 
@@ -130,14 +136,17 @@
 
   WriteRegStr SHCTX "Software\${productname_short}" "" $INSTDIR
 
-    ;Create uninstaller
+; Set up autostart
+  WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Run" "TrustBridge" "$INSTDIR\trustbridge.exe --tray"
+
+;Create uninstaller
   WriteUninstaller "$INSTDIR\Uninstall.exe"
 
   !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
 
   ;Create shortcuts
   CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
-  CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${productname}.lnk" "$INSTDIR\m13ui.exe"
+  CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${productname}.lnk" "$INSTDIR\trustbridge.exe"
 
   !insertmacro MUI_STARTMENU_WRITE_END
 
--- a/ui/CMakeLists.txt	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/CMakeLists.txt	Tue Apr 29 15:26:43 2014 +0200
@@ -12,26 +12,33 @@
 
 find_package(Qt5LinguistTools)
 
-set(CERTIFICATELIST_SOURCES
+# Common code is used in either the client or the administrator
+# application or in unit tests.
+set(UICOMMON_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/certificatelist.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/certificate.cpp
-)
-
-set(DOWNLOADER_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/downloader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/sslconnection.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/sslhelp.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/aboutdialog.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/createcertlistdialog.cpp
 )
 
+# Cmake does not correctly identify gcc windres when cross compiling
+# making this line neccessary to set the correct flags for it.
+# See: http://public.kitware.com/Bug/view.php?id=11773
+SET(CMAKE_RC_COMPILE_OBJECT
+      "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -Ocoff <SOURCE> <OBJECT>")
+
 set(TRUSTBRIDGE_SOURCES
-    ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/helpdialog.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/aboutdialog.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/statusdialog.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/certificateitemdelegate.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/separatoritemdelegate.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/installwrapper.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/img/icon.rc
     ${CERTIFICATELIST_SOURCES}
     ${DOWNLOADER_SOURCES}
 )
@@ -42,9 +49,6 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/certificatetablemodel.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/certificatetabledelegate.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/createinstallerdialog.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/createcertlistdialog.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/aboutdialog.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/sslhelp.cpp
     ${CERTIFICATELIST_SOURCES}
 )
 
@@ -107,6 +111,12 @@
 set(ADMINSTRATOR_SOURCES_WITH_RESOURCES ${ADMINSTRATOR_SOURCES})
 qt5_add_resources(ADMINSTRATOR_SOURCES_WITH_RESOURCES ${ADMINSTRATOR_RESOURCES})
 
+if(WIN32)
+   # This option causes cmake to use the appropiate liker flags to hide
+   # the console Window on Windows
+   set (_add_executable_params WIN32)
+endif()
+
 if(Qt5LinguistTools_FOUND)
    # Include translation as a resource
    # This works in the source directory to enable the rcc dependencies to be found
@@ -116,7 +126,9 @@
    qt5_add_resources(ADMINISTRATOR_L10N ${CMAKE_CURRENT_BINARY_DIR}/administrator.qrc)
    qt5_create_translation(ADMINISTRATOR_TRANSLATION ${ADMINSTRATOR_SOURCES_WITH_RESOURCES}
       ${CMAKE_CURRENT_SOURCE_DIR}/l10n/administrator_de_DE.ts)
-   add_executable(administrator ${ADMINSTRATOR_SOURCES_WITH_RESOURCES}
+   add_executable(trustbridge-admin
+      ${_add_executable_params}
+      ${ADMINSTRATOR_SOURCES_WITH_RESOURCES}
       ${ADMINISTRATOR_L10N}
       ${ADMINISTRATOR_TRANSLATION}
       )
@@ -125,24 +137,34 @@
    qt5_add_resources(TRUSTBRIDGE_L10N ${CMAKE_CURRENT_BINARY_DIR}/trustbridge.qrc)
    qt5_create_translation(TRUSTBRIDGE_TRANSLATION ${TRUSTBRIDGE_SOURCES_WITH_RESOURCES}
       ${CMAKE_CURRENT_SOURCE_DIR}/l10n/trustbridge_de_DE.ts)
-   add_executable(trustbridge ${TRUSTBRIDGE_SOURCES_WITH_RESOURCES}
+   add_executable(trustbridge
+      ${_add_executable_params}
+      ${TRUSTBRIDGE_SOURCES_WITH_RESOURCES}
       ${TRUSTBRIDGE_L10N}
       ${TRUSTBRIDGE_TRANSLATION}
       )
 
 else()
    message (STATUS "WARNING: Could not find qt linguist tools. Translation will not be included.")
-   add_executable(administrator ${ADMINSTRATOR_SOURCES_WITH_RESOURCES})
-   add_executable(trustbridge ${TRUSTBRIDGE_SOURCES_WITH_RESOURCES})
+   add_executable(trustbridge-admin
+      ${_add_executable_params}
+      ${ADMINSTRATOR_SOURCES_WITH_RESOURCES})
+   add_executable(trustbridge
+      ${_add_executable_params}
+      ${TRUSTBRIDGE_SOURCES_WITH_RESOURCES})
 endif()
 
-target_link_libraries(administrator Qt5::Widgets
+add_library(ui_common STATIC ${UICOMMON_SOURCES})
+
+target_link_libraries(trustbridge-admin Qt5::Widgets
+   ui_common
    trustbridge_common
    ${POLARSSL_LIBRARIES}
    ${EXTRA_STATIC_LIBS}
    ${PROFILING_LIBS})
 
 target_link_libraries(trustbridge Qt5::Widgets
+   ui_common
    trustbridge_common
    ${POLARSSL_LIBRARIES}
    ${EXTRA_STATIC_LIBS}
@@ -153,4 +175,4 @@
 add_subdirectory(tests)
 
 install(TARGETS trustbridge DESTINATION bin)
-install(TARGETS administrator DESTINATION bin)
+install(TARGETS trustbridge-admin DESTINATION bin)
--- a/ui/administrator.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/administrator.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -19,7 +19,7 @@
 #endif
 
 #ifndef APPNAME
-#define APPNAME "trustbridge-administration"
+#define APPNAME "trustbridge-admin"
 #endif
 
 #ifndef ORGANIZATION
--- a/ui/administratorwindow.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/administratorwindow.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -138,14 +138,16 @@
 
 void AdministratorWindow::loadCertificateFile()
 {
+    QString lastCertFile = mSettings.value("LastCertList", QDir::homePath()).toString();
     QString certFile = QFileDialog::getOpenFileName(
-        this, tr("Select certificate list file"), QDir::homePath(), "*.txt");
+        this, tr("Select certificate list file"), lastCertFile, "*.txt");
     mCertList.readList(certFile.toLocal8Bit().constData());
     if (!mCertList.isValid()) {
-        qDebug() << "Not a valid list.";
+        QMessageBox::warning(this, tr("Error!"), tr("Failed to load the certificate list."));
     } else {
         certificateModel->removeAll();
         loadCertificateTable();
+        mSettings.setValue("LastCertList", certFile);
     }
 }
 
--- a/ui/createcertlistdialog.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/createcertlistdialog.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -258,7 +258,16 @@
         return;
     }
 
-    if (!outputFile.copy(archiveDir.filePath("current_certificates.txt"))) {
+    QString curCerts = archiveDir.filePath("current_certificates.txt");
+
+    if (QFile::exists(curCerts)) {
+        if (!QFile::remove(curCerts)) {
+            showErrorMessage(tr("Failed to update current_certificates.txt"));
+            return;
+        }
+    }
+
+    if (!outputFile.copy(curCerts)) {
         showErrorMessage(tr("Failed to write current_certificates file."));
         return;
     }
--- a/ui/createinstallerdialog.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/createinstallerdialog.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -14,13 +14,25 @@
 #include <QVBoxLayout>
 #include <QLabel>
 #include <QFileDialog>
+#include <QSettings>
+#include <QMessageBox>
 
 CreateInstallerDialog::CreateInstallerDialog(QMainWindow *parent) :
-    QDialog(parent)
+    QDialog(parent),
+    mProgress(this)
 {
+    QSettings settings;
     setWindowTitle(tr("Create binary installer"));
     setupGUI();
     resize(500, 250);
+    mCertFile->setText(settings.value("CodeSignCert", QString()).toString());
+    mBinaryFolder->setText(settings.value("LastBinaryFolder", QString()).toString());
+    mSaveFile->setText(settings.value("LastBinOutputFolder", QString()).toString());
+
+    connect(&mNSISProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(processFinished(int, QProcess::ExitStatus)));
+    connect(&mNSISProc, SIGNAL(error(QProcess::ProcessError)),
+            this, SLOT(processError(QProcess::ProcessError)));
 }
 
 void CreateInstallerDialog::setupGUI()
@@ -37,7 +49,7 @@
 
     QLabel *header = new QLabel("<h3>" + tr("Create binary installer") + "</h3>");
     QLabel *description = new QLabel(
-        tr("Create and sign a TrustBridge binary installer from source."));
+        tr("Create and sign a TrustBridge binary installer."));
     headerSubLayout->insertSpacing(0, 40);
     headerSubLayout->addWidget(description);
     QFrame *headerSeparator = new QFrame();
@@ -48,22 +60,22 @@
     headerLayout->addWidget(headerSeparator);
     headerLayout->insertSpacing(4, 10);
 
-    QLabel *archiveLabel = new QLabel(tr("Select source archive:"));
-    QLabel *certLabel = new QLabel(tr("Select code signing certificate (secret key):"));
+    QLabel *archiveLabel = new QLabel(tr("Select binary folder:"));
+    QLabel *certLabel = new QLabel(tr("Select code signing certificate:"));
     QLabel *saveLabel = new QLabel(tr("Select output folder:"));
     labelLayout->addWidget(archiveLabel);
     labelLayout->addWidget(certLabel);
     labelLayout->addWidget(saveLabel);
 
-    mArchiveFile = new QLineEdit();
+    mBinaryFolder = new QLineEdit();
     mCertFile = new QLineEdit();
     mSaveFile = new QLineEdit();
-    fieldLayout->addWidget(mArchiveFile);
+    fieldLayout->addWidget(mBinaryFolder);
     fieldLayout->addWidget(mCertFile);
     fieldLayout->addWidget(mSaveFile);
 
     QPushButton *archiveSelect = new QPushButton("...");
-    connect(archiveSelect, SIGNAL(clicked()), this, SLOT(openArchiveSelect()));
+    connect(archiveSelect, SIGNAL(clicked()), this, SLOT(openFolderSelect()));
     archiveSelect->setFixedWidth(30);
     QPushButton *certSelect = new QPushButton("...");
     connect(certSelect, SIGNAL(clicked()), this, SLOT(openCertificateSelect()));
@@ -100,35 +112,109 @@
 
     setLayout(topLayout);
 
+    mProgress.setWindowModality(Qt::WindowModal);
+    mProgress.setLabelText(tr("Creating installer package..."));
+    mProgress.setCancelButton(0);
+    mProgress.setRange(0,0);
+    mProgress.setMinimumDuration(0);
+
     return;
 }
 
 void CreateInstallerDialog::openCertificateSelect()
 {
+    QSettings settings;
     QString certFile = QFileDialog::getOpenFileName(
-        this, tr("Select certificate"), QDir::homePath(), "*.pem *.der *.crt");
+        this, tr("Select certificate"),
+        mCertFile->text().isEmpty() ? QDir::homePath() : mCertFile->text(),
+        "*.pem *.der *.crt");
+    settings.setValue("CodeSignCert", certFile);
     mCertFile->setText(certFile);
 }
 
-void CreateInstallerDialog::openArchiveSelect()
+void CreateInstallerDialog::openFolderSelect()
 {
-    QString archiveFile = QFileDialog::getOpenFileName(
-        this, tr("Select source archive"), QDir::homePath(), "*.zip *.tar.gz");
-    mArchiveFile->setText(archiveFile);
+    QSettings settings;
+    QString archiveFolder = QFileDialog::getExistingDirectory(
+        this, tr("Select binary folder"),
+        mBinaryFolder->text().isEmpty() ? QDir::homePath() : mBinaryFolder->text());
+    mBinaryFolder->setText(archiveFolder);
+    settings.setValue("LastBinaryFolder", archiveFolder);
 }
 
 void CreateInstallerDialog::openSaveLocation()
 {
+    QSettings settings;
     QString saveFile = QFileDialog::getExistingDirectory(
-        this, tr("Select target location"), QDir::homePath());
+        this, tr("Select target location"),
+        mSaveFile->text().isEmpty() ? QDir::homePath() : mSaveFile->text());
     mSaveFile->setText(saveFile);
+    settings.setValue("LastBinOutputFolder", saveFile);
+}
+
+void CreateInstallerDialog::showErrorMessage(const QString &msg)
+{
+    QMessageBox::warning(this, tr("Error!"), msg);
+}
+
+void CreateInstallerDialog::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+    qDebug() << "Finished: " << mNSISProc.readAll();
+    mProgress.cancel();
+}
+
+void CreateInstallerDialog::processError(QProcess::ProcessError error)
+{
+    qDebug() << "Error: " << mNSISProc.readAll();
+    mProgress.cancel();
 }
 
 void CreateInstallerDialog::createInstaller()
 {
-    qDebug() << "and now create the installer using:";
-    qDebug() << "source archive: " << mArchiveFile->text();
-    qDebug() << "certificate: " << mCertFile->text();
-    qDebug() << "target" << mSaveFile->text();
-    // TODO
+    QDir binDir(mBinaryFolder->text());
+    QDir outDir(mSaveFile->text());
+    if (mBinaryFolder->text().isEmpty() || !binDir.exists()) {
+        showErrorMessage(tr("Please select an existing input folder."));
+        return;
+    }
+    if (mCertFile->text().isEmpty()) {
+        showErrorMessage(tr("Please select a codesigning certificate."));
+        return;
+    }
+    if (mSaveFile->text().isEmpty() || !outDir.exists()) {
+        showErrorMessage(tr("Please select a output folder."));
+        return;
+    }
+    QSettings options(binDir.filePath("meta.ini"), QSettings::IniFormat);
+    options.sync();
+    QStringList keys = options.allKeys();
+    if (options.status() != QSettings::NoError || keys.size() < 1) {
+        showErrorMessage(tr("Folder %1 does not appear to contain a meta.ini")
+                .arg(binDir.path()));
+        return;
+    }
+
+    /* Copy windows directory contents to tmpdir */
+    QStringList arguments;
+    mNSISProc.setProgram("makensis");
+    mNSISProc.setProcessChannelMode(QProcess::MergedChannels);
+    mNSISProc.setWorkingDirectory(outDir.path());
+    arguments << QString::fromLatin1("-Dfiles_dir=") + binDir.path() + "/windows";
+    foreach (const QString &key, keys) {
+        arguments << QString::fromLatin1("-D%1=%2").arg(key,
+                options.value(key, QString()).toString());
+    }
+
+    arguments << binDir.path() + "/trustbridge.nsi";
+
+    qDebug() << "Starting makensis with arguments: " << arguments;
+    mNSISProc.setArguments(arguments);
+    mNSISProc.start();
+    mProgress.show();
+
+    if (!mNSISProc.waitForStarted() ||
+        mNSISProc.state() == QProcess::NotRunning) {
+        showErrorMessage(tr("Failed to start makensis.\n"
+            "Please ensure that makensis is installed and in your PATH variable."));
+    }
 }
--- a/ui/createinstallerdialog.h	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/createinstallerdialog.h	Tue Apr 29 15:26:43 2014 +0200
@@ -11,6 +11,8 @@
 #include <QDialog>
 #include <QMainWindow>
 #include <QLineEdit>
+#include <QProcess>
+#include <QProgressDialog>
 /**
  * @file createinstallerdialog.h
  * @brief The dialog to show settings and create an installer.
@@ -31,14 +33,27 @@
     void setupGUI();
 
     QLineEdit *mCertFile;
-    QLineEdit *mArchiveFile;
+    QLineEdit *mBinaryFolder;
     QLineEdit *mSaveFile;
 
+    QProcess mNSISProc;
+    QProgressDialog mProgress;
+
+    /** @brief show an error message with QMessageBox
+     *
+     * @param [in] msg The message to show
+     */
+    void showErrorMessage(const QString &msg);
+
 private slots:
     void openCertificateSelect();
-    void openArchiveSelect();
+    void openFolderSelect();
     void openSaveLocation();
     void createInstaller();
+
+    /* Slots for the creator process */
+    void processError(QProcess::ProcessError error);
+    void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
 };
 
 #endif // CREATEINSTALLERDIALOG_H
Binary file ui/img/icon.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/img/icon.rc	Tue Apr 29 15:26:43 2014 +0200
@@ -0,0 +1,1 @@
+IDI_ICON1               ICON    DISCARDABLE     "icon.ico"
--- a/ui/installwrapper.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/installwrapper.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -15,6 +15,7 @@
 #include <QDebug>
 
 #include "logging.h"
+#include "util.h"
 
 #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */
 
@@ -95,7 +96,11 @@
 
     shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
     shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
-    shExecInfo.lpVerb = L"runas";
+    if (!is_admin()) {
+        shExecInfo.lpVerb = L"open";
+    } else {
+        shExecInfo.lpVerb = L"runas";
+    }
     shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16());
     shExecInfo.lpParameters =  reinterpret_cast<LPCWSTR> (parameters.utf16());
 
--- a/ui/l10n/administrator_de_DE.ts	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/l10n/administrator_de_DE.ts	Tue Apr 29 15:26:43 2014 +0200
@@ -4,45 +4,14 @@
 <context>
     <name>AboutDialog</name>
     <message>
-        <location filename="../aboutdialog.cpp" line="35"/>
-        <source>TrustBridge</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="36"/>
-        <source>Version: </source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="50"/>
-        <source>TrustBridge is a secure root certificate installer for Windows and Linux.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="52"/>
         <source>The root certificate lists are managed by the German &lt;a href=&quot;https://www.bsi.bund.de&quot;&gt;Federal Office for Information Security (BSI)&lt;/a&gt;.
 
 </source>
-        <translation type="unfinished">Die Liste der Wurzelzertifikate wird vom &lt;a href=&quot;https://www.bsi.bund.de&quot;&gt;Bundesamt für Sicherheit in der Informationstechnik (BSI)&lt;/a&gt; verwaltet.</translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="55"/>
-        <source>The software was developed by the companies &lt;a href=&quot;http://www.intevation.de&quot;&gt;Intevation GmbH&lt;/a&gt; and  &lt;a href=&quot;http://www.dn-systems.de&quot;&gt;DN-Systems GmbH&lt;/a&gt;, &lt;br&gt; contracted by the German Federal Office for Information Security (BSI).
-
-</source>
-        <translation type="unfinished"></translation>
+        <translation type="obsolete">Die Liste der Wurzelzertifikate wird vom &lt;a href=&quot;https://www.bsi.bund.de&quot;&gt;Bundesamt für Sicherheit in der Informationstechnik (BSI)&lt;/a&gt; verwaltet.</translation>
     </message>
     <message>
-        <location filename="../aboutdialog.cpp" line="59"/>
-        <source>TrustBridge is Free Software licensed under GNU GPL v2+.
-
-Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="73"/>
         <source>Close</source>
-        <translation type="unfinished">Schließen</translation>
+        <translation type="obsolete">Schließen</translation>
     </message>
 </context>
 <context>
@@ -80,11 +49,21 @@
         <translation>In der Liste enthaltene Zertifikate:</translation>
     </message>
     <message>
-        <location filename="../administratorwindow.cpp" line="142"/>
+        <location filename="../administratorwindow.cpp" line="143"/>
         <source>Select certificate list file</source>
         <translation>Zertifikatsliste auswählen</translation>
     </message>
     <message>
+        <location filename="../administratorwindow.cpp" line="146"/>
+        <source>Error!</source>
+        <translation>Fehler!</translation>
+    </message>
+    <message>
+        <location filename="../administratorwindow.cpp" line="146"/>
+        <source>Failed to load the certificate list.</source>
+        <translation>Fehler beim Laden der Zertifikatsliste</translation>
+    </message>
+    <message>
         <source>All managed root certificates of the certificate list:</source>
         <translation type="vanished">Alle verwalteten Wurzelzertifikate der Zertifikatsliste:</translation>
     </message>
@@ -118,7 +97,7 @@
         <translation type="vanished">Zertifikatslistendatei auswählen</translation>
     </message>
     <message>
-        <location filename="../administratorwindow.cpp" line="161"/>
+        <location filename="../administratorwindow.cpp" line="163"/>
         <source>Select certificate</source>
         <translation>Zertifikat auswählen</translation>
     </message>
@@ -177,10 +156,8 @@
 <context>
     <name>CreateCertListDialog</name>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="30"/>
-        <location filename="../createcertlistdialog.cpp" line="52"/>
         <source>Save certificate list</source>
-        <translation>Zertifikatsliste speichern</translation>
+        <translation type="vanished">Zertifikatsliste speichern</translation>
     </message>
     <message>
         <source>Save all managed root certificates in a new, signed certificate list</source>
@@ -196,94 +173,78 @@
         <translation type="obsolete">Liste signieren</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="54"/>
         <source>Save all managed root certificates in a new, signed certificate list.</source>
-        <translation>Eine neue, signierte Zertifikatsliste erstellen.</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="84"/>
-        <source>In addition, each certificate list will be saved automatically in the archive directory:
-</source>
-        <translation>Zusätzlich wird jede Zertifikatsliste automatisch in diesem Ordner Archiviert:</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="94"/>
-        <source>Save list</source>
-        <translation>Liste speichern</translation>
+        <translation type="vanished">Eine neue, signierte Zertifikatsliste erstellen.</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="96"/>
-        <source>Cancel</source>
-        <translation>Abbrechen</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="121"/>
-        <source>Error!</source>
-        <translation>Fehler!</translation>
+        <source>In addition, each certificate list will be saved automatically in the archive directory:
+</source>
+        <translation type="vanished">Zusätzlich wird jede Zertifikatsliste automatisch in diesem Ordner Archiviert:</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="159"/>
-        <source>Select certificate</source>
-        <translation>Zertifikat auswählen</translation>
+        <source>Save list</source>
+        <translation type="vanished">Liste speichern</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="244"/>
-        <source>Failed to write list to: %1</source>
-        <translation>Fehler beim schreiben der Liste in Datei: %1</translation>
+        <source>Cancel</source>
+        <translation type="vanished">Abbrechen</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="137"/>
+        <source>Error!</source>
+        <translation type="vanished">Fehler!</translation>
+    </message>
+    <message>
+        <source>Select certificate</source>
+        <translation type="vanished">Zertifikat auswählen</translation>
+    </message>
+    <message>
+        <source>Failed to write list to: %1</source>
+        <translation type="vanished">Fehler beim schreiben der Liste in Datei: %1</translation>
+    </message>
+    <message>
         <source>Failed to load certificate: %1</source>
         <translatorcomment>English wording is wrong</translatorcomment>
-        <translation>Fehler beim laden des Schlüssels: %1</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="148"/>
-        <source>Only 3072 bit RSA keys are supported by the current format.</source>
-        <translation>Nur 3027 bit RSA Schlüssel werden vom aktuellen Format unterstützt.</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="172"/>
-        <source>Select target location</source>
-        <translation>Zielordner auswählen</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="228"/>
-        <source>Please select a valid rsa key.</source>
-        <translation>Kein Signaturschlüssel ausgewählt.</translation>
+        <translation type="vanished">Fehler beim laden des Schlüssels: %1</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="231"/>
-        <source>Please select an output location first.</source>
-        <translation>Kein Zielordner angegeben.</translation>
-    </message>
-    <message>
-        <location filename="../createcertlistdialog.cpp" line="252"/>
-        <source>Failed to create archive location.</source>
-        <translation>Fehler beim erstellen des Archivordners.</translation>
+        <source>Only 3072 bit RSA keys are supported by the current format.</source>
+        <translation type="vanished">Nur 3027 bit RSA Schlüssel werden vom aktuellen Format unterstützt.</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="257"/>
-        <source>Failed Archive a copy.</source>
-        <translation>Fehler beim speichern der Archivkopie.</translation>
+        <source>Select target location</source>
+        <translation type="vanished">Zielordner auswählen</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="262"/>
-        <source>Failed to write current_certificates file.</source>
-        <translation>Fehler beim schreiben der Datei &quot;current_certificates&quot;.</translation>
+        <source>Please select a valid rsa key.</source>
+        <translation type="vanished">Kein Signaturschlüssel ausgewählt.</translation>
     </message>
     <message>
-        <location filename="../createcertlistdialog.cpp" line="266"/>
+        <source>Please select an output location first.</source>
+        <translation type="vanished">Kein Zielordner angegeben.</translation>
+    </message>
+    <message>
+        <source>Failed to create archive location.</source>
+        <translation type="vanished">Fehler beim erstellen des Archivordners.</translation>
+    </message>
+    <message>
+        <source>Failed Archive a copy.</source>
+        <translation type="vanished">Fehler beim speichern der Archivkopie.</translation>
+    </message>
+    <message>
+        <source>Failed to write current_certificates file.</source>
+        <translation type="vanished">Fehler beim schreiben der Datei &quot;current_certificates&quot;.</translation>
+    </message>
+    <message>
         <source>Saved certificate list:
 %1</source>
-        <translation>Zertifikatsliste: %1 gespeichert.</translation>
+        <translation type="vanished">Zertifikatsliste: %1 gespeichert.</translation>
     </message>
 </context>
 <context>
     <name>CreateInstallerDialog</name>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="21"/>
-        <location filename="../createinstallerdialog.cpp" line="38"/>
+        <location filename="../createinstallerdialog.cpp" line="25"/>
+        <location filename="../createinstallerdialog.cpp" line="50"/>
         <source>Create binary installer</source>
         <translation>Installationspaket erstellen</translation>
     </message>
@@ -292,47 +253,96 @@
         <translation type="vanished">Ein TrustBridge-Installationspaket aus den Quellen erstellen und signieren.</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="40"/>
-        <source>Create and sign a TrustBridge binary installer from source.</source>
-        <translation type="unfinished"></translation>
+        <source>Select source archive:</source>
+        <translation type="vanished">Quellcode-Archiv auswählen:</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="51"/>
-        <source>Select source archive:</source>
-        <translation>Quellcode-Archiv auswählen:</translation>
+        <source>Select code signing certificate (secret key):</source>
+        <translation type="vanished">Code Signing Zertifikat auswählen (privater Schlüssel):</translation>
     </message>
     <message>
         <location filename="../createinstallerdialog.cpp" line="52"/>
-        <source>Select code signing certificate (secret key):</source>
-        <translation>Code Signing Zertifikat auswählen (privater Schlüssel):</translation>
+        <source>Create and sign a TrustBridge binary installer.</source>
+        <translation>Erzeugt und signiert ein TrustBridge-Installationspaket.</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="53"/>
+        <location filename="../createinstallerdialog.cpp" line="63"/>
+        <source>Select binary folder:</source>
+        <translation>Binärverzeichnis auswählen:</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="64"/>
+        <source>Select code signing certificate:</source>
+        <translation>Code-Signing-Zertifikat auswählen:</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="65"/>
         <source>Select output folder:</source>
         <translation>Ausgabeverzeichnis auswählen:</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="82"/>
+        <location filename="../createinstallerdialog.cpp" line="94"/>
         <source>Create installer</source>
         <translation>Installationspaket erzeugen</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="84"/>
+        <location filename="../createinstallerdialog.cpp" line="96"/>
         <source>Cancel</source>
         <translation>Abbrechen</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="109"/>
+        <location filename="../createinstallerdialog.cpp" line="116"/>
+        <source>Creating installer package...</source>
+        <translation>Installationspaket wird erstellt...</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="128"/>
         <source>Select certificate</source>
         <translation>Zertifikat auswählen</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="116"/>
-        <source>Select source archive</source>
-        <translation>Archiv auswählen</translation>
+        <location filename="../createinstallerdialog.cpp" line="139"/>
+        <source>Select binary folder</source>
+        <translation>Binärverzeichnis auswählen</translation>
     </message>
     <message>
-        <location filename="../createinstallerdialog.cpp" line="123"/>
+        <location filename="../createinstallerdialog.cpp" line="157"/>
+        <source>Error!</source>
+        <translation>Fehler!</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="177"/>
+        <source>Please select an existing input folder.</source>
+        <translation>Bitte wählen Sie ein existierendes Eingabeverzeichnis.</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="181"/>
+        <source>Please select a codesigning certificate.</source>
+        <translation>Bitte wählen Sie ein Code-Signing-Zertifikat.</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="185"/>
+        <source>Please select a output folder.</source>
+        <translation>Bitte wählen Sie ein Ausgabeverzeichnis.</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="192"/>
+        <source>Folder %1 does not appear to contain a meta.ini</source>
+        <translation>Das Verzeichnis %1 enthält keine meta.ini Datei</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="217"/>
+        <source>Failed to start makensis.
+Please ensure that makensis is installed and in your PATH variable.</source>
+        <translation>Fehler beim Starten von makensis.
+Bitte versichern Sie sich, dass makensis korrekt installiert und in der PATH-Variable enthalten ist.</translation>
+    </message>
+    <message>
+        <source>Select source archive</source>
+        <translation type="vanished">Archiv auswählen</translation>
+    </message>
+    <message>
+        <location filename="../createinstallerdialog.cpp" line="149"/>
         <source>Select target location</source>
         <translation>Zielort auswählen</translation>
     </message>
@@ -340,22 +350,8 @@
 <context>
     <name>QObject</name>
     <message>
-        <location filename="../certificate.cpp" line="75"/>
-        <source>Certificate:
-    &lt;bold&gt;%1&lt;/bold&gt;
-    %2, %3
-
-Serial number:
-%4
-Valid from: &lt;bold&gt;%5&lt;/bold&gt; to &lt;bold&gt;%6&lt;/bold&gt;
-
-Issued by: ..</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../certificate.cpp" line="129"/>
         <source>Failed to parse certificate</source>
-        <translation>Fehler beim Parsen des Zertifikats</translation>
+        <translation type="vanished">Fehler beim Parsen des Zertifikats</translation>
     </message>
 </context>
 </TS>
--- a/ui/l10n/trustbridge_de_DE.ts	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/l10n/trustbridge_de_DE.ts	Tue Apr 29 15:26:43 2014 +0200
@@ -2,392 +2,300 @@
 <!DOCTYPE TS>
 <TS version="2.1" language="de_DE">
 <context>
-    <name>AboutDialog</name>
-    <message>
-        <location filename="../aboutdialog.cpp" line="35"/>
-        <source>TrustBridge</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="36"/>
-        <source>Version: </source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="50"/>
-        <source>TrustBridge is a secure root certificate installer for Windows and Linux.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="52"/>
-        <source>The root certificate lists are managed by the German &lt;a href=&quot;https://www.bsi.bund.de&quot;&gt;Federal Office for Information Security (BSI)&lt;/a&gt;.
-
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="55"/>
-        <source>The software was developed by the companies &lt;a href=&quot;http://www.intevation.de&quot;&gt;Intevation GmbH&lt;/a&gt; and  &lt;a href=&quot;http://www.dn-systems.de&quot;&gt;DN-Systems GmbH&lt;/a&gt;, &lt;br&gt; contracted by the German Federal Office for Information Security (BSI).
-
-</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="59"/>
-        <source>TrustBridge is Free Software licensed under GNU GPL v2+.
-
-Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../aboutdialog.cpp" line="73"/>
-        <source>Close</source>
-        <translation type="unfinished"></translation>
-    </message>
-</context>
-<context>
-    <name>Downloader</name>
-    <message>
-        <location filename="../downloader.cpp" line="82"/>
-        <source>Invalid response</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="117"/>
-        <location filename="../downloader.cpp" line="125"/>
-        <location filename="../downloader.cpp" line="164"/>
-        <location filename="../downloader.cpp" line="176"/>
-        <source>Connection lost</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="139"/>
-        <source>Invalid response from the server</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="202"/>
-        <source>Failed to initialize SSL Module.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="209"/>
-        <source>Failed to connect.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="214"/>
-        <source>Connected</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../downloader.cpp" line="274"/>
-        <source>Closing</source>
-        <translation type="unfinished"></translation>
-    </message>
-</context>
-<context>
     <name>HelpDialog</name>
     <message>
         <location filename="../helpdialog.cpp" line="25"/>
         <source>This dialog contains some text to help the user.</source>
-        <translation type="unfinished"></translation>
+        <translation>Dieser Dialog enthält die Hilfe für den Benutzer.</translation>
     </message>
     <message>
         <location filename="../helpdialog.cpp" line="28"/>
         <source>Close</source>
-        <translation type="unfinished"></translation>
+        <translation>Schließen</translation>
     </message>
 </context>
 <context>
     <name>InstallWrapper</name>
     <message>
-        <location filename="../installwrapper.cpp" line="70"/>
+        <location filename="../installwrapper.cpp" line="71"/>
         <source>Could not find certificate installation process.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../installwrapper.cpp" line="75"/>
-        <source>Failed to write temporary file.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../installwrapper.cpp" line="108"/>
-        <source>Error executing process: %1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../installwrapper.cpp" line="119"/>
-        <source>Error monitoring process: %1</source>
-        <translation type="unfinished"></translation>
+        <translation>Der Zertifikatsinstallations-Prozess konnte nicht gefunden werden.</translation>
     </message>
     <message>
-        <location filename="../installwrapper.cpp" line="122"/>
-        <source>Certificate installation timed out.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../installwrapper.cpp" line="135"/>
-        <source>Failed to check process status: %1</source>
-        <translation type="unfinished"></translation>
+        <location filename="../installwrapper.cpp" line="76"/>
+        <source>Failed to write temporary file.</source>
+        <translation>Fehler beim Schreiben der temporären Datei.</translation>
     </message>
     <message>
-        <location filename="../installwrapper.cpp" line="143"/>
-        <source>The process failed with return code. %1</source>
-        <translation type="unfinished"></translation>
+        <location filename="../installwrapper.cpp" line="113"/>
+        <source>Error executing process: %1</source>
+        <translation>Auführungsfehler: %1</translation>
     </message>
     <message>
-        <location filename="../installwrapper.cpp" line="160"/>
-        <source>Failed to start installer process.</source>
-        <translation type="unfinished"></translation>
+        <location filename="../installwrapper.cpp" line="124"/>
+        <source>Error monitoring process: %1</source>
+        <translation>Fehlerüberwachung: %1</translation>
     </message>
     <message>
-        <location filename="../installwrapper.cpp" line="168"/>
+        <location filename="../installwrapper.cpp" line="127"/>
+        <source>Certificate installation timed out.</source>
+        <translation>Zeitüberschreitung bei der Zertifikatsinstallation.</translation>
+    </message>
+    <message>
+        <location filename="../installwrapper.cpp" line="140"/>
+        <source>Failed to check process status: %1</source>
+        <translation>Fehler in der Prozess-Statusprüfung: %1</translation>
+    </message>
+    <message>
+        <location filename="../installwrapper.cpp" line="148"/>
+        <source>The process failed with return code. %1</source>
+        <translation>Der Prozess ist fehlgeschlagen. Fehlercode: %1</translation>
+    </message>
+    <message>
+        <location filename="../installwrapper.cpp" line="165"/>
+        <source>Failed to start installer process.</source>
+        <translation>Fehler beim Starten des Installer-Prozess.</translation>
+    </message>
+    <message>
         <location filename="../installwrapper.cpp" line="173"/>
+        <location filename="../installwrapper.cpp" line="178"/>
         <source>Failed to complete installation.</source>
-        <translation type="unfinished"></translation>
+        <translation>Fehler beim Abschließen der Installation.</translation>
     </message>
 </context>
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../mainwindow.cpp" line="166"/>
+        <location filename="../mainwindow.cpp" line="172"/>
         <source>An updated certificate list is available. Click here to install.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="174"/>
-        <source>An update for %1 is available. Click here to install.</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="230"/>
-        <source>New Software version is available.</source>
-        <translation type="unfinished"></translation>
+        <translation>Eine aktualisierte Zertifikatsliste ist verfügbar. Klicken Sie hier zum Installieren.</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="231"/>
-        <source>Do you want to install the new Version?</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="249"/>
-        <source>Check for Updates</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="180"/>
+        <source>An update for %1 is available. Click here to install.</source>
+        <translation>Eine Aktualisierung für %1 ist verfügbar. Klicken Sie hier zum Installieren.</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="251"/>
-        <location filename="../mainwindow.cpp" line="286"/>
-        <location filename="../mainwindow.cpp" line="358"/>
-        <source>Quit</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="271"/>
+        <source>New Software version is available.</source>
+        <translation>Neue Softwareversion verfügbar.</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="269"/>
-        <source>TrustBridge</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="272"/>
+        <source>Do you want to install the new Version?</source>
+        <translatorcomment>typo: _v_ersion</translatorcomment>
+        <translation>Möchten Sie die neue Version installieren?</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="277"/>
+        <location filename="../mainwindow.cpp" line="290"/>
+        <source>Check for Updates</source>
+        <translation>Aktualisierungen prüfen</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="292"/>
+        <location filename="../mainwindow.cpp" line="327"/>
+        <location filename="../mainwindow.cpp" line="409"/>
+        <source>Quit</source>
+        <translation>Beenden</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="310"/>
+        <source>TrustBridge</source>
+        <translation>TrustBridge</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="318"/>
         <source>Menu</source>
         <translation>Menü</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="279"/>
+        <location filename="../mainwindow.cpp" line="320"/>
         <source>Force Update</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="280"/>
-        <location filename="../mainwindow.cpp" line="344"/>
-        <source>Settings</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="281"/>
-        <source>Statusdialog</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="283"/>
-        <source>Help</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="284"/>
-        <source>About</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="315"/>
-        <source>Managed Certificates</source>
-        <translation type="unfinished"></translation>
+        <translation>Aktualisierung erzwingen</translation>
     </message>
     <message>
         <location filename="../mainwindow.cpp" line="321"/>
-        <location filename="../mainwindow.cpp" line="442"/>
-        <location filename="../mainwindow.cpp" line="472"/>
-        <source>Current List Date: %1</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="345"/>
-        <source>Autoupdate</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="346"/>
-        <source>Autostart</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="354"/>
-        <source>Install selected</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="368"/>
-        <source>Details</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="369"/>
-        <source>Subject Common Name:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="370"/>
-        <source>Subject Organisation:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="371"/>
-        <source>Issuer Common Name:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="372"/>
-        <source>Issuer Organisation:</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="385"/>
+        <source>Settings</source>
+        <translation>Einstellungen</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="373"/>
-        <source>Valid from:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="374"/>
-        <source>Valid to:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="375"/>
-        <source>Fingerprint:</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="474"/>
-        <source>New List Date: %1</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="322"/>
+        <source>Statusdialog</source>
+        <translation>Statusdialog</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="478"/>
-        <source>New certificates to install</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../mainwindow.cpp" line="483"/>
-        <source>New certificates to remove</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="324"/>
+        <source>Help</source>
+        <translation>Hilfe</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="488"/>
-        <source>Old certificates to install</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="325"/>
+        <source>About</source>
+        <translatorcomment>&quot;TrustBridge&quot; ergänzen</translatorcomment>
+        <translation>Über TrustBridge</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="493"/>
-        <source>Old certificates to remove</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="356"/>
+        <source>Managed Certificates</source>
+        <translation>Verwaltete Zertifikate</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="579"/>
-        <source>Error executing update</source>
-        <translation type="unfinished"></translation>
+        <location filename="../mainwindow.cpp" line="362"/>
+        <location filename="../mainwindow.cpp" line="500"/>
+        <location filename="../mainwindow.cpp" line="530"/>
+        <source>Current List Date: %1</source>
+        <translation>Datum der aktuellen Liste: %1</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="621"/>
+        <location filename="../mainwindow.cpp" line="386"/>
+        <source>Autoupdate</source>
+        <translation>Automatische Aktualisierung</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="387"/>
+        <source>Autostart</source>
+        <translation>Start der Anwendung bei Systemstart</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="405"/>
+        <source>Install selected</source>
+        <translation>Jetzt installieren</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="426"/>
+        <source>Details</source>
+        <translation>Details</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="427"/>
+        <source>Subject Common Name:</source>
+        <translation>Inhaber CN:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="428"/>
+        <source>Subject Organisation:</source>
+        <translation>Inhaber Organisation:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="429"/>
+        <source>Issuer Common Name:</source>
+        <translation>Aussteller CN:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="430"/>
+        <source>Issuer Organisation:</source>
+        <translation>Aussteller Organidation:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="431"/>
+        <source>Valid from:</source>
+        <translation>Gültig ab:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="432"/>
+        <source>Valid to:</source>
+        <translation>Gültig bis:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="433"/>
+        <source>Fingerprint:</source>
+        <translation>Fingerprint:</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="532"/>
+        <source>New List Date: %1</source>
+        <translation>Datum der neuen Liste: %1</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="537"/>
+        <source>New certificates to install</source>
+        <translation>Neu zu installierende Zertifikate</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="544"/>
+        <source>New certificates to remove</source>
+        <translation>Neu zu löschende Zertifikate</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="551"/>
+        <source>Old certificates to install</source>
+        <translation>Bisher installierte Zertifikate</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="558"/>
+        <source>Old certificates to remove</source>
+        <translation>Bisher gelöschte Zertifikate</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="645"/>
+        <source>Error executing update</source>
+        <translation>Fehler bei der Aktualisierung</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="690"/>
         <source>Installing certificates...</source>
-        <translation type="unfinished"></translation>
+        <translation>Zertifikate werden installiert...</translation>
     </message>
 </context>
 <context>
     <name>QObject</name>
     <message>
-        <location filename="../certificate.cpp" line="75"/>
-        <source>Certificate:
-    &lt;bold&gt;%1&lt;/bold&gt;
-    %2, %3
-
-Serial number:
-%4
-Valid from: &lt;bold&gt;%5&lt;/bold&gt; to &lt;bold&gt;%6&lt;/bold&gt;
-
-Issued by: ..</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../certificate.cpp" line="129"/>
-        <source>Failed to parse certificate</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../main.cpp" line="57"/>
+        <location filename="../main.cpp" line="72"/>
         <source>Couldn&apos;t detect any system tray on this system. This software can only be used in a desktop environment.</source>
-        <translation type="unfinished"></translation>
+        <translation>Es konnte kein SystemTray auf diesem System gefunden werden. Diese Software kann nur in einer Desktopumgebung verwendet werden.</translation>
     </message>
 </context>
 <context>
     <name>StatusDialog</name>
     <message>
         <location filename="../statusdialog.cpp" line="25"/>
-        <source>The following certificates are successfully installed:
</source>
-        <translation type="unfinished"></translation>
+        <source>The following certificates are successfully installed:
+</source>
+        <translation>Die folgenden Zertifikate wurden erfolgreich installiert:</translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="26"/>
-        <source>* Email CA 2013
</source>
+        <source>* Email CA 2013
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="27"/>
-        <source>* Server CA 2010
</source>
+        <source>* Server CA 2010
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="28"/>
-        <source>
The following certificates are successfully removed:
</source>
+        <source>
+The following certificates are successfully removed:
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="29"/>
-        <source>* Email CA 2010
</source>
+        <source>* Email CA 2010
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="30"/>
-        <source>
Errors while processing certificates:
</source>
+        <source>
+Errors while processing certificates:
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="31"/>
-        <source>* PCA-1-Verwaltung-08
</source>
+        <source>* PCA-1-Verwaltung-08
+</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../statusdialog.cpp" line="35"/>
         <source>Close</source>
-        <translation type="unfinished"></translation>
+        <translation>Schließen</translation>
     </message>
 </context>
 </TS>
--- a/ui/main.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/main.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -48,10 +48,10 @@
 
     QSettings settings;
     settings.beginGroup("settings");
-    int autoStart = settings.value("autostart").toInt();
+    bool autoStart = settings.value("autostart", true).toBool();
     settings.endGroup();
 
-    if (trayMode && autoStart <= 0) {
+    if (trayMode && !autoStart) {
         return 0;
     }
 
--- a/ui/mainwindow.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/mainwindow.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -50,6 +50,7 @@
 #include "certificateitemdelegate.h"
 #include "separatoritemdelegate.h"
 #include "installwrapper.h"
+#include "util.h"
 
 MainWindow::MainWindow(bool trayMode):
     mTrayMode(trayMode)
@@ -392,11 +393,11 @@
     connect(mAutoStartOption, SIGNAL(stateChanged(int)),
         this, SLOT(saveAutoStart(int)));
     mSettings.beginGroup("settings");
-    int autoUpdate = mSettings.value("autoupdate").toInt();
-    int autoStart = mSettings.value("autostart").toInt();
+    bool autoUpdate = mSettings.value("autoupdate", false).toBool();
+    bool autoStart = mSettings.value("autostart", true).toBool();
     mSettings.endGroup();
-    mAutoUpdateOption->setCheckState(autoUpdate > 0 ? Qt::Checked : Qt::Unchecked);
-    mAutoStartOption->setCheckState(autoStart > 0 ? Qt::Checked : Qt::Unchecked);
+    mAutoUpdateOption->setCheckState(autoUpdate ? Qt::Checked : Qt::Unchecked);
+    mAutoStartOption->setCheckState(autoStart ? Qt::Checked : Qt::Unchecked);
 
 
     // The buttons.
@@ -414,6 +415,13 @@
     bottomLayout->addWidget(quitButton);
     bottomLayout->setAlignment(quitButton, Qt::AlignBottom);
 
+#ifdef Q_OS_WIN
+    if (is_admin()) {
+        QIcon uacShield = QApplication::style()->standardIcon(QStyle::SP_VistaShield);
+        installButton->setIcon(uacShield);
+    }
+#endif
+
     // The certificate details
     QGroupBox *detailBox = new QGroupBox(tr("Details"));
     QLabel *subjectCN = new QLabel(tr("Subject Common Name:"));
@@ -525,24 +533,32 @@
     }
 
     // Add separators and certificates to list widget.
-    mCertListWidget->addItem(createSeparator(tr("New certificates to install"), i++));
-    foreach (const Certificate &cert, newInstallCerts) {
-        mCertListWidget->addItem(createListItem(cert, Certificate::InstallNew, i++));
+    if (!newInstallCerts.isEmpty()) {
+        mCertListWidget->addItem(createSeparator(tr("New certificates to install"), i++));
+        foreach (const Certificate &cert, newInstallCerts) {
+            mCertListWidget->addItem(createListItem(cert, Certificate::InstallNew, i++));
+        }
     }
 
-    mCertListWidget->addItem(createSeparator(tr("New certificates to remove"), i++));
-    foreach (const Certificate &cert, newRemoveCerts) {
-        mCertListWidget->addItem(createListItem(cert, Certificate::RemoveNew, i++));
+    if (!newRemoveCerts.isEmpty()) {
+        mCertListWidget->addItem(createSeparator(tr("New certificates to remove"), i++));
+        foreach (const Certificate &cert, newRemoveCerts) {
+            mCertListWidget->addItem(createListItem(cert, Certificate::RemoveNew, i++));
+        }
     }
 
-    mCertListWidget->addItem(createSeparator(tr("Old certificates to install"), i++));
-    foreach (const Certificate &cert, oldInstallCerts) {
-        mCertListWidget->addItem(createListItem(cert, Certificate::InstallOld, i++));
+    if (!oldInstallCerts.isEmpty()) {
+        mCertListWidget->addItem(createSeparator(tr("Old certificates to install"), i++));
+        foreach (const Certificate &cert, oldInstallCerts) {
+            mCertListWidget->addItem(createListItem(cert, Certificate::InstallOld, i++));
+        }
     }
 
-    mCertListWidget->addItem(createSeparator(tr("Old certificates to remove"), i++));
-    foreach (const Certificate &cert, oldRemoveCerts) {
-        mCertListWidget->addItem(createListItem(cert, Certificate::RemoveOld, i++));
+    if (!oldRemoveCerts.isEmpty()) {
+        mCertListWidget->addItem(createSeparator(tr("Old certificates to remove"), i++));
+        foreach (const Certificate &cert, oldRemoveCerts) {
+            mCertListWidget->addItem(createListItem(cert, Certificate::RemoveOld, i++));
+        }
     }
 }
 
@@ -732,14 +748,14 @@
 void MainWindow::saveAutoUpdate(int state)
 {
     mSettings.beginGroup("settings");
-    mSettings.setValue("autoupdate", state);
+    mSettings.setValue("autoupdate", state != Qt::Unchecked);
     mSettings.endGroup();
 }
 
 void MainWindow::saveAutoStart(int state)
 {
     mSettings.beginGroup("settings");
-    mSettings.setValue("autostart", state);
+    mSettings.setValue("autostart", state != Qt::Unchecked);
     mSettings.endGroup();
 }
 
--- a/ui/tests/CMakeLists.txt	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/tests/CMakeLists.txt	Tue Apr 29 15:26:43 2014 +0200
@@ -31,7 +31,9 @@
      ${CMAKE_CURRENT_SOURCE_DIR}/data/testdata.qrc)
   add_executable(${_name} ${_test_sources_with_resources})
   add_test(tb-${_name} ${_name})
-  target_link_libraries(${_name} Qt5::Test Qt5::Widgets
+  target_link_libraries(${_name}
+     ui_common
+     Qt5::Test Qt5::Widgets
      trustbridge_common
      ${POLARSSL_LIBRARIES}
      ${EXTRA_STATIC_LIBS})
@@ -44,26 +46,24 @@
 
 # Downloader
 if (HIAWATHA_EXECUTABLE)
-  set(DOWNLOADER_SOURCES_WITH_RESOURCES ${DOWNLOADER_SOURCES})
   qt5_add_resources(DOWNLOADER_SOURCES_WITH_RESOURCES ${TRUSTBRIDGE_RESOURCES})
   add_custom_test(downloadertest.cpp "${DOWNLOADER_SOURCES_WITH_RESOURCES}")
 endif()
 
 # Cinstprocess
-add_custom_test(cinstprocesstest.cpp "${CERTIFICATELIST_SOURCES}")
+add_custom_test(cinstprocesstest.cpp "")
 add_dependencies(cinstprocesstest cinst)
 add_custom_test(commontest.cpp "")
 
-add_custom_test(createcertlisttest.cpp "${CERTIFICATELIST_SOURCES};${CMAKE_SOURCE_DIR}/ui/sslhelp.cpp;${CMAKE_SOURCE_DIR}/ui/createcertlistdialog.cpp")
+add_custom_test(createcertlisttest.cpp "")
 
 if (WIN32)
-   add_custom_test(windowsstoretest.cpp "${CERTIFICATELIST_SOURCES};${CMAKE_SOURCE_DIR}/cinst/windowsstore.c")
+   add_custom_test(windowsstoretest.cpp "${CMAKE_SOURCE_DIR}/cinst/windowsstore.c")
 endif (WIN32)
 
 if (NSS_FOUND)
    include_directories(${NSS_INCLUDE_DIRS})
    set(NSSTEST_SOURCES
-      ${CERTIFICATELIST_SOURCES}
       ${CMAKE_SOURCE_DIR}/cinst/nssstore_linux.c
       ${CMAKE_SOURCE_DIR}/cinst/nssstore_win.c)
    add_custom_test(nsstest.cpp "${NSSTEST_SOURCES}")
--- a/ui/tests/nsstest.cpp	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/tests/nsstest.cpp	Tue Apr 29 15:26:43 2014 +0200
@@ -89,9 +89,22 @@
     /* Create the profiles.ini `s set environment variables*/
 //    fakeHome.setAutoRemove(false);
 #ifndef WIN32
-    QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1));
     fakeFirefoxDir = QDir(fakeHome.path() + "/.mozilla/firefox");
     fakeThunderbirdDir = QDir(fakeHome.path() + "/.thunderbird");
+
+    /* Copy the current systems NSSSHARED db in the fake home for benchmark tests */
+    QDir fakeNSSSharedDir = fakeHome.path() + "/.pki/nssdb";
+    QVERIFY(fakeNSSSharedDir.mkpath(fakeNSSSharedDir.path()));
+    qDebug() << "Copying: " << QDir::homePath() + "/.pki/nssdb/cert9.db" <<
+            " to " << fakeNSSSharedDir.path() + "cert9.db";
+    QVERIFY(QFile::copy(QDir::homePath() + "/.pki/nssdb/cert9.db",
+            fakeNSSSharedDir.path() + "cert9.db"));
+    QVERIFY(QFile::copy(QDir::homePath() + "/.pki/nssdb/key4.db",
+            fakeNSSSharedDir.path() + "key4.db"));
+    QVERIFY(QFile::copy(QDir::homePath() + "/.pki/nssdb/pkcs11.txt",
+            fakeNSSSharedDir.path() + "pkcs11.txt"));
+
+    QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1));
 #else
     {
         char buf[fakeHome.path().toLocal8Bit().size() + 9];
@@ -225,4 +238,26 @@
     }
 }
 
+void NSSTest::benchmarkInstall()
+{
+    char ** to_install = NULL,
+         ** to_remove = NULL;
+
+    QList<Certificate> instList;
+
+    /* Install all certificates */
+    foreach (const Certificate &cert, validList.getCertificates()) {
+        if (!cert.isInstallCert())
+            continue;
+        instList << cert;
+        strv_append (&to_install, cert.base64Line().toLatin1().constData() + 2,
+                cert.base64Line().size() - 2);
+    }
+    QVERIFY((size_t) instList.size() == strv_length(to_install));
+    QVERIFY(strv_length(to_install) != 0);
+
+    QBENCHMARK {
+        write_stores_nss(to_install, to_remove);
+    }
+}
 QTEST_GUILESS_MAIN (NSSTest);
--- a/ui/tests/nsstest.h	Tue Apr 29 15:26:02 2014 +0200
+++ b/ui/tests/nsstest.h	Tue Apr 29 15:26:43 2014 +0200
@@ -34,6 +34,7 @@
 private Q_SLOTS:
     void initTestCase();
     void testInstRemove();
+    void benchmarkInstall();
 };
 
 #endif // NSSTEST_H

http://wald.intevation.org/projects/trustbridge/