diff --git a/.puppet/hiera/common.yaml b/.puppet/hiera/common.yaml
index 0a85ba63a..d7802181f 100644
--- a/.puppet/hiera/common.yaml
+++ b/.puppet/hiera/common.yaml
@@ -1,7 +1,8 @@
 ---
-icingaweb2::config:   /etc/icingaweb
-icingaweb2::log:      /var/log/icingaweb/icingaweb.log
-icingaweb2::web_path: icingaweb
-icingaweb2::db_user:  icingaweb
-icingaweb2::db_pass:  icingaweb
-icingaweb2::db_name:  icingaweb
+icingaweb2::config:   /etc/icingaweb2
+icingaweb2::log:      /var/log/icingaweb2/icingaweb2.log
+icingaweb2::web_path: icingaweb2
+icingaweb2::db_user:  icingaweb2
+icingaweb2::db_pass:  icingaweb2
+icingaweb2::db_name:  icingaweb2
+icingaweb2::group:    icingaweb2
diff --git a/.puppet/manifests/site.pp b/.puppet/manifests/site.pp
index 08120d911..043f24dbb 100644
--- a/.puppet/manifests/site.pp
+++ b/.puppet/manifests/site.pp
@@ -13,5 +13,5 @@ node default {
     source => 'puppet:////vagrant/.puppet/files/etc/profile.d/env.sh'
   }
   @user { vagrant: ensure => present }
-  User <| title == vagrant |> { groups +> icingaweb }
+  User <| title == vagrant |> { groups +> hiera('icingaweb2::group') }
 }
diff --git a/.puppet/modules/icinga2_pgsql/manifests/init.pp b/.puppet/modules/icinga2_pgsql/manifests/init.pp
index 2326449af..95bc71034 100644
--- a/.puppet/modules/icinga2_pgsql/manifests/init.pp
+++ b/.puppet/modules/icinga2_pgsql/manifests/init.pp
@@ -11,7 +11,8 @@ class icinga2_pgsql {
     password   => 'icinga2',
     schemafile => '/usr/share/icinga2-ido-pgsql/schema/pgsql.sql',
   }
-  -> icinga2::feature { 'ido-pgsql':
-    source => 'puppet:///modules/icinga2_pgsql',
-  }
+# Because Icinga 2 does not handle more than one IDO connection properly, The ido-pgsql will not be enabled by default.
+#  -> icinga2::feature { 'ido-pgsql':
+#    source => 'puppet:///modules/icinga2_pgsql',
+#  }
 }
diff --git a/.puppet/modules/icingaweb2/manifests/config.pp b/.puppet/modules/icingaweb2/manifests/config.pp
index 473d89d06..625c47b7a 100644
--- a/.puppet/modules/icingaweb2/manifests/config.pp
+++ b/.puppet/modules/icingaweb2/manifests/config.pp
@@ -1,14 +1,15 @@
 class icingaweb2::config (
-  $config = hiera('icingaweb2::config')
+  $config    = hiera('icingaweb2::config'),
+  $web_group = hiera('icingaweb2::group')
 ) {
-  group { 'icingaweb':
+  group { $web_group:
       ensure => present,
   }
 
   file { [ "${config}", "${config}/enabledModules", "${config}/modules", "${config}/preferences" ]:
     ensure  => directory,
     owner   => 'root',
-    group   => 'icingaweb',
+    group   => $web_group,
     mode    => '2770',
   }
 }
diff --git a/.puppet/modules/icingaweb2/manifests/config/general.pp b/.puppet/modules/icingaweb2/manifests/config/general.pp
index c2daec83f..8ccea172f 100644
--- a/.puppet/modules/icingaweb2/manifests/config/general.pp
+++ b/.puppet/modules/icingaweb2/manifests/config/general.pp
@@ -1,14 +1,15 @@
 define icingaweb2::config::general (
   $source,
-  $config   = hiera('icingaweb2::config'),
-  $replace  = true
+  $config    = hiera('icingaweb2::config'),
+  $web_group = hiera('icingaweb2::group'),
+  $replace   = true
 ) {
   include icingaweb2::config
 
   file { "${config}/${name}.ini":
      content => template("${source}/${name}.ini.erb"),
      owner   => 'root',
-     group   => 'icingaweb',
+     group   => $web_group,
      mode    => 0660,
      replace => $replace,
   }
diff --git a/.puppet/modules/icingaweb2/manifests/config/module.pp b/.puppet/modules/icingaweb2/manifests/config/module.pp
index 69e5abd6b..19db02250 100644
--- a/.puppet/modules/icingaweb2/manifests/config/module.pp
+++ b/.puppet/modules/icingaweb2/manifests/config/module.pp
@@ -1,8 +1,9 @@
 define icingaweb2::config::module (
   $module,
   $source,
-  $config  = hiera('icingaweb2::config'),
-  $replace = true
+  $config    = hiera('icingaweb2::config'),
+  $web_group = hiera('icingaweb2::group'),
+  $replace   = true
 ) {
   include icingaweb2::config
 
@@ -10,7 +11,7 @@ define icingaweb2::config::module (
     file { "${config}/modules/${module}":
       ensure  => directory,
       owner   => 'root',
-      group   => 'icingaweb',
+      group   => $web_group,
       mode    => '2770',
     }
   }
@@ -18,7 +19,7 @@ define icingaweb2::config::module (
   file { "${config}/modules/${module}/${name}.ini":
      source  => "${source}/modules/${module}/${name}.ini",
      owner   => 'root',
-     group   => 'icingaweb',
+     group   => $web_group,
      mode    => 0660,
      replace => $replace,
   }
diff --git a/.puppet/modules/pgsql/templates/pg_hba.conf.erb b/.puppet/modules/pgsql/templates/pg_hba.conf.erb
index f6fb19ebf..ca98bebd8 100644
--- a/.puppet/modules/pgsql/templates/pg_hba.conf.erb
+++ b/.puppet/modules/pgsql/templates/pg_hba.conf.erb
@@ -71,6 +71,11 @@ local   icinga      icinga                            trust
 host    icinga      icinga      127.0.0.1/32          trust
 host    icinga      icinga      ::1/128               trust
 
+# icinga2
+local   icinga2     icinga2                           trust
+host    icinga2     icinga2     127.0.0.1/32          trust
+host    icinga2     icinga2     ::1/128               trust
+
 # icinga_unittest
 local   icinga_unittest      icinga_unittest                            trust
 host    icinga_unittest      icinga_unittest      127.0.0.1/32          trust
@@ -81,6 +86,11 @@ local   icingaweb      icingaweb                            trust
 host    icingaweb      icingaweb      127.0.0.1/32          trust
 host    icingaweb      icingaweb      ::1/128               trust
 
+# icingaweb2
+local   <%= scope.function_hiera(['icingaweb2::db_user']) %>    <%= scope.function_hiera(['icingaweb2::db_user']) %>                    trust
+host    <%= scope.function_hiera(['icingaweb2::db_user']) %>    <%= scope.function_hiera(['icingaweb2::db_user']) %>    127.0.0.1/32    trust
+host    <%= scope.function_hiera(['icingaweb2::db_user']) %>    <%= scope.function_hiera(['icingaweb2::db_user']) %>    ::1/128         trust
+
 # "local" is for Unix domain socket connections only
 local   all         all                               ident
 # IPv4 local connections:
diff --git a/.puppet/modules/php_imagick/manifests/init.pp b/.puppet/modules/php_imagick/manifests/init.pp
new file mode 100644
index 000000000..5ef0453af
--- /dev/null
+++ b/.puppet/modules/php_imagick/manifests/init.pp
@@ -0,0 +1,29 @@
+# Class: php_imagick
+#
+#   This class installs the ImageMagick PHP module.
+#
+# Parameters:
+#
+# Actions:
+#
+# Requires:
+#
+#   php
+#
+# Sample Usage:
+#
+#   include php_imagick
+#
+class php_imagick {
+  include php
+
+  $php_imagick = $::operatingsystem ? {
+    /(Debian|Ubuntu)/        => 'php5-imagick',
+    /(RedHat|CentOS|Fedora)/ => 'php-pecl-imagick',
+    /(SLES|OpenSuSE)/        => 'php5-imagick',
+  }
+
+  package { $php_imagick:
+    ensure => latest,
+  }
+}
diff --git a/.puppet/profiles/icingaweb2_dev/manifests/init.pp b/.puppet/profiles/icingaweb2_dev/manifests/init.pp
index 379f75247..b8bea040f 100644
--- a/.puppet/profiles/icingaweb2_dev/manifests/init.pp
+++ b/.puppet/profiles/icingaweb2_dev/manifests/init.pp
@@ -1,13 +1,15 @@
 class icingaweb2_dev (
-  $config   = hiera('icingaweb2::config'),
-  $log      = hiera('icingaweb2::log'),
-  $web_path = hiera('icingaweb2::web_path'),
-  $db_user  = hiera('icingaweb2::db_user'),
-  $db_pass  = hiera('icingaweb2::db_pass'),
-  $db_name  = hiera('icingaweb2::db_name'),
+  $config    = hiera('icingaweb2::config'),
+  $log       = hiera('icingaweb2::log'),
+  $web_path  = hiera('icingaweb2::web_path'),
+  $db_user   = hiera('icingaweb2::db_user'),
+  $db_pass   = hiera('icingaweb2::db_pass'),
+  $db_name   = hiera('icingaweb2::db_name'),
+  $web_group = hiera('icingaweb2::group'),
 ) {
   include apache
   include php
+  include php_imagick
   include icingaweb2::config
   include icingacli
   include icinga_packages
@@ -19,7 +21,7 @@ class icingaweb2_dev (
   }
 
   # TODO(el): icinga-gui is not a icingaweb2_dev package
-  package { [ 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]:
+  package { [ 'php-gd', 'php-intl', 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]:
     ensure => latest,
     notify => Service['apache'],
     require => Class['icinga_packages'],
@@ -28,7 +30,7 @@ class icingaweb2_dev (
   Exec { path => '/usr/local/bin:/usr/bin:/bin' }
 
   # TODO(el): Enabling/disabling modules should be a resource
-  User <| alias == apache |> { groups +> 'icingaweb' }
+  User <| alias == apache |> { groups +> $web_group }
   -> exec { 'enable-monitoring-module':
     command => 'icingacli module enable monitoring',
     user    => 'apache',
@@ -50,7 +52,7 @@ class icingaweb2_dev (
   file { $log_dir:
     ensure  => directory,
     owner   => 'root',
-    group   => 'icingaweb',
+    group   => $web_group,
     mode    => '2775'
   }
 
diff --git a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb
index f28395e18..87f9f53ed 100644
--- a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb
+++ b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb
@@ -1,5 +1,5 @@
 [autologin]
-backend = autologin
+backend = external
 
 [icingaweb-mysql]
 backend  = db
diff --git a/README.md b/README.md
index 16eb1444a..55e4e77ee 100644
--- a/README.md
+++ b/README.md
@@ -2,267 +2,26 @@
 
 ## Table of Contents
 
-0. [General Information](#general information)
+0. [About](#about)
 1. [Installation](#installation)
 2. [Support](#support)
-3. [Vagrant - Virtual development environment](#vagrant)
 
-## General Information
+## About
 
-`Icinga Web 2` is the next generation monitoring web interface, framework
-and CLI tool developed by the [Icinga Project](https://www.icinga.org/community/team/).
+**Icinga Web 2** is the next generation open source monitoring web interface, framework
+and command-line interface developed by the [Icinga Project](https://www.icinga.org/), supporting Icinga 2,
+Icinga Core and any other monitoring backend compatible with the Livestatus Protocol.
 
-Responsive and fast, rewritten from scratch supporting multiple backends and
-providing a CLI tool. Compatible with Icinga Core 2.x and 1.x.
-
-Check the Icinga website for some [insights](https://www.icinga.org/icinga/screenshots/icinga-web-2/).
-
-> **Note**
->
-> `Icinga Web 2` is still in development and not meant for production deployment.
-> Watch the [development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap)
-> and [Icinga website](https://www.icinga.org/) for release schedule updates!
+![Icinga Web 2](https://www.icinga.org/wp-content/uploads/2014/06/service_detail.png "Icinga Web 2")
 
 ## Installation
 
-Please navigate to [doc/installation.md](doc/installation.md) for updated details.
+For installing Icinga Web 2 please read [doc/installation.md](doc/installation.md).
 
 ## Support
 
-Please head over to the [community support channels](https://www.icinga.org/icinga/faq/get-help/)
-in case of questions, bugs, etc.
-
-Please make sure to provide the following details:
-
-* OS, distribution, version
-* PHP and/or MySQL/PostgreSQL version
-* Which browser and its version
-* Screenshot and problem description
-
-
-## Vagrant
-
-### Requirements
-
-* Vagrant 1.2+
-* Virtualbox 4.2.16+
-* a fairly powerful hardware (quad core, 4gb ram, fast hdd)
-
-> **Note**
->
-> The deployment of the virtual machine is tested against Vagrant starting with version 1.2.
-> Unfortunately older versions will not work.
-
-### General
-
-The Icinga Web 2 project ships with a Vagrant virtual machine that integrates
-the source code with various services and example data in a controlled
-environment. This enables developers and users to test Livestatus, status.dat,
-MySQL and PostgreSQL backends as well as the LDAP authentication. All you
-have to do is install Vagrant and run:
-
-    vagrant up
-
-> **Note**
-> 
-> The first boot of the vm takes a fairly long time because
-> you'll download a plain CentOS base box and Vagrant will automatically
-> provision the environment on the first go.
-
-After you should be able to browse [localhost:8080/icingaweb](http://localhost:8080/icingaweb).
-
-### Environment
-
-**Forwarded ports**:
-
-<table>
-    <tr>
-        <th>Proctocol</th>
-        <th>Local port (virtual machine host)</th>
-        <th>Remote port (the virtual machine)</th>
-    </tr>
-    <tr>
-        <td>SSH</td>
-        <td>2222</td>
-        <td>22</td>
-    </tr>
-    <tr>
-        <td>HTTP</td>
-        <td>8080</td>
-        <td>80</td>
-    </tr>
-</table>
-
-**Installed packages**:
-
-* Apache2 with PHP enabled
-* PHP with MySQL and PostgreSQL libraries
-* MySQL server and client software
-* PostgreSQL server and client software
-* [Icinga prerequisites](http://docs.icinga.org/latest/en/quickstart-idoutils.html#installpackages)
-* OpenLDAP servers and clients
-
-**Installed users and groups**:
-
-* User icinga with group icinga and icinga-cmd
-* Webserver user added to group icinga-cmd
-
-**Installed software**:
-
-* Icinga with IDOUtils using a MySQL database
-* Icinga with IDOUtils using a PostgreSQL database
-* Icinga 2
-
-**Installed files**:
-
-* `/usr/share/icinga/htpasswd.users` account information for logging into the Icinga classic web interface for both icinga instances
-* `/usr/lib64/nagios/plugins` Monitoring Plugins for all Icinga instances
-
-#### Icinga with IDOUtils using a MySQL database
-
-**Installation path**: `/usr/local/icinga-mysql`
-
-**Services**:
-
-* `icinga-mysql`
-* `ido2db-mysql`
-
-Connect to the **icinga mysql database** using the following command:
-
-    mysql -u icinga -p icinga icinga
-
-Access the **Classic UI** (CGIs) via [localhost:8080/icinga-mysql](http://localhost:8080/icinga-mysql).
-For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*.
-
-#### Icinga with IDOUtils using a PostgreSQL database
-
-**Installation path**: `/usr/local/icinga-pgsql`
-
-**Services**:
-
-* `icinga-pgsql`
-* `ido2db-pgsql`
-
-Connect to the **icinga mysql database** using the following command:
-
-    sudo -u postgres psql -U icinga -d icinga
-
-Access the **Classic UI** (CGIs) via [localhost:8080/icinga-pgsql](http://localhost:8080/icinga-pgsql).
-For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*.
-
-#### Monitoring Test Config
-
-Test config is added to both the MySQL and PostgreSQL Icinga instance utilizing the Perl module
-**Monitoring::Generator::TestConfig** to generate test config to **/usr/local/share/misc/monitoring_test_config**
-which is then copied to **<instance>/etc/conf.d/test_config/**.
-Configuration can be adjusted and recreated with **/usr/local/share/misc/monitoring_test_config/recreate.pl**.
-**Note** that you have to run
-
-    vagrant provision
-
-in the host after any modification to the script just mentioned.
-
-#### MK Livestatus
-
-MK Livestatus is added to the Icinga installation using a MySQL database.
-
-**Installation path**:
-
-* `/usr/local/icinga-mysql/bin/unixcat`
-* `/usr/local/icinga-mysql/lib/mk-livestatus/livecheck`
-* `/usr/local/icinga-mysql/lib/mk-livestatus/livestatus.o`
-* `/usr/local/icinga-mysql/etc/modules/mk-livestatus.cfg`
-* `/usr/local/icinga-mysql/var/rw/live`
-
-**Example usage**:
-
-    echo "GET hosts" | /usr/local/icinga-mysql/bin/unixcat /usr/local/icinga-mysql/var/rw/live
-
-#### LDAP example data
-
-The environment includes a openldap server with example data. *Domain* suffix is **dc=icinga,dc=org**.
-Administrator (*rootDN*) of the slapd configuration database is **cn=admin,cn=config** and the
-administrator (*rootDN*) of our database instance is **cn=admin,dc=icinga,dc=org**. Both share
-the *password* `admin`.
-
-Examples to query the slapd configuration database:
-
-    ldapsearch -x -W -LLL -D cn=admin,cn=config -b cn=config dn
-    ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b cn=config dn
-
-Examples to query our database instance:
-
-    ldapsearch -x -W -LLL -D cn=admin,dc=icinga,dc=org -b dc=icinga,dc=org dn
-    ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b dc=icinga,dc=org dn
-
-This is what the **dc=icinga,dc=org** *DIT* looks like:
-
-> dn: dc=icinga,dc=org
->
-> dn: ou=people,dc=icinga,dc=org
->
-> dn: ou=groups,dc=icinga,dc=org
->
-> dn: cn=Users,ou=groups,dc=icinga,dc=org
-> cn: Users
-> uniqueMember: cn=Jon Doe,ou=people,dc=icinga,dc=org
-> uniqueMember: cn=Jane Smith,ou=people,dc=icinga,dc=org
-> uniqueMember: cn=John Q. Public,ou=people,dc=icinga,dc=org
-> uniqueMember: cn=Richard Roe,ou=people,dc=icinga,dc=org
->
-> dn: cn=John Doe,ou=people,dc=icinga,dc=org
-> cn: John Doe
-> uid: jdoe
->
-> dn: cn=Jane Smith,ou=people,dc=icinga,dc=org
-> cn: Jane Smith
-> uid: jsmith
->
-> dn: cn=John Q. Public,ou=people,dc=icinga,dc=org
-> cn: John Q. Public
-> uid: jqpublic
->
-> dn: cn=Richard Roe,ou=people,dc=icinga,dc=org
-> cn: Richard Roe
-> uid: rroe
-
-All users share the password `password`.
-
-#### Testing the code
-
-All software required to run tests is installed in the virtual machine.
-In order to run all tests you have to execute the following commands:
-
-    vagrant ssh -c /vagrant/test/php/runtests
-    vagrant ssh -c /vagrant/test/php/checkswag
-    vagrant ssh -c /vagrant/test/js/runtests
-    vagrant ssh -c /vagrant/test/js/checkswag
-    vagrant ssh -c /vagrant/test/frontend/runtests
-
-`runtests` will execute unit and regression tests and `checkswag` will report
-code style issues.
-
-#### Icinga 2
-
-Installed from the Icinga [snapshot package repository](http://packages.icinga.org/epel/).
-The configuration is located in `/etc/icinga2`.
-
-**Example usage**:
-
-    /etc/init.d/icinga2 (start|stop|restart|reload)
-
-
-## Log into Icinga Web 2
-
-If you've configure LDAP as authentication backend (which is the default) use the following login credentials:
-
-> **Username**: jdoe
-> **Password**: password
-
-Have a look at [LDAP example data](#ldap example data) for more accounts.
-
-Using MySQL as backend:
-
-> **Username**: icingaadmin
-> **Password**: icinga
+If you come across problems at some time, the [community support channels](https://support.icinga.org/) 
+are good places to ask for advice from other users and give some in return.
 
+For status updates check the [Icinga website](https://www.icinga.org/) and the
+[Icinga Web 2 development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap).
diff --git a/Vagrantfile b/Vagrantfile
index 28b69cab9..1e5e3a073 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -4,7 +4,6 @@
 VAGRANTFILE_API_VERSION = "2"
 VAGRANT_REQUIRED_VERSION = "1.5.0"
 
-# Require 1.2.x at least
 if ! defined? Vagrant.require_version
   if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new(VAGRANT_REQUIRED_VERSION)
     puts "Vagrant >= " + VAGRANT_REQUIRED_VERSION + " required. Your version is " + Vagrant::VERSION
diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php
index 00dae1c6d..4e70894a1 100644
--- a/application/controllers/AuthenticationController.php
+++ b/application/controllers/AuthenticationController.php
@@ -4,16 +4,17 @@
 
 # namespace Icinga\Application\Controllers;
 
-use Icinga\Authentication\Backend\AutoLoginBackend;
-use Icinga\Web\Controller\ActionController;
-use Icinga\Forms\Authentication\LoginForm;
-use Icinga\Authentication\AuthChain;
 use Icinga\Application\Config;
+use Icinga\Application\Icinga;
 use Icinga\Application\Logger;
+use Icinga\Authentication\AuthChain;
+use Icinga\Authentication\Backend\ExternalBackend;
 use Icinga\Exception\AuthenticationException;
-use Icinga\Exception\NotReadableError;
 use Icinga\Exception\ConfigurationError;
+use Icinga\Exception\NotReadableError;
+use Icinga\Forms\Authentication\LoginForm;
 use Icinga\User;
+use Icinga\Web\Controller\ActionController;
 use Icinga\Web\Url;
 
 /**
@@ -33,10 +34,12 @@ class AuthenticationController extends ActionController
      */
     public function loginAction()
     {
-        if (@file_exists(Config::resolvePath('setup.token')) && !@file_exists(Config::resolvePath('config.ini'))) {
+        $icinga = Icinga::app();
+        if ($icinga->setupTokenExists() && $icinga->requiresSetup()) {
             $this->redirectNow(Url::fromPath('setup'));
         }
 
+        $triedOnlyExternalAuth = null;
         $auth = $this->Auth();
         $this->view->form = $form = new LoginForm();
         $this->view->title = $this->translate('Icingaweb Login');
@@ -80,7 +83,7 @@ class AuthenticationController extends ActionController
                 }
 
                 foreach ($chain as $backend) {
-                    if ($backend instanceof AutoLoginBackend) {
+                    if ($backend instanceof ExternalBackend) {
                         continue;
                     }
                     ++$backendsTried;
@@ -124,7 +127,8 @@ class AuthenticationController extends ActionController
             } elseif ($request->isGet()) {
                 $user = new User('');
                 foreach ($chain as $backend) {
-                    if ($backend instanceof AutoLoginBackend) {
+                    $triedOnlyExternalAuth = $triedOnlyExternalAuth === null;
+                    if ($backend instanceof ExternalBackend) {
                         $authenticated  = $backend->authenticate($user);
                         if ($authenticated === true) {
                             $auth->setAuthenticated($user);
@@ -132,6 +136,8 @@ class AuthenticationController extends ActionController
                                 Url::fromPath(Url::fromRequest()->getParam('redirect', 'dashboard'))
                             );
                         }
+                    } else {
+                        $triedOnlyExternalAuth = false;
                     }
                 }
             }
@@ -139,7 +145,8 @@ class AuthenticationController extends ActionController
             $this->view->errorInfo = $e->getMessage();
         }
 
-        $this->view->configMissing = is_dir(Config::$configDir) === false;
+        $this->view->requiresExternalAuth = $triedOnlyExternalAuth && !$auth->isAuthenticated();
+        $this->view->requiresSetup = Icinga::app()->requiresSetup();
     }
 
     /**
diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php
index 7acab7c25..832f57644 100644
--- a/application/controllers/PreferenceController.php
+++ b/application/controllers/PreferenceController.php
@@ -7,7 +7,6 @@ use Icinga\Web\Url;
 use Icinga\Web\Widget\Tab;
 use Icinga\Application\Config;
 use Icinga\Forms\PreferenceForm;
-use Icinga\Exception\ConfigurationError;
 use Icinga\User\Preferences\PreferencesStore;
 
 /**
@@ -40,14 +39,13 @@ class PreferenceController extends BasePreferenceController
     public function indexAction()
     {
         $storeConfig = Config::app()->getSection('preferences');
-        if ($storeConfig->isEmpty()) {
-            throw new ConfigurationError(t('You need to configure how to store preferences first.'));
-        }
 
         $user = $this->getRequest()->getUser();
         $form = new PreferenceForm();
         $form->setPreferences($user->getPreferences());
-        $form->setStore(PreferencesStore::create($storeConfig, $user));
+        if ($storeConfig->get('store', 'ini') !== 'none') {
+            $form->setStore(PreferencesStore::create($storeConfig, $user));
+        }
         $form->handleRequest();
 
         $this->view->form = $form;
diff --git a/application/fonts/icingaweb.md b/application/fonts/icingaweb.md
new file mode 100644
index 000000000..5699f07b2
--- /dev/null
+++ b/application/fonts/icingaweb.md
@@ -0,0 +1,9 @@
+# fontello-ifont font files moved
+
+New target is: public/font
+
+The font directory has been moved to the public structure because of
+Internet Explorer version 8 compatibility. The common way for browsers is to
+include the binary embeded font type in the javascript. IE8 falls back and
+include one of the provided font sources. Therefore it is important to have
+the font files available public and exported by the HTTP server.
diff --git a/application/forms/Authentication/LoginForm.php b/application/forms/Authentication/LoginForm.php
index a6d69d15a..8be455dcc 100644
--- a/application/forms/Authentication/LoginForm.php
+++ b/application/forms/Authentication/LoginForm.php
@@ -18,7 +18,7 @@ class LoginForm extends Form
     public function init()
     {
         $this->setName('form_login');
-        $this->setSubmitLabel(t('Login'));
+        $this->setSubmitLabel($this->translate('Login'));
     }
 
     /**
@@ -31,8 +31,8 @@ class LoginForm extends Form
             'username',
             array(
                 'required'      => true,
-                'label'         => t('Username'),
-                'placeholder'   => t('Please enter your username...'),
+                'label'         => $this->translate('Username'),
+                'placeholder'   => $this->translate('Please enter your username...'),
                 'class'         => false === isset($formData['username']) ? 'autofocus' : ''
             )
         );
@@ -41,8 +41,8 @@ class LoginForm extends Form
             'password',
             array(
                 'required'      => true,
-                'label'         => t('Password'),
-                'placeholder'   => t('...and your password'),
+                'label'         => $this->translate('Password'),
+                'placeholder'   => $this->translate('...and your password'),
                 'class'         => isset($formData['username']) ? 'autofocus' : ''
             )
         );
diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php
index 572a09c2e..d3a5af51d 100644
--- a/application/forms/Config/Authentication/DbBackendForm.php
+++ b/application/forms/Config/Authentication/DbBackendForm.php
@@ -53,8 +53,8 @@ class DbBackendForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Backend Name'),
-                'description'   => t(
+                'label'         => $this->translate('Backend Name'),
+                'description'   => $this->translate(
                     'The name of this authentication provider that is used to differentiate it from others'
                 ),
             )
@@ -64,8 +64,10 @@ class DbBackendForm extends Form
             'resource',
             array(
                 'required'      => true,
-                'label'         => t('Database Connection'),
-                'description'   => t('The database connection to use for authenticating with this provider'),
+                'label'         => $this->translate('Database Connection'),
+                'description'   => $this->translate(
+                    'The database connection to use for authenticating with this provider'
+                ),
                 'multiOptions'  => false === empty($this->resources)
                     ? array_combine($this->resources, $this->resources)
                     : array()
@@ -107,11 +109,11 @@ class DbBackendForm extends Form
         try {
             $dbUserBackend = new DbUserBackend(ResourceFactory::createResource($form->getResourceConfig()));
             if ($dbUserBackend->count() < 1) {
-                $form->addError(t('No users found under the specified database backend'));
+                $form->addError($form->translate('No users found under the specified database backend'));
                 return false;
             }
         } catch (Exception $e) {
-            $form->addError(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
+            $form->addError(sprintf($form->translate('Using the specified backend failed: %s'), $e->getMessage()));
             return false;
         }
 
diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/ExternalBackendForm.php
similarity index 73%
rename from application/forms/Config/Authentication/AutologinBackendForm.php
rename to application/forms/Config/Authentication/ExternalBackendForm.php
index a21d2c006..51000b2d2 100644
--- a/application/forms/Config/Authentication/AutologinBackendForm.php
+++ b/application/forms/Config/Authentication/ExternalBackendForm.php
@@ -8,16 +8,16 @@ use Zend_Validate_Callback;
 use Icinga\Web\Form;
 
 /**
- * Form class for adding/modifying autologin authentication backends
+ * Form class for adding/modifying authentication backends of type "external"
  */
-class AutologinBackendForm extends Form
+class ExternalBackendForm extends Form
 {
     /**
      * Initialize this form
      */
     public function init()
     {
-        $this->setName('form_config_authbackend_autologin');
+        $this->setName('form_config_authbackend_external');
     }
 
     /**
@@ -30,8 +30,8 @@ class AutologinBackendForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Backend Name'),
-                'description'   => t(
+                'label'         => $this->translate('Backend Name'),
+                'description'   => $this->translate(
                     'The name of this authentication provider that is used to differentiate it from others'
                 ),
                 'validators'    => array(
@@ -52,9 +52,11 @@ class AutologinBackendForm extends Form
             'text',
             'strip_username_regexp',
             array(
-                'label'         => t('Filter Pattern'),
-                'description'   => t('The regular expression to use to strip specific parts off from usernames. Leave empty if you do not want to strip off anything'),
-                'value'         => '/\@[^$]+$/',
+                'label'         => $this->translate('Filter Pattern'),
+                'description'   => $this->translate(
+                    'The regular expression to use to strip specific parts off from usernames.'
+                    . ' Leave empty if you do not want to strip off anything'
+                ),
                 'validators'    => array(
                     new Zend_Validate_Callback(function ($value) {
                         return @preg_match($value, '') !== false;
@@ -67,7 +69,7 @@ class AutologinBackendForm extends Form
             'backend',
             array(
                 'disabled'  => true,
-                'value'     => 'autologin'
+                'value'     => 'external'
             )
         );
 
@@ -77,7 +79,7 @@ class AutologinBackendForm extends Form
     /**
      * Validate the configuration by creating a backend and requesting the user count
      *
-     * Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.)
+     * Returns always true as backends of type "external" are just "passive" backends.
      *
      * @param   Form    $form   The form to fetch the configuration values from
      *
diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php
index 9b48c3dbc..1b8fc3f11 100644
--- a/application/forms/Config/Authentication/LdapBackendForm.php
+++ b/application/forms/Config/Authentication/LdapBackendForm.php
@@ -54,8 +54,8 @@ class LdapBackendForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Backend Name'),
-                'description'   => t(
+                'label'         => $this->translate('Backend Name'),
+                'description'   => $this->translate(
                     'The name of this authentication provider that is used to differentiate it from others'
                 )
             )
@@ -65,8 +65,8 @@ class LdapBackendForm extends Form
             'resource',
             array(
                 'required'      => true,
-                'label'         => t('LDAP Resource'),
-                'description'   => t('The resource to use for authenticating with this provider'),
+                'label'         => $this->translate('LDAP Resource'),
+                'description'   => $this->translate('The resource to use for authenticating with this provider'),
                 'multiOptions'  => false === empty($this->resources)
                     ? array_combine($this->resources, $this->resources)
                     : array()
@@ -77,8 +77,8 @@ class LdapBackendForm extends Form
             'user_class',
             array(
                 'required'      => true,
-                'label'         => t('LDAP User Object Class'),
-                'description'   => t('The object class used for storing users on the ldap server'),
+                'label'         => $this->translate('LDAP User Object Class'),
+                'description'   => $this->translate('The object class used for storing users on the ldap server'),
                 'value'         => 'inetOrgPerson'
             )
         );
@@ -87,8 +87,10 @@ class LdapBackendForm extends Form
             'user_name_attribute',
             array(
                 'required'      => true,
-                'label'         => t('LDAP User Name Attribute'),
-                'description'   => t('The attribute name used for storing the user name on the ldap server'),
+                'label'         => $this->translate('LDAP User Name Attribute'),
+                'description'   => $this->translate(
+                    'The attribute name used for storing the user name on the ldap server'
+                ),
                 'value'         => 'uid'
             )
         );
@@ -105,9 +107,11 @@ class LdapBackendForm extends Form
             'base_dn',
             array(
                 'required'      => false,
-                'label'         => t('Base DN'),
-                'description'   => t('The path where users can be found on the ldap server. ' .
-                    ' Leave empty to select all users available on the specified resource.')
+                'label'         => $this->translate('Base DN'),
+                'description'   => $this->translate(
+                    'The path where users can be found on the ldap server. Leave ' .
+                    'empty to select all users available on the specified resource.'
+                )
             )
         );
         return $this;
@@ -146,7 +150,7 @@ class LdapBackendForm extends Form
             $form->addError($e->getMessage());
             return false;
         } catch (Exception $e) {
-            $form->addError(sprintf(t('Unable to validate authentication: %s'), $e->getMessage()));
+            $form->addError(sprintf($form->translate('Unable to validate authentication: %s'), $e->getMessage()));
             return false;
         }
 
diff --git a/application/forms/Config/AuthenticationBackendConfigForm.php b/application/forms/Config/AuthenticationBackendConfigForm.php
index 12f407c69..de3093ada 100644
--- a/application/forms/Config/AuthenticationBackendConfigForm.php
+++ b/application/forms/Config/AuthenticationBackendConfigForm.php
@@ -14,7 +14,7 @@ use Icinga\Data\ResourceFactory;
 use Icinga\Exception\ConfigurationError;
 use Icinga\Forms\Config\Authentication\DbBackendForm;
 use Icinga\Forms\Config\Authentication\LdapBackendForm;
-use Icinga\Forms\Config\Authentication\AutologinBackendForm;
+use Icinga\Forms\Config\Authentication\ExternalBackendForm;
 
 class AuthenticationBackendConfigForm extends ConfigForm
 {
@@ -31,7 +31,7 @@ class AuthenticationBackendConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_authbackend');
-        $this->setSubmitLabel(t('Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
@@ -67,10 +67,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
         } elseif ($type === 'ldap') {
             $form = new LdapBackendForm();
             $form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
-        } elseif ($type === 'autologin') {
-            $form = new AutologinBackendForm();
+        } elseif ($type === 'external') {
+            $form = new ExternalBackendForm();
         } else {
-            throw new InvalidArgumentException(sprintf(t('Invalid backend type "%s" provided'), $type));
+            throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type));
         }
 
         return $form;
@@ -91,9 +91,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
     {
         $name = isset($values['name']) ? $values['name'] : '';
         if (! $name) {
-            throw new InvalidArgumentException(t('Authentication backend name missing'));
+            throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
         } elseif ($this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Authentication backend already exists'));
+            throw new InvalidArgumentException($this->translate('Authentication backend already exists'));
         }
 
         unset($values['name']);
@@ -114,11 +114,11 @@ class AuthenticationBackendConfigForm extends ConfigForm
     public function edit($name, array $values)
     {
         if (! $name) {
-            throw new InvalidArgumentException(t('Old authentication backend name missing'));
+            throw new InvalidArgumentException($this->translate('Old authentication backend name missing'));
         } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
-            throw new InvalidArgumentException(t('New authentication backend name missing'));
+            throw new InvalidArgumentException($this->translate('New authentication backend name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+            throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
         }
 
         $backendConfig = $this->config->getSection($name);
@@ -144,9 +144,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
     public function remove($name)
     {
         if (! $name) {
-            throw new InvalidArgumentException(t('Authentication backend name missing'));
+            throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+            throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
         }
 
         $backendConfig = $this->config->getSection($name);
@@ -167,9 +167,9 @@ class AuthenticationBackendConfigForm extends ConfigForm
     public function move($name, $position)
     {
         if (! $name) {
-            throw new InvalidArgumentException(t('Authentication backend name missing'));
+            throw new InvalidArgumentException($this->translate('Authentication backend name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Unknown authentication backend provided'));
+            throw new InvalidArgumentException($this->translate('Unknown authentication backend provided'));
         }
 
         $backendOrder = $this->config->keys();
@@ -208,10 +208,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
         try {
             if ($authBackend === null) { // create new backend
                 $this->add($this->getValues());
-                $message = t('Authentication backend "%s" has been successfully created');
+                $message = $this->translate('Authentication backend "%s" has been successfully created');
             } else { // edit existing backend
                 $this->edit($authBackend, $this->getValues());
-                $message = t('Authentication backend "%s" has been successfully changed');
+                $message = $this->translate('Authentication backend "%s" has been successfully changed');
             }
         } catch (InvalidArgumentException $e) {
             Notification::error($e->getMessage());
@@ -237,11 +237,13 @@ class AuthenticationBackendConfigForm extends ConfigForm
         $authBackend = $this->request->getQuery('auth_backend');
         if ($authBackend !== null) {
             if ($authBackend === '') {
-                throw new ConfigurationError(t('Authentication backend name missing'));
+                throw new ConfigurationError($this->translate('Authentication backend name missing'));
             } elseif (! $this->config->hasSection($authBackend)) {
-                throw new ConfigurationError(t('Unknown authentication backend provided'));
+                throw new ConfigurationError($this->translate('Unknown authentication backend provided'));
             } elseif ($this->config->getSection($authBackend)->backend === null) {
-                throw new ConfigurationError(sprintf(t('Backend "%s" has no `backend\' setting'), $authBackend));
+                throw new ConfigurationError(
+                    sprintf($this->translate('Backend "%s" has no `backend\' setting'), $authBackend)
+                );
             }
 
             $configValues = $this->config->getSection($authBackend)->toArray();
@@ -249,15 +251,15 @@ class AuthenticationBackendConfigForm extends ConfigForm
             $configValues['name'] = $authBackend;
             $this->populate($configValues);
         } elseif (empty($this->resources)) {
-            $autologinBackends = array_filter(
+            $externalBackends = array_filter(
                 $this->config->toArray(),
                 function ($authBackendCfg) {
-                    return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
+                    return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external';
                 }
             );
 
-            if (false === empty($autologinBackends)) {
-                throw new ConfigurationError(t('Could not find any resources for authentication'));
+            if (false === empty($externalBackends)) {
+                throw new ConfigurationError($this->translate('Could not find any resources for authentication'));
             }
         }
     }
@@ -276,8 +278,8 @@ class AuthenticationBackendConfigForm extends ConfigForm
             array(
                 'order'         => 0,
                 'ignore'        => true,
-                'label'         => t('Force Changes'),
-                'description'   => t('Check this box to enforce changes without connectivity validation')
+                'label'         => $this->translate('Force Changes'),
+                'description'   => $this->translate('Check this box to enforce changes without connectivity validation')
             )
         );
     }
@@ -291,20 +293,20 @@ class AuthenticationBackendConfigForm extends ConfigForm
         $backendType = isset($formData['type']) ? $formData['type'] : null;
 
         if (isset($this->resources['db'])) {
-            $backendTypes['db'] = t('Database');
+            $backendTypes['db'] = $this->translate('Database');
         }
         if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
             $backendTypes['ldap'] = 'LDAP';
         }
 
-        $autologinBackends = array_filter(
+        $externalBackends = array_filter(
             $this->config->toArray(),
             function ($authBackendCfg) {
-                return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
+                return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external';
             }
         );
-        if ($backendType === 'autologin' || empty($autologinBackends)) {
-            $backendTypes['autologin'] = t('Autologin');
+        if ($backendType === 'external' || empty($externalBackends)) {
+            $backendTypes['external'] = $this->translate('External');
         }
 
         if ($backendType === null) {
@@ -318,8 +320,10 @@ class AuthenticationBackendConfigForm extends ConfigForm
                 'ignore'            => true,
                 'required'          => true,
                 'autosubmit'        => true,
-                'label'             => t('Backend Type'),
-                'description'       => t('The type of the resource to use for this authenticaton provider'),
+                'label'             => $this->translate('Backend Type'),
+                'description'       => $this->translate(
+                    'The type of the resource to use for this authenticaton provider'
+                ),
                 'multiOptions'      => $backendTypes
             )
         );
diff --git a/application/forms/Config/AuthenticationBackendReorderForm.php b/application/forms/Config/AuthenticationBackendReorderForm.php
index 07200827a..a41224248 100644
--- a/application/forms/Config/AuthenticationBackendReorderForm.php
+++ b/application/forms/Config/AuthenticationBackendReorderForm.php
@@ -52,7 +52,7 @@ class AuthenticationBackendReorderForm extends ConfigForm
 
             try {
                 if ($configForm->move($backendName, $position)->save()) {
-                    Notification::success(t('Authentication order updated!'));
+                    Notification::success($this->translate('Authentication order updated!'));
                 } else {
                     return false;
                 }
diff --git a/application/forms/Config/General/ApplicationConfigForm.php b/application/forms/Config/General/ApplicationConfigForm.php
index 95ad22071..29b7b512e 100644
--- a/application/forms/Config/General/ApplicationConfigForm.php
+++ b/application/forms/Config/General/ApplicationConfigForm.php
@@ -4,10 +4,8 @@
 
 namespace Icinga\Forms\Config\General;
 
-use DateTimeZone;
 use Icinga\Application\Icinga;
 use Icinga\Data\ResourceFactory;
-use Icinga\Util\Translator;
 use Icinga\Web\Form;
 
 
@@ -33,10 +31,10 @@ class ApplicationConfigForm extends Form
             'text',
             'global_module_path',
             array(
-                'label'         => t('Module Path'),
+                'label'         => $this->translate('Module Path'),
                 'required'      => true,
                 'value'         => implode(':', Icinga::app()->getModuleManager()->getModuleDirs()),
-                'description'   => t(
+                'description'   => $this->translate(
                     'Contains the directories that will be searched for available modules, separated by '
                     . 'colons. Modules that don\'t exist in these directories can still be symlinked in '
                     . 'the module folder, but won\'t show up in the list of disabled modules.'
@@ -46,19 +44,19 @@ class ApplicationConfigForm extends Form
 
         $this->addElement(
             'select',
-            'preferences_type',
+            'preferences_store',
             array(
                 'required'      => true,
                 'autosubmit'    => true,
-                'label'         => t('User Preference Storage Type'),
+                'label'         => $this->translate('User Preference Storage Type'),
                 'multiOptions'  => array(
-                    'ini'   => t('File System (INI Files)'),
-                    'db'    => t('Database'),
-                    'null'  => t('Don\'t Store Preferences')
+                    'ini'   => $this->translate('File System (INI Files)'),
+                    'db'    => $this->translate('Database'),
+                    'none'  => $this->translate('Don\'t Store Preferences')
                 )
             )
         );
-        if (isset($formData['preferences_type']) && $formData['preferences_type'] === 'db') {
+        if (isset($formData['preferences_store']) && $formData['preferences_store'] === 'db') {
             $backends = array();
             foreach (ResourceFactory::getResourceConfigs()->toArray() as $name => $resource) {
                 if ($resource['type'] === 'db') {
@@ -72,7 +70,7 @@ class ApplicationConfigForm extends Form
                 array(
                     'required'      => true,
                     'multiOptions'  => $backends,
-                    'label'         => t('Database Connection')
+                    'label'         => $this->translate('Database Connection')
                 )
             );
         }
diff --git a/application/forms/Config/General/LoggingConfigForm.php b/application/forms/Config/General/LoggingConfigForm.php
index deed06011..997bd558a 100644
--- a/application/forms/Config/General/LoggingConfigForm.php
+++ b/application/forms/Config/General/LoggingConfigForm.php
@@ -4,7 +4,6 @@
 
 namespace Icinga\Forms\Config\General;
 
-use Icinga\Application\Icinga;
 use Icinga\Application\Logger;
 use Icinga\Web\Form;
 use Icinga\Web\Form\Validator\WritablePathValidator;
@@ -31,12 +30,12 @@ class LoggingConfigForm extends Form
             array(
                 'required'      => true,
                 'autosubmit'    => true,
-                'label'         => t('Logging Type'),
-                'description'   => t('The type of logging to utilize.'),
+                'label'         => $this->translate('Logging Type'),
+                'description'   => $this->translate('The type of logging to utilize.'),
                 'multiOptions'  => array(
                     'syslog'    => 'Syslog',
-                    'file'      => t('File', 'app.config.logging.type'),
-                    'none'      => t('None', 'app.config.logging.type')
+                    'file'      => $this->translate('File', 'app.config.logging.type'),
+                    'none'      => $this->translate('None', 'app.config.logging.type')
                 )
             )
         );
@@ -47,13 +46,13 @@ class LoggingConfigForm extends Form
                 'logging_level',
                 array(
                     'required'      => true,
-                    'label'         => t('Logging Level'),
-                    'description'   => t('The maximum logging level to emit.'),
+                    'label'         => $this->translate('Logging Level'),
+                    'description'   => $this->translate('The maximum logging level to emit.'),
                     'multiOptions'  => array(
-                        Logger::$levels[Logger::ERROR]      => t('Error', 'app.config.logging.level'),
-                        Logger::$levels[Logger::WARNING]    => t('Warning', 'app.config.logging.level'),
-                        Logger::$levels[Logger::INFO]       => t('Information', 'app.config.logging.level'),
-                        Logger::$levels[Logger::DEBUG]      => t('Debug', 'app.config.logging.level')
+                        Logger::$levels[Logger::ERROR]   => $this->translate('Error', 'app.config.logging.level'),
+                        Logger::$levels[Logger::WARNING] => $this->translate('Warning', 'app.config.logging.level'),
+                        Logger::$levels[Logger::INFO]    => $this->translate('Information', 'app.config.logging.level'),
+                        Logger::$levels[Logger::DEBUG]   => $this->translate('Debug', 'app.config.logging.level')
                     )
                 )
             );
@@ -65,9 +64,11 @@ class LoggingConfigForm extends Form
                 'logging_application',
                 array(
                     'required'      => true,
-                    'label'         => t('Application Prefix'),
-                    'description'   => t('The name of the application by which to prefix syslog messages.'),
-                    'value'         => 'icingaweb',
+                    'label'         => $this->translate('Application Prefix'),
+                    'description'   => $this->translate(
+                        'The name of the application by which to prefix syslog messages.'
+                    ),
+                    'value'         => 'icingaweb2',
                     'validators'    => array(
                         array(
                             'Regex',
@@ -91,8 +92,8 @@ class LoggingConfigForm extends Form
 //                'logging_facility',
 //                array(
 //                    'required'      => true,
-//                    'label'         => t('Facility'),
-//                    'description'   => t('The syslog facility to utilize.'),
+//                    'label'         => $this->translate('Facility'),
+//                    'description'   => $this->translate('The syslog facility to utilize.'),
 //                    'multiOptions'  => array(
 //                        'user' => 'LOG_USER'
 //                    )
@@ -104,9 +105,9 @@ class LoggingConfigForm extends Form
                 'logging_file',
                 array(
                     'required'      => true,
-                    'label'         => t('File path'),
-                    'description'   => t('The full path to the log file to write messages to.'),
-                    'value'         => $this->getDefaultLogDir(),
+                    'label'         => $this->translate('File path'),
+                    'description'   => $this->translate('The full path to the log file to write messages to.'),
+                    'value'         => '/var/log/icingaweb2/icingaweb2.log',
                     'validators'    => array(new WritablePathValidator())
                 )
             );
@@ -114,14 +115,4 @@ class LoggingConfigForm extends Form
 
         return $this;
     }
-
-    /**
-     * Return the default logging directory for type 'file'
-     *
-     * @return string
-     */
-    protected function getDefaultLogDir()
-    {
-        return realpath(Icinga::app()->getApplicationDir('../var/log/icingaweb.log'));
-    }
 }
diff --git a/application/forms/Config/GeneralConfigForm.php b/application/forms/Config/GeneralConfigForm.php
index 0d81bb96b..7e3357d7b 100644
--- a/application/forms/Config/GeneralConfigForm.php
+++ b/application/forms/Config/GeneralConfigForm.php
@@ -20,7 +20,7 @@ class GeneralConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_general');
-        $this->setSubmitLabel(t('Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
@@ -52,7 +52,7 @@ class GeneralConfigForm extends ConfigForm
         }
 
         if ($this->save()) {
-            Notification::success(t('New configuration has successfully been stored'));
+            Notification::success($this->translate('New configuration has successfully been stored'));
         } else {
             return false;
         }
diff --git a/application/forms/Config/Resource/DbResourceForm.php b/application/forms/Config/Resource/DbResourceForm.php
index 36e69e9e1..97dd951d1 100644
--- a/application/forms/Config/Resource/DbResourceForm.php
+++ b/application/forms/Config/Resource/DbResourceForm.php
@@ -41,8 +41,8 @@ class DbResourceForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Resource Name'),
-                'description'   => t('The unique name of this resource')
+                'label'         => $this->translate('Resource Name'),
+                'description'   => $this->translate('The unique name of this resource')
             )
         );
         $this->addElement(
@@ -50,8 +50,8 @@ class DbResourceForm extends Form
             'db',
             array(
                 'required'      => true,
-                'label'         => t('Database Type'),
-                'description'   => t('The type of SQL database'),
+                'label'         => $this->translate('Database Type'),
+                'description'   => $this->translate('The type of SQL database'),
                 'multiOptions'  => $dbChoices
             )
         );
@@ -60,8 +60,8 @@ class DbResourceForm extends Form
             'host',
             array (
                 'required'      => true,
-                'label'         => t('Host'),
-                'description'   => t('The hostname of the database'),
+                'label'         => $this->translate('Host'),
+                'description'   => $this->translate('The hostname of the database'),
                 'value'         => 'localhost'
             )
         );
@@ -70,8 +70,8 @@ class DbResourceForm extends Form
             'port',
             array(
                 'required'      => true,
-                'label'         => t('Port'),
-                'description'   => t('The port to use'),
+                'label'         => $this->translate('Port'),
+                'description'   => $this->translate('The port to use'),
                 'value'         => 3306
             )
         );
@@ -80,8 +80,8 @@ class DbResourceForm extends Form
             'dbname',
             array(
                 'required'      => true,
-                'label'         => t('Database Name'),
-                'description'   => t('The name of the database to use')
+                'label'         => $this->translate('Database Name'),
+                'description'   => $this->translate('The name of the database to use')
             )
         );
         $this->addElement(
@@ -89,8 +89,8 @@ class DbResourceForm extends Form
             'username',
             array (
                 'required'      => true,
-                'label'         => t('Username'),
-                'description'   => t('The user name to use for authentication')
+                'label'         => $this->translate('Username'),
+                'description'   => $this->translate('The user name to use for authentication')
             )
         );
         $this->addElement(
@@ -99,8 +99,8 @@ class DbResourceForm extends Form
             array(
                 'required'          => true,
                 'renderPassword'    => true,
-                'label'             => t('Password'),
-                'description'       => t('The password to use for authentication')
+                'label'             => $this->translate('Password'),
+                'description'       => $this->translate('The password to use for authentication')
             )
         );
 
@@ -132,7 +132,9 @@ class DbResourceForm extends Form
             $resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
             $resource->getConnection()->getConnection();
         } catch (Exception $e) {
-            $form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
+            $form->addError(
+                $form->translate('Connectivity validation failed, connection to the given resource not possible.')
+            );
             return false;
         }
 
diff --git a/application/forms/Config/Resource/FileResourceForm.php b/application/forms/Config/Resource/FileResourceForm.php
index 8e2920313..960926114 100644
--- a/application/forms/Config/Resource/FileResourceForm.php
+++ b/application/forms/Config/Resource/FileResourceForm.php
@@ -30,8 +30,8 @@ class FileResourceForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Resource Name'),
-                'description'   => t('The unique name of this resource')
+                'label'         => $this->translate('Resource Name'),
+                'description'   => $this->translate('The unique name of this resource')
             )
         );
         $this->addElement(
@@ -39,8 +39,8 @@ class FileResourceForm extends Form
             'filename',
             array(
                 'required'      => true,
-                'label'         => t('Filepath'),
-                'description'   => t('The filename to fetch information from'),
+                'label'         => $this->translate('Filepath'),
+                'description'   => $this->translate('The filename to fetch information from'),
                 'validators'    => array(new ReadablePathValidator())
             )
         );
@@ -49,8 +49,8 @@ class FileResourceForm extends Form
             'fields',
             array(
                 'required'      => true,
-                'label'         => t('Pattern'),
-                'description'   => t('The regular expression by which to identify columns')
+                'label'         => $this->translate('Pattern'),
+                'description'   => $this->translate('The regular expression by which to identify columns')
             )
         );
 
diff --git a/application/forms/Config/Resource/LdapResourceForm.php b/application/forms/Config/Resource/LdapResourceForm.php
index 6641b96bb..3293546c5 100644
--- a/application/forms/Config/Resource/LdapResourceForm.php
+++ b/application/forms/Config/Resource/LdapResourceForm.php
@@ -32,8 +32,8 @@ class LdapResourceForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Resource Name'),
-                'description'   => t('The unique name of this resource')
+                'label'         => $this->translate('Resource Name'),
+                'description'   => $this->translate('The unique name of this resource')
             )
         );
         $this->addElement(
@@ -41,8 +41,10 @@ class LdapResourceForm extends Form
             'hostname',
             array(
                 'required'      => true,
-                'label'         => t('Host'),
-                'description'   => t('The hostname or address of the LDAP server to use for authentication'),
+                'label'         => $this->translate('Host'),
+                'description'   => $this->translate(
+                    'The hostname or address of the LDAP server to use for authentication'
+                ),
                 'value'         => 'localhost'
             )
         );
@@ -51,8 +53,8 @@ class LdapResourceForm extends Form
             'port',
             array(
                 'required'      => true,
-                'label'         => t('Port'),
-                'description'   => t('The port of the LDAP server to use for authentication'),
+                'label'         => $this->translate('Port'),
+                'description'   => $this->translate('The port of the LDAP server to use for authentication'),
                 'value'         => 389
             )
         );
@@ -61,8 +63,10 @@ class LdapResourceForm extends Form
             'root_dn',
             array(
                 'required'      => true,
-                'label'         => t('Root DN'),
-                'description'   => t('Only the root and its child nodes will be accessible on this resource.')
+                'label'         => $this->translate('Root DN'),
+                'description'   => $this->translate(
+                    'Only the root and its child nodes will be accessible on this resource.'
+                )
             )
         );
         $this->addElement(
@@ -70,8 +74,8 @@ class LdapResourceForm extends Form
             'bind_dn',
             array(
                 'required'      => true,
-                'label'         => t('Bind DN'),
-                'description'   => t('The user dn to use for querying the ldap server')
+                'label'         => $this->translate('Bind DN'),
+                'description'   => $this->translate('The user dn to use for querying the ldap server')
             )
         );
         $this->addElement(
@@ -80,8 +84,8 @@ class LdapResourceForm extends Form
             array(
                 'required'          => true,
                 'renderPassword'    => true,
-                'label'             => t('Bind Password'),
-                'description'       => t('The password to use for querying the ldap server')
+                'label'             => $this->translate('Bind Password'),
+                'description'       => $this->translate('The password to use for querying the ldap server')
             )
         );
 
@@ -119,7 +123,9 @@ class LdapResourceForm extends Form
                 throw new Exception();
             }
         } catch (Exception $e) {
-            $form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
+            $form->addError(
+                $form->translate('Connectivity validation failed, connection to the given resource not possible.')
+            );
             return false;
         }
 
diff --git a/application/forms/Config/Resource/LivestatusResourceForm.php b/application/forms/Config/Resource/LivestatusResourceForm.php
index d90600370..e893a4657 100644
--- a/application/forms/Config/Resource/LivestatusResourceForm.php
+++ b/application/forms/Config/Resource/LivestatusResourceForm.php
@@ -33,8 +33,8 @@ class LivestatusResourceForm extends Form
             'name',
             array(
                 'required'      => true,
-                'label'         => t('Resource Name'),
-                'description'   => t('The unique name of this resource')
+                'label'         => $this->translate('Resource Name'),
+                'description'   => $this->translate('The unique name of this resource')
             )
         );
         $this->addElement(
@@ -42,9 +42,9 @@ class LivestatusResourceForm extends Form
             'socket',
             array(
                 'required'      => true,
-                'label'         => t('Socket'),
-                'description'   => t('The path to your livestatus socket used for querying monitoring data'),
-                'value'         => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus')
+                'label'         => $this->translate('Socket'),
+                'description'   => $this->translate('The path to your livestatus socket used for querying monitoring data'),
+                'value'         => '/var/run/icinga2/cmd/livestatus'
             )
         );
 
@@ -75,8 +75,10 @@ class LivestatusResourceForm extends Form
         try {
             $resource = ResourceFactory::createResource(new ConfigObject($form->getValues()));
             $resource->connect()->disconnect();
-        } catch (Exception $e) {
-            $form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
+        } catch (Exception $_) {
+            $form->addError(
+                $form->translate('Connectivity validation failed, connection to the given resource not possible.')
+            );
             return false;
         }
 
diff --git a/application/forms/Config/ResourceConfigForm.php b/application/forms/Config/ResourceConfigForm.php
index e7933c18f..67912142a 100644
--- a/application/forms/Config/ResourceConfigForm.php
+++ b/application/forms/Config/ResourceConfigForm.php
@@ -22,7 +22,7 @@ class ResourceConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_resource');
-        $this->setSubmitLabel(t('Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
@@ -43,7 +43,7 @@ class ResourceConfigForm extends ConfigForm
         } elseif ($type === 'file') {
             return new FileResourceForm();
         } else {
-            throw new InvalidArgumentException(sprintf(t('Invalid resource type "%s" provided'), $type));
+            throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type));
         }
     }
 
@@ -62,9 +62,9 @@ class ResourceConfigForm extends ConfigForm
     {
         $name = isset($values['name']) ? $values['name'] : '';
         if (! $name) {
-            throw new InvalidArgumentException(t('Resource name missing'));
+            throw new InvalidArgumentException($this->translate('Resource name missing'));
         } elseif ($this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Resource already exists'));
+            throw new InvalidArgumentException($this->translate('Resource already exists'));
         }
 
         unset($values['name']);
@@ -85,11 +85,11 @@ class ResourceConfigForm extends ConfigForm
     public function edit($name, array $values)
     {
         if (! $name) {
-            throw new InvalidArgumentException(t('Old resource name missing'));
+            throw new InvalidArgumentException($this->translate('Old resource name missing'));
         } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
-            throw new InvalidArgumentException(t('New resource name missing'));
+            throw new InvalidArgumentException($this->translate('New resource name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Unknown resource provided'));
+            throw new InvalidArgumentException($this->translate('Unknown resource provided'));
         }
 
         $resourceConfig = $this->config->getSection($name);
@@ -111,9 +111,9 @@ class ResourceConfigForm extends ConfigForm
     public function remove($name)
     {
         if (! $name) {
-            throw new InvalidArgumentException(t('Resource name missing'));
+            throw new InvalidArgumentException($this->translate('Resource name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(t('Unknown resource provided'));
+            throw new InvalidArgumentException($this->translate('Unknown resource provided'));
         }
 
         $resourceConfig = $this->config->getSection($name);
@@ -143,10 +143,10 @@ class ResourceConfigForm extends ConfigForm
         try {
             if ($resource === null) { // create new resource
                 $this->add($this->getValues());
-                $message = t('Resource "%s" has been successfully created');
+                $message = $this->translate('Resource "%s" has been successfully created');
             } else { // edit existing resource
                 $this->edit($resource, $this->getValues());
-                $message = t('Resource "%s" has been successfully changed');
+                $message = $this->translate('Resource "%s" has been successfully changed');
             }
         } catch (InvalidArgumentException $e) {
             Notification::error($e->getMessage());
@@ -172,9 +172,9 @@ class ResourceConfigForm extends ConfigForm
         $resource = $this->request->getQuery('resource');
         if ($resource !== null) {
             if ($resource === '') {
-                throw new ConfigurationError(t('Resource name missing'));
+                throw new ConfigurationError($this->translate('Resource name missing'));
             } elseif (! $this->config->hasSection($resource)) {
-                throw new ConfigurationError(t('Unknown resource provided'));
+                throw new ConfigurationError($this->translate('Unknown resource provided'));
             }
 
             $configValues = $this->config->getSection($resource)->toArray();
@@ -197,8 +197,8 @@ class ResourceConfigForm extends ConfigForm
             array(
                 'order'         => 0,
                 'ignore'        => true,
-                'label'         => t('Force Changes'),
-                'description'   => t('Check this box to enforce changes without connectivity validation')
+                'label'         => $this->translate('Force Changes'),
+                'description'   => $this->translate('Check this box to enforce changes without connectivity validation')
             )
         );
     }
@@ -211,14 +211,14 @@ class ResourceConfigForm extends ConfigForm
         $resourceType = isset($formData['type']) ? $formData['type'] : 'db';
 
         $resourceTypes = array(
-            'file'          => t('File'),
+            'file'          => $this->translate('File'),
             'livestatus'    => 'Livestatus',
         );
         if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
             $resourceTypes['ldap'] = 'LDAP';
         }
         if ($resourceType === 'db' || Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) {
-            $resourceTypes['db'] = t('SQL Database');
+            $resourceTypes['db'] = $this->translate('SQL Database');
         }
 
         $this->addElement(
@@ -227,8 +227,8 @@ class ResourceConfigForm extends ConfigForm
             array(
                 'required'          => true,
                 'autosubmit'        => true,
-                'label'             => t('Resource Type'),
-                'description'       => t('The type of resource'),
+                'label'             => $this->translate('Resource Type'),
+                'description'       => $this->translate('The type of resource'),
                 'multiOptions'      => $resourceTypes,
                 'value'             => $resourceType
             )
diff --git a/application/forms/ConfirmRemovalForm.php b/application/forms/ConfirmRemovalForm.php
index 02d7263df..6840db37d 100644
--- a/application/forms/ConfirmRemovalForm.php
+++ b/application/forms/ConfirmRemovalForm.php
@@ -17,6 +17,6 @@ class ConfirmRemovalForm extends Form
     public function init()
     {
         $this->setName('form_confirm_removal');
-        $this->setSubmitLabel(t('Confirm Removal'));
+        $this->setSubmitLabel($this->translate('Confirm Removal'));
     }
 }
diff --git a/application/forms/Dashboard/DashletForm.php b/application/forms/Dashboard/DashletForm.php
index 6c38ff97e..e58ca8aba 100644
--- a/application/forms/Dashboard/DashletForm.php
+++ b/application/forms/Dashboard/DashletForm.php
@@ -26,7 +26,7 @@ class DashletForm extends Form
     {
         $this->setName('form_dashboard_addurl');
         if (! $this->getSubmitLabel()) {
-            $this->setSubmitLabel(t('Add To Dashboard'));
+            $this->setSubmitLabel($this->translate('Add To Dashboard'));
         }
         $this->setAction(URL::fromRequest());
     }
@@ -66,9 +66,10 @@ class DashletForm extends Form
             'url',
             array(
                 'required'      => true,
-                'label'         => t('Url'),
-                'description'   =>
-                    t('Enter url being loaded in the dashlet. You can paste the full URL, including filters.')
+                'label'         => $this->translate('Url'),
+                'description'   => $this->translate(
+                    'Enter url being loaded in the dashlet. You can paste the full URL, including filters.'
+                )
             )
         );
         $this->addElement(
@@ -76,8 +77,8 @@ class DashletForm extends Form
             'dashlet',
             array(
                 'required'      => true,
-                'label'         => t('Dashlet Title'),
-                'description'   => t('Enter a title for the dashlet.')
+                'label'         => $this->translate('Dashlet Title'),
+                'description'   => $this->translate('Enter a title for the dashlet.')
             )
         );
         $this->addElement(
@@ -95,9 +96,8 @@ class DashletForm extends Form
                 'pane',
                 array(
                     'required'      => true,
-                    'label'         => t("New Dashboard Title"),
-                    'description'   =>
-                        t('Enter a title for the new pane.')
+                    'label'         => $this->translate("New Dashboard Title"),
+                    'description'   => $this->translate('Enter a title for the new pane.')
                 )
             );
         } else {
@@ -106,10 +106,9 @@ class DashletForm extends Form
                 'pane',
                 array(
                     'required'      => true,
-                    'label'         => t('Dashboard'),
+                    'label'         => $this->translate('Dashboard'),
                     'multiOptions'  => $panes,
-                    'description'   =>
-                        t('Select a pane you want to add the dashlet.')
+                    'description'   => $this->translate('Select a pane you want to add the dashlet.')
                 )
             );
         }
@@ -119,9 +118,9 @@ class DashletForm extends Form
             'create_new_pane',
             array(
                 'required'      => false,
-                'label'         => t('New dashboard'),
+                'label'         => $this->translate('New dashboard'),
                 'class'         => 'autosubmit',
-                'description'   => t('Check this box if you want to add the dashlet to a new dashboard')
+                'description'   => $this->translate('Check this box if you want to add the dashlet to a new dashboard')
             )
         );
     }
diff --git a/application/forms/LdapDiscoveryForm.php b/application/forms/LdapDiscoveryForm.php
index 0fd0ea0d3..6a14c2ecd 100644
--- a/application/forms/LdapDiscoveryForm.php
+++ b/application/forms/LdapDiscoveryForm.php
@@ -26,8 +26,8 @@ class LdapDiscoveryForm extends Form
             'domain',
             array(
                 'required'      => true,
-                'label'         => t('Search Domain'),
-                'description'   => t('Search this domain for records of available servers.'),
+                'label'         => $this->translate('Search Domain'),
+                'description'   => $this->translate('Search this domain for records of available servers.'),
             )
         );
 
@@ -36,7 +36,7 @@ class LdapDiscoveryForm extends Form
                 'note',
                 'additional_description',
                 array(
-                    'value' => t('No Ldap servers found on this domain.'
+                    'value' => $this->translate('No Ldap servers found on this domain.'
                         . ' You can try to specify host and port and try again, or just skip this step and '
                         . 'configure the server manually.'
                     )
@@ -47,8 +47,8 @@ class LdapDiscoveryForm extends Form
                 'hostname',
                 array(
                     'required'      => false,
-                    'label'         => t('Host'),
-                    'description'   => t('IP or host name to search.'),
+                    'label'         => $this->translate('Host'),
+                    'description'   => $this->translate('IP or hostname to search.'),
                 )
             );
 
@@ -57,8 +57,8 @@ class LdapDiscoveryForm extends Form
                 'port',
                 array(
                     'required'      => false,
-                    'label'         => t('Port'),
-                    'description'   => t('Port', 389),
+                    'label'         => $this->translate('Port'),
+                    'description'   => $this->translate('Port', 389),
                 )
             );
         }
diff --git a/application/forms/PreferenceForm.php b/application/forms/PreferenceForm.php
index e3cfdf319..ed20c58cd 100644
--- a/application/forms/PreferenceForm.php
+++ b/application/forms/PreferenceForm.php
@@ -86,7 +86,7 @@ class PreferenceForm extends Form
      */
     public function onSuccess()
     {
-        $this->preferences = new Preferences($this->store->load());
+        $this->preferences = new Preferences($this->store ? $this->store->load() : array());
 
         $webPreferences = $this->preferences->get('icingaweb', array());
         foreach ($this->getValues() as $key => $value) {
@@ -103,11 +103,11 @@ class PreferenceForm extends Form
         Session::getSession()->user->setPreferences($this->preferences);
 
         try {
-            if ($this->getElement('btn_submit_preferences')->isChecked()) {
+            if ($this->store && $this->getElement('btn_submit_preferences')->isChecked()) {
                 $this->save();
-                Notification::success(t('Preferences successfully saved'));
+                Notification::success($this->translate('Preferences successfully saved'));
             } else {
-                Notification::success(t('Preferences successfully saved for the current session'));
+                Notification::success($this->translate('Preferences successfully saved for the current session'));
             }
         } catch (Exception $e) {
             Logger::error($e);
@@ -142,13 +142,13 @@ class PreferenceForm extends Form
     public function createElements(array $formData)
     {
         $languages = array();
-        $languages['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getLocale());
+        $languages['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getLocale());
         foreach (Translator::getAvailableLocaleCodes() as $language) {
             $languages[$language] = $language;
         }
 
         $tzList = array();
-        $tzList['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone());
+        $tzList['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone());
         foreach (DateTimeZone::listIdentifiers() as $tz) {
             $tzList[$tz] = $tz;
         }
@@ -158,8 +158,8 @@ class PreferenceForm extends Form
             'language',
             array(
                 'required'      => true,
-                'label'         => t('Your Current Language'),
-                'description'   => t('Use the following language to display texts and messages'),
+                'label'         => $this->translate('Your Current Language'),
+                'description'   => $this->translate('Use the following language to display texts and messages'),
                 'multiOptions'  => $languages,
                 'value'         => substr(setlocale(LC_ALL, 0), 0, 5)
             )
@@ -170,8 +170,8 @@ class PreferenceForm extends Form
             'timezone',
             array(
                 'required'      => true,
-                'label'         => t('Your Current Timezone'),
-                'description'   => t('Use the following timezone for dates and times'),
+                'label'         => $this->translate('Your Current Timezone'),
+                'description'   => $this->translate('Use the following timezone for dates and times'),
                 'multiOptions'  => $tzList,
                 'value'         => $this->getDefaultTimezone()
             )
@@ -182,29 +182,31 @@ class PreferenceForm extends Form
             'show_benchmark',
             array(
                 'required'  => true,
-                'label'     => t('Use benchmark')
+                'label'     => $this->translate('Use benchmark')
             )
         );
 
-        $this->addElement(
-            'submit',
-            'btn_submit_preferences',
-            array(
-                'ignore'        => true,
-                'label'         => t('Save to the Preferences'),
-                'decorators'    => array(
-                    'ViewHelper',
-                    array('HtmlTag', array('tag' => 'div'))
+        if ($this->store) {
+            $this->addElement(
+                'submit',
+                'btn_submit_preferences',
+                array(
+                    'ignore'        => true,
+                    'label'         => $this->translate('Save to the Preferences'),
+                    'decorators'    => array(
+                        'ViewHelper',
+                        array('HtmlTag', array('tag' => 'div'))
+                    )
                 )
-            )
-        );
+            );
+        }
 
         $this->addElement(
             'submit',
             'btn_submit_session',
             array(
                 'ignore'        => true,
-                'label'         => t('Save for the current Session'),
+                'label'         => $this->translate('Save for the current Session'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'div'))
diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php
index 0fb53e858..f32c0cab4 100644
--- a/application/forms/Security/RoleForm.php
+++ b/application/forms/Security/RoleForm.php
@@ -6,6 +6,7 @@ namespace Icinga\Forms\Security;
 
 use InvalidArgumentException;
 use LogicException;
+use Zend_Form_Element;
 use Icinga\Application\Icinga;
 use Icinga\Forms\ConfigForm;
 use Icinga\Util\String;
@@ -18,14 +19,14 @@ class RoleForm extends ConfigForm
     /**
      * Provided permissions by currently loaded modules
      *
-     * @var array
+     * @type array
      */
-    protected $providedPermissions = array();
+    protected $providedPermissions = array('*' => '*');
 
     /**
      * Provided restrictions by currently loaded modules
      *
-     * @var array
+     * @type array
      */
     protected $providedRestrictions = array();
 
@@ -35,14 +36,26 @@ class RoleForm extends ConfigForm
      */
     public function init()
     {
+        $helper = new Zend_Form_Element('bogus');
         foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
             foreach ($module->getProvidedPermissions() as $permission) {
-                /** @var object $permission */
+                /** @type object $permission */
                 $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description;
             }
             foreach ($module->getProvidedRestrictions() as $restriction) {
-                /** @var object $restriction */
-                $this->providedRestrictions[$restriction->name] = $restriction->description;
+                /** @type object $restriction */
+                $name = $helper->filterName($restriction->name); // Zend only permits alphanumerics, the underscore,
+                                                                 // the circumflex and any ASCII character in range
+                                                                 // \x7f to \xff (127 to 255)
+                while (isset($this->providedRestrictions[$name])) {
+                    // Because Zend_Form_Element::filterName() replaces any not permitted character with the empty
+                    // string we may have duplicate names, e.g. 're/striction' and 'restriction'
+                    $name .= '_';
+                }
+                $this->providedRestrictions[$name] = array(
+                    'description'   => $restriction->description,
+                    'name'          => $restriction->name
+                );
             }
         }
     }
@@ -59,8 +72,8 @@ class RoleForm extends ConfigForm
                 'name',
                 array(
                     'required'      => true,
-                    'label'         => t('Role Name'),
-                    'description'   => t('The name of the role'),
+                    'label'         => $this->translate('Role Name'),
+                    'description'   => $this->translate('The name of the role'),
                     'ignore'        => true
                 ),
             ),
@@ -68,35 +81,37 @@ class RoleForm extends ConfigForm
                 'textarea',
                 'users',
                 array(
-                    'label'         => t('Users'),
-                    'description'   => t('Comma-separated list of users that are assigned to the role')
+                    'label'         => $this->translate('Users'),
+                    'description'   => $this->translate('Comma-separated list of users that are assigned to the role')
                 ),
             ),
             array(
                 'textarea',
                 'groups',
                 array(
-                    'label'         => t('Groups'),
-                    'description'   => t('Comma-separated list of groups that are assigned to the role')
+                    'label'         => $this->translate('Groups'),
+                    'description'   => $this->translate('Comma-separated list of groups that are assigned to the role')
                 ),
             ),
             array(
                 'multiselect',
                 'permissions',
                 array(
-                    'label'         => t('Permissions Set'),
-                    'description'   => t('The permissions to grant. You may select more than one permission'),
+                    'label'         => $this->translate('Permissions Set'),
+                    'description'   => $this->translate(
+                        'The permissions to grant. You may select more than one permission'
+                    ),
                     'multiOptions'  => $this->providedPermissions
                 )
             )
         ));
-        foreach ($this->providedRestrictions as $name => $description) {
+        foreach ($this->providedRestrictions as $name => $spec) {
             $this->addElement(
                 'text',
                 $name,
                 array(
-                    'label'         => $name,
-                    'description'   => $description
+                    'label'         => $spec['name'],
+                    'description'   => $spec['description']
                 )
             );
         }
@@ -120,7 +135,7 @@ class RoleForm extends ConfigForm
         }
         if (! $this->config->hasSection($name)) {
             throw new InvalidArgumentException(sprintf(
-                t('Can\'t load role \'%s\'. Role does not exist'),
+                $this->translate('Can\'t load role \'%s\'. Role does not exist'),
                 $name
             ));
         }
@@ -129,6 +144,15 @@ class RoleForm extends ConfigForm
             ? String::trimSplit($role['permissions'])
             : null;
         $role['name'] = $name;
+        $restrictions = array();
+        foreach ($this->providedRestrictions as $name => $spec) {
+            if (isset($role[$spec['name']])) {
+                // Translate restriction names to filtered element names
+                $restrictions[$name] = $role[$spec['name']];
+                unset($role[$spec['name']]);
+            }
+        }
+        $role = array_merge($role, $restrictions);
         $this->populate($role);
         return $this;
     }
@@ -152,7 +176,7 @@ class RoleForm extends ConfigForm
         }
         if ($this->config->hasSection($name)) {
             throw new InvalidArgumentException(sprintf(
-                t('Can\'t add role \'%s\'. Role already exists'),
+                $this->translate('Can\'t add role \'%s\'. Role already exists'),
                 $name
             ));
         }
@@ -178,7 +202,7 @@ class RoleForm extends ConfigForm
         }
         if (! $this->config->hasSection($name)) {
             throw new InvalidArgumentException(sprintf(
-                t('Can\'t remove role \'%s\'. Role does not exist'),
+                $this->translate('Can\'t remove role \'%s\'. Role does not exist'),
                 $name
             ));
         }
@@ -211,7 +235,7 @@ class RoleForm extends ConfigForm
         } else {
             if (! $this->config->hasSection($name)) {
                 throw new InvalidArgumentException(sprintf(
-                    t('Can\'t update role \'%s\'. Role does not exist'),
+                    $this->translate('Can\'t update role \'%s\'. Role does not exist'),
                     $name
                 ));
             }
@@ -230,6 +254,15 @@ class RoleForm extends ConfigForm
         if (isset($values['permissions'])) {
             $values['permissions'] = implode(', ', $values['permissions']);
         }
+        $restrictions = array();
+        foreach ($this->providedRestrictions as $name => $spec) {
+            if (isset($values[$name])) {
+                // Translate filtered element names to restriction names
+                $restrictions[$spec['name']] = $values[$name];
+                unset($values[$name]);
+            }
+        }
+        $values = array_merge($values, $restrictions);
         return $values;
     }
 }
diff --git a/application/layouts/scripts/parts/navigation.phtml b/application/layouts/scripts/parts/navigation.phtml
index bed44ba5f..dc56b9199 100644
--- a/application/layouts/scripts/parts/navigation.phtml
+++ b/application/layouts/scripts/parts/navigation.phtml
@@ -3,7 +3,6 @@
 use Icinga\Web\Url;
 use Icinga\Web\Menu;
 use Icinga\Web\MenuRenderer;
-use Icinga\Web\Widget\SearchDashboard;
 
 // Don't render a menu for unauthenticated users unless menu is auth aware
 if (! $this->auth()->isAuthenticated()) {
@@ -11,15 +10,16 @@ if (! $this->auth()->isAuthenticated()) {
 }
 
 ?>
-<div
-    id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container" data-icinga-url="<?=$this->href('layout/menu');?>"
-    data-icinga-refresh="15"
->
-  <? if (SearchDashboard::search('dummy')->getPane('search')->hasDashlets()): ?>
-      <form action="<?= $this->href('search') ?>" method="get" role="search">
-        <input type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
-               autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
-      </form>
-  <? endif; ?>
-  <?= new MenuRenderer(Menu::load(), Url::fromRequest()->without('renderLayout')->getRelativeUrl()); ?>
+<div  id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container"
+      data-icinga-url="<?= $this->href('layout/menu') ?>"  data-icinga-refresh="15">
+    <?= $this->partial(
+        'layout/menu.phtml',
+        'default',
+        array(
+            'menuRenderer' => new MenuRenderer(
+                Menu::load(),
+                Url::fromRequest()->without('renderLayout')->getRelativeUrl()
+            )
+        )
+    ) ?>
 </div>
diff --git a/application/views/helpers/FormDateTime.php b/application/views/helpers/FormDateTime.php
index cb760a620..b75dfec62 100644
--- a/application/views/helpers/FormDateTime.php
+++ b/application/views/helpers/FormDateTime.php
@@ -57,7 +57,7 @@ class Zend_View_Helper_FormDateTime extends Zend_View_Helper_FormElement
         $type = $attribs['local'] === true ? 'datetime-local' : 'datetime';
         unset($attribs['local']);  // Unset local to not render it again in $this->_htmlAttribs($attribs)
         $html5 =  sprintf(
-            '<input type="%s" name="%s" id="%s" value="%s"%s%s%s%s%s',
+            '<input type="%s" name="%s" id="%s" step="1" value="%s"%s%s%s%s%s',
             $type,
             $this->view->escape($name),
             $this->view->escape($id),
diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml
index 584d8ad16..805196b96 100644
--- a/application/views/scripts/authentication/login.phtml
+++ b/application/views/scripts/authentication/login.phtml
@@ -1,11 +1,28 @@
  <div id="login">
   <div class="logo">
    <div class="image">
-    <img class="fade-in one" src="<?= $this->baseUrl('img/logo_icinga_big.png') ?>" alt="<?= t('The Icinga logo') ?>" >
+    <img class="fade-in one" src="<?= $this->baseUrl('img/logo_icinga_big.png'); ?>" alt="<?= $this->translate('The Icinga logo'); ?>" >
    </div>
   </div>
   <div class="form" data-base-target="layout">
-    <h1>Welcome to Icinga Web 2</h1>
+    <?php if ($requiresSetup): ?>
+    <p class="config-note"><?= sprintf(
+      $this->translate(
+        'It appears that you did not configure Icinga Web 2 yet so it\'s not possible to log in without any defined '
+        . 'authentication method. Please define a authentication method by following the instructions in the'
+        . ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.'
+      ),
+      '<a href="http://docs.icinga.org/" title="' . $this->translate('Icinga Web 2 Documentation') . '">', // TODO: More exact documentation link..
+      '<a href="' . $this->href('setup') . '" title="' . $this->translate('Icinga Web 2 Setup-Wizard') . '">',
+      '</a>'
+    ); ?></p>
+    <?php elseif ($requiresExternalAuth): ?>
+    <p class="info-box"><span class="icon-info"></span><?= $this->translate(
+      'You\'re currently not authenticated using any of the web server\'s authentication mechanisms.'
+      . ' Make sure you\'ll configure such, otherwise you\'ll not be able to login.'
+    ); ?></p>
+    <?php endif ?>
+    <h1><?= $this->translate('Welcome to Icinga Web 2'); ?></h1>
    <?php
    /* TODO: remove this as soon as notifications and forms are ready */
    if (isset($this->errorInfo)): ?>
@@ -14,18 +31,6 @@
     </div>
    <?php endif ?>
    <?= $this->form ?>
-   <div class="footer">Icinga Web 2 &copy; 2013-2014<br><a href="https://www.icinga.org">The Icinga Project</a></div>
-   <?php if ($configMissing): ?>
-   <div class="config-note"><?= sprintf(
-     t(
-       'You seem not to have Icinga Web 2 configured yet so it\'s not possible to log in without any defined '
-       . 'authentication method. Please define a authentication method by following the instructions in the'
-       . ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.'
-     ),
-     '<a href="http://docs.icinga.org/" title="Icinga Web 2 Documentation">', // TODO: Documentation link
-     '<a href="' . $this->href('setup') . '" title="Icinga Web 2 Setup-Wizard">',
-     '</a>'
-   ); ?></div>
-   <?php endif ?>
+   <div class="footer">Icinga Web 2 &copy; 2013-2015<br><a href="https://www.icinga.org"><?= $this->translate('The Icinga Project'); ?></a></div>
   </div>
  </div>
diff --git a/application/views/scripts/config/authentication/reorder.phtml b/application/views/scripts/config/authentication/reorder.phtml
index 688d99f88..807f80efe 100644
--- a/application/views/scripts/config/authentication/reorder.phtml
+++ b/application/views/scripts/config/authentication/reorder.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_main">
   <?= $tabs; ?>
 </div>
 <div class="content" data-base-target="_next">
diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml
index dab0acc4f..1ffd120b4 100644
--- a/application/views/scripts/config/index.phtml
+++ b/application/views/scripts/config/index.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_main">
 <?= $this->tabs->render($this); ?>
 </div>
 
diff --git a/application/views/scripts/config/logging.phtml b/application/views/scripts/config/logging.phtml
deleted file mode 100644
index da6d886cc..000000000
--- a/application/views/scripts/config/logging.phtml
+++ /dev/null
@@ -1,35 +0,0 @@
-<div class="controls">
-<?= $this->tabs->render($this); ?>
-</div>
-
-<div class="content">
-<?php $errors = $this->form->getErrorMessages(); ?>
-
-<?php if (isset($this->messageBox)): ?>
-  <?= $this->messageBox->render() ?>
-<?php endif ?>
-
-<?php if ($this->successMessage): ?>
-<div>
-  <i class="icinga-icon-success"></i>
-  <strong><?= $this->escape($this->successMessage); ?></strong>
-</div>
-<?php endif; ?>
-
-<?php if (!empty($errors)) : ?>
-<div>
-  <h4>Errors occured when trying to save the project.</h4>
-  <p>
-      The following errors occured when trying to save the configuration:
-  </p>
-  <ul>
-    <?php foreach($errors as $error): ?>
-    <li><?= $this->escape($error) ?></li>
-    <?php endforeach; ?>
-  </ul>
-</div>
-
-<?php endif; ?>
-<?= $this->form ?>
-</div>
-
diff --git a/application/views/scripts/config/module.phtml b/application/views/scripts/config/module.phtml
index cd6ad5af8..e26ade195 100644
--- a/application/views/scripts/config/module.phtml
+++ b/application/views/scripts/config/module.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_right">
 <?= $this->tabs ?>
 <h1><?= $this->escape($module->getTitle()) ?></h1>
 </div>
diff --git a/application/views/scripts/config/resource.phtml b/application/views/scripts/config/resource.phtml
index c5d4ca0fc..f93b2af82 100644
--- a/application/views/scripts/config/resource.phtml
+++ b/application/views/scripts/config/resource.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_main">
   <?= $tabs; ?>
 </div>
 <div class="content" data-base-target="_next">
diff --git a/application/views/scripts/layout/menu.phtml b/application/views/scripts/layout/menu.phtml
index 83196d362..a1e13b060 100644
--- a/application/views/scripts/layout/menu.phtml
+++ b/application/views/scripts/layout/menu.phtml
@@ -5,7 +5,7 @@ use Icinga\Web\Widget\SearchDashboard;
 <? if (SearchDashboard::search('dummy')->getPane('search')->hasDashlets()): ?>
     <form action="<?= $this->href('search') ?>" method="get" role="search">
         <input
-            type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
+            type="text" name="q" class="search" placeholder="<?= $this->translate('Search...') ?>"
             autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
         />
     </form>
diff --git a/application/views/scripts/roles/index.phtml b/application/views/scripts/roles/index.phtml
index 67c957661..db4a6aef2 100644
--- a/application/views/scripts/roles/index.phtml
+++ b/application/views/scripts/roles/index.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_main">
     <?= $tabs ?>
     <h1><?= $this->translate('Roles') ?></h1>
 </div>
@@ -30,7 +30,7 @@
                         <td>
                             <?php
                             // TODO(el): $role->without(...) or $role->shift(...) would be nice!
-                            $restrictions = $role;
+                            $restrictions = clone $role;
                             unset($restrictions['users']);
                             unset($restrictions['groups']);
                             unset($restrictions['permissions']);
diff --git a/doc/authentication.md b/doc/authentication.md
index d36051e8f..542eb9934 100644
--- a/doc/authentication.md
+++ b/doc/authentication.md
@@ -24,7 +24,7 @@ For delegating authentication to the web server simply add `autologin` to your a
 
 ````
 [autologin]
-backend = autologin
+backend = external
 ````
 
 If your web server is not configured for authentication though the `autologin` section has no effect.
diff --git a/doc/external_authentication.md b/doc/external_authentication.md
index 240713038..15df1e1cf 100644
--- a/doc/external_authentication.md
+++ b/doc/external_authentication.md
@@ -1,90 +1,83 @@
-# Externel Authentication
+# External Authentication
 
-It is possible to use the authentication mechanism of the webserver, 
-instead of using the internal authentication-manager to
-authenticate users. This might be useful if you only have very few users, and
-user management over *.htaccess* is sufficient, or if you must use some other
-authentication mechanism that is only available through your webserver.
+It is possible to utilize the authentication mechanism of the webserver instead
+of the internal authentication of Icinga Web 2 to authenticate users. This might
+be useful if you only have very few users and user management over **.htaccess**
+is not sufficient or if you are required to use some other authentication
+mechanism that is only available by utilizing the webserver.
 
-When external authentication is used, Icingaweb will entrust the 
-complete authentication process to the external authentication provider (the webserver):
-The provider should take care of authenticating the user and declining
-all requests with invalid or missing credentials. When the authentication 
-was succesful, it should provide the authenticated users name to its php-module
-and Icingaweb will assume that the user is authorized to access the page.
-Because of this it is very important that the webservers authentication is
-configured correctly, as wrong configuration could lead to unauthorized
-access to the site, or a broken login-process. 
+Icinga Web 2 will entrust the complete authentication process to the
+authentication provider of the webserver, if external authentication is used.
+So it is very important that the webserver's authentication is configured
+correctly as wrong configuration might lead to unauthorized access or a
+malfunction in the login-process.
 
+## Using External Authentication
 
-## Use External Authentication
+External authentication in Icinga Web 2 requires the following preparations:
 
-Using external authentication in Icingaweb requires two steps to work:
+1. The external authentication must be set up properly to correctly
+   authenticate users
+2. Icinga Web 2 must be configured to use external authentication
 
-1. The external authentication must be set up correctly to always
-   authenticate the users.
-2. Icingaweb must be configured to use the external authentication.
+### Preparing the External Authentication Provider
 
+This step depends heavily on the used webserver and authentication mechanism you
+want to use. It is not possible to cover all possibillities and you should
+probably read the documentation for your webserver to get detailed instructions
+on how to set up authentication properly.
 
-### Prepare the External Authentication Provider
-
-This step depends heavily on the used webserver and authentication 
-mechanism you want to use. It is not possible to cover all possibillities 
-and you should probably read the documentation for your webserver for
-detailed instructions on how to set up authentication properly.
-
-In general, you need to make sure that:
-
-	- All routes require authentication
-	- Only permitted users are allowed to authenticate
+In general you need to make sure that:
 
+- All routes require authentication
+- Only permitted users are allowed to authenticate
 
 #### Example Configuration for Apache and HTTPDigestAuthentication
 
-The following example will show how to enable external authentication in Apache using
-*HTTP Digest Authentication*.
+The following example will show how to enable external authentication in Apache
+using *HTTP Digest Authentication*.
 
-##### Create users
+##### Creating users
 
-To create users for a digest authentication we can use the tool *htdigest*.
-We choose *.icingawebdigest* as a name for the created file, containing
-the user credentials.
+To create users for digest authentication you can use the tool *htdigest*. In
+this example **.icingawebdigest** is the name of the file containing the user
+credentials.
 
-This command will create a new file with the user *jdoe*. *htdigest* 
-will prompt you for your password, after it has been executed. If you 
-want to add more users to the file you need to ommit the *-c* parameter 
-in all further commands to avoInid the file to be overwritten.
+This command creates a new file with the user *jdoe*. *htdigest* will prompt
+you for a password. If you want to add more users to the file you need to omit
+the *-c* parameter in all following commands to not to overwrite the file.
 
+````
+sudo htdigest -c /etc/icingaweb2/.icingawebdigest "Icinga Web 2" jdoe
+````
 
-		sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe
+##### Configuring the Webserver
 
+The webserver should require authentication for all public Icinga Web 2 files.
 
-##### Set up authentication
+````
+<Directory "/usr/share/icingaweb2/public">
+    AuthType digest
+    AuthName "Icinga Web 2"
+    AuthDigestProvider file
+    AuthUserFile /etc/icingaweb2/.icingawebdigest
+    Require valid-user
+</Directory>
+````
 
-The webserver should require authentication for all public icingaweb files.
+### Preparing Icinga Web 2
 
+Once external authentication is set up correctly you need to configure Icinga
+Web 2. In case you already completed the setup wizard it is likely that you are
+now finished.
 
-		<Directory "/var/www/html/icingaweb">
-			AuthType digest
-			AuthName "Icingaweb 2"
-			AuthDigestProvider file
-			AuthUserFile /etc/httpd/conf.d/.icingawebdigest
-			Require valid-user
-		</Directory>		
+To get Icinga Web 2 to use external authentication the file
+**config/authentication.ini** is required. Just add the following section
+called "autologin", or any name of your choice, and save your changes:
 
-		
-### Prepare Icingaweb
+````
+[autologin]
+backend = external
+````
 
-When the external authentication is set up correctly, we need
-to configure IcingaWeb to use it as an authentication source. The
-configuration key *authenticationMode* in the section *global* defines
-if the authentication should be handled internally or externally. Since
-we want to delegate the authentication to the Webserver we choose 
-"external" as the new value:
-
-
-		[global]
-		; ...
-		authenticationMode = "external"
-		; ...
-		
+Congratulations! You are now logged in when visiting Icinga Web 2.
\ No newline at end of file
diff --git a/doc/installation.md b/doc/installation.md
index 88c9c3650..170199832 100644
--- a/doc/installation.md
+++ b/doc/installation.md
@@ -6,7 +6,7 @@ system and distribution you are running. But it is also possible to install Icin
 ## <a id="installation-requirements"></a> Installing Requirements
 
 * A web server, e.g. Apache or nginx
-* PHP >= 5.3.0
+* PHP >= 5.3.0 w/ gettext and OpenSSL support
 * MySQL or PostgreSQL PHP libraries when using a database for authentication or storing user preferences into a database
 * LDAP PHP library when using Active Directory or LDAP for authentication
 * Icinga 1.x w/ Livestatus or IDO, Icinga 2 w/ Livestatus or IDO feature enabled
@@ -26,7 +26,7 @@ repository either via git or http protocol using the following URLs:
   * http://git.icinga.org/icingaweb2.git
 
 There is also a browsable version available at
-[gi.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository").
+[git.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository").
 This version also offers snapshots for easy download which you can use if you do not have git present on your system.
 
 ````
@@ -38,25 +38,73 @@ git clone git://git.icinga.org/icingaweb2.git
 Choose a target directory and move Icinga Web 2 there.
 
 ````
-mv icingaweb2 /usr/share/icingaweb
+mv icingaweb2 /usr/share/icingaweb2
 ````
 
 **Step 3: Configuring the Web Server**
 
 Use `icingacli` to generate web server configuration for either Apache or nginx.
 
-*Apache*
-
+Apache:
 ````
-./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb/public
+./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public
 ````
 
-*nginx*
-
+nginx:
 ````
-./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb/public
+./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public
 ````
 
-**Step 4: Web Setup**
+**Step 4: Preparing Web Setup**
 
-Visit Icinga Web 2 in your browser and complete installation using the web setup.
+Because both web and CLI must have access to configuration and logs, permissions will be managed using a special
+system group. The web server user and CLI user have to be added to this system group.
+
+Add the system group `icingaweb2` in the first place.
+
+Fedora, RHEL, CentOS, SLES and OpenSUSE:
+````
+groupadd -r icingaweb2
+````
+
+Debian and Ubuntu:
+````
+addgroup --system icingaweb2
+````
+
+Add your web server's user to the system group `icingaweb2`:
+
+Fedora, RHEL and CentOS:
+````
+usermod -a -G icingaweb2 apache
+````
+
+SLES and OpenSUSE:
+````
+usermod -G icingaweb2 wwwrun
+````
+
+Debian and Ubuntu:
+````
+usermod -a -G icingaweb2 wwwrun
+````
+
+Use `icingacli` to create the configuration directory which defaults to **/etc/icingaweb2**:
+````
+./bin/icingacli setup config directory
+````
+
+When using the web setup you are required to authenticate using a token. In order to generate a token use the
+`icingacli`:
+````
+./bin/icingacli setup token create
+````
+
+In case you do not remember the token you can show it using the `icingacli`:
+````
+./bin/icingacli setup token show
+````
+
+**Step 5: Web Setup**
+
+Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup
diff --git a/doc/vagrant.md b/doc/vagrant.md
new file mode 100644
index 000000000..b1b98b436
--- /dev/null
+++ b/doc/vagrant.md
@@ -0,0 +1,52 @@
+# Vagrant
+
+## Requirements
+
+* Vagrant &gt;= version 1.5
+* VirtualBox or Parallels
+
+> **Note:** The deployment of the virtual machine is tested against Vagrant starting with version 1.5.
+> Unfortunately older versions will not work.
+
+## General
+
+The Icinga Web 2 project ships with a Vagrant virtual machine that integrates
+the source code with various services and example data in a controlled
+environment. This enables developers and users to test Livestatus,
+MySQL and PostgreSQL backends as well as the LDAP authentication. All you
+have to do is install Vagrant and run:
+
+````
+vagrant up
+````
+
+> **Note:** The first boot of the vm takes a fairly long time because
+> you'll download a plain CentOS base box and Vagrant will automatically
+> provision the environment on the first go.
+
+After you should be able to browse [localhost:8080/icingaweb2](http://localhost:8080/icingaweb2).
+
+## Log into Icinga Web 2
+
+Both LDAP and a MySQL are configured as authentication backend. Please use one of the following login credentials:
+
+> LDAP:
+>> **Username**: `jdoe`
+
+>> **Password**: `password`
+
+>MySQL:
+>> **Username**: `icingaadmin`
+
+>> **Password**: `icinga`
+
+
+
+## Testing the Source Code
+
+All software required to run tests is installed in the virtual machine.
+In order to run all tests you have to execute the following command:
+
+````
+vagrant ssh -c "icingacli test php unit"
+````
diff --git a/icingaweb2.spec b/icingaweb2.spec
index fb628f995..cd1ee485f 100644
--- a/icingaweb2.spec
+++ b/icingaweb2.spec
@@ -1,237 +1,271 @@
-#/**
-# * This file is part of Icinga Web 2.
-# *
-# * Icinga Web 2 - Head for multiple monitoring backends.
-# * Copyright (C) 2014 Icinga Development Team
-# *
-# * This program is free software; you can redistribute it and/or
-# * modify it under the terms of the GNU General Public License
-# * as published by the Free Software Foundation; either version 2
-# * of the License, or (at your option) any later version.
-# *
-# * This program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; if not, write to the Free Software
-# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-# *
-# * @copyright  2014 Icinga Development Team <info@icinga.org>
-# * @license    http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
-# * @author     Icinga Development Team <info@icinga.org>
-# *
-# */
+%define revision 1.beta2
 
-%define revision 1
-
-%define configdir %{_sysconfdir}/%{name}
-%define sharedir %{_datadir}/%{name}
-%define prefixdir %{_datadir}/%{name}
-%define usermodparam -a -G
-%define logdir %{_localstatedir}/log/%{name}
-%define docdir %{sharedir}/doc
-
-%if "%{_vendor}" == "suse"
-%define phpname php5
-%define phpzendname php5-ZendFramework
-%define apache2modphpname apache2-mod_php5
-%endif
-# SLE 11 = 1110
-%if 0%{?suse_version} == 1110
-%define phpname php53
-%define apache2modphpname apache2-mod_php53
-%define usermodparam -A
-%endif
-
-%if "%{_vendor}" == "redhat"
-%define phpname php
-%define phpzendname php-ZendFramework
-%endif
-
-# el5 requires newer php53 rather than php (5.1)
-%if 0%{?el5} || 0%{?rhel} == 5 || "%{?dist}" == ".el5"
-%define phpname php53
-%endif
-
-%if "%{_vendor}" == "suse"
-%define apacheconfdir  %{_sysconfdir}/apache2/conf.d
-%define apacheuser wwwrun
-%define apachegroup www
-%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd
-%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus
-%endif
-%if "%{_vendor}" == "redhat"
-%define apacheconfdir %{_sysconfdir}/httpd/conf.d
-%define apacheuser apache
-%define apachegroup apache
-%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd
-%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus
-%endif
-
-Summary:        Open Source host, service and network monitoring Web UI
 Name:           icingaweb2
-Version:        0.0.1
+Version:        2.0.0
 Release:        %{revision}%{?dist}
-License:        GPLv2
+Summary:        Icinga Web 2
 Group:          Applications/System
-URL:            http://www.icinga.org
+License:        GPL
+URL:            https://icinga.org
+Source0:        https://github.com/Icinga/%{name}/archive/v%{version}.tar.gz
 BuildArch:      noarch
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}
+Packager:       Icinga Team <info@icinga.org>
 
-%if "%{_vendor}" == "suse"
-AutoReqProv:    Off
+%if 0%{?fedora} || 0%{?rhel}
+%define wwwconfigdir    %{_sysconfdir}/httpd/conf.d
+%define wwwuser         apache
+%if 0%{?rhel} == 5
+%define php     php53
+%define php_cli php53-cli
+%else
+%define php     php
+%define php_cli php-cli
+%endif
+%if 0%{?rhel} == 6
+%define zend php-ZendFramework
+%else
+%define zend %{name}-vendor-Zend
+%endif
 %endif
 
-Source:        icingaweb2-%{version}.tar.gz
 
-BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root
-
-BuildRequires:  %{phpname} >= 5.3.0
-BuildRequires:  %{phpname}-devel >= 5.3.0
-BuildRequires:  %{phpname}-ldap
-BuildRequires:  %{phpname}-pdo
-BuildRequires:  %{phpzendname}
-%if "%{_vendor}" != "suse"
-BuildRequires:  %{phpzendname}-Db-Adapter-Pdo
-BuildRequires:  %{phpzendname}-Db-Adapter-Pdo-Mysql
-BuildRequires:  %{phpzendname}-Db-Adapter-Pdo-Pgsql
+%if 0%{?suse_version}
+%define wwwconfigdir    %{_sysconfdir}/apache2/conf.d
+%define wwwuser         wwwrun
+%define zend            php5-ZendFramework
+%if 0%{?suse_version} == 1110
+%define php php53
+Requires: apache2-mod_php53
+%else
+%define php php5
+Requires: apache2-mod_php5
+%endif
 %endif
 
-%if "%{_vendor}" == "redhat"
-%endif
-%if "%{_vendor}" == "suse"
-Requires:       %{phpname}-devel >= 5.3.0
-BuildRequires:  %{phpname}-json
-BuildRequires:  %{phpname}-sockets
-BuildRequires:  %{phpname}-dom
-%endif
-
-Requires:       %{phpname} >= 5.3.0
-Requires:       %{phpzendname}
-Requires:       %{phpname}-ldap
-Requires:       %{phpname}-pdo
-%if "%{_vendor}" == "redhat"
-Requires:       %{phpname}-common
-Requires:       %{phpzendname}-Db-Adapter-Pdo
-Requires:       %{phpzendname}-Db-Adapter-Pdo-Mysql
-Requires:       php-pear
-%endif
-%if "%{_vendor}" == "suse"
-Requires:       %{phpname}-pear
-Requires:       %{phpname}-dom
-Requires:       %{phpname}-tokenizer
-Requires:       %{phpname}-gettext
-Requires:       %{phpname}-ctype
-Requires:       %{phpname}-json
-Requires:       %{apache2modphpname}
-%endif
-
-Requires:       php-Icinga
+Requires(pre):  shadow-utils
+Requires:       %{name}-common = %{version}-%{release}
+Requires:       php-Icinga = %{version}-%{release}
+Requires:       %{name}-vendor-dompdf
+Requires:       %{name}-vendor-HTMLPurifier
+Requires:       %{name}-vendor-JShrink
+Requires:       %{name}-vendor-lessphp
+Requires:       %{name}-vendor-Parsedown
+Requires:       %{zend}
 
 
 %description
-Icinga Web 2 for Icinga 2 or Icinga 1.x using multiple backends
-for example DB IDO.
+Icinga Web 2
 
-%package -n icingacli
-Summary:        Icinga CLI
-Group:          Applications/System
-Requires:       %{name} = %{version}-%{release}
-Requires:       php-Icinga
 
-%description -n icingacli
-Icinga CLI using php-Icinga Icinga Web 2 backend.
+%define basedir         %{_datadir}/%{name}
+%define bindir          %{_bindir}
+%define configdir       %{_sysconfdir}/%{name}
+%define logdir          %{_localstatedir}/log/%{name}
+%define phpdir          %{_datadir}/php
+%define icingawebgroup  icingaweb2
+%define docsdir         %{_datadir}/doc/%{name}
+
+
+%package common
+Summary:    Common files for Icinga Web 2 and the Icinga CLI
+Group:      Applications/System
+
+%description common
+Common files for Icinga Web 2 and the Icinga CLI
+
 
 %package -n php-Icinga
-Summary:        Icinga Web 2 PHP Libraries
-Group:          Applications/System
-Requires:       %{name} = %{version}-%{release}
-Requires:       %{phpname} >= 5.3.0
-Requires:       %{phpzendname}
-
+Summary:                    Icinga Web 2 PHP library
+Group:                      Development/Libraries
+Requires:                   %{php} >= 5.3.0
+Requires:                   %{php}-gd %{php}-intl
+%{?fedora:Requires:         php-pecl-imagick}
+%{?rhel:Requires:           php-pecl-imagick}
+%{?suse_version:Requires:   %{php}-gettext %{php}-openssl php5-imagick}
 
 %description -n php-Icinga
-Icinga Web 2 PHP Libraries required by the web frontend and cli tool.
+Icinga Web 2 PHP library
+
+
+%package -n icingacli
+Summary:                    Icinga CLI
+Group:                      Applications/System
+Requires:                   %{name}-common = %{version}-%{release}
+Requires:                   php-Icinga = %{version}-%{release}
+%{?fedora:Requires:         %{php_cli} >= 5.3.0 bash-completion}
+%{?rhel:Requires:           %{php_cli} >= 5.3.0 bash-completion}
+%{?suse_version:Requires:   %{php} >= 5.3.0}
+
+%description -n icingacli
+Icinga CLI
+
+
+%package vendor-dompdf
+Version:    0.6.1
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library dompdf
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-dompdf
+Icinga Web 2 vendor library dompdf
+
+
+%package vendor-HTMLPurifier
+Version:    4.6.0
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library HTMLPurifier
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-HTMLPurifier
+Icinga Web 2 vendor library HTMLPurifier
+
+
+%package vendor-JShrink
+Version:    1.0.1
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library JShrink
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-JShrink
+Icinga Web 2 vendor library JShrink
+
+
+%package vendor-lessphp
+Version:    0.4.0
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library lessphp
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-lessphp
+Icinga Web 2 vendor library lessphp
+
+
+%package vendor-Parsedown
+Version:    1.0.0
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library Parsedown
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-Parsedown
+Icinga Web 2 vendor library Parsedown
+
+
+%package vendor-Zend
+Version:    1.12.9
+Release:    1%{?dist}
+Summary:    Icinga Web 2 vendor library Zend Framework
+Group:      Development/Libraries
+Requires:   %{php} >= 5.3.0
+
+%description vendor-Zend
+Icinga Web 2 vendor library Zend
 
 
 %prep
-#VERSION=0.0.1; git archive --format=tar --prefix=icingaweb2-$VERSION/ HEAD | gzip >icingaweb2-$VERSION.tar.gz
-%setup -q -n %{name}-%{version}
+%setup -q
 
 %build
 
 %install
-[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot}
-
-# prepare configuration for sub packages
-
-# install rhel apache config
-install -D -m0644 packages/files/apache/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf
-
-# install public, library, modules
-%{__mkdir} -p %{buildroot}/%{sharedir}
-%{__mkdir} -p %{buildroot}/%{logdir}
-%{__mkdir} -p %{buildroot}/%{docdir}
-%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}
-%{__mkdir} -p %{buildroot}/%{_sysconfdir}/dashboard
-%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules
-%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules/monitoring
-%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/enabledModules
-
-# make sure to install local icingacli for setup wizard token generation & webserver config
-%{__cp} -r application doc library modules public bin %{buildroot}/%{sharedir}/
-
-# enable the monitoring module by default
-ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/%{name}/enabledModules/monitoring
-## config
-
-# symlink icingacli
-mkdir -p %{buildroot}/usr/bin
-ln -sf %{sharedir}/bin/icingacli %{buildroot}/usr/bin/icingacli
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir}/modules/setup,%{logdir},%{phpdir},%{wwwconfigdir},%{_sysconfdir}/bash_completion.d,%{docsdir}}
+cp -prv application doc %{buildroot}/%{basedir}
+cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli
+cp -prv modules/{monitoring,setup} %{buildroot}/%{basedir}/modules
+cp -prv library/Icinga %{buildroot}/%{phpdir}
+cp -prv library/vendor %{buildroot}/%{basedir}/library
+cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public
+cp -pv packages/files/apache/icingaweb2.conf %{buildroot}/%{wwwconfigdir}/icingaweb2.conf
+cp -pv packages/files/bin/icingacli %{buildroot}/%{bindir}
+cp -pv packages/files/public/index.php %{buildroot}/%{basedir}/public
+cp -prv etc/schema %{buildroot}/%{docsdir}
+cp -prv packages/files/config/modules/setup %{buildroot}/%{configdir}/modules/
 
 %pre
-# Add apacheuser in the icingacmd group
-# If the group exists, add the apacheuser in the icingacmd group.
-# It is not neccessary that icinga2-web is installed on the same system as
-# icinga and only on systems with icinga installed the icingacmd
-# group exists. In all other cases the user used for ssh access has
-# to be added to the icingacmd group on the remote icinga server.
-getent group icingacmd > /dev/null
-
-if [ $? -eq 0 ]; then
-%{_sbindir}/usermod %{usermodparam} icingacmd %{apacheuser}
-fi
-
-%preun
-
-%post
+getent group icingacmd >/dev/null || groupadd -r icingacmd
+%if 0%{?suse_version}
+usermod -G icingacmd,%{icingawebgroup} %{wwwuser}
+%else
+usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser}
+%endif
+exit 0
 
 %clean
-[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot}
+rm -rf %{buildroot}
 
 %files
-# main dirs
 %defattr(-,root,root)
-%doc etc/schema doc packages/RPM.md
-%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public
-%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules
-# configs
+%{basedir}/application/controllers
+%{basedir}/application/fonts
+%{basedir}/application/forms
+%{basedir}/application/layouts
+%{basedir}/application/views
+%{basedir}/doc
+%{basedir}/modules
+%{basedir}/public
+%{wwwconfigdir}/icingaweb2.conf
+%attr(2775,root,%{icingawebgroup}) %dir %{logdir}
+%{docsdir}
+%docdir %{docsdir}
+%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules/setup
+%attr(0660,root,%{icingawebgroup}) %config(noreplace) %{configdir}/modules/setup/config.ini
+
+
+%pre common
+getent group %{icingawebgroup} >/dev/null || groupadd -r %{icingawebgroup}
+exit 0
+
+%files common
 %defattr(-,root,root)
-%config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf
-%config(noreplace) %attr(-,%{apacheuser},%{apachegroup}) %{configdir}
-# logs
-%attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir}
-# shipped docs
-%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/doc
+%{basedir}/application/locale
+%dir %{basedir}/modules
+%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}
+%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules
+
 
 %files -n php-Icinga
-%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application
-%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library
+%defattr(-,root,root)
+%{phpdir}/Icinga
+
 
 %files -n icingacli
-%attr(0755,root,root) /usr/bin/icingacli
-%attr(0755,root,root) %{sharedir}/bin/icingacli
-%attr(0755,root,root) %{sharedir}/bin/license_writer.py
+%defattr(-,root,root)
+%{basedir}/application/clicommands
+%{_sysconfdir}/bash_completion.d/icingacli
+%attr(0755,root,root) %{bindir}/icingacli
 
-%changelog
+
+%files vendor-dompdf
+%defattr(-,root,root)
+%{basedir}/library/vendor/dompdf
+
+
+%files vendor-HTMLPurifier
+%defattr(-,root,root)
+%{basedir}/library/vendor/HTMLPurifier
+
+
+%files vendor-JShrink
+%defattr(-,root,root)
+%{basedir}/library/vendor/JShrink
+
+
+%files vendor-lessphp
+%defattr(-,root,root)
+%{basedir}/library/vendor/lessphp
+
+
+%files vendor-Parsedown
+%defattr(-,root,root)
+%{basedir}/library/vendor/Parsedown
+
+
+%files vendor-Zend
+%defattr(-,root,root)
+%{basedir}/library/vendor/Zend
diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php
index 6de3081ba..89bca7b97 100644
--- a/library/Icinga/Application/ApplicationBootstrap.php
+++ b/library/Icinga/Application/ApplicationBootstrap.php
@@ -113,6 +113,13 @@ abstract class ApplicationBootstrap
      */
     protected $isWeb = false;
 
+    /**
+     * Whether Icinga Web 2 requires setup
+     *
+     * @type bool
+     */
+    protected $requiresSetup = false;
+
     /**
      * Constructor
      *
@@ -133,7 +140,7 @@ abstract class ApplicationBootstrap
             if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
                 $configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
             } else {
-                $configDir = '/etc/icingaweb';
+                $configDir = '/etc/icingaweb2';
             }
         }
         $canonical = realpath($configDir);
@@ -333,7 +340,7 @@ abstract class ApplicationBootstrap
     /**
      * Setup Icinga auto loader
      *
-     * @return self
+     * @return $this
      */
     public function setupAutoloader()
     {
@@ -366,7 +373,7 @@ abstract class ApplicationBootstrap
     /**
      * Setup module manager
      *
-     * @return self
+     * @return $this
      */
     protected function setupModuleManager()
     {
@@ -378,25 +385,10 @@ abstract class ApplicationBootstrap
         return $this;
     }
 
-    /**
-     * Load all core modules
-     *
-     * @return self
-     */
-    protected function loadCoreModules()
-    {
-        try {
-            $this->moduleManager->loadCoreModules();
-        } catch (NotReadableError $e) {
-            Logger::error(new IcingaException('Cannot load core modules. An exception was thrown:', $e));
-        }
-        return $this;
-    }
-
     /**
      * Load all enabled modules
      *
-     * @return self
+     * @return $this
      */
     protected function loadEnabledModules()
     {
@@ -408,10 +400,47 @@ abstract class ApplicationBootstrap
         return $this;
     }
 
+    /**
+     * Load the setup module if Icinga Web 2 requires setup or the setup token exists
+     *
+     * @return $this
+     */
+    protected function loadSetupModuleIfNecessary()
+    {
+        if (! @file_exists($this->config->resolvePath('authentication.ini'))) {
+            $this->requiresSetup = true;
+            $this->moduleManager->loadModule('setup');
+        } elseif ($this->setupTokenExists()) {
+            // Load setup module but do not require setup
+            $this->moduleManager->loadModule('setup');
+        }
+        return $this;
+    }
+
+    /**
+     * Get whether Icinga Web 2 requires setup
+     *
+     * @return bool
+     */
+    public function requiresSetup()
+    {
+        return $this->requiresSetup;
+    }
+
+    /**
+     * Get whether the setup token exists
+     *
+     * @return bool
+     */
+    public function setupTokenExists()
+    {
+        return @file_exists($this->config->resolvePath('setup.token'));
+    }
+
     /**
      * Setup default logging
      *
-     * @return  self
+     * @return $this
      */
     protected function setupLogging()
     {
@@ -428,7 +457,7 @@ abstract class ApplicationBootstrap
     /**
      * Load Configuration
      *
-     * @return self
+     * @return $this
      */
     protected function loadConfig()
     {
@@ -447,7 +476,7 @@ abstract class ApplicationBootstrap
     /**
      * Error handling configuration
      *
-     * @return self
+     * @return $this
      */
     protected function setupErrorHandling()
     {
@@ -473,7 +502,7 @@ abstract class ApplicationBootstrap
     /**
      * Set up logger
      *
-     * @return self
+     * @return $this
      */
     protected function setupLogger()
     {
@@ -490,7 +519,7 @@ abstract class ApplicationBootstrap
     /**
      * Set up the resource factory
      *
-     * @return self
+     * @return $this
      */
     protected function setupResourceFactory()
     {
diff --git a/library/Icinga/Application/Cli.php b/library/Icinga/Application/Cli.php
index abf46262f..6341d561e 100644
--- a/library/Icinga/Application/Cli.php
+++ b/library/Icinga/Application/Cli.php
@@ -44,7 +44,7 @@ class Cli extends ApplicationBootstrap
             ->setupLogger()
             ->setupResourceFactory()
             ->setupModuleManager()
-            ->loadCoreModules();
+            ->loadSetupModuleIfNecessary();
     }
 
     protected function setupLogging()
diff --git a/library/Icinga/Application/Config.php b/library/Icinga/Application/Config.php
index dcb837fde..361f5f11d 100644
--- a/library/Icinga/Application/Config.php
+++ b/library/Icinga/Application/Config.php
@@ -279,7 +279,7 @@ class Config implements Countable, Iterator
      *
      * @param   string      $file   The file to parse
      *
-     * @throws  NotReadableError    When the file does not exist or cannot be read
+     * @throws  NotReadableError    When the file cannot be read
      */
     public static function fromIni($file)
     {
@@ -292,7 +292,7 @@ class Config implements Countable, Iterator
             $config = new static(new ConfigObject(parse_ini_file($filepath, true)));
             $config->setConfigFile($filepath);
             return $config;
-        } else {
+        } elseif (@file_exists($filepath)) {
             throw new NotReadableError(t('Cannot read config file "%s". Permission denied'), $filepath);
         }
 
@@ -322,7 +322,7 @@ class Config implements Countable, Iterator
      */
     public static function app($configname = 'config', $fromDisk = false)
     {
-        if (!isset(self::$app[$configname]) || $fromDisk) {
+        if (! isset(self::$app[$configname]) || $fromDisk) {
             self::$app[$configname] = static::fromIni(static::resolvePath($configname . '.ini'));
         }
 
@@ -341,12 +341,12 @@ class Config implements Countable, Iterator
      */
     public static function module($modulename, $configname = 'config', $fromDisk = false)
     {
-        if (!isset(self::$modules[$modulename])) {
+        if (! isset(self::$modules[$modulename])) {
             self::$modules[$modulename] = array();
         }
 
         $moduleConfigs = self::$modules[$modulename];
-        if (!isset($moduleConfigs[$configname]) || $fromDisk) {
+        if (! isset($moduleConfigs[$configname]) || $fromDisk) {
             $moduleConfigs[$configname] = static::fromIni(
                 static::resolvePath('modules/' . $modulename . '/' . $configname . '.ini')
             );
diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php
index 23cb365f0..b9ed067a2 100644
--- a/library/Icinga/Application/EmbeddedWeb.php
+++ b/library/Icinga/Application/EmbeddedWeb.php
@@ -6,10 +6,8 @@ namespace Icinga\Application;
 
 require_once dirname(__FILE__) . '/ApplicationBootstrap.php';
 
-use Icinga\Exception\ProgrammingError;
-
 /**
- * Use this if you want to make use of Icinga funtionality in other web projects
+ * Use this if you want to make use of Icinga functionality in other web projects
  *
  * Usage example:
  * <code>
diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php
index 6469d3929..7ee2461f9 100644
--- a/library/Icinga/Application/Modules/Manager.php
+++ b/library/Icinga/Application/Modules/Manager.php
@@ -68,18 +68,6 @@ class Manager
      */
     private $modulePaths        = array();
 
-    /**
-     * The core modules
-     *
-     * Core modules do not need to be enabled to load and cannot be disabled
-     * by the user. This must not be writable programmatically!
-     *
-     * @var array
-     */
-    private $coreModules = array(
-        'setup'
-    );
-
     /**
      *  Create a new instance of the module manager
      *
@@ -170,21 +158,7 @@ class Manager
     }
 
     /**
-     * Try to set all core modules in loaded state
-     *
-     * @return  self
-     * @see     Manager::loadModule()
-     */
-    public function loadCoreModules()
-    {
-        foreach ($this->coreModules as $name) {
-            $this->loadModule($name);
-        }
-        return $this;
-    }
-
-    /**
-     * Try to set all enabled modules in loaded state
+     * Try to set all enabled modules in loaded sate
      *
      * @return  self
      * @see     Manager::loadModule()
@@ -239,8 +213,6 @@ class Manager
                 'Cannot enable module "%s". Module is not installed.',
                 $name
             );
-        } elseif (in_array($name, $this->coreModules)) {
-            return $this;
         }
 
         clearstatcache(true);
@@ -458,7 +430,7 @@ class Manager
         }
 
         $installed = $this->listInstalledModules();
-        foreach (array_diff($installed, $this->coreModules) as $name) {
+        foreach ($installed as $name) {
             $info[$name] = (object) array(
                 'name'    => $name,
                 'path'    => $this->installedBaseDirs[$name],
diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php
index 99722f2b6..96bbae7be 100644
--- a/library/Icinga/Application/Modules/Module.php
+++ b/library/Icinga/Application/Modules/Module.php
@@ -759,15 +759,15 @@ class Module
     protected function registerAutoloader()
     {
         $moduleName = ucfirst($this->getName());
+
         $moduleLibraryDir = $this->getLibDir(). '/'. $moduleName;
-        if (is_dir($this->getBaseDir()) && is_dir($this->getLibDir()) && is_dir($moduleLibraryDir)) {
+        if (is_dir($moduleLibraryDir)) {
             $this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir);
-            if (is_dir($this->getFormDir())) {
-                $this->app->getLoader()->registerNamespace(
-                    'Icinga\\Module\\' . $moduleName. '\\Forms',
-                    $this->getFormDir()
-                );
-            }
+        }
+
+        $moduleFormDir = $this->getFormDir();
+        if (is_dir($moduleFormDir)) {
+            $this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName. '\\Forms',  $moduleFormDir);
         }
 
         return $this;
diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php
index 37ec5138a..5b18f1be8 100644
--- a/library/Icinga/Application/Web.php
+++ b/library/Icinga/Application/Web.php
@@ -104,7 +104,7 @@ class Web extends ApplicationBootstrap
             ->setupZendMvc()
             ->setupFormNamespace()
             ->setupModuleManager()
-            ->loadCoreModules()
+            ->loadSetupModuleIfNecessary()
             ->loadEnabledModules()
             ->setupRoute()
             ->setupPagination();
diff --git a/library/Icinga/Authentication/Backend/DbUserBackend.php b/library/Icinga/Authentication/Backend/DbUserBackend.php
index d2d0147e5..7865aa905 100644
--- a/library/Icinga/Authentication/Backend/DbUserBackend.php
+++ b/library/Icinga/Authentication/Backend/DbUserBackend.php
@@ -87,9 +87,16 @@ class DbUserBackend extends UserBackend
      */
     protected function getPasswordHash($username)
     {
-        $stmt = $this->conn->getDbAdapter()->prepare(
-            'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1'
-        );
+        if ($this->conn->getDbType() === 'pgsql') {
+            // Since PostgreSQL version 9.0 the default value for bytea_output is 'hex' instead of 'escape'
+            $stmt = $this->conn->getDbAdapter()->prepare(
+                'SELECT ENCODE(password_hash, \'escape\') FROM icingaweb_user WHERE name = :name AND active = 1'
+            );
+        } else {
+            $stmt = $this->conn->getDbAdapter()->prepare(
+                'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1'
+            );
+        }
         $stmt->execute(array(':name' => $username));
         $stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
         $stmt->fetch(PDO::FETCH_BOUND);
diff --git a/library/Icinga/Authentication/Backend/AutoLoginBackend.php b/library/Icinga/Authentication/Backend/ExternalBackend.php
similarity index 91%
rename from library/Icinga/Authentication/Backend/AutoLoginBackend.php
rename to library/Icinga/Authentication/Backend/ExternalBackend.php
index b4a70bd4f..d5eb491e5 100644
--- a/library/Icinga/Authentication/Backend/AutoLoginBackend.php
+++ b/library/Icinga/Authentication/Backend/ExternalBackend.php
@@ -11,7 +11,7 @@ use Icinga\User;
 /**
  * Test login with external authentication mechanism, e.g. Apache
  */
-class AutoLoginBackend extends UserBackend
+class ExternalBackend extends UserBackend
 {
     /**
      * Regexp expression to strip values from a username
@@ -21,7 +21,7 @@ class AutoLoginBackend extends UserBackend
     private $stripUsernameRegexp;
 
     /**
-     * Create new autologin backend
+     * Create new authentication backend of type "external"
      *
      * @param ConfigObject $config
      */
@@ -33,7 +33,7 @@ class AutoLoginBackend extends UserBackend
     /**
      * Count the available users
      *
-     * Autologin backends will always return 1
+     * Authenticaton backends of type "external" will always return 1
      *
      * @return int
      */
diff --git a/library/Icinga/Authentication/Backend/LdapUserBackend.php b/library/Icinga/Authentication/Backend/LdapUserBackend.php
index a9ffba0c5..69fe795fc 100644
--- a/library/Icinga/Authentication/Backend/LdapUserBackend.php
+++ b/library/Icinga/Authentication/Backend/LdapUserBackend.php
@@ -213,7 +213,7 @@ class LdapUserBackend extends UserBackend
      */
     public function count()
     {
-        return $this->conn->count($this->selectUsers());
+        return $this->selectUsers()->count();
     }
 
     /**
diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php
index 0a9b40981..8aee93c0e 100644
--- a/library/Icinga/Authentication/Manager.php
+++ b/library/Icinga/Authentication/Manager.php
@@ -63,7 +63,7 @@ class Manager
             );
             $config = new Config();
         }
-        if ($config->hasSection('preferences')) {
+        if ($config->get('preferences', 'store', 'ini') !== 'none') {
             $preferencesConfig = $config->getSection('preferences');
             try {
                 $preferencesStore = PreferencesStore::create(
@@ -165,6 +165,7 @@ class Manager
      */
     public function hasPermission($permission)
     {
+        return true;
         if (! $this->isAuthenticated()) {
             return false;
         }
diff --git a/library/Icinga/Authentication/UserBackend.php b/library/Icinga/Authentication/UserBackend.php
index eaf39e49d..7215f4d41 100644
--- a/library/Icinga/Authentication/UserBackend.php
+++ b/library/Icinga/Authentication/UserBackend.php
@@ -5,7 +5,7 @@
 namespace Icinga\Authentication;
 
 use Countable;
-use Icinga\Authentication\Backend\AutoLoginBackend;
+use Icinga\Authentication\Backend\ExternalBackend;
 use Icinga\Authentication\Backend\DbUserBackend;
 use Icinga\Authentication\Backend\LdapUserBackend;
 use Icinga\Data\ConfigObject;
@@ -69,8 +69,8 @@ abstract class UserBackend implements Countable
             );
         }
         $backendType = strtolower($backendType);
-        if ($backendType === 'autologin') {
-            $backend = new AutoLoginBackend($backendConfig);
+        if ($backendType === 'external') {
+            $backend = new ExternalBackend($backendConfig);
             $backend->setName($name);
             return $backend;
         }
diff --git a/library/Icinga/Chart/Axis.php b/library/Icinga/Chart/Axis.php
index 00a5f5679..c12d9a904 100644
--- a/library/Icinga/Chart/Axis.php
+++ b/library/Icinga/Chart/Axis.php
@@ -78,24 +78,23 @@ class Axis implements Drawable
     private $yUnit = null;
 
     /**
-     * If the displayed labels should be aligned horizontally or diagonally
+     * The minimum amount of units each step must take up
+     *
+     * @var int
      */
-    private $labelRotationStyle = self::LABEL_ROTATE_DIAGONAL;
+    public $minUnitsPerStep = 80;
 
     /**
-     * Set the label rotation style for the horizontal axis
+     * The minimum amount of units each tick must take up
      *
-     * <ul>
-     *   <li><b>LABEL_ROTATE_HORIZONTAL</b>: Labels will be displayed horizontally </li>
-     *   <li><b>LABEL_ROTATE_DIAGONAL</b>: Labels will be rotated by 45° </li>
-     * </ul>
-     *
-     * @param $style    The rotation mode
+     * @var int
      */
-    public function setHorizontalLabelRotationStyle($style)
-    {
-        $this->labelRotationStyle = $style;
-    }
+    public $minUnitsPerTick = 15;
+
+    /**
+     * If the displayed labels should be aligned horizontally or diagonally
+     */
+    protected $labelRotationStyle = self::LABEL_ROTATE_HORIZONTAL;
 
     /**
      * Inform the axis about an added dataset
@@ -160,58 +159,74 @@ class Axis implements Drawable
      */
     private function renderHorizontalAxis(RenderContext $ctx, DOMElement $group)
     {
+        $steps = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerStep);
+        $ticks = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerTick);
+
+        // Steps should always be ticks
+        if ($ticks !== $steps) {
+            $steps = $ticks * 5;
+        }
+
+        // Check whether there is enough room for regular labels
+        $labelRotationStyle = $this->labelRotationStyle;
+        if ($this->labelsOversized($this->xUnit, 6)) {
+            $labelRotationStyle = self::LABEL_ROTATE_DIAGONAL;
+        }
+
+        /*
         $line = new Line(0, 100, 100, 100);
         $line->setStrokeWidth(2);
         $group->appendChild($line->toSvg($ctx));
+        */
 
         // contains the approximate end position of the last label
         $lastLabelEnd = -1;
         $shift = 0;
 
+        $i = 0;
         foreach ($this->xUnit as $label => $pos) {
-            if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
-                // If the  last label would overlap this label we shift the y axis a bit
-                if ($lastLabelEnd > $pos) {
-                    $shift = ($shift + 5) % 10;
-                } else {
-                    $shift = 0;
+
+            if ($i % $ticks === 0) {
+                /*
+                $tick = new Line($pos, 100, $pos, 101);
+                $group->appendChild($tick->toSvg($ctx));
+                */
+            }
+
+            if ($i % $steps === 0) {
+                if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
+                    // If the  last label would overlap this label we shift the y axis a bit
+                    if ($lastLabelEnd > $pos) {
+                        $shift = ($shift + 5) % 10;
+                    } else {
+                        $shift = 0;
+                    }
                 }
+
+                $labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label);
+                if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
+                    $labelField->setAlignment(Text::ALIGN_MIDDLE)
+                        ->setFontSize('2.5em');
+                } else {
+                    $labelField->setFontSize('2.5em');
+                }
+
+                if ($labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) {
+                    $labelField = new Rotator($labelField, 45);
+                }
+                $labelField = $labelField->toSvg($ctx);
+
+                $group->appendChild($labelField);
+
+                if ($this->drawYGrid) {
+                    $bgLine = new Line($pos, 0, $pos, 100);
+                    $bgLine->setStrokeWidth(0.5)
+                        ->setStrokeColor('#BFBFBF');
+                    $group->appendChild($bgLine->toSvg($ctx));
+                }
+                $lastLabelEnd = $pos + strlen($label) * 1.2;
             }
-
-            $tick = new Line($pos, 100, $pos, 102);
-            $group->appendChild($tick->toSvg($ctx));
-
-            $labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label);
-            if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) {
-                $labelField->setAlignment(Text::ALIGN_MIDDLE)
-                    ->setFontSize('1.8em');
-            } else {
-                $labelField->setFontSize('2.5em');
-            }
-
-            if ($this->labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) {
-                $labelField = new Rotator($labelField, 45);
-            }
-            $labelField = $labelField->toSvg($ctx);
-
-            $group->appendChild($labelField);
-
-            if ($this->drawYGrid) {
-                $bgLine = new Line($pos, 0, $pos, 100);
-                $bgLine->setStrokeWidth(0.5)
-                    ->setStrokeColor('#232');
-                $group->appendChild($bgLine->toSvg($ctx));
-            }
-            $lastLabelEnd = $pos + strlen($label) * 1.2;
-        }
-
-        // render the label for this axis
-        if ($this->xLabel) {
-            $axisLabel = new Text(50, 104, $this->xLabel);
-            $axisLabel->setFontSize('2em')
-                ->setFontWeight('bold')
-                ->setAlignment(Text::ALIGN_MIDDLE);
-            $group->appendChild($axisLabel->toSvg($ctx));
+            $i++;
         }
     }
 
@@ -223,34 +238,59 @@ class Axis implements Drawable
      */
     private function renderVerticalAxis(RenderContext $ctx, DOMElement $group)
     {
+        $steps = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerStep);
+        $ticks = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerTick);
+
+        // Steps should always be ticks
+        if ($ticks !== $steps) {
+            $steps = $ticks * 5;
+        }
+        /*
         $line = new Line(0, 0, 0, 100);
         $line->setStrokeWidth(2);
         $group->appendChild($line->toSvg($ctx));
+        */
 
+        $i = 0;
         foreach ($this->yUnit as $label => $pos) {
             $pos = 100 - $pos;
-            $tick = new Line(0, $pos, -1, $pos);
-            $group->appendChild($tick->toSvg($ctx));
 
-            $labelField = new Text(-0.5, $pos+0.5, $label);
-            $labelField->setFontSize('1.8em')
-                ->setAlignment(Text::ALIGN_END);
-
-            $group->appendChild($labelField->toSvg($ctx));
-            if ($this->drawXGrid) {
-                $bgLine = new Line(0, $pos, 100, $pos);
-                $bgLine->setStrokeWidth(0.5)
-                    ->setStrokeColor('#343');
-                $group->appendChild($bgLine->toSvg($ctx));
+            if ($i % $ticks === 0) {
+                // draw a tick
+                //$tick = new Line(0, $pos, -1, $pos);
+                //$group->appendChild($tick->toSvg($ctx));
             }
+
+            if ($i % $steps === 0) {
+                // draw a step
+                $labelField = new Text(-0.5, $pos + 0.5, $label);
+                $labelField->setFontSize('2.5em')
+                    ->setAlignment(Text::ALIGN_END);
+
+                $group->appendChild($labelField->toSvg($ctx));
+                if ($this->drawXGrid) {
+                    $bgLine = new Line(0, $pos, 100, $pos);
+                    $bgLine->setStrokeWidth(0.5)
+                        ->setStrokeColor('#BFBFBF');
+                    $group->appendChild($bgLine->toSvg($ctx));
+                }
+            }
+            $i++;
         }
 
-        if ($this->yLabel) {
-            $axisLabel = new Text(-8, 50, $this->yLabel);
+        if ($this->yLabel || $this->xLabel) {
+            if ($this->yLabel && $this->xLabel) {
+                $txt = $this->yLabel . ' / ' . $this->xLabel;
+            } else if ($this->xLabel) {
+                $txt = $this->xLabel;
+            } else {
+                $txt = $this->yLabel;
+            }
+
+            $axisLabel = new Text(50, -3, $txt);
             $axisLabel->setFontSize('2em')
                 ->setFontWeight('bold')
                 ->setAlignment(Text::ALIGN_MIDDLE);
-            $axisLabel = new Rotator($axisLabel, 90);
 
             $group->appendChild($axisLabel->toSvg($ctx));
         }
@@ -416,4 +456,32 @@ class Axis implements Drawable
         $this->renderVerticalAxis($ctx, $group);
         return $group;
     }
+
+    protected function ticksPerX($ticks, $units, $min)
+    {
+        $per = 1;
+        while ($per * $units / $ticks < $min) {
+            $per++;
+        }
+        return $per;
+    }
+
+    /**
+     * Returns whether at least one label of the given Axis
+     * is bigger than the given maxLength
+     *
+     * @param   AxisUnit    $axis   The axis that contains the labels that will be checked
+     *
+     * @return  boolean             Whether at least one label is bigger than maxLength
+     */
+    private function labelsOversized(AxisUnit $axis, $maxLength = 5)
+    {
+        $oversized = false;
+        foreach ($axis as $label => $pos) {
+            if (strlen($label) > $maxLength) {
+                $oversized = true;
+            }
+        }
+        return $oversized;
+    }
 }
diff --git a/library/Icinga/Chart/Graph/BarGraph.php b/library/Icinga/Chart/Graph/BarGraph.php
index 1225307ad..febad8d09 100644
--- a/library/Icinga/Chart/Graph/BarGraph.php
+++ b/library/Icinga/Chart/Graph/BarGraph.php
@@ -28,7 +28,7 @@ class BarGraph extends Styleable implements Drawable
      *
      * @var int
      */
-    private $barWidth = 4;
+    private $barWidth = 3;
 
     /**
      * The dataset to use for this bar graph
@@ -122,6 +122,14 @@ class BarGraph extends Styleable implements Drawable
         $doc = $ctx->getDocument();
         $group = $doc->createElement('g');
         $idx = 0;
+
+        if (count($this->dataSet) > 15) {
+            $this->barWidth = 2;
+        }
+        if (count($this->dataSet) > 25) {
+            $this->barWidth = 1;
+        }
+
         foreach ($this->dataSet as $x => $point) {
             // add white background bar, to prevent other bars from altering transparency effects
             $bar = $this->drawSingleBar($point, $idx++, 'white', $this->strokeWidth, $idx)->toSvg($ctx);
diff --git a/library/Icinga/Chart/Graph/LineGraph.php b/library/Icinga/Chart/Graph/LineGraph.php
index d12d4eed9..3644f1492 100644
--- a/library/Icinga/Chart/Graph/LineGraph.php
+++ b/library/Icinga/Chart/Graph/LineGraph.php
@@ -45,6 +45,13 @@ class LineGraph extends Styleable implements Drawable
      */
     public $strokeWidth = 5;
 
+    /**
+     * The size of the displayed dots
+     *
+     * @var int
+     */
+    public $dotWith = 0;
+
     /**
      * Create a new LineGraph displaying the given dataset
      *
@@ -138,8 +145,8 @@ class LineGraph extends Styleable implements Drawable
         $group = $path->toSvg($ctx);
         if ($this->showDataPoints === true) {
             foreach ($this->dataset as $point) {
-                $dot = new Circle($point[0], $point[1], $this->strokeWidth*5);
-                $dot->setFill('black');
+                $dot = new Circle($point[0], $point[1], $this->dotWith);
+                $dot->setFill($this->strokeColor);
 
                 $group->appendChild($dot->toSvg($ctx));
             }
diff --git a/library/Icinga/Chart/Legend.php b/library/Icinga/Chart/Legend.php
index 46ba8081c..df334089f 100644
--- a/library/Icinga/Chart/Legend.php
+++ b/library/Icinga/Chart/Legend.php
@@ -66,13 +66,14 @@ class Legend implements Drawable
         $outer->getLayout()->setPadding(2, 2, 2, 2);
         $nrOfColumns = 4;
 
-        $leftstep = 100 / $nrOfColumns;
         $topstep = 10 / $nrOfColumns + 2;
 
         $top = 0;
         $left = 0;
         $lastLabelEndPos = -1;
         foreach ($this->dataset as $color => $text) {
+            $leftstep = 100 / $nrOfColumns + strlen($text);
+
             // Make sure labels don't overlap each other
             while ($lastLabelEndPos >= $left) {
                 $left += $leftstep;
diff --git a/library/Icinga/Chart/Primitive/Circle.php b/library/Icinga/Chart/Primitive/Circle.php
index 058211bf7..da5f1785e 100644
--- a/library/Icinga/Chart/Primitive/Circle.php
+++ b/library/Icinga/Chart/Primitive/Circle.php
@@ -61,7 +61,7 @@ class Circle extends Styleable implements Drawable
         $circle = $ctx->getDocument()->createElement('circle');
         $circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
         $circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
-        $circle->setAttribute('r', 5);
+        $circle->setAttribute('r', $this->radius);
         $circle->setAttribute('style', $this->getStyle());
         $this->applyAttributes($circle);
         return $circle;
diff --git a/library/Icinga/Chart/Unit/AxisUnit.php b/library/Icinga/Chart/Unit/AxisUnit.php
index dc57f99e0..fba521778 100644
--- a/library/Icinga/Chart/Unit/AxisUnit.php
+++ b/library/Icinga/Chart/Unit/AxisUnit.php
@@ -9,13 +9,14 @@ use Iterator;
 /**
  * Base class for Axis Units
  *
+ * An AxisUnit takes a set of values and places them on a given range
+ *
  * Concrete subclasses must implement the iterator interface, with
  * getCurrent returning the axis relative position and getValue the label
  * that will be displayed
  */
 interface AxisUnit extends Iterator
 {
-
     /**
      * Add a dataset to this AxisUnit, required for dynamic min and max vlaues
      *
@@ -46,4 +47,11 @@ interface AxisUnit extends Iterator
      * @param int $max The new maximum value
      */
     public function setMax($max);
+
+    /**
+     * Get the amount of ticks of this axis
+     *
+     * @return int
+     */
+    public function getTicks();
 }
diff --git a/library/Icinga/Chart/Unit/LinearUnit.php b/library/Icinga/Chart/Unit/LinearUnit.php
index d776fe304..fe80971d4 100644
--- a/library/Icinga/Chart/Unit/LinearUnit.php
+++ b/library/Icinga/Chart/Unit/LinearUnit.php
@@ -9,7 +9,6 @@ namespace Icinga\Chart\Unit;
  */
 class LinearUnit implements AxisUnit
 {
-
     /**
      * The minimum value to display
      *
@@ -43,7 +42,7 @@ class LinearUnit implements AxisUnit
      *
      * @var int
      */
-    private $nrOfTicks = 10;
+    protected $nrOfTicks = 10;
 
     /**
      * The currently displayed tick
@@ -95,45 +94,13 @@ class LinearUnit implements AxisUnit
         if (!$this->staticMin) {
             $this->min = min($this->min, $datapoints[0]);
         }
-        if (!$this->staticMin || !$this->staticMax) {
-            $this->updateMaxValue();
-        }
         $this->currentTick = 0;
         $this->currentValue = $this->min;
-        return $this;
-    }
-
-    /**
-     * Refresh the range depending on the current values of min, max and nrOfTicks
-     */
-    private function updateMaxValue()
-    {
-        $this->max = $this->calculateTickRange($this->max - $this->min, $this->nrOfTicks) *
-             $this->nrOfTicks + $this->min;
-    }
-
-    /**
-     * Determine the minimum tick range that is necessary to display the given value range
-     * correctly
-     *
-     * @param   int range   The range to display
-     * @param   int ticks   The amount of ticks to use
-     *
-     * @return  int         The value for each tick
-     */
-    private function calculateTickRange($range, $ticks)
-    {
-        $factor = 1;
-        $steps = array(1, 2, 5);
-        $step = 0;
-        while ($range / ($factor * $steps[$step]) > $ticks) {
-            $step++;
-            if ($step === count($steps)) {
-                $step = 0;
-                $factor *= 10;
-            }
+        if ($this->max === $this->min) {
+            $this->max = $this->min + 10;
         }
-        return $steps[$step] * $factor;
+        $this->nrOfTicks = $this->max - $this->min;
+        return $this;
     }
 
     /**
@@ -149,7 +116,7 @@ class LinearUnit implements AxisUnit
         } elseif ($value > $this->max) {
             return 100;
         } else {
-            return 100 * ($value - $this->min) / $this->max - $this->min;
+            return 100 * ($value - $this->min) / $this->nrOfTicks;
         }
     }
 
@@ -211,7 +178,6 @@ class LinearUnit implements AxisUnit
         if ($max !== null) {
             $this->max = $max;
             $this->staticMax = true;
-            $this->updateMaxValue();
         }
     }
 
@@ -225,7 +191,6 @@ class LinearUnit implements AxisUnit
         if ($min !== null) {
             $this->min = $min;
             $this->staticMin = true;
-            $this->updateMaxValue();
         }
     }
 
@@ -248,4 +213,14 @@ class LinearUnit implements AxisUnit
     {
         return $this->max;
     }
+
+    /**
+     * Get the amount of ticks necessary to display this AxisUnit
+     *
+     * @return int
+     */
+    public function getTicks()
+    {
+        return $this->nrOfTicks;
+    }
 }
diff --git a/library/Icinga/Chart/Unit/LogarithmicUnit.php b/library/Icinga/Chart/Unit/LogarithmicUnit.php
new file mode 100644
index 000000000..6d07f3d45
--- /dev/null
+++ b/library/Icinga/Chart/Unit/LogarithmicUnit.php
@@ -0,0 +1,264 @@
+<?php
+// {{{ICINGA_LICENSE_HEADER}}}
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Chart\Unit;
+
+/**
+ * Logarithmic tick distribution over the axis
+ *
+ * This class does not use the actual logarithm, but a slightly altered version called the
+ * Log-Modulo transformation. This is necessary, since a regular logarithmic scale is not able to display negative
+ * values and zero-points. See <a href="http://blogs.sas.com/content/iml/2014/07/14/log-transformation-of-pos-neg>
+ * this article </a> for a more detailed description.
+ */
+class LogarithmicUnit implements AxisUnit
+{
+    /**
+     * @var int
+     */
+    protected $base;
+
+    /**
+     * @var
+     */
+    protected $currentTick;
+
+    /**
+     * @var
+     */
+    protected $minExp;
+
+    /**
+     * @var
+     */
+    protected $maxExp;
+
+    /**
+     * True when the minimum value is static and isn't affected by the data set
+     *
+     * @var bool
+     */
+    protected $staticMin = false;
+
+    /**
+     * True when the maximum value is static and isn't affected by the data set
+     *
+     * @var bool
+     */
+    protected $staticMax = false;
+
+    /**
+     * Create and initialize this AxisUnit
+     *
+     * @param int $nrOfTicks The number of ticks to use
+     */
+    public function __construct($base = 10)
+    {;
+        $this->base = $base;
+        $this->minExp = PHP_INT_MAX;
+        $this->maxExp = ~PHP_INT_MAX;
+    }
+
+    /**
+     * Add a dataset and calculate the minimum and maximum value for this AxisUnit
+     *
+     * @param   array $dataset  The dataset to add
+     * @param   int $idx        The idx (0 for x, 1 for y)
+     *
+     * @return  self            Fluent interface
+     */
+    public function addValues(array $dataset, $idx = 0)
+    {
+        $datapoints = array();
+
+        foreach ($dataset['data'] as $points) {
+            $datapoints[] = $points[$idx];
+        }
+        if (empty($datapoints)) {
+            return $this;
+        }
+        sort($datapoints);
+        if (!$this->staticMax) {
+            $this->maxExp = max($this->maxExp, $this->logCeil($datapoints[count($datapoints) - 1]));
+        }
+        if (!$this->staticMin) {
+            $this->minExp = min($this->minExp, $this->logFloor($datapoints[0]));
+        }
+        $this->currentTick = 0;
+
+        return $this;
+    }
+
+    /**
+     * Transform the absolute value to an axis relative value
+     *
+     * @param   int $value  The absolute coordinate from the data set
+     * @return  float|int   The axis relative coordinate (between 0 and 100)
+     */
+    public function transform($value)
+    {
+        if ($value < $this->pow($this->minExp)) {
+            return 0;
+        } elseif ($value > $this->pow($this->maxExp)) {
+            return 100;
+        } else {
+            return 100 * ($this->log($value) - $this->minExp) / $this->getTicks();
+        }
+    }
+
+    /**
+     * Return the position of the current tick
+     *
+     * @return int
+     */
+    public function current()
+    {
+        return $this->currentTick * (100 / $this->getTicks());
+    }
+
+    /**
+     * Calculate the next tick and tick value
+     */
+    public function next()
+    {
+        ++ $this->currentTick;
+    }
+
+    /**
+     * Return the label for the current tick
+     *
+     * @return string The label for the current tick
+     */
+    public function key()
+    {
+        $currentBase = $this->currentTick + $this->minExp;
+        if (abs($currentBase) > 4) {
+            return $this->base . 'E' . $currentBase;
+        }
+        return (string) intval($this->pow($currentBase));
+    }
+
+    /**
+     * True when we're at a valid tick (iterator interface)
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        return $this->currentTick >= 0 && $this->currentTick < $this->getTicks();
+    }
+
+    /**
+     * Reset the current tick and label value
+     */
+    public function rewind()
+    {
+        $this->currentTick = 0;
+    }
+
+    /**
+     * Perform a log-modulo transformation
+     *
+     * @param $value    The value to transform
+     *
+     * @return double   The transformed value
+     */
+    protected function log($value)
+    {
+        $sign = $value > 0 ? 1 : -1;
+        return $sign * log1p($sign * $value) / log($this->base);
+    }
+
+    /**
+     * Calculate the biggest exponent necessary to display the given data point
+     *
+     * @param $value
+     *
+     * @return float
+     */
+    protected function logCeil($value)
+    {
+        return ceil($this->log($value)) + 1;
+    }
+
+    /**
+     * Calculate the smallest exponent necessary to display the given data point
+     *
+     * @param $value
+     *
+     * @return float
+     */
+    protected function logFloor($value)
+    {
+        return floor($this->log($value));
+    }
+
+    /**
+     * Inverse function to the log-modulo transformation
+     *
+     * @param $value
+     *
+     * @return double
+     */
+    protected function pow($value)
+    {
+        if ($value == 0) {
+            return 0;
+        }
+        $sign = $value > 0 ? 1 : -1;
+        return $sign * (pow($this->base, $sign * $value));
+    }
+
+    /**
+     * Set the axis minimum value to a fixed value
+     *
+     * @param int $min The new minimum value
+     */
+    public function setMin($min)
+    {
+        $this->minExp = $this->logFloor($min);
+        $this->staticMin = true;
+    }
+
+    /**
+     * Set the axis maximum value to a fixed value
+     *
+     * @param int $max The new maximum value
+     */
+    public function setMax($max)
+    {
+        $this->maxExp = $this->logCeil($max);
+        $this->staticMax = true;
+    }
+
+    /**
+     * Return the current minimum value of the axis
+     *
+     * @return int The minimum set for this axis
+     */
+    public function getMin()
+    {
+        return $this->pow($this->minExp);
+    }
+
+    /**
+     * Return the current maximum value of the axis
+     *
+     * @return int The maximum set for this axis
+     */
+    public function getMax()
+    {
+        return $this->pow($this->maxExp);
+    }
+
+    /**
+     * Get the amount of ticks necessary to display this AxisUnit
+     *
+     * @return int
+     */
+    public function getTicks()
+    {
+        return $this->maxExp - $this->minExp;
+    }
+}
diff --git a/library/Icinga/Chart/Unit/StaticAxis.php b/library/Icinga/Chart/Unit/StaticAxis.php
index 6458ae599..c7e9c2be5 100644
--- a/library/Icinga/Chart/Unit/StaticAxis.php
+++ b/library/Icinga/Chart/Unit/StaticAxis.php
@@ -118,4 +118,14 @@ class StaticAxis implements AxisUnit
     {
         return reset($this->items);
     }
+
+    /**
+     * Get the amount of ticks of this axis
+     *
+     * @return int
+     */
+    public function getTicks()
+    {
+        return count($this->items);
+    }
 }
diff --git a/library/Icinga/Cli/Command.php b/library/Icinga/Cli/Command.php
index 7546f871f..c410cfc0e 100644
--- a/library/Icinga/Cli/Command.php
+++ b/library/Icinga/Cli/Command.php
@@ -16,6 +16,10 @@ abstract class Command
 {
     protected $app;
     protected $docs;
+
+    /**
+     * @type Params
+     */
     protected $params;
     protected $screen;
     protected $isVerbose;
@@ -124,7 +128,7 @@ abstract class Command
 
     public function fail($msg)
     {
-        throw new IcingaException('%s', $msg);
+        throw new IcingaException($msg);
     }
 
     public function getDefaultActionName()
diff --git a/library/Icinga/Data/Filterable.php b/library/Icinga/Data/Filterable.php
index 73ce5dcb4..25d1fc9f5 100644
--- a/library/Icinga/Data/Filterable.php
+++ b/library/Icinga/Data/Filterable.php
@@ -8,6 +8,11 @@ use Icinga\Data\Filter\Filter;
 
 /**
  * Interface for filtering a result set
+ *
+ * @deprecated(EL): addFilter and applyFilter do the same in all usages.
+ * addFilter could be replaced w/ getFilter()->add(). We must no require classes implementing this interface to
+ * implement redundant methods over and over again. This interface must be moved to the namespace Icinga\Data\Filter.
+ * It lacks documentation.
  */
 interface Filterable
 {
diff --git a/library/Icinga/File/FileExtensionFilterIterator.php b/library/Icinga/File/FileExtensionFilterIterator.php
new file mode 100644
index 000000000..909156749
--- /dev/null
+++ b/library/Icinga/File/FileExtensionFilterIterator.php
@@ -0,0 +1,71 @@
+<?php
+// {{{ICINGA_LICENSE_HEADER}}}
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\File;
+
+use FilterIterator;
+use Iterator;
+
+/**
+ * Iterator over files having a specific file extension
+ *
+ * Usage example:
+ * <code>
+ * <?php
+ *
+ * namespace Icinga\Example;
+ *
+ * use RecursiveDirectoryIterator;
+ * use RecursiveIteratorIterator;
+ * use Icinga\File\FileExtensionFilterIterator;
+ *
+ * $markdownFiles = new FileExtensionFilterIterator(
+ *     new RecursiveIteratorIterator(
+ *         new RecursiveDirectoryIterator(__DIR__),
+ *         RecursiveIteratorIterator::SELF_FIRST
+ *     ),
+ *     'md'
+ * );
+ * </code>
+ */
+class FileExtensionFilterIterator extends FilterIterator
+{
+    /**
+     * The extension to filter for
+     *
+     * @type string
+     */
+    protected $extension;
+
+    /**
+     * Create a new FileExtensionFilterIterator
+     *
+     * @param Iterator  $iterator   Apply filter to this iterator
+     * @param string    $extension  The file extension to filter for. The file extension may not contain the leading dot
+     */
+    public function __construct(Iterator $iterator, $extension)
+    {
+        $this->extension = '.' . ltrim(strtolower((string) $extension), '.');
+        parent::__construct($iterator);
+    }
+
+    /**
+     * Accept files which match the file extension to filter for
+     *
+     * @return bool Whether the current element of the iterator is acceptable
+     *              through this filter
+     */
+    public function accept()
+    {
+        $current = $this->current();
+        /* @var $current \SplFileInfo */
+        if (! $current->isFile()) {
+            return false;
+        }
+        // SplFileInfo::getExtension() is only available since PHP 5 >= 5.3.6
+        $filename = $current->getFilename();
+        $sfx = substr($filename, -strlen($this->extension));
+        return $sfx === false ? false : strtolower($sfx) === $this->extension;
+    }
+}
diff --git a/library/Icinga/File/Ini/IniWriter.php b/library/Icinga/File/Ini/IniWriter.php
index 94a20faa5..21402ab74 100644
--- a/library/Icinga/File/Ini/IniWriter.php
+++ b/library/Icinga/File/Ini/IniWriter.php
@@ -27,7 +27,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
      *
      * @var int
      */
-    public static $fileMode = 0664;
+    public static $fileMode = 0660;
 
     /**
      * Create a new INI writer
@@ -90,11 +90,9 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
 
         if ($setMode) {
             $mode = isset($this->options['filemode']) ? $this->options['filemode'] : static::$fileMode;
-            $old = umask(0); // Make sure that the mode we're going to set doesn't get mangled
             if (is_int($mode) && false === @chmod($filePath, $mode)) {
                 throw new Zend_Config_Exception(sprintf('Failed to set file mode "%o" on file "%s"', $mode, $filePath));
             }
-            umask($old);
         }
     }
 
@@ -234,7 +232,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract
 
     /**
      * Getter for filename
-     * 
+     *
      * @return string
      */
     public function getFilename()
diff --git a/library/Icinga/File/NonEmptyFileIterator.php b/library/Icinga/File/NonEmptyFileIterator.php
new file mode 100644
index 000000000..c5c7fda45
--- /dev/null
+++ b/library/Icinga/File/NonEmptyFileIterator.php
@@ -0,0 +1,49 @@
+<?php
+// {{{ICINGA_LICENSE_HEADER}}}
+// {{{ICINGA_LICENSE_HEADER}}
+
+namespace Icinga\File;
+
+use FilterIterator;
+
+/**
+ * Iterator over non-empty files
+ *
+ * Usage example:
+ * <code>
+ * <?php
+ *
+ * namespace Icinga\Example;
+ *
+ * use RecursiveDirectoryIterator;
+ * use RecursiveIteratorIterator;
+ * use Icinga\File\NonEmptyFilterIterator;
+ *
+ * $nonEmptyFiles = new NonEmptyFileIterator(
+ *     new RecursiveIteratorIterator(
+ *         new RecursiveDirectoryIterator(__DIR__),
+ *         RecursiveIteratorIterator::SELF_FIRST
+ *     )
+ * );
+ * </code>
+ */
+class NonEmptyFileIterator extends FilterIterator
+{
+    /**
+     * Accept non-empty files
+     *
+     * @return bool Whether the current element of the iterator is acceptable
+     *              through this filter
+     */
+    public function accept()
+    {
+        $current = $this->current();
+        /** @type $current \SplFileInfo */
+        if (! $current->isFile()
+            || $current->getSize() === 0
+        ) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/library/Icinga/Protocol/Ldap/Connection.php b/library/Icinga/Protocol/Ldap/Connection.php
index 2f8737c8b..1f58f34da 100644
--- a/library/Icinga/Protocol/Ldap/Connection.php
+++ b/library/Icinga/Protocol/Ldap/Connection.php
@@ -4,6 +4,7 @@
 
 namespace Icinga\Protocol\Ldap;
 
+use Exception;
 use Icinga\Protocol\Ldap\Exception as LdapException;
 use Icinga\Application\Platform;
 use Icinga\Application\Config;
@@ -97,6 +98,9 @@ class Connection
     protected $namingContexts;
     protected $discoverySuccess = false;
 
+    protected $lastResult;
+    protected $pageCookie;
+
     /**
      * Constructor
      *
@@ -238,7 +242,8 @@ class Connection
      */
     public function fetchRow($query, $fields = array())
     {
-        // TODO: This is ugly, make it better!
+        $query = clone $query;
+        $query->limit(1);
         $results = $this->fetchAll($query, $fields);
         return array_shift($results);
     }
@@ -250,44 +255,56 @@ class Connection
      */
     public function count(Query $query)
     {
-        $results = $this->runQuery($query, '+');
-        if (! $results) {
-            return 0;
+        $this->connect();
+        $this->bind();
+
+        $count = 0;
+        $results = $this->runQuery($query);
+        while (! empty($results)) {
+            $count += ldap_count_entries($this->ds, $results);
+            $results = $this->runQuery($query);
         }
-        return ldap_count_entries($this->ds, $results);
+
+        return $count;
     }
 
-    public function fetchAll($query, $fields = array())
+    public function fetchAll(Query $query, $fields = array())
     {
-        $offset = null;
-        $limit = null;
+        $this->connect();
+        $this->bind();
+
+        $offset = $limit = null;
         if ($query->hasLimit()) {
             $offset = $query->getOffset();
-            $limit  = $query->getLimit();
+            $limit = $query->getLimit();
         }
+
+        $count = 0;
         $entries = array();
         $results = $this->runQuery($query, $fields);
-        if (! $results) {
-            return array();
-        }
-        $entry = ldap_first_entry($this->ds, $results);
-        $count = 0;
-        while ($entry) {
-            if (($offset === null || $offset <= $count)
-                && ($limit === null || ($offset + $limit) >= $count)
-            ) {
-                $attrs = ldap_get_attributes($this->ds, $entry);
-                $entries[ldap_get_dn($this->ds, $entry)]
-                    = $this->cleanupAttributes($attrs);
+        while (! empty($results)) {
+            $entry = ldap_first_entry($this->ds, $results);
+            while ($entry) {
+                $count++;
+                if (
+                    ($offset === null || $offset <= $count)
+                    && ($limit === null || $limit > count($entries))
+                ) {
+                    $entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes(
+                        ldap_get_attributes($this->ds, $entry)
+                    );
+                }
+
+                $entry = ldap_next_entry($this->ds, $entry);
             }
-            $count++;
-            $entry = ldap_next_entry($this->ds, $entry);
+
+            $results = $this->runQuery($query, $fields);
         }
-        ldap_free_result($results);
+
         return $entries;
     }
 
-    public function cleanupAttributes(& $attrs)
+    protected function cleanupAttributes($attrs)
     {
         $clean = (object) array();
         for ($i = 0; $i < $attrs['count']; $i++) {
@@ -303,26 +320,55 @@ class Connection
         return $clean;
     }
 
-    protected function runQuery($query, $fields)
+    protected function runQuery(Query $query, $fields = array())
     {
-        $this->connect();
-        $this->bind();
-        if ($query instanceof Query) {
-            $fields = $query->listFields();
+        if ($query->getUsePagedResults() && version_compare(PHP_VERSION, '5.4.0') >= 0) {
+            if ($this->pageCookie === null) {
+                $this->pageCookie = '';
+            } else {
+                try {
+                    ldap_control_paged_result_response($this->ds, $this->lastResult, $this->pageCookie);
+                } catch (Exception $e) {
+                    $this->pageCookie = '';
+                    Logger::debug(
+                        'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)',
+                        $e->getMessage()
+                    );
+                }
+
+                ldap_free_result($this->lastResult);
+                if (! $this->pageCookie) {
+                    $this->pageCookie = $this->lastResult = null;
+                    // Abandon the paged search request so that subsequent requests succeed
+                    ldap_control_paged_result($this->ds, 0);
+                    return false;
+                }
+            }
+
+            // Does not matter whether we'll use a valid page size here,
+            // as the server applies its hard limit in case its too high
+            ldap_control_paged_result(
+                $this->ds,
+                $query->hasLimit() ? $query->getLimit() : 500,
+                true,
+                $this->pageCookie
+            );
+        } elseif ($this->lastResult !== null) {
+            ldap_free_result($this->lastResult);
+            $this->lastResult = null;
+            return false;
         }
-        // WARNING:
-        // We do not support pagination right now, and there is no chance to
-        // do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
-        // therefore not be hidden right now.
+
         $base = $query->hasBase() ? $query->getBase() : $this->root_dn;
         $results = @ldap_search(
             $this->ds,
             $base,
             $query->create(),
-            $fields,
+            empty($fields) ? $query->listFields() : $fields,
             0, // Attributes and values
-            0  // No limit - at least where possible
+            $query->hasLimit() ? $query->getOffset() + $query->getLimit() : 0 // No limit - at least where possible
         );
+
         if ($results === false) {
             if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
                 return false;
@@ -336,12 +382,12 @@ class Connection
                 )
             );
         }
-        $list = array();
-        if ($query instanceof Query) {
-            foreach ($query->getSortColumns() as $col) {
-                ldap_sort($this->ds, $results, $col[0]);
-            }
+
+        foreach ($query->getSortColumns() as $col) {
+            ldap_sort($this->ds, $results, $col[0]);
         }
+
+        $this->lastResult = $results;
         return $results;
     }
 
diff --git a/library/Icinga/Protocol/Ldap/Query.php b/library/Icinga/Protocol/Ldap/Query.php
index 462c83d61..c6f0d6fa1 100644
--- a/library/Icinga/Protocol/Ldap/Query.php
+++ b/library/Icinga/Protocol/Ldap/Query.php
@@ -33,6 +33,7 @@ class Query
     protected $sort_columns = array();
     protected $count;
     protected $base;
+    protected $usePagedResults = true;
 
     /**
      * Constructor
@@ -61,6 +62,17 @@ class Query
         return $this->base;
     }
 
+    public function setUsePagedResults($state = true)
+    {
+        $this->usePagedResults = (bool) $state;
+        return $this;
+    }
+
+    public function getUsePagedResults()
+    {
+        return $this->usePagedResults;
+    }
+
     /**
      * Count result set, ignoring limits
      *
diff --git a/library/Icinga/User.php b/library/Icinga/User.php
index 659767644..db80c929a 100644
--- a/library/Icinga/User.php
+++ b/library/Icinga/User.php
@@ -197,8 +197,8 @@ class User
      */
     public function setPermissions(array $permissions)
     {
-        natcasesort($permissions);
         if (! empty($permissions)) {
+            natcasesort($permissions);
             $this->permissions = array_combine($permissions, $permissions);
         }
         return $this;
diff --git a/library/Icinga/User/Preferences/PreferencesStore.php b/library/Icinga/User/Preferences/PreferencesStore.php
index c2cba0c41..11454a2f8 100644
--- a/library/Icinga/User/Preferences/PreferencesStore.php
+++ b/library/Icinga/User/Preferences/PreferencesStore.php
@@ -26,7 +26,7 @@ use Icinga\Data\Db\DbConnection;
  * // Create a INI store
  * $store = PreferencesStore::create(
  *     new ConfigObject(
- *         'type'        => 'ini',
+ *         'store'       => 'ini',
  *         'config_path' => '/path/to/preferences'
  *     ),
  *     $user // Instance of \Icinga\User
@@ -117,13 +117,7 @@ abstract class PreferencesStore
      */
     public static function create(ConfigObject $config, User $user)
     {
-        if (($type = $config->type) === null) {
-            throw new ConfigurationError(
-                'Preferences configuration is missing the type directive'
-            );
-        }
-
-        $type = ucfirst(strtolower($type));
+        $type = ucfirst(strtolower($config->get('store', 'ini')));
         $storeClass = 'Icinga\\User\\Preferences\\Store\\' . $type . 'Store';
         if (!class_exists($storeClass)) {
             throw new ConfigurationError(
diff --git a/library/Icinga/Util/String.php b/library/Icinga/Util/String.php
index 248ab0d34..69fb26927 100644
--- a/library/Icinga/Util/String.php
+++ b/library/Icinga/Util/String.php
@@ -36,4 +36,22 @@ class String
     {
         return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name))));
     }
+
+    /**
+     * Add ellipsis when a string is longer than max length
+     *
+     * @param   string  $string
+     * @param   int     $maxLength
+     * @param   string  $ellipsis
+     *
+     * @return  string
+     */
+    public static function ellipsis($string, $maxLength, $ellipsis = '...')
+    {
+        if (strlen($string) > $maxLength) {
+            return substr($string, 0, $maxLength - strlen($ellipsis)) . $ellipsis;
+        }
+
+        return $string;
+    }
 }
diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php
index 400803dce..78fcaf7bf 100644
--- a/library/Icinga/Web/Controller/ActionController.php
+++ b/library/Icinga/Web/Controller/ActionController.php
@@ -5,7 +5,7 @@
 namespace Icinga\Web\Controller;
 
 use Exception;
-use Icinga\Authentication\Manager as AuthManager;
+use Icinga\Authentication\Manager;
 use Icinga\Application\Benchmark;
 use Icinga\Application\Config;
 use Icinga\Exception\IcingaException;
@@ -47,6 +47,11 @@ class ActionController extends Zend_Controller_Action
 
     private $xhrLayout = 'inline';
 
+    /**
+     * Authentication manager
+     *
+     * @type \Icinga\Authentication\Manager|null
+     */
     private $auth;
 
     protected $params;
@@ -101,6 +106,49 @@ class ActionController extends Zend_Controller_Action
     {
     }
 
+
+    /**
+     * Get the authentication manager
+     *
+     * @return Manager
+     */
+    public function Auth()
+    {
+        if ($this->auth === null) {
+            $this->auth = Manager::getInstance();
+        }
+        return $this->auth;
+    }
+
+    /**
+     * Whether the current user has the given permission
+     *
+     * @param   string  $permission Name of the permission
+     *
+     * @return  bool
+     */
+    public function hasPermission($permission)
+    {
+        return $this->Auth()->hasPermission($permission);
+    }
+
+    /**
+     * Throw an exception if user lacks the given permission
+     *
+     * @param  string  $name Permission name
+     * @throws Exception
+     */
+    public function assertPermission($name)
+    {
+        if (! $this->Auth()->hasPermission($name)) {
+            // TODO: Shall this be an Auth Exception? Or a 404?
+            throw new IcingaException(
+                'Auth error, no permission for "%s"',
+                $name
+            );
+        }
+    }
+
     public function Config($file = null)
     {
         if ($file === null) {
@@ -110,14 +158,6 @@ class ActionController extends Zend_Controller_Action
         }
     }
 
-    public function Auth()
-    {
-        if ($this->auth === null) {
-            $this->auth = AuthManager::getInstance();
-        }
-        return $this->auth;
-    }
-
     public function Window()
     {
         if ($this->window === null) {
@@ -146,6 +186,22 @@ class ActionController extends Zend_Controller_Action
         return $this;
     }
 
+    /**
+     * Respond with HTTP 405 if the current request's method is not one of the given methods
+     *
+     * @param   string $httpMethod                  Unlimited number of allowed HTTP methods
+     *
+     * @throws  \Zend_Controller_Action_Exception   If the request method is not one of the given methods
+     */
+    public function assertHttpMethod($httpMethod)
+    {
+        $httpMethods = array_flip(array_map('strtoupper', func_get_args()));
+        if (! isset($httpMethods[$this->getRequest()->getMethod()])) {
+            $this->getResponse()->setHeader('Allow', implode(', ', array_keys($httpMethods)));
+            throw new \Zend_Controller_Action_Exception($this->translate('Method Not Allowed'), 405);
+        }
+    }
+
     /**
      * Return restriction information for an eventually authenticated user
      *
@@ -157,34 +213,6 @@ class ActionController extends Zend_Controller_Action
         return $this->Auth()->getRestrictions($name);
     }
 
-    /**
-     * Whether the user currently authenticated has the given permission
-     *
-     * @param  string  $name Permission name
-     * @return bool
-     */
-    public function hasPermission($name)
-    {
-        return $this->Auth()->hasPermission($name);
-    }
-
-    /**
-     * Throws an exception if user lacks the given permission
-     *
-     * @param  string  $name Permission name
-     * @throws Exception
-     */
-    public function assertPermission($name)
-    {
-        if (! $this->Auth()->hasPermission($name)) {
-            // TODO: Shall this be an Auth Exception? Or a 404?
-            throw new IcingaException(
-                'Auth error, no permission for "%s"',
-                $name
-            );
-        }
-    }
-
     /**
      * Check whether the controller requires a login. That is when the controller requires authentication and the
      * user is currently not authenticated
@@ -270,7 +298,7 @@ class ActionController extends Zend_Controller_Action
     /**
      * Redirect to the login path
      *
-     * @param   string      $afterLogin   The action to call when the login was successful. Defaults to '/index/welcome'
+     * @param   Url         $afterLogin   The action to call when the login was successful. Defaults to '/index/welcome'
      *
      * @throws  \Exception
      */
diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php
index 205c4e238..1f3e0d4bd 100644
--- a/library/Icinga/Web/Form.php
+++ b/library/Icinga/Web/Form.php
@@ -512,7 +512,7 @@ class Form extends Zend_Form
 
         $el = parent::createElement($type, $name, $options);
 
-        if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== null) {
+        if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== false) {
             $label->setOptions(array(
                 'title' => $description,
                 'class' => 'has-feedback'
@@ -805,6 +805,24 @@ class Form extends Zend_Form
         return array();
     }
 
+    /**
+     * Get the translation domain for this form
+     *
+     * The returned translation domain is either determined based on this form's qualified name or it is the default
+     * 'icinga' domain
+     *
+     * @return string
+     */
+    protected function getTranslationDomain()
+    {
+        $parts = explode('\\', get_called_class());
+        if ($parts[1] === 'Module') {
+            // Assume format Icinga\Module\ModuleName\Forms\...
+            return strtolower($parts[2]);
+        }
+        return 'icinga';
+    }
+
     /**
      * Translate a string
      *
@@ -815,7 +833,7 @@ class Form extends Zend_Form
      */
     protected function translate($text, $context = null)
     {
-        return Translator::translate($text, $this->request->getModuleName(), $context);
+        return Translator::translate($text, $this->getTranslationDomain(), $context);
     }
 
     /**
@@ -834,7 +852,7 @@ class Form extends Zend_Form
             $textSingular,
             $textPlural,
             $number,
-            $this->request->getModuleName(),
+            $this->getTranslationDomain(),
             $context
         );
     }
diff --git a/library/Icinga/Web/LessCompiler.php b/library/Icinga/Web/LessCompiler.php
index 791fdbab0..261790579 100644
--- a/library/Icinga/Web/LessCompiler.php
+++ b/library/Icinga/Web/LessCompiler.php
@@ -43,12 +43,6 @@ class LessCompiler
     {
         require_once 'lessphp/lessc.inc.php';
         $this->lessc = new lessc();
-
-        $this->lessc->setVariables(
-            array(
-                'baseurl' => '\'' . Zend_Controller_Front::getInstance()->getBaseUrl(). '\''
-            )
-        );
     }
 
     public function compress()
diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php
index 18a17ea67..f0279ea9c 100644
--- a/library/Icinga/Web/Menu.php
+++ b/library/Icinga/Web/Menu.php
@@ -248,7 +248,8 @@ class Menu implements RecursiveIterator
 
             $section->add(t('Logout'), array(
                 'url'      => 'authentication/logout',
-                'priority' => 700
+                'priority' => 700,
+                'renderer' => 'ForeignMenuItemRenderer'
             ));
         }
     }
@@ -366,7 +367,7 @@ class Menu implements RecursiveIterator
     /**
      * Return the url of this menu
      *
-     * @return  string
+     * @return  Url
      */
     public function getUrl()
     {
diff --git a/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php
new file mode 100644
index 000000000..659709868
--- /dev/null
+++ b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php
@@ -0,0 +1,24 @@
+<?php
+// {{{ICINGA_LICENSE_HEADER}}}
+// {{{ICINGA_LICENSE_HEADER}}}
+
+namespace Icinga\Web\Menu;
+
+use Icinga\Web\Menu;
+use Icinga\Web\Url;
+
+/**
+ * A menu item with a link that surpasses the regular navigation link behavior
+ */
+class ForeignMenuItemRenderer implements MenuItemRenderer {
+
+    public function render(Menu $menu)
+    {
+        return sprintf(
+            '<a href="%s" target="_self">%s%s<span></span></a>',
+            $menu->getUrl() ?: '#',
+            $menu->getIcon() ? '<img src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
+            htmlspecialchars($menu->getTitle())
+        );
+    }
+}
diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php
old mode 100644
new mode 100755
index bef978c0b..fa545fd8d
--- a/library/Icinga/Web/Session/PhpSession.php
+++ b/library/Icinga/Web/Session/PhpSession.php
@@ -78,8 +78,9 @@ class PhpSession extends Session
             }
         }
 
-        if (!is_writable(session_save_path())) {
-            throw new ConfigurationError('Can\'t save session');
+        $sessionSavePath = session_save_path();
+        if (session_module_name() === 'files' && !is_writable($sessionSavePath)) {
+            throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable.");
         }
 
         if ($this->exists()) {
diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php
index 719d1c829..9e6bd0bed 100644
--- a/library/Icinga/Web/StyleSheet.php
+++ b/library/Icinga/Web/StyleSheet.php
@@ -96,6 +96,7 @@ class StyleSheet
             $cache->send($cacheFile);
             return;
         }
+
         $less = new LessCompiler();
         foreach ($lessFiles as $file) {
             $less->addFile($file);
diff --git a/library/Icinga/Web/View.php b/library/Icinga/Web/View.php
index 7a954934a..2122662ac 100644
--- a/library/Icinga/Web/View.php
+++ b/library/Icinga/Web/View.php
@@ -4,10 +4,11 @@
 
 namespace Icinga\Web;
 
+use Closure;
+use Zend_View_Abstract;
+use Icinga\Authentication\Manager;
 use Icinga\Exception\ProgrammingError;
 use Icinga\Util\Translator;
-use Zend_View_Abstract;
-use Closure;
 
 /**
  * Icinga view
@@ -36,6 +37,13 @@ class View extends Zend_View_Abstract
      */
     private $helperFunctions = array();
 
+    /**
+     * Authentication manager
+     *
+     * @type \Icinga\Authentication\Manager|null
+     */
+    private $auth;
+
     /**
      * Create a new view object
      *
@@ -154,6 +162,31 @@ class View extends Zend_View_Abstract
         }
     }
 
+    /**
+     * Get the authentication manager
+     *
+     * @return Manager
+     */
+    public function Auth()
+    {
+        if ($this->auth === null) {
+            $this->auth = Manager::getInstance();
+        }
+        return $this->auth;
+    }
+
+    /**
+     * Whether the current user has the given permission
+     *
+     * @param   string  $permission Name of the permission
+     *
+     * @return  bool
+     */
+    public function hasPermission($permission)
+    {
+        return $this->Auth()->hasPermission($permission);
+    }
+
     /**
      * Use to include the view script in a scope that only allows public
      * members.
diff --git a/library/Icinga/Web/View/helpers/string.php b/library/Icinga/Web/View/helpers/string.php
new file mode 100644
index 000000000..1d79d885a
--- /dev/null
+++ b/library/Icinga/Web/View/helpers/string.php
@@ -0,0 +1,8 @@
+<?php
+namespace Icinga\Web\View;
+
+use Icinga\Util\String;
+
+$this->addHelperFunction('ellipsis', function ($string, $maxLength, $ellipsis = '...') {
+    return String::ellipsis($string, $maxLength, $ellipsis);
+});
diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php
index 618d2903b..04e3e7318 100644
--- a/library/Icinga/Web/Widget/Chart/InlinePie.php
+++ b/library/Icinga/Web/Widget/Chart/InlinePie.php
@@ -5,6 +5,7 @@
 namespace Icinga\Web\Widget\Chart;
 
 use Icinga\Chart\PieChart;
+use Icinga\Module\Monitoring\Plugin\PerfdataSet;
 use Icinga\Web\Widget\AbstractWidget;
 use Icinga\Web\Url;
 use Icinga\Util\Format;
@@ -28,36 +29,23 @@ class InlinePie extends AbstractWidget
     const NUMBER_FORMAT_RATIO = 'ratio';
 
     /**
-     * The template string used for rendering this widget
      * The template string used for rendering this widget
      *
      * @var string
      */
     private $template =<<<'EOD'
-    <span
-        class="sparkline"
-        sparkTitle="{title}"
-        sparkWidth="{width}"
-        sparkHeight="{height}"
-        sparkBorderWidth="{borderWidth}"
-        sparkBorderColor="{borderColor}"
-        sparkTooltipChartTitle="{title}"
-        style="{style}"
-        labels="{labels}"
-        formatted="{formatted}"
-        hideEmptyLabel={hideEmptyLabel}
-        values="{data}"
-        tooltipFormat="{tooltipFormat}"
-        sparkSliceColors="[{colors}]"
-        sparkType="pie"></span>
-    <noscript>
-    <img class="inlinepie"
-        title="{title}" src="{url}" style="position: relative; top: 10px; width: {width}px; height: {height}px; {style}"
-        data-icinga-colors="{colors}" data-icinga-values="{data}"
-    />
-    </noscript>
+<span sparkType="pie" class="sparkline {class}" {title} {size} sparkSliceColors="[{colors}]" values="{data}">
+</span>
+{noscript}
 EOD;
 
+    private $noscript =<<<'EOD'
+<noscript>
+  <img class="inlinepie {class}" {title} src="{url}" data-icinga-colors="{colors}" data-icinga-values="{data}"/>
+</noscript>
+EOD;
+
+
     /**
      * @var Url
      */
@@ -68,35 +56,7 @@ EOD;
      *
      * @var array
      */
-    private $colors = array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd');
-
-    /**
-     * The width of the rendered chart
-     *
-     * @var int The value in px
-     */
-    private $width = 16;
-
-    /**
-     * The height of the rendered chart
-     *
-     * @var int The value in px
-     */
-    private $height = 16;
-
-    /**
-     * PieChart border width
-     *
-     * @var float
-     */
-    private $borderWidth = 1;
-
-    /**
-     * The color of the border
-     *
-     * @var string
-     */
-    private $borderColor = '#fff';
+    private $colors = array('#049BAF', '#ffaa44', '#ff5566', '#ddccdd');
 
     /**
      * The title of the chart
@@ -106,11 +66,9 @@ EOD;
     private $title;
 
     /**
-     * The style for the HtmlElement
-     *
-     * @var string
+     * @var
      */
-    private $style = '';
+    private $size;
 
     /**
      * The data displayed by the pie-chart
@@ -120,45 +78,9 @@ EOD;
     private $data;
 
     /**
-     * The labels to display for each data set
-     *
-     * @var array
+     * @var
      */
-    private $labels = array();
-
-    /**
-     * If the tooltip for the "empty" area should be hidden
-     *
-     * @var bool
-     */
-    private $hideEmptyLabel = false;
-
-    /**
-     * The format string used to display tooltips
-     *
-     * @var string
-     */
-    private $tooltipFormat = '<b>{{title}}</b></br> {{label}}: {{formatted}} ({{percent}}%)';
-
-    /**
-     * The number format used to render numeric values in tooltips
-     *
-     * @var array
-     */
-    private $format = self::NUMBER_FORMAT_NONE;
-
-    /**
-     * Set if the tooltip for the empty area should be hidden
-     *
-     * @param   bool $hide    Whether to hide the empty area
-     *
-     * @return  $this
-     */
-    public function setHideEmptyLabel($hide = true)
-    {
-        $this->hideEmptyLabel = $hide;
-        return $this;
-    }
+    private $class = '';
 
     /**
      * Set the data to be displayed.
@@ -175,24 +97,36 @@ EOD;
     }
 
     /**
-     * The labels to be displayed in the pie-chart
+     * Set the size of the inline pie
      *
-     * @param   mixed $label     The label of the displayed value, or null for no labels
+     * @param int $size     Sets both, the height and width
      *
-     * @return  $this
+     * @return $this
      */
-    public function setLabel($label)
+    public function setSize($size = null)
     {
-        if (is_array($label)) {
-            $this->url->setParam('labels', implode(',', array_keys($label)));
-        } elseif ($label != null) {
-            $labelArr =  array($label, $label, $label, '');
-            $this->url->setParam('labels', implode(',', $labelArr));
-            $label = $labelArr;
-        } else {
-            $this->url->removeKey('labels');
-        }
-        $this->labels = $label;
+        $this->size = $size;
+        return $this;
+    }
+
+    /**
+     * Do not display the NoScript fallback html
+     */
+    public function disableNoScript()
+    {
+        $this->noscript = '';
+    }
+
+    /**
+     * Set the class to define the
+     *
+     * @param  $class
+     *
+     * @return $this
+     */
+    public function setSparklineClass($class)
+    {
+        $this->class = $class;
         return $this;
     }
 
@@ -214,105 +148,6 @@ EOD;
         return $this;
     }
 
-    /**
-     * Set the used number format
-     *
-     * @param   $format   string  'bytes' or 'time'
-     *
-     * @return  $this
-     */
-    public function setNumberFormat($format)
-    {
-        $this->format = $format;
-        return $this;
-    }
-
-    /**
-     * A format string used to render the content of the piechart tooltips
-     *
-     * Placeholders using curly braces '{FOO}' are replace with their specific values. The format
-     * String may contain HTML-Markup. The available replaceable values are:
-     * <ul>
-     *      <li><b>label</b>:     The description for the current value </li>
-     *      <li><b>formatted</b>: A string representing the formatted value </li>
-     *      <li><b>value</b>:     The raw (non-formatted) value used to render the piechart </li>
-     *      <li><b>percent</b>:   The percentage of the current value </li>
-     * </ul>
-     * Note: Changes will only affect JavaScript sparklines and not the SVG charts used for fallback
-     *
-     * @param   $format
-     *
-     * @return  $this
-     */
-    public function setTooltipFormat($format)
-    {
-        $this->tooltipFormat = $format;
-        return $this;
-    }
-
-    /**
-     * Set the height
-     *
-     * @param   $height
-     *
-     * @return  $this
-     */
-    public function setHeight($height)
-    {
-        $this->height = $height;
-        return $this;
-    }
-
-    /**
-     * Set the border width of the pie chart
-     *
-     * @param   float $width    Width in px
-     *
-     * @return  $this
-     */
-    public function setBorderWidth($width)
-    {
-        $this->borderWidth = $width;
-        return $this;
-    }
-
-    /**
-     * Set the color of the pie chart border
-     *
-     * @param   string $col   The color string
-     *
-     * @return  $this
-     */
-    public function setBorderColor($col)
-    {
-        $this->borderColor = $col;
-    }
-
-    /**
-     * Set the width
-     *
-     * @param   $width
-     *
-     * @return  $this
-     */
-    public function setWidth($width)
-    {
-        $this->width = $width;
-        return $this;
-    }
-
-    /**
-     * Set the styling of the created HtmlElement
-     *
-     * @param   string $style
-     *
-     * @return  $this
-     */
-    public function setStyle($style)
-    {
-        $this->style = $style;
-    }
-
     /**
      * Set the title of the displayed Data
      *
@@ -322,7 +157,7 @@ EOD;
      */
     public function setTitle($title)
     {
-        $this->title = $title;
+        $this->title = 'title="' .  htmlspecialchars($title) . '"';
         return $this;
     }
 
@@ -335,13 +170,10 @@ EOD;
      */
     public function __construct(array $data, $title, $colors = null)
     {
-        $this->title = $title;
+        $this->setTitle($title);
         $this->url = Url::fromPath('svg/chart.php');
         if (array_key_exists('data', $data)) {
             $this->data = $data['data'];
-            if (array_key_exists('labels', $data)) {
-                $this->labels = $data['labels'];
-            }
             if (array_key_exists('colors', $data)) {
                 $this->colors = $data['colors'];
             }
@@ -354,21 +186,6 @@ EOD;
             $this->setColors($this->colors);
         }
     }
-
-    /**
-     * Create a serialization containing the current label array
-     *
-     * @return string   A serialized array of labels
-     */
-    private function createLabelString ()
-    {
-        $labels = $this->labels;
-        foreach ($labels as $key => $label) {
-            $labels[$key] = str_replace('|', '', $label);
-        }
-        return isset($this->labels) && is_array($this->labels) ? implode('|', $this->labels) : '';
-    }
-
     /**
      * Renders this widget via the given view and returns the
      * HTML as a string
@@ -382,11 +199,11 @@ EOD;
             $pie->alignTopLeft();
             $pie->disableLegend();
             $pie->drawPie(array(
-                'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels
+                'data' => $this->data, 'colors' => $this->colors
             ));
 
             try {
-                $png = $pie->toPng($this->width, $this->height);
+                $png = $pie->toPng($this->size, $this->size);
                 return '<img class="inlinepie" src="data:image/png;base64,' . base64_encode($png) . '" />';
             } catch (IcingaException $_) {
                 return '';
@@ -394,17 +211,17 @@ EOD;
         }
 
         $template = $this->template;
+        // TODO: Check whether we are XHR and don't send
+        $template = str_replace('{noscript}', $this->noscript, $template);
         $template = str_replace('{url}', $this->url, $template);
+        $template = str_replace('{class}', $this->class, $template);
 
         // style
-        $template = str_replace('{width}', $this->width, $template);
-        $template = str_replace('{height}', $this->height, $template);
-        $template = str_replace('{title}', htmlspecialchars($this->title), $template);
-        $template = str_replace('{style}', $this->style, $template);
+        $template = str_replace('{size}',
+            isset($this->size) ? 'sparkWidth="' . $this->size . '" sparkHeight="' . $this->size . '" ' : '', $template);
+        $template = str_replace('{title}', $this->title, $template);
+
         $template = str_replace('{colors}', implode(',', $this->colors), $template);
-        $template = str_replace('{borderWidth}', $this->borderWidth, $template);
-        $template = str_replace('{borderColor}', $this->borderColor, $template);
-        $template = str_replace('{hideEmptyLabel}', $this->hideEmptyLabel ? 'true' : 'false', $template);
 
         // Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again.
         // Problem is that implode respects locales when casting floats. This means
@@ -414,38 +231,7 @@ EOD;
             $data[] = sprintf('%F', $dat);
         }
 
-        // values
-        $formatted = array();
-        foreach ($this->data as $key => $value) {
-            $formatted[$key] = $this->formatValue($value);
-        }
         $template = str_replace('{data}', htmlspecialchars(implode(',', $data)), $template);
-        $template = str_replace('{formatted}', htmlspecialchars(implode('|', $formatted)), $template);
-        $template = str_replace('{labels}', htmlspecialchars($this->createLabelString()), $template);
-        $template = str_replace('{tooltipFormat}', $this->tooltipFormat, $template);
         return $template;
     }
-
-    /**
-     * Format the given value depending on the current value of numberFormat
-     *
-     * @param   float   $value  The value to format
-     *
-     * @return  string          The formatted value
-     */
-    private function formatValue($value)
-    {
-        if ($this->format === self::NUMBER_FORMAT_NONE) {
-            return (string)$value;
-        } elseif ($this->format === self::NUMBER_FORMAT_BYTES) {
-            return Format::bytes($value);
-        } elseif ($this->format === self::NUMBER_FORMAT_TIME) {
-            return Format::duration($value);
-        } elseif ($this->format === self::NUMBER_FORMAT_RATIO) {
-            return $value;
-        } else {
-            Logger::warning('Unknown format string "' . $this->format . '" for InlinePie, value not formatted.');
-            return $value;
-        }
-    }
 }
diff --git a/library/Icinga/Web/Widget/Tabs.php b/library/Icinga/Web/Widget/Tabs.php
index 72522282e..c6a4bd31b 100644
--- a/library/Icinga/Web/Widget/Tabs.php
+++ b/library/Icinga/Web/Widget/Tabs.php
@@ -218,6 +218,25 @@ EOT;
         return $this;
     }
 
+    /**
+     * Remove a tab
+     *
+     * @param   string  $name
+     *
+     * @return  self
+     */
+    public function remove($name)
+    {
+        if ($this->has($name)) {
+            unset($this->tabs[$name]);
+            if (($dropdownIndex = array_search($name, $this->dropdownTabs)) !== false) {
+                array_splice($this->dropdownTabs, $dropdownIndex, 2);
+            }
+        }
+
+        return $this;
+    }
+
     /**
      * Add a tab to the dropdown on the right side of the tab-bar.
      *
diff --git a/library/Icinga/Web/Wizard.php b/library/Icinga/Web/Wizard.php
index 2cc4abe5a..42dea5c1c 100644
--- a/library/Icinga/Web/Wizard.php
+++ b/library/Icinga/Web/Wizard.php
@@ -39,6 +39,13 @@ class Wizard
      */
     const BTN_PREV = 'btn_prev';
 
+    /**
+     * This wizard's parent
+     *
+     * @var Wizard
+     */
+    protected $parent;
+
     /**
      * The name of the wizard's current page
      *
@@ -71,19 +78,55 @@ class Wizard
 
     }
 
+    /**
+     * Return this wizard's parent or null in case it has none
+     *
+     * @return  Wizard|null
+     */
+    public function getParent()
+    {
+        return $this->parent;
+    }
+
+    /**
+     * Set this wizard's parent
+     *
+     * @param   Wizard  $wizard     The parent wizard
+     *
+     * @return  self
+     */
+    public function setParent(Wizard $wizard)
+    {
+        $this->parent = $wizard;
+        return $this;
+    }
+
     /**
      * Return the pages being part of this wizard
      *
+     * In case this is a nested wizard a flattened array of all contained pages is returned.
+     *
      * @return  array
      */
     public function getPages()
     {
-        return $this->pages;
+        $pages = array();
+        foreach ($this->pages as $page) {
+            if ($page instanceof self) {
+                $pages = array_merge($pages, $page->getPages());
+            } else {
+                $pages[] = $page;
+            }
+        }
+
+        return $pages;
     }
 
     /**
      * Return the page with the given name
      *
+     * Note that it's also possible to retrieve a nested wizard's page by using this method.
+     *
      * @param   string      $name   The name of the page to return
      *
      * @return  null|Form           The page or null in case there is no page with the given name
@@ -98,22 +141,31 @@ class Wizard
     }
 
     /**
-     * Add a new page to this wizard
+     * Add a new page or wizard to this wizard
      *
-     * @param   Form    $page   The page to add to the wizard
+     * @param   Form|Wizard     $page   The page or wizard to add to the wizard
      *
      * @return  self
      */
-    public function addPage(Form $page)
+    public function addPage($page)
     {
+        if (! $page instanceof Form && ! $page instanceof self) {
+            throw InvalidArgumentException(
+                'The $page argument must be an instance of Icinga\Web\Form '
+                . 'or Icinga\Web\Wizard but is of type: ' . get_class($page)
+            );
+        } elseif ($page instanceof self) {
+            $page->setParent($this);
+        }
+
         $this->pages[] = $page;
         return $this;
     }
 
     /**
-     * Add multiple pages to this wizard
+     * Add multiple pages or wizards to this wizard
      *
-     * @param   array   $pages      The pages to add to the wizard
+     * @param   array   $pages      The pages or wizards to add to the wizard
      *
      * @return  self
      */
@@ -148,6 +200,10 @@ class Wizard
      */
     public function getCurrentPage()
     {
+        if ($this->parent) {
+            return $this->parent->getCurrentPage();
+        }
+
         if ($this->currentPage === null) {
             $this->assertHasPages();
             $pages = $this->getPages();
@@ -202,6 +258,10 @@ class Wizard
     {
         $page = $this->getCurrentPage();
 
+        if (($wizard = $this->findWizard($page)) !== null) {
+            return $wizard->handleRequest($request);
+        }
+
         if ($request === null) {
             $request = $page->getRequest();
         }
@@ -238,6 +298,39 @@ class Wizard
         return $request;
     }
 
+    /**
+     * Return the wizard for the given page or null if its not part of a wizard
+     *
+     * @param   Form    $page   The page to return its wizard for
+     *
+     * @return  Wizard|null
+     */
+    protected function findWizard(Form $page)
+    {
+        foreach ($this->getWizards() as $wizard) {
+            if ($wizard->getPage($page->getName()) === $page) {
+                return $wizard;
+            }
+        }
+    }
+
+    /**
+     * Return this wizard's child wizards
+     *
+     * @return  array
+     */
+    protected function getWizards()
+    {
+        $wizards = array();
+        foreach ($this->pages as $pageOrWizard) {
+            if ($pageOrWizard instanceof self) {
+                $wizards[] = $pageOrWizard;
+            }
+        }
+
+        return $wizards;
+    }
+
     /**
      * Return the request data based on given form's request method
      *
@@ -264,6 +357,10 @@ class Wizard
      */
     protected function getRequestedPage(array $requestData)
     {
+        if ($this->parent) {
+            return $this->parent->getRequestedPage($requestData);
+        }
+
         if (isset($requestData[static::BTN_NEXT])) {
             return $requestData[static::BTN_NEXT];
         } elseif (isset($requestData[static::BTN_PREV])) {
@@ -280,6 +377,10 @@ class Wizard
      */
     protected function getDirection(Request $request = null)
     {
+        if ($this->parent) {
+            return $this->parent->getDirection($request);
+        }
+
         $currentPage = $this->getCurrentPage();
 
         if ($request === null) {
@@ -299,7 +400,7 @@ class Wizard
     /**
      * Return the new page to set as current page
      *
-     * Permission is checked by verifying that the requested page's previous page has page data available.
+     * Permission is checked by verifying that the requested page or its previous page has page data available.
      * The requested page is automatically permitted without any checks if the origin page is its previous
      * page or one that occurs later in order.
      *
@@ -312,11 +413,15 @@ class Wizard
      */
     protected function getNewPage($requestedPage, Form $originPage)
     {
+        if ($this->parent) {
+            return $this->parent->getNewPage($requestedPage, $originPage);
+        }
+
         if (($page = $this->getPage($requestedPage)) !== null) {
             $permitted = true;
 
             $pages = $this->getPages();
-            if (($index = array_search($page, $pages, true)) > 0) {
+            if (! $this->hasPageData($requestedPage) && ($index = array_search($page, $pages, true)) > 0) {
                 $previousPage = $pages[$index - 1];
                 if ($originPage === null || ($previousPage->getName() !== $originPage->getName()
                     && array_search($originPage, $pages, true) < $index))
@@ -335,6 +440,36 @@ class Wizard
         );
     }
 
+    /**
+     * Return the next or previous page based on the given one
+     *
+     * @param   Form    $page   The page to skip
+     *
+     * @return  Form
+     */
+    protected function skipPage(Form $page)
+    {
+        if ($this->parent) {
+            return $this->parent->skipPage($page);
+        }
+
+        if ($this->hasPageData($page->getName())) {
+            $pageData = & $this->getPageData();
+            unset($pageData[$page->getName()]);
+        }
+
+        $pages = $this->getPages();
+        if ($this->getDirection() === static::FORWARD) {
+            $nextPage = $pages[array_search($page, $pages, true) + 1];
+            $newPage = $this->getNewPage($nextPage->getName(), $page);
+        } else { // $this->getDirection() === static::BACKWARD
+            $previousPage = $pages[array_search($page, $pages, true) - 1];
+            $newPage = $this->getNewPage($previousPage->getName(), $page);
+        }
+
+        return $newPage;
+    }
+
     /**
      * Return whether the given page is this wizard's last page
      *
@@ -344,10 +479,27 @@ class Wizard
      */
     protected function isLastPage(Form $page)
     {
+        if ($this->parent) {
+            return $this->parent->isLastPage($page);
+        }
+
         $pages = $this->getPages();
         return $page->getName() === end($pages)->getName();
     }
 
+    /**
+     * Return whether all of this wizard's pages were visited by the user
+     *
+     * The base implementation just verifies that the very last page has page data available.
+     *
+     * @return  bool
+     */
+    public function isComplete()
+    {
+        $pages = $this->getPages();
+        return $this->hasPageData($pages[count($pages) - 1]->getName());
+    }
+
     /**
      * Set whether this wizard has been completed
      *
@@ -421,6 +573,10 @@ class Wizard
      */
     public function getSession()
     {
+        if ($this->parent) {
+            return $this->parent->getSession();
+        }
+
         return Session::getSession()->getNamespace(get_class($this));
     }
 
diff --git a/library/vendor/Parsedown/LICENSE.txt b/library/vendor/Parsedown/LICENSE
similarity index 100%
rename from library/vendor/Parsedown/LICENSE.txt
rename to library/vendor/Parsedown/LICENSE
diff --git a/library/vendor/Parsedown/SOURCE b/library/vendor/Parsedown/SOURCE
index c5a2c7c28..43ee6c61c 100644
--- a/library/vendor/Parsedown/SOURCE
+++ b/library/vendor/Parsedown/SOURCE
@@ -4,3 +4,4 @@ DESTINATION=.
 wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz
 tar xfz ${FILENAME}.tar.gz -C $DESTINATION/ --strip-components 1 $FILENAME/Parsedown.php $FILENAME/LICENSE.txt
 chmod 644 $DESTINATION/Parsedown.php
+mv LICENSE.txt LICENSE
diff --git a/library/vendor/dompdf/LICENSE.LGPL b/library/vendor/dompdf/LICENSE
similarity index 100%
rename from library/vendor/dompdf/LICENSE.LGPL
rename to library/vendor/dompdf/LICENSE
diff --git a/library/vendor/dompdf/SOURCE b/library/vendor/dompdf/SOURCE
index 9343b58cf..c26253e30 100644
--- a/library/vendor/dompdf/SOURCE
+++ b/library/vendor/dompdf/SOURCE
@@ -1,6 +1,7 @@
 curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.1 -o dompdf-0.6.1.tar.gz
 tar xzf dompdf-0.6.1.tar.gz --strip-components 1 dompdf-0.6.1/{include/*.php,lib,dompdf*.php,LICENSE.LGPL}
 rm dompdf-0.6.1.tar.gz
+mv LICENSE.LGPL LICENSE
 
 curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.3.1 -o php-font-lib-0.3.1.tar.gz
 mkdir lib/php-font-lib/classes
diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php
index 5740f50a9..60c5da5ee 100644
--- a/modules/doc/application/controllers/IcingawebController.php
+++ b/modules/doc/application/controllers/IcingawebController.php
@@ -8,12 +8,36 @@ use Icinga\Module\Doc\DocController;
 
 class Doc_IcingawebController extends DocController
 {
+    /**
+     * Get the path to Icinga Web 2's documentation
+     *
+     * @return  string
+     *
+     * @throws  Zend_Controller_Action_Exception    If Icinga Web 2's documentation is not available
+     */
+    protected function getPath()
+    {
+        $path = Icinga::app()->getBaseDir('doc');
+        if (is_dir($path)) {
+            return $path;
+        }
+        if (($path = $this->Config()->get('documentation', 'icingaweb2')) !== null) {
+            if (is_dir($path)) {
+                return $path;
+            }
+        }
+        throw new Zend_Controller_Action_Exception(
+            $this->translate('Documentation for Icinga Web 2 is not available'),
+            404
+        );
+    }
+
     /**
      * View the toc of Icinga Web 2's documentation
      */
     public function tocAction()
     {
-        return $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
+        $this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter');
     }
 
     /**
@@ -26,12 +50,12 @@ class Doc_IcingawebController extends DocController
         $chapterId = $this->getParam('chapterId');
         if ($chapterId === null) {
             throw new Zend_Controller_Action_Exception(
-                $this->translate('Missing parameter \'chapterId\''),
+                sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'),
                 404
             );
         }
-        return $this->renderChapter(
-            Icinga::app()->getApplicationDir('/../doc'),
+        $this->renderChapter(
+            $this->getPath(),
             $chapterId,
             'doc/icingaweb/toc',
             'doc/icingaweb/chapter'
@@ -43,6 +67,6 @@ class Doc_IcingawebController extends DocController
      */
     public function pdfAction()
     {
-        return $this->renderPdf(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
+        $this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter');
     }
 }
diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php
index 1e9cf43b1..a4d14cf61 100644
--- a/modules/doc/application/controllers/ModuleController.php
+++ b/modules/doc/application/controllers/ModuleController.php
@@ -9,6 +9,40 @@ use Icinga\Module\Doc\Exception\DocException;
 
 class Doc_ModuleController extends DocController
 {
+    /**
+     * Get the path to a module documentation
+     *
+     * @param   string  $module                     The name of the module
+     * @param   string  $default                    The default path
+     * @param   bool    $suppressErrors             Whether to not throw an exception if the module documentation is not
+     *                                              available
+     *
+     * @return  string|null                         Path to the documentation or null if the module documentation is not
+     *                                              available and errors are suppressed
+     *
+     * @throws  Zend_Controller_Action_Exception    If the module documentation is not available and errors are not
+     *                                              suppressed
+     */
+    protected function getPath($module, $default, $suppressErrors = false)
+    {
+        if (is_dir($default)) {
+            return $default;
+        }
+        if (($path = $this->Config()->get('documentation', 'modules')) !== null) {
+            $path = str_replace('{module}', $module, $path);
+            if (is_dir($path)) {
+                return $path;
+            }
+        }
+        if ($suppressErrors) {
+            return null;
+        }
+        throw new Zend_Controller_Action_Exception(
+            sprintf($this->translate('Documentation for module \'%s\' is not available'), $module),
+            404
+        );
+    }
+
     /**
      * List modules which are enabled and having the 'doc' directory
      */
@@ -16,10 +50,10 @@ class Doc_ModuleController extends DocController
     {
         $moduleManager = Icinga::app()->getModuleManager();
         $modules = array();
-        foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $enabledModule) {
-            $docDir = $moduleManager->getModuleDir($enabledModule, '/doc');
-            if (is_dir($docDir)) {
-                $modules[] = $enabledModule;
+        foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $module) {
+            $path = $this->getPath($module, $moduleManager->getModuleDir($module, '/doc'), true);
+            if ($path !== null) {
+                $modules[] = $module;
             }
         }
         $this->view->modules = $modules;
@@ -37,7 +71,7 @@ class Doc_ModuleController extends DocController
     {
         if (empty($moduleName)) {
             throw new Zend_Controller_Action_Exception(
-                $this->translate('Missing parameter \'moduleName\''),
+                sprintf($this->translate('Missing parameter \'%s\''), 'moduleName'),
                 404
             );
         }
@@ -63,16 +97,15 @@ class Doc_ModuleController extends DocController
      */
     public function tocAction()
     {
-        $moduleName = $this->getParam('moduleName');
-        $this->assertModuleEnabled($moduleName);
-        $this->view->moduleName = $moduleName;
-        $moduleManager = Icinga::app()->getModuleManager();
+        $module = $this->getParam('moduleName');
+        $this->assertModuleEnabled($module);
+        $this->view->moduleName = $module;
         try {
-            return $this->renderToc(
-                $moduleManager->getModuleDir($moduleName, '/doc'),
-                $moduleName,
+            $this->renderToc(
+                $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
+                $module,
                 'doc/module/chapter',
-                array('moduleName' => $moduleName)
+                array('moduleName' => $module)
             );
         } catch (DocException $e) {
             throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
@@ -88,24 +121,23 @@ class Doc_ModuleController extends DocController
      */
     public function chapterAction()
     {
-        $moduleName = $this->getParam('moduleName');
-        $this->assertModuleEnabled($moduleName);
+        $module = $this->getParam('moduleName');
+        $this->assertModuleEnabled($module);
         $chapterId = $this->getParam('chapterId');
         if ($chapterId === null) {
             throw new Zend_Controller_Action_Exception(
-                $this->translate('Missing parameter \'chapterId\''),
+                sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'),
                 404
             );
         }
-        $this->view->moduleName = $moduleName;
-        $moduleManager = Icinga::app()->getModuleManager();
+        $this->view->moduleName = $module;
         try {
-            return $this->renderChapter(
-                $moduleManager->getModuleDir($moduleName, '/doc'),
+            $this->renderChapter(
+                $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
                 $chapterId,
-                $this->_helper->url->url(array('moduleName' => $moduleName), 'doc/module/toc'),
+                $this->_helper->url->url(array('moduleName' => $module), 'doc/module/toc'),
                 'doc/module/chapter',
-                array('moduleName' => $moduleName)
+                array('moduleName' => $module)
             );
         } catch (DocException $e) {
             throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
@@ -119,14 +151,13 @@ class Doc_ModuleController extends DocController
      */
     public function pdfAction()
     {
-        $moduleName = $this->getParam('moduleName');
-        $this->assertModuleEnabled($moduleName);
-        $moduleManager = Icinga::app()->getModuleManager();
-        return $this->renderPdf(
-            $moduleManager->getModuleDir($moduleName, '/doc'),
-            $moduleName,
+        $module = $this->getParam('moduleName');
+        $this->assertModuleEnabled($module);
+        $this->renderPdf(
+            $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
+            $module,
             'doc/module/chapter',
-            array('moduleName' => $moduleName)
+            array('moduleName' => $module)
         );
     }
 }
diff --git a/modules/doc/configuration.php b/modules/doc/configuration.php
index 87e5da77a..6e924e964 100644
--- a/modules/doc/configuration.php
+++ b/modules/doc/configuration.php
@@ -2,7 +2,7 @@
 // {{{ICINGA_LICENSE_HEADER}}}
 // {{{ICINGA_LICENSE_HEADER}}}
 
-/* @var $this \Icinga\Application\Modules\Module */
+/** @type $this \Icinga\Application\Modules\Module */
 
 $section = $this->menuSection($this->translate('Documentation'), array(
     'title'    => 'Documentation',
diff --git a/modules/doc/doc/1-module-documentation.md b/modules/doc/doc/1-module-documentation.md
new file mode 100644
index 000000000..edf20aac2
--- /dev/null
+++ b/modules/doc/doc/1-module-documentation.md
@@ -0,0 +1,67 @@
+# <a id="module-documentation"></a> Writing Module Documentation
+
+![Markdown](/img/doc/doc/markdown.png)
+
+Icinga Web 2 is capable of viewing your module's documentation, if the documentation is written in
+[Markdown](http://en.wikipedia.org/wiki/Markdown). Please refer to
+[Markdown Syntax Documentation](http://daringfireball.net/projects/markdown/syntax) for Markdown's formatting syntax.
+
+## <a id="location"></a> Where to Put Module Documentation?
+
+By default, your module's Markdown documentation files must be placed in the `doc` directory beneath your module's root
+directory, e.g.:
+
+    example-module/doc
+
+## <a id="chapters"></a> Chapters
+
+Each Markdown documentation file represents a chapter of your module's documentation. The first found heading inside
+each file is the chapter's title. The order of chapters is based on the case insensitive "Natural Order" of your files'
+names. <dfn>Natural Order</dfn> means that the file names are ordered in the way which seems natural to humans.
+It is best practice to prefix Markdown documentation file names with numbers to ensure that they appear in the correct
+order, e.g.:
+
+    1-about.md
+    2-installation.md
+    3-configuration.md
+
+## <a id="toc"></a> Table Of Contents
+
+The table of contents for your module's documentation is auto-generated based on all found headings inside each
+Markdown documentation file.
+
+## <a id="linking"></a> Linking Between Headings
+
+For linking between headings, place an anchor where you want to link to, e.g.:
+
+    # <a id="heading"></a> Heading
+
+Please note that anchors have to be unique across all your Markdown documentation files.
+
+Now you can reference the anchor either in the same or **in another** Markdown documentation file, e.g.:
+
+    This is a link to [Heading](#heading).
+
+Other tools support linking between headings by giving the filename plus the anchor to link to, e.g.:
+
+    This is a link to [About/Heading](1-about.md#heading.md)
+
+This syntax is also supported in Icinga Web 2.
+
+## <a id="images"></a> Including Images
+
+Images must placed in the `img` directory beneath your module's `public` directory, e.g.:
+
+    example-module/public/img/doc
+
+Module images can be accessed using the following URL:
+
+    {baseURL}/img/{moduleName}/{file} e.g. icingaweb/img/example-module/doc/example.png
+
+Markdown's image syntax is very similar to Markdown's link syntax, but prefixed with an exclamation mark, e.g.:
+
+    ![Alt text](http://path/to/img.png "Optional Title")
+
+URLs to images inside your Markdown documentation files must be specified without the base URL, e.g.:
+
+    ![Example](/img/example-module/doc/example.png)
diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php
index bc782953f..0d12f58df 100644
--- a/modules/doc/library/Doc/DocController.php
+++ b/modules/doc/library/Doc/DocController.php
@@ -28,7 +28,7 @@ class DocController extends ModuleActionController
             $urlParams
         );
         $this->view->title = $chapterId;
-        return $this->render('chapter', null, true);
+        $this->render('chapter', null, true);
     }
 
     /**
@@ -46,7 +46,7 @@ class DocController extends ModuleActionController
         $name = ucfirst($name);
         $this->view->docName = $name;
         $this->view->title = sprintf($this->translate('%s Documentation'), $name);
-        return $this->render('toc', null, true);
+        $this->render('toc', null, true);
     }
 
     /**
@@ -71,6 +71,6 @@ class DocController extends ModuleActionController
         );
         $this->view->docName = $name;
         $this->_request->setParam('format', 'pdf');
-        return $this->render('pdf', null, true);
+        $this->render('pdf', null, true);
     }
 }
diff --git a/modules/doc/library/Doc/DocIterator.php b/modules/doc/library/Doc/DocIterator.php
index 43a9c7727..3045b6309 100644
--- a/modules/doc/library/Doc/DocIterator.php
+++ b/modules/doc/library/Doc/DocIterator.php
@@ -9,6 +9,8 @@ use Countable;
 use IteratorAggregate;
 use RecursiveIteratorIterator;
 use RecursiveDirectoryIterator;
+use Icinga\File\NonEmptyFileIterator;
+use Icinga\File\FileExtensionFilterIterator;
 
 /**
  * Iterator over non-empty Markdown files ordered by the case insensitive "natural order" of file names
@@ -29,12 +31,14 @@ class DocIterator implements Countable, IteratorAggregate
      */
     public function __construct($path)
     {
-        $it = new RecursiveIteratorIterator(
+        $it = new FileExtensionFilterIterator(
             new NonEmptyFileIterator(
-                new MarkdownFileIterator(
-                    new RecursiveDirectoryIterator($path)
+                new RecursiveIteratorIterator(
+                    new RecursiveDirectoryIterator($path),
+                    RecursiveIteratorIterator::SELF_FIRST
                 )
-            )
+            ),
+            'md'
         );
         // Unfortunately we have no chance to sort the iterator
         $fileInfo = iterator_to_array($it);
diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php
index c63532dc1..6cfeca418 100644
--- a/modules/doc/library/Doc/DocParser.php
+++ b/modules/doc/library/Doc/DocParser.php
@@ -31,7 +31,7 @@ class DocParser
     /**
      * Create a new documentation parser for the given path
      *
-     * @param   string $path Path to the documentation
+     * @param   string $path        Path to the documentation
      *
      * @throws  DocException        If the documentation directory does not exist
      * @throws  NotReadableError    If the documentation directory is not readable
diff --git a/modules/doc/library/Doc/MarkdownFileIterator.php b/modules/doc/library/Doc/MarkdownFileIterator.php
deleted file mode 100644
index 6f317ce6a..000000000
--- a/modules/doc/library/Doc/MarkdownFileIterator.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-namespace Icinga\Module\Doc;
-
-use RecursiveFilterIterator;
-
-/**
- * Recursive iterator over Markdown files
- */
-class MarkdownFileIterator extends RecursiveFilterIterator
-{
-    /**
-     * Accept files with '.md' suffix
-     *
-     * @return bool Whether the current element of the iterator is acceptable
-     *              through this filter
-     */
-    public function accept()
-    {
-        $current = $this->getInnerIterator()->current();
-        /* @var $current \SplFileInfo */
-        if (! $current->isFile()) {
-            return false;
-        }
-        $filename = $current->getFilename();
-        $sfx = substr($filename, -3);
-        return $sfx === false ? false : strtolower($sfx) === '.md';
-    }
-}
diff --git a/modules/doc/library/Doc/NonEmptyFileIterator.php b/modules/doc/library/Doc/NonEmptyFileIterator.php
deleted file mode 100644
index 71bf5acfa..000000000
--- a/modules/doc/library/Doc/NonEmptyFileIterator.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}
-
-namespace Icinga\Module\Doc;
-
-use RecursiveFilterIterator;
-
-/**
- * Recursive iterator over non-empty files
- */
-class NonEmptyFileIterator extends RecursiveFilterIterator
-{
-    /**
-     * Accept non-empty files
-     *
-     * @return bool Whether the current element of the iterator is acceptable
-     *              through this filter
-     */
-    public function accept()
-    {
-        $current = $this->getInnerIterator()->current();
-        /* @var $current \SplFileInfo */
-        if (! $current->isFile()
-            || $current->getSize() === 0
-        ) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/modules/doc/library/Doc/SectionRenderer.php b/modules/doc/library/Doc/SectionRenderer.php
index 2fdaf8e90..f923783f6 100644
--- a/modules/doc/library/Doc/SectionRenderer.php
+++ b/modules/doc/library/Doc/SectionRenderer.php
@@ -232,7 +232,7 @@ class SectionRenderer extends Renderer
                 $html
             );
             $content[] = preg_replace_callback(
-                '/<a\s+(?P<attribs>[^>]*?\s+)?href="#(?P<fragment>[^"]+)"/',
+                '/<a\s+(?P<attribs>[^>]*?\s+)?href="(?:(?!http:\/\/)[^#]*)#(?P<fragment>[^"]+)"/',
                 array($callback, 'render'),
                 $html
             );
diff --git a/modules/doc/module.info b/modules/doc/module.info
index 2826d72de..1689fd940 100644
--- a/modules/doc/module.info
+++ b/modules/doc/module.info
@@ -1,4 +1,4 @@
 Module: doc
-Version: 2.0.0~alpha4
+Version: 2.0.0
 Description: Documentation module
  Extracts, shows and exports documentation for Icinga Web 2 and it's modules.
diff --git a/modules/doc/public/img/doc/markdown.png b/modules/doc/public/img/doc/markdown.png
new file mode 100644
index 000000000..93e729bc7
Binary files /dev/null and b/modules/doc/public/img/doc/markdown.png differ
diff --git a/modules/doc/run.php b/modules/doc/run.php
index 7392e4c22..31aff8ff0 100644
--- a/modules/doc/run.php
+++ b/modules/doc/run.php
@@ -47,4 +47,3 @@ $this->addRoute('doc/module/chapter', $docModuleChapter);
 $this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter);
 $this->addRoute('doc/module/toc', $docModuleToc);
 $this->addRoute('doc/module/pdf', $docModulePdf);
-
diff --git a/modules/monitoring/application/controllers/AlertsummaryController.php b/modules/monitoring/application/controllers/AlertsummaryController.php
index 75f0fc1fe..a4ef76b44 100644
--- a/modules/monitoring/application/controllers/AlertsummaryController.php
+++ b/modules/monitoring/application/controllers/AlertsummaryController.php
@@ -78,7 +78,9 @@ class Monitoring_AlertsummaryController extends Controller
             'notification',
             array(
                 'host',
+                'host_display_name',
                 'service',
+                'service_display_name',
                 'notification_output',
                 'notification_contact',
                 'notification_start_time',
@@ -193,11 +195,11 @@ class Monitoring_AlertsummaryController extends Controller
 
         $out = new stdClass();
         if ($yesterday === $today) {
-            $out->trend = 'unchanged';
+            $out->trend = $this->translate('unchanged');
         } elseif ($yesterday > $today) {
-            $out->trend = 'down';
+            $out->trend = $this->translate('down');
         } else {
-            $out->trend = 'up';
+            $out->trend = $this->translate('up');
         }
 
         if ($yesterday <= 0) {
@@ -342,10 +344,10 @@ class Monitoring_AlertsummaryController extends Controller
         $gridChart = new GridChart();
 
         $gridChart->alignTopLeft();
-        $gridChart->setAxisLabel('', mt('monitoring', 'Notifications'))
+        $gridChart->setAxisLabel($this->createPeriodDescription(), mt('monitoring', 'Notifications'))
             ->setXAxis(new StaticAxis())
-            ->setAxisMin(null, 0)
-            ->setYAxis(new LinearUnit(10));
+            ->setYAxis(new LinearUnit(10))
+            ->setAxisMin(null, 0);
 
         $interval = $this->getInterval();
 
@@ -429,11 +431,10 @@ class Monitoring_AlertsummaryController extends Controller
             $item[1] = $item[1]/60/60;
         }
 
-
         $gridChart->drawBars(
             array(
                 'label' => $this->translate('Notifications'),
-                'color' => '#049baf',
+                'color' => '#07C0D9',
                 'data'  =>  $notifications,
                 'showPoints' => true
             )
@@ -470,15 +471,15 @@ class Monitoring_AlertsummaryController extends Controller
         $gridChart = new GridChart();
 
         $gridChart->alignTopLeft();
-        $gridChart->setAxisLabel('', mt('monitoring', 'Notifications'))
+        $gridChart->setAxisLabel($this->createPeriodDescription(), mt('monitoring', 'Notifications'))
             ->setXAxis(new StaticAxis())
-            ->setAxisMin(null, 0)
-            ->setYAxis(new LinearUnit(10));
+            ->setYAxis(new LinearUnit(10))
+            ->setAxisMin(null, 0);
 
         $gridChart->drawBars(
             array(
                 'label' => $this->translate('Notifications'),
-                'color' => '#049baf',
+                'color' => '#07C0D9',
                 'data'  =>  $this->notificationData,
                 'showPoints' => true
             )
@@ -507,7 +508,9 @@ class Monitoring_AlertsummaryController extends Controller
             'notification',
             array(
                 'host',
+                'host_display_name',
                 'service',
+                'service_display_name',
                 'notification_output',
                 'notification_contact',
                 'notification_start_time',
@@ -554,7 +557,7 @@ class Monitoring_AlertsummaryController extends Controller
     {
         $format = '';
         if ($interval === '1d') {
-            $format = '%H:00:00';
+            $format = '%H:00';
         } elseif ($interval === '1w') {
             $format = '%Y-%m-%d';
         } elseif ($interval === '1m') {
@@ -623,4 +626,28 @@ class Monitoring_AlertsummaryController extends Controller
 
         return $interval;
     }
+
+    /**
+     * Create a human-readable description of the current interval size
+     *
+     * @return string   The description of the current interval size
+     */
+    private function createPeriodDescription()
+    {
+        $int = $this->getInterval();
+        switch ($int) {
+            case '1d':
+                return t('Hour');
+                break;
+            case '1w';
+                return t('Day');
+                break;
+            case '1m':
+                return t('Day');
+                break;
+            case '1y':
+                return t('Month');
+                break;
+        }
+    }
 }
diff --git a/modules/monitoring/application/controllers/ChartController.php b/modules/monitoring/application/controllers/ChartController.php
index 2024f83f4..757329bfe 100644
--- a/modules/monitoring/application/controllers/ChartController.php
+++ b/modules/monitoring/application/controllers/ChartController.php
@@ -6,6 +6,8 @@ use Icinga\Module\Monitoring\Controller;
 use Icinga\Chart\GridChart;
 use Icinga\Chart\PieChart;
 use Icinga\Chart\Unit\StaticAxis;
+use Icinga\Chart\Unit\LogarithmicUnit;
+use Icinga\Chart\Unit\LinearUnit;
 
 /**
  * Class Monitoring_CommandController
@@ -20,6 +22,95 @@ class Monitoring_ChartController extends Controller
         $this->view->compact = $this->_request->getParam('view') === 'compact';
     }
 
+    private function drawLogChart1()
+    {
+        $chart = new GridChart();
+        $chart->alignTopLeft();
+        $chart->setAxisLabel('X axis label', 'Y axis label')
+            ->setYAxis(new LogarithmicUnit());
+
+        for ($i = -15; $i < 15; $i++) {
+            $data1[] = array($i, -$i * rand(1, 10) * pow(2, rand(1, 2)));
+        }
+        for ($i = -15; $i < 15; $i++) {
+            $data2[] = array($i, 1000 + $i * rand(1, 35) * pow(2, rand(1, 2)));
+        }
+        for ($i = -15; $i < 15; $i++) {
+            $data3[] = array($i, $i * rand(1, 100) * pow(2, rand(1, 10)) - 1000);
+        }
+
+        $chart->drawLines(
+            array(
+                'label' => 'Random 1',
+                'color' => '#F56',
+                'data'  =>  $data1,
+                'showPoints' => true
+            )
+        );
+        $chart->drawLines(
+            array(
+                'label' => 'Random 2',
+                'color' => '#fa4',
+                'data'  =>  $data2,
+                'showPoints' => true
+            )
+        );
+        $chart->drawLines(
+            array(
+                'label' => 'Random 3',
+                'color' => '#4b7',
+                'data'  =>  $data3,
+                'showPoints' => true
+            )
+        );
+        return $chart;
+    }
+
+    private function drawLogChart2()
+    {
+        $chart = new GridChart();
+        $chart->alignTopLeft();
+        $chart->setAxisLabel('X axis label', 'Y axis label')
+            ->setYAxis(new LogarithmicUnit());
+
+        for ($i = -10; $i < 10; $i++) {
+            $sign = $i > 0 ?  1 :
+                   ($i < 0 ? -1 : 0);
+            $data[] = array($i, $sign * pow(10, abs($i)));
+        }
+        $chart->drawLines(
+            array(
+                'label' => 'f(x): sign(x) * 10^|x|',
+                'color' => '#F56',
+                'data'  =>  $data,
+                'showPoints' => true
+            )
+        );
+        return $chart;
+    }
+    private function drawLogChart3()
+    {
+        $chart = new GridChart();
+        $chart->alignTopLeft();
+        $chart->setAxisLabel('X axis label', 'Y axis label')
+            ->setYAxis(new LogarithmicUnit());
+
+        for ($i = -2; $i < 3; $i++) {
+            $sign = $i > 0 ?  1 :
+                ($i < 0 ? -1 : 0);
+            $data[] = array($i, $sign * pow(10, abs($i)));
+        }
+        $chart->drawLines(
+            array(
+                'label' => 'f(x): sign(x) * 10^|x|',
+                'color' => '#F56',
+                'data'  =>  $data,
+                'showPoints' => true
+            )
+        );
+        return $chart;
+    }
+
     public function testAction()
     {
         $this->chart = new GridChart();
@@ -28,7 +119,7 @@ class Monitoring_ChartController extends Controller
         $data1 = array();
         $data2 = array();
         $data3 = array();
-        for ($i = 0; $i < 25; $i++) {
+        for ($i = 0; $i < 50; $i++) {
             $data3[] = array('Label ' . $i, rand(0, 30));
         }
 
@@ -36,13 +127,13 @@ class Monitoring_ChartController extends Controller
         $this->chart->drawLines(
             array(
                 'label' => 'Nr of outtakes',
-                'color' => 'red',
+                'color' => '#F56',
                 'width' => '5',
 
                 'data'  => $data
             ), array(
                 'label' => 'Some line',
-                'color' => 'blue',
+                'color' => '#fa4',
                 'width' => '4',
 
                 'data'  =>  $data3,
@@ -52,8 +143,8 @@ class Monitoring_ChartController extends Controller
 */
         $this->chart->drawBars(
             array(
-                'label' => 'Some other line',
-                'color' => 'green',
+                'label' => 'A big amount of data',
+                'color' => '#4b7',
                 'data'  =>  $data3,
                 'showPoints' => true
             )
@@ -68,7 +159,11 @@ class Monitoring_ChartController extends Controller
             )
         );
 */
-        $this->view->svg = $this->chart;
+        $this->view->svgs = array();
+        $this->view->svgs[] = $this->drawLogChart1();
+        $this->view->svgs[] = $this->drawLogChart2();
+        $this->view->svgs[] = $this->drawLogChart3();
+        $this->view->svgs[] = $this->chart;
     }
 
     public function hostgroupAction()
@@ -185,18 +280,15 @@ class Monitoring_ChartController extends Controller
         $upBars = array();
         $downBars = array();
         $unreachableBars = array();
-        foreach ($query as $hostgroup) {
+        for ($i = 0; $i < 50; $i++) {
             $upBars[] = array(
-                $hostgroup->hostgroup,
-                $hostgroup->hosts_up
+                (string)$i, rand(1, 200), rand(1, 200)
             );
             $downBars[] = array(
-                $hostgroup->hostgroup,
-                $hostgroup->hosts_down_unhandled
+                (string)$i, rand(1, 200), rand(1, 200)
             );
             $unreachableBars[] = array(
-                $hostgroup->hostgroup,
-                $hostgroup->hosts_unreachable_unhandled
+                (string)$i, rand(1, 200), rand(1, 200)
             );
         }
         $tooltip = mt('monitoring', '<b>{title}:</b><br> {value} of {sum} hosts are {label}');
@@ -272,7 +364,14 @@ class Monitoring_ChartController extends Controller
                 (int) $query->hosts_unreachable_unhandled,
                 (int) $query->hosts_pending
             ),
-            'colors' => array('#44bb77', '#ff4444', '#ff0000', '#E066FF', '#f099FF', '#fefefe'),
+            'colors' => array(
+                '#44bb77',   // 'Ok'
+                '#ff4444',   // 'Warning'
+                '#ff0000',   // 'WarningHandled'
+                '#E066FF',
+                '#f099FF',
+                '#fefefe'
+            ),
             'labels'=> array(
                 (int) $query->hosts_up . mt('monitoring', ' Up Hosts'),
                 (int) $query->hosts_down_handled . mt('monitoring', ' Down Hosts (Handled)'),
diff --git a/modules/monitoring/application/controllers/CommandController.php b/modules/monitoring/application/controllers/CommandController.php
deleted file mode 100644
index d2615104a..000000000
--- a/modules/monitoring/application/controllers/CommandController.php
+++ /dev/null
@@ -1,1098 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-use Icinga\Application\Icinga;
-use Icinga\Application\Config;
-use Icinga\Application\Logger;
-use Icinga\Module\Monitoring\Forms\Command\DisableNotificationWithExpireForm;
-use Icinga\Module\Monitoring\Forms\Command\SingleArgumentCommandForm;
-use Icinga\Web\Form;
-use Icinga\Web\Url;
-use Icinga\Web\Notification;
-use Icinga\Module\Monitoring\Controller;
-use Icinga\Protocol\Commandpipe\CommandPipe;
-use Icinga\Exception\ConfigurationError;
-use Icinga\Exception\MissingParameterException;
-use Icinga\Module\Monitoring\Forms\Command\AcknowledgeForm;
-use Icinga\Module\Monitoring\Forms\Command\CommentForm;
-use Icinga\Module\Monitoring\Forms\Command\CommandForm;
-use Icinga\Module\Monitoring\Forms\Command\CustomNotificationForm;
-use Icinga\Module\Monitoring\Forms\Command\DelayNotificationForm;
-use Icinga\Module\Monitoring\Forms\Command\RescheduleNextCheckForm;
-use Icinga\Module\Monitoring\Forms\Command\ScheduleDowntimeForm;
-use Icinga\Module\Monitoring\Forms\Command\SubmitPassiveCheckResultForm;
-use Icinga\Exception\IcingaException;
-
-/**
- * Class Monitoring_CommandController
- *
- * Interface to send commands and display forms
- */
-class Monitoring_CommandController extends Controller
-{
-    const DEFAULT_VIEW_SCRIPT = 'renderform';
-
-    /**
-     * Command target
-     *
-     * @var CommandPipe
-     */
-    private $target;
-
-    /**
-     * Current form working on
-     *
-     * @var Form
-     */
-    private $form;
-
-    /**
-     * Setter for form
-     *
-     * @param CommandForm $form
-     */
-    public function setForm(CommandForm $form)
-    {
-        $this->form = $form;
-    }
-
-    /**
-     * Test if we have a valid form object
-     *
-     * @return bool
-     */
-    public function issetForm()
-    {
-        return $this->form !== null && ($this->form instanceof Form);
-    }
-
-    protected function addTitleTab($action)
-    {
-        $this->getTabs()->add($action, array(
-            'title' => ucfirst($action),
-            'url' => Url::fromRequest()
-        ))->activate($action);
-    }
-
-    /**
-     * Post dispatch method
-     *
-     * When we have a form put it into the view
-     */
-    public function postDispatch()
-    {
-
-        if ($this->issetForm()) {
-            if ($this->form->isSubmittedAndValid()) {
-                $this->_helper->viewRenderer->setNoRender(true);
-                $this->_helper->layout()->disableLayout();
-                $this->ignoreXhrBody();
-                if ($this->_request->getHeader('referer') && ! $this->getRequest()->isXmlHttpRequest()) {
-                    $this->redirect($this->_request->getHeader('referer'));
-                }
-            } else {
-                $this->view->form = $this->form;
-            }
-        }
-        parent::postDispatch();
-    }
-
-    /**
-     * Controller configuration
-     *
-     * @throws Icinga\Exception\ConfigurationError
-     */
-    public function init()
-    {
-        if ($this->_request->isPost()) {
-            $instance = $this->_request->getPost('instance');
-            $targetConfig = Config::module('monitoring', 'instances');
-            if ($instance) {
-                if ($targetConfig->get($instance)) {
-                    $this->target = new CommandPipe($targetConfig->get($instance));
-                } else {
-                    throw new ConfigurationError(
-                        $this->translate('Instance is not configured: %s'),
-                        $instance
-                    );
-                }
-            } else {
-                if ($targetConfig && $targetInfo = $targetConfig->current()) {
-                    // Take the very first section
-                    $this->target = new CommandPipe($targetInfo);
-                } else {
-                    throw new ConfigurationError($this->translate('No instances are configured yet'));
-                }
-            }
-        }
-
-        if ($this->getRequest()->getActionName() !== 'list') {
-            $this->_helper->viewRenderer->setRender(self::DEFAULT_VIEW_SCRIPT);
-        }
-
-        $this->view->objects = array();
-    }
-
-    /**
-     * Retrieve all existing targets for host- and service combination
-     *
-     * @param $hostOnly         Ignore the service parameters
-     *                          (for example when using commands that only make sense for hosts)
-     * @return array            Array of monitoring objects
-     * @throws Icinga\Exception\MissingParameterException
-     */
-    private function selectCommandTargets($hostOnly = false)
-    {
-        $query = null;
-
-        $fields = array(
-            'host_name',
-            'host_state'
-        );
-
-        try {
-            $hostname    =  $this->getParam('host', null);
-            $servicename =  $this->getParam('service', null);
-
-            if (!$hostname && !$servicename) {
-                throw new MissingParameterException('No target given for this command');
-            }
-
-            if ($servicename && !$hostOnly) {
-                $fields[] = 'service_description';
-                $query = $this->backend->select()
-                    ->from('serviceStatus', $fields)
-                    ->where('host', $hostname)
-                    ->where('service', $servicename);
-            } elseif ($hostname) {
-                $query = $this->backend->select()->from('hostStatus', $fields)->where('host', $hostname);
-            } else {
-                throw new MissingParameterException('hostOnly command got no hostname');
-            }
-            return $query->getQuery()->fetchAll();
-
-        } catch (\Exception $e) {
-            Logger::error(
-                "CommandController: SQL Query '%s' failed (message %s) ",
-                $query ? (string) $query->dump() : '--', $e->getMessage()
-            );
-            return array();
-        }
-    }
-
-    /**
-     * Convert other params into valid command structure
-     *
-     * @param   array   $supported  Array of supported parameter names
-     * @param   array   $params     Parameters from request
-     *
-     * @return  array               Return
-     */
-    private function selectOtherTargets(array $supported, array $params)
-    {
-        $others = array_diff_key($supported, array('host' => true, 'service' => true));
-        $otherParams = array_intersect_key($params, $others);
-        $out = array();
-
-        foreach ($otherParams as $name => $value) {
-            $data = new stdClass();
-            $data->{$name} = $value;
-            $out[] = $data;
-        }
-
-        return $out;
-    }
-
-    /**
-     * Displays a list of all commands
-     *
-     * This method uses reflection on the sourcecode to determine all *Action classes and return
-     * a list of them (ignoring the listAction)
-     */
-    public function listAction()
-    {
-        $reflection = new ReflectionObject($this);
-        $commands = array();
-        $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
-        foreach ($methods as $method) {
-            $name = $method->getName();
-            if ($name !== 'listAction' && preg_match('/Action$/', $name)) {
-                $commands[] = preg_replace('/Action$/', '', $name);
-            }
-        }
-        $this->view->commands = $commands;
-    }
-
-    /**
-     * Tell the controller that at least one of the parameters in $supported is required to be availabe
-     *
-     * @param  array    $supported      An array of properties to check for existence in the POST or GET parameter list
-     * @throws Exception                When non of the supported parameters is given
-     */
-    private function setSupportedParameters(array $supported)
-    {
-        $objects = array();
-
-        $supported = array_flip($supported);
-
-        $given = array_intersect_key($supported, $this->getRequest()->getParams());
-
-        if (empty($given)) {
-            throw new IcingaException(
-                'Missing parameter, supported: %s',
-                implode(', ', array_flip($supported))
-            );
-        }
-
-        if (isset($given['host'])) {
-            $objects = $this->selectCommandTargets(!in_array("service", $supported));
-            if (empty($objects)) {
-                throw new IcingaException('No objects found for your command');
-            }
-        }
-
-        $this->view->objects = $objects;
-    }
-
-    // ------------------------------------------------------------------------
-    // Commands for hosts / services
-    // ------------------------------------------------------------------------
-
-    /**
-     * Handle command disableactivechecks
-     */
-    public function disableactivechecksAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-
-        $form = new SingleArgumentCommandForm();
-
-        $form->setCommand(
-            'DISABLE_HOST_CHECK',
-            'DISABLE_SVC_CHECK'
-        );
-
-        $form->setGlobalCommands(
-            'STOP_EXECUTING_HOST_CHECKS',
-            'STOP_EXECUTING_SVC_CHECKS'
-        );
-
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Disable Active Checks'));
-
-        if ($form->provideGlobalCommand()) {
-            $form->addNote($this->translate('Disable active checks on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Disable active checks for this object.'));
-        }
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, active checks will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command  enableactivechecks
-     */
-    public function enableactivechecksAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setCommand('ENABLE_HOST_CHECK', 'ENABLE_SVC_CHECK');
-        $form->setGlobalCommands('START_EXECUTING_HOST_CHECKS', 'START_EXECUTING_SVC_CHECKS');
-
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Enable Active Checks'));
-        if ($form->provideGlobalCommand()) {
-            $form->addNote($this->translate('Enable active checks on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Enable active checks for this object.'));
-        }
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, active checks will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command  reschedulenextcheck
-     */
-    public function reschedulenextcheckAction()
-    {
-        $this->addTitleTab('Reschedule Next Check');
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new RescheduleNextCheckForm();
-        $form->setRequest($this->getRequest());
-        $form->setConfiguration(Config::app());
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, check will be rescheduled'));
-        }
-    }
-
-    /**
-     * Handle command  submitpassivecheckresult
-     */
-    public function submitpassivecheckresultAction()
-    {
-        $this->setSupportedParameters(array('host', 'service'));
-        $type = SubmitPassiveCheckResultForm::TYPE_SERVICE;
-        if ($this->getParam('service', null) === null) {
-            $type = SubmitPassiveCheckResultForm::TYPE_HOST;
-        }
-
-        $form = new SubmitPassiveCheckResultForm();
-        $form->setRequest($this->getRequest());
-        $form->setType($type);
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Passive check result has been submitted'));
-        }
-    }
-
-    /**
-     * Handle command stopobsessing
-     */
-    public function stopobsessingAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Stop obsessing'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Disable obsessing on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Stop obsessing over this object.'));
-        }
-
-        $form->setCommand(
-            'STOP_OBSESSING_OVER_HOST',
-            'STOP_OBSESSING_OVER_SVC'
-        );
-
-        $form->setGlobalCommands(
-            'STOP_OBSESSING_OVER_HOST_CHECKS',
-            'STOP_OBSESSING_OVER_SVC_CHECKS'
-        );
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, obsessing will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command startobsessing
-     */
-    public function startobsessingAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Start obsessing'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Enable obsessing on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Start obsessing over this object.'));
-        }
-
-        $form->setCommand(
-            'START_OBSESSING_OVER_HOST',
-            'START_OBSESSING_OVER_SVC'
-        );
-
-        $form->setGlobalCommands(
-            'START_OBSESSING_OVER_HOST_CHECKS',
-            'START_OBSESSING_OVER_SVC_CHECKS'
-        );
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, obsessing will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command stopacceptingpassivechecks
-     */
-    public function stopacceptingpassivechecksAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Stop Accepting Passive Checks'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Disable passive checks on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Passive checks for this object will be omitted.'));
-        }
-
-        $form->setCommand(
-            'DISABLE_PASSIVE_HOST_CHECKS',
-            'DISABLE_PASSIVE_SVC_CHECKS'
-        );
-
-        $form->setGlobalCommands(
-            'STOP_ACCEPTING_PASSIVE_HOST_CHECKS',
-            'STOP_ACCEPTING_PASSIVE_SVC_CHECKS'
-        );
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, passive check results will be refused'));
-        }
-    }
-
-    /**
-     * Handle command startacceptingpassivechecks
-     */
-    public function startacceptingpassivechecksAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Start Accepting Passive Checks'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Enable passive checks on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Passive checks for this object will be accepted.'));
-        }
-
-        $form->setCommand(
-            'ENABLE_PASSIVE_HOST_CHECKS',
-            'ENABLE_PASSIVE_SVC_CHECKS'
-        );
-
-        $form->setGlobalCommands(
-            'START_ACCEPTING_PASSIVE_HOST_CHECKS',
-            'START_ACCEPTING_PASSIVE_SVC_CHECKS'
-        );
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, passive check results will be accepted'));
-        }
-    }
-
-    /**
-     * Disable notifications with expiration
-     *
-     * This is a global command only
-     */
-    public function disablenotificationswithexpireAction()
-    {
-        $this->setParam('global', 1);
-        $form = new DisableNotificationWithExpireForm();
-        $form->setRequest($this->_request);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, notifications will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command disablenotifications
-     */
-    public function disablenotificationsAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-
-        $form->setSubmitLabel($this->translate('Disable Notifications'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Disable notifications on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Notifications for this object will be disabled.'));
-        }
-
-        $form->setCommand('DISABLE_HOST_NOTIFICATIONS', 'DISABLE_SVC_NOTIFICATIONS');
-        $form->setGlobalCommands('DISABLE_NOTIFICATIONS');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, notifications will be disabled'));
-        }
-
-    }
-
-    /**
-     * Handle command enablenotifications
-     */
-    public function enablenotificationsAction()
-    {
-        $this->addTitleTab('Enable Notifications');
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-
-        $form->setSubmitLabel($this->translate('Enable Notifications'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Enable notifications on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Notifications for this object will be enabled.'));
-        }
-
-        $form->setCommand('ENABLE_HOST_NOTIFICATIONS', 'ENABLE_SVC_NOTIFICATIONS');
-        $form->setGlobalCommands('ENABLE_NOTIFICATIONS');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, notifications will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command sendcustomnotification
-     */
-    public function sendcustomnotificationAction()
-    {
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new CustomNotificationForm();
-        $form->setRequest($this->getRequest());
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Custom notification has been sent'));
-        }
-    }
-
-    /**
-     * Handle command scheduledowntime
-     */
-    public function scheduledowntimeAction()
-    {
-        $this->addTitleTab('Schedule Downtime');
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new ScheduleDowntimeForm();
-        $form->setRequest($this->getRequest());
-        $form->setConfiguration(Config::app());
-        $form->setWithChildren(false);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Downtime scheduling requested'));
-        }
-    }
-
-    /**
-     * Handle command scheduledowntimeswithchildren
-     */
-    public function scheduledowntimeswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new ScheduleDowntimeForm();
-        $form->setRequest($this->getRequest());
-        $form->setConfiguration(Config::app());
-        $form->setWithChildren(true);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Downtime scheduling requested'));
-        }
-    }
-
-    /**
-     * Handle command removedowntimeswithchildren
-     */
-    public function removedowntimeswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Remove Downtime(s)'));
-        $form->addNote($this->translate('Remove downtime(s) from this host and its services.'));
-        $form->setCommand('DEL_DOWNTIME_BY_HOST_NAME', 'DEL_DOWNTIME_BY_HOST_NAME');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Downtime removal requested'));
-        }
-    }
-
-    /**
-     * Handle command disablenotificationswithchildren
-     */
-    public function disablenotificationswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Disable Notifications'));
-        $form->addNote($this->translate('Notifications for this host and its services will be disabled.'));
-        $form->setCommand('DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            $form->setCommand('DISABLE_HOST_NOTIFICATIONS', 'DISABLE_SVC_NOTIFICATIONS');
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, notifications will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command enablenotificationswithchildren
-     */
-    public function enablenotificationswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Enable Notifications'));
-        $form->addNote($this->translate('Notifications for this host and its services will be enabled.'));
-        $form->setCommand('ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            $form->setCommand('ENABLE_HOST_NOTIFICATIONS', 'ENABLE_SVC_NOTIFICATIONS');
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, notifications will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command reschedulenextcheckwithchildren
-     */
-    public function reschedulenextcheckwithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new RescheduleNextCheckForm();
-        $form->setRequest($this->getRequest());
-        $form->setConfiguration(Config::app());
-        $form->setWithChildren(true);
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, checks will be rescheduled'));
-        }
-    }
-
-    /**
-     * Handle command disableactivecheckswithchildren
-     */
-    public function disableactivecheckswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Disable Active Checks'));
-        $form->addNote($this->translate('Disable active checks for this host and its services.'));
-        $form->setCommand('DISABLE_HOST_CHECK');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            // @TODO(mh): Missing child command
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, active checks will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command enableactivecheckswithchildren
-     */
-    public function enableactivecheckswithchildrenAction()
-    {
-        $this->setSupportedParameters(array('host'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Enable Active Checks'));
-        $form->addNote($this->translate('Enable active checks for this host and its services.'));
-        $form->setCommand('ENABLE_HOST_CHECK');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            // @TODO(mh): Missing child command
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, active checks will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command disableeventhandler
-     */
-    public function disableeventhandlerAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Disable Event Handler'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Disable event handler for the whole system.'));
-        } else {
-            $form->addNote($this->translate('Disable event handler for this object.'));
-        }
-
-        $form->setCommand(
-            'DISABLE_HOST_EVENT_HANDLER',
-            'DISABLE_SVC_EVENT_HANDLER'
-        );
-
-        $form->setGlobalCommands('DISABLE_EVENT_HANDLERS');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, event handlers will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command enableeventhandler
-     */
-    public function enableeventhandlerAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Enable Event Handler'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Enable event handlers on the whole system.'));
-        } else {
-            $form->addNote($this->translate('Enable event handler for this object.'));
-        }
-
-        $form->setCommand(
-            'ENABLE_HOST_EVENT_HANDLER',
-            'ENABLE_SVC_EVENT_HANDLER'
-        );
-
-        $form->setGlobalCommands('ENABLE_EVENT_HANDLERS');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, event handlers will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command disableflapdetection
-     */
-    public function disableflapdetectionAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Disable Flapping Detection'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Disable flapping detection on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Disable flapping detection for this object.'));
-        }
-
-        $form->setCommand(
-            'DISABLE_HOST_FLAP_DETECTION',
-            'DISABLE_SVC_FLAP_DETECTION'
-        );
-
-        $form->setGlobalCommands(
-            'DISABLE_FLAP_DETECTION'
-        );
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, flap detection will be disabled'));
-        }
-    }
-
-    /**
-     * Handle command enableflapdetection
-     */
-    public function enableflapdetectionAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'global'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Enable Flapping Detection'));
-
-        if ($form->provideGlobalCommand() === true) {
-            $form->addNote($this->translate('Enable flapping detection on a program-wide basis.'));
-        } else {
-            $form->addNote($this->translate('Enable flapping detection for this object.'));
-        }
-
-        $form->setCommand(
-            'ENABLE_HOST_FLAP_DETECTION',
-            'ENABLE_SVC_FLAP_DETECTION'
-        );
-
-        $form->setGlobalCommands(
-            'ENABLE_FLAP_DETECTION'
-        );
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, flap detection will be enabled'));
-        }
-    }
-
-    /**
-     * Handle command addcomment
-     */
-    public function addcommentAction()
-    {
-        $this->addTitleTab('Add comment');
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new CommentForm();
-        $form->setRequest($this->_request);
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Your new comment has been submitted'));
-        }
-    }
-
-    /**
-     * Remove a single comment
-     */
-    public function removecommentAction()
-    {
-        $this->addTitleTab('Remove Comment');
-        $this->setSupportedParameters(array('commentid', 'host', 'service'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->_request);
-        $form->setCommand('DEL_HOST_COMMENT', 'DEL_SVC_COMMENT');
-        $form->setParameterName('commentid');
-        $form->setSubmitLabel($this->translate('Remove comment'));
-        $form->setObjectIgnoreFlag(true);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Comment removal has been requested'));
-        }
-    }
-
-    /**
-     * Handle command resetattributes
-     */
-    public function resetattributesAction()
-    {
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Reset Attributes'));
-        $form->addNote($this->translate('Reset modified attributes to its default.'));
-        $form->setCommand('CHANGE_HOST_MODATTR', 'CHANGE_SVC_MODATTR');
-        $form->setParameterValue(0);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-        }
-    }
-
-    /**
-     * Handle command acknowledgeproblem
-     */
-    public function acknowledgeproblemAction()
-    {
-        $this->addTitleTab('Acknowledge Problem');
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new AcknowledgeForm();
-        $form->setRequest($this->getRequest());
-        $form->setConfiguration(Config::app());
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Acknowledgement has been sent'));
-        }
-
-        $this->setForm($form);
-    }
-
-    /**
-     * Handle command removeacknowledgement
-     */
-    public function removeacknowledgementAction()
-    {
-        $this->addTitleTab('Remove Acknowledgement');
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-        $form->setSubmitLabel($this->translate('Remove Problem Acknowledgement'));
-        $form->addNote($this->translate('Remove problem acknowledgement for this object.'));
-        $form->setCommand('REMOVE_HOST_ACKNOWLEDGEMENT', 'REMOVE_SVC_ACKNOWLEDGEMENT');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Acknowledgement removal has been requested'));
-        }
-    }
-
-    /**
-     * Handle command delaynotification
-     */
-    public function delaynotificationAction()
-    {
-        $this->setSupportedParameters(array('host', 'service'));
-        $form = new DelayNotificationForm();
-        $form->setRequest($this->getRequest());
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Notification delay has been requested'));
-        }
-    }
-
-    /**
-     * Handle command removedowntime
-     */
-    public function removedowntimeAction()
-    {
-        $this->setSupportedParameters(array('host', 'service', 'downtimeid'));
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->getRequest());
-
-        $form->setSubmitLabel($this->translate('Delete Downtime'));
-        $form->setParameterName('downtimeid');
-        $form->addNote($this->translate('Delete a single downtime with the id shown above'));
-        $form->setCommand('DEL_HOST_DOWNTIME', 'DEL_SVC_DOWNTIME');
-        $form->setObjectIgnoreFlag(true);
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Downtime removal has been requested'));
-        }
-    }
-
-    /**
-     * Shutdown the icinga process
-     */
-    public function shutdownprocessAction()
-    {
-        $this->setParam('global', '1');
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->_request);
-
-        $form->setSubmitLabel($this->translate('Shutdown monitoring process'));
-        $form->addNote($this->translate('Stop monitoring instance. You have to start it again from command line.'));
-        $form->setGlobalCommands('SHUTDOWN_PROCESS');
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, process will shut down'));
-        }
-    }
-
-    /**
-     * Restart the icinga process
-     */
-    public function restartprocessAction()
-    {
-        $this->setParam('global', '1');
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->_request);
-
-        $form->setSubmitLabel($this->translate('Restart monitoring process'));
-        $form->addNote($this->translate('Restart the monitoring process.'));
-        $form->setGlobalCommands('RESTART_PROCESS');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, monitoring process will restart now'));
-        }
-    }
-
-    /**
-     * Disable processing of performance data
-     */
-    public function disableperformancedataAction()
-    {
-        $this->setParam('global', 1);
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->_request);
-
-        $form->setSubmitLabel($this->translate('Disable Performance Data'));
-        $form->addNote($this->translate('Disable processing of performance data on a program-wide basis.'));
-
-        $form->setGlobalCommands('DISABLE_PERFORMANCE_DATA');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, performance data processing will be disabled'));
-        }
-    }
-
-    /**
-     * Enable processing of performance data
-     */
-    public function enableperformancedataAction()
-    {
-        $this->setParam('global', 1);
-        $form = new SingleArgumentCommandForm();
-        $form->setRequest($this->_request);
-
-        $form->setSubmitLabel($this->translate('Enable Performance Data'));
-        $form->addNote($this->translate('Enable processing of performance data on a program-wide basis.'));
-
-        $form->setGlobalCommands('ENABLE_PERFORMANCE_DATA');
-
-        $this->setForm($form);
-
-        if ($form->IsSubmittedAndValid() === true) {
-            $this->target->sendCommand($form->createCommand(), $this->view->objects);
-            Notification::success($this->translate('Command has been sent, performance data processing will be enabled'));
-        }
-    }
-}
diff --git a/modules/monitoring/application/controllers/HostController.php b/modules/monitoring/application/controllers/HostController.php
index ab62c3756..4eccb8899 100644
--- a/modules/monitoring/application/controllers/HostController.php
+++ b/modules/monitoring/application/controllers/HostController.php
@@ -26,20 +26,15 @@ class Monitoring_HostController extends MonitoredObjectController
     public function init()
     {
         $host = new Host($this->backend, $this->params->get('host'));
+
+        $this->applyRestriction('monitoring/hosts/filter', $host);
+
         if ($host->fetch() === false) {
             throw new Zend_Controller_Action_Exception($this->translate('Host not found'));
         }
         $this->object = $host;
         $this->createTabs();
-    }
-
-    /**
-     * Show a host
-     */
-    public function showAction()
-    {
         $this->getTabs()->activate('host');
-        parent::showAction();
     }
 
     /**
@@ -47,6 +42,8 @@ class Monitoring_HostController extends MonitoredObjectController
      */
     public function acknowledgeProblemAction()
     {
+        $this->assertPermission('monitoring/command/acknowledge-problem');
+
         $this->view->title = $this->translate('Acknowledge Host Problem');
         $this->handleCommandForm(new AcknowledgeProblemCommandForm());
     }
@@ -56,6 +53,8 @@ class Monitoring_HostController extends MonitoredObjectController
      */
     public function addCommentAction()
     {
+        $this->assertPermission('monitoring/command/comment/add');
+
         $this->view->title = $this->translate('Add Host Comment');
         $this->handleCommandForm(new AddCommentCommandForm());
     }
@@ -65,6 +64,8 @@ class Monitoring_HostController extends MonitoredObjectController
      */
     public function rescheduleCheckAction()
     {
+        $this->assertPermission('monitoring/command/schedule-check');
+
         $this->view->title = $this->translate('Reschedule Host Check');
         $this->handleCommandForm(new ScheduleHostCheckCommandForm());
     }
@@ -74,6 +75,8 @@ class Monitoring_HostController extends MonitoredObjectController
      */
     public function scheduleDowntimeAction()
     {
+        $this->assertPermission('monitoring/command/downtime/schedule');
+
         $this->view->title = $this->translate('Schedule Host Downtime');
         $this->handleCommandForm(new ScheduleHostDowntimeCommandForm());
     }
@@ -83,6 +86,8 @@ class Monitoring_HostController extends MonitoredObjectController
      */
     public function processCheckResultAction()
     {
+        $this->assertPermission('monitoring/command/process-check-result');
+
         $this->view->title = $this->translate('Submit Passive Host Check Result');
         $this->handleCommandForm(new ProcessCheckResultCommandForm());
     }
diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php
index 4944cc237..869be92d8 100644
--- a/modules/monitoring/application/controllers/HostsController.php
+++ b/modules/monitoring/application/controllers/HostsController.php
@@ -72,8 +72,10 @@ class Monitoring_HostsController extends Controller
             'host_obsessing'*/
         ));
         $unhandledObjects = array();
+        $unhandledFilterExpressions = array();
         $acknowledgedObjects = array();
         $objectsInDowntime = array();
+        $downtimeFilterExpressions = array();
         $hostStates = array(
             Host::getStateText(Host::STATE_UP) => 0,
             Host::getStateText(Host::STATE_DOWN) => 0,
@@ -81,15 +83,17 @@ class Monitoring_HostsController extends Controller
             Host::getStateText(Host::STATE_PENDING) => 0,
         );
         foreach ($this->hostList as $host) {
-            /** @var Service $host */
+            /** @var Host $host */
             if ((bool) $host->problem === true && (bool) $host->handled === false) {
                 $unhandledObjects[] = $host;
+                $unhandledFilterExpressions[] = Filter::where('host', $host->getName());
             }
             if ((bool) $host->acknowledged === true) {
                 $acknowledgedObjects[] = $host;
             }
             if ((bool) $host->in_downtime === true) {
                 $objectsInDowntime[] = $host;
+                $downtimeFilterExpressions[] = Filter::where('downtime_host', $host->getName());
             }
             ++$hostStates[$host::getStateText($host->state)];
         }
@@ -108,16 +112,15 @@ class Monitoring_HostsController extends Controller
         $this->view->hostStates = $hostStates;
         $this->view->objects = $this->hostList;
         $this->view->unhandledObjects = $unhandledObjects;
-        $this->view->acknowledgeUnhandledLink = Url::fromRequest()
-            ->setPath('monitoring/hosts/acknowledge-problem')
-            ->addParams(array('host_problem' => 1, 'host_handled' => 0));
-        $this->view->downtimeUnhandledLink = Url::fromRequest()
-            ->setPath('monitoring/hosts/schedule-downtime')
-            ->addParams(array('host_problem' => 1, 'host_handled' => 0));
+        $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString();
+        $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/hosts/acknowledge-problem')
+            ->setQueryString($unhandledFilterQueryString);
+        $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/hosts/schedule-downtime')
+            ->setQueryString($unhandledFilterQueryString);
         $this->view->acknowledgedObjects = $acknowledgedObjects;
         $this->view->objectsInDowntime = $objectsInDowntime;
-        $this->view->inDowntimeLink = Url::fromRequest()
-            ->setPath('monitoring/list/downtimes');
+        $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes')
+            ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString());
         $this->view->havingCommentsLink = Url::fromRequest()
             ->setPath('monitoring/list/comments');
         $this->view->hostStatesPieChart = $this->createPieChart(
@@ -131,10 +134,9 @@ class Monitoring_HostsController extends Controller
     {
         $chart = new InlinePie(array_values($states), $title, $colors);
         return $chart
-            ->setLabel(array_map('strtoupper', array_keys($states)))
-            ->setHeight(100)
-            ->setWidth(100)
-            ->setTitle($title);
+            ->setSize(75)
+            ->setTitle('')
+            ->setSparklineClass('sparkline-multi');
     }
 
     /**
diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php
index 4f92a25b1..faaea713a 100644
--- a/modules/monitoring/application/controllers/ListController.php
+++ b/modules/monitoring/application/controllers/ListController.php
@@ -1,6 +1,4 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 use Icinga\Module\Monitoring\Controller;
 use Icinga\Module\Monitoring\Backend;
@@ -12,13 +10,9 @@ use Icinga\Web\Widget\Tabextension\DashboardAction;
 use Icinga\Web\Widget\Tabextension\OutputFormat;
 use Icinga\Web\Widget\Tabs;
 use Icinga\Web\Widget\SortBox;
-use Icinga\Web\Widget\FilterBox;
-use Icinga\Web\Widget\Chart\HistoryColorGrid;
 use Icinga\Data\Filter\Filter;
 use Icinga\Web\Widget;
-use Icinga\Module\Monitoring\Web\Widget\SelectBox;
 use Icinga\Module\Monitoring\Forms\StatehistoryForm;
-use Icinga\Module\Monitoring\Forms\EventOverviewForm;
 
 class Monitoring_ListController extends Controller
 {
@@ -97,12 +91,10 @@ class Monitoring_ListController extends Controller
         }
 
         // Handle soft and hard states
-        $stateType = $this->params->shift('stateType', 'soft');
-        if ($stateType == 'hard') {
+        if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') {
             $stateColumn = 'host_hard_state';
             $stateChangeColumn = 'host_last_hard_state_change';
         } else {
-            $stateType = 'soft';
             $stateColumn = 'host_state';
             $stateChangeColumn = 'host_last_state_change';
         }
@@ -112,6 +104,7 @@ class Monitoring_ListController extends Controller
         $query = $this->backend->select()->from('hostStatus', array_merge(array(
             'host_icon_image',
             'host_name',
+            'host_display_name',
             'host_state' => $stateColumn,
             'host_address',
             'host_acknowledged',
@@ -138,13 +131,14 @@ class Monitoring_ListController extends Controller
 
         $this->filterQuery($query);
 
+        $this->applyRestriction('monitoring/hosts/filter', $query);
+
         $this->setupSortControl(array(
-            'host_last_check'   => $this->translate('Last Check'),
             'host_severity'     => $this->translate('Severity'),
-            'host_name'         => $this->translate('Hostname'),
-            'host_address'      => $this->translate('Address'),
             'host_state'        => $this->translate('Current State'),
-            'host_state'        => $this->translate('Hard State')
+            'host_display_name' => $this->translate('Hostname'),
+            'host_address'      => $this->translate('Address'),
+            'host_last_check'   => $this->translate('Last Check')
         ));
         $this->view->hosts = $query->paginate();
 
@@ -171,14 +165,12 @@ class Monitoring_ListController extends Controller
         }
 
         // Handle soft and hard states
-        $stateType = $this->params->shift('stateType', 'soft');
-        if ($stateType == 'hard') {
+        if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') {
             $stateColumn = 'service_hard_state';
             $stateChangeColumn = 'service_last_hard_state_change';
         } else {
             $stateColumn = 'service_state';
             $stateChangeColumn = 'service_last_state_change';
-            $stateType = 'soft';
         }
 
         $this->addTitleTab('services', $this->translate('Services'));
@@ -192,6 +184,7 @@ class Monitoring_ListController extends Controller
 
         $columns = array_merge(array(
             'host_name',
+            'host_display_name',
             'host_state',
             'host_state_type',
             'host_last_state_change',
@@ -227,15 +220,17 @@ class Monitoring_ListController extends Controller
         $query = $this->backend->select()->from('serviceStatus', $columns);
 
         $this->filterQuery($query);
+
+        $this->applyRestriction('monitoring/services/filter', $query);
+
         $this->setupSortControl(array(
-            'service_last_check'    => $this->translate('Last Service Check'),
-            'service_severity'      => $this->translate('Severity'),
+            'service_severity'      => $this->translate('Service Severity'),
             'service_state'         => $this->translate('Current Service State'),
-            'service_description'   => $this->translate('Service Name'),
-            'service_state_type'    => $this->translate('Hard State'),
+            'service_display_name'  => $this->translate('Service Name'),
+            'service_last_check'    => $this->translate('Last Service Check'),
             'host_severity'         => $this->translate('Host Severity'),
             'host_state'            => $this->translate('Current Host State'),
-            'host_name'             => $this->translate('Host Name'),
+            'host_display_name'     => $this->translate('Hostname'),
             'host_address'          => $this->translate('Host Address'),
             'host_last_check'       => $this->translate('Last Host Check')
         ));
@@ -295,26 +290,31 @@ class Monitoring_ListController extends Controller
             'host'            => 'downtime_host',
             'service'         => 'downtime_service',
             'host_state'      => 'downtime_host_state',
-            'service_state'   => 'downtime_service_state'
-        ))->order('downtime_is_in_effect', 'DESC')
-          ->order('downtime_scheduled_start', 'DESC');
+            'service_state'   => 'downtime_service_state',
+            'host_display_name',
+            'service_display_name'
+        ));
 
         $this->filterQuery($query);
 
         $this->setupSortControl(array(
-            'downtime_is_in_effect'    => $this->translate('Is In Effect'),
-            'downtime_host'            => $this->translate('Host / Service'),
-            'downtime_entry_time'      => $this->translate('Entry Time'),
-            'downtime_author'          => $this->translate('Author'),
-            'downtime_start'           => $this->translate('Start Time'),
-            'downtime_start'           => $this->translate('End Time'),
-            'downtime_scheduled_start' => $this->translate('Scheduled Start'),
-            'downtime_scheduled_end'   => $this->translate('Scheduled End'),
-            'downtime_duration'        => $this->translate('Duration'),
+            'downtime_is_in_effect'     => $this->translate('Is In Effect'),
+            'host_display_name'         => $this->translate('Host'),
+            'service_display_name'      => $this->translate('Service'),
+            'downtime_entry_time'       => $this->translate('Entry Time'),
+            'downtime_author'           => $this->translate('Author'),
+            'downtime_start'            => $this->translate('Start Time'),
+            'downtime_end'              => $this->translate('End Time'),
+            'downtime_scheduled_start'  => $this->translate('Scheduled Start'),
+            'downtime_scheduled_end'    => $this->translate('Scheduled End'),
+            'downtime_duration'         => $this->translate('Duration')
         ));
 
         $this->view->downtimes = $query->paginate();
-        $this->view->delDowntimeForm = new DeleteDowntimeCommandForm();
+
+        if ($this->Auth()->hasPermission('monitoring/command/downtime/delete')) {
+            $this->view->delDowntimeForm = new DeleteDowntimeCommandForm();
+        }
     }
 
     /**
@@ -333,7 +333,9 @@ class Monitoring_ListController extends Controller
             'notification_output',
             'notification_contact',
             'notification_start_time',
-            'notification_state'
+            'notification_state',
+            'host_display_name',
+            'service_display_name'
         ));
         $this->filterQuery($query);
         $this->view->notifications = $query->paginate();
@@ -471,20 +473,26 @@ class Monitoring_ListController extends Controller
             'persistent' => 'comment_is_persistent',
             'expiration' => 'comment_expiration',
             'host'       => 'comment_host',
-            'service'    => 'comment_service'
+            'service'    => 'comment_service',
+            'host_display_name',
+            'service_display_name'
         ));
         $this->filterQuery($query);
         $this->view->comments = $query->paginate();
 
         $this->setupSortControl(
             array(
-                'comment_timestamp'  => $this->translate('Comment Timestamp'),
-                'comment_host'       => $this->translate('Host / Service'),
-                'comment_type'       => $this->translate('Comment Type'),
-                'comment_expiration' => $this->translate('Expiration'),
+                'comment_timestamp'     => $this->translate('Comment Timestamp'),
+                'host_display_name'     => $this->translate('Host'),
+                'service_display_name'  => $this->translate('Service'),
+                'comment_type'          => $this->translate('Comment Type'),
+                'comment_expiration'    => $this->translate('Expiration')
             )
         );
-        $this->view->delCommentForm = new DeleteCommentCommandForm();
+
+        if ($this->Auth()->hasPermission('monitoring/command/comment/delete')) {
+            $this->view->delCommentForm = new DeleteCommentCommandForm();
+        }
     }
 
     public function servicegroupsAction()
@@ -496,6 +504,7 @@ class Monitoring_ListController extends Controller
         $this->setAutorefreshInterval(12);
         $query = $this->backend->select()->from('groupsummary', array(
             'servicegroup',
+            'servicegroup_alias',
             'hosts_up',
             'hosts_unreachable_handled',
             'hosts_unreachable_unhandled',
@@ -519,18 +528,20 @@ class Monitoring_ListController extends Controller
             'services_critical_last_state_change_unhandled',
             'services_unknown_last_state_change_unhandled',
             'services_total'
-        ));
+        ))->order('services_severity')->order('servicegroup_alias');
+        // TODO(el): Can't default to the sort rules of the data view because it's meant for both host groups and
+        // service groups. We should separate them.
         $this->filterQuery($query);
         $this->view->servicegroups = $query->paginate();
         $this->setupSortControl(array(
-            'services_severity' => $this->translate('Severity'),
-            'servicegroup'      => $this->translate('Service Group Name'),
-            'services_total'    => $this->translate('Total Services'),
-            'services_ok'       => $this->translate('Services OK'),
-            'services_unknown'  => $this->translate('Services UNKNOWN'),
-            'services_critical' => $this->translate('Services CRITICAL'),
-            'services_warning'  => $this->translate('Services WARNING'),
-            'services_pending'  => $this->translate('Services PENDING')
+            'services_severity'     => $this->translate('Severity'),
+            'servicegroup_alias'    => $this->translate('Service Group Name'),
+            'services_total'        => $this->translate('Total Services'),
+            'services_ok'           => $this->translate('Services OK'),
+            'services_unknown'      => $this->translate('Services UNKNOWN'),
+            'services_critical'     => $this->translate('Services CRITICAL'),
+            'services_warning'      => $this->translate('Services WARNING'),
+            'services_pending'      => $this->translate('Services PENDING')
         ));
     }
 
@@ -543,6 +554,7 @@ class Monitoring_ListController extends Controller
         $this->setAutorefreshInterval(12);
         $query = $this->backend->select()->from('groupsummary', array(
             'hostgroup',
+            'hostgroup_alias',
             'hosts_up',
             'hosts_unreachable_handled',
             'hosts_unreachable_unhandled',
@@ -566,12 +578,14 @@ class Monitoring_ListController extends Controller
             'services_critical_last_state_change_unhandled',
             'services_unknown_last_state_change_unhandled',
             'services_total'
-        ));
+        ))->order('services_severity')->order('hostgroup_alias');
+        // TODO(el): Can't default to the sort rules of the data view because it's meant for both host groups and
+        // service groups. We should separate them.
         $this->filterQuery($query);
         $this->view->hostgroups = $query->paginate();
         $this->setupSortControl(array(
             'services_severity' => $this->translate('Severity'),
-            'hostgroup'         => $this->translate('Host Group Name'),
+            'hostgroup_alias'   => $this->translate('Host Group Name'),
             'services_total'    => $this->translate('Total Services'),
             'services_ok'       => $this->translate('Services OK'),
             'services_unknown'  => $this->translate('Services UNKNOWN'),
@@ -590,7 +604,9 @@ class Monitoring_ListController extends Controller
 
         $query = $this->backend->select()->from('eventHistory', array(
             'host_name',
+            'host_display_name',
             'service_description',
+            'service_display_name',
             'object_type',
             'timestamp',
             'state',
@@ -605,7 +621,7 @@ class Monitoring_ListController extends Controller
         $this->filterQuery($query);
 
         $this->setupSortControl(array(
-            'timestamp' => 'Occurence'
+            'timestamp' => $this->translate('Occurence')
         ));
         $this->view->history = $query->paginate();
     }
@@ -650,22 +666,10 @@ class Monitoring_ListController extends Controller
         if ($sort = $this->params->get('sort')) {
             $query->order($sort, $this->params->get('dir'));
         }
-        $this->applyRestrictions($query);
         $this->handleFormatRequest($query);
         return $query;
     }
 
-    /**
-     * Apply current user's `monitoring/filter' restrictions on the given data view
-     */
-    protected function applyRestrictions($query)
-    {
-        foreach ($this->getRestrictions('monitoring/filter') as $restriction) {
-            // TODO: $query->applyFilter(Filter::fromQueryString());
-        }
-        return $query;
-    }
-
     protected function extraColumns()
     {
         $columns = preg_split(
diff --git a/modules/monitoring/application/controllers/MultiController.php b/modules/monitoring/application/controllers/MultiController.php
deleted file mode 100644
index 52d927ffb..000000000
--- a/modules/monitoring/application/controllers/MultiController.php
+++ /dev/null
@@ -1,282 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-use Icinga\Module\Monitoring\Controller;
-use Icinga\Web\Widget\Chart\InlinePie;
-use Icinga\Module\Monitoring\Forms\Command\MultiCommandFlagForm;
-use Icinga\Web\Widget;
-use Icinga\Data\Filter\Filter;
-
-/**
- * Displays aggregations collections of multiple objects.
- */
-class Monitoring_MultiController extends Controller
-{
-    public function hostAction()
-    {
-        $errors  = array();
-        $query = $this->backend->select()->from(
-            'hostStatus',
-            array(
-                'host_name',
-                'host_in_downtime',
-                'host_passive_checks_enabled',
-                'host_obsessing',
-                'host_state',
-                'host_notifications_enabled',
-                'host_event_handler_enabled',
-                'host_flap_detection_enabled',
-                'host_active_checks_enabled',
-                // columns intended for filter-request
-                'host_problem',
-                'host_handled'
-            )
-        )->getQuery();
-        $this->applyQueryFilter($query);
-        $hosts = $query->fetchAll();
-
-        $comments = $this->backend->select()->from('comment', array(
-            'comment_internal_id',
-            'comment_host',
-        ));
-        $this->applyQueryFilter($comments);
-        $uniqueComments = array_keys($this->getUniqueValues($comments->getQuery()->fetchAll(), 'comment_internal_id'));
-
-        // Populate view
-        $this->view->objects = $this->view->hosts = $hosts;
-        $this->view->problems = $this->getProblems($hosts);
-        $this->view->comments = $uniqueComments;
-        $this->view->hostnames = $this->getProperties($hosts, 'host_name');
-        $this->view->downtimes = $this->getDowntimes($hosts);
-        $this->view->errors = $errors;
-        $this->view->states = $this->countStates($hosts, 'host', 'host_name');
-        $this->view->pie = $this->createPie(
-            $this->view->states,
-            $this->view->getHelper('MonitoringState')->getHostStateColors(),
-            mt('monitoring', 'Host State')
-        );
-
-        // Handle configuration changes
-        $this->handleConfigurationForm(array(
-            'host_passive_checks_enabled' => $this->translate('Passive Checks'),
-            'host_active_checks_enabled'  => $this->translate('Active Checks'),
-            'host_notifications_enabled'  => $this->translate('Notifications'),
-            'host_event_handler_enabled'  => $this->translate('Event Handler'),
-            'host_flap_detection_enabled' => $this->translate('Flap Detection'),
-            'host_obsessing'              => $this->translate('Obsessing')
-        ));
-    }
-
-    public function serviceAction()
-    {
-        $errors = array();
-        $query = $this->backend->select()->from('serviceStatus', array(
-            'host_name',
-            'host_state',
-            'service_description',
-            'service_handled',
-            'service_state',
-            'service_in_downtime',
-            'service_passive_checks_enabled',
-            'service_notifications_enabled',
-            'service_event_handler_enabled',
-            'service_flap_detection_enabled',
-            'service_active_checks_enabled',
-            'service_obsessing',
-             // also accept all filter-requests from ListView
-            'service_problem',
-            'service_severity',
-            'service_last_check',
-            'service_state_type',
-            'host_severity',
-            'host_address',
-            'host_last_check'
-        ));
-
-        $this->applyQueryFilter($query);
-        $services = $query->getQuery()->fetchAll();
-
-        $comments = $this->backend->select()->from('comment', array(
-            'comment_internal_id',
-            'comment_host',
-            'comment_service'
-        ));
-        $this->applyQueryFilter($comments);
-        $uniqueComments = array_keys($this->getUniqueValues($comments->getQuery()->fetchAll(), 'comment_internal_id'));
-
-        // populate the view
-        $this->view->objects        = $this->view->services = $services;
-        $this->view->problems       = $this->getProblems($services);
-        $this->view->comments       = $uniqueComments;
-        $this->view->hostnames      = $this->getProperties($services, 'host_name');
-        $this->view->servicenames   = $this->getProperties($services, 'service_description');
-        $this->view->downtimes      = $this->getDowntimes($services);
-        $this->view->service_states = $this->countStates($services, 'service');
-        $this->view->host_states    = $this->countStates($services, 'host', 'host_name');
-        $this->view->service_pie    = $this->createPie(
-            $this->view->service_states,
-            $this->view->getHelper('MonitoringState')->getServiceStateColors(),
-            mt('monitoring', 'Service State')
-        );
-        $this->view->host_pie       = $this->createPie(
-            $this->view->host_states,
-            $this->view->getHelper('MonitoringState')->getHostStateColors(),
-            mt('monitoring', 'Host State')
-        );
-        $this->view->errors         = $errors;
-
-        $this->handleConfigurationForm(array(
-            'service_passive_checks_enabled' => $this->translate('Passive Checks'),
-            'service_active_checks_enabled'  => $this->translate('Active Checks'),
-            'service_notifications_enabled'  => $this->translate('Notifications'),
-            'service_event_handler_enabled'  => $this->translate('Event Handler'),
-            'service_flap_detection_enabled' => $this->translate('Flap Detection'),
-            'service_obsessing'              => $this->translate('Obsessing'),
-        ));
-    }
-
-    protected function applyQueryFilter($query)
-    {
-        $params = clone $this->params;
-        $modifyFilter = $params->shift('modifyFilter');
-
-        $filter = Filter::fromQueryString((string) $params);
-        if ($modifyFilter) {
-            $this->view->filterWidget = Widget::create('filterEditor', array(
-                'filter' => $filter,
-                'query'  => $query
-            ));
-        }
-        $this->view->filter = $filter;
-        $query->applyFilter($filter);
-        return $query;
-    }
-
-    /**
-     * Create an array with all unique values as keys.
-     *
-     * @param array $values     The array containing the objects
-     * @param       $key        The key to access
-     *
-     * @return array
-     */
-    private function getUniqueValues($values, $key)
-    {
-        $unique = array();
-        foreach ($values as $value) {
-            if (is_array($value)) {
-                $unique[$value[$key]] = $value[$key];
-            } else {
-                $unique[$value->$key] = $value->$key;
-            }
-        }
-        return $unique;
-    }
-
-    /**
-     * Get the numbers of problems of the given objects
-     *
-     * @param $objects  The objects containing the problems
-     *
-     * @return int  The problem count
-     */
-    private function getProblems($objects)
-    {
-        $problems = 0;
-        foreach ($objects as $object) {
-            if (property_exists($object, 'host_unhandled_service_count')) {
-                $problems += $object->host_unhandled_service_count;
-            } else if (
-                property_exists($object, 'service_handled') &&
-                !$object->service_handled &&
-                $object->service_state > 0
-            ) {
-                $problems++;
-            }
-        }
-        return $problems;
-    }
-
-    private function countStates($objects, $type = 'host', $unique = null)
-    {
-        $known  = array();
-        if ($type === 'host') {
-            $states = array_fill_keys($this->view->getHelper('MonitoringState')->getHostStateNames(), 0);
-        } else {
-            $states = array_fill_keys($this->view->getHelper('MonitoringState')->getServiceStateNames(), 0);
-        }
-        foreach ($objects as $object) {
-            if (isset($unique)) {
-                if (array_key_exists($object->$unique, $known)) {
-                    continue;
-                }
-                $known[$object->$unique] = true;
-            }
-            $states[$this->view->monitoringState($object, $type)]++;
-        }
-        return $states;
-    }
-
-    private function createPie($states, $colors, $title)
-    {
-        $chart = new InlinePie(array_values($states), $title, $colors);
-        $chart->setLabel(array_keys($states))->setHeight(100)->setWidth(100);
-        $chart->setTitle($title);
-        return $chart;
-    }
-
-
-    private function getComments($objects)
-    {
-        $unique = array();
-        foreach ($objects as $object) {
-            $unique = array_merge($unique, $this->getUniqueValues($object->comments, 'comment_internal_id'));
-        }
-        return array_keys($unique);
-    }
-
-    private function getProperties($objects, $property)
-    {
-        $objectnames = array();
-        foreach ($objects as $object) {
-            $objectnames[] = $object->$property;
-        }
-        return $objectnames;
-    }
-
-    private function getDowntimes($objects)
-    {
-        $downtimes = array();
-        foreach ($objects as $object)
-        {
-            if (
-                (property_exists($object, 'host_in_downtime') && $object->host_in_downtime) ||
-                (property_exists($object, 'service_in_downtime') && $object->service_in_downtime)
-            ) {
-                $downtimes[] = true;
-            }
-        }
-        return $downtimes;
-    }
-
-
-    /**
-     * Handle the form to edit configuration flags.
-     *
-     * @param $flags array  The used flags.
-     */
-    private function handleConfigurationForm(array $flags)
-    {
-        $this->view->form = $form = new MultiCommandFlagForm($flags);
-        $this->view->formElements = $form->buildCheckboxes();
-        $form->setRequest($this->_request);
-        if ($form->isSubmittedAndValid()) {
-            // TODO: Handle commands
-            $changed = $form->getChangedValues();
-        }
-        if ($this->_request->isPost() === false) {
-            $this->view->form->initFromItems($this->view->objects);
-        }
-    }
-}
diff --git a/modules/monitoring/application/controllers/ProcessController.php b/modules/monitoring/application/controllers/ProcessController.php
index 62334d7e8..bb5a4e5c2 100644
--- a/modules/monitoring/application/controllers/ProcessController.php
+++ b/modules/monitoring/application/controllers/ProcessController.php
@@ -64,8 +64,9 @@ class Monitoring_ProcessController extends Controller
                     'process_performance_data'
                 )
             )
-            ->getQuery()
-            ->fetchRow();
+            ->getQuery();
+        $this->handleFormatRequest($programStatus);
+        $programStatus = $programStatus->fetchRow();
         if ($programStatus === false) {
             return $this->render('not-running', true, null);
         }
diff --git a/modules/monitoring/application/controllers/ServiceController.php b/modules/monitoring/application/controllers/ServiceController.php
index 06417cc6e..4e4e67402 100644
--- a/modules/monitoring/application/controllers/ServiceController.php
+++ b/modules/monitoring/application/controllers/ServiceController.php
@@ -26,20 +26,15 @@ class Monitoring_ServiceController extends MonitoredObjectController
     public function init()
     {
         $service = new Service($this->backend, $this->params->get('host'), $this->params->get('service'));
+
+        $this->applyRestriction('monitoring/services/filter', $service);
+
         if ($service->fetch() === false) {
             throw new Zend_Controller_Action_Exception($this->translate('Service not found'));
         }
         $this->object = $service;
         $this->createTabs();
-    }
-
-    /**
-     * Show a service
-     */
-    public function showAction()
-    {
         $this->getTabs()->activate('service');
-        parent::showAction();
     }
 
     /**
@@ -47,6 +42,8 @@ class Monitoring_ServiceController extends MonitoredObjectController
      */
     public function acknowledgeProblemAction()
     {
+        $this->assertPermission('monitoring/command/acknowledge-problem');
+
         $this->view->title = $this->translate('Acknowledge Service Problem');
         $this->handleCommandForm(new AcknowledgeProblemCommandForm());
     }
@@ -56,6 +53,8 @@ class Monitoring_ServiceController extends MonitoredObjectController
      */
     public function addCommentAction()
     {
+        $this->assertPermission('monitoring/command/comment/add');
+
         $this->view->title = $this->translate('Add Service Comment');
         $this->handleCommandForm(new AddCommentCommandForm());
     }
@@ -65,6 +64,8 @@ class Monitoring_ServiceController extends MonitoredObjectController
      */
     public function rescheduleCheckAction()
     {
+        $this->assertPermission('monitoring/command/schedule-check');
+
         $this->view->title = $this->translate('Reschedule Service Check');
         $this->handleCommandForm(new ScheduleServiceCheckCommandForm());
     }
@@ -74,6 +75,8 @@ class Monitoring_ServiceController extends MonitoredObjectController
      */
     public function scheduleDowntimeAction()
     {
+        $this->assertPermission('monitoring/command/downtime/schedule');
+
         $this->view->title = $this->translate('Schedule Service Downtime');
         $this->handleCommandForm(new ScheduleServiceDowntimeCommandForm());
     }
@@ -83,6 +86,8 @@ class Monitoring_ServiceController extends MonitoredObjectController
      */
     public function processCheckResultAction()
     {
+        $this->assertPermission('monitoring/command/process-check-result');
+
         $this->view->title = $this->translate('Submit Passive Service Check Result');
         $this->handleCommandForm(new ProcessCheckResultCommandForm());
     }
diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php
index cdf86f460..dc7feb2da 100644
--- a/modules/monitoring/application/controllers/ServicesController.php
+++ b/modules/monitoring/application/controllers/ServicesController.php
@@ -74,8 +74,10 @@ class Monitoring_ServicesController extends Controller
             'service_obsessing'*/
         ));
         $unhandledObjects = array();
+        $unhandledFilterExpressions = array();
         $acknowledgedObjects = array();
         $objectsInDowntime = array();
+        $downtimeFilterExpressions = array();
         $serviceStates = array(
             Service::getStateText(Service::STATE_OK) => 0,
             Service::getStateText(Service::STATE_WARNING) => 0,
@@ -94,12 +96,20 @@ class Monitoring_ServicesController extends Controller
             /** @var Service $service */
             if ((bool) $service->problem === true && (bool) $service->handled === false) {
                 $unhandledObjects[] = $service;
+                $unhandledFilterExpressions[] = Filter::matchAll(
+                    Filter::where('host', $service->getHost()->getName()),
+                    Filter::where('service', $service->getName())
+                );
             }
             if ((bool) $service->acknowledged === true) {
                 $acknowledgedObjects[] = $service;
             }
             if ((bool) $service->in_downtime === true) {
                 $objectsInDowntime[] = $service;
+                $downtimeFilterExpressions[] = Filter::matchAll(
+                    Filter::where('downtime_host', $service->getHost()->getName()),
+                    Filter::where('downtime_service', $service->getName())
+                );
             }
             ++$serviceStates[$service::getStateText($service->state)];
             if (! isset($knownHostStates[$service->getHost()->getName()])) {
@@ -125,16 +135,15 @@ class Monitoring_ServicesController extends Controller
         $this->view->serviceStates = $serviceStates;
         $this->view->objects = $this->serviceList;
         $this->view->unhandledObjects = $unhandledObjects;
-        $this->view->acknowledgeUnhandledLink = Url::fromRequest()
-            ->setPath('monitoring/services/acknowledge-problem')
-            ->addParams(array('service_problem' => 1, 'service_handled' => 0));
-        $this->view->downtimeUnhandledLink = Url::fromRequest()
-            ->setPath('monitoring/services/schedule-downtime')
-            ->addParams(array('service_problem' => 1, 'service_handled' => 0));
+        $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString();
+        $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/services/acknowledge-problem')
+            ->setQueryString($unhandledFilterQueryString);
+        $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/services/schedule-downtime')
+            ->setQueryString($unhandledFilterQueryString);
         $this->view->acknowledgedObjects = $acknowledgedObjects;
         $this->view->objectsInDowntime = $objectsInDowntime;
-        $this->view->inDowntimeLink = Url::fromRequest()
-            ->setPath('monitoring/list/downtimes');
+        $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes')
+            ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString());
         $this->view->havingCommentsLink = Url::fromRequest()
             ->setPath('monitoring/list/comments');
         $this->view->serviceStatesPieChart = $this->createPieChart(
@@ -153,10 +162,9 @@ class Monitoring_ServicesController extends Controller
     {
         $chart = new InlinePie(array_values($states), $title, $colors);
         return $chart
-            ->setLabel(array_map('strtoupper', array_keys($states)))
-            ->setHeight(100)
-            ->setWidth(100)
-            ->setTitle($title);
+            ->setSize(75)
+            ->setTitle('')
+            ->setSparklineClass('sparkline-multi');
     }
 
     /**
diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php
index efec6665a..0b7a2f897 100644
--- a/modules/monitoring/application/controllers/ShowController.php
+++ b/modules/monitoring/application/controllers/ShowController.php
@@ -73,9 +73,8 @@ class Monitoring_ShowController extends Controller
     public function historyAction()
     {
         $this->getTabs()->activate('history');
-        //$this->view->object->populate();
         $this->view->object->fetchEventHistory();
-        $this->view->history = $this->view->object->eventhistory->paginate($this->params->get('limit', 50));
+        $this->view->history = $this->view->object->eventhistory->getQuery()->paginate($this->params->get('limit', 50));
         $this->handleFormatRequest($this->view->object->eventhistory);
         $this->fetchHostStats();
     }
@@ -166,8 +165,10 @@ class Monitoring_ShowController extends Controller
                 'notification_output',
                 'notification_contact',
                 'notification_start_time',
-                'notification_state'
-            ))->order('notification_start_time');
+                'notification_state',
+                'host_display_name',
+                'service_display_name'
+            ));
 
             $notifications->where('contact_object_id', $contact->contact_object_id);
 
diff --git a/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php b/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php
index 0e64a4b03..21d926b58 100644
--- a/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php
@@ -21,7 +21,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm
      */
     public function init()
     {
-        $this->setSubmitLabel(mt('monitoring', 'Disable Notifications'));
+        $this->setSubmitLabel($this->translate('Disable Notifications'));
     }
 
     /**
@@ -30,8 +30,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to disable host and service notifications for a specific time.'
         );
     }
@@ -49,8 +48,8 @@ class DisableNotificationsExpireCommandForm extends CommandForm
             'expire_time',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Expire Time'),
-                'description'   => mt('monitoring', 'Set the expire time.'),
+                'label'         => $this->translate('Expire Time'),
+                'description'   => $this->translate('Set the expire time.'),
                 'value'         => $expireTime
             )
         );
@@ -67,7 +66,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm
         $disableNotifications
             ->setExpireTime($this->getElement('expire_time')->getValue()->getTimestamp());
         $this->getTransport($this->request)->send($disableNotifications);
-        Notification::success(mt('monitoring', 'Disabling host and service notifications..'));
+        Notification::success($this->translate('Disabling host and service notifications..'));
         return true;
     }
 }
diff --git a/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php b/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php
index 291619b2f..469c1b6eb 100644
--- a/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php
@@ -61,13 +61,13 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
         if ((bool) $this->status->notifications_enabled) {
             $notificationDescription = sprintf(
                 '<a title="%s" href="%s" data-base-target="_next">%s</a>',
-                mt('monitoring', 'Disable notifications for a specific time on a program-wide basis'),
+                $this->translate('Disable notifications for a specific time on a program-wide basis'),
                 $this->getView()->href('monitoring/process/disable-notifications'),
-                mt('monitoring', 'Disable temporarily')
+                $this->translate('Disable temporarily')
             );
         } elseif ($this->status->disable_notif_expire_time) {
             $notificationDescription = sprintf(
-                mt('monitoring', 'Notifications will be re-enabled in <strong>%s</strong>'),
+                $this->translate('Notifications will be re-enabled in <strong>%s</strong>'),
                 $this->getView()->timeUntil($this->status->disable_notif_expire_time)
             );
         } else {
@@ -78,7 +78,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_ACTIVE_HOST_CHECKS,
                 array(
-                    'label'         =>  mt('monitoring', 'Active Host Checks Being Executed'),
+                    'label'         =>  $this->translate('Active Host Checks Being Executed'),
                     'autosubmit'    => true
                 )
             ),
@@ -86,7 +86,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_ACTIVE_SERVICE_CHECKS,
                 array(
-                    'label'         =>  mt('monitoring', 'Active Service Checks Being Executed'),
+                    'label'         =>  $this->translate('Active Service Checks Being Executed'),
                     'autosubmit'    => true
                 )
             ),
@@ -94,7 +94,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_EVENT_HANDLERS,
                 array(
-                    'label'         => mt('monitoring', 'Event Handlers Enabled'),
+                    'label'         => $this->translate('Event Handlers Enabled'),
                     'autosubmit'    => true
                 )
             ),
@@ -102,7 +102,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_FLAP_DETECTION,
                 array(
-                    'label'         => mt('monitoring', 'Flap Detection Enabled'),
+                    'label'         => $this->translate('Flap Detection Enabled'),
                     'autosubmit'    => true
                 )
             ),
@@ -110,7 +110,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_NOTIFICATIONS,
                 array(
-                    'label'         => mt('monitoring', 'Notifications Enabled'),
+                    'label'         => $this->translate('Notifications Enabled'),
                     'autosubmit'    => true,
                     'description'   => $notificationDescription,
                     'decorators'    => array(
@@ -129,7 +129,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_HOST_OBSESSING,
                 array(
-                    'label'         => mt('monitoring', 'Obsessing Over Hosts'),
+                    'label'         => $this->translate('Obsessing Over Hosts'),
                     'autosubmit'    => true
                 )
             ),
@@ -137,7 +137,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_SERVICE_OBSESSING,
                 array(
-                    'label'         => mt('monitoring', 'Obsessing Over Services'),
+                    'label'         => $this->translate('Obsessing Over Services'),
                     'autosubmit'    => true
                 )
             ),
@@ -145,7 +145,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_PASSIVE_HOST_CHECKS,
                 array(
-                    'label'         =>  mt('monitoring', 'Passive Host Checks Being Accepted'),
+                    'label'         =>  $this->translate('Passive Host Checks Being Accepted'),
                     'autosubmit'    => true
                 )
             ),
@@ -153,7 +153,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_PASSIVE_SERVICE_CHECKS,
                 array(
-                    'label'         =>  mt('monitoring', 'Passive Service Checks Being Accepted'),
+                    'label'         =>  $this->translate('Passive Service Checks Being Accepted'),
                     'autosubmit'    => true
                 )
             ),
@@ -161,7 +161,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 'checkbox',
                 ToggleInstanceFeatureCommand::FEATURE_PERFORMANCE_DATA,
                 array(
-                    'label'         =>  mt('monitoring', 'Performance Data Being Processed'),
+                    'label'         =>  $this->translate('Performance Data Being Processed'),
                     'autosubmit'    => true
                 )
             )
@@ -198,7 +198,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
                 ->setEnabled($enabled);
             $this->getTransport($this->request)->send($toggleFeature);
         }
-        Notification::success(mt('monitoring', 'Toggling feature..'));
+        Notification::success($this->translate('Toggling feature..'));
         return true;
     }
 }
diff --git a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
index 25ac76c25..df3731837 100644
--- a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
@@ -31,8 +31,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to acknowledge host or service problems. When a problem is acknowledged,'
             . ' future notifications about problems are temporarily disabled until the host or service'
             . ' recovers.'
@@ -51,9 +50,8 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'comment',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Comment'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Comment'),
+                    'description'   => $this->translate(
                         'If you work with other administrators, you may find it useful to share information about the'
                         . ' the host or service that is having problems. Make sure you enter a brief description of'
                         . ' what you are doing.'
@@ -64,9 +62,8 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'persistent',
                 array(
-                    'label'         => mt('monitoring', 'Persistent Comment'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Persistent Comment'),
+                    'description'   => $this->translate(
                         'If you would like the comment to remain even when the acknowledgement is removed, check this'
                         . ' option.'
                     )
@@ -76,8 +73,10 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'expire',
                 array(
-                    'label'         => mt('monitoring', 'Use Expire Time'),
-                    'description'   => mt('monitoring', 'If the acknowledgement should expire, check this option.'),
+                    'label'         => $this->translate('Use Expire Time'),
+                    'description'   => $this->translate(
+                        'If the acknowledgement should expire, check this option.'
+                    ),
                     'autosubmit'    => true
                 )
             )
@@ -89,10 +88,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'dateTimePicker',
                 'expire_time',
                 array(
-                    'label'         => mt('monitoring', 'Expire Time'),
+                    'label'         => $this->translate('Expire Time'),
                     'value'         => $expireTime,
-                    'description'   => mt(
-                        'monitoring',
+                    'description'   => $this->translate(
                         'Enter the expire date and time for this acknowledgement here. Icinga will delete the'
                         . ' acknowledgement after this time expired.'
                     )
@@ -114,10 +112,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'sticky',
                 array(
-                    'label'         => mt('monitoring', 'Sticky Acknowledgement'),
+                    'label'         => $this->translate('Sticky Acknowledgement'),
                     'value'         => true,
-                    'description'   => mt(
-                        'monitoring',
+                    'description'   => $this->translate(
                         'If you want the acknowledgement to disable notifications until the host or service recovers,'
                         . ' check this option.'
                     )
@@ -127,10 +124,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'notify',
                 array(
-                    'label'         => mt('monitoring', 'Send Notification'),
+                    'label'         => $this->translate('Send Notification'),
                     'value'         => true,
-                    'description'   => mt(
-                        'monitoring',
+                    'description'   => $this->translate(
                         'If you do not want an acknowledgement notification to be sent out to the appropriate contacts,'
                         . ' uncheck this option.'
                     )
diff --git a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
index f5adf6c71..e7f7e91f9 100644
--- a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
@@ -29,8 +29,7 @@ class AddCommentCommandForm extends ObjectsCommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to add host or service comments.'
         );
     }
@@ -47,9 +46,8 @@ class AddCommentCommandForm extends ObjectsCommandForm
                 'comment',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Comment'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Comment'),
+                    'description'   => $this->translate(
                         'If you work with other administrators, you may find it useful to share information about the'
                         . ' the host or service that is having problems. Make sure you enter a brief description of'
                         . ' what you are doing.'
@@ -60,10 +58,9 @@ class AddCommentCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'persistent',
                 array(
-                    'label'         => mt('monitoring', 'Persistent'),
+                    'label'         => $this->translate('Persistent'),
                     'value'         => true,
-                    'description'   => mt(
-                        'monitoring',
+                    'description'   => $this->translate(
                         'If you uncheck this option, the comment will automatically be deleted the next time Icinga is'
                         . ' restarted.'
                     )
diff --git a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
index 01006683f..1054aae05 100644
--- a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
@@ -35,8 +35,8 @@ class CheckNowCommandForm extends ObjectsCommandForm
                 array(
                     'ignore'        => true,
                     'type'          => 'submit',
-                    'value'         => mt('monitoring', 'Check now'),
-                    'label'         => '<i class="icon-reschedule"></i> ' . mt('monitoring', 'Check now'),
+                    'value'         => $this->translate('Check now'),
+                    'label'         => '<i class="icon-reschedule"></i> ' . $this->translate('Check now'),
                     'decorators'    => array('ViewHelper'),
                     'escape'        => false,
                     'class'         => 'link-like'
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
index 3d85afcec..0f7858ad9 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
@@ -55,7 +55,7 @@ class DeleteCommentCommandForm extends ObjectsCommandForm
             array(
                 'ignore'        => true,
                 'label'         => 'X',
-                'title'         => mt('monitoring', 'Delete comment'),
+                'title'         => $this->translate('Delete comment'),
                 'decorators'    => array('ViewHelper')
             )
         );
@@ -80,7 +80,7 @@ class DeleteCommentCommandForm extends ObjectsCommandForm
         if (! empty($redirect)) {
             $this->setRedirectUrl($redirect);
         }
-        Notification::success(mt('monitoring', 'Deleting comment..'));
+        Notification::success($this->translate('Deleting comment..'));
         return true;
     }
 }
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
index 1c7095b82..43ca52b05 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
@@ -55,7 +55,7 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm
             array(
                 'ignore'        => true,
                 'label'         => 'X',
-                'title'         => mt('monitoring', 'Delete downtime'),
+                'title'         => $this->translate('Delete downtime'),
                 'decorators'    => array('ViewHelper')
             )
         );
@@ -80,7 +80,7 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm
         if (! empty($redirect)) {
             $this->setRedirectUrl($redirect);
         }
-        Notification::success(mt('monitoring', 'Deleting downtime..'));
+        Notification::success($this->translate('Deleting downtime..'));
         return true;
     }
 }
diff --git a/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php b/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php
index 48ee00ab3..44e248956 100644
--- a/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php
@@ -29,8 +29,7 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to submit passive host or service check results.'
         );
     }
@@ -53,17 +52,17 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm
             'status',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Status'),
-                'description'   => mt('monitoring', 'The state this check result should report'),
+                'label'         => $this->translate('Status'),
+                'description'   => $this->translate('The state this check result should report'),
                 'multiOptions'  => $object->getType() === $object::TYPE_HOST ? array(
-                    ProcessCheckResultCommand::HOST_UP          => mt('monitoring', 'UP', 'icinga.state'),
-                    ProcessCheckResultCommand::HOST_DOWN        => mt('monitoring', 'DOWN', 'icinga.state'),
-                    ProcessCheckResultCommand::HOST_UNREACHABLE => mt('monitoring', 'UNREACHABLE', 'icinga.state')
+                    ProcessCheckResultCommand::HOST_UP          => $this->translate('UP', 'icinga.state'),
+                    ProcessCheckResultCommand::HOST_DOWN        => $this->translate('DOWN', 'icinga.state'),
+                    ProcessCheckResultCommand::HOST_UNREACHABLE => $this->translate('UNREACHABLE', 'icinga.state')
                 ) : array(
-                    ProcessCheckResultCommand::SERVICE_OK       => mt('monitoring', 'OK', 'icinga.state'),
-                    ProcessCheckResultCommand::SERVICE_WARNING  => mt('monitoring', 'WARNING', 'icinga.state'),
-                    ProcessCheckResultCommand::SERVICE_CRITICAL => mt('monitoring', 'CRITICAL', 'icinga.state'),
-                    ProcessCheckResultCommand::SERVICE_UNKNOWN  => mt('monitoring', 'UNKNOWN', 'icinga.state')
+                    ProcessCheckResultCommand::SERVICE_OK       => $this->translate('OK', 'icinga.state'),
+                    ProcessCheckResultCommand::SERVICE_WARNING  => $this->translate('WARNING', 'icinga.state'),
+                    ProcessCheckResultCommand::SERVICE_CRITICAL => $this->translate('CRITICAL', 'icinga.state'),
+                    ProcessCheckResultCommand::SERVICE_UNKNOWN  => $this->translate('UNKNOWN', 'icinga.state')
                 )
             )
         );
@@ -72,8 +71,8 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm
             'output',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Output'),
-                'description'   => mt('monitoring', 'The plugin output of this check result')
+                'label'         => $this->translate('Output'),
+                'description'   => $this->translate('The plugin output of this check result')
             )
         );
         $this->addElement(
@@ -81,9 +80,8 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm
             'perfdata',
             array(
                 'allowEmpty'    => true,
-                'label'         => mt('monitoring', 'Performance Data'),
-                'description'   => mt(
-                    'monitoring',
+                'label'         => $this->translate('Performance Data'),
+                'description'   => $this->translate(
                     'The performance data of this check result. Leave empty'
                     . ' if this check result has no performance data'
                 )
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
index 82a9b2e52..949ec33e1 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
@@ -24,9 +24,8 @@ class ScheduleHostCheckCommandForm extends ScheduleServiceCheckCommandForm
                 'checkbox',
                 'all_services',
                 array(
-                    'label'         => mt('monitoring', 'All Services'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('All Services'),
+                    'description'   => $this->translate(
                         'Schedule check for all services on the hosts and the hosts themselves.'
                     )
                 )
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
index beb0793ef..f84069a9a 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
@@ -27,9 +27,8 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
                 'checkbox',
                 'all_services',
                 array(
-                    'label'         => mt('monitoring', 'All Services'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('All Services'),
+                    'description'   => $this->translate(
                         'Schedule downtime for all services on the hosts and the hosts themselves.'
                     )
                 )
@@ -38,15 +37,14 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
                 'select',
                 'child_hosts',
                 array(
-                    'label'        => mt('monitoring', 'Child Hosts'),
+                    'label'        => $this->translate('Child Hosts'),
                     'required'     => true,
                     'multiOptions' => array(
-                        0 => mt('monitoring', 'Do nothing with child hosts'),
-                        1 => mt('monitoring', 'Schedule triggered downtime for all child hosts'),
-                        2 => mt('monitoring', 'Schedule non-triggered downtime for all child hosts')
+                        0 => $this->translate('Do nothing with child hosts'),
+                        1 => $this->translate('Schedule triggered downtime for all child hosts'),
+                        2 => $this->translate('Schedule non-triggered downtime for all child hosts')
                     ),
-                    'description' => mt(
-                        'monitoring',
+                    'description' => $this->translate(
                         'Define what should be done with the child hosts of the hosts.'
                     )
                 )
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php
index 9e04a2254..b34472d49 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php
@@ -32,8 +32,7 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to schedule the next check of hosts or services. Icinga will re-queue the'
             . ' hosts or services to be checked at the time you specify.'
         );
@@ -52,8 +51,7 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm
                 'note',
                 'command-info',
                 array(
-                    'value' => mt(
-                        'monitoring',
+                    'value' => $this->translate(
                         'This command is used to schedule the next check of hosts or services. Icinga will re-queue the'
                         . ' hosts or services to be checked at the time you specify.'
                     )
@@ -64,8 +62,10 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm
                 'check_time',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Check Time'),
-                    'description'   => mt('monitoring', 'Set the date and time when the check should be scheduled.'),
+                    'label'         => $this->translate('Check Time'),
+                    'description'   => $this->translate(
+                        'Set the date and time when the check should be scheduled.'
+                    ),
                     'value'         => $checkTime
                 )
             ),
@@ -73,9 +73,8 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm
                 'checkbox',
                 'force_check',
                 array(
-                    'label'         => mt('monitoring', 'Force Check'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Force Check'),
+                    'description'   => $this->translate(
                         'If you select this option, Icinga will force a check regardless of both what time the'
                         . ' scheduled check occurs and whether or not checks are enabled.'
                     )
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php
index 9961d4b65..4f66898f6 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php
@@ -42,8 +42,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
      */
     public function getHelp()
     {
-        return mt(
-            'monitoring',
+        return $this->translate(
             'This command is used to schedule host and service downtimes. During the specified downtime,'
             . ' Icinga will not send notifications out about the hosts and services. When the scheduled'
             . ' downtime expires, Icinga will send out notifications for the hosts and services as it'
@@ -67,9 +66,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                 'comment',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Comment'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Comment'),
+                    'description'   => $this->translate(
                         'If you work with other administrators, you may find it useful to share information about the'
                         . ' the host or service that is having problems. Make sure you enter a brief description of'
                         . ' what you are doing.'
@@ -81,8 +79,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                 'start',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Start Time'),
-                    'description'   => mt('monitoring', 'Set the start date and time for the downtime.'),
+                    'label'         => $this->translate('Start Time'),
+                    'description'   => $this->translate('Set the start date and time for the downtime.'),
                     'value'         => $start
                 )
             ),
@@ -91,8 +89,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                 'end',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'End Time'),
-                    'description'   => mt('monitoring', 'Set the end date and time for the downtime.'),
+                    'label'         => $this->translate('End Time'),
+                    'description'   => $this->translate('Set the end date and time for the downtime.'),
                     'value'         => $end
                 )
             ),
@@ -102,17 +100,16 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                 array(
                     'required'      => true,
                     'autosubmit'    => true,
-                    'label'         => mt('monitoring', 'Type'),
-                    'description'   => mt(
-                        'monitoring',
+                    'label'         => $this->translate('Type'),
+                    'description'   => $this->translate(
                         'If you select the fixed option, the downtime will be in effect between the start and end'
                         . ' times you specify whereas a flexible downtime starts when the host or service enters a'
                         . ' problem state sometime between the start and end times you specified and lasts as long'
                         . ' as the duration time you enter. The duration fields do not apply for fixed downtimes.'
                     ),
                     'multiOptions' => array(
-                        self::FIXED     => mt('monitoring', 'Fixed'),
-                        self::FLEXIBLE  => mt('monitoring', 'Flexible')
+                        self::FIXED     => $this->translate('Fixed'),
+                        self::FLEXIBLE  => $this->translate('Flexible')
                     ),
                     'validators' => array(
                         array(
@@ -141,7 +138,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                     'hours',
                     array(
                         'required'  => true,
-                        'label'     => mt('monitoring', 'Hours'),
+                        'label'     => $this->translate('Hours'),
                         'value'     => 2,
                         'min'       => -1
                     )
@@ -151,7 +148,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                     'minutes',
                     array(
                         'required'  => true,
-                        'label'     => mt('monitoring', 'Minutes'),
+                        'label'     => $this->translate('Minutes'),
                         'value'     => 0,
                         'min'       => -1
                     )
@@ -161,9 +158,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm
                 array('hours', 'minutes'),
                 'duration',
                 array(
-                    'legend'        => mt('monitoring', 'Flexible Duration'),
-                    'description'   => mt(
-                        'monitoring',
+                    'legend'        => $this->translate('Flexible Duration'),
+                    'description'   => $this->translate(
                         'Enter here the duration of the downtime. The downtime will be automatically deleted after this'
                         . ' time expired.'
                     ),
diff --git a/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php b/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php
index c33527895..bf0a1d8b1 100644
--- a/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php
@@ -33,7 +33,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_ACTIVE_CHECKS,
                 array(
-                    'label'         => mt('monitoring', 'Active Checks'),
+                    'label'         => $this->translate('Active Checks'),
                     'autosubmit'    => true
                 )
             ),
@@ -41,7 +41,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_PASSIVE_CHECKS,
                 array(
-                    'label'         => mt('monitoring', 'Passive Checks'),
+                    'label'         => $this->translate('Passive Checks'),
                     'autosubmit'    => true
                 )
             ),
@@ -49,7 +49,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_OBSESSING,
                 array(
-                    'label'         => mt('monitoring', 'Obsessing'),
+                    'label'         => $this->translate('Obsessing'),
                     'autosubmit'    => true
                 )
             ),
@@ -57,7 +57,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_NOTIFICATIONS,
                 array(
-                    'label'         => mt('monitoring', 'Notifications'),
+                    'label'         => $this->translate('Notifications'),
                     'autosubmit'    => true
                 )
             ),
@@ -65,7 +65,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_EVENT_HANDLER,
                 array(
-                    'label'         => mt('monitoring', 'Event Handler'),
+                    'label'         => $this->translate('Event Handler'),
                     'autosubmit'    => true
                 )
             ),
@@ -73,7 +73,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 'checkbox',
                 ToggleObjectFeatureCommand::FEATURE_FLAP_DETECTION,
                 array(
-                    'label'         => mt('monitoring', 'Flap Detection'),
+                    'label'         => $this->translate('Flap Detection'),
                     'autosubmit'    => true
                 )
             )
@@ -95,7 +95,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
             $element = $this->getElement($feature);
             $element->setChecked($object->{$feature});
             if ((bool) $object->{$feature . '_changed'} === true) {
-                $element->setDescription(mt('monitoring', 'changed'));
+                $element->setDescription($this->translate('changed'));
             }
         }
         return $this;
@@ -120,7 +120,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
                 }
             }
         }
-        Notification::success(mt('monitoring', 'Toggling feature..'));
+        Notification::success($this->translate('Toggling feature..'));
         return true;
     }
 }
diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php
index 4b1aa65b6..ca45c068b 100644
--- a/modules/monitoring/application/forms/Config/BackendConfigForm.php
+++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php
@@ -5,10 +5,10 @@
 namespace Icinga\Module\Monitoring\Forms\Config;
 
 use InvalidArgumentException;
-use Icinga\Web\Notification;
-use Icinga\Forms\ConfigForm;
 use Icinga\Application\Config;
 use Icinga\Exception\ConfigurationError;
+use Icinga\Forms\ConfigForm;
+use Icinga\Web\Notification;
 
 /**
  * Form class for creating/modifying monitoring backends
@@ -18,7 +18,7 @@ class BackendConfigForm extends ConfigForm
     /**
      * The available monitoring backend resources split by type
      *
-     * @var array
+     * @type array
      */
     protected $resources;
 
@@ -28,15 +28,15 @@ class BackendConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_monitoring_backends');
-        $this->setSubmitLabel(mt('monitoring', 'Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
      * Set the resource configuration to use
      *
-     * @param   Config      $resources      The resource configuration
+     * @param   Config  $resourceConfig     The resource configuration
      *
-     * @return  self
+     * @return  $this
      *
      * @throws  ConfigurationError          In case there are no valid monitoring backend resources
      */
@@ -50,7 +50,7 @@ class BackendConfigForm extends ConfigForm
         }
 
         if (empty($resources)) {
-            throw new ConfigurationError(mt('monitoring', 'Could not find any valid monitoring backend resources'));
+            throw new ConfigurationError($this->translate('Could not find any valid monitoring backend resources'));
         }
 
         $this->resources = $resources;
@@ -64,7 +64,7 @@ class BackendConfigForm extends ConfigForm
      *
      * @param   array   $values             The values to extend the configuration with
      *
-     * @return  self
+     * @return  $this
      *
      * @throws  InvalidArgumentException    In case the backend does already exist
      */
@@ -72,9 +72,9 @@ class BackendConfigForm extends ConfigForm
     {
         $name = isset($values['name']) ? $values['name'] : '';
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing'));
+            throw new InvalidArgumentException($this->translate('Monitoring backend name missing'));
         } elseif ($this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend already exists'));
+            throw new InvalidArgumentException($this->translate('Monitoring backend already exists'));
         }
 
         unset($values['name']);
@@ -95,11 +95,11 @@ class BackendConfigForm extends ConfigForm
     public function edit($name, array $values)
     {
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Old monitoring backend name missing'));
+            throw new InvalidArgumentException($this->translate('Old monitoring backend name missing'));
         } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
-            throw new InvalidArgumentException(mt('monitoring', 'New monitoring backend name missing'));
+            throw new InvalidArgumentException($this->translate('New monitoring backend name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided'));
+            throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided'));
         }
 
         unset($values['name']);
@@ -119,9 +119,9 @@ class BackendConfigForm extends ConfigForm
     public function remove($name)
     {
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing'));
+            throw new InvalidArgumentException($this->translate('Monitoring backend name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided'));
+            throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided'));
         }
 
         $backendConfig = $this->config->getSection($name);
@@ -131,23 +131,21 @@ class BackendConfigForm extends ConfigForm
 
     /**
      * Add or edit a monitoring backend and save the configuration
-     *
-     * @see Form::onSuccess()
      */
     public function onSuccess()
     {
         $monitoringBackend = $this->request->getQuery('backend');
         try {
-            if ($monitoringBackend === null) { // create new backend
+            if ($monitoringBackend === null) { // Create new backend
                 $this->add($this->getValues());
-                $message = mt('monitoring', 'Monitoring backend "%s" has been successfully created');
-            } else { // edit existing backend
+                $message = $this->translate('Monitoring backend "%s" has been successfully created');
+            } else { // Edit existing backend
                 $this->edit($monitoringBackend, $this->getValues());
-                $message = mt('monitoring', 'Monitoring backend "%s" has been successfully changed');
+                $message = $this->translate('Monitoring backend "%s" has been successfully changed');
             }
         } catch (InvalidArgumentException $e) {
             Notification::error($e->getMessage());
-            return;
+            return null;
         }
 
         if ($this->save()) {
@@ -160,18 +158,16 @@ class BackendConfigForm extends ConfigForm
     /**
      * Populate the form in case a monitoring backend is being edited
      *
-     * @see Form::onRequest()
-     *
-     * @throws  ConfigurationError      In case the backend name is missing in the request or is invalid
+     * @throws  ConfigurationError  In case the backend name is missing in the request or is invalid
      */
     public function onRequest()
     {
         $monitoringBackend = $this->request->getQuery('backend');
         if ($monitoringBackend !== null) {
             if ($monitoringBackend === '') {
-                throw new ConfigurationError(mt('monitoring', 'Monitoring backend name missing'));
+                throw new ConfigurationError($this->translate('Monitoring backend name missing'));
             } elseif (! $this->config->hasSection($monitoringBackend)) {
-                throw new ConfigurationError(mt('monitoring', 'Unknown monitoring backend provided'));
+                throw new ConfigurationError($this->translate('Unknown monitoring backend provided'));
             }
 
             $backendConfig = $this->config->getSection($monitoringBackend)->toArray();
@@ -181,7 +177,8 @@ class BackendConfigForm extends ConfigForm
     }
 
     /**
-     * @see Form::createElements()
+     * (non-PHPDoc)
+     * @see Form::createElements() For the method documentation.
      */
     public function createElements(array $formData)
     {
@@ -200,7 +197,7 @@ class BackendConfigForm extends ConfigForm
             'disabled',
             array(
                 'required'  => true,
-                'label'     => mt('monitoring', 'Disable This Backend')
+                'label'     => $this->translate('Disable This Backend')
             )
         );
         $this->addElement(
@@ -208,8 +205,8 @@ class BackendConfigForm extends ConfigForm
             'name',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Backend Name'),
-                'description'   => mt('monitoring', 'The identifier of this backend')
+                'label'         => $this->translate('Backend Name'),
+                'description'   => $this->translate('The identifier of this backend')
             )
         );
         $this->addElement(
@@ -218,8 +215,8 @@ class BackendConfigForm extends ConfigForm
             array(
                 'required'      => true,
                 'autosubmit'    => true,
-                'label'         => mt('monitoring', 'Backend Type'),
-                'description'   => mt('monitoring', 'The data source used for retrieving monitoring information'),
+                'label'         => $this->translate('Backend Type'),
+                'description'   => $this->translate('The data source used for retrieving monitoring information'),
                 'multiOptions'  => $resourceTypes,
                 'value'         => $resourceType
             )
@@ -230,8 +227,8 @@ class BackendConfigForm extends ConfigForm
             'resource',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Resource'),
-                'description'   => mt('monitoring', 'The resource to use'),
+                'label'         => $this->translate('Resource'),
+                'description'   => $this->translate('The resource to use'),
                 'multiOptions'  => $this->resources[$resourceType],
                 'autosubmit'    => true
             )
@@ -253,8 +250,8 @@ class BackendConfigForm extends ConfigForm
                 array(
                     'value' => sprintf(
                         '<a href="%s" data-base-target="_main">%s</a>',
-                        $this->getView()->href('/icingaweb/config/editresource', array('resource' => $resourceName)),
-                        mt('monitoring', 'Show resource configuration')
+                        $this->getView()->url('config/editresource', array('resource' => $resourceName)),
+                        $this->translate('Show resource configuration')
                     ),
                     'escape' => false
                 )
diff --git a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php
index daabe7e02..405bac144 100644
--- a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php
+++ b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php
@@ -28,9 +28,9 @@ class LocalInstanceForm extends Form
             'path',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Command File'),
+                'label'         => $this->translate('Command File'),
                 'value'         => '/var/run/icinga2/cmd/icinga2.cmd',
-                'description'   => mt('monitoring', 'Path to the local Icinga command file')
+                'description'   => $this->translate('Path to the local Icinga command file')
             )
         );
         return $this;
diff --git a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php
index 7c55f655a..47b2a0316 100644
--- a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php
+++ b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php
@@ -29,8 +29,8 @@ class RemoteInstanceForm extends Form
                 'host',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Host'),
-                    'description'   => mt('monitoring',
+                    'label'         => $this->translate('Host'),
+                    'description'   => $this->translate(
                         'Hostname or address of the remote Icinga instance'
                     )
                 )
@@ -40,8 +40,8 @@ class RemoteInstanceForm extends Form
                 'port',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Port'),
-                    'description'   => mt('monitoring', 'SSH port to connect to on the remote Icinga instance'),
+                    'label'         => $this->translate('Port'),
+                    'description'   => $this->translate('SSH port to connect to on the remote Icinga instance'),
                     'value'         => 22
                 )
             ),
@@ -50,8 +50,8 @@ class RemoteInstanceForm extends Form
                 'user',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'User'),
-                    'description'   => mt('monitoring',
+                    'label'         => $this->translate('User'),
+                    'description'   => $this->translate(
                         'User to log in as on the remote Icinga instance. Please note that key-based SSH login must be'
                         . ' possible for this user'
                     )
@@ -62,9 +62,9 @@ class RemoteInstanceForm extends Form
                 'path',
                 array(
                     'required'      => true,
-                    'label'         => mt('monitoring', 'Command File'),
+                    'label'         => $this->translate('Command File'),
                     'value'         => '/var/run/icinga2/cmd/icinga2.cmd',
-                    'description'   => mt('monitoring', 'Path to the Icinga command file on the remote Icinga instance')
+                    'description'   => $this->translate('Path to the Icinga command file on the remote Icinga instance')
                 )
             )
         ));
diff --git a/modules/monitoring/application/forms/Config/InstanceConfigForm.php b/modules/monitoring/application/forms/Config/InstanceConfigForm.php
index b89e48c0a..5618f27ee 100644
--- a/modules/monitoring/application/forms/Config/InstanceConfigForm.php
+++ b/modules/monitoring/application/forms/Config/InstanceConfigForm.php
@@ -25,7 +25,7 @@ class InstanceConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_monitoring_instance');
-        $this->setSubmitLabel(mt('monitoring', 'Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
@@ -48,7 +48,7 @@ class InstanceConfigForm extends ConfigForm
                 break;
             default:
                 throw new InvalidArgumentException(
-                    sprintf(mt('monitoring', 'Invalid instance type "%s" given'), $type)
+                    sprintf($this->translate('Invalid instance type "%s" given'), $type)
                 );
         }
         return $form;
@@ -69,10 +69,10 @@ class InstanceConfigForm extends ConfigForm
     {
         $name = isset($values['name']) ? $values['name'] : '';
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Instance name missing'));
+            throw new InvalidArgumentException($this->translate('Instance name missing'));
         }
         if ($this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Instance already exists'));
+            throw new InvalidArgumentException($this->translate('Instance already exists'));
         }
 
         unset($values['name']);
@@ -93,11 +93,11 @@ class InstanceConfigForm extends ConfigForm
     public function edit($name, array $values)
     {
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Old instance name missing'));
+            throw new InvalidArgumentException($this->translate('Old instance name missing'));
         } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
-            throw new InvalidArgumentException(mt('monitoring', 'New instance name missing'));
+            throw new InvalidArgumentException($this->translate('New instance name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Unknown instance name provided'));
+            throw new InvalidArgumentException($this->translate('Unknown instance name provided'));
         }
 
         unset($values['name']);
@@ -117,9 +117,9 @@ class InstanceConfigForm extends ConfigForm
     public function remove($name)
     {
         if (! $name) {
-            throw new InvalidArgumentException(mt('monitoring', 'Instance name missing'));
+            throw new InvalidArgumentException($this->translate('Instance name missing'));
         } elseif (! $this->config->hasSection($name)) {
-            throw new InvalidArgumentException(mt('monitoring', 'Unknown instance name provided'));
+            throw new InvalidArgumentException($this->translate('Unknown instance name provided'));
         }
 
         $instanceConfig = $this->config->getSection($name);
@@ -136,10 +136,10 @@ class InstanceConfigForm extends ConfigForm
         $instanceName = $this->request->getQuery('instance');
         if ($instanceName !== null) {
             if (! $instanceName) {
-                throw new ConfigurationError(mt('monitoring', 'Instance name missing'));
+                throw new ConfigurationError($this->translate('Instance name missing'));
             }
             if (! $this->config->hasSection($instanceName)) {
-                throw new ConfigurationError(mt('monitoring', 'Unknown instance name given'));
+                throw new ConfigurationError($this->translate('Unknown instance name given'));
             }
 
             $instanceConfig = $this->config->getSection($instanceName)->toArray();
@@ -158,10 +158,10 @@ class InstanceConfigForm extends ConfigForm
         try {
             if ($instanceName === null) { // create new instance
                 $this->add($this->getValues());
-                $message = mt('monitoring', 'Instance "%s" created successfully.');
+                $message = $this->translate('Instance "%s" created successfully.');
             } else { // edit existing instance
                 $this->edit($instanceName, $this->getValues());
-                $message = mt('monitoring', 'Instance "%s" edited successfully.');
+                $message = $this->translate('Instance "%s" edited successfully.');
             }
         } catch (InvalidArgumentException $e) {
             Notification::error($e->getMessage());
@@ -189,7 +189,7 @@ class InstanceConfigForm extends ConfigForm
                 'name',
                 array(
                     'required'  => true,
-                    'label'     => mt('monitoring', 'Instance Name')
+                    'label'     => $this->translate('Instance Name')
                 )
             ),
             array(
@@ -198,10 +198,10 @@ class InstanceConfigForm extends ConfigForm
                 array(
                     'required'      => true,
                     'autosubmit'    => true,
-                    'label'         => mt('monitoring', 'Instance Type'),
+                    'label'         => $this->translate('Instance Type'),
                     'multiOptions'  => array(
-                        LocalCommandFile::TRANSPORT     => mt('monitoring', 'Local Command File'),
-                        RemoteCommandFile::TRANSPORT    => mt('monitoring', 'Remote Command File')
+                        LocalCommandFile::TRANSPORT     => $this->translate('Local Command File'),
+                        RemoteCommandFile::TRANSPORT    => $this->translate('Remote Command File')
                     ),
                     'value' => $instanceType
                 )
diff --git a/modules/monitoring/application/forms/Config/SecurityConfigForm.php b/modules/monitoring/application/forms/Config/SecurityConfigForm.php
index 40c0b7b8c..b202f5938 100644
--- a/modules/monitoring/application/forms/Config/SecurityConfigForm.php
+++ b/modules/monitoring/application/forms/Config/SecurityConfigForm.php
@@ -18,7 +18,7 @@ class SecurityConfigForm extends ConfigForm
     public function init()
     {
         $this->setName('form_config_monitoring_security');
-        $this->setSubmitLabel(mt('monitoring', 'Save Changes'));
+        $this->setSubmitLabel($this->translate('Save Changes'));
     }
 
     /**
@@ -29,7 +29,7 @@ class SecurityConfigForm extends ConfigForm
         $this->config->setSection('security', $this->getValues());
 
         if ($this->save()) {
-            Notification::success(mt('monitoring', 'New security configuration has successfully been stored'));
+            Notification::success($this->translate('New security configuration has successfully been stored'));
         } else {
             return false;
         }
@@ -54,8 +54,8 @@ class SecurityConfigForm extends ConfigForm
             array(
                 'allowEmpty'    => true,
                 'value'         => '*pw*,*pass*,community',
-                'label'         => mt('monitoring', 'Protected Custom Variables'),
-                'description'   => mt('monitoring',
+                'label'         => $this->translate('Protected Custom Variables'),
+                'description'   => $this->translate(
                     'Comma separated case insensitive list of protected custom variables.'
                     . ' Use * as a placeholder for zero or more wildcard characters.'
                     . ' Existance of those custom variables will be shown, but their values will be masked.'
diff --git a/modules/monitoring/application/forms/EventOverviewForm.php b/modules/monitoring/application/forms/EventOverviewForm.php
index 25d268f76..dc697b940 100644
--- a/modules/monitoring/application/forms/EventOverviewForm.php
+++ b/modules/monitoring/application/forms/EventOverviewForm.php
@@ -44,7 +44,7 @@ class EventOverviewForm extends Form
             'checkbox',
             'statechange',
             array(
-                'label' => t('State Changes'),
+                'label' => $this->translate('State Changes'),
                 'class' => 'autosubmit',
                 'decorators' => $decorators,
                 'value' => strpos($url, $this->stateChangeFilter()->toQueryString()) === false ? 0 : 1
@@ -54,7 +54,7 @@ class EventOverviewForm extends Form
             'checkbox',
             'downtime',
             array(
-                'label' => t('Downtimes'),
+                'label' => $this->translate('Downtimes'),
                 'class' => 'autosubmit',
                 'decorators' => $decorators,
                 'value' => strpos($url, $this->downtimeFilter()->toQueryString()) === false ? 0 : 1
@@ -64,7 +64,7 @@ class EventOverviewForm extends Form
             'checkbox',
             'comment',
             array(
-                'label' => t('Comments'),
+                'label' => $this->translate('Comments'),
                 'class' => 'autosubmit',
                 'decorators' => $decorators,
                 'value' => strpos($url, $this->commentFilter()->toQueryString()) === false ? 0 : 1
@@ -74,7 +74,7 @@ class EventOverviewForm extends Form
             'checkbox',
             'notification',
             array(
-                'label' => t('Notifications'),
+                'label' => $this->translate('Notifications'),
                 'class' => 'autosubmit',
                 'decorators' => $decorators,
                 'value' => strpos($url, $this->notificationFilter()->toQueryString()) === false ? 0 : 1
@@ -84,7 +84,7 @@ class EventOverviewForm extends Form
             'checkbox',
             'flapping',
             array(
-                'label' => t('Flapping'),
+                'label' => $this->translate('Flapping'),
                 'class' => 'autosubmit',
                 'decorators' => $decorators,
                 'value' => strpos($url, $this->flappingFilter()->toQueryString()) === false ? 0 : 1
diff --git a/modules/monitoring/application/forms/Setup/BackendPage.php b/modules/monitoring/application/forms/Setup/BackendPage.php
index 1f6ef6894..b5ab2ffd6 100644
--- a/modules/monitoring/application/forms/Setup/BackendPage.php
+++ b/modules/monitoring/application/forms/Setup/BackendPage.php
@@ -20,7 +20,7 @@ class BackendPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('monitoring', 'Monitoring Backend', 'setup.page.title'),
+                'value'         => $this->translate('Monitoring Backend', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -31,8 +31,7 @@ class BackendPage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'Please configure below how Icinga Web 2 should retrieve monitoring information.'
                 )
             )
@@ -44,8 +43,8 @@ class BackendPage extends Form
             array(
                 'required'      => true,
                 'value'         => 'icinga',
-                'label'         => mt('monitoring', 'Backend Name'),
-                'description'   => mt('monitoring', 'The identifier of this backend')
+                'label'         => $this->translate('Backend Name'),
+                'description'   => $this->translate('The identifier of this backend')
             )
         );
 
@@ -60,8 +59,10 @@ class BackendPage extends Form
             'type',
             array(
                 'required'      => true,
-                'label'         => mt('monitoring', 'Backend Type'),
-                'description'   => mt('monitoring', 'The data source used for retrieving monitoring information'),
+                'label'         => $this->translate('Backend Type'),
+                'description'   => $this->translate(
+                    'The data source used for retrieving monitoring information'
+                ),
                 'multiOptions'  => $resourceTypes
             )
         );
diff --git a/modules/monitoring/application/forms/Setup/IdoResourcePage.php b/modules/monitoring/application/forms/Setup/IdoResourcePage.php
index 189d65fea..c28b52e6b 100644
--- a/modules/monitoring/application/forms/Setup/IdoResourcePage.php
+++ b/modules/monitoring/application/forms/Setup/IdoResourcePage.php
@@ -28,7 +28,7 @@ class IdoResourcePage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('monitoring', 'Monitoring IDO Resource', 'setup.page.title'),
+                'value'         => $this->translate('Monitoring IDO Resource', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -39,8 +39,7 @@ class IdoResourcePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'Please fill out the connection details below to access'
                     . ' the IDO database of your monitoring environment.'
                 )
@@ -91,8 +90,10 @@ class IdoResourcePage extends Form
             'skip_validation',
             array(
                 'required'      => true,
-                'label'         => t('Skip Validation'),
-                'description'   => t('Check this to not to validate connectivity with the given database server')
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate(
+                    'Check this to not to validate connectivity with the given database server'
+                )
             )
         );
     }
diff --git a/modules/monitoring/application/forms/Setup/InstancePage.php b/modules/monitoring/application/forms/Setup/InstancePage.php
index dccfd1d91..8f151554d 100644
--- a/modules/monitoring/application/forms/Setup/InstancePage.php
+++ b/modules/monitoring/application/forms/Setup/InstancePage.php
@@ -20,7 +20,7 @@ class InstancePage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('monitoring', 'Monitoring Instance', 'setup.page.title'),
+                'value'         => $this->translate('Monitoring Instance', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -31,8 +31,7 @@ class InstancePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'Please define the settings specific to your monitoring instance below.'
                 )
             )
diff --git a/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php b/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php
index 4faa17416..245d2abcc 100644
--- a/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php
+++ b/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php
@@ -28,7 +28,7 @@ class LivestatusResourcePage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('monitoring', 'Monitoring Livestatus Resource', 'setup.page.title'),
+                'value'         => $this->translate('Monitoring Livestatus Resource', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -39,8 +39,7 @@ class LivestatusResourcePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'Please fill out the connection details below to access the Livestatus'
                     . ' socket interface for your monitoring environment.'
                 )
@@ -91,8 +90,10 @@ class LivestatusResourcePage extends Form
             'skip_validation',
             array(
                 'required'      => true,
-                'label'         => t('Skip Validation'),
-                'description'   => t('Check this to not to validate connectivity with the given Livestatus socket')
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate(
+                    'Check this to not to validate connectivity with the given Livestatus socket'
+                )
             )
         );
     }
diff --git a/modules/monitoring/application/forms/Setup/SecurityPage.php b/modules/monitoring/application/forms/Setup/SecurityPage.php
index 0c7d3d1de..ba8083e50 100644
--- a/modules/monitoring/application/forms/Setup/SecurityPage.php
+++ b/modules/monitoring/application/forms/Setup/SecurityPage.php
@@ -20,7 +20,7 @@ class SecurityPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('monitoring', 'Monitoring Security', 'setup.page.title'),
+                'value'         => $this->translate('Monitoring Security', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -31,8 +31,7 @@ class SecurityPage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'To protect your monitoring environment against prying eyes please fill out the settings below.'
                 )
             )
diff --git a/modules/monitoring/application/forms/Setup/WelcomePage.php b/modules/monitoring/application/forms/Setup/WelcomePage.php
index d910e2e01..f79eb6c62 100644
--- a/modules/monitoring/application/forms/Setup/WelcomePage.php
+++ b/modules/monitoring/application/forms/Setup/WelcomePage.php
@@ -19,10 +19,7 @@ class WelcomePage extends Form
             'note',
             'welcome',
             array(
-                'value' => mt(
-                    'monitoring',
-                    'Welcome to the configuration of the monitoring module for Icinga Web 2!'
-                ),
+                'value' => $this->translate('Welcome to the configuration of the monitoring module for Icinga Web 2!'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -34,7 +31,7 @@ class WelcomePage extends Form
             'note',
             'core_hint',
             array(
-                'value' => mt('monitoring', 'This is the core module for Icinga Web 2.')
+                'value' => $this->translate('This is the core module for Icinga Web 2.')
             )
         );
 
@@ -42,8 +39,7 @@ class WelcomePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'monitoring',
+                'value' => $this->translate(
                     'It offers various status and reporting views with powerful filter capabilities that allow'
                     . ' you to keep track of the most important events in your monitoring environment.'
                 )
diff --git a/modules/monitoring/application/forms/StatehistoryForm.php b/modules/monitoring/application/forms/StatehistoryForm.php
index 9fa1bdc26..d859f5815 100644
--- a/modules/monitoring/application/forms/StatehistoryForm.php
+++ b/modules/monitoring/application/forms/StatehistoryForm.php
@@ -19,7 +19,7 @@ class StatehistoryForm extends Form
     public function init()
     {
         $this->setName('form_event_overview');
-        $this->setSubmitLabel(mt('monitoring', 'Apply'));
+        $this->setSubmitLabel($this->translate('Apply'));
     }
 
     /**
@@ -65,14 +65,14 @@ class StatehistoryForm extends Form
             'select',
             'from',
             array(
-                'label' => mt('monitoring', 'From'),
+                'label' => $this->translate('From'),
                 'value' => $this->getRequest()->getParam('from', strtotime('3 months ago')),
                 'multiOptions' => array(
-                    strtotime('midnight 3 months ago') => mt('monitoring', '3 Months'),
-                    strtotime('midnight 4 months ago') => mt('monitoring', '4 Months'),
-                    strtotime('midnight 8 months ago') => mt('monitoring', '8 Months'),
-                    strtotime('midnight 12 months ago') => mt('monitoring', '1 Year'),
-                    strtotime('midnight 24 months ago') => mt('monitoring', '2 Years')
+                    strtotime('midnight 3 months ago') => $this->translate('3 Months'),
+                    strtotime('midnight 4 months ago') => $this->translate('4 Months'),
+                    strtotime('midnight 8 months ago') => $this->translate('8 Months'),
+                    strtotime('midnight 12 months ago') => $this->translate('1 Year'),
+                    strtotime('midnight 24 months ago') => $this->translate('2 Years')
                 ),
                 'class' => 'autosubmit'
             )
@@ -81,10 +81,10 @@ class StatehistoryForm extends Form
             'select',
             'to',
             array(
-                'label' => mt('monitoring', 'To'),
+                'label' => $this->translate('To'),
                 'value' => $this->getRequest()->getParam('to', time()),
                 'multiOptions' => array(
-                    time() => mt('monitoring', 'Today')
+                    time() => $this->translate('Today')
                 ),
                 'class' => 'autosubmit'
             )
@@ -95,11 +95,11 @@ class StatehistoryForm extends Form
             'select',
             'objecttype',
             array(
-                'label' => mt('monitoring', 'Object type'),
+                'label' => $this->translate('Object type'),
                 'value' => $objectType,
                 'multiOptions' => array(
-                    'services' => mt('monitoring', 'Services'),
-                    'hosts' => mt('monitoring', 'Hosts')
+                    'services' => $this->translate('Services'),
+                    'hosts' => $this->translate('Hosts')
                 ),
                 'class' => 'autosubmit'
             )
@@ -113,13 +113,13 @@ class StatehistoryForm extends Form
                 'select',
                 'state',
                 array(
-                    'label' => mt('monitoring', 'State'),
+                    'label' => $this->translate('State'),
                     'value' => $serviceState,
                     'multiOptions' => array(
-                        'cnt_critical_hard' => mt('monitoring', 'Critical'),
-                        'cnt_warning_hard' => mt('monitoring', 'Warning'),
-                        'cnt_unknown_hard' => mt('monitoring', 'Unknown'),
-                        'cnt_ok' => mt('monitoring', 'Ok')
+                        'cnt_critical_hard' => $this->translate('Critical'),
+                        'cnt_warning_hard' => $this->translate('Warning'),
+                        'cnt_unknown_hard' => $this->translate('Unknown'),
+                        'cnt_ok' => $this->translate('Ok')
                     ),
                     'class' => 'autosubmit'
                 )
@@ -133,12 +133,12 @@ class StatehistoryForm extends Form
                 'select',
                 'state',
                 array(
-                    'label' => mt('monitoring', 'State'),
+                    'label' => $this->translate('State'),
                     'value' => $hostState,
                     'multiOptions' =>  array(
-                        'cnt_up' => mt('monitoring', 'Up'),
-                        'cnt_down_hard' => mt('monitoring', 'Down'),
-                        'cnt_unreachable_hard' => mt('monitoring', 'Unreachable')
+                        'cnt_up' => $this->translate('Up'),
+                        'cnt_down_hard' => $this->translate('Down'),
+                        'cnt_unreachable_hard' => $this->translate('Unreachable')
                     ),
                     'class' => 'autosubmit'
                 )
diff --git a/modules/monitoring/application/views/helpers/Link.php b/modules/monitoring/application/views/helpers/Link.php
new file mode 100644
index 000000000..0d8c35861
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/Link.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * Helper for generating frequently used jump links
+ *
+ * Most of the monitoring overviews link to detail information, e.g. the full information of the involved monitored
+ * object. Instead of reintroducing link generation and translation in those views, this helper contains most
+ * frequently used jump links.
+ */
+class Zend_View_Helper_Link extends Zend_View_Helper_Abstract
+{
+    /**
+     * Helper entry point
+     *
+     * @return $this
+     */
+    public function link()
+    {
+        return $this;
+    }
+
+    /**
+     * Create a host link
+     *
+     * @param   string  $host       Hostname
+     * @param   string  $linkText   Link text, e.g. the host's display name
+     *
+     * @return  string
+     */
+    public function host($host, $linkText)
+    {
+        return $this->view->qlink(
+            $linkText,
+            $this->view->href('monitoring/host/show', array('host' => $host))
+        );
+    }
+
+    /**
+     * Create a service link
+     *
+     * @param   string  $service            Service name
+     * @param   string  $serviceLinkText    Text for the service link, e.g. the service's display name
+     * @param   string  $host               Hostname
+     * @param   string  $hostLinkText       Text for the host link, e.g. the host's display name
+     *
+     * @return  string
+     */
+    public function service($service, $serviceLinkText, $host, $hostLinkText)
+    {
+        return sprintf(
+            $this->view->translate('%s on %s', 'Service running on host'),
+            $this->view->qlink(
+                $serviceLinkText,
+                $this->view->href('monitoring/service/show', array('host' => $host, 'service' => $service))
+            ),
+            $this->host($host, $hostLinkText)
+        );
+    }
+}
diff --git a/modules/monitoring/application/views/helpers/MonitoringState.php b/modules/monitoring/application/views/helpers/MonitoringState.php
deleted file mode 100644
index 13bd93ea7..000000000
--- a/modules/monitoring/application/views/helpers/MonitoringState.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-/**
- * @deprecated Most of these helpers are currently only used in the MultiController, which is probably obsolete
- */
-class Zend_View_Helper_MonitoringState extends Zend_View_Helper_Abstract
-{
-    private $servicestates = array('ok', 'warning', 'critical', 'unknown', 99 => 'pending', null => 'pending');
-    private $hoststates = array('up', 'down', 'unreachable', 99 => 'pending', null => 'pending');
-
-    /**
-     * @deprecated Not used anywhere.
-     */
-    public function monitoringState($object, $type = 'service')
-    {
-        if ($type === 'service') {
-            return $this->servicestates[$object->service_state];
-        } elseif ($type === 'host') {
-            return $this->hoststates[$object->host_state];
-        }
-    }
-
-    /**
-     * @deprecated Not used anywhere.
-     */
-    public function monitoringStateById($id, $type = 'service')
-    {
-        if ($type === 'service') {
-            return $this->servicestates[$id];
-        } elseif ($type === 'host') {
-            return $this->hoststates[$id];
-        }
-    }
-
-    /**
-     * @deprecated Monitoring colors are clustered.
-     */
-    public function getServiceStateColors()
-    {
-        return array('#44bb77', '#FFCC66', '#FF5566', '#E066FF', '#77AAFF');
-    }
-
-    /**
-     * @deprecated Monitoring colors are clustered.
-     */
-    public function getHostStateColors()
-    {
-        return array('#44bb77', '#FF5566', '#E066FF', '#77AAFF');
-    }
-
-    /**
-     * @deprecated The service object must know about it's possible states.
-     */
-    public function getServiceStateNames()
-    {
-        return array_values($this->servicestates);
-    }
-
-    /**
-     * @deprecated The host object must know about it's possible states.
-     */
-    public function getHostStateNames()
-    {
-        return array_values($this->hoststates);
-    }
-
-    /**
-     * @deprecated Not used anywhere.
-     */
-    public function getStateFlags($object, $type = 'service')
-    {
-        $state_classes = array();
-        if ($type === 'host') {
-            $state_classes[] = $this->monitoringState($object, "host");
-            if ($object->host_acknowledged || $object->host_in_downtime) {
-                $state_classes[] = 'handled';
-            }
-            if ($object->host_last_state_change > (time() - 600)) {
-                $state_classes[] = 'new';
-            }
-        } else {
-            $state_classes[] = $this->monitoringState($object, "service");
-            if ($object->service_acknowledged || $object->service_in_downtime) {
-                $state_classes[] = 'handled';
-            }
-            if ($object->service_last_state_change > (time() - 600)) {
-                $state_classes[] = 'new';
-            }
-        }
-
-        return $state_classes;
-    }
-
-    /**
-     * @deprecated Not used anywhere.
-     */
-    public function getStateTitle($object, $type)
-    {
-        return sprintf(
-            '%s %s %s',
-             $this->view->translate(strtoupper($this->monitoringState($object, $type))),
-            $this->view->translate('since'),
-            date('Y-m-d H:i:s', $object->{$type.'_last_state_change'})
-        );
-    }
-}
diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php
index eb649e77d..4c2bee89a 100644
--- a/modules/monitoring/application/views/helpers/Perfdata.php
+++ b/modules/monitoring/application/views/helpers/Perfdata.php
@@ -8,34 +8,52 @@ use Icinga\Module\Monitoring\Plugin\Perfdata;
 use Icinga\Module\Monitoring\Plugin\PerfdataSet;
 
 class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
-{
-    public function perfdata($perfdataStr, $compact = false)
+{#
+
+    /**
+     * Display the given perfdata string to the user
+     *
+     * @param      $perfdataStr The perfdata string
+     * @param bool $compact     Whether to display the perfdata in compact mode
+     * @param      $color       The color indicating the perfdata state
+     *
+     * @return string
+     */
+    public function perfdata($perfdataStr, $compact = false, $color = Perfdata::PERFDATA_OK)
     {
-        $pset = PerfdataSet::fromString($perfdataStr)->asArray();
-        $onlyPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() > 0; });
-        if ($compact) {
-            $onlyPieChartData = array_slice($onlyPieChartData, 0, 5);
-        } else {
-            $nonPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() == 0; });
-        }
+        $pieChartData = PerfdataSet::fromString($perfdataStr)->asArray();
 
         $result = '';
-        $table = array();
-        foreach ($onlyPieChartData as $perfdata) {
-            $pieChart = $this->createInlinePie($perfdata);
-            if ($compact) {
-                $result .= $pieChart->render();
+        $table = array(
+            '<td><b>' . implode(
+                '</b></td><td><b>',
+                array('', t('Label'), t('Value'), t('Min'), t('Max'), t('Warning'), t('Critical'))
+            ) . '<b></td>'
+        );
+        foreach ($pieChartData as $perfdata) {
+
+            if ($compact && $perfdata->isVisualizable()) {
+                $result .= $perfdata->asInlinePie($color)->render();
             } else {
-                if (! $perfdata->isPercentage()) {
-                    // TODO: Should we trust sprintf-style placeholders in perfdata titles?
-                    $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)');
+                $row = '<tr>';
+
+                $row .= '<td>';
+                if ($perfdata->isVisualizable()) {
+                    $row .= $perfdata->asInlinePie($color)->render() . '&nbsp;';
                 }
-                // $pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;');
-                $table[] = '<tr><th>' . $pieChart->render()
-                    . htmlspecialchars($perfdata->getLabel())
-                    . '</th><td> '
-                    . htmlspecialchars($this->formatPerfdataValue($perfdata)) .
-                    ' </td></tr>';
+                $row .= '</td>';
+
+                if (!$compact) {
+                    foreach ($perfdata->toArray() as $value) {
+                        if ($value === '') {
+                            $value = '-';
+                        }
+                        $row .= '<td>' . (string)$value  . '</td>';
+                    }
+                }
+
+                $row .= '</tr>';
+                $table[] = $row;
             }
         }
 
@@ -43,63 +61,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
             return $result;
         } else {
             $pieCharts = empty($table) ? '' : '<table class="perfdata">' . implode("\n", $table) . '</table>';
-            return $pieCharts . "\n" . implode("<br>\n", $nonPieChartData);
+            return $pieCharts;
         }
     }
-
-    protected function calculatePieChartData(Perfdata $perfdata)
-    {
-        $rawValue = $perfdata->getValue();
-        $minValue = $perfdata->getMinimumValue() !== null ? $perfdata->getMinimumValue() : 0;
-        $maxValue = $perfdata->getMaximumValue();
-        $usedValue = ($rawValue - $minValue);
-        $unusedValue = ($maxValue - $minValue) - $usedValue;
-
-        $gray = $unusedValue;
-        $green = $orange = $red = 0;
-        // TODO(#6122): Add proper treshold parsing.
-        if ($perfdata->getCriticalThreshold() && $perfdata->getValue() > $perfdata->getCriticalThreshold()) {
-            $red = $usedValue;
-        } elseif ($perfdata->getWarningThreshold() && $perfdata->getValue() > $perfdata->getWarningThreshold()) {
-            $orange = $usedValue;
-        } else {
-            $green = $usedValue;
-        }
-
-        return array($green, $orange, $red, $gray);
-    }
-
-    protected function formatPerfdataValue(Perfdata $perfdata)
-    {
-        if ($perfdata->isBytes()) {
-            return Format::bytes($perfdata->getValue());
-        } elseif ($perfdata->isSeconds()) {
-            return Format::seconds($perfdata->getValue());
-        } elseif ($perfdata->isPercentage()) {
-            return $perfdata->getValue() . '%';
-        }
-
-        return $perfdata->getValue();
-    }
-
-    protected function createInlinePie(Perfdata $perfdata)
-    {
-        $pieChart = new InlinePie($this->calculatePieChartData($perfdata), $perfdata->getLabel());
-        $pieChart->setLabel(htmlspecialchars($perfdata->getLabel()));
-        $pieChart->setHideEmptyLabel();
-
-        //$pieChart->setHeight(32)->setWidth(32);
-        if ($perfdata->isBytes()) {
-            $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)');
-            $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_BYTES);
-        } else if ($perfdata->isSeconds()) {
-            $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)');
-            $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_TIME);
-        } else {
-            $pieChart->setTooltipFormat('{{label}}: {{formatted}}%');
-            $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_RATIO);
-            $pieChart->setHideEmptyLabel();
-        }
-        return $pieChart;
-    }
 }
diff --git a/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php b/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php
deleted file mode 100644
index d7612ac30..000000000
--- a/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-class Zend_View_Helper_RenderServicePerfdata extends Zend_View_Helper_Abstract
-{
-    private static $RENDERMAP = array(
-        "check_local_disk" =>  array("self::renderDiskPie")
-    );
-
-    public function renderServicePerfdata($service)
-    {
-        if (isset(self::$RENDERMAP[$service->check_command])) {
-            $fn = self::$RENDERMAP[$service->check_command];
-            $fn($service);
-        }
-    }
-
-    public static function renderDiskPie($service) {
-        $perfdata = $service->performance_data;
-        if(!$perfdata)
-            return "";
-
-    }
-}
diff --git a/modules/monitoring/application/views/scripts/alertsummary/index.phtml b/modules/monitoring/application/views/scripts/alertsummary/index.phtml
index 624b942b3..dbfff6433 100644
--- a/modules/monitoring/application/views/scripts/alertsummary/index.phtml
+++ b/modules/monitoring/application/views/scripts/alertsummary/index.phtml
@@ -1,6 +1,3 @@
-<?php
-$helper = $this->getHelper('MonitoringState');
-?>
 <div class="controls">
     <?= $this->tabs ?>
     <div style="margin: 1em;" class="dontprint">
diff --git a/modules/monitoring/application/views/scripts/chart/test.phtml b/modules/monitoring/application/views/scripts/chart/test.phtml
index 1c2046bdf..214f44d33 100644
--- a/modules/monitoring/application/views/scripts/chart/test.phtml
+++ b/modules/monitoring/application/views/scripts/chart/test.phtml
@@ -1,6 +1,5 @@
-mah
-<div style="border:1px dashed black;width:900px;height:520px">
-<?=
-  $svg->render();
-?>
-</div>
\ No newline at end of file
+<?php foreach ($svgs as $svg) { ?>
+    <div style="border:1px dashed black;width:900px;height:520px">
+        <?= $svg->render() ?>
+    </div>
+<?php } ?>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/command/list.phtml b/modules/monitoring/application/views/scripts/command/list.phtml
deleted file mode 100644
index 747dd4b5e..000000000
--- a/modules/monitoring/application/views/scripts/command/list.phtml
+++ /dev/null
@@ -1,10 +0,0 @@
-<h4><?= mt('monitoring', 'List Of Supported Commands'); ?></h4>
-<ul>
-  <?php foreach($this->commands as $command): ?>
-  <li>
-    <a href="<?= $this->href('monitoring/command/'. $command); ?>">
-      <?= $this->escape($command); ?>
-    </a>
-  </li>
-  <?php endforeach; ?>
-</ul>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/command/renderform.phtml b/modules/monitoring/application/views/scripts/command/renderform.phtml
deleted file mode 100644
index 9c8e79428..000000000
--- a/modules/monitoring/application/views/scripts/command/renderform.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<div class="controls">
-<?= $this->tabs ?>
-</div>
-<div class="content">
-<?php if (isset($this->objects) && !empty($this->objects) && isset($this->objects[0]->host_name)): ?>
-<table class="objectlist">
-  <thead>
-    <tr>
-      <th><?= $this->icon('host') ?> Host</th>
-      <th><?= $this->icon('conf') ?> Service</th>
-    </tr>
-  </thead>
-    <tbody>
-<?php foreach ($this->objects as $object): ?>
-      <tr>
-        <td><?= $object->host_name; ?></td>
-        <td><?= (isset($object->service_description) ? $object->service_description : '') ?></td>
-      </tr>
-<?php endforeach; ?>
-    </tbody>
-</table>
-
-<?php endif ?>
-<?= $this->form ?>
-</div>
diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml
index b1729f9b1..deca8d468 100644
--- a/modules/monitoring/application/views/scripts/config/index.phtml
+++ b/modules/monitoring/application/views/scripts/config/index.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_right">
   <?= $tabs; ?>
   <h1><?= $this->translate('Monitoring Backends') ?></h1>
 </div>
diff --git a/modules/monitoring/application/views/scripts/config/security.phtml b/modules/monitoring/application/views/scripts/config/security.phtml
index 71f2a341a..2a84b2469 100644
--- a/modules/monitoring/application/views/scripts/config/security.phtml
+++ b/modules/monitoring/application/views/scripts/config/security.phtml
@@ -1,4 +1,4 @@
-<div class="controls">
+<div class="controls" data-base-target="_right">
     <?= $this->tabs ?>
 </div>
 <div class="content">
diff --git a/modules/monitoring/application/views/scripts/hosts/show.phtml b/modules/monitoring/application/views/scripts/hosts/show.phtml
index 6e114f2d8..f21c09fd1 100644
--- a/modules/monitoring/application/views/scripts/hosts/show.phtml
+++ b/modules/monitoring/application/views/scripts/hosts/show.phtml
@@ -2,25 +2,31 @@
     <?= $this->tabs ?>
 </div>
 <div class="content">
-    <?php if (count($objects) === 0): ?>
+    <?php $hostCount = count($objects) ?>
+    <?php if ($hostCount === 0): ?>
         <?= $this->translate('No hosts matching the filter') ?>
     <?php else: ?>
         <div class="hbox-item">
-            <b><?= sprintf($this->translate('Hosts (%u)'), array_sum(array_values($hostStates)))  ?></b>
+            <b><?= sprintf($this->translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount) ?></b>
         </div>
         <div class="hbox-item">
-            <?= $this->hostStatesPieChart ?>
+            &nbsp;<?= $this->hostStatesPieChart ?>
         </div>
         <div class="hbox-item" style="font-size: 14px">
             <?php foreach (array_filter($hostStates) as $text => $count) {
-                echo sprintf('%s: %u <br>', strtoupper($text), $count);
+                echo sprintf('%s: %u <br>', $this->translate(strtoupper($text)), $count);
             } ?>
         </div>
 
         <h3>
-            <?= sprintf($this->translate('%u Hosts'),
-                count($objects))
-            ?>
+            <?= sprintf(
+                $this->translatePlural(
+                    '%u Host',
+                    '%u Hosts',
+                     $hostCount
+                ),
+                $hostCount
+            ) ?>
         </h3>
 
         <div>
@@ -59,13 +65,14 @@
 
         <?php if (! empty($unhandledObjects)): ?>
         <h3>
+            <?php $unhandledCount = count($unhandledObjects) ?>
             <?= sprintf(
                 $this->translatePlural(
                     '%u Unhandled Host Problem',
                     '%u Unhandled Host Problems',
-                    count($unhandledObjects)
+                    $unhandledCount
                 ),
-                count($unhandledObjects)
+                $unhandledCount
             ) ?>
         </h3>
         <div>
@@ -86,13 +93,14 @@
 
         <?php if (! empty($acknowledgedObjects)): ?>
             <h2>
+                <?php $acknowledgedCount = count($acknowledgedObjects) ?>
                 <?= sprintf(
                     $this->translatePlural(
                         '%u Acknowledged Host Problem',
                         '%u Acknowledged Host Problems',
-                        count($acknowledgedObjects)
+                        $acknowledgedCount
                     ),
-                    count($acknowledgedObjects)
+                    $acknowledgedCount
                 ) ?>
             </h2>
             <div>
@@ -102,25 +110,27 @@
 
         <?php if (! empty($objectsInDowntime)): ?>
             <h2>
+                <?php $inDowntimeCount = count($objectsInDowntime) ?>
                 <a href="<?= $inDowntimeLink ?>"
                    title="<?php printf(
                         $this->translate('List all hosts in downtime (%u)'),
                         count($objectsInDowntime)
                     ); ?>">
                     <?= $this->icon('plug') ?>
-                    <?php printf(
+                    <?= sprintf(
                         $this->translatePlural(
                             '%u host is in downtime',
                             '%u hosts are in downtime',
-                            count($objectsInDowntime)
+                            $inDowntimeCount
                         ),
-                        count($objectsInDowntime)
-                    ); ?>
+                        $inDowntimeCount
+                    ) ?>
                 </a>
             </h2>
         <?php endif ?>
 
-        <?php if (count($objects->getComments())): ?>
+        <?php $havingCommentsCount = count($objects->getComments()) ?>
+        <?php if ($havingCommentsCount): ?>
             <h2>
                 <a href="<?= $havingCommentsLink ?>"
                    title="<?php printf(
@@ -128,7 +138,14 @@
                         count($objects->getComments())
                     ); ?>">
                     <?= $this->icon('comment') ?>
-                    <?= $this->translate(sprintf('%u comments', count($objects->getComments()))) ?>
+                    <?= sprintf(
+                        $this->translatePlural(
+                            '%u comment',
+                            '%u comments',
+                            $havingCommentsCount
+                        ),
+                        $havingCommentsCount
+                    ) ?>
                 </a>
             </h2>
         <?php endif ?>
diff --git a/modules/monitoring/application/views/scripts/layout/topbar.phtml b/modules/monitoring/application/views/scripts/layout/topbar.phtml
deleted file mode 100644
index f7c58db85..000000000
--- a/modules/monitoring/application/views/scripts/layout/topbar.phtml
+++ /dev/null
@@ -1,65 +0,0 @@
-<div class="nav navbar-nav topbar-host-status-summary">
-    <span class="topbar-status-up">
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 0)); ?>" title="<?= $this->translate('Hosts Up') ?>">
-            <?= $hostSummary->hosts_up ?>
-        </a>
-    </span>
-    <span class="topbar-status-down">
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 1, 'host_unhandled' => 1)); ?>" title="<?= $this->translate('Hosts Down Unhandled') ?>">
-            <?= $hostSummary->hosts_down_unhandled ?>
-        </a>/
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 1, 'host_handled' => 1)); ?>" title="<?= $this->translate('Hosts Down Handled') ?>">
-            <?= $hostSummary->hosts_down_handled ?>
-        </a>
-    </span>
-    <span class="topbar-status-unreachable">
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 2, 'host_unhandled' => 1)); ?>" title="<?= $this->translate('Hosts Unreachable Unhandled') ?>">
-            <?= $hostSummary->hosts_unreachable_unhandled ?>
-        </a>/
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 2, 'host_handled' => 1)); ?>" title="<?= $this->translate('Hosts Unreachable Handled') ?>">
-            <?= $hostSummary->hosts_unreachable_handled ?>
-        </a>
-    </span>
-    <span class="topbar-status-pending">
-        <a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 99)); ?>" title="<?= $this->translate('Hosts Pending') ?>">
-            <?= $hostSummary->hosts_pending ?>
-        </a>
-    </span>
-</div>
-
-<div class="nav navbar-nav topbar-service-status-summary">
-    <span class="topbar-status-ok">
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 0)); ?>" title="<?= $this->translate('Services Ok') ?>">
-            <?= $serviceSummary->services_ok ?>
-        </a>
-    </span>
-    <span class="topbar-status-critical">
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 2, 'service_unhandled' => 1)); ?>" title="<?= $this->translate('Services Critical Unhandled') ?>">
-            <?= $serviceSummary->services_critical_unhandled ?>
-        </a>/
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 2, 'service_handled' => 1)); ?>" title="<?= $this->translate('Services Critical Handled') ?>">
-            <?= $serviceSummary->services_critical_handled ?>
-        </a>
-    </span>
-    <span class="topbar-status-warning">
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_unhandled' => 1)); ?>" title="<?= $this->translate('Services Warning Unhandled') ?>">
-            <?= $serviceSummary->services_warning_unhandled ?>
-        </a>/
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_handled' => 1)); ?>" title="<?= $this->translate('Services Warning Handled') ?>">
-            <?= $serviceSummary->services_warning_handled ?>
-        </a>
-    </span>
-    <span class="topbar-status-unknown">
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 3, 'service_unhandled' => 1)); ?>" title="<?= $this->translate('Services Unknown Unhandled') ?>">
-            <?= $serviceSummary->services_unknown_unhandled ?>
-        </a>/
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 3, 'service_handled' => 1)); ?>" title="<?= $this->translate('Services Unknown Handled') ?>">
-            <?= $serviceSummary->services_unknown_handled ?>
-        </a>
-    </span>
-    <span class="topbar-status-pending">
-        <a href="<?= $this->href('monitoring/list/services', array('service_state' => 99)); ?>" title="<?= $this->translate('Services Pending') ?>">
-            <?= $serviceSummary->services_pending ?>
-        </a>
-    </span>
-</div>
diff --git a/modules/monitoring/application/views/scripts/list/comments.phtml b/modules/monitoring/application/views/scripts/list/comments.phtml
index 677010f1b..857017b4d 100644
--- a/modules/monitoring/application/views/scripts/list/comments.phtml
+++ b/modules/monitoring/application/views/scripts/list/comments.phtml
@@ -50,21 +50,13 @@
         </td>
         <td>
         <?php if ($comment->objecttype === 'service'): ?>
-          <?= $this->icon('conf'); ?> <a href="<?= $this->href('monitoring/service/show', array(
-            'host'    => $comment->host,
-            'service' => $comment->service,
-          )); ?>">
-            <?= $comment->service; ?>
-          </a>
-          <small>
-            <?= $this->translate('on') . ' ' . $comment->host; ?>
-          </small>
+          <?= $this->icon('service') ?>
+          <?= $this->link()->service(
+              $comment->service, $comment->service_display_name, $comment->host, $comment->host_display_name
+          ) ?>
         <?php else: ?>
-          <?= $this->icon('host'); ?> <a href="<?= $this->href('monitoring/host/show', array(
-            'host' => $comment->host
-          )); ?>">
-            <?= $comment->host; ?>
-          </a>
+          <?= $this->icon('host') ?>
+          <?= $this->link()->host($comment->host, $comment->host_display_name) ?>
         <?php endif ?>
           <br>
           <?= $this->icon('comment'); ?> <?= isset($comment->author)
@@ -83,18 +75,20 @@
               date('H:i', $comment->expiration)
             ) : $this->translate('This comment does not expire.'); ?>
         </td>
+        <?php if (isset($delCommentForm)): // Form is unset if the current user lacks the respective permission ?>
         <td style="width: 2em" data-base-target="self">
           <?php
           $delCommentForm = clone $delCommentForm;
           $delCommentForm->populate(array('comment_id' => $comment->id, 'redirect' => $this->url));
           if ($comment->objecttype === 'host') {
-            $delCommentForm->setAction($this->url('monitoring/host/remove-comment', array('host' => $comment->host)));
+            $delCommentForm->setAction($this->url('monitoring/host/delete-comment', array('host' => $comment->host)));
           } else {
-            $delCommentForm->setAction($this->url('monitoring/service/remove-comment', array('host' => $comment->host, 'service' => $comment->service)));
+            $delCommentForm->setAction($this->url('monitoring/service/delete-comment', array('host' => $comment->host, 'service' => $comment->service)));
           }
           echo $delCommentForm;
           ?>
         </td>
+        <?php endif ?>
       </tr>
 <?php endforeach ?>
     </tbody>
diff --git a/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml b/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml
index dab7071a1..c870b09b0 100644
--- a/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml
+++ b/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml
@@ -12,7 +12,7 @@ $currentUrl = Url::fromRequest()->getRelativeUrl();
     $this->stats->services_ok,
     $selfUrl,
     array('service_state' => 0),
-    array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('ok'))))
+    array('title' => sprintf($this->translate('Services with state %s'), $this->translate('OK')))
 )  ?></span>
 <?php endif ?>
 
@@ -44,7 +44,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
                 $this->stats->$unhandled,
                 $selfUrl,
                 $paramsUnhandled,
-                array('title' => sprintf($this->translate('Unhandled services with state %s'), strtoupper($this->translate($state))))
+                array('title' => sprintf($this->translate('Unhandled services with state %s'), $this->translate(strtoupper($state))))
             );
         }
         if ($this->stats->$handled) {
@@ -61,7 +61,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
                 $this->stats->$handled,
                 $selfUrl,
                 $paramsHandled,
-                array('title' => sprintf($this->translate('Handled services with state %s'), strtoupper($this->translate($state))))
+                array('title' => sprintf($this->translate('Handled services with state %s'), $this->translate(strtoupper($state))))
             );
             if ($this->stats->$unhandled) {
                 echo "</span>\n";
@@ -77,7 +77,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
     $this->stats->services_pending,
     $selfUrl,
     array('service_state' => 99),
-    array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('pending'))))
+    array('title' => sprintf($this->translate('Services with state %s'), $this->translate('PENDING')))
 )  ?></span>
 <?php endif ?>
 </span>
diff --git a/modules/monitoring/application/views/scripts/list/contacts.phtml b/modules/monitoring/application/views/scripts/list/contacts.phtml
index f6face461..d8d2a2e72 100644
--- a/modules/monitoring/application/views/scripts/list/contacts.phtml
+++ b/modules/monitoring/application/views/scripts/list/contacts.phtml
@@ -1,7 +1,3 @@
-<?php
-$viewHelper = $this->getHelper('MonitoringState');
-$contactHelper = $this->getHelper('ContactFlags');
-?>
 <div class="controls">
     <?= $this->tabs ?>
     <div style="margin: 1em">
diff --git a/modules/monitoring/application/views/scripts/list/downtimes.phtml b/modules/monitoring/application/views/scripts/list/downtimes.phtml
index 37b34fe5e..eaf4b7f8e 100644
--- a/modules/monitoring/application/views/scripts/list/downtimes.phtml
+++ b/modules/monitoring/application/views/scripts/list/downtimes.phtml
@@ -31,8 +31,10 @@ use Icinga\Module\Monitoring\Object\Service;
     <?php foreach ($downtimes as $downtime): ?>
     <?php
       if (isset($downtime->service)) {
+          $isService = true;
           $stateName = Service::getStateText($downtime->service_state);
       } else {
+          $isService = false;
           $stateName = Host::getStateText($downtime->host_state);
       }
     ?>
@@ -52,31 +54,25 @@ use Icinga\Module\Monitoring\Object\Service;
             ?>
         </td>
         <td>
-        <?php if (isset($downtime->service)): ?>
-          <a href="<?= $this->href('monitoring/service/show', array(
-            'host'      => $downtime->host,
-            'service'   => $downtime->service
-          )); ?>">
-            <?= $downtime->service; ?>
-          </a>
-          <small>
-            <?= $this->translate('on'); ?> <?= $downtime->host; ?>
-          </small>
+        <?php if ($isService): ?>
+          <?= $this->icon('service') ?>
+          <?= $this->link()->service(
+              $downtime->service, $downtime->service_display_name, $downtime->host, $downtime->host_display_name
+          ) ?>
         <?php else: ?>
-          <a href="<?= $this->href('monitoring/host/show', array(
-            'host' => $downtime->host
-          )); ?>">
-            <?= $downtime->host; ?>
-          </a>
+          <?= $this->icon('host') ?>
+          <?= $this->link()->host($downtime->host, $downtime->host_display_name) ?>
         <?php endif ?>
           <br>
-          <?= $this->icon('comment'); ?> [<?= $downtime->author; ?>] <?= $downtime->comment; ?>
+          <?= $this->icon('comment') ?> [<?= $this->escape($downtime->author) ?>] <?= $this->escape($downtime->comment) ?>
           <br>
           <small>
         <?php if ($downtime->is_flexible): ?>
           <?php if ($downtime->is_in_effect): ?>
             <?= sprintf(
-              $this->translate('This flexible downtime was started on %s at %s and lasts for %s until %s at %s.'),
+              isset($downtime->service)
+                ? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
+                : $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
               date('d.m.y', $downtime->start),
               date('H:i', $downtime->start),
               $this->format()->duration($downtime->duration),
@@ -85,7 +81,9 @@ use Icinga\Module\Monitoring\Object\Service;
             ); ?>
           <?php else: ?>
             <?= sprintf(
-              $this->translate('This flexible downtime has been scheduled to start between %s - %s and to last for %s.'),
+              isset($downtime->service)
+                ? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
+                : $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
               date('d.m.y H:i', $downtime->scheduled_start),
               date('d.m.y H:i', $downtime->scheduled_end),
               $this->format()->duration($downtime->duration)
@@ -94,7 +92,9 @@ use Icinga\Module\Monitoring\Object\Service;
         <?php else: ?>
           <?php if ($downtime->is_in_effect): ?>
             <?= sprintf(
-              $this->translate('This fixed downtime was started on %s at %s and expires on %s at %s.'),
+              isset($downtime->service)
+                ? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
+                : $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
               date('d.m.y', $downtime->start),
               date('H:i', $downtime->start),
               date('d.m.y', $downtime->end),
@@ -102,7 +102,9 @@ use Icinga\Module\Monitoring\Object\Service;
             ); ?>
           <?php else: ?>
             <?= sprintf(
-              $this->translate('This fixed downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
+              isset($downtime->service)
+                ? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
+                : $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
               date('d.m.y', $downtime->scheduled_start),
               date('H:i', $downtime->scheduled_start),
               date('d.m.y', $downtime->scheduled_end),
@@ -112,6 +114,7 @@ use Icinga\Module\Monitoring\Object\Service;
         <?php endif ?>
           </small>
         </td>
+        <?php if (isset($delDowntimeForm)): // Form is unset if the current user lacks the respective permission ?>
         <td style="width: 2em" data-base-target="self">
           <?php
           $delDowntimeForm = clone $delDowntimeForm;
@@ -124,6 +127,7 @@ use Icinga\Module\Monitoring\Object\Service;
           echo $delDowntimeForm;
           ?>
         </td>
+        <?php endif ?>
       </tr>
 <?php endforeach ?>
     </tbody>
diff --git a/modules/monitoring/application/views/scripts/list/eventhistory.phtml b/modules/monitoring/application/views/scripts/list/eventhistory.phtml
index a9516aab1..0b6b9bcec 100644
--- a/modules/monitoring/application/views/scripts/list/eventhistory.phtml
+++ b/modules/monitoring/application/views/scripts/list/eventhistory.phtml
@@ -70,21 +70,13 @@ use Icinga\Module\Monitoring\Object\Service;
           $icon = $isService ? 'service' : 'host';
           $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $event->output;
           $stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
-          $title = strtoupper(
-            $isService
-              ? Service::getStateText($event->state, true)
-              : Host::getStateText($event->state, true)
-          );
+          $title = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true);
           break;
         case 'soft_state':
           $icon = 'lightbulb';
           $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $event->output;
           $stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
-          $title = strtoupper(
-            $isService
-              ? Service::getStateText($event->state, true)
-              : Host::getStateText($event->state, true)
-          );
+          $title = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true);
           break;
         case 'dt_start':
           $icon = 'starttime';
@@ -106,25 +98,15 @@ use Icinga\Module\Monitoring\Object\Service;
         </td>
         <td>
         <?php if ($isService): ?>
-          <a href="<?= $this->href('monitoring/show/service', array(
-            'host'      => $event->host,
-            'service'   => $event->service
-          )); ?>">
-            <?= $event->service; ?>
-          </a>
-          <small>
-            <?= $this->translate('on') . ' ' . $event->host; ?>
-          </small>
+          <?= $this->link()->service(
+              $event->service, $event->service_display_name, $event->host, $event->host_display_name
+          ) ?>
         <?php else: ?>
-          <a href="<?= $this->href('monitoring/show/host', array(
-            'host' => $event->host
-          )); ?>">
-            <?= $event->host; ?>
-          </a>
+          <?= $this->link()->host($event->host, $event->host_display_name) ?>
         <?php endif ?>
           <br>
           <div>
-            <?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $msg; ?>
+            <?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $this->escape($msg) ?>
           </div>
         </td>
       </tr>
diff --git a/modules/monitoring/application/views/scripts/list/hostgroups.phtml b/modules/monitoring/application/views/scripts/list/hostgroups.phtml
index 6238c1963..9e773c61a 100644
--- a/modules/monitoring/application/views/scripts/list/hostgroups.phtml
+++ b/modules/monitoring/application/views/scripts/list/hostgroups.phtml
@@ -79,8 +79,8 @@
         </td>
        <?php endif ?>
         <td class="groupname">
-          <a href="<?= $this->href('monitoring/list/services', array('hostgroup' => $h->hostgroup)); ?>">
-            <?= $h->hostgroup; ?>
+          <a href="<?= $this->href('monitoring/list/hosts', array('hostgroup' => $h->hostgroup)); ?>">
+            <?= $this->escape($h->hostgroup_alias) ?>
           </a>
         </td>
         <td class="total">
diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml
index 3953db975..55242101c 100644
--- a/modules/monitoring/application/views/scripts/list/hosts.phtml
+++ b/modules/monitoring/application/views/scripts/list/hosts.phtml
@@ -1,8 +1,6 @@
 <?php
 use Icinga\Module\Monitoring\Object\Host;
 
-$helper = $this->getHelper('MonitoringState');
-
 if ($this->compact): ?>
 <div class="content">
 <?php else: ?>
@@ -82,7 +80,7 @@ if ($hosts->count() === 0) {
     <tr class="state <?= $hostStateName ?><?= $host->host_handled ? ' handled' : '' ?>">
       <!-- State -->
       <td class="state">
-        <strong><?= strtoupper(Host::getStateText($host->host_state, true)); ?></strong><br />
+        <strong><?= Host::getStateText($host->host_state, true); ?></strong><br />
         <?php if ((int) $host->host_state !== 99): ?>
         <?= $this->prefixedTimeSince($host->host_last_state_change, true) ?>
         <?php if ($host->host_state > 0 && (int) $host->host_state_type === 0): ?>
@@ -98,7 +96,7 @@ if ($hosts->count() === 0) {
         <?= $this->icon($this->resolveMacros($host->host_icon_image, $host)) ?>
         <?php endif ?>
         <?= implode(' ', $icons) ?>
-        <a href="<?= $hostLink  ?>"><?= $host->host_name ?></a>
+        <a href="<?= $hostLink  ?>"><?= $this->escape($host->host_display_name) ?></a>
         <?php if (isset($host->host_unhandled_services) && $host->host_unhandled_services > 0): ?>
         <span title="<?php printf(
           $this->translatePlural('%s Service Problem on Host "%s"', '%s Service Problems on Host "%s"', $host->host_unhandled_services),
@@ -110,15 +108,14 @@ if ($hosts->count() === 0) {
                $host->host_unhandled_services),
            'monitoring/show/services',
            array(
-               'host'                 => $host->host_name,
-               'service_problem'      => 1,
-               'service_acknowledged' => 0,
-               'service_in_downtime'  => 0
+               'host'               => $host->host_name,
+               'service_problem'    => 1,
+               'service_handled'    => 0
            ),
            array('style' => 'font-weight: normal')
         ) ?>)</span>
         <?php endif ?>
-        <p class="pluginoutput"><?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)) ?></p>
+        <p class="pluginoutput"><?= $this->escape($this->ellipsis($host->host_output, 10000)) ?></p>
       </td>
       <?php foreach($this->extraColumns as $col): ?>
       <td><?= $this->escape($host->$col) ?></td>
diff --git a/modules/monitoring/application/views/scripts/list/notifications.phtml b/modules/monitoring/application/views/scripts/list/notifications.phtml
index 845effbc5..44f33851f 100644
--- a/modules/monitoring/application/views/scripts/list/notifications.phtml
+++ b/modules/monitoring/application/views/scripts/list/notifications.phtml
@@ -5,85 +5,72 @@ use Icinga\Module\Monitoring\Object\Service;
 
 ?>
 
-<?php if (!$this->compact): ?>
+<?php if (! $this->compact): ?>
 <div class="controls">
-  <?= $this->tabs ?>
-  <div class="dontprint" style="margin: 1em;">
-    <?= $this->translate('Sort by') ?> <?=  $this->sortControl->render($this) ?>
-  </div>
-  <?= $this->widget('limiter') ?>
-  <?=  $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
- </div>
+    <?= $this->tabs ?>
+    <div class="dontprint" style="margin: 1em;">
+        <?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this) ?>
+    </div>
+    <?= $this->widget('limiter') ?>
+    <?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
+</div>
 <?php endif ?>
 
-<?php if (! $this->inline): ?>
 <div class="content">
-<?php endif; ?>
+    <?php if (count($notifications) === 0): ?>
+    <?= $this->translate('No notifications matching the filter') ?>
+    <?php return; endif ?>
 
-<?php
-
-if (empty($this->notifications)) {
-    echo 'No notifications yet</div>';
-    return;
-}
-?>
-
-<table data-base-target="_next" class="action">
-<tbody>
-<?php
-
-if (count($notifications) === 0) {
-    echo mt('monitoring', 'No notifications matching the filter');
-}
-foreach ($notifications as $notification):
-
-  if (isset($notification->service)) {
-      $isService = true;
-      $href = $this->href('monitoring/show/service', array(
-          'host'    => $notification->host,
-          'service' => $notification->service
-      ));
-      $stateName = Service::getStateText($notification->notification_state);
-  } else {
-      $isService = false;
-      $href = $this->href('monitoring/show/host', array(
-          'host'    => $notification->host
-      ));
-      $stateName = Host::getStateText($notification->notification_state);
-  }
-?>
-  <tr class="state <?= $stateName ?>">
-    <td class="state">
-        <?= $this->dateTimeRenderer($notification->notification_start_time)->render(
-                $this->translate('on %s', 'datetime'),
-                $this->translate('at %s', 'time'),
-                $this->translate('%s ago', 'timespan')
-            );
-        ?>
-    </td>
-    <td style="font-size: 0.8em">
-      <?php if ($isService): ?>
-        <a href="<?= $href ?>"><?= $notification->service ?></a> on <?= $notification->host ?>
-      <?php else: ?>
-        <a href="<?= $href ?>"><?= $notification->host ?></a>
-      <?php endif; ?>
-      <br />
-      <?= $this->escape(substr(strip_tags($notification->notification_output), 0, 10000)); ?>
-      <br />
-      <?php if (!$this->contact): ?>
-      <small>
-          Sent to <a href="<?= $this->href(
-              'monitoring/show/contact',
-              array('contact' => $notification->notification_contact)
-          ) ?>"><?= $this->escape($notification->notification_contact) ?></a>
-      </small>
-      <?php endif ?>
-    </td>
-  </tr>
-<?php endforeach ?>
-</tbody>
-</table>
-
-<?php if (!$this->inline): ?>
+    <table data-base-target="_next" class="action">
+    <tbody>
+    <?php foreach ($notifications as $notification):
+        if (isset($notification->service)) {
+            $isService = true;
+            $stateName = Service::getStateText($notification->notification_state);
+        } else {
+            $isService = false;
+            $stateName = Host::getStateText($notification->notification_state);
+        }
+    ?>
+        <tr class="state <?= $stateName ?>">
+            <td class="state">
+                <?= $this->dateTimeRenderer($notification->notification_start_time)->render(
+                    $this->translate('on %s', 'datetime'),
+                    $this->translate('at %s', 'time'),
+                    $this->translate('%s ago', 'timespan')
+                ) ?>
+            </td>
+            <td style="font-size: 0.8em">
+                <?php if ($isService): ?>
+                    <?= $this->icon('service') ?>
+                    <?= $this->link()->service(
+                        $notification->service,
+                        $notification->service_display_name,
+                        $notification->host,
+                        $notification->host_display_name
+                    ) ?>
+                <?php else: ?>
+                    <?= $this->icon('host') ?>
+                    <?= $this->link()->host($notification->host, $notification->host_display_name) ?>
+                <?php endif ?>
+                <br>
+                <?= $this->escape($this->ellipsis($notification->notification_output, 10000)) ?>
+                <br>
+                <?php if (! $this->contact): ?>
+                    <small>
+                        <?= sprintf(
+                            $this->translate('Sent to %s'),
+                            $this->qlink(
+                                $notification->notification_contact,
+                                'monitoring/show/contact',
+                                array('contact' => $notification->notification_contact)
+                            )
+                        ) ?>
+                    </small>
+                <?php endif ?>
+            </td>
+        </tr>
+    <?php endforeach ?>
+    </tbody>
+    </table>
 </div>
-<?php endif; ?>
diff --git a/modules/monitoring/application/views/scripts/list/servicegroups.phtml b/modules/monitoring/application/views/scripts/list/servicegroups.phtml
index 09abae6a1..71195ba61 100644
--- a/modules/monitoring/application/views/scripts/list/servicegroups.phtml
+++ b/modules/monitoring/application/views/scripts/list/servicegroups.phtml
@@ -80,7 +80,7 @@
        <?php endif ?>
         <td class="groupname">
           <a href="<?= $this->href('monitoring/list/services', array('servicegroup' => $s->servicegroup)); ?>">
-            <?= $s->servicegroup; ?>
+            <?= $this->translate($s->servicegroup_alias) ?>
           </a>
         </td>
         <td class="total">
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml
index 994304f08..45d59adf5 100644
--- a/modules/monitoring/application/views/scripts/list/services.phtml
+++ b/modules/monitoring/application/views/scripts/list/services.phtml
@@ -2,8 +2,6 @@
 use Icinga\Module\Monitoring\Object\Host;
 use Icinga\Module\Monitoring\Object\Service;
 
-$helper = $this->getHelper('MonitoringState');
-
 $selfUrl = 'monitoring/list/services';
 
 if (!$this->compact): ?>
@@ -58,7 +56,7 @@ foreach ($services as $service):
 ?>
     <tr class="state <?= $serviceStateName ?><?= $service->service_handled ? ' handled' : '' ?>">
       <td class="state">
-        <strong><?= strtoupper(Service::getStateText($service->service_state, true)); ?></strong><br />
+        <strong><?= Service::getStateText($service->service_state, true); ?></strong><br />
             <?php if (!$this->compact): ?><?= $this->prefixedTimeSince($service->service_last_state_change); ?><?php else: ?><?= $this->timeSince($service->service_last_state_change); ?><?php endif ?>
             <?php if ($service->service_state > 0 && (int) $service->service_state_type === 0): ?>
               <br />
@@ -106,12 +104,12 @@ foreach ($services as $service):
       <?php if ($service->service_icon_image && ! preg_match('/[\'"]/', $service->service_icon_image)): ?>
       <?= $this->icon($this->resolveMacros($service->service_icon_image, $service)) ?>
       <?php endif ?>
-<a href="<?= $serviceLink ?>"><?= $service->service_display_name ?></a><?php if ($this->showHost): ?> on <a href="<?= $hostLink ?>"><?= $service->host_name; ?>
+<a href="<?= $serviceLink ?>"><?= $this->escape($service->service_display_name) ?></a><?php if ($this->showHost): ?> on <a href="<?= $hostLink ?>"><?= $this->escape($service->host_display_name) ?>
 <?php if ($service->host_state != 0): ?>
-  (<?= strtoupper(Host::getStateText($service->host_state, true)); ?>)
+  (<?= Host::getStateText($service->host_state, true); ?>)
 <?php endif ?>
 </a><?php endif ?><br />
-        <p class="pluginoutput"><?= $this->escape(substr(strip_tags($service->service_output), 0, 10000)); ?></p>
+        <p class="pluginoutput"><?= $this->escape($this->ellipsis($service->service_output, 10000)); ?></p>
       </td>
 <?php foreach($this->extraColumns as $col): ?>
       <td><?= $this->escape($service->$col) ?></td>
diff --git a/modules/monitoring/application/views/scripts/multi/components/comments.phtml b/modules/monitoring/application/views/scripts/multi/components/comments.phtml
deleted file mode 100644
index f0b262c9d..000000000
--- a/modules/monitoring/application/views/scripts/multi/components/comments.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-$objectName = $this->is_service ? 'Services' : 'Hosts';
-
-?><tr class="newsection" data-base-target="_next">
-  <th><a href=<?= count($comments) ?> <?= $this->translate('Comments') ?></th>
-  <td>
-    <a href="<?= $this->href('monitoring/command/removecomment', $this->target) ?>"><?=
-        $this->icon('cancel')
-    ?> <?= $this->translate('Remove Comments') ?></a><br />
-    <a href="<?= $this->href('monitoring/command/delaynotifications', $this->target); ?>"><?=
-        $this->icon('bell-off-empty')
-    ?> <?= $this->translate('Delay Notifications') ?></a><br />
-    <a title="<?= $this->translate('Acknowledge all problems on the selected hosts or services') ?>"
-        href="<?= $this->href('monitoring/command/acknowledgeproblem') ?>, $this->target); ?>">
-        <?= $this->icon('ok') ?> Acknowledge
-    </a>
-  </td>
-  <td><a href=" <?= $this->href(
-          'monitoring/list/comments',
-          array('comment_internal_id' => '(' . implode('|', $this->comments) . ')')
-      );
-      ?>"> <?= count($comments) ?> comments </a>.
-  </td>
-</tr>
diff --git a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml b/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml
deleted file mode 100644
index af8d841b4..000000000
--- a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-$objectName = $this->is_service ? 'Services' : 'Hosts';
-
-?>
-<tr class="newsection">
-  <th><?= count($downtimes) ?> Downtimes</th>
-  <td>
-    <a href="<?=$this->href('monitoring/command/removedowntime', $this->target); ?>"><?=
-      $this->icon('cancel') ?>Remove Downtimes</a><br />
-    <a title="Schedule downtimes for all selected <?= $objectName ?>" href="<?=
-      $this->href('monitoring/command/scheduledowntime', $this->target) ?>"><?=
-      $this->icon('plug')
-      ?> Schedule Downtimes</a>
-  </td>
-  <td>
-    Change <a data-base-target='_next' href="<?= $this->href('') ?>"> <?= count($downtimes) ?> downtimes</a>.
-  </td>
-</tr>
diff --git a/modules/monitoring/application/views/scripts/multi/components/flags.phtml b/modules/monitoring/application/views/scripts/multi/components/flags.phtml
deleted file mode 100644
index 1269e2f49..000000000
--- a/modules/monitoring/application/views/scripts/multi/components/flags.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<form
-    id="<?= $form->getId() ?>"
-    name="<?= $form->getName() ?>"
-    enctype="<?= $form->getEnctype() ?>"
-    action="<?= $form->getAction() ?>"
-    method="post"
->
-  <table class="avp newsection">
-  <?php foreach($this->form->getElements() as $name => $element):
-    if ($element instanceof \Icinga\Web\Form\Element\TriStateCheckbox):
-        $element->setDecorators(array('ViewHelper'));
-    ?>
-    <tr>
-      <th><label for="<?= $element->getName() ?>"> <?= $element->getLabel() ?> </label></th>
-      <td><?= $element->render() ?></td>
-    </tr>
-    <?php else: ?>
-    <tr>
-      <th></th>
-      <td><?= $element->render() ?></td>
-    </tr>
-    <?php endif ?>
-  <?php endforeach ?>
-  </table>
-</form>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml b/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml
deleted file mode 100644
index 879a13a1d..000000000
--- a/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-  
-$objectCount = count($objects);
-
-$links = array();
-for ($i = 0; $i < $objectCount && $i < 5; $i++) {
-    $object = $objects[$i];    
-
-    if ($this->is_service) {
-        $links[] = $this->qlink(
-            $object->host_name . ' ' . $object->service_description,
-            'monitoring/show/service',
-            array(
-                'host' => $object->host_name,
-                'service' => $object->service_description
-            )
-        );
-    } else {
-        $links[] =  $this->qlink(
-            $object->host_name,
-            'monitoring/show/host',
-            array(
-                'host' => $object->host_name
-            )
-        );
-    }
-}
-
-if ($this->is_service) {
-    $objectName = $this->translate('Services');
-    $link = 'monitoring/list/services';
-    $target = array(
-        'host'    => $this->hostquery,
-        'service' => $this->servicequery
-    );
-} else {
-    $objectName = $this->translate('Hosts');
-    $link = 'monitoring/list/hosts';
-    $target = array(
-        'host' => $this->hostquery
-    );
-}
-
-$more = clone $this->url;
-
-
-?><tr class="newsection" data-base-target="_next">
-<th><?= $this->qlink(
-    $this->translate('List all'),
-    $more->setPath($link),
-    null,
-    array('title' => $this->translate('List all selected objects'))
-) ?></th>
-<td colspan="3">
-<?php
-
-echo implode(', ', $links);
-
-if ($objectCount > 5) {
-    echo ' ' . sprintf($this->translate('and %d more'), count($objects) - 5);
-}
-
-?>
-</td>
-</tr>
diff --git a/modules/monitoring/application/views/scripts/multi/components/summary.phtml b/modules/monitoring/application/views/scripts/multi/components/summary.phtml
deleted file mode 100644
index d832624c7..000000000
--- a/modules/monitoring/application/views/scripts/multi/components/summary.phtml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-$cf = $this->getHelper('CommandForm');
-$servicequery = isset($this->servicequery) ? $this->servicequery : '';
-$objectName = $this->is_service ? $this->translate('Services') : $this->translate('Hosts');
-
-$params = array(
-    'host'       => $this->target['host'],
-    'service'    => null,
-    'checktime'  => time(),
-    'forcecheck' => '1'
-);
-if (array_key_exists('service', $this->target)) {
-    $params['service'] = $this->target['service'];
-} else {
-    unset($params['service']);
-}
-?>
-<tr class="newsection">
-  <th><?= count($objects) . ' ' . $objectName ?></th>
-  <td>
-    <a href="<?=
-      $this->href('monitoring/command/reschedulenextcheck', $params) ?>"><?=
-        $this->icon('rescheduel')
-      ?> Recheck</a><br />
-    <a href="<?= $this->href('monitoring/command/reschedulenextcheck', $this->target) ?>"><?=
-       $this->icon('reschedule')
-    ?> Reschedule</a><br />
-  </td>
-  <td>Perform actions on <?=  count($objects) . ' ' . $objectName ?>.</td>
-</tr>
-
-<tr class="newsection">
-  <th><?= $this->problems ?> Problems</th>
-  <td>
-    <a title="Schedule downtimes for all selected hosts" href="<?=
-      $this->href('monitoring/command/scheduledowntime', $this->target) ?>"><?=
-      $this->icon('plug')
-      ?> Schedule Downtimes</a>
-  </td>
-  <td><?= sprintf(
-      'Handle %d problems on %d %s.',
-      $this->problems,
-      count($this->objects),
-      $objectName
-  ) ?></td>
-</tr>
-<tr>
-  <th><?= count($this->unhandled) ?> Unhandled</th>
-  <td colspan="2">
-    <a title="Acknowledge all problems on the selected hosts or services" href="<?=
-      $this->href('monitoring/command/acknowledgeproblem', $this->target) ?>"><?=
-      $this->icon('ok')
-      ?> Acknowledge</a><br />
-    <a title="Remove all acknowledgements from all selected hosts or services" href="<?=
-      $this->href('monitoring/command/removeacknowledgement', $target) ?>"><?=
-      $this->icon('remove_petrol.png') ?> Remove Acknowledgements</a>
-  </td>
-</tr>
diff --git a/modules/monitoring/application/views/scripts/multi/host.phtml b/modules/monitoring/application/views/scripts/multi/host.phtml
deleted file mode 100644
index 6179f6339..000000000
--- a/modules/monitoring/application/views/scripts/multi/host.phtml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-$this->is_service = false;
-$this->hostquery = implode($this->hostnames, ',');
-$this->target = array('host'	=> $this->hostquery);
-?>
-
-<div class="controls">
-    <?= $this->tabs; ?>
-</div>
-
-<div class="content">
-    <?php if (count($objects) === 0): ?>
-         <?= mt('monitoring', 'No hosts matching the filter'); ?>
-    <?php else: ?>
-    <h1> Summary for <?= count($objects) ?> hosts </h1>
-    <?= $this->render('multi/components/objectlist.phtml'); ?>
-    <table class="avp">
-        <tr>
-            <th align="center">
-                <h3><?= array_sum(array_values($states)) ?> Hosts</h3>
-            </th>
-            <th></th>
-        </tr>
-        <tr>
-            <td align="center">
-                <?= $this->pie->render(); ?>
-            </td>
-            <td>
-                <?php
-                foreach ($states as $state => $count) {
-                    if ($count > 0) {
-                        echo ucfirst($state) . ': ' . $count . '<br />';
-                    }
-                }
-                ?>
-            </td>
-            <td></td>
-        </tr>
-    </table>
-
-    <h2> <?=$this->icon('host')?> Host Actions </h2>
-
-        <table class="avp newsection">
-            <tbody>
-                <?= $this->render('multi/components/summary.phtml'); ?>
-                <?= $this->render('multi/components/comments.phtml'); ?>
-                <?= $this->render('multi/components/downtimes.phtml'); ?>
-            </tbody>
-        </table>
-
-    <?= $this->render('multi/components/flags.phtml') ?>
-    <?php endif ?>
-</div>
-
-<a
-    rel="tooltip"
-    title="Submit passive checkresults"
-    href="<?= $this->href('monitoring/command/submitpassivecheckresult', $this->target); ?>"
-    class="button btn-cta btn-common btn-small"
->
-    <i class="icinga-icon-submit"></i>
-</a>
diff --git a/modules/monitoring/application/views/scripts/multi/service.phtml b/modules/monitoring/application/views/scripts/multi/service.phtml
deleted file mode 100644
index dc2e9f19e..000000000
--- a/modules/monitoring/application/views/scripts/multi/service.phtml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-$this->is_service = true;
-$this->hostquery = implode($this->hostnames, ',');
-$this->servicequery = implode($this->servicenames, ',');
-$this->target = array(
-    'host' => $this->hostquery,
-    'service' => $this->servicequery
-);
-?>
-
-<div class="controls">
-<?= $this->tabs ?>
-</div>
-
-<div class="content">
-  <?php if (count($objects) === 0): ?>
-      <?= mt('monitoring', 'No services matching the filter'); ?>
-  <?php else: ?>
-  <h1> Summary for <?= count($objects) ?> services </h1>
-
-  <table style="width: 100%; font-size: 0.8em;">
-    <tr>
-      <th colspan="2"><?= array_sum(array_values($service_states)) ?> Services</th>
-      <th colspan="2"><?= array_sum(array_values($host_states)) ?> Hosts</th>
-    </tr>
-    <tr>
-      <td align="center"><?= $this->service_pie->render() ?></td>
-      <td><?php
-
-          foreach ($service_states as $state => $count) {
-              if ($count > 0) {
-                  echo ucfirst($state) . ': ' . $count . '<br />';
-              }
-          }
-
-      ?></td>
-      <td align="center"><?= $this->host_pie->render() ?></td>
-      <td><?php
-          foreach ($host_states as $state => $count) {
-              if ($count > 0) {
-                  echo ucfirst($state) . ': ' . $count . '<br />';
-              }
-          }
-      ?></td>
-    </tr>
-  </table>
-
-  <h2><?=$this->icon('conf')?> Service Actions</h2>
-
-  <table class="avp newsection">
-    <tbody>
-      <?= $this->render('multi/components/objectlist.phtml') ?>
-      <?= $this->render('multi/components/summary.phtml') ?>
-      <?= $this->render('multi/components/comments.phtml') ?>
-      <?= $this->render('multi/components/downtimes.phtml') ?>
-    </tbody>
-  </table>
-
-  <?= $this->render('multi/components/flags.phtml') ?>
-  <?php endif ?>
-</div>
diff --git a/modules/monitoring/application/views/scripts/partials/command-form.phtml b/modules/monitoring/application/views/scripts/partials/command-form.phtml
index 9832bfe17..380687a00 100644
--- a/modules/monitoring/application/views/scripts/partials/command-form.phtml
+++ b/modules/monitoring/application/views/scripts/partials/command-form.phtml
@@ -1,5 +1,5 @@
 <div class="controls">
-    <?= $this->tabs->showOnlyCloseButton() ?>
+    <?= $this->tabs->remove('dashboard') ?>
 </div>
 <div class="content">
     <h1><?= $title ?> <?= /** @var \Icinga\Module\Monitoring\Forms\Command\CommandForm $form */ $this->icon('help', $form->getHelp()) ?></h1>
diff --git a/modules/monitoring/application/views/scripts/process/info.phtml b/modules/monitoring/application/views/scripts/process/info.phtml
index 02b8eeb80..92bb6cb63 100644
--- a/modules/monitoring/application/views/scripts/process/info.phtml
+++ b/modules/monitoring/application/views/scripts/process/info.phtml
@@ -26,11 +26,11 @@ $cp = $this->checkPerformance()->create($this->checkperformance);
                 </tr>
                 <tr>
                     <th><?= $this->translate('Last Status Update'); ?></th>
-                    <td><?= $this->timeSince($this->programStatus->status_update_time) ?> ago</td>
+                    <td><?= sprintf($this->translate('%s ago'), $this->timeSince($this->programStatus->status_update_time)); ?></td>
                 </tr>
                 <tr>
                     <th><?= $this->translate('Last External Command Check'); ?></th>
-                    <td><?= $this->timeSince($this->programStatus->last_command_check) ?> ago</td>
+                    <td><?= sprintf($this->translate('%s ago'), $this->timeSince($this->programStatus->last_command_check)); ?></td>
                 </tr>
                 <tr>
                     <th><?= $this->translate('Last Log File Rotation'); ?></th>
diff --git a/modules/monitoring/application/views/scripts/services/show.phtml b/modules/monitoring/application/views/scripts/services/show.phtml
index 18071c152..522d32ce7 100644
--- a/modules/monitoring/application/views/scripts/services/show.phtml
+++ b/modules/monitoring/application/views/scripts/services/show.phtml
@@ -2,34 +2,36 @@
     <?= $this->tabs ?>
 </div>
 <div class="content">
-    <?php if (count($objects) === 0): ?>
+    <?php $serviceCount = count($objects) ?>
+    <?php if ($serviceCount === 0): ?>
         <?= $this->translate('No services matching the filter') ?>
     <?php else: ?>
 
         <div class="hbox">
             <div class="hbox-item" style="width: 6em;">
-                <b><?= sprintf($this->translate('Services (%u)'), array_sum(array_values($serviceStates))) ?></b>
+                <b><?= sprintf($this->translatePlural('Service (%u)', 'Services (%u)', $serviceCount), $serviceCount) ?></b>
             </div>
             <div class="hbox-item">
-                <?= $this->serviceStatesPieChart ?>
+                &nbsp;<?= $this->serviceStatesPieChart ?>
             </div>
             <div class="hbox-item" style="font-size: 14px">
                 <?php foreach (array_filter($serviceStates) as $text => $count) {
-                    echo sprintf(' %s: %u <br>', strtoupper($text), $count);
+                    echo sprintf(' %s: %u <br>', $this->translate(strtoupper($text)), $count);
                 } ?>
             </div>
         </div>
 
         <div class="hbox">
             <div class="hbox-item" style="width: 6em;">
-                <b><?= sprintf($this->translate('Hosts (%u)'), array_sum(array_values($hostStates)))  ?></b>
+                <?php $hostCount = array_sum(array_values($hostStates)) ?>
+                <b><?= sprintf($this->translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount) ?></b>
             </div>
             <div class="hbox-item">
-                <?= $this->hostStatesPieChart ?>
+                &nbsp;<?= $this->hostStatesPieChart ?>
             </div>
             <div class="hbox-item" style="font-size: 14px">
                 <?php foreach (array_filter($hostStates) as $text => $count) {
-                    echo sprintf('%s: %u <br>', strtoupper($text), $count);
+                    echo sprintf('%s: %u <br>', $this->translate(strtoupper($text)), $count);
                 } ?>
             </div>
         </div>
@@ -68,13 +70,14 @@
 
         <?php if (! empty($unhandledObjects)): ?>
         <h3>
+            <?php $unhandledCount = count($unhandledObjects) ?>
             <?= sprintf(
                 $this->translatePlural(
                     '%u Unhandled Service Problem',
                     '%u Unhandled Service Problems',
-                    count($unhandledObjects)
+                    $unhandledCount
                 ),
-                count($unhandledObjects)
+                $unhandledCount
             ) ?>
         </h3>
         <div>
@@ -95,13 +98,14 @@
 
         <?php if (! empty($acknowledgedObjects)): ?>
             <h2>
+                <?php $acknowledgedCount = count($acknowledgedObjects) ?>
                 <?= sprintf(
                     $this->translatePlural(
                         '%u Acknowledged Service Problem',
                         '%u Acknowledged Service Problems',
-                        count($acknowledgedObjects)
+                        $acknowledgedCount
                     ),
-                    count($acknowledgedObjects)
+                    $acknowledgedCount
                 ) ?>
             </h2>
             <div>
@@ -111,20 +115,36 @@
 
         <?php if (! empty($objectsInDowntime)): ?>
             <h2>
+                <?php $inDowntimeCount = count($objectsInDowntime) ?>
                 <a href="<?= $inDowntimeLink ?>"
                    title="<?= $this->translate('Services in downtime') ?>">
                     <?= $this->icon('plug') ?>
-                    <?= $this->translate(sprintf('%u services are in downtime', count($objectsInDowntime))) ?>
+                    <?= sprintf(
+                        $this->translatePlural(
+                            '%u service is in downtime',
+                            '%u services are in downtime',
+                            $inDowntimeCount
+                        ),
+                        $inDowntimeCount
+                    ) ?>
                 </a>
             </h2>
         <?php endif ?>
 
-        <?php if (count($objects->getComments())): ?>
+        <?php $havingCommentsCount = count($objects->getComments()) ?>
+        <?php if ($havingCommentsCount): ?>
             <h2>
                 <a href="<?= $havingCommentsLink ?>"
                    title="<?= $this->translate('Comments') ?>">
                     <?= $this->icon('comment') ?>
-                    <?= $this->translate(sprintf('%u comments', count($objects->getComments()))) ?>
+                    <?= sprintf(
+                        $this->translatePlural(
+                            '%u comment',
+                            '%u comments',
+                            $havingCommentsCount
+                        ),
+                        $havingCommentsCount
+                    ) ?>
                 </a>
             </h2>
         <?php endif ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml b/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml
index 9b323e2f5..8da35590f 100644
--- a/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml
@@ -7,33 +7,40 @@ if (in_array((int) $object->state, array(0, 99))) {
     return;
 }
 
-if ($object->getType() === $object::TYPE_HOST) {
-    $ackLink = $this->href(
-        'monitoring/host/acknowledge-problem',
-        array('host' => $object->getName())
-    );
-} else {
-    $ackLink = $this->href(
-        'monitoring/service/acknowledge-problem',
-        array('host' => $object->getHost()->getName(), 'service' => $object->getName())
-    );
-}
-
 if ($object->acknowledged): ?>
     <tr>
         <th><?= $this->translate('Acknowledged') ?></th>
-        <td><?= $removeAckForm ?></td>
+        <td>
+            <?php if (isset($removeAckForm)) { // Form is unset if the current user lacks the respective permission
+                echo $removeAckForm;
+            } else {
+                echo '&#45;';
+            } ?>
+        </td>
     </tr>
 <?php else: ?>
     <tr>
         <th><?= $this->translate('Not acknowledged') ?></th>
         <td>
-            <?php
-
+            <?php if ($this->hasPermission('monitoring/command/acknowledge-problem')) {
+                if ($object->getType() === $object::TYPE_HOST) {
+                    $ackLink = $this->href(
+                        'monitoring/host/acknowledge-problem',
+                        array('host' => $object->getName())
+                    );
+                } else {
+                    $ackLink = $this->href(
+                        'monitoring/service/acknowledge-problem',
+                        array('host' => $object->getHost()->getName(), 'service' => $object->getName())
+                    );
+                }
             ?>
-            <a href="<?= $ackLink ?>">
+            <a href="<?= $ackLink ?>" data-base-target="_self">
                 <?= $this->icon('ok') ?> <?= $this->translate('Acknowledge') ?>
             </a>
+            <?php } else {
+                echo '&#45;';
+            } // endif ?>
         </td>
     </tr>
 <?php endif ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml
index 50b40cdcc..ec0c2792a 100644
--- a/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml
@@ -1,19 +1,13 @@
 <?php
 
-/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
+/** @type \Icinga\Module\Monitoring\Object\MonitoredObject $object */
 
 if ($object->getType() === $object::TYPE_HOST) {
-    $reschedule = $this->href(
-        'monitoring/host/reschedule-check',
-        array('host' => $object->getName())
-    );
+    $isService = false;
     $checkAttempts = $object->host_current_check_attempt . '/' . $object->host_max_check_attempts;
     $stateType = (int) $object->host_state_type;
 } else {
-    $reschedule = $this->href(
-        'monitoring/service/reschedule-check',
-        array('host' => $object->getHost()->getName(), 'service' => $object->getName())
-    );
+    $isService = true;
     $checkAttempts = $object->service_attempt;
     $stateType = (int) $object->service_state_type;
 }
@@ -23,36 +17,53 @@ if ($object->getType() === $object::TYPE_HOST) {
 <tr>
     <th><?= $this->translate('Last check') ?></th>
     <td data-base-target="_self">
-        <?= $checkNowForm ?>
+        <?php if (isset($checkNowForm)) { // Form is unset if the current user lacks the respective permission
+            echo $checkNowForm;
+        } ?>
         <?= $this->timeSince($object->last_check) ?>
     </td>
 </tr>
 <tr>
   <th><?= $this->translate('Next check') ?></th>
   <td>
-      <a href="<?= $reschedule ?>">
-          <?= $this->icon('reschedule') ?> <?= $this->translate('Reschedule') ?>
+      <?php if ($this->hasPermission('monitoring/command/schedule-check')) {
+          if ($isService) {
+              $reschedule = $this->href(
+                  'monitoring/service/reschedule-check',
+                  array('host' => $object->getHost()->getName(), 'service' => $object->getName())
+              );
+          } else {
+              $reschedule = $this->href(
+                  'monitoring/host/reschedule-check',
+                  array('host' => $object->getName())
+              );
+          }
+      ?>
+      <a href="<?= $reschedule ?>" data-base-target="_self">
+          <?= $this->icon('reschedule') ?>
+          <?= $this->translate('Reschedule') ?>
       </a>
+      <?php } // endif ?>
       <?= $this->timeUntil($object->next_check) ?>
   </td>
 </tr>
 <tr>
     <th><?= $this->translate('Check attempts') ?></th>
     <?php if ($stateType === 0): ?>
-    <td><?= $checkAttempts ?> <?= $this->translate('(soft state)') ?></td>
+        <td><?= $checkAttempts ?> (<?= $this->translate('soft state') ?>)</td>
     <?php else: ?>
-    <td><?= $checkAttempts ?> <?= $this->translate('(hard state)') ?></td>
+        <td><?= $checkAttempts ?> (<?= $this->translate('hard state') ?>)</td>
     <?php endif; ?>
 </tr>
 <?php if ($object->check_execution_time): ?>
-<tr>
-  <th><?= $this->translate('Check execution time') ?></th>
-  <td><?= $object->check_execution_time ?>s</td>
-</tr>
+    <tr>
+        <th><?= $this->translate('Check execution time') ?></th>
+        <td><?= $object->check_execution_time ?>s</td>
+    </tr>
 <?php endif ?>
 <?php if ($object->check_latency): ?>
-<tr>
- <th><?= $this->translate('Check latency') ?></th>
- <td><?= $object->check_latency ?>s</td>
-</tr>
+    <tr>
+        <th><?= $this->translate('Check latency') ?></th>
+        <td><?= $object->check_latency ?>s</td>
+    </tr>
 <?php endif ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/command.phtml b/modules/monitoring/application/views/scripts/show/components/command.phtml
index a13ed1bee..a74b5b884 100644
--- a/modules/monitoring/application/views/scripts/show/components/command.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/command.phtml
@@ -3,24 +3,32 @@
 $parts = explode('!', $object->check_command);
 $command = array_shift($parts);
 
-?><tr class="newsection">
-  <th><?= $this->translate('Command') ?></th>
-  <td>
-    <?= $this->escape($command) ?>
-  <?php if ($object->passive_checks_enabled): ?>
-   <?php if ($object->getType() === $object::TYPE_HOST): ?>
-    <a href="<?= $this->href(
-      'monitoring/host/process-check-result',
-      array('host' => $object->getName())
-    ); ?>"><?= $this->icon('reply'); ?> <?= $this->translate('Process check result'); ?></a>
-   <?php else: ?>
-    <a href="<?= $this->href(
-      'monitoring/service/process-check-result',
-      array('host' => $object->getHost()->getName(), 'service' => $object->getName())
-    ); ?>"><?= $this->icon('reply'); ?> <?= $this->translate('Process check result'); ?></a>
-   <?php endif ?>
-  <?php endif ?>
+?>
+
+<tr class="newsection">
+    <th><?= $this->translate('Command') ?></th>
+    <td>
+        <?= $this->escape($command) ?>
+        <?php if ($this->hasPermission('monitoring/command/schedule-check') && $object->passive_checks_enabled): ?>
+            <?php if ($object->getType() === $object::TYPE_HOST) {
+                $processCheckResult = $this->href(
+                    'monitoring/host/process-check-result',
+                    array('host' => $object->getName())
+                );
+            } else {
+                $processCheckResult = $this->href(
+                    'monitoring/service/process-check-result',
+                    array('host' => $object->getHost()->getName(), 'service' => $object->getName())
+                );
+            } ?>
+            <a href="<?= $processCheckResult ?>" data-base-target="_self">
+                <?= $this->icon('reply') ?>
+                <?= $this->translate('Process check result') ?>
+            </a>
+        <?php endif ?>
+    </td>
 </tr>
+
 <?php
 
 $row = "<tr>\n  <th>%s</th>\n  <td>%s</td>\n</tr>\n";
diff --git a/modules/monitoring/application/views/scripts/show/components/comments.phtml b/modules/monitoring/application/views/scripts/show/components/comments.phtml
index 07968dfc8..a6503a70b 100644
--- a/modules/monitoring/application/views/scripts/show/components/comments.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/comments.phtml
@@ -1,26 +1,27 @@
 <tr>
     <th><?= $this->translate('Comments') ?></th>
     <td>
-        <?php
-
-        /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
-
-        if ($object->getType() === $object::TYPE_HOST) {
-            $addCommentLink = $this->href(
-                'monitoring/host/add-comment',
-                array('host' => $object->getName())
-            );
-        } else {
-            $addCommentLink = $this->href(
-                'monitoring/service/add-comment',
-                array('host' => $object->getHost()->getName(), 'service' => $object->getName())
-            );
-        }
-
+        <?php if ($this->hasPermission('monitoring/command/comment/add')) {
+            /** @type \Icinga\Module\Monitoring\Object\MonitoredObject $object */
+            if ($object->getType() === $object::TYPE_HOST) {
+                $addCommentLink = $this->href(
+                    'monitoring/host/add-comment',
+                    array('host' => $object->getName())
+                );
+            } else {
+                $addCommentLink = $this->href(
+                    'monitoring/service/add-comment',
+                    array('host' => $object->getHost()->getName(), 'service' => $object->getName())
+                );
+            }
         ?>
-        <a href="<?= $addCommentLink ?>">
-            <?= $this->icon('comment') ?> <?= $this->translate('Add comment') ?>
+        <a href="<?= $addCommentLink ?>" data-base-target="_self">
+            <?= $this->icon('comment') ?>
+            <?= $this->translate('Add comment') ?>
         </a>
+        <?php } else {
+            echo '&#45;';
+        } // endif ?>
     </td>
 </tr>
 
@@ -28,16 +29,12 @@
 
 foreach ($object->comments as $comment) {
     // Ticket hook sample
-    $text = $this->tickets ? preg_replace_callback(
+    $commentText = $this->tickets ? preg_replace_callback(
         $this->tickets->getPattern(),
         array($this->tickets, 'createLink'),
         $this->escape($comment->comment)
     ) : $this->escape($comment->comment);
 
-
-    $form = clone $delCommentForm;
-    $form->populate(array('comment_id' => $comment->id));
-
     ?>
 
     <tr>
@@ -46,14 +43,19 @@ foreach ($object->comments as $comment) {
             <table>
                 <tr>
                     <td style="vertical-align: top;" data-base-target="_self">
-                        <?= $form ?> (<?= ucfirst($comment->type) ?>):
+                        <?php if (isset($delCommentForm)) { // Form is unset if the current user lacks the respective permission
+                            $delCommentForm = clone $delCommentForm;
+                            $delCommentForm->populate(array('comment_id' => $comment->id));
+                            echo $delCommentForm;
+                        } ?>
+                        (<?= ucfirst($comment->type) ?>):
                     </td>
                     <td style="padding-left: .5em;">
-                        <?= str_replace(array('\r\n', '\n'), '<br>', $text) ?>
+                        <?= nl2br($commentText) ?>
                     </td>
                 </tr>
             </table>
         </td>
     </tr>
 
-<?php }  // endforeach ?>
+<?php } // endforeach ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/downtime.phtml b/modules/monitoring/application/views/scripts/show/components/downtime.phtml
index 2cd7147f1..4aa1e21c1 100644
--- a/modules/monitoring/application/views/scripts/show/components/downtime.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/downtime.phtml
@@ -1,25 +1,27 @@
 <tr>
     <th><?= $this->translate('Downtimes') ?></th>
     <td>
-        <?php
-
-        /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
-
-        if ($object->getType() === $object::TYPE_HOST) {
-            $scheduleDowntimeLink = $this->href(
-                'monitoring/host/schedule-downtime',
-                array('host' => $object->getName())
-            );
-        } else {
-            $scheduleDowntimeLink = $this->href(
-                'monitoring/service/schedule-downtime',
-                array('host' => $object->getHost()->getName(), 'service' => $object->getName())
-            );
-        }
+        <?php if ($this->hasPermission('monitoring/command/downtime/schedule')) {
+            /** @type \Icinga\Module\Monitoring\Object\MonitoredObject $object */
+            if ($object->getType() === $object::TYPE_HOST) {
+                $scheduleDowntimeLink = $this->href(
+                    'monitoring/host/schedule-downtime',
+                    array('host' => $object->getName())
+                );
+            } else {
+                $scheduleDowntimeLink = $this->href(
+                    'monitoring/service/schedule-downtime',
+                    array('host' => $object->getHost()->getName(), 'service' => $object->getName())
+                );
+            }
         ?>
-        <a href="<?= $scheduleDowntimeLink ?>">
-            <?= $this->icon('plug') ?> <?= $this->translate('Schedule downtime') ?>
+        <a href="<?= $scheduleDowntimeLink ?>" data-base-target="_self">
+            <?= $this->icon('plug') ?>
+            <?= $this->translate('Schedule downtime') ?>
         </a>
+        <?php } else {
+            echo '&#45;';
+        } // endif ?>
     </td>
 </tr>
 
@@ -27,15 +29,12 @@
 
 foreach ($object->downtimes as $downtime) {
     // Ticket hook sample
-    $text = $this->tickets ? preg_replace_callback(
+    $commentText = $this->tickets ? preg_replace_callback(
         $this->tickets->getPattern(),
         array($this->tickets, 'createLink'),
         $this->escape($downtime->comment)
     ) : $this->escape($downtime->comment);
 
-    $form = clone $delDowntimeForm;
-    $form->populate(array('downtime_id' => $downtime->id));
-
     if ((bool) $downtime->is_in_effect) {
         $state = 'in downtime since ' . $this->timeSince($downtime->start);
     } else {
@@ -54,14 +53,19 @@ foreach ($object->downtimes as $downtime) {
             <table>
                 <tr>
                     <td style="vertical-align: top;" data-base-target="_self">
-                        <?= $form ?> <?= $state ?>
+                        <?php if (isset($delDowntimeForm)) { // Form is unset if the current user lacks the respective permission
+                            $delDowntimeForm = clone $delDowntimeForm;
+                            $delDowntimeForm->populate(array('downtime_id' => $downtime->id));
+                            echo $delDowntimeForm;
+                        } ?>
+                        <?= $state ?>
                     </td>
                     <td style="padding-left: .5em;">
-                        <?= str_replace(array('\r\n', '\n'), '<br>', $text) ?>
+                        <?= nl2br($commentText) ?>
                     </td>
                 </tr>
             </table>
         </td>
     </tr>
 
-<?php }  // endforeach ?>
+<?php } // endforeach ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/header.phtml b/modules/monitoring/application/views/scripts/show/components/header.phtml
index ccf7d2d5e..8ba84da43 100644
--- a/modules/monitoring/application/views/scripts/show/components/header.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/header.phtml
@@ -3,37 +3,44 @@
 use Icinga\Module\Monitoring\Object\Host;
 use Icinga\Module\Monitoring\Object\Service;
 
-$showService = $object->getType() === $object::TYPE_SERVICE;
+$isService = $object->getType() === $object::TYPE_SERVICE;
 
 ?>
-<?php if (!$this->compact): ?>
+
+<?php if (! $this->compact): ?>
 <?= $tabs ?>
 <?php endif ?>
+
 <table class="objectstate">
     <tr class="state <?= Host::getStateText($object->host_state); ?><?= $object->host_handled ? ' handled' : '' ?>">
-    <td class="state"<?= $showService ? '' : ' rowspan="2"' ?>>
-        <strong><?= strtoupper(Host::getStateText($object->host_state, true)); ?></strong><br />
-      <?= $this->prefixedTimeSince($object->host_last_state_change, true) ?>
-    </td>
-    <td><b><?= $this->escape($object->host_name) ?></b><?php
- if ($object->host_address && $object->host_address !== $object->host_name): ?>
- <br><?= $this->escape($object->host_address) ?>
-<?php endif ?>
-    </td>
+        <td class="state"<?= $isService ? '' : ' rowspan="2"' ?>>
+            <strong><?= Host::getStateText($object->host_state, true); ?></strong><br>
+            <?= $this->prefixedTimeSince($object->host_last_state_change, true) ?>
+        </td>
+        <td>
+            <b><?= $this->escape($object->host_display_name) ?></b>
+            <?php if ($object->host_display_name !== $object->host_name): ?>
+            <small>(<?= $this->escape($object->host_name) ?>)</small>
+            <?php endif ?>
+            <?php if ($object->host_address && $object->host_address !== $object->host_name): ?>
+            <br>
+            <?= $this->escape($object->host_address) ?>
+            <?php endif ?>
+        </td>
+    </tr>
+<?php if ($isService): ?>
+    <tr class="state <?= Service::getStateText($object->service_state); ?><?= $object->service_handled ? ' handled' : '' ?>">
+        <td class="state">
+            <strong><?= Service::getStateText($object->service_state, true); ?></strong><br>
+            <?= $this->prefixedTimeSince($object->service_last_state_change, true) ?>
+        </td>
+        <td>
+            <b><?= $this->translate('Service') ?>: <?= $this->escape($object->service_display_name) ?></b>
+            <?php if ($object->service_display_name !== $object->service_description): ?>
+            <small>(<?= $this->escape($object->service_description) ?>)</small>
+            <?php endif ?>
+            <?= $this->render('show/components/statusIcons.phtml') ?>
+        </td>
   </tr>
-<?php if ($showService): ?>
-  <tr class="state <?= Service::getStateText($object->service_state); ?><?= $object->service_handled ? ' handled' : '' ?>">
-    <td class="state">
-      <strong><?= strtoupper(Service::getStateText($object->service_state, true)); ?></strong><br />
-      <?= $this->prefixedTimeSince($object->service_last_state_change, true) ?>
-    </td>
-    <td><b><?= $this->translate('Service') ?>: <?= $this->escape($object->service_description) ?></b>
-
-    <?= $this->render('show/components/statusIcons.phtml') ?>
-
-</td>
-  </tr>
-<?php else: ?>
-  <tr><td><!--<b>Host state</b>-->&nbsp;</td></tr>
 <?php endif ?>
 </table>
diff --git a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml
index 40db3e5c4..165df627a 100644
--- a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml
@@ -4,7 +4,7 @@ if (empty($object->hostgroups)) return;
 
 $list = array();
 foreach ($object->hostgroups as $name => $alias) {
-    $list[] = $this->qlink($alias, 'monitoring/list/services', array(
+    $list[] = $this->qlink($alias, 'monitoring/list/hosts', array(
         'hostgroup' => $name
     ));
 }
diff --git a/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml b/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml
index 3c603786a..641dd026a 100644
--- a/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml
+++ b/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml
@@ -17,7 +17,7 @@ $currentUrl = Url::fromRequest()->without('limit')->getRelativeUrl();
     $object->stats->services_ok,
     $selfUrl,
     array('service_state' => 0),
-    array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('ok'))))
+    array('title' => sprintf($this->translate('Services with state %s'), $this->translate('OK')))
 )  ?></span>
 <?php endif ?>
 <?php
@@ -48,7 +48,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
                 $object->stats->$unhandled,
                 $selfUrl,
                 $paramsUnhandled,
-                array('title' => sprintf($this->translate('Unhandled services with state %s'), strtoupper($this->translate($state))))
+                array('title' => sprintf($this->translate('Unhandled services with state %s'), $this->translate(strtoupper($state))))
             );
         }
         if ($object->stats->$handled) {
@@ -65,7 +65,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
                 $object->stats->$handled,
                 $selfUrl,
                 $paramsHandled,
-                array('title' => sprintf($this->translate('Handled services with state %s'), strtoupper($this->translate($state))))
+                array('title' => sprintf($this->translate('Handled services with state %s'), $this->translate(strtoupper($state))))
             );
             if ($object->stats->$unhandled) {
                 echo "</span>\n";
@@ -81,7 +81,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
     $object->stats->services_pending,
     $selfUrl,
     array('service_state' => 99),
-    array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('pending'))))
+    array('title' => sprintf($this->translate('Services with state %s'), $this->translate('PENDING')))
 )  ?></span>
 <?php endif ?>
 </span>
diff --git a/modules/monitoring/application/views/scripts/show/history.phtml b/modules/monitoring/application/views/scripts/show/history.phtml
index 5b922d4a0..40fb15363 100644
--- a/modules/monitoring/application/views/scripts/show/history.phtml
+++ b/modules/monitoring/application/views/scripts/show/history.phtml
@@ -92,21 +92,13 @@ function contactsLink($match, $view) {
           $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output);
           $stateClass = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
           $icon = 'attention-alt';
-          $title = strtoupper(
-            $isService
-              ? Service::getStateText($event->state)
-              : Host::getStateText($event->state)
-          );
+          $title = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
           break;
         case 'soft_state':
           $icon = 'spinner';
           $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output);
           $stateClass = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
-          $title = strtoupper(
-            $isService
-              ? Service::getStateText($event->state)
-              : Host::getStateText($event->state)
-          );
+          $title = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
           break;
         case 'dt_start':
           $icon = 'downtime_start';
@@ -136,19 +128,24 @@ $output = $this->tickets ? preg_replace_callback(
 
 ?>
         <?php if ($isService): ?>
-          <?= $hostContext ? $this->qlink(
-            $this->escape($event->service_description),
-            'monitoring/show/service',
-            array(
-              'host' => $event->host_name,
-              'service' => $event->service_description)
-            ) : $this->escape($event->service_description); ?> <?= $this->translate('on') . ' ' . $this->escape($event->host_name); ?>
+          <?= sprintf(
+              $this->translate('%s on %s', 'Service running on host'),
+              $hostContext ? $this->qlink(
+                  $this->escape($event->service_display_name),
+                  'monitoring/show/service',
+                  array(
+                      'host' => $event->host_name,
+                      'service' => $event->service_description
+                  )
+              ) : $this->escape($event->service_display_name),
+              $event->host_display_name
+          ) ?>
         <?php else: ?>
           <?= $this->escape($event->host_name); ?>
         <?php endif ?>
           <br>
           <div>
-            <?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $msg; ?>
+            <?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $this->escape($msg) ?>
           </div>
         </td>
       </tr>
diff --git a/modules/monitoring/configuration.php b/modules/monitoring/configuration.php
index d61e32858..72df4e73f 100644
--- a/modules/monitoring/configuration.php
+++ b/modules/monitoring/configuration.php
@@ -1,53 +1,68 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
-/** @var $this \Icinga\Application\Modules\Module */
+/** @type $this \Icinga\Application\Modules\Module */
 
 $this->providePermission(
     'monitoring/command/*',
     $this->translate('Allow all commands')
 );
-$this->providePermission(
-    'monitoring/command/schedule*',
-    $this->translate('Allow all scheduling checks and downtimes')
-);
 $this->providePermission(
     'monitoring/command/schedule-check',
     $this->translate('Allow scheduling host and service checks')
 );
-$this->providePermission(
-    'monitoring/command/schedule-downtime',
-    $this->translate('Allow scheduling host and service downtimes')
-);
 $this->providePermission(
     'monitoring/command/acknowledge-problem',
     $this->translate('Allow acknowledging host and service problems')
 );
-$this->providePermission(
-    'monitoring/command/add-comment',
-    $this->translate('Allow commenting on hosts and services')
-);
-$this->providePermission(
-    'monitoring/command/remove*',
-    $this->translate('Allow removing problem acknowledgements, host and service comments and downtimes')
-);
 $this->providePermission(
     'monitoring/command/remove-acknowledgement',
     $this->translate('Allow removing problem acknowledgements')
 );
 $this->providePermission(
-    'monitoring/command/remove-comment',
-    $this->translate('Allow removing host and service comments')
+    'monitoring/command/comment/*',
+    $this->translate('Allow adding and deleting host and service comments')
 );
 $this->providePermission(
-    'monitoring/command/remove-downtime',
-    $this->translate('Allow removing host and service downtimes')
+    'monitoring/command/comment/add',
+    $this->translate('Allow commenting on hosts and services')
+);
+$this->providePermission(
+    'monitoring/command/comment/delete',
+    $this->translate('Allow deleting host and service comments')
+);
+$this->providePermission(
+    'monitoring/command/downtime/*',
+    $this->translate('Allow scheduling and deleting host and service downtimes')
+);
+$this->providePermission(
+    'monitoring/command/downtime/schedule',
+    $this->translate('Allow scheduling host and service downtimes')
+);
+$this->providePermission(
+    'monitoring/command/downtime/delete',
+    $this->translate('Allow deleting host and service downtimes')
+);
+$this->providePermission(
+    'monitoring/command/process-check-result',
+    $this->translate('Allow processing host and service check results')
+);
+$this->providePermission(
+    'monitoring/command/feature/program',
+    $this->translate('Allow processing commands for toggling features on a program-wide basis')
+);
+$this->providePermission(
+    'monitoring/command/feature/object',
+    $this->translate('Allow processing commands for toggling features on host and service objects')
 );
 
 $this->provideRestriction(
-    'monitoring/filter',
-    $this->translate('Restrict views to the hosts and services that match the filter')
+    'monitoring/hosts/filter',
+    $this->translate('Restrict hosts view to the hosts that match the filter')
+);
+
+$this->provideRestriction(
+    'monitoring/services/filter',
+    $this->translate('Restrict services view to the services that match the filter')
 );
 
 $this->provideConfigTab('backends', array(
@@ -127,22 +142,27 @@ $section->add($this->translate('Hostgroups'), array(
     'url'      => 'monitoring/list/hostgroups',
     'priority' => 60
 ));
-$section->add($this->translate('Contactgroups'), array(
-    'url'      => 'monitoring/list/contactgroups',
-    'priority' => 61
-));
-$section->add($this->translate('Downtimes'), array(
-    'url'      => 'monitoring/list/downtimes',
-    'priority' => 71
-));
-$section->add($this->translate('Comments'), array(
-    'url'      => 'monitoring/list/comments?comment_type=(comment|ack)',
-    'priority' => 70
-));
 $section->add($this->translate('Contacts'), array(
     'url'      => 'monitoring/list/contacts',
     'priority' => 70
 ));
+$section->add($this->translate('Contactgroups'), array(
+    'url'      => 'monitoring/list/contactgroups',
+    'priority' => 70
+));
+$section->add($this->translate('Comments'), array(
+    'url'      => 'monitoring/list/comments?comment_type=(comment|ack)',
+    'priority' => 80
+));
+$section->add($this->translate('Downtimes'), array(
+    'url'      => 'monitoring/list/downtimes',
+    'priority' => 80
+));
+$section->add($this->translate('Notifications'), array(
+    'url'      => 'monitoring/list/notifications',
+    'priority' => 80
+));
+
 
 /*
  * History Section
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
index 5145a96ad..a522d702e 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
@@ -23,6 +23,12 @@ class CommentQuery extends IdoQuery
             'comment_service'       => 'so.name2 COLLATE latin1_general_ci',
             'service'               => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279
             'comment_objecttype'    => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END",
+        ),
+        'hosts' => array(
+            'host_display_name'     => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END'
+        ),
+        'services' => array(
+            'service_display_name'  => 's.display_name'
         )
     );
 
@@ -44,4 +50,29 @@ class CommentQuery extends IdoQuery
         );
         $this->joinedVirtualTables = array('comments' => true);
     }
+
+    protected function joinHosts()
+    {
+        $this->select->joinLeft(
+            array('h' => $this->prefix . 'hosts'),
+            'h.host_object_id = ho.object_id',
+            array()
+        );
+        return $this;
+    }
+
+    protected function joinServices()
+    {
+        $this->select->joinLeft(
+            array('s' => $this->prefix . 'services'),
+            's.service_object_id = so.object_id',
+            array()
+        );
+        $this->select->joinLeft(
+            array('sh' => $this->prefix . 'hosts'),
+            'sh.host_object_id = s.host_object_id',
+            array()
+        );
+        return $this;
+    }
 }
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php
index a53fd18e9..efc10f6a5 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php
@@ -1,47 +1,41 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
-/**
- * Handling downtime queries
- */
 class DowntimeQuery extends IdoQuery
 {
-    /**
-     * Column map
-     * @var array
-     */
     protected $columnMap = array(
         'downtime' => array(
-            'downtime_author'          => 'sd.author_name',
-            'author'                   => 'sd.author_name',
-            'downtime_comment'         => 'sd.comment_data',
-            'downtime_entry_time'      => 'UNIX_TIMESTAMP(sd.entry_time)',
-            'downtime_is_fixed'        => 'sd.is_fixed',
-            'downtime_is_flexible'     => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END',
-            'downtime_triggered_by_id' => 'sd.triggered_by_id',
-            'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)',
-            'downtime_scheduled_end'   => 'UNIX_TIMESTAMP(sd.scheduled_end_time)',
-            'downtime_start'           => "UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)",
-            'downtime_end'             => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END',
-            'downtime_duration'        => 'sd.duration',
-            'downtime_is_in_effect'    => 'sd.is_in_effect',
-            'downtime_internal_id'     => 'sd.internal_downtime_id',
-            'downtime_host'            => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', // #7278, #7279
-            'host'                     => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci',
-            'downtime_service'         => 'so.name2 COLLATE latin1_general_ci',
-            'service'                  => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279
-            'downtime_objecttype'      => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END",
-            'downtime_host_state'      => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
-            'downtime_service_state'   => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
+            'downtime_author'           => 'sd.author_name',
+            'author'                    => 'sd.author_name',
+            'downtime_comment'          => 'sd.comment_data',
+            'downtime_entry_time'       => 'UNIX_TIMESTAMP(sd.entry_time)',
+            'downtime_is_fixed'         => 'sd.is_fixed',
+            'downtime_is_flexible'      => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END',
+            'downtime_triggered_by_id'  => 'sd.triggered_by_id',
+            'downtime_scheduled_start'  => 'UNIX_TIMESTAMP(sd.scheduled_start_time)',
+            'downtime_scheduled_end'    => 'UNIX_TIMESTAMP(sd.scheduled_end_time)',
+            'downtime_start'            => "UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)",
+            'downtime_end'              => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END',
+            'downtime_duration'         => 'sd.duration',
+            'downtime_is_in_effect'     => 'sd.is_in_effect',
+            'downtime_internal_id'      => 'sd.internal_downtime_id',
+            'downtime_host'             => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', // #7278, #7279
+            'host'                      => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci',
+            'downtime_service'          => 'so.name2 COLLATE latin1_general_ci',
+            'service'                   => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279
+            'downtime_objecttype'       => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END",
+            'downtime_host_state'       => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
+            'downtime_service_state'    => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
         ),
+        'hosts' => array(
+            'host_display_name'         => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END'
+        ),
+        'services' => array(
+            'service_display_name'      => 's.display_name'
+        )
     );
 
-    /**
-     * Join with scheduleddowntime
-     */
     protected function joinBaseTables()
     {
         $this->select->from(
@@ -70,4 +64,29 @@ class DowntimeQuery extends IdoQuery
         );
         $this->joinedVirtualTables = array('downtime' => true);
     }
+
+    protected function joinHosts()
+    {
+        $this->select->joinLeft(
+            array('h' => $this->prefix . 'hosts'),
+            'h.host_object_id = ho.object_id',
+            array()
+        );
+        return $this;
+    }
+
+    protected function joinServices()
+    {
+        $this->select->joinLeft(
+            array('s' => $this->prefix . 'services'),
+            's.service_object_id = so.object_id',
+            array()
+        );
+        $this->select->joinLeft(
+            array('sh' => $this->prefix . 'hosts'),
+            'sh.host_object_id = s.host_object_id',
+            array()
+        );
+        return $this;
+    }
 }
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php
index 2d5a0a2d8..2896f9536 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php
@@ -1,11 +1,9 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
-use Icinga\Data\Filter\Filter;
 use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
 
 class EventHistoryQuery extends IdoQuery
 {
@@ -13,28 +11,33 @@ class EventHistoryQuery extends IdoQuery
 
     protected $columnMap = array(
         'eventhistory' => array(
-            'cnt_notification'    => "SUM(CASE eh.type WHEN 'notify' THEN 1 ELSE 0 END)",
-            'cnt_hard_state'      => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
-            'cnt_soft_state'      => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
-            'cnt_downtime_start'  => "SUM(CASE eh.type WHEN 'dt_start' THEN 1 ELSE 0 END)",
-            'cnt_downtime_end'    => "SUM(CASE eh.type WHEN 'dt_end' THEN 1 ELSE 0 END)",
-            'host'                => 'eho.name1 COLLATE latin1_general_ci',
-            'service'             => 'eho.name2 COLLATE latin1_general_ci',
-            'host_name'           => 'eho.name1 COLLATE latin1_general_ci',
-            'service_description' => 'eho.name2 COLLATE latin1_general_ci',
-            'object_type'         => 'eh.object_type',
-            'timestamp'           => 'eh.timestamp',
-            'state'               => 'eh.state',
-            'attempt'             => 'eh.attempt',
-            'max_attempts'        => 'eh.max_attempts',
-            'output'              => 'eh.output', // we do not want long_output
-            'type'                => 'eh.type',
-            'service_host_name'   => 'eho.name1 COLLATE latin1_general_ci',
-            'service_description' => 'eho.name2 COLLATE latin1_general_ci'
+            'cnt_notification'      => "SUM(CASE eh.type WHEN 'notify' THEN 1 ELSE 0 END)",
+            'cnt_hard_state'        => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
+            'cnt_soft_state'        => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
+            'cnt_downtime_start'    => "SUM(CASE eh.type WHEN 'dt_start' THEN 1 ELSE 0 END)",
+            'cnt_downtime_end'      => "SUM(CASE eh.type WHEN 'dt_end' THEN 1 ELSE 0 END)",
+            'host'                  => 'eho.name1 COLLATE latin1_general_ci',
+            'service'               => 'eho.name2 COLLATE latin1_general_ci',
+            'host_name'             => 'eho.name1 COLLATE latin1_general_ci',
+            'service_description'   => 'eho.name2 COLLATE latin1_general_ci',
+            'object_type'           => 'eh.object_type',
+            'timestamp'             => 'eh.timestamp',
+            'state'                 => 'eh.state',
+            'attempt'               => 'eh.attempt',
+            'max_attempts'          => 'eh.max_attempts',
+            'output'                => 'eh.output', // we do not want long_output
+            'type'                  => 'eh.type',
+            'service_host_name'     => 'eho.name1 COLLATE latin1_general_ci'
         ),
         'hostgroups' => array(
-            'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+            'hostgroup'             => 'hgo.name1 COLLATE latin1_general_ci',
         ),
+        'hosts' => array(
+            'host_display_name'     => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END'
+        ),
+        'services' => array(
+            'service_display_name'  => 's.display_name'
+        )
     );
 
     protected $useSubqueryCount = true;
@@ -84,20 +87,20 @@ class EventHistoryQuery extends IdoQuery
 
     public function addFilter(Filter $filter)
     {
-  	    foreach ($this->subQueries as $sub) {
-		        $sub->applyFilter(clone $filter);
-		    }
-		    return $this;
+        foreach ($this->subQueries as $sub) {
+            $sub->applyFilter(clone $filter);
+        }
+        return $this;
     }
 
-	  public function where($condition, $value = null)
-	  {
-		  $this->requireColumn($condition);
-		  foreach ($this->subQueries as $sub) {
-		      $sub->where($condition, $value);
-		  }
-		  return $this;
-	  }
+    public function where($condition, $value = null)
+    {
+        $this->requireColumn($condition);
+        foreach ($this->subQueries as $sub) {
+            $sub->where($condition, $value);
+        }
+        return $this;
+    }
 
     protected function joinHostgroups()
     {
@@ -117,4 +120,28 @@ class EventHistoryQuery extends IdoQuery
         return $this;
     }
 
+    protected function joinHosts()
+    {
+        $this->select->joinLeft(
+            array('h' => $this->prefix . 'hosts'),
+            'h.host_object_id = eho.object_id',
+            array()
+        );
+        return $this;
+    }
+
+    protected function joinServices()
+    {
+        $this->select->joinLeft(
+            array('s' => $this->prefix . 'services'),
+            's.service_object_id = eho.object_id',
+            array()
+        );
+        $this->select->joinLeft(
+            array('sh' => $this->prefix . 'hosts'),
+            'sh.host_object_id = s.host_object_id',
+            array()
+        );
+        return $this;
+    }
 }
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php
index 20e98fc63..53c1d7ed7 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php
@@ -11,7 +11,7 @@ class GroupSummaryQuery extends IdoQuery
     protected $useSubqueryCount = true;
 
     protected $columnMap = array(
-        'hoststatussummary'     => array(
+        'hoststatussummary' => array(
             'hosts_up'                      => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)',
             'hosts_unreachable'             => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)',
             'hosts_unreachable_handled'     => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
@@ -20,21 +20,22 @@ class GroupSummaryQuery extends IdoQuery
             'hosts_down_handled'            => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
             'hosts_down_unhandled'          => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)',
             'hosts_pending'                 => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)',
-            'hostgroup'                     => 'hostgroup'
+            'hostgroup'                     => 'hostgroup',
+            'hostgroup_alias'               => 'hostgroup_alias'
         ),
-        'servicestatussummary'  => array(
-            'services_total'                => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)',
-            'services_ok'                   => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
-            'services_pending'              => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
-            'services_warning'              => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
-            'services_warning_handled'      => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
-            'services_critical'             => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
-            'services_critical_handled'     => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
-            'services_unknown'              => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
-            'services_unknown_handled'      => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
-            'services_warning_unhandled'    => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
-            'services_critical_unhandled'   => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
-            'services_unknown_unhandled'    => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
+        'servicestatussummary' => array(
+            'services_total'                                => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)',
+            'services_ok'                                   => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
+            'services_pending'                              => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
+            'services_warning'                              => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
+            'services_warning_handled'                      => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+            'services_critical'                             => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
+            'services_critical_handled'                     => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+            'services_unknown'                              => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
+            'services_unknown_handled'                      => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+            'services_warning_unhandled'                    => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
+            'services_critical_unhandled'                   => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
+            'services_unknown_unhandled'                    => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
             'services_severity'                             => 'MAX(CASE WHEN object_type = \'service\' THEN severity ELSE 0 END)',
             'services_ok_last_state_change'                 => 'MAX(CASE WHEN object_type = \'service\' AND state = 0 THEN state_change ELSE 0 END)',
             'services_pending_last_state_change'            => 'MAX(CASE WHEN object_type = \'service\' AND state = 99 THEN state_change ELSE 0 END)',
@@ -44,7 +45,8 @@ class GroupSummaryQuery extends IdoQuery
             'services_warning_last_state_change_unhandled'  => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
             'services_critical_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
             'services_unknown_last_state_change_unhandled'  => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
-            'servicegroup'                  => 'servicegroup'
+            'servicegroup'                                  => 'servicegroup',
+            'servicegroup_alias'                            => 'servicegroup_alias'
         )
     );
 
@@ -52,14 +54,17 @@ class GroupSummaryQuery extends IdoQuery
     {
         $columns = array(
             'object_type',
-            'host_state',
+            'host_state'
         );
 
-        // Prepend group column since we'll use columns index 0 later for grouping
         if (in_array('servicegroup', $this->desiredColumns)) {
-            array_unshift($columns, 'servicegroup');
+            $columns[] = 'servicegroup';
+            $columns[] = 'servicegroup_alias';
+            $groupColumns = array('servicegroup', 'servicegroup_alias');
         } else {
-            array_unshift($columns, 'hostgroup');
+            $columns[] = 'hostgroup';
+            $columns[] = 'hostgroup_alias';
+            $groupColumns = array('hostgroup', 'hostgroup_alias');
         }
         $hosts = $this->createSubQuery(
             'Hoststatus',
@@ -75,6 +80,7 @@ class GroupSummaryQuery extends IdoQuery
             $hosts->group(array(
                 'sgo.name1',
                 'ho.object_id',
+                'sg.alias',
                 'state',
                 'acknowledged',
                 'in_downtime',
@@ -92,16 +98,8 @@ class GroupSummaryQuery extends IdoQuery
                 'severity'     => 'service_severity'
             )
         );
-
-        $groupColumn = 'hostgroup';
-
-        if (in_array('servicegroup', $this->desiredColumns)) {
-            $groupColumn = 'servicegroup';
-        }
-
         $union = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL);
-        $this->select->from(array('statussummary' => $union), array())->group(array($groupColumn));
-
+        $this->select->from(array('statussummary' => $union), array())->group($groupColumns);
         $this->joinedVirtualTables = array(
             'servicestatussummary'  => true,
             'hoststatussummary'     => true
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php
index e9903ec86..7cca01d31 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php
@@ -84,10 +84,12 @@ class HoststatusQuery extends IdoQuery
             END'
         ),
         'hostgroups' => array(
-            'hostgroup'     => 'hgo.name1 COLLATE latin1_general_ci',
+            'hostgroup'         => 'hgo.name1 COLLATE latin1_general_ci',
+            'hostgroup_alias'   => 'hg.alias'
         ),
         'servicegroups' => array(
-            'servicegroup'  => 'sgo.name1 COLLATE latin1_general_ci',
+            'servicegroup'          => 'sgo.name1 COLLATE latin1_general_ci',
+            'servicegroup_alias'    => 'sg.alias'
         ),
         'contactgroups' => array(
             'contactgroup'  => 'contactgroup',
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
index 4682487d2..cf6968ea3 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
@@ -292,7 +292,6 @@ abstract class IdoQuery extends DbQuery
         $mapped = $this->getMappedField($field);
         if ($mapped === null) {
             return stripos($field, 'UNIX_TIMESTAMP') !== false;
-            return false;
         }
         return stripos($mapped, 'UNIX_TIMESTAMP') !== false;
     }
@@ -324,6 +323,11 @@ abstract class IdoQuery extends DbQuery
             foreach ($columns as $key => & $value) {
                 $value = preg_replace('/ COLLATE .+$/', '', $value);
                 $value = preg_replace('/inet_aton\(([[:word:].]+)\)/i', '$1::inet - \'0.0.0.0\'', $value);
+                $value = preg_replace(
+                    '/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i',
+                    'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END',
+                    $value
+                );
             }
         }
     }
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php
index 00b6957b8..3181eebbf 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php
@@ -1,41 +1,37 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
-/**
- * Notification query
- */
 class NotificationQuery extends IdoQuery
 {
-    /**
-     * Column map
-     *
-     * @var array
-     */
     protected $columnMap = array(
         'notification' => array(
-            'notification_output'       => 'n.output',
-            'notification_start_time'   => 'UNIX_TIMESTAMP(n.start_time)',
-            'notification_state'        => 'n.state',
-            'notification_object_id'    => 'n.object_id'
+            'notification_output'           => 'n.output',
+            'notification_start_time'       => 'UNIX_TIMESTAMP(n.start_time)',
+            'notification_state'            => 'n.state',
+            'notification_object_id'        => 'n.object_id'
         ),
         'objects' => array(
-            'host'                      => 'o.name1',
-            'service'                   => 'o.name2'
+            'host'                          => 'o.name1',
+            'service'                       => 'o.name2'
         ),
         'contact' => array(
-            'notification_contact'      => 'c_o.name1',
-            'contact_object_id'         => 'c_o.object_id'
+            'notification_contact'          => 'c_o.name1',
+            'contact_object_id'             => 'c_o.object_id'
         ),
         'command' => array(
-            'notification_command'      => 'cmd_o.name1'
+            'notification_command'          => 'cmd_o.name1'
         ),
         'acknowledgement' => array(
             'acknowledgement_entry_time'    => 'UNIX_TIMESTAMP(a.entry_time)',
             'acknowledgement_author_name'   => 'a.author_name',
             'acknowledgement_comment_data'  => 'a.comment_data'
+        ),
+        'hosts' => array(
+            'host_display_name'             => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END'
+        ),
+        'services' => array(
+            'service_display_name'          => 's.display_name'
         )
     );
 
@@ -110,4 +106,29 @@ class NotificationQuery extends IdoQuery
             array()
         );
     }
+
+    protected function joinHosts()
+    {
+        $this->select->joinLeft(
+            array('h' => $this->prefix . 'hosts'),
+            'h.host_object_id = o.object_id',
+            array()
+        );
+        return $this;
+    }
+
+    protected function joinServices()
+    {
+        $this->select->joinLeft(
+            array('s' => $this->prefix . 'services'),
+            's.service_object_id = o.object_id',
+            array()
+        );
+        $this->select->joinLeft(
+            array('sh' => $this->prefix . 'hosts'),
+            'sh.host_object_id = s.host_object_id',
+            array()
+        );
+        return $this;
+    }
 }
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php
index e6abd4f77..989c2b698 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php
@@ -11,17 +11,27 @@ class ProgramstatusQuery extends IdoQuery
 {
     protected $columnMap = array(
         'programstatus' => array(
-            'id'                                => 'programstatus_id',
-            'status_update_time'                => 'UNIX_TIMESTAMP(status_update_time)',
-            'program_start_time'                => 'UNIX_TIMESTAMP(program_start_time)',
-            'program_end_time'                  => 'UNIX_TIMESTAMP(program_end_time)',
-            'is_currently_running'              => 'is_currently_running',
+            'id'                    => 'programstatus_id',
+            'status_update_time'    => 'UNIX_TIMESTAMP(programstatus.status_update_time)',
+            'program_start_time'    => 'UNIX_TIMESTAMP(programstatus.program_start_time)',
+            'program_end_time'      => 'UNIX_TIMESTAMP(programstatus.program_end_time)',
+            'is_currently_running'  => 'CASE WHEN (programstatus.is_currently_running = 0)
+                THEN
+                    0
+                ELSE
+                    CASE WHEN (UNIX_TIMESTAMP(programstatus.status_update_time) + 60 > UNIX_TIMESTAMP(NOW()))
+                    THEN
+                        1
+                    ELSE
+                        0
+                    END
+                END',
             'process_id'                        => 'process_id',
             'daemon_mode'                       => 'daemon_mode',
-            'last_command_check'                => 'UNIX_TIMESTAMP(last_command_check)',
-            'last_log_rotation'                 => 'UNIX_TIMESTAMP(last_log_rotation)',
+            'last_command_check'                => 'UNIX_TIMESTAMP(programstatus.last_command_check)',
+            'last_log_rotation'                 => 'UNIX_TIMESTAMP(programstatus.last_log_rotation)',
             'notifications_enabled'             => 'notifications_enabled',
-            'disable_notif_expire_time'         => 'UNIX_TIMESTAMP(disable_notif_expire_time)',
+            'disable_notif_expire_time'         => 'UNIX_TIMESTAMP(programstatus.disable_notif_expire_time)',
             'active_service_checks_enabled'     => 'active_service_checks_enabled',
             'passive_service_checks_enabled'    => 'passive_service_checks_enabled',
             'active_host_checks_enabled'        => 'active_host_checks_enabled',
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php
index e979cdc08..dfa81b1ef 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php
@@ -1,6 +1,4 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\Backend\Ido\Query;
 
@@ -8,29 +6,27 @@ class StatehistoryQuery extends IdoQuery
 {
     protected $types = array(
         'soft_state' => 0,
-        'hard_state' => 1,
+        'hard_state' => 1
     );
 
     protected $columnMap = array(
         'statehistory' => array(
-            'raw_timestamp' => 'sh.state_time',
-            'timestamp'  => 'UNIX_TIMESTAMP(sh.state_time)',
-            'state_time' => 'sh.state_time',
-            'object_id'  => 'sho.object_id',
-            'type'       => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)",
-            'state'      => 'sh.state',
-            'state_type' => 'sh.state_type',
-            'output'     => 'sh.output',
-            'attempt'      => 'sh.current_check_attempt',
-            'max_attempts' => 'sh.max_check_attempts',
-
-            'host'                => 'sho.name1 COLLATE latin1_general_ci',
-            'service'             => 'sho.name2 COLLATE latin1_general_ci',
-            'host_name'           => 'sho.name1 COLLATE latin1_general_ci',
-            'service_description' => 'sho.name2 COLLATE latin1_general_ci',
-            'service_host_name'   => 'sho.name1 COLLATE latin1_general_ci',
-            'service_description' => 'sho.name2 COLLATE latin1_general_ci',
-            'object_type'         => "CASE WHEN sho.objecttype_id = 1 THEN 'host' ELSE 'service' END"
+            'raw_timestamp'         => 'sh.state_time',
+            'timestamp'             => 'UNIX_TIMESTAMP(sh.state_time)',
+            'state_time'            => 'sh.state_time',
+            'object_id'             => 'sho.object_id',
+            'type'                  => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)",
+            'state'                 => 'sh.state',
+            'state_type'            => 'sh.state_type',
+            'output'                => 'sh.output',
+            'attempt'               => 'sh.current_check_attempt',
+            'max_attempts'          => 'sh.max_check_attempts',
+            'host'                  => 'sho.name1 COLLATE latin1_general_ci',
+            'host_name'             => 'sho.name1 COLLATE latin1_general_ci',
+            'service'               => 'sho.name2 COLLATE latin1_general_ci',
+            'service_description'   => 'sho.name2 COLLATE latin1_general_ci',
+            'service_host_name'     => 'sho.name1 COLLATE latin1_general_ci',
+            'object_type'           => "CASE WHEN sho.objecttype_id = 1 THEN 'host' ELSE 'service' END"
         )
     );
 
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
index e390aa114..0cc807ac8 100644
--- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
@@ -118,7 +118,6 @@ class StatusQuery extends IdoQuery
 
             'host_modified_host_attributes' => 'hs.modified_host_attributes',
             'host_event_handler' => 'hs.event_handler',
-            'host_check_command' => 'hs.check_command',
             'host_normal_check_interval' => 'hs.normal_check_interval',
             'host_retry_check_interval' => 'hs.retry_check_interval',
             'host_check_timeperiod_object_id' => 'hs.check_timeperiod_object_id',
@@ -161,10 +160,12 @@ class StatusQuery extends IdoQuery
             END'
         ),
         'hostgroups' => array(
-            'hostgroup' => 'hgo.name1',
+            'hostgroup'         => 'hgo.name1 COLLATE latin1_general_ci',
+            'hostgroup_alias'   => 'hg.alias'
         ),
         'servicegroups' => array(
-            'servicegroup' => 'sgo.name1',
+            'servicegroup'          => 'sgo.name1 COLLATE latin1_general_ci',
+            'servicegroup_alias'    => 'sg.alias'
         ),
         'services' => array(
             'service_host_name'      => 'so.name1 COLLATE latin1_general_ci',
@@ -368,7 +369,7 @@ class StatusQuery extends IdoQuery
 
             case 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END':
                 if ($sign !== '=') break;
-               
+
                 if ($expression) {
                     return 'ss.current_state > 0';
                 } else {
@@ -518,12 +519,14 @@ class StatusQuery extends IdoQuery
     protected function joinServiceproblemsummary()
     {
         $sub = new Zend_Db_Expr('(SELECT'
-             . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,'
-             . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END) AS handled_services_count,'
+             . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,'
+             . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END) AS handled_services_count,'
              . ' s.host_object_id FROM icinga_servicestatus ss'
              . ' JOIN icinga_services s'
              . ' ON s.service_object_id = ss.service_object_id'
              . ' AND ss.current_state > 0'
+             . ' JOIN icinga_hoststatus hs'
+             . ' ON hs.host_object_id = s.host_object_id'
              . ' GROUP BY s.host_object_id)');
         $this->select->joinLeft(
             array('sps' => $sub),
diff --git a/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php
index c8f75f540..d165f1252 100644
--- a/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php
+++ b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php
@@ -145,7 +145,7 @@ class MonitoringBackend implements Selectable, Queryable, ConnectionInterface
                 $this->type = lcfirst(substr($class, 0, -7));
             } else {
                 throw new ProgrammingError(
-                    '%s is not a valid monitoring backend class name', 
+                    '%s is not a valid monitoring backend class name',
                     $class
                 );
             }
@@ -251,7 +251,7 @@ class MonitoringBackend implements Selectable, Queryable, ConnectionInterface
      * @param   string  $name
      * @param   array   $columns
      *
-     * @return  DataView
+     * @return  \Icinga\Module\Monitoring\DataView\DataView
      */
     public function from($name, array $columns = null)
     {
diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php
index 32bafb8b2..f294e9a2e 100644
--- a/modules/monitoring/library/Monitoring/Controller.php
+++ b/modules/monitoring/library/Monitoring/Controller.php
@@ -4,9 +4,11 @@
 
 namespace Icinga\Module\Monitoring;
 
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filterable;
+use Icinga\File\Csv;
 use Icinga\Web\Controller\ModuleActionController;
 use Icinga\Web\Url;
-use Icinga\File\Csv;
 
 /**
  * Base class for all monitoring action controller
@@ -60,5 +62,21 @@ class Controller extends ModuleActionController
             exit;
         }
     }
+
+    /**
+     * Apply a restriction on the given data view
+     *
+     * @param   string      $restriction    The name of restriction
+     * @param   Filterable  $filterable     The filterable to restrict
+     *
+     * @return  Filterable  The filterable
+     */
+    protected function applyRestriction($restriction, Filterable $view)
+    {
+        foreach ($this->getRestrictions($restriction) as $filter) {
+            $view->applyFilter(Filter::fromQueryString($filter));
+        }
+        return $view;
+    }
 }
 
diff --git a/modules/monitoring/library/Monitoring/DataView/Comment.php b/modules/monitoring/library/Monitoring/DataView/Comment.php
index 4d62fd27c..4cd11e1a1 100644
--- a/modules/monitoring/library/Monitoring/DataView/Comment.php
+++ b/modules/monitoring/library/Monitoring/DataView/Comment.php
@@ -29,6 +29,8 @@ class Comment extends DataView
             'comment_service',
             'host',
             'service',
+            'host_display_name',
+            'service_display_name'
         );
     }
 
@@ -43,13 +45,20 @@ class Comment extends DataView
             'comment_timestamp' => array(
                 'order' => self::SORT_DESC
             ),
-            'comment_host' => array(
+            'host_display_name' => array(
                 'columns' => array(
-                    'comment_host',
-                    'comment_service'
+                    'host_display_name',
+                    'service_display_name'
                 ),
                 'order' => self::SORT_ASC
             ),
+            'service_display_name' => array(
+                'columns' => array(
+                    'service_display_name',
+                    'host_display_name'
+                ),
+                'order' => self::SORT_ASC
+            )
         );
     }
 }
diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php
index 1fdd8b4f9..da48f31c3 100644
--- a/modules/monitoring/library/Monitoring/DataView/DataView.php
+++ b/modules/monitoring/library/Monitoring/DataView/DataView.php
@@ -83,6 +83,7 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable
 
     public function dump()
     {
+        $this->order();
         return $this->query->dump();
     }
 
@@ -354,12 +355,21 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable
         return $this;
     }
 
+    /**
+     * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing
+     * column validation. Filter::matchAny() for the IdoQuery (or the DbQuery or the SimpleQuery I didn't have a look)
+     * is required for the filter to work properly.
+     */
     public function setFilter(Filter $filter)
     {
         $this->query->setFilter($filter);
         return $this;
     }
 
+    /**
+     * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing
+     * column validation.
+     */
     public function addFilter(Filter $filter)
     {
         $this->query->addFilter(clone($filter));
diff --git a/modules/monitoring/library/Monitoring/DataView/Downtime.php b/modules/monitoring/library/Monitoring/DataView/Downtime.php
index e075d658c..681608b17 100644
--- a/modules/monitoring/library/Monitoring/DataView/Downtime.php
+++ b/modules/monitoring/library/Monitoring/DataView/Downtime.php
@@ -32,7 +32,9 @@ class Downtime extends DataView
             'downtime_host',
             'downtime_service',
             'downtime_host_state',
-            'downtime_service_state'
+            'downtime_service_state',
+            'host_display_name',
+            'service_display_name'
         );
     }
 
@@ -40,18 +42,29 @@ class Downtime extends DataView
     {
         return array(
             'downtime_is_in_effect' => array(
+                'columns' => array(
+                    'downtime_is_in_effect',
+                    'downtime_scheduled_start'
+                ),
                 'order' => self::SORT_DESC
             ),
             'downtime_start' => array(
                 'order' => self::SORT_DESC
             ),
-            'downtime_host' => array(
+            'host_display_name' => array(
                 'columns' => array(
-                    'downtime_host',
-                    'downtime_service'
+                    'host_display_name',
+                    'service_display_name'
                 ),
                 'order' => self::SORT_ASC
             ),
+            'service_display_name' => array(
+                'columns' => array(
+                    'service_display_name',
+                    'host_display_name'
+                ),
+                'order' => self::SORT_ASC
+            )
         );
     }
 }
diff --git a/modules/monitoring/library/Monitoring/DataView/EventHistory.php b/modules/monitoring/library/Monitoring/DataView/EventHistory.php
index 09779b27d..f13815aae 100644
--- a/modules/monitoring/library/Monitoring/DataView/EventHistory.php
+++ b/modules/monitoring/library/Monitoring/DataView/EventHistory.php
@@ -1,6 +1,4 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\DataView;
 
@@ -20,7 +18,9 @@ class EventHistory extends DataView
             'cnt_downtime_start',
             'cnt_downtime_end',
             'host_name',
+            'host_display_name',
             'service_description',
+            'service_display_name',
             'object_type',
             'timestamp',
             'state',
@@ -38,8 +38,8 @@ class EventHistory extends DataView
     {
         return array(
             'timestamp' => array(
-                'columns' => array('timestamp'),
-                'order' => 'DESC'
+                'columns'   => array('timestamp'),
+                'order'     => 'DESC'
             )
         );
     }
diff --git a/modules/monitoring/library/Monitoring/DataView/Groupsummary.php b/modules/monitoring/library/Monitoring/DataView/Groupsummary.php
index 7fe6d2e6d..a4736e47c 100644
--- a/modules/monitoring/library/Monitoring/DataView/Groupsummary.php
+++ b/modules/monitoring/library/Monitoring/DataView/Groupsummary.php
@@ -15,7 +15,9 @@ class Groupsummary extends DataView
     {
         return array(
             'servicegroup',
+            'servicegroup_alias',
             'hostgroup',
+            'hostgroup_alias',
             'hosts_up',
             'hosts_unreachable',
             'hosts_unreachable_handled',
@@ -47,7 +49,7 @@ class Groupsummary extends DataView
             'services_unknown_last_state_change_unhandled'
         );
     }
-    
+
     public function getSortRules()
     {
         return array(
diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php
index e9b5b60dd..86bff52bf 100644
--- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php
+++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php
@@ -24,6 +24,7 @@ class HostStatus extends DataView
         return array(
             'host',
             'host_name',
+            'host_display_name',
             'host_alias',
             'host_address',
             'host_state',
@@ -90,7 +91,7 @@ class HostStatus extends DataView
     public function getSortRules()
     {
         return array(
-            'host_name' => array(
+            'host_display_name' => array(
                 'order' => self::SORT_ASC
             ),
             'host_address' => array(
diff --git a/modules/monitoring/library/Monitoring/DataView/Notification.php b/modules/monitoring/library/Monitoring/DataView/Notification.php
index 6156a5f15..7f6fd238f 100644
--- a/modules/monitoring/library/Monitoring/DataView/Notification.php
+++ b/modules/monitoring/library/Monitoring/DataView/Notification.php
@@ -20,7 +20,9 @@ class Notification extends DataView
             'notification_start_time',
             'notification_contact',
             'notification_output',
-            'notification_command'
+            'notification_command',
+            'host_display_name',
+            'service_display_name'
         );
     }
 
diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php
index 9edcabc87..e7e2accb2 100644
--- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php
+++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php
@@ -25,6 +25,7 @@ class ServiceStatus extends DataView
     {
         return array(
             'host_name',
+            'host_display_name',
             'host_state',
             'host_state_type',
             'host_last_state_change',
@@ -123,22 +124,12 @@ class ServiceStatus extends DataView
     public function getSortRules()
     {
         return array(
-            'host_name' => array(
+            'service_severity' => array(
                 'columns' => array(
-                    'service_host_name',
-                    'service_description'
+                    'service_severity',
+                    'service_last_state_change'
                 ),
-                'order' => self::SORT_ASC
-            ),
-            'host_address' => array(
-                'columns' => array(
-                    'host_ipv4',
-                    'service_description'
-                ),
-                'order' => self::SORT_ASC
-            ),
-            'host_last_state_change' => array(
-                'order' => self::SORT_ASC
+                'order' => self::SORT_DESC
             ),
             'host_severity' => array(
                 'columns' => array(
@@ -147,12 +138,19 @@ class ServiceStatus extends DataView
                 ),
                 'order' => self::SORT_ASC
             ),
-            'service_severity' => array(
+            'host_display_name' => array(
                 'columns' => array(
-                    'service_severity',
-                    'service_last_state_change',
+                    'host_display_name',
+                    'service_display_name'
                 ),
-                'order' => self::SORT_DESC
+                'order' => self::SORT_ASC
+            ),
+            'host_address' => array(
+                'columns' => array(
+                    'host_ipv4',
+                    'service_display_name'
+                ),
+                'order' => self::SORT_ASC
             )
         );
     }
diff --git a/modules/monitoring/library/Monitoring/MonitoringWizard.php b/modules/monitoring/library/Monitoring/MonitoringWizard.php
index 0ac4c7f63..d7a3671a4 100644
--- a/modules/monitoring/library/Monitoring/MonitoringWizard.php
+++ b/modules/monitoring/library/Monitoring/MonitoringWizard.php
@@ -4,6 +4,7 @@
 
 namespace Icinga\Module\Monitoring;
 
+use Icinga\Application\Icinga;
 use Icinga\Web\Form;
 use Icinga\Web\Wizard;
 use Icinga\Web\Request;
@@ -11,7 +12,6 @@ use Icinga\Module\Setup\Setup;
 use Icinga\Module\Setup\SetupWizard;
 use Icinga\Module\Setup\Requirements;
 use Icinga\Module\Setup\Utils\MakeDirStep;
-use Icinga\Module\Setup\Utils\EnableModuleStep;
 use Icinga\Module\Setup\Forms\SummaryPage;
 use Icinga\Module\Monitoring\Forms\Setup\WelcomePage;
 use Icinga\Module\Monitoring\Forms\Setup\BackendPage;
@@ -36,7 +36,7 @@ class MonitoringWizard extends Wizard implements SetupWizard
         $this->addPage(new LivestatusResourcePage());
         $this->addPage(new InstancePage());
         $this->addPage(new SecurityPage());
-        $this->addPage(new SummaryPage());
+        $this->addPage(new SummaryPage(array('name' => 'setup_monitoring_summary')));
     }
 
     /**
@@ -46,7 +46,7 @@ class MonitoringWizard extends Wizard implements SetupWizard
     {
         if ($page->getName() === 'setup_requirements') {
             $page->setRequirements($this->getRequirements());
-        } elseif ($page->getName() === 'setup_summary') {
+        } elseif ($page->getName() === 'setup_monitoring_summary') {
             $page->setSummary($this->getSetup()->getSummary());
             $page->setSubjectTitle(mt('monitoring', 'the monitoring module', 'setup.summary.subject'));
         } elseif (
@@ -78,23 +78,7 @@ class MonitoringWizard extends Wizard implements SetupWizard
             $skip = $backendData['type'] !== 'livestatus';
         }
 
-        if ($skip) {
-            if ($this->hasPageData($newPage->getName())) {
-                $pageData = & $this->getPageData();
-                unset($pageData[$newPage->getName()]);
-            }
-
-            $pages = $this->getPages();
-            if ($this->getDirection() === static::FORWARD) {
-                $nextPage = $pages[array_search($newPage, $pages, true) + 1];
-                $newPage = $this->getNewPage($nextPage->getName(), $newPage);
-            } else { // $this->getDirection() === static::BACKWARD
-                $previousPage = $pages[array_search($newPage, $pages, true) - 1];
-                $newPage = $this->getNewPage($previousPage->getName(), $newPage);
-            }
-        }
-
-        return $newPage;
+        return $skip ? $this->skipPage($newPage) : $newPage;
     }
 
     /**
@@ -124,7 +108,7 @@ class MonitoringWizard extends Wizard implements SetupWizard
         $pageData = $this->getPageData();
         $setup = new Setup();
 
-        $setup->addStep(new MakeDirStep(array($this->getConfigDir() . '/modules/monitoring'), 0775));
+        $setup->addStep(new MakeDirStep(array(Icinga::app()->getConfigDir() . '/modules/monitoring'), 2770));
 
         $setup->addStep(
             new BackendStep(array(
@@ -147,8 +131,6 @@ class MonitoringWizard extends Wizard implements SetupWizard
             ))
         );
 
-        $setup->addStep(new EnableModuleStep('monitoring'));
-
         return $setup;
     }
 
@@ -159,21 +141,4 @@ class MonitoringWizard extends Wizard implements SetupWizard
     {
         return new Requirements();
     }
-
-    /**
-     * Return the configuration directory of Icinga Web 2
-     *
-     * @return  string
-     */
-    protected function getConfigDir()
-    {
-        if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
-            $configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
-        } else {
-            $configDir = '/etc/icingaweb';
-        }
-
-        $canonical = realpath($configDir);
-        return $canonical ? $canonical : $configDir;
-    }
 }
diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php
index fd08f6a20..8f7df07cb 100644
--- a/modules/monitoring/library/Monitoring/Object/Host.php
+++ b/modules/monitoring/library/Monitoring/Object/Host.php
@@ -47,7 +47,7 @@ class Host extends MonitoredObject
     public $prefix = 'host_';
 
     /**
-     * Host name
+     * Hostname
      *
      * @var string
      */
@@ -63,8 +63,8 @@ class Host extends MonitoredObject
     /**
      * Create a new host
      *
-     * @param MonitoringBackend   $backend    Backend to fetch host information from
-     * @param string    $host       Host name
+     * @param MonitoringBackend $backend    Backend to fetch host information from
+     * @param string            $host       Hostname
      */
     public function __construct(MonitoringBackend $backend, $host)
     {
@@ -73,7 +73,7 @@ class Host extends MonitoredObject
     }
 
     /**
-     * Get the host name
+     * Get the hostname
      *
      * @return string
      */
@@ -91,6 +91,7 @@ class Host extends MonitoredObject
     {
         $columns = array(
             'host_name',
+            'host_display_name',
             'host_alias',
             'host_address',
             'host_state',
@@ -172,16 +173,16 @@ class Host extends MonitoredObject
         $translate = (bool) $translate;
         switch ((int) $state) {
             case self::STATE_UP:
-                $text = $translate ? mt('monitoring', 'up') : 'up';
+                $text = $translate ? mt('monitoring', 'UP') : 'up';
                 break;
             case self::STATE_DOWN:
-                $text = $translate ? mt('monitoring', 'down') : 'down';
+                $text = $translate ? mt('monitoring', 'DOWN') : 'down';
                 break;
             case self::STATE_UNREACHABLE:
-                $text = $translate ? mt('monitoring', 'unreachable') : 'unreachable';
+                $text = $translate ? mt('monitoring', 'UNREACHABLE') : 'unreachable';
                 break;
             case self::STATE_PENDING:
-                $text = $translate ? mt('monitoring', 'pending') : 'pending';
+                $text = $translate ? mt('monitoring', 'PENDING') : 'pending';
                 break;
             default:
                 throw new InvalidArgumentException('Invalid host state \'%s\'', $state);
diff --git a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php
index 4be004d99..213cf47b8 100644
--- a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php
+++ b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php
@@ -7,13 +7,15 @@ namespace Icinga\Module\Monitoring\Object;
 use InvalidArgumentException;
 use Icinga\Application\Config;
 use Icinga\Exception\InvalidPropertyException;
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filterable;
 use Icinga\Module\Monitoring\Backend\MonitoringBackend;
 use Icinga\Web\UrlParams;
 
 /**
  * A monitored Icinga object, i.e. host or service
  */
-abstract class MonitoredObject
+abstract class MonitoredObject implements Filterable
 {
     /**
      * Type host
@@ -116,6 +118,13 @@ abstract class MonitoredObject
      */
     protected $stats;
 
+    /**
+     * Filter
+     *
+     * @type Filter
+     */
+    protected $filter;
+
     /**
      * Create a monitored object, i.e. host or service
      *
@@ -133,6 +142,35 @@ abstract class MonitoredObject
      */
     abstract protected function getDataView();
 
+    public function applyFilter(Filter $filter)
+    {
+        $this->getFilter()->addFilter($filter);
+        return $this;
+    }
+
+    public function setFilter(Filter $filter)
+    {
+        // Left out on purpose. Interface is deprecated.
+    }
+
+    public function getFilter()
+    {
+        if ($this->filter === null) {
+            $this->filter = Filter::matchAny();
+        }
+        return $this->filter;
+    }
+
+    public function addFilter(Filter $filter)
+    {
+        // Left out on purpose. Interface is deprecated.
+    }
+
+    public function where($condition, $value = null)
+    {
+        // Left out on purpose. Interface is deprecated.
+    }
+
     /**
      * Fetch the object's properties
      *
@@ -140,7 +178,7 @@ abstract class MonitoredObject
      */
     public function fetch()
     {
-        $this->properties = $this->getDataView()->getQuery()->fetchRow();
+        $this->properties = $this->getDataView()->applyFilter($this->getFilter())->getQuery()->fetchRow();
         if ($this->properties === false) {
             return false;
         }
@@ -408,7 +446,9 @@ abstract class MonitoredObject
         $eventHistory = $this->backend->select()->from('eventHistory', array(
                 'object_type',
                 'host_name',
+                'host_display_name',
                 'service_description',
+                'service_display_name',
                 'timestamp',
                 'state',
                 'attempt',
@@ -421,7 +461,7 @@ abstract class MonitoredObject
         if ($this->type === self::TYPE_SERVICE) {
             $eventHistory->where('service_description', $this->service_description);
         }
-        $this->eventhistory = $eventHistory->getQuery();
+        $this->eventhistory = $eventHistory;
         return $this;
     }
 
diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php
index 6d5245f0d..870ff78ba 100644
--- a/modules/monitoring/library/Monitoring/Object/Service.php
+++ b/modules/monitoring/library/Monitoring/Object/Service.php
@@ -68,9 +68,9 @@ class Service extends MonitoredObject
     /**
      * Create a new service
      *
-     * @param MonitoringBackend   $backend    Backend to fetch service information from
-     * @param string    $host       Host name the service is running on
-     * @param string    $service    Service name
+     * @param MonitoringBackend $backend    Backend to fetch service information from
+     * @param string            $host       Hostname the service is running on
+     * @param string            $service    Service name
      */
     public function __construct(MonitoringBackend $backend, $host, $service)
     {
@@ -108,6 +108,7 @@ class Service extends MonitoredObject
     {
         return $this->backend->select()->from('serviceStatus', array(
             'host_name',
+            'host_display_name',
             'host_state',
             'host_state_type',
             'host_last_state_change',
@@ -213,19 +214,19 @@ class Service extends MonitoredObject
         $translate = (bool) $translate;
         switch ((int) $state) {
             case self::STATE_OK:
-                $text = $translate ? mt('monitoring', 'ok') : 'ok';
+                $text = $translate ? mt('monitoring', 'OK') : 'ok';
                 break;
             case self::STATE_WARNING:
-                $text = $translate ? mt('monitoring', 'warning') : 'warning';
+                $text = $translate ? mt('monitoring', 'WARNING') : 'warning';
                 break;
             case self::STATE_CRITICAL:
-                $text = $translate ? mt('monitoring', 'critical') : 'critical';
+                $text = $translate ? mt('monitoring', 'CRITICAL') : 'critical';
                 break;
             case self::STATE_UNKNOWN:
-                $text = $translate ? mt('monitoring', 'unknown') : 'unknown';
+                $text = $translate ? mt('monitoring', 'UNKNOWN') : 'unknown';
                 break;
             case self::STATE_PENDING:
-                $text = $translate ? mt('monitoring', 'pending') : 'pending';
+                $text = $translate ? mt('monitoring', 'PENDING') : 'pending';
                 break;
             default:
                 throw new InvalidArgumentException('Invalid service state \'%s\'', $state);
diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
index 6af3cde17..f51801192 100644
--- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
+++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php
@@ -4,10 +4,18 @@
 
 namespace Icinga\Module\Monitoring\Plugin;
 
+use Icinga\Util\Format;
 use InvalidArgumentException;
+use Icinga\Exception\ProgrammingError;
+use Icinga\Web\Widget\Chart\InlinePie;
+use Zend_Controller_Front;
 
 class Perfdata
 {
+    const PERFDATA_OK = 'ok';
+    const PERFDATA_WARNING = 'warning';
+    const PERFDATA_CRITICAL = 'critical';
+
     /**
      * The performance data value being parsed
      *
@@ -53,6 +61,8 @@ class Perfdata
     /**
      * The WARNING threshold
      *
+     * TODO: Should be parsed Range-Object instead of string
+     *
      * @var string
      */
     protected $warningThreshold;
@@ -60,6 +70,8 @@ class Perfdata
     /**
      * The CRITICAL threshold
      *
+     * TODO: Should be parsed Range-Object instead of string
+     *
      * @var string
      */
     protected $criticalThreshold;
@@ -159,6 +171,16 @@ class Perfdata
         return $this->unit === 'c';
     }
 
+    /**
+     * Returns whether it is possible to display a visual representation
+     *
+     * @return  bool    True when the perfdata is visualizable
+     */
+    public function isVisualizable()
+    {
+        return isset($this->minValue) && isset($this->maxValue) && isset($this->value);
+    }
+
     /**
      * Return this perfomance data's label
      */
@@ -223,7 +245,7 @@ class Perfdata
     /**
      * Return the minimum value or null if it is not available
      *
-     * @return  null|float
+     * @return  null|string
      */
     public function getMinimumValue()
     {
@@ -247,7 +269,7 @@ class Perfdata
      */
     public function __toString()
     {
-        return sprintf(strpos($this->label, ' ') === false ? '%s=%s' : "'%s'=%s", $this->label, $this->perfdataValue);
+        return $this->formatLabel();
     }
 
     /**
@@ -278,10 +300,8 @@ class Perfdata
                     $this->minValue = self::convert($parts[3], $this->unit);
                 }
             case 3:
-                // TODO(#6123): Tresholds have the same UOM and need to be converted as well!
                 $this->criticalThreshold = trim($parts[2]) ? trim($parts[2]) : null;
             case 2:
-                // TODO(#6123): Tresholds have the same UOM and need to be converted as well!
                 $this->warningThreshold = trim($parts[1]) ? trim($parts[1]) : null;
         }
     }
@@ -316,4 +336,122 @@ class Perfdata
             }
         }
     }
+
+    protected function calculatePieChartData()
+    {
+        $rawValue = $this->getValue();
+        $minValue = $this->getMinimumValue() !== null ? $this->getMinimumValue() : 0;
+        $maxValue = $this->getMaximumValue();
+        $usedValue = ($rawValue - $minValue);
+        $unusedValue = ($maxValue - $minValue) - $usedValue;
+
+        $warningThreshold = $this->convert($this->warningThreshold, $this->unit);
+        $criticalThreshold = $this->convert($this->criticalThreshold, $this->unit);
+
+        $gray = $unusedValue;
+        $green = $orange = $red = 0;
+
+        $pieState = self::PERFDATA_OK;
+        if ($warningThreshold > $criticalThreshold) {
+            // inverted threshold parsing OK > warning > critical
+            if (isset($warningThreshold) && $this->value <= $warningThreshold) {
+                $pieState = self::PERFDATA_WARNING;
+            }
+            if (isset($criticalThreshold) && $this->value <= $criticalThreshold) {
+                $pieState = self::PERFDATA_CRITICAL;
+            }
+
+        } else {
+            // TODO: Use standard perfdata range format to decide the state #8194
+
+            // regular threshold parsing  OK < warning < critical
+            if (isset($warningThreshold) && $rawValue > $warningThreshold) {
+                $pieState = self::PERFDATA_WARNING;
+            }
+            if (isset($criticalThreshold) && $rawValue > $criticalThreshold) {
+                $pieState = self::PERFDATA_CRITICAL;
+            }
+        }
+
+        switch ($pieState) {
+            case self::PERFDATA_OK:
+                $green = $usedValue;
+                break;
+
+            case self::PERFDATA_CRITICAL:
+                $red = $usedValue;
+                break;
+
+            case self::PERFDATA_WARNING:
+                $orange = $usedValue;
+                break;
+        }
+
+        return array($green, $orange, $red, $gray);
+    }
+
+
+    public function asInlinePie()
+    {
+        if (! $this->isVisualizable()) {
+            throw new ProgrammingError('Cannot calculate piechart data for unvisualizable perfdata entry.');
+        }
+
+        $data = $this->calculatePieChartData();
+        $pieChart = new InlinePie($data, $this);
+        $pieChart->setColors(array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd'));
+        $pieChart->setSparklineClass('sparkline-perfdata');
+
+        if (Zend_Controller_Front::getInstance()->getRequest()->isXmlHttpRequest()) {
+            $pieChart->disableNoScript();
+        }
+        return $pieChart;
+    }
+
+    /**
+     * Format the given value depending on the currently used unit
+     */
+    protected function format($value)
+    {
+        if ($this->isPercentage()) {
+            return (string)$value . '%';
+        }
+        if ($this->isBytes()) {
+            return Format::bytes($value);
+        }
+        if ($this->isSeconds()) {
+            return Format::seconds($value);
+        }
+        return number_format($value, 2);
+    }
+
+    /**
+     * Format the title string that represents this perfdata set
+     *
+     * @param bool $html
+     *
+     * @return stringS
+     */
+    public function formatLabel($html = false)
+    {
+        return sprintf(
+            $html ? t('<b>%s %s</b> (%s%%)') : t('%s %s (%s%%)'),
+            htmlspecialchars($this->getLabel()),
+            $this->format($this->value),
+            number_format($this->getPercentage(), 2)
+        );
+    }
+
+    public function toArray()
+    {
+        $parts = array(
+            $this->getLabel(),
+            'value' => $this->format($this->getvalue()),
+            'min' => isset($this->minValue) && !$this->isPercentage() ? $this->format($this->minValue) : '',
+            'max' => isset($this->maxValue) && !$this->isPercentage() ? $this->format($this->maxValue) : '',
+            'warn' => isset($this->warningThreshold) ? $this->format(self::convert($this->warningThreshold, $this->unit)) : '',
+            'crit' => isset($this->criticalThreshold) ? $this->format(self::convert($this->criticalThreshold, $this->unit)) : ''
+        );
+        return $parts;
+    }
 }
diff --git a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php
index 7ee73d575..5de11e1e2 100644
--- a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php
+++ b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php
@@ -1,11 +1,8 @@
 <?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
 
 namespace Icinga\Module\Monitoring\Web\Controller;
 
 use Icinga\Module\Monitoring\Controller;
-use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
 use Icinga\Module\Monitoring\Forms\Command\Object\CheckNowCommandForm;
 use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentCommandForm;
 use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimeCommandForm;
@@ -15,7 +12,6 @@ use Icinga\Module\Monitoring\Forms\Command\Object\ToggleObjectFeaturesCommandFor
 use Icinga\Web\Hook;
 use Icinga\Web\Url;
 use Icinga\Web\Widget\Tabextension\DashboardAction;
-use Icinga\Web\Widget\Tabextension\OutputFormat;
 
 /**
  * Base class for the host and service controller
@@ -57,34 +53,33 @@ abstract class MonitoredObjectController extends Controller
     public function showAction()
     {
         $this->setAutorefreshInterval(10);
-        $checkNowForm = new CheckNowCommandForm();
-        $checkNowForm
-            ->setObjects($this->object)
-            ->handleRequest();
-        $this->view->checkNowForm = $checkNowForm;
+        $auth = $this->Auth();
+        if ($auth->hasPermission('monitoring/command/schedule-check')) {
+            $checkNowForm = new CheckNowCommandForm();
+            $checkNowForm
+                ->setObjects($this->object)
+                ->handleRequest();
+            $this->view->checkNowForm = $checkNowForm;
+        }
         if ( ! in_array((int) $this->object->state, array(0, 99))) {
             if ((bool) $this->object->acknowledged) {
-                $removeAckForm = new RemoveAcknowledgementCommandForm();
-                $removeAckForm
-                    ->setObjects($this->object)
-                    ->handleRequest();
-                $this->view->removeAckForm = $removeAckForm;
-            } else {
-                $ackForm = new AcknowledgeProblemCommandForm();
-                $ackForm
-                    ->setObjects($this->object)
-                    ->handleRequest();
-                $this->view->ackForm = $ackForm;
+                if ($auth->hasPermission('monitoring/command/remove-acknowledgement')) {
+                    $removeAckForm = new RemoveAcknowledgementCommandForm();
+                    $removeAckForm
+                        ->setObjects($this->object)
+                        ->handleRequest();
+                    $this->view->removeAckForm = $removeAckForm;
+                }
             }
         }
-        if (count($this->object->comments) > 0) {
+        if (count($this->object->comments) > 0 && $auth->hasPermission('monitoring/command/comment/delete')) {
             $delCommentForm = new DeleteCommentCommandForm();
             $delCommentForm
                 ->setObjects($this->object)
                 ->handleRequest();
             $this->view->delCommentForm = $delCommentForm;
         }
-        if (count($this->object->downtimes > 0)) {
+        if (count($this->object->downtimes > 0) && $auth->hasPermission('monitoring/command/downtime/delete')) {
             $delDowntimeForm = new DeleteDowntimeCommandForm();
             $delDowntimeForm
                 ->setObjects($this->object)
@@ -139,30 +134,20 @@ abstract class MonitoredObjectController extends Controller
     abstract public function scheduleDowntimeAction();
 
     /**
-     * Remove a comment
+     * Delete a comment
      */
-    public function removeCommentAction()
+    public function deleteCommentAction()
     {
-        /*
-         * TODO(el): This is here because monitoring/list/comments has buttons to remove comments. Because of the nature
-         * of an action, the form is accessible via GET which does not make much sense because the form requires
-         * us to populate the ID of the comment which is to be deleted. We may introduce a combo box for choosing
-         * the comment ID on GET or deny GET access.
-         */
+        $this->assertHttpMethod('POST');
         $this->handleCommandForm(new DeleteCommentCommandForm());
     }
 
     /**
-     * Remove a downtime
+     * Delete a downtime
      */
     public function deleteDowntimeAction()
     {
-        /*
-         * TODO(el): This is here because monitoring/list/downtimes has buttons to remove comments. Because of the
-         * nature of an action, the form is accessible via GET which does not make much sense because the form requires
-         * us to populate the ID of the downtime which is to be deleted. We may introduce a combo box for choosing
-         * the downtime ID on GET or deny GET access.
-         */
+        $this->assertHttpMethod('POST');
         $this->handleCommandForm(new DeleteDowntimeCommandForm());
     }
 
@@ -223,8 +208,6 @@ abstract class MonitoredObjectController extends Controller
                 )
             );
         }
-        $tabs
-            ->extend(new OutputFormat())
-            ->extend(new DashboardAction());
+        $tabs->extend(new DashboardAction());
     }
 }
diff --git a/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php b/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php
deleted file mode 100644
index 082a03c5b..000000000
--- a/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-namespace Icinga\Module\Monitoring\Web\Hook;
-
-use Icinga\Web\Hook\TopBarHook;
-use Icinga\Module\Monitoring\DataView\StatusSummary as StatusSummaryView;
-use Icinga\Web\Request;
-use Zend_View;
-
-/**
- * Render status summary into the topbar of icinga
- */
-class TopBar extends TopBarHook
-{
-    /**
-     * Function to generate top bar content
-     *
-     * @param   Request $request
-     *
-     * @return  string
-     */
-    public function getHtml($request)
-    {
-        $hostSummary = StatusSummaryView::fromRequest(
-            $request,
-            array(
-                'hosts_up',
-                'hosts_unreachable_handled',
-                'hosts_unreachable_unhandled',
-                'hosts_down_handled',
-                'hosts_down_unhandled',
-                'hosts_pending'
-            )
-        )->getQuery()->fetchRow();
-
-        $serviceSummary = StatusSummaryView::fromRequest(
-            $request,
-            array(
-                'services_ok',
-                'services_critical_handled',
-                'services_critical_unhandled',
-                'services_warning_handled',
-                'services_warning_unhandled',
-                'services_unknown_handled',
-                'services_unknown_unhandled',
-                'services_pending'
-            )
-        )->getQuery()->fetchRow();
-
-        return $this->getView()->partial(
-            'layout/topbar.phtml',
-            'monitoring',
-            array(
-                'hostSummary'       => $hostSummary,
-                'serviceSummary'    => $serviceSummary
-            )
-        );
-    }
-}
diff --git a/modules/monitoring/run.php b/modules/monitoring/run.php
deleted file mode 100644
index 8f4ee1b67..000000000
--- a/modules/monitoring/run.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-// {{{ICINGA_LICENSE_HEADER}}}
-// {{{ICINGA_LICENSE_HEADER}}}
-
-$this->registerHook(
-    'TopBar',
-    'Icinga\\Module\\Monitoring\\Web\\Hook\\TopBar'
-);
diff --git a/modules/setup/application/clicommands/ConfigCommand.php b/modules/setup/application/clicommands/ConfigCommand.php
index 676572542..e63e770b8 100644
--- a/modules/setup/application/clicommands/ConfigCommand.php
+++ b/modules/setup/application/clicommands/ConfigCommand.php
@@ -12,56 +12,78 @@ use Icinga\Module\Setup\Webserver;
 class ConfigCommand extends Command
 {
     /**
-     * Create the configuration directory
-     *
-     * This command creates the configuration directory for Icinga Web 2. The `group' argument
-     * is mandatory and should be the groupname of the user your web server is running as.
+     * Create Icinga Web 2's configuration directory
      *
      * USAGE:
      *
-     *   icingacli setup config createDirectory <group> [options]
+     *  icingacli setup config directory [options]
      *
      * OPTIONS:
      *
-     *   --mode  The access mode to use. Default is: 2770
-     *   --path  The path to the configuration directory. If omitted the default is used.
+     *  --config=<directory>    Path to Icinga Web 2's configuration files [/etc/icingaweb2]
+     *
+     *  --mode=<mode>           The access mode to use [2770]
+     *
+     *  --group=<group>         Owner group for the configuration directory [icingaweb2]
      *
      * EXAMPLES:
      *
-     *   icingacli setup config createDirectory apache
-     *   icingacli setup config createDirectory apache --mode 2775
-     *   icingacli setup config createDirectory apache --path /some/path
+     *  icingacli setup config directory
+     *
+     *  icingacli setup config directory --mode 2775 --config /opt/icingaweb2/etc
      */
-    public function createDirectoryAction()
+    public function directoryAction()
     {
-        $group = $this->params->getStandalone();
-        if ($group === null) {
-            $this->fail($this->translate('The `group\' argument is mandatory.'));
-            return false;
+        $configDir = trim($this->params->get('config', $this->app->getConfigDir()));
+        if (strlen($configDir) === 0) {
+            $this->fail($this->translate(
+                'The argument --config expects a path to Icinga Web 2\'s configuration files'
+            ));
         }
 
-        $path = $this->params->get('path', $this->app->getConfigDir());
-        if (file_exists($path)) {
-            printf($this->translate("Configuration directory already exists at: %s\n"), $path);
-            return true;
+        $group = trim($this->params->get('group', 'icingaweb2'));
+        if (strlen($group) === 0) {
+            $this->fail($this->translate(
+                'The argument --group expects a owner group for the configuration directory'
+            ));
         }
 
-        $mode = octdec($this->params->get('mode', '2770'));
-        if (false === mkdir($path)) {
-            $this->fail(sprintf($this->translate('Unable to create path: %s'), $path));
-            return false;
+        $mode = trim($this->params->get('mode', '2770'));
+        if (strlen($mode) === 0) {
+            $this->fail($this->translate(
+                'The argument --mode expects an access mode for the configuration directory'
+            ));
         }
 
-        $old = umask(0); // Prevent $mode from being mangled by the system's umask ($old)
-        chmod($path, $mode);
-        umask($old);
-
-        if (chgrp($path, $group) === false) {
-            $this->fail(sprintf($this->translate('Unable to change the group of "%s" to "%s".'), $path, $group));
-            return false;
+        if (! file_exists($configDir) && ! @mkdir($configDir)) {
+            $e = error_get_last();
+            $this->fail(sprintf(
+                $this->translate('Can\'t create configuration directory %s: %s'),
+                $configDir,
+                $e['message']
+            ));
         }
 
-        printf($this->translate("Successfully created configuration directory at: %s\n"), $path);
+        if (! @chmod($configDir, octdec($mode))) {
+            $e = error_get_last();
+            $this->fail(sprintf(
+                $this->translate('Can\'t change the mode of the configuration directory to %s: %s'),
+                $mode,
+                $e['message']
+            ));
+        }
+
+        if (! @chgrp($configDir, $group)) {
+            $e = error_get_last();
+            $this->fail(sprintf(
+                $this->translate('Can\'t change the group of %s to %s: %s'),
+                $configDir,
+                $group,
+                $e['message']
+            ));
+        }
+
+        printf($this->translate('Successfully created configuration directory %s') . PHP_EOL, $configDir);
     }
 
     /**
@@ -73,24 +95,23 @@ class ConfigCommand extends Command
      *
      * OPTIONS:
      *
-     *  --path=<urlpath>                    The URL path to Icinga Web 2 [/icingaweb]
+     *  --path=<urlpath>                    The URL path to Icinga Web 2 [/icingaweb2]
      *
-     *  --root/--document-root=<directory>  The directory from which the webserver will serve files [./public]
+     *  --root/--document-root=<directory>  The directory from which the webserver will serve files [/path/to/icingaweb2/public]
      *
-     *  --config=<directory>                Path to Icinga Web 2's configuration files [/etc/icingaweb]
+     *  --config=<directory>                Path to Icinga Web 2's configuration files [/etc/icingaweb2]
      *
      *  --file=<filename>                   Write configuration to file [stdout]
      *
-     *
      * EXAMPLES:
      *
-     * icingacli setup config webserver apache
+     *  icingacli setup config webserver apache
      *
-     * icingacli setup config webserver apache --path /icingaweb --document-root /usr/share/icingaweb/public --config=/etc/icingaweb
+     *  icingacli setup config webserver apache --path /icingaweb2 --document-root /usr/share/icingaweb2/public --config=/etc/icingaweb2
      *
-     * icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb.conf
+     *  icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb2.conf
      *
-     * icingacli setup config webserver nginx
+     *  icingacli setup config webserver nginx
      */
     public function webserverAction()
     {
@@ -102,18 +123,20 @@ class ConfigCommand extends Command
         } catch (ProgrammingError $e) {
             $this->fail($this->translate('Unknown type') . ': ' . $type);
         }
-        $urlPath = $this->params->get('path', $webserver->getUrlPath());
-        if (! is_string($urlPath) || strlen(trim($urlPath)) === 0) {
+        $urlPath = trim($this->params->get('path', $webserver->getUrlPath()));
+        if (strlen($urlPath) === 0) {
             $this->fail($this->translate('The argument --path expects a URL path'));
         }
-        $documentRoot = $this->params->get('root', $this->params->get('document-root', $webserver->getDocumentRoot()));
-        if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) {
+        $documentRoot = trim(
+            $this->params->get('root', $this->params->get('document-root', $webserver->getDocumentRoot()))
+        );
+        if (strlen($documentRoot) === 0) {
             $this->fail($this->translate(
                 'The argument --root/--document-root expects a directory from which the webserver will serve files'
             ));
         }
-        $configDir = $this->params->get('config', $webserver->getConfigDir());
-        if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) {
+        $configDir = trim($this->params->get('config', $webserver->getConfigDir()));
+        if (strlen($configDir) === 0) {
             $this->fail($this->translate(
                 'The argument --config expects a path to Icinga Web 2\'s configuration files'
             ));
diff --git a/modules/setup/application/clicommands/TokenCommand.php b/modules/setup/application/clicommands/TokenCommand.php
index ff0229cfe..6f6e2b08e 100644
--- a/modules/setup/application/clicommands/TokenCommand.php
+++ b/modules/setup/application/clicommands/TokenCommand.php
@@ -22,11 +22,22 @@ class TokenCommand extends Command
      *
      * USAGE:
      *
-     *   icingacli setup token show
+     *   icingacli setup token show [options]
+     *
+     * OPTIONS:
+     *
+     *  --config=<directory>    Path to Icinga Web 2's configuration files [/etc/icingaweb2]
      */
     public function showAction()
     {
-        $token = file_get_contents($this->app->getConfigDir() . '/setup.token');
+        $configDir = $this->params->get('config', $this->app->getConfigDir());
+        if (! is_string($configDir) || strlen(trim($configDir)) === 0) {
+            $this->fail($this->translate(
+                'The argument --config expects a path to Icinga Web 2\'s configuration files'
+            ));
+        }
+
+        $token = file_get_contents($configDir . '/setup.token');
         if (! $token) {
             $this->fail(
                 $this->translate('Nothing to show. Please create a new setup token using the generateToken action.')
@@ -43,24 +54,35 @@ class TokenCommand extends Command
      *
      * USAGE:
      *
-     *   icingacli setup token create
+     *   icingacli setup token create [options]
+     *
+     * OPTIONS:
+     *
+     *  --config=<directory>    Path to Icinga Web 2's configuration files [/etc/icingaweb2]
      */
     public function createAction()
     {
+        $configDir = $this->params->get('config', $this->app->getConfigDir());
+        if (! is_string($configDir) || strlen(trim($configDir)) === 0) {
+            $this->fail($this->translate(
+                'The argument --config expects a path to Icinga Web 2\'s configuration files'
+            ));
+        }
+
+        $file = $configDir . '/setup.token';
+
         if (function_exists('openssl_random_pseudo_bytes')) {
             $token = bin2hex(openssl_random_pseudo_bytes(8));
         } else {
             $token = substr(md5(mt_rand()), 16);
         }
 
-        $filepath = $this->app->getConfigDir() . '/setup.token';
-
-        if (false === file_put_contents($filepath, $token)) {
-            $this->fail(sprintf($this->translate('Cannot write setup token "%s" to disk.'), $filepath));
+        if (false === file_put_contents($file, $token)) {
+            $this->fail(sprintf($this->translate('Cannot write setup token "%s" to disk.'), $file));
         }
 
-        if (false === chmod($filepath, 0660)) {
-            $this->fail(sprintf($this->translate('Cannot change access mode of "%s" to %o.'), $filepath, 0660));
+        if (! chmod($file, 0660)) {
+            $this->fail(sprintf($this->translate('Cannot change access mode of "%s" to %o.'), $file, 0660));
         }
 
         printf($this->translate("The newly generated setup token is: %s\n"), $token);
diff --git a/modules/setup/application/forms/AdminAccountPage.php b/modules/setup/application/forms/AdminAccountPage.php
index 6ef791d4e..3b2e6ec9f 100644
--- a/modules/setup/application/forms/AdminAccountPage.php
+++ b/modules/setup/application/forms/AdminAccountPage.php
@@ -74,16 +74,15 @@ class AdminAccountPage extends Form
         $choices = array();
 
         if ($this->backendConfig['backend'] !== 'db') {
-            $choices['by_name'] = mt('setup', 'By Name', 'setup.admin');
+            $choices['by_name'] = $this->translate('By Name', 'setup.admin');
             $this->addElement(
                 'text',
                 'by_name',
                 array(
                     'required'      => isset($formData['user_type']) && $formData['user_type'] === 'by_name',
                     'value'         => $this->getUsername(),
-                    'label'         => mt('setup', 'Username'),
-                    'description'   => mt(
-                        'setup',
+                    'label'         => $this->translate('Username'),
+                    'description'   => $this->translate(
                         'Define the initial administrative account by providing a username that reflects'
                         . ' a user created later or one that is authenticated using external mechanisms'
                     )
@@ -94,21 +93,20 @@ class AdminAccountPage extends Form
         if ($this->backendConfig['backend'] === 'db' || $this->backendConfig['backend'] === 'ldap') {
             $users = $this->fetchUsers();
             if (false === empty($users)) {
-                $choices['existing_user'] = mt('setup', 'Existing User');
+                $choices['existing_user'] = $this->translate('Existing User');
                 $this->addElement(
                     'select',
                     'existing_user',
                     array(
                         'required'      => isset($formData['user_type']) && $formData['user_type'] === 'existing_user',
-                        'label'         => mt('setup', 'Username'),
+                        'label'         => $this->translate('Username'),
                         'description'   => sprintf(
-                            mt(
-                                'setup',
+                            $this->translate(
                                 'Choose a user reported by the %s backend as the initial administrative account',
                                 'setup.admin'
                             ),
                             $this->backendConfig['backend'] === 'db'
-                                ? mt('setup', 'database', 'setup.admin.authbackend')
+                                ? $this->translate('database', 'setup.admin.authbackend')
                                 : 'LDAP'
                         ),
                         'multiOptions'  => array_combine($users, $users)
@@ -118,16 +116,15 @@ class AdminAccountPage extends Form
         }
 
         if ($this->backendConfig['backend'] === 'db') {
-            $choices['new_user'] = mt('setup', 'New User');
+            $choices['new_user'] = $this->translate('New User');
             $required = isset($formData['user_type']) && $formData['user_type'] === 'new_user';
             $this->addElement(
                 'text',
                 'new_user',
                 array(
                     'required'      => $required,
-                    'label'         => mt('setup', 'Username'),
-                    'description'   => mt(
-                        'setup',
+                    'label'         => $this->translate('Username'),
+                    'description'   => $this->translate(
                         'Enter the username to be used when creating an initial administrative account'
                     )
                 )
@@ -137,8 +134,8 @@ class AdminAccountPage extends Form
                 'new_user_password',
                 array(
                     'required'      => $required,
-                    'label'         => mt('setup', 'Password'),
-                    'description'   => mt('setup', 'Enter the password to assign to the newly created account')
+                    'label'         => $this->translate('Password'),
+                    'description'   => $this->translate('Enter the password to assign to the newly created account')
                 )
             );
             $this->addElement(
@@ -146,8 +143,8 @@ class AdminAccountPage extends Form
                 'new_user_2ndpass',
                 array(
                     'required'      => $required,
-                    'label'         => mt('setup', 'Repeat password'),
-                    'description'   => mt('setup', 'Please repeat the password given above to avoid typing errors'),
+                    'label'         => $this->translate('Repeat password'),
+                    'description'   => $this->translate('Please repeat the password given above to avoid typing errors'),
                     'validators'    => array(
                         array('identical', false, array('new_user_password'))
                     )
@@ -179,7 +176,7 @@ class AdminAccountPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Administration', 'setup.page.title'),
+                'value'         => $this->translate('Administration', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -215,7 +212,7 @@ class AdminAccountPage extends Form
         }
 
         if ($data['user_type'] === 'new_user' && array_search($data['new_user'], $this->fetchUsers()) !== false) {
-            $this->getElement('new_user')->addError(mt('setup', 'Username already exists.'));
+            $this->getElement('new_user')->addError($this->translate('Username already exists.'));
             return false;
         }
 
diff --git a/modules/setup/application/forms/AuthBackendPage.php b/modules/setup/application/forms/AuthBackendPage.php
index fac2a7bbd..b123b5906 100644
--- a/modules/setup/application/forms/AuthBackendPage.php
+++ b/modules/setup/application/forms/AuthBackendPage.php
@@ -7,7 +7,7 @@ namespace Icinga\Module\Setup\Forms;
 use Icinga\Web\Form;
 use Icinga\Forms\Config\Authentication\DbBackendForm;
 use Icinga\Forms\Config\Authentication\LdapBackendForm;
-use Icinga\Forms\Config\Authentication\AutologinBackendForm;
+use Icinga\Forms\Config\Authentication\ExternalBackendForm;
 use Icinga\Data\ConfigObject;
 
 /**
@@ -62,7 +62,7 @@ class AuthBackendPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Authentication Backend', 'setup.page.title'),
+                'value'         => $this->translate('Authentication Backend', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -71,20 +71,17 @@ class AuthBackendPage extends Form
         );
 
         if ($this->config['type'] === 'db') {
-            $note = mt(
-                'setup',
+            $note = $this->translate(
                 'As you\'ve chosen to use a database for authentication all you need '
                 . 'to do now is defining a name for your first authentication backend.'
             );
         } elseif ($this->config['type'] === 'ldap') {
-            $note = mt(
-                'setup',
+            $note = $this->translate(
                 'Before you are able to authenticate using the LDAP connection defined earlier you need to'
                 . ' provide some more information so that Icinga Web 2 is able to locate account details.'
             );
-        } else { // if ($this->config['type'] === 'autologin'
-            $note = mt(
-                'setup',
+        } else { // if ($this->config['type'] === 'external'
+            $note = $this->translate(
                 'You\'ve chosen to authenticate using a web server\'s mechanism so it may be necessary'
                 . ' to adjust usernames before any permissions, restrictions, etc. are being applied.'
             );
@@ -106,13 +103,13 @@ class AuthBackendPage extends Form
         } elseif ($this->config['type'] === 'ldap') {
             $backendForm = new LdapBackendForm();
             $backendForm->createElements($formData)->removeElement('resource');
-        } else { // $this->config['type'] === 'autologin'
-            $backendForm = new AutologinBackendForm();
+        } else { // $this->config['type'] === 'external'
+            $backendForm = new ExternalBackendForm();
             $backendForm->createElements($formData);
         }
 
         $this->addElements($backendForm->getElements());
-        $this->getElement('name')->setValue('icingaweb');
+        $this->getElement('name')->setValue('icingaweb2');
     }
 
     /**
@@ -150,8 +147,8 @@ class AuthBackendPage extends Form
                 'order'         => 2,
                 'ignore'        => true,
                 'required'      => true,
-                'label'         => mt('setup', 'Skip Validation'),
-                'description'   => mt('setup', 'Check this to not to validate authentication using this backend')
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate('Check this to not to validate authentication using this backend')
             )
         );
     }
diff --git a/modules/setup/application/forms/AuthenticationPage.php b/modules/setup/application/forms/AuthenticationPage.php
index 2a579e670..f51ef946a 100644
--- a/modules/setup/application/forms/AuthenticationPage.php
+++ b/modules/setup/application/forms/AuthenticationPage.php
@@ -29,19 +29,40 @@ class AuthenticationPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Authentication', 'setup.page.title'),
+                'value'         => $this->translate('Authentication', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
                 )
             )
         );
+
+        if (isset($formData['type']) && $formData['type'] === 'external' && !isset($_SERVER['REMOTE_USER'])) {
+            $this->addElement(
+                'note',
+                'external_note',
+                array(
+                    'value'         => $this->translate(
+                        'You\'re currently not authenticated using any of the web server\'s authentication '
+                        . 'mechanisms. Make sure you\'ll configure such, otherwise you\'ll not be able to '
+                        . 'log into Icinga Web 2.'
+                    ),
+                    'decorators'    => array(
+                        'ViewHelper',
+                        array(
+                            'HtmlTag',
+                            array('tag' => 'p', 'class' => 'icon-info info-box')
+                        )
+                    )
+                )
+            );
+        }
+
         $this->addElement(
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'Please choose how you want to authenticate when accessing Icinga Web 2.'
                     . ' Configuring backend specific details follows in a later step.'
                 )
@@ -50,20 +71,21 @@ class AuthenticationPage extends Form
 
         $backendTypes = array();
         if (Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) {
-            $backendTypes['db'] = t('Database');
+            $backendTypes['db'] = $this->translate('Database');
         }
         if (Platform::extensionLoaded('ldap')) {
             $backendTypes['ldap'] = 'LDAP';
         }
-        $backendTypes['autologin'] = t('Autologin');
+        $backendTypes['external'] = $this->translate('External');
 
         $this->addElement(
             'select',
             'type',
             array(
                 'required'      => true,
-                'label'         => mt('setup', 'Authentication Type'),
-                'description'   => mt('setup', 'The type of authentication to use when accessing Icinga Web 2'),
+                'autosubmit'    => true,
+                'label'         => $this->translate('Authentication Type'),
+                'description'   => $this->translate('The type of authentication to use when accessing Icinga Web 2'),
                 'multiOptions'  => $backendTypes
             )
         );
diff --git a/modules/setup/application/forms/DatabaseCreationPage.php b/modules/setup/application/forms/DatabaseCreationPage.php
index ec4a77ee1..be2974a52 100644
--- a/modules/setup/application/forms/DatabaseCreationPage.php
+++ b/modules/setup/application/forms/DatabaseCreationPage.php
@@ -90,7 +90,7 @@ class DatabaseCreationPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Database Setup', 'setup.page.title'),
+                'value'         => $this->translate('Database Setup', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -101,8 +101,7 @@ class DatabaseCreationPage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'It seems that either the database you defined earlier does not yet exist and cannot be created'
                     . ' using the provided access credentials or the database does not have the required schema to '
                     . 'be operated by Icinga Web 2. Please provide appropriate access credentials to solve this.'
@@ -116,16 +115,16 @@ class DatabaseCreationPage extends Form
             'username',
             array(
                 'required'      => false === $skipValidation,
-                'label'         => mt('setup', 'Username'),
-                'description'   => mt('setup', 'A user which is able to create databases and/or touch the database schema')
+                'label'         => $this->translate('Username'),
+                'description'   => $this->translate('A user which is able to create databases and/or touch the database schema')
             )
         );
         $this->addElement(
             'password',
             'password',
             array(
-                'label'         => mt('setup', 'Password'),
-                'description'   => mt('setup', 'The password for the database user defined above')
+                'label'         => $this->translate('Password'),
+                'description'   => $this->translate('The password for the database user defined above')
             )
         );
 
@@ -182,7 +181,7 @@ class DatabaseCreationPage extends Form
         // form need to be granted to create databases, users...
         if (false === $db->checkPrivileges($this->databaseSetupPrivileges)) {
             $this->addError(
-                mt('setup', 'The provided credentials cannot be used to create the database and/or the user.')
+                $this->translate('The provided credentials cannot be used to create the database and/or the user.')
             );
             $this->addSkipValidationCheckbox();
             return false;
@@ -191,8 +190,7 @@ class DatabaseCreationPage extends Form
         // ...and to grant all required usage privileges to others
         if (false === $db->isGrantable($this->databaseUsagePrivileges)) {
             $this->addError(sprintf(
-                mt(
-                    'setup',
+                $this->translate(
                     'The provided credentials cannot be used to grant all required privileges to the login "%s".'
                 ),
                 $this->config['username']
@@ -215,9 +213,8 @@ class DatabaseCreationPage extends Form
             array(
                 'order'         => 2,
                 'required'      => true,
-                'label'         => mt('setup', 'Skip Validation'),
-                'description'   => mt(
-                    'setup',
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate(
                     'Check this to not to validate the ability to login and required privileges'
                 )
             )
diff --git a/modules/setup/application/forms/DbResourcePage.php b/modules/setup/application/forms/DbResourcePage.php
index 4a6535324..1901d8ca9 100644
--- a/modules/setup/application/forms/DbResourcePage.php
+++ b/modules/setup/application/forms/DbResourcePage.php
@@ -39,7 +39,7 @@ class DbResourcePage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Database Resource', 'setup.page.title'),
+                'value'         => $this->translate('Database Resource', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -50,8 +50,7 @@ class DbResourcePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'Now please configure your database resource. Note that the database itself does not need to'
                     . ' exist at this time as it is going to be created once the wizard is about to be finished.'
                 )
@@ -121,8 +120,10 @@ class DbResourcePage extends Form
             'skip_validation',
             array(
                 'required'      => true,
-                'label'         => mt('setup', 'Skip Validation'),
-                'description'   => mt('setup', 'Check this to not to validate connectivity with the given database server')
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate(
+                    'Check this to not to validate connectivity with the given database server'
+                )
             )
         );
     }
diff --git a/modules/setup/application/forms/GeneralConfigPage.php b/modules/setup/application/forms/GeneralConfigPage.php
index 309c1784d..e0a9d0fab 100644
--- a/modules/setup/application/forms/GeneralConfigPage.php
+++ b/modules/setup/application/forms/GeneralConfigPage.php
@@ -29,7 +29,7 @@ class GeneralConfigPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Application Configuration', 'setup.page.title'),
+                'value'         => $this->translate('Application Configuration', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -40,8 +40,7 @@ class GeneralConfigPage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'Now please adjust all application and logging related configuration options to fit your needs.'
                 )
             )
diff --git a/modules/setup/application/forms/LdapDiscoveryConfirmPage.php b/modules/setup/application/forms/LdapDiscoveryConfirmPage.php
index f76cbee07..66fd39001 100644
--- a/modules/setup/application/forms/LdapDiscoveryConfirmPage.php
+++ b/modules/setup/application/forms/LdapDiscoveryConfirmPage.php
@@ -82,7 +82,7 @@ EOT;
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'LDAP Discovery Results', 'setup.page.title'),
+                'value'         => $this->translate('LDAP Discovery Results', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -94,7 +94,7 @@ EOT;
             'description',
             array(
                 'value' => sprintf(
-                    mt('setup', 'The following directory service has been found on domain "%s":'),
+                    $this->translate('The following directory service has been found on domain "%s":'),
                     $this->config['domain']
                 )
             )
@@ -119,7 +119,7 @@ EOT;
             'confirm',
             array(
                 'value' => '1',
-                'label' => mt('setup', 'Use this configuration?')
+                'label' => $this->translate('Use this configuration?')
             )
         );
     }
diff --git a/modules/setup/application/forms/LdapDiscoveryPage.php b/modules/setup/application/forms/LdapDiscoveryPage.php
index 8c61eb379..26b43803b 100644
--- a/modules/setup/application/forms/LdapDiscoveryPage.php
+++ b/modules/setup/application/forms/LdapDiscoveryPage.php
@@ -36,7 +36,7 @@ class LdapDiscoveryPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'LDAP Discovery', 'setup.page.title'),
+                'value'         => $this->translate('LDAP Discovery', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -47,8 +47,7 @@ class LdapDiscoveryPage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'You can use this page to discover LDAP or ActiveDirectory servers ' .
                     ' for authentication. If you don\' want to execute a discovery, just skip this step.'
                 )
@@ -66,8 +65,8 @@ class LdapDiscoveryPage extends Form
             'skip_validation',
             array(
                 'required'      => true,
-                'label'         => mt('setup', 'Skip'),
-                'description'   => mt('setup', 'Do not discover LDAP servers and enter all settings manually.')
+                'label'         => $this->translate('Skip'),
+                'description'   => $this->translate('Do not discover LDAP servers and enter all settings manually.')
             )
         );
     }
@@ -94,7 +93,9 @@ class LdapDiscoveryPage extends Form
                 return true;
             }
         }
-        $this->addError(sprintf(t('Could not find any LDAP servers on the domain "%s".'), $data['domain']));
+        $this->addError(
+            sprintf($this->translate('Could not find any LDAP servers on the domain "%s".'), $data['domain'])
+        );
         return false;
     }
 
diff --git a/modules/setup/application/forms/LdapResourcePage.php b/modules/setup/application/forms/LdapResourcePage.php
index 49bed69c3..f003a7370 100644
--- a/modules/setup/application/forms/LdapResourcePage.php
+++ b/modules/setup/application/forms/LdapResourcePage.php
@@ -37,7 +37,7 @@ class LdapResourcePage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'LDAP Resource', 'setup.page.title'),
+                'value'         => $this->translate('LDAP Resource', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -48,8 +48,7 @@ class LdapResourcePage extends Form
             'note',
             'description',
             array(
-                'value' => mt(
-                    'setup',
+                'value' => $this->translate(
                     'Now please configure your AD/LDAP resource. This will later '
                     . 'be used to authenticate users logging in to Icinga Web 2.'
                 )
@@ -107,9 +106,8 @@ class LdapResourcePage extends Form
             'skip_validation',
             array(
                 'required'      => true,
-                'label'         => mt('setup', 'Skip Validation'),
-                'description'   => mt(
-                    'setup',
+                'label'         => $this->translate('Skip Validation'),
+                'description'   => $this->translate(
                     'Check this to not to validate connectivity with the given directory service'
                 )
             )
diff --git a/modules/setup/application/forms/ModulePage.php b/modules/setup/application/forms/ModulePage.php
index 5e8927dbc..ef765c0e7 100644
--- a/modules/setup/application/forms/ModulePage.php
+++ b/modules/setup/application/forms/ModulePage.php
@@ -4,22 +4,13 @@
 
 namespace Icinga\Module\Setup\Forms;
 
-use InvalidArgumentException;
 use Icinga\Application\Icinga;
 use Icinga\Web\Form;
-use Icinga\Web\Session;
-use Icinga\Web\Request;
 
 class ModulePage extends Form
 {
-    protected $session;
-
-    protected $wizards;
-
     protected $modules;
 
-    protected $pageData;
-
     protected $modulePaths;
 
     /**
@@ -29,7 +20,6 @@ class ModulePage extends Form
     {
         $this->setName('setup_modules');
         $this->setViewScript('form/setup-modules.phtml');
-        $this->session = Session::getSession()->getNamespace(get_class($this));
 
         $this->modulePaths = array();
         if (($appModulePath = realpath(Icinga::app()->getApplicationDir() . '/../modules')) !== false) {
@@ -37,84 +27,24 @@ class ModulePage extends Form
         }
     }
 
-    public function setPageData(array $pageData)
+    public function createElements(array $formData)
     {
-        $this->pageData = $pageData;
-        return $this;
-    }
-
-    public function handleRequest(Request $request = null)
-    {
-        $isPost = strtolower($request->getMethod()) === 'post';
-        if ($isPost && $this->wasSent($request->getPost())) {
-            if (($newModule = $request->getPost('module')) !== null) {
-                $this->setCurrentModule($newModule);
-                $this->getResponse()->redirectAndExit($this->getRedirectUrl());
-            } else {
-                // The user submitted this form but with the parent wizard's navigation
-                // buttons so it's now up to the parent wizard to handle the request..
-            }
-        } else {
-            $wizard = $this->getCurrentWizard();
-            $wizardPage = $wizard->getCurrentPage();
-
-            $wizard->handleRequest($request);
-            if ($isPost && $wizard->isFinished() && $wizardPage->wasSent($request->getPost())) {
-                $wizards = $this->getWizards();
-
-                $newModule = null;
-                foreach ($wizards as $moduleName => $moduleWizard) {
-                    if (false === $moduleWizard->isFinished()) {
-                        $newModule = $moduleName;
-                    }
-                }
-
-                if ($newModule === null) {
-                    // In case all module wizards were completed just pick the first one again
-                    reset($wizards);
-                    $newModule = key($wizards);
-                }
-
-                $this->setCurrentModule($newModule);
-            }
+        foreach ($this->getModules() as $module) {
+            $this->addElement(
+                'checkbox',
+                $module->getName(),
+                array(
+                    'required'      => true,
+                    'description'   => $module->getDescription(),
+                    'label'         => ucfirst($module->getName()),
+                    'value'         => $module->getName() === 'monitoring' ? 1 : 0,
+                    'decorators'    => array('ViewHelper')
+                )
+            );
         }
     }
 
-    public function clearSession()
-    {
-        $this->session->clear();
-        foreach ($this->getWizards() as $wizard) {
-            $wizard->clearSession();
-        }
-    }
-
-    public function setCurrentModule($moduleName)
-    {
-        if (false === array_key_exists($moduleName, $this->getWizards())) {
-            throw new InvalidArgumentException(sprintf('Module "%s" does not provide a setup wizard', $moduleName));
-        }
-
-        $this->session->currentModule = $moduleName;
-    }
-
-    public function getCurrentModule()
-    {
-        $moduleName = $this->session->get('currentModule');
-        if ($moduleName === null) {
-            $moduleName = key($this->getWizards());
-            $this->setCurrentModule($moduleName);
-        }
-
-        return $moduleName;
-    }
-
-    public function getCurrentWizard()
-    {
-        $wizards = $this->getWizards();
-        return $wizards[$this->getCurrentModule()];
-    }
-
-    public function getModules()
+    protected function getModules()
     {
         if ($this->modules !== null) {
             return $this->modules;
@@ -125,37 +55,39 @@ class ModulePage extends Form
         $moduleManager = Icinga::app()->getModuleManager();
         $moduleManager->detectInstalledModules($this->modulePaths);
         foreach ($moduleManager->listInstalledModules() as $moduleName) {
-            $this->modules[] = $moduleManager->loadModule($moduleName)->getModule($moduleName);
+            if ($moduleName !== 'setup') {
+                $this->modules[$moduleName] = $moduleManager->loadModule($moduleName)->getModule($moduleName);
+            }
         }
 
         return $this->modules;
     }
 
-    public function getWizards()
+    public function getCheckedModules()
     {
-        if ($this->wizards !== null) {
-            return $this->wizards;
-        } else {
-            $this->wizards = array();
-        }
+        $modules = $this->getModules();
 
-        foreach ($this->getModules() as $module) {
-            if ($module->providesSetupWizard()) {
-                $this->wizards[$module->getName()] = $module->getSetupWizard();
+        $checked = array();
+        foreach ($this->getElements() as $name => $element) {
+            if (array_key_exists($name, $modules) && $element->isChecked()) {
+                $checked[$name] = $modules[$name];
             }
         }
 
-        $this->mergePageData($this->wizards);
-        return $this->wizards;
+        return $checked;
     }
 
-    protected function mergePageData(array $wizards)
+    public function getModuleWizards()
     {
-        foreach ($wizards as $wizard) {
-            $wizardPageData = & $wizard->getPageData();
-            foreach ($this->pageData as $pageName => $pageData) {
-                $wizardPageData[$pageName] = $pageData;
+        $checked = $this->getCheckedModules();
+
+        $wizards = array();
+        foreach ($checked as $name => $module) {
+            if ($module->providesSetupWizard()) {
+                $wizards[$name] = $module->getSetupWizard();
             }
         }
+
+        return $wizards;
     }
 }
diff --git a/modules/setup/application/forms/PreferencesPage.php b/modules/setup/application/forms/PreferencesPage.php
index 26fd048e1..01b3296f4 100644
--- a/modules/setup/application/forms/PreferencesPage.php
+++ b/modules/setup/application/forms/PreferencesPage.php
@@ -27,11 +27,10 @@ class PreferencesPage extends Form
      */
     public function showDatabaseNote()
     {
-        $this->getElement('type')
+        $this->getElement('store')
             ->setValue('db')
             ->setDescription(
-                mt(
-                    'setup',
+                $this->translate(
                     'Note that choosing "Database" causes Icinga Web 2 to use the same database as for authentication.'
                 )
             );
@@ -47,7 +46,7 @@ class PreferencesPage extends Form
             'note',
             'title',
             array(
-                'value'         => mt('setup', 'Preferences', 'setup.page.title'),
+                'value'         => $this->translate('Preferences', 'setup.page.title'),
                 'decorators'    => array(
                     'ViewHelper',
                     array('HtmlTag', array('tag' => 'h2'))
@@ -58,23 +57,23 @@ class PreferencesPage extends Form
             'note',
             'description',
             array(
-                'value' => mt('setup', 'Please choose how Icinga Web 2 should store user preferences.')
+                'value' => $this->translate('Please choose how Icinga Web 2 should store user preferences.')
             )
         );
 
         $storageTypes = array();
-        $storageTypes['ini'] = t('File System (INI Files)');
+        $storageTypes['ini'] = $this->translate('File System (INI Files)');
         if (Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) {
-            $storageTypes['db'] = t('Database');
+            $storageTypes['db'] = $this->translate('Database');
         }
-        $storageTypes['null'] = t('Don\'t Store Preferences');
+        $storageTypes['none'] = $this->translate('Don\'t Store Preferences');
 
         $this->addElement(
             'select',
-            'type',
+            'store',
             array(
                 'required'      => true,
-                'label'         => t('User Preference Storage Type'),
+                'label'         => $this->translate('User Preference Storage Type'),
                 'multiOptions'  => $storageTypes
             )
         );
diff --git a/modules/setup/application/forms/SummaryPage.php b/modules/setup/application/forms/SummaryPage.php
index 14ad93c56..9b42ec9d8 100644
--- a/modules/setup/application/forms/SummaryPage.php
+++ b/modules/setup/application/forms/SummaryPage.php
@@ -4,6 +4,7 @@
 
 namespace Icinga\Module\Setup\Forms;
 
+use LogicException;
 use Icinga\Web\Form;
 
 /**
@@ -30,7 +31,12 @@ class SummaryPage extends Form
      */
     public function init()
     {
-        $this->setName('setup_summary');
+        if ($this->getName() === $this->filterName(get_class($this))) {
+            throw new LogicException(
+                'When utilizing ' . get_class($this) . ' it is required to set a unique name by using the form options'
+            );
+        }
+
         $this->setViewScript('form/setup-summary.phtml');
     }
 
diff --git a/modules/setup/application/forms/WelcomePage.php b/modules/setup/application/forms/WelcomePage.php
index 5da607683..66340ff25 100644
--- a/modules/setup/application/forms/WelcomePage.php
+++ b/modules/setup/application/forms/WelcomePage.php
@@ -32,9 +32,8 @@ class WelcomePage extends Form
             'token',
             array(
                 'required'      => true,
-                'label'         => mt('setup', 'Setup Token'),
-                'description'   => mt(
-                    'setup',
+                'label'         => $this->translate('Setup Token'),
+                'description'   => $this->translate(
                     'For security reasons we need to ensure that you are permitted to run this wizard.'
                     . ' Please provide a token by following the instructions below.'
                 ),
diff --git a/modules/setup/application/views/scripts/form/setup-modules.phtml b/modules/setup/application/views/scripts/form/setup-modules.phtml
index a352803d7..8d8e9ecf9 100644
--- a/modules/setup/application/views/scripts/form/setup-modules.phtml
+++ b/modules/setup/application/views/scripts/form/setup-modules.phtml
@@ -3,41 +3,18 @@
 use Icinga\Web\Wizard;
 
 ?>
-<div class="module-menu">
-  <p><?= mt('setup', 'The following modules can be set up by using a web-based wizard as well. To setup a module, just complete its wizard and advance to the summary!'); ?></p>
-  <p><?= mt('setup', 'You can freely switch to a module\'s wizard by clicking its name below. The wizard you are currently looking at is written in bold. A small tick is shown on the right once a wizard has been completed.'); ?></p>
-  <form name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
-    <?= $form->getElement($form->getTokenElementName()); ?>
-    <?= $form->getElement($form->getUidElementName()); ?>
-    <ul>
-    <?php $allFinished = true; ?>
-    <?php foreach ($form->getModules() as $module): ?>
-     <?php if ($module->providesSetupWizard()): ?>
-      <li>
-        <?php $isActive = $module->getName() === $form->getCurrentModule(); ?>
-        <button type="submit" name="module" value="<?= $module->getName(); ?>">
-          <?= $isActive ? '<strong>' : '' ?><?= $module->getTitle(); ?><?= $isActive ? '</strong>' : '' ?>
-        </button>
-       <?php if ($module->getSetupWizard()->isFinished()): ?>
-        <?= $this->icon('ok', mt('setup', 'Completed', 'setup.modules.wizard.state')); ?>
-       <?php else: ?>
-        <?php $allFinished = false; ?>
-       <?php endif ?>
-      </li>
-     <?php endif ?>
-    <?php endforeach ?>
-    </ul>
-  </form>
- <?php if ($allFinished): ?>
-  <p class="all-completed"><?= mt('setup', 'You\'ve completed all module wizards!'); ?></p>
- <?php else: ?>
-  <p style="font-size: 80%;"><?= mt('setup', 'Note that you can skip a specific module by just not completing its wizard.'); ?></p>
+<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
+<h2><?= $this->translate('Modules', 'setup.page.title'); ?></h2>
+<p><?= $this->translate('The following modules were found in your Icinga Web 2 installation. To enable and configure a module, just tick it and click "Next".'); ?></p>
+<?php foreach ($form->getElements() as $element): ?>
+ <?php if (! in_array($element->getName(), array(Wizard::BTN_PREV, Wizard::BTN_NEXT, $form->getTokenElementName(), $form->getUidElementName()))): ?>
+  <div class="module">
+    <h3><label for="<?= $element->getId(); ?>"><strong><?= $element->getLabel(); ?></strong></label></h3>
+    <label for="<?= $element->getId(); ?>"><?= $element->getDescription(); ?></label>
+    <?= $element; ?>
+  </div>
  <?php endif ?>
-</div>
-<div class="module-wizard">
-  <?= $form->getCurrentWizard()->getForm()->render(); ?>
-</div>
-<form name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
+<?php endforeach ?>
   <?= $form->getElement($form->getTokenElementName()); ?>
   <?= $form->getElement($form->getUidElementName()); ?>
   <div class="buttons">
diff --git a/modules/setup/application/views/scripts/form/setup-requirements.phtml b/modules/setup/application/views/scripts/form/setup-requirements.phtml
index ca2556b95..47842efde 100644
--- a/modules/setup/application/views/scripts/form/setup-requirements.phtml
+++ b/modules/setup/application/views/scripts/form/setup-requirements.phtml
@@ -11,7 +11,17 @@ $requirements = $form->getRequirements();
 <?php foreach ($requirements as $requirement): ?>
     <tr>
       <td><h2><?= $requirement->title; ?></h2></td>
-      <td style="width: 50%"><?= $requirement->description; ?></td>
+      <td style="width: 50%">
+      <?php if (is_array($requirement->description)): ?>
+        <ul>
+        <?php foreach ($requirement->description as $desc): ?>
+          <li><?= $desc; ?></li>
+        <?php endforeach ?>
+        </ul>
+      <?php else: ?>
+        <?= $requirement->description; ?>
+      <?php endif ?>
+      </td>
       <td class="state <?= $requirement->state === Requirements::STATE_OK ? 'fulfilled' : (
         $requirement->state === Requirements::STATE_OPTIONAL ? 'not-available' : 'missing'
       ); ?>"><?= $requirement->message; ?></td>
@@ -22,7 +32,7 @@ $requirements = $form->getRequirements();
       <td></td>
       <td class="btn-update">
         <div class="buttons">
-          <a title="<?= $this->translate('You may also need to restart the web-server for the changes to take effect!'); ?>" href="<?= $this->href(); ?>" class="button-like"><?= mt('setup', 'Refresh'); ?></a>
+          <a title="<?= $this->translate('You may also need to restart the web-server for the changes to take effect!'); ?>" href="<?= $this->href(); ?>" class="button-like"><?= $this->translate('Refresh'); ?></a>
         </div>
       </td>
     </tr>
diff --git a/modules/setup/application/views/scripts/form/setup-summary.phtml b/modules/setup/application/views/scripts/form/setup-summary.phtml
index 714416833..e8053a897 100644
--- a/modules/setup/application/views/scripts/form/setup-summary.phtml
+++ b/modules/setup/application/views/scripts/form/setup-summary.phtml
@@ -4,9 +4,8 @@ use Icinga\Web\Wizard;
 
 ?>
 <p><?= sprintf(
-  mt(
-    'setup',
-    'The wizard is now complete. You can review the changes supposed to be made before setting up %1$s.'
+  $this->translate(
+    'You\'ve configured %1$s successfully. You can review the changes supposed to be made before setting it up.'
     . ' Make sure that everything is correct (Feel free to navigate back to make any corrections!) so'
     . ' that you can start using %1$s right after it has successfully been set up.'
   ),
@@ -21,7 +20,7 @@ use Icinga\Web\Wizard;
  <?php endif ?>
 <?php endforeach ?>
 </div>
-<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
+<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>" class="summary">
   <?= $form->getElement($form->getTokenElementName()); ?>
   <?= $form->getElement($form->getUidElementName()); ?>
   <div class="buttons">
diff --git a/modules/setup/application/views/scripts/form/setup-welcome.phtml b/modules/setup/application/views/scripts/form/setup-welcome.phtml
index 6c8228541..d4bc1c3d7 100644
--- a/modules/setup/application/views/scripts/form/setup-welcome.phtml
+++ b/modules/setup/application/views/scripts/form/setup-welcome.phtml
@@ -11,16 +11,14 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
 
 ?>
 <div class="welcome-page">
-  <h2><?= mt('setup', 'Welcome to the configuration of Icinga Web 2!') ?></h2>
+  <h2><?= $this->translate('Welcome to the configuration of Icinga Web 2!') ?></h2>
  <?php if (false === file_exists($setupTokenPath) && file_exists(Config::resolvePath('config.ini'))): ?>
-  <p class="restart-warning"><?= mt(
-    'setup',
+  <p class="restart-warning"><?= $this->translate(
     'You\'ve already completed the configuration of Icinga Web 2. Note that most of your configuration'
       . ' files will be overwritten in case you\'ll re-configure Icinga Web 2 using this wizard!'
   ); ?></p>
  <?php else: ?>
-  <p><?= mt(
-    'setup',
+  <p><?= $this->translate(
     'This wizard will guide you through the configuration of Icinga Web 2. Once completed and successfully'
     . ' finished you are able to log in and to explore all the new and stunning features!'
   ); ?></p>
@@ -39,25 +37,26 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');
     </div>
     <div>
       <p><?=
-        mt(
-          'setup',
+        $this->translate(
           'To run this wizard a user needs to authenticate using a token which is usually'
           . ' provided to him by an administrator who\'d followed the instructions below.'
       ); ?></p>
-      <p><?= mt('setup', 'If you\'ve got the IcingaCLI installed you can do the following:'); ?></p>
+      <p><?= $this->translate('In any case, make sure that a group called "icingaweb2" exists:'); ?></p>
       <div class="code">
-        <span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup config createDirectory <?= ($user = Platform::getPhpUser()) !== null ? $user : 'your_webserver_group'; ?><?= $configDir !== '/etc/icingaweb' ? ' --path ' . $configDir : ''; ?>;</span>
+        <span>groupadd icingaweb2;</span>
+      </div>
+      <p><?= $this->translate('If you\'ve got the IcingaCLI installed you can do the following:'); ?></p>
+      <div class="code">
+        <span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup config directory --group icingaweb2<?= $configDir !== '/etc/icingaweb2' ? ' --config ' . $configDir : ''; ?>;</span>
         <span><?= $cliPath ? $cliPath : 'icingacli'; ?> setup token create;</span>
       </div>
-      <p><?= mt('setup', 'In case the IcingaCLI is missing you can create the token manually:'); ?></p>
+      <p><?= $this->translate('In case the IcingaCLI is missing you can create the token manually:'); ?></p>
       <div class="code">
-        <span>su <?= ($user = Platform::getPhpUser()) !== null ? $user : 'your_webserver_group'; ?> && mkdir -m 2770 <?= dirname($setupTokenPath); ?>;</span>
-        <span>head -c 12 /dev/urandom | base64 | tee <?= $setupTokenPath; ?>;</span>
-        <span>chmod 0660 <?= $setupTokenPath; ?>;</span>
+        <span>su <?= ($user = Platform::getPhpUser()) !== null ? $user : 'your_webserver_user'; ?> -c "mkdir -m 2770 <?= dirname($setupTokenPath); ?>; chgrp icingaweb2 <?= dirname($setupTokenPath); ?>; head -c 12 /dev/urandom | base64 | tee <?= $setupTokenPath; ?>; chmod 0660 <?= $setupTokenPath; ?>;";</span>
       </div>
       <p><?= sprintf(
-        mt('setup', 'Please see the %s for an extensive description on how to access and use this wizard.'),
-        '<a href="http://docs.icinga.org/">' . mt('setup', 'Icinga Web 2 documentation') . '</a>' // TODO: Add link to iw2 docs which points to the installation topic
+        $this->translate('Please see the %s for an extensive description on how to access and use this wizard.'),
+        '<a href="http://docs.icinga.org/">' . $this->translate('Icinga Web 2 documentation') . '</a>' // TODO: Add link to iw2 docs which points to the installation topic
       ); ?></p>
     </div>
   </div>
diff --git a/modules/setup/application/views/scripts/index/index.phtml b/modules/setup/application/views/scripts/index/index.phtml
index 9af37be7c..a55cfa198 100644
--- a/modules/setup/application/views/scripts/index/index.phtml
+++ b/modules/setup/application/views/scripts/index/index.phtml
@@ -4,7 +4,7 @@ use Icinga\Web\Notification;
 
 $pages = $wizard->getPages();
 $finished = isset($success);
-$configPages = array_slice($pages, 2, count($pages) - 4, true);
+$configPages = array_slice($pages, 3, count($pages) - 1, true);
 $currentPos = array_search($wizard->getCurrentPage(), $pages, true);
 list($configPagesLeft, $configPagesRight) = array_chunk($configPages, count($configPages) / 2, true);
 
@@ -30,7 +30,7 @@ if ($notifications->hasMessages()) {
     <?= $this->img('img/logo_icinga_big.png'); ?>
     <div class="progress-bar">
       <div class="step" style="width: 10%;">
-        <h1><?= mt('setup', 'Welcome', 'setup.progress'); ?></h1>
+        <h1><?= $this->translate('Welcome', 'setup.progress'); ?></h1>
         <?php $stateClass = $finished || $currentPos > 0 ? 'complete' : (
           $maxProgress > 0 ? 'visited' : 'active'
         ); ?>
@@ -41,30 +41,43 @@ if ($notifications->hasMessages()) {
         </tr></tbody></table>
       </div>
       <div class="step" style="width: 10%;">
-        <h1><?= mt('setup', 'Requirements', 'setup.progress'); ?></h1>
+        <h1><?= $this->translate('Modules', 'setup.progress'); ?></h1>
         <?php $stateClass = $finished || $currentPos > 1 ? ' complete' : (
           $maxProgress > 1 ? ' visited' : (
             $currentPos === 1 ? ' active' : ''
           )
         ); ?>
+        <table><tbody><tr>
+          <td class="left"><div class="line left<?= $stateClass; ?>"></div></td>
+          <td class="middle"><div class="bubble <?= $stateClass; ?>"></div></td>
+          <td class="right"><div class="line right <?= $stateClass; ?>"></div></td>
+        </tr></tbody></table>
+      </div>
+      <div class="step" style="width: 10%;">
+        <h1><?= $this->translate('Requirements', 'setup.progress'); ?></h1>
+        <?php $stateClass = $finished || $currentPos > 2 ? ' complete' : (
+          $maxProgress > 2 ? ' visited' : (
+            $currentPos === 2 ? ' active' : ''
+          )
+        ); ?>
         <table><tbody><tr>
           <td class="left"><div class="line left<?= $stateClass; ?>"></div></td>
           <td class="middle"><div class="bubble<?= $stateClass; ?>"></div></td>
           <td class="right"><div class="line right<?= $stateClass; ?>"></div></td>
         </tr></tbody></table>
       </div>
-      <div class="step" style="width: 50%;">
-        <h1><?= mt('setup', 'Configuration', 'setup.progress'); ?></h1>
+      <div class="step" style="width: 60%;">
+        <h1><?= $this->translate('Configuration', 'setup.progress'); ?></h1>
         <table><tbody><tr>
           <td class="left">
           <?php
             $firstPage = current($configPagesLeft);
             $lastPage = end($configPagesLeft);
-            $lineWidth = round(100 / count($configPagesLeft), 2, PHP_ROUND_HALF_DOWN);
+            $lineWidth = sprintf('%.2F', round(100 / count($configPagesLeft), 2, PHP_ROUND_HALF_DOWN));
           ?>
           <?php foreach ($configPagesLeft as $pos => $page): ?>
             <?php $stateClass = $finished || $pos < $currentPos ? ' complete' : (
-              $pos < $maxProgress ? ' visited' : ($currentPos > 1 ? ' active' : '')
+              $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
             ); ?>
             <?php if ($page === $firstPage): ?>
             <div class="line left<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%; margin-right: 0"></div>
@@ -78,7 +91,7 @@ if ($notifications->hasMessages()) {
           <td class="middle">
             <div class="bubble<?= array_key_exists($currentPos, $configPagesLeft) ? (
               key($configPagesRight) <= $maxProgress ? ' visited' : ' active') : (
-              $finished || $currentPos > 1 ? ' complete' : (
+              $finished || $currentPos > 2 ? ' complete' : (
                 key($configPagesRight) < $maxProgress ? ' visited' : ''
               )
             ); ?>"></div>
@@ -87,11 +100,11 @@ if ($notifications->hasMessages()) {
           <?php
             $firstPage = current($configPagesRight);
             $lastPage = end($configPagesRight);
-            $lineWidth = round(100 / count($configPagesRight), 2, PHP_ROUND_HALF_DOWN);
+            $lineWidth = sprintf('%.2F', round(100 / count($configPagesRight), 2, PHP_ROUND_HALF_DOWN));
           ?>
           <?php foreach ($configPagesRight as $pos => $page): ?>
             <?php $stateClass = $finished || $pos < $currentPos ? ' complete' : (
-              $pos < $maxProgress ? ' visited' : ($currentPos > 1 ? ' active' : '')
+              $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
             ); ?>
             <?php if ($page === $firstPage): ?>
             <div class="line<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%; margin-left: -0.1em;"></div>
@@ -105,27 +118,7 @@ if ($notifications->hasMessages()) {
         </tr></tbody></table>
       </div>
       <div class="step" style="width: 10%;">
-        <h1><?= mt('setup', 'Modules', 'setup.progress'); ?></h1>
-        <?php $stateClass = $finished || $currentPos > count($pages) - 2 ? ' complete' : (
-          $maxProgress > count($pages) - 2 ? ' visited' : ($currentPos === count($pages) - 2 ? ' active' : '')
-        ); ?>
-        <table><tbody><tr>
-          <td class="left"><div class="line left<?= $stateClass; ?>"></div></td>
-          <td class="middle"><div class="bubble<?= $stateClass; ?>"></div></td>
-          <td class="right"><div class="line right<?= $stateClass; ?>"></div></td>
-        </tr></tbody></table>
-      </div>
-      <div class="step" style="width: 10%;">
-        <h1><?= mt('setup', 'Summary', 'setup.progress'); ?></h1>
-        <?php $stateClass = $finished ? ' complete' : ($currentPos === count($pages) - 1 ? ' active' : ''); ?>
-        <table><tbody><tr>
-          <td class="left"><div class="line left<?= $stateClass; ?>"></div></td>
-          <td class="middle"><div class="bubble<?= $stateClass; ?>"></div></td>
-          <td class="right"><div class="line right<?= $stateClass; ?>"></div></td>
-        </tr></tbody></table>
-      </div>
-      <div class="step" style="width: 10%;">
-        <h1><?= mt('setup', 'Finish', 'setup.progress'); ?></h1>
+        <h1><?= $this->translate('Finish', 'setup.progress'); ?></h1>
         <?php $stateClass = $finished ? ' active' : ''; ?>
         <table><tbody><tr>
           <td class="left"><div class="line left<?= $stateClass; ?>"></div></td>
diff --git a/modules/setup/application/views/scripts/index/parts/finish.phtml b/modules/setup/application/views/scripts/index/parts/finish.phtml
index 94217017d..e695d72ce 100644
--- a/modules/setup/application/views/scripts/index/parts/finish.phtml
+++ b/modules/setup/application/views/scripts/index/parts/finish.phtml
@@ -11,16 +11,16 @@
     <?php endif ?>
   <?php endforeach ?>
   <?php if ($success): ?>
-    <p class="success"><?= mt('setup', 'Congratulations! Icinga Web 2 has been successfully set up.'); ?></p>
+    <p class="success"><?= $this->translate('Congratulations! Icinga Web 2 has been successfully set up.'); ?></p>
   <?php else: ?>
-    <p class="failure"><?= mt('setup', 'Sorry! Failed to set up Icinga Web 2 successfully.'); ?></p>
+    <p class="failure"><?= $this->translate('Sorry! Failed to set up Icinga Web 2 successfully.'); ?></p>
   <?php endif ?>
   </div>
   <div class="buttons">
   <?php if ($success): ?>
-    <a href="<?= $this->href('authentication/login'); ?>" class="button-like login"><?= mt('setup', 'Login to Icinga Web 2'); ?></a>
+    <a href="<?= $this->href('authentication/login'); ?>" class="button-like login"><?= $this->translate('Login to Icinga Web 2'); ?></a>
   <?php else: ?>
-    <a href="<?= $this->href(); ?>" class="button-like"><?= mt('setup', 'Back'); ?></a>
+    <a href="<?= $this->href(); ?>" class="button-like"><?= $this->translate('Back'); ?></a>
   <?php endif ?>
   </div>
 </div>
\ No newline at end of file
diff --git a/modules/setup/library/Setup/Requirements.php b/modules/setup/library/Setup/Requirements.php
index 4b3d411cb..ab9e693e5 100644
--- a/modules/setup/library/Setup/Requirements.php
+++ b/modules/setup/library/Setup/Requirements.php
@@ -9,6 +9,9 @@ use IteratorAggregate;
 
 /**
  * Container to store and handle requirements
+ *
+ * TODO: Requirements should be registered as objects with a specific purpose (PhpModRequirement, PhpIniRequirement, ..)
+ *       so that it's not necessary to define unique identifiers which may differ between different modules.
  */
 class Requirements implements IteratorAggregate
 {
@@ -41,12 +44,40 @@ class Requirements implements IteratorAggregate
      *
      * @return  self
      */
-    public function add($requirement)
+    public function add($name, $requirement)
     {
-        $this->requirements[] = $requirement;
+        $this->requirements[$name] = array_key_exists($name, $this->requirements)
+            ? $this->combine($this->requirements[$name], $requirement)
+            : $requirement;
         return $this;
     }
 
+    /**
+     * Combine the two given requirements
+     *
+     * Returns the most important requirement with the description from the other one being added.
+     *
+     * @param   object  $oldRequirement
+     * @param   object  $newRequirement
+     *
+     * @return  object
+     */
+    protected function combine($oldRequirement, $newRequirement)
+    {
+        if ($newRequirement->state === static::STATE_MANDATORY && $oldRequirement->state === static::STATE_OPTIONAL) {
+            $tempRequirement = $oldRequirement;
+            $oldRequirement = $newRequirement;
+            $newRequirement = $tempRequirement;
+        }
+
+        if (! is_array($oldRequirement->description)) {
+            $oldRequirement->description = array($oldRequirement->description);
+        }
+
+        $oldRequirement->description[] = $newRequirement->description;
+        return $oldRequirement;
+    }
+
     /**
      * Return all registered requirements
      *
@@ -70,6 +101,7 @@ class Requirements implements IteratorAggregate
     /**
      * Register an optional requirement
      *
+     * @param   string      $name
      * @param   string      $title
      * @param   string      $description
      * @param   bool        $state
@@ -77,20 +109,24 @@ class Requirements implements IteratorAggregate
      *
      * @return  self
      */
-    public function addOptional($title, $description, $state, $message)
+    public function addOptional($name, $title, $description, $state, $message)
     {
-        $this->add((object) array(
-            'title'         => $title,
-            'message'       => $message,
-            'description'   => $description,
-            'state'         => (bool) $state ? static::STATE_OK : static::STATE_OPTIONAL
-        ));
+        $this->add(
+            $name,
+            (object) array(
+                'title'         => $title,
+                'message'       => $message,
+                'description'   => $description,
+                'state'         => (bool) $state ? static::STATE_OK : static::STATE_OPTIONAL
+            )
+        );
         return $this;
     }
 
     /**
      * Register a mandatory requirement
      *
+     * @param   string      $name
      * @param   string      $title
      * @param   string      $description
      * @param   bool        $state
@@ -98,14 +134,17 @@ class Requirements implements IteratorAggregate
      *
      * @return  self
      */
-    public function addMandatory($title, $description, $state, $message)
+    public function addMandatory($name, $title, $description, $state, $message)
     {
-        $this->add((object) array(
-            'title'         => $title,
-            'message'       => $message,
-            'description'   => $description,
-            'state'         => (bool) $state ? static::STATE_OK : static::STATE_MANDATORY
-        ));
+        $this->add(
+            $name,
+            (object) array(
+                'title'         => $title,
+                'message'       => $message,
+                'description'   => $description,
+                'state'         => (bool) $state ? static::STATE_OK : static::STATE_MANDATORY
+            )
+        );
         return $this;
     }
 
@@ -118,8 +157,8 @@ class Requirements implements IteratorAggregate
      */
     public function merge(Requirements $requirements)
     {
-        foreach ($requirements->getAll() as $requirement) {
-            $this->add($requirement);
+        foreach ($requirements->getAll() as $name => $requirement) {
+            $this->add($name, $requirement);
         }
 
         return $this;
diff --git a/modules/setup/library/Setup/Steps/AuthenticationStep.php b/modules/setup/library/Setup/Steps/AuthenticationStep.php
index a15198c57..ce0b49f58 100644
--- a/modules/setup/library/Setup/Steps/AuthenticationStep.php
+++ b/modules/setup/library/Setup/Steps/AuthenticationStep.php
@@ -139,7 +139,7 @@ class AuthenticationStep extends Step
                 . '<td><strong>' . t('User Name Attribute') . '</strong></td>'
                 . '<td>' . $this->data['backendConfig']['user_name_attribute'] . '</td>'
                 . '</tr>'
-            ) : ($authType === 'autologin' ? (
+            ) : ($authType === 'external' ? (
                 '<tr>'
                 . '<td><strong>' . t('Filter Pattern') . '</strong></td>'
                 . '<td>' . $this->data['backendConfig']['strip_username_regexp'] . '</td>'
diff --git a/modules/setup/library/Setup/Steps/DatabaseStep.php b/modules/setup/library/Setup/Steps/DatabaseStep.php
index c6ec2ef2b..006b6c9ed 100644
--- a/modules/setup/library/Setup/Steps/DatabaseStep.php
+++ b/modules/setup/library/Setup/Steps/DatabaseStep.php
@@ -6,7 +6,6 @@ namespace Icinga\Module\Setup\Steps;
 
 use Exception;
 use PDOException;
-use Icinga\Application\Icinga;
 use Icinga\Module\Setup\Step;
 use Icinga\Module\Setup\Utils\DbTool;
 use Icinga\Module\Setup\Exception\SetupException;
@@ -71,7 +70,7 @@ class DatabaseStep extends Step
             $this->log(mt('setup', 'Database schema already exists...'));
         } else {
             $this->log(mt('setup', 'Creating database schema...'));
-            $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/mysql.schema.sql');
+            $db->import($this->data['schemaPath'] . '/mysql.schema.sql');
         }
 
         if ($db->hasLogin($this->data['resourceConfig']['username'])) {
@@ -122,7 +121,7 @@ class DatabaseStep extends Step
             $this->log(mt('setup', 'Database schema already exists...'));
         } else {
             $this->log(mt('setup', 'Creating database schema...'));
-            $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/pgsql.schema.sql');
+            $db->import($this->data['schemaPath'] . '/pgsql.schema.sql');
         }
 
         if ($db->hasLogin($this->data['resourceConfig']['username'])) {
diff --git a/modules/setup/library/Setup/Steps/GeneralConfigStep.php b/modules/setup/library/Setup/Steps/GeneralConfigStep.php
index ee9e2c581..39c160628 100644
--- a/modules/setup/library/Setup/Steps/GeneralConfigStep.php
+++ b/modules/setup/library/Setup/Steps/GeneralConfigStep.php
@@ -29,7 +29,7 @@ class GeneralConfigStep extends Step
             $config[$section][$property] = $value;
         }
 
-        $config['preferences']['type'] = $this->data['preferencesType'];
+        $config['preferences']['store'] = $this->data['preferencesStore'];
         if (isset($this->data['preferencesResource'])) {
             $config['preferences']['resource'] = $this->data['preferencesResource'];
         }
@@ -58,11 +58,11 @@ class GeneralConfigStep extends Step
         $generalHtml = ''
             . '<ul>'
             . '<li>' . sprintf(
-                $this->data['preferencesType'] === 'ini' ? sprintf(
+                $this->data['preferencesStore'] === 'ini' ? sprintf(
                     t('Preferences will be stored per user account in INI files at: %s'),
                     Config::resolvePath('preferences')
                 ) : (
-                    $this->data['preferencesType'] === 'db' ? t('Preferences will be stored using a database.') : (
+                    $this->data['preferencesStore'] === 'db' ? t('Preferences will be stored using a database.') : (
                         t('Preferences will not be persisted across browser sessions.')
                     )
                 )
diff --git a/modules/setup/library/Setup/Utils/DbTool.php b/modules/setup/library/Setup/Utils/DbTool.php
index a368bfa1a..63184acd0 100644
--- a/modules/setup/library/Setup/Utils/DbTool.php
+++ b/modules/setup/library/Setup/Utils/DbTool.php
@@ -641,7 +641,8 @@ EOD;
             foreach ($mysqlPrivileges as $privilege) {
                 if (false === empty($context) && $this->mysqlGrantContexts[$privilege] & static::TABLE_LEVEL) {
                     $tablePrivileges[] = $privilege;
-                } elseif ($this->mysqlGrantContexts[$privilege] & static::DATABASE_LEVEL) {
+                }
+                if ($this->mysqlGrantContexts[$privilege] & static::DATABASE_LEVEL) {
                     $dbPrivileges[] = $privilege;
                 }
             }
@@ -661,7 +662,11 @@ EOD;
             }
 
             $tablePrivilegesGranted = true;
-            if (false === empty($tablePrivileges)) {
+            if (
+                false === empty($tablePrivileges) && (
+                    !$dbPrivilegesGranted || array_intersect($dbPrivileges, $tablePrivileges) != $tablePrivileges
+                )
+            ) {
                 $tableCondition = 'table_name IN (' . join(',', array_map(array($this, 'quote'), $context)) . ')';
                 $query = $this->query(
                     'SELECT COUNT(*) as matches'
diff --git a/modules/setup/library/Setup/Utils/EnableModuleStep.php b/modules/setup/library/Setup/Utils/EnableModuleStep.php
index 3ca3eebd1..a23e532f2 100644
--- a/modules/setup/library/Setup/Utils/EnableModuleStep.php
+++ b/modules/setup/library/Setup/Utils/EnableModuleStep.php
@@ -12,13 +12,13 @@ class EnableModuleStep extends Step
 {
     protected $modulePaths;
 
-    protected $moduleName;
+    protected $moduleNames;
 
-    protected $error;
+    protected $errors;
 
-    public function __construct($moduleName)
+    public function __construct(array $moduleNames)
     {
-        $this->moduleName = $moduleName;
+        $this->moduleNames = $moduleNames;
 
         $this->modulePaths = array();
         if (($appModulePath = realpath(Icinga::app()->getApplicationDir() . '/../modules')) !== false) {
@@ -28,17 +28,20 @@ class EnableModuleStep extends Step
 
     public function apply()
     {
-        try {
-            $moduleManager = Icinga::app()->getModuleManager();
-            $moduleManager->detectInstalledModules($this->modulePaths);
-            $moduleManager->enableModule($this->moduleName);
-        } catch (Exception $e) {
-            $this->error = $e;
-            return false;
+        $moduleManager = Icinga::app()->getModuleManager();
+        $moduleManager->detectInstalledModules($this->modulePaths);
+
+        $success = true;
+        foreach ($this->moduleNames as $moduleName) {
+            try {
+                $moduleManager->enableModule($moduleName);
+            } catch (Exception $e) {
+                $this->errors[$moduleName] = $e;
+                $success = false;
+            }
         }
 
-        $this->error = false;
-        return true;
+        return $success;
     }
 
     public function getSummary()
@@ -48,12 +51,19 @@ class EnableModuleStep extends Step
 
     public function getReport()
     {
-        if ($this->error === false) {
-            return '<p>' . sprintf(mt('setup', 'Module "%s" has been successfully enabled.'), $this->moduleName) . '</p>';
-        } elseif ($this->error !== null) {
-            $message = mt('setup', 'Module "%s" could not be enabled. An error occured:');
-            return '<p class="error">' . sprintf($message, $this->moduleName) . '</p>'
-                . '<p>' . $this->error->getMessage() . '</p>';
+        $okMessage = mt('setup', 'Module "%s" has been successfully enabled.');
+        $failMessage = mt('setup', 'Module "%s" could not be enabled. An error occured:');
+
+        $report = '';
+        foreach ($this->moduleNames as $moduleName) {
+            if (isset($this->errors[$moduleName])) {
+                $report .= '<p class="error">' . sprintf($failMessage, $moduleName) . '</p>'
+                    . '<p>' . $this->errors[$moduleName]->getMessage() . '</p>';
+            } else {
+                $report .= '<p>' . sprintf($okMessage, $moduleName) . '</p>';
+            }
         }
+
+        return $report;
     }
 }
diff --git a/modules/setup/library/Setup/Utils/MakeDirStep.php b/modules/setup/library/Setup/Utils/MakeDirStep.php
index d15c7db6a..d7813541b 100644
--- a/modules/setup/library/Setup/Utils/MakeDirStep.php
+++ b/modules/setup/library/Setup/Utils/MakeDirStep.php
@@ -16,12 +16,12 @@ class MakeDirStep extends Step
 
     /**
      * @param array $paths
-     * @param int   $dirmode
+     * @param int   $dirmode    Directory mode in octal notation
      */
     public function __construct($paths, $dirmode)
     {
         $this->paths = $paths;
-        $this->dirmode = $dirmode;
+        $this->dirmode = octdec((string) $dirmode);
         $this->errors = array();
     }
 
@@ -35,9 +35,7 @@ class MakeDirStep extends Step
                     $success = false;
                 } else {
                     $this->errors[$path] = null;
-                    $old = umask(0);
                     chmod($path, $this->dirmode);
-                    umask($old);
                 }
             }
         }
diff --git a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php
index 7dc2ea2f9..fa858f531 100644
--- a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php
+++ b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php
@@ -38,10 +38,6 @@ class TokenValidator extends Zend_Validate_Abstract
                 mt('setup', 'Cannot validate token, file "%s" is empty. Please define a token.'),
                 $tokenPath
             ),
-            'TOKEN_FILE_PUBLIC' => sprintf(
-                mt('setup', 'Cannot validate token, file "%s" must only be accessible by the webserver\'s user.'),
-                $tokenPath
-            ),
             'TOKEN_INVALID'     => mt('setup', 'Invalid token supplied.')
         );
     }
@@ -56,12 +52,6 @@ class TokenValidator extends Zend_Validate_Abstract
      */
     public function isValid($value, $context = null)
     {
-        $tokenStats = @stat($this->tokenPath);
-        if (($tokenStats['mode'] & 4) === 4) {
-            $this->_error('TOKEN_FILE_PUBLIC');
-            return false;
-        }
-
         try {
             $file = new File($this->tokenPath);
             $expectedToken = trim($file->fgets());
diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php
index faa123fe8..8ae7344ea 100644
--- a/modules/setup/library/Setup/WebWizard.php
+++ b/modules/setup/library/Setup/WebWizard.php
@@ -9,6 +9,7 @@ use Icinga\Web\Form;
 use Icinga\Web\Wizard;
 use Icinga\Web\Request;
 use Icinga\Application\Config;
+use Icinga\Application\Icinga;
 use Icinga\Application\Platform;
 use Icinga\Module\Setup\Forms\ModulePage;
 use Icinga\Module\Setup\Forms\WelcomePage;
@@ -28,6 +29,7 @@ use Icinga\Module\Setup\Steps\DatabaseStep;
 use Icinga\Module\Setup\Steps\GeneralConfigStep;
 use Icinga\Module\Setup\Steps\ResourceStep;
 use Icinga\Module\Setup\Steps\AuthenticationStep;
+use Icinga\Module\Setup\Utils\EnableModuleStep;
 use Icinga\Module\Setup\Utils\MakeDirStep;
 use Icinga\Module\Setup\Utils\DbTool;
 
@@ -82,6 +84,7 @@ class WebWizard extends Wizard implements SetupWizard
     protected function init()
     {
         $this->addPage(new WelcomePage());
+        $this->addPage(new ModulePage());
         $this->addPage(new RequirementsPage());
         $this->addPage(new AuthenticationPage());
         $this->addPage(new PreferencesPage());
@@ -93,8 +96,14 @@ class WebWizard extends Wizard implements SetupWizard
         $this->addPage(new AdminAccountPage());
         $this->addPage(new GeneralConfigPage());
         $this->addPage(new DatabaseCreationPage());
-        $this->addPage(new ModulePage());
-        $this->addPage(new SummaryPage());
+        $this->addPage(new SummaryPage(array('name' => 'setup_summary')));
+
+        if (($modulePageData = $this->getPageData('setup_modules')) !== null) {
+            $modulePage = $this->getPage('setup_modules')->populate($modulePageData);
+            foreach ($modulePage->getModuleWizards() as $moduleWizard) {
+                $this->addPage($moduleWizard);
+            }
+        }
     }
 
     /**
@@ -166,9 +175,6 @@ class WebWizard extends Wizard implements SetupWizard
                 unset($pageData['setup_admin_account']);
                 unset($pageData['setup_authentication_backend']);
             }
-        } elseif ($page->getName() === 'setup_modules') {
-            $page->setPageData($this->getPageData());
-            $page->handleRequest($request);
         }
     }
 
@@ -182,7 +188,7 @@ class WebWizard extends Wizard implements SetupWizard
         if ($newPage->getName() === 'setup_db_resource') {
             $prefData = $this->getPageData('setup_preferences_type');
             $authData = $this->getPageData('setup_authentication_type');
-            $skip = $prefData['type'] !== 'db' && $authData['type'] !== 'db';
+            $skip = $prefData['store'] !== 'db' && $authData['type'] !== 'db';
         } elseif ($newPage->getname() === 'setup_ldap_discovery') {
             $authData = $this->getPageData('setup_authentication_type');
             $skip = $authData['type'] !== 'ldap';
@@ -221,23 +227,7 @@ class WebWizard extends Wizard implements SetupWizard
             }
         }
 
-        if ($skip) {
-            if ($this->hasPageData($newPage->getName())) {
-                $pageData = & $this->getPageData();
-                unset($pageData[$newPage->getName()]);
-            }
-
-            $pages = $this->getPages();
-            if ($this->getDirection() === static::FORWARD) {
-                $nextPage = $pages[array_search($newPage, $pages, true) + 1];
-                $newPage = $this->getNewPage($nextPage->getName(), $newPage);
-            } else { // $this->getDirection() === static::BACKWARD
-                $previousPage = $pages[array_search($newPage, $pages, true) - 1];
-                $newPage = $this->getNewPage($previousPage->getName(), $newPage);
-            }
-        }
-
-        return $newPage;
+        return $skip ? $this->skipPage($newPage) : $newPage;
     }
 
     /**
@@ -262,7 +252,6 @@ class WebWizard extends Wizard implements SetupWizard
     public function clearSession()
     {
         parent::clearSession();
-        $this->getPage('setup_modules')->clearSession();
 
         $tokenPath = Config::resolvePath('setup.token');
         if (file_exists($tokenPath)) {
@@ -294,7 +283,9 @@ class WebWizard extends Wizard implements SetupWizard
                         : null,
                     'adminPassword'     => isset($pageData['setup_database_creation']['password'])
                         ? $pageData['setup_database_creation']['password']
-                        : null
+                        : null,
+                    'schemaPath'        => Config::module('setup')
+                        ->get('schema', 'path', Icinga::app()->getBaseDir('etc' . DIRECTORY_SEPARATOR . 'schema'))
                 ))
             );
         }
@@ -302,7 +293,7 @@ class WebWizard extends Wizard implements SetupWizard
         $setup->addStep(
             new GeneralConfigStep(array(
                 'generalConfig'         => $pageData['setup_general_config'],
-                'preferencesType'       => $pageData['setup_preferences_type']['type'],
+                'preferencesStore'       => $pageData['setup_preferences_type']['store'],
                 'preferencesResource'   => isset($pageData['setup_db_resource']['name'])
                     ? $pageData['setup_db_resource']['name']
                     : null
@@ -343,24 +334,26 @@ class WebWizard extends Wizard implements SetupWizard
             );
         }
 
-        $configDir = $this->getConfigDir();
+        $configDir = Icinga::app()->getConfigDir();
         $setup->addStep(
             new MakeDirStep(
                 array(
-                    $configDir . '/modules',
-                    $configDir . '/preferences',
-                    $configDir . '/enabledModules'
+                    $configDir . DIRECTORY_SEPARATOR . 'modules',
+                    $configDir . DIRECTORY_SEPARATOR . 'preferences',
+                    $configDir . DIRECTORY_SEPARATOR . 'enabledModules'
                 ),
-                0775
+                2770
             )
         );
 
-        foreach ($this->getPage('setup_modules')->setPageData($this->getPageData())->getWizards() as $wizard) {
-            if ($wizard->isFinished()) {
+        foreach ($this->getWizards() as $wizard) {
+            if ($wizard->isComplete()) {
                 $setup->addSteps($wizard->getSetup()->getSteps());
             }
         }
 
+        $setup->addStep(new EnableModuleStep(array_keys($this->getPage('setup_modules')->getCheckedModules())));
+
         return $setup;
     }
 
@@ -373,6 +366,7 @@ class WebWizard extends Wizard implements SetupWizard
 
         $phpVersion = Platform::getPhpVersion();
         $requirements->addMandatory(
+            'php_version_>=_5_3_2',
             mt('setup', 'PHP Version'),
             mt(
                 'setup',
@@ -385,6 +379,7 @@ class WebWizard extends Wizard implements SetupWizard
 
         $defaultTimezone = Platform::getPhpConfig('date.timezone');
         $requirements->addMandatory(
+            'existing_default_timezone',
             mt('setup', 'Default Timezone'),
             sprintf(
                 mt('setup', 'It is required that a default timezone has been set using date.timezone in %s.'),
@@ -397,6 +392,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'platform=linux',
             mt('setup', 'Linux Platform'),
             mt(
                 'setup',
@@ -408,6 +404,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addMandatory(
+            'existing_php_mod_openssl',
             mt('setup', 'PHP Module: OpenSSL'),
             mt('setup', 'The PHP module for OpenSSL is required to generate cryptographically safe password salts.'),
             Platform::extensionLoaded('openssl'),
@@ -417,6 +414,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_json',
             mt('setup', 'PHP Module: JSON'),
             mt('setup', 'The JSON module for PHP is required for various export functionalities as well as APIs.'),
             Platform::extensionLoaded('json'),
@@ -426,6 +424,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_ldap',
             mt('setup', 'PHP Module: LDAP'),
             mt('setup', 'If you\'d like to authenticate users using LDAP the corresponding PHP module is required'),
             Platform::extensionLoaded('ldap'),
@@ -435,6 +434,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_intl',
             mt('setup', 'PHP Module: INTL'),
             mt(
                 'setup',
@@ -449,6 +449,7 @@ class WebWizard extends Wizard implements SetupWizard
 
         // TODO(6172): Remove this requirement once we do not ship dompdf with Icinga Web 2 anymore
         $requirements->addOptional(
+            'existing_php_mod_dom',
             mt('setup', 'PHP Module: DOM'),
             mt('setup', 'To be able to export views and reports to PDF, the DOM module for PHP is required.'),
             Platform::extensionLoaded('dom'),
@@ -458,6 +459,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_gd',
             mt('setup', 'PHP Module: GD'),
             mt(
                 'setup',
@@ -471,6 +473,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_imagick',
             mt('setup', 'PHP Module: Imagick'),
             mt(
                 'setup',
@@ -484,6 +487,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_pdo_mysql',
             mt('setup', 'PHP Module: PDO-MySQL'),
             mt(
                 'setup',
@@ -496,6 +500,7 @@ class WebWizard extends Wizard implements SetupWizard
         );
 
         $requirements->addOptional(
+            'existing_php_mod_pdo_pgsql',
             mt('setup', 'PHP Module: PDO-PostgreSQL'),
             mt(
                 'setup',
@@ -510,6 +515,7 @@ class WebWizard extends Wizard implements SetupWizard
 
         $mysqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Mysql');
         $requirements->addOptional(
+            'existing_class_Zend_Db_Adapter_Pdo_Mysql',
             mt('setup', 'Zend Database Adapter For MySQL'),
             mt('setup', 'The Zend database adapter for MySQL is required to access a MySQL database.'),
             $mysqlAdapterFound,
@@ -520,6 +526,7 @@ class WebWizard extends Wizard implements SetupWizard
 
         $pgsqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Pgsql');
         $requirements->addOptional(
+            'existing_class_Zend_Db_Adapter_Pdo_Pgsql',
             mt('setup', 'Zend Database Adapter For PostgreSQL'),
             mt('setup', 'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'),
             $pgsqlAdapterFound,
@@ -528,12 +535,13 @@ class WebWizard extends Wizard implements SetupWizard
             )
         );
 
-        $configDir = $this->getConfigDir();
+        $configDir = Icinga::app()->getConfigDir();
         $requirements->addMandatory(
+            'writable_directory_' . $configDir,
             mt('setup', 'Writable Config Directory'),
             mt(
                 'setup',
-                'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb", if' .
+                'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb2", if' .
                 ' not explicitly set in the environment variable "ICINGAWEB_CONFIGDIR".'
             ),
             is_writable($configDir),
@@ -545,27 +553,10 @@ class WebWizard extends Wizard implements SetupWizard
             )
         );
 
-        foreach ($this->getPage('setup_modules')->setPageData($this->getPageData())->getWizards() as $wizard) {
-            $requirements->merge($wizard->getRequirements()->allOptional());
+        foreach ($this->getWizards() as $wizard) {
+            $requirements->merge($wizard->getRequirements());
         }
 
         return $requirements;
     }
-
-    /**
-     * Return the configuration directory of Icinga Web 2
-     *
-     * @return  string
-     */
-    protected function getConfigDir()
-    {
-        if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) {
-            $configDir = $_SERVER['ICINGAWEB_CONFIGDIR'];
-        } else {
-            $configDir = '/etc/icingaweb';
-        }
-
-        $canonical = realpath($configDir);
-        return $canonical ? $canonical : $configDir;
-    }
 }
diff --git a/modules/setup/library/Setup/Webserver.php b/modules/setup/library/Setup/Webserver.php
index 2449f9b9e..dbc55b6a2 100644
--- a/modules/setup/library/Setup/Webserver.php
+++ b/modules/setup/library/Setup/Webserver.php
@@ -24,7 +24,7 @@ abstract class Webserver
      *
      * @var string
      */
-    protected $urlPath = '/icingaweb';
+    protected $urlPath = '/icingaweb2';
 
     /**
      * Path to Icinga Web 2's configuration files
diff --git a/modules/translation/library/Translation/Util/GettextTranslationHelper.php b/modules/translation/library/Translation/Util/GettextTranslationHelper.php
index 0d5a950e1..5702def85 100644
--- a/modules/translation/library/Translation/Util/GettextTranslationHelper.php
+++ b/modules/translation/library/Translation/Util/GettextTranslationHelper.php
@@ -101,7 +101,7 @@ class GettextTranslationHelper
      */
     public function __construct(ApplicationBootstrap $bootstrap, $locale)
     {
-        $this->moduleMgr = $bootstrap->getModuleManager()->loadCoreModules()->loadEnabledModules();
+        $this->moduleMgr = $bootstrap->getModuleManager()->loadEnabledModules();
         $this->appDir = $bootstrap->getApplicationDir();
         $this->locale = $locale;
     }
diff --git a/packages/files/apache/icingaweb.conf b/packages/files/apache/icingaweb2.conf
similarity index 91%
rename from packages/files/apache/icingaweb.conf
rename to packages/files/apache/icingaweb2.conf
index 2c52b73e3..6bf0b7a66 100644
--- a/packages/files/apache/icingaweb.conf
+++ b/packages/files/apache/icingaweb2.conf
@@ -1,4 +1,4 @@
-Alias /icingaweb "/usr/share/icingaweb2/public"
+Alias /icingaweb2 "/usr/share/icingaweb2/public"
 
 <Directory "/usr/share/icingaweb2/public">
     Options SymLinksIfOwnerMatch
@@ -23,7 +23,7 @@ Alias /icingaweb "/usr/share/icingaweb2/public"
 
     <IfModule mod_rewrite.c>
         RewriteEngine on
-        RewriteBase /icingaweb/
+        RewriteBase /icingaweb2/
         RewriteCond %{REQUEST_FILENAME} -s [OR]
         RewriteCond %{REQUEST_FILENAME} -l [OR]
         RewriteCond %{REQUEST_FILENAME} -d
diff --git a/packages/files/bin/icingacli b/packages/files/bin/icingacli
index 10b4857aa..5b41e4e8c 100755
--- a/packages/files/bin/icingacli
+++ b/packages/files/bin/icingacli
@@ -3,4 +3,4 @@
 
 require_once '/usr/share/php/Icinga/Application/Cli.php';
 
-Icinga\Application\Cli::start('/usr/share/icingaweb')->dispatch();
+Icinga\Application\Cli::start('/usr/share/icingaweb2')->dispatch();
diff --git a/packages/files/config/modules/doc/config.ini b/packages/files/config/modules/doc/config.ini
new file mode 100644
index 000000000..80df20784
--- /dev/null
+++ b/packages/files/config/modules/doc/config.ini
@@ -0,0 +1,3 @@
+[documentation]
+icingaweb2 = /usr/share/doc/icingaweb2/markdown
+modules = /usr/share/doc/icingaweb2/modules/{module}/markdown
diff --git a/packages/files/config/modules/setup/config.ini b/packages/files/config/modules/setup/config.ini
new file mode 100644
index 000000000..5158aae99
--- /dev/null
+++ b/packages/files/config/modules/setup/config.ini
@@ -0,0 +1,2 @@
+[schema]
+path = /usr/share/doc/icingaweb2/schema
diff --git a/public/css/icinga/login.less b/public/css/icinga/login.less
index cfae3c478..6b03b476a 100644
--- a/public/css/icinga/login.less
+++ b/public/css/icinga/login.less
@@ -113,18 +113,33 @@
     margin-left: 5em;
   }
 
-  div.config-note {
+  p.config-note {
     width: 50%;
     padding: 1em;
-    margin: 5em auto 0;
+    margin: 0 auto 2.5em;
     text-align: center;
     color: white;
     background-color: @colorCritical;
+
+    a {
+      color: white;
+      font-weight: bold;
+    }
   }
 
-  div.config-note a {
-    color: white;
-    font-weight: bold;
+  p.info-box {
+    width: 50%;
+    height: 2.2em;
+    margin: 0 auto 2.5em;
+
+    span.icon-info {
+      float: left;
+      height: 100%;
+    }
+
+    em {
+      text-decoration: underline;
+    }
   }
 }
 
diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less
index 6972e95dc..e3e31b397 100644
--- a/public/css/icinga/main-content.less
+++ b/public/css/icinga/main-content.less
@@ -154,6 +154,7 @@ table.perfdata th {
 
 table.perfdata td {
   white-space: nowrap;
+  padding-right: 0.5em;
 }
 
 table.objectlist {
@@ -202,3 +203,9 @@ table.benchmark {
 [class^="icon-"]:before, [class*=" icon-"]:before {
     text-decoration: none;
 }
+
+.info-box {
+  padding: 0.5em;
+  border: 1px solid lightgrey;
+  background-color: infobackground;
+}
diff --git a/public/css/icinga/menu.less b/public/css/icinga/menu.less
index c8ab698a5..0f3f2691e 100644
--- a/public/css/icinga/menu.less
+++ b/public/css/icinga/menu.less
@@ -62,15 +62,6 @@
   color: @colorPetrol;
 }
 
-#menu > ul > li.active li a:focus {
-  color: @colorTextDefault;
-}
-
-#menu > ul > li > a:focus {
-  color: @colorTextDefault;
-  text-shadow: none;
-}
-
 #menu > ul > li.active li a:hover {
   text-decoration: underline;
 }
@@ -264,3 +255,16 @@ html.ie8 #menu input.search {
 
 input:focus { outline: none; }
 
+/* Make focus outline properly visible */
+a:focus {
+  outline: dotted black 1px;
+}
+
+/* Displaying the outline in the navigation is not possible because of the messed up link borders,
+   color those links instead. */
+#menu a:focus,
+#menu > ul > li > a:focus,
+#menu .active ul li a:focus {
+  color: #21b5ad;
+  outline: none;
+}
diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less
index 86268d2ce..1e657101f 100644
--- a/public/css/icinga/monitoring-colors.less
+++ b/public/css/icinga/monitoring-colors.less
@@ -195,7 +195,7 @@ tr.state.handled td.state {
 }
 
 /* HOVER colors */
-tr.state:hover, tr[href]:hover {
+tr[href]:hover {
   color: black;
   background-color: #eee;
 }
diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less
index 166e47ff8..9dff6fecf 100644
--- a/public/css/icinga/setup.less
+++ b/public/css/icinga/setup.less
@@ -176,6 +176,12 @@
       margin: 0 1em 0 0;
     }
 
+    ul {
+      margin: 0;
+      padding-left: 1em;
+      list-style-type: square;
+    }
+
     &.state {
       color: white;
       padding: 0.4em;
@@ -214,6 +220,10 @@
   }
 }
 
+#setup_authentication_type p.info-box em {
+  text-decoration: underline;
+}
+
 #setup_ldap_discovery_confirm table {
   margin: 1em 0;
   border-collapse: separate;
@@ -270,7 +280,7 @@
     }
   }
 
-  form#setup_summary {
+  form.summary {
     clear: left;
   }
 }
@@ -395,71 +405,44 @@
   }
 }
 
-#setup {
-  div.module-wizard {
-    width: auto;
-    padding: 1em;
-    overflow: hidden;
-    border: solid 1px lightgrey;
+#setup_modules {
+  div.module {
+    float: left;
+    width: 15em;
+    height: 15em;
+    margin: 1em;
+    padding: 0.3em;
+    border: 1px solid #ccc;
+    background-color: snow;
 
-    div.buttons {
-      margin: 1.5em 0 0;
+    h3 {
+      border: none;
+      margin: 0.5em 0;
+      text-align: center;
+
+      label {
+        margin: 0;
+        width: 15em;
+        cursor: pointer;
+      }
+    }
+
+    h3 + label {
+      width: 13.5em;
+      height: 13.9em;
+      overflow: auto;
+      cursor: pointer;
+      font-weight: normal;
+    }
+
+    input[type=checkbox] {
+      height: 10em;
       float: right;
-
-      button[type=submit] {
-        padding: 0.5em;
-        line-height: 0.5em;
-	background-color: @colorPetrol;
-
-        &:hover, &:focus, &:active {
-          background-color: #666;
-        }
-      }
     }
   }
 
-  div.module-menu {
-    font-size: 0.9em;
-    width: 25%;
-    float: right;
-    margin-left: 1.5em;
-
-    p {
-      margin-top: 0;
-
-      &.all-completed {
-        .conspicuous-state-notification;
-        text-align: center;
-        font-size: 90%;
-        background-color: @colorOk;
-      }
-    }
-
-    ul {
-      padding-left: 1.2em;
-
-      button {
-        margin: 0 0 0.8em;
-        padding: 0;
-        color: black;
-        border: none;
-        outline: none;
-        font-size: 90%;
-        background-color: white;
-
-        &:hover {
-          color: #666;
-          cursor: pointer;
-        }
-
-        &:focus, &:active {
-          color: #666;
-        }
-      }
-
-      img {
-        margin: 0 0.5em 0.2em;
-      }
-    }
+  div.buttons {
+    padding-top: 1em;
+    clear: both;
   }
-}
+}
\ No newline at end of file
diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less
index 93625b0dc..e2e37d7ab 100644
--- a/public/css/icinga/widgets.less
+++ b/public/css/icinga/widgets.less
@@ -285,3 +285,10 @@ li li .badge {
 .widgetFilter li.active {
     background-color: #eee;
 }
+
+.sparkline {
+  width: 12px;
+  height: 12px;
+  position: relative;
+  top: 4px;
+}
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/font/ifont.eot b/public/font/ifont.eot
similarity index 100%
rename from application/fonts/fontello-ifont/font/ifont.eot
rename to public/font/ifont.eot
diff --git a/application/fonts/fontello-ifont/font/ifont.svg b/public/font/ifont.svg
similarity index 100%
rename from application/fonts/fontello-ifont/font/ifont.svg
rename to public/font/ifont.svg
diff --git a/application/fonts/fontello-ifont/font/ifont.ttf b/public/font/ifont.ttf
similarity index 100%
rename from application/fonts/fontello-ifont/font/ifont.ttf
rename to public/font/ifont.ttf
diff --git a/application/fonts/fontello-ifont/font/ifont.woff b/public/font/ifont.woff
similarity index 100%
rename from application/fonts/fontello-ifont/font/ifont.woff
rename to public/font/ifont.woff
diff --git a/public/js/icinga/behavior/navigation.js b/public/js/icinga/behavior/navigation.js
index fde043c01..b8a12064d 100644
--- a/public/js/icinga/behavior/navigation.js
+++ b/public/js/icinga/behavior/navigation.js
@@ -32,6 +32,15 @@
             if ($outerMenu.size()) {
                 $outerMenu.addClass('active');
             }
+
+            /*
+              Recreate the html content of the menu item to force the browser to update the layout, or else
+              the link would only be visible as active after another click or page reload in Gecko and WebKit.
+              
+              fixes #7897
+            */
+            $selectedMenu.html($selectedMenu.html());
+
         } else {
             // store menu state
             var $menus = $('#menu li.active', el);
@@ -121,23 +130,26 @@
         }
 
         setTimeout(function () {
-            if (! $li.is('li:hover')) {
-                return;
-            }
-            if ($li.hasClass('active')) {
-                return;
-            }
+            try {
+                if (!$li.is('li:hover')) {
+                    return;
+                }
+                if ($li.hasClass('active')) {
+                    return;
+                }
+            } catch(e) { /* Bypass because if IE8 */ }
 
             $li.siblings().each(function () {
                 var $sibling = $(this);
-                if ($sibling.is('li:hover')) {
-                    return;
-                }
+                try {
+                    if ($sibling.is('li:hover')) {
+                        return;
+                    }
+                } catch(e) { /* Bypass because if IE8 */ };
                 if ($sibling.hasClass('hover')) {
                     $sibling.removeClass('hover');
                 }
             });
-
             self.hoverElement($li);
         }, delay);
     };
@@ -152,9 +164,11 @@
         }
 
         setTimeout(function () {
-            if ($li.is('li:hover') || $sidebar.is('sidebar:hover') ) {
-                return;
-            }
+            try {
+                if ($li.is('li:hover') || $sidebar.is('sidebar:hover')) {
+                    return;
+                }
+            } catch(e) { /* Bypass because if IE8 */ };
             $li.removeClass('hover');
             $('#layout').removeClass('hoveredmenu');
         }, 500);
@@ -174,9 +188,11 @@
             self = event.data.self;
         setTimeout(function () {
             // TODO: make this behave well together with keyboard navigation
-            if (! $li.is('li:hover') /*&& ! $li.find('a:focus')*/) {
-                $li.removeClass('hover');
-            }
+            try {
+                if (!$li.is('li:hover') /*&& ! $li.find('a:focus')*/) {
+                    $li.removeClass('hover');
+                }
+            } catch(e) { /* Bypass because if IE8 */ }
         }, 300);
     };
     Icinga.Behaviors.Navigation = Navigation;
diff --git a/public/js/icinga/behavior/sparkline.js b/public/js/icinga/behavior/sparkline.js
index 33cc0d34b..e0d0fb0c7 100644
--- a/public/js/icinga/behavior/sparkline.js
+++ b/public/js/icinga/behavior/sparkline.js
@@ -18,34 +18,33 @@
 
         $('span.sparkline', el).each(function(i, element) {
             // read custom options
-            var $spark            = $(element);
-            var labels            = $spark.attr('labels').split('|');
-            var formatted         = $spark.attr('formatted').split('|');
-            var tooltipChartTitle = $spark.attr('sparkTooltipChartTitle') || '';
-            var format            = $spark.attr('tooltipformat');
-            var hideEmpty         = $spark.attr('hideEmptyLabel') === 'true';
-            $spark.sparkline(
-                'html',
-                {
+            var $spark = $(element);
+            var title  = $spark.attr('title');
+
+            if ($spark.attr('labels')) {
+                $spark.removeAttr('original-title');
+            }
+
+            var options;
+            if ($spark.hasClass('sparkline-perfdata')) {
+                options = {
                     enableTagOptions: true,
-                    tooltipFormatter: function (sparkline, options, fields) {
-                        var out       = format;
-                        if (hideEmpty && fields.offset === 3) {
-                            return '';
-                        }
-                        var replace   = {
-                            title:     tooltipChartTitle,
-                            label:     labels[fields.offset] ? labels[fields.offset] : fields.offset,
-                            formatted: formatted[fields.offset] ? formatted[fields.offset] : '',
-                            value:     fields.value,
-                            percent:   Math.round(fields.percent * 100) / 100
-                        };
-                        $.each(replace, function(key, value) {
-                            out = out.replace('{{' + key + '}}', value);
-                        });
-                        return out;
-                    }
-            });
+                    width: 12,
+                    height: 12,
+                    title: title,
+                    disableTooltips: true
+                };
+                $spark.sparkline('html', options);
+            } else if ($spark.hasClass('sparkline-multi')) {
+                options = {
+                    width: 100,
+                    height: 100,
+                    title: title,
+                    enableTagOptions: true
+                };
+                $spark.sparkline('html', options);
+            }
+
         });
     };
 
diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js
index e7ac3e3f1..b7f2f5cee 100644
--- a/public/js/icinga/events.js
+++ b/public/js/icinga/events.js
@@ -482,6 +482,16 @@
                     targetId = 'col1';
                     $target = $('#' + targetId);
                     self.icinga.ui.layout1col();
+                } else if (targetId === '_right') {
+                    // Ensure that the content is displayed in the rightmost column
+                    $target = $el.closest('.container');
+                    if ($target.attr('id') === 'col1') {
+                        // As it's not possible to detect what's preceding the current state in the
+                        // history stack this just simulates _main in case the respective element
+                        // is not part of the rightmost column
+                        $target = $('#col1');
+                        self.icinga.ui.layout1col();
+                    }
                 } else {
                     $target = $('#' + targetId);
                 }
diff --git a/var/log/.gitkeep b/var/log/.gitkeep
deleted file mode 100644
index e69de29bb..000000000