From 4d795494fc1c5ab7da89c7f0c83e9ab454b827a9 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 10:48:37 +0200
Subject: [PATCH 1/6] Fix MissingParameterException's PHPDoc

refs #8886
---
 library/Icinga/Exception/MissingParameterException.php | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/library/Icinga/Exception/MissingParameterException.php b/library/Icinga/Exception/MissingParameterException.php
index 2673cc2d6..6ccd28dc3 100644
--- a/library/Icinga/Exception/MissingParameterException.php
+++ b/library/Icinga/Exception/MissingParameterException.php
@@ -4,8 +4,7 @@
 namespace Icinga\Exception;
 
 /**
- * Class MissingParameterException
- * @package Icinga\Exception
+ * Exception thrown if a mandatory parameter was not given
  */
 class MissingParameterException extends IcingaException
 {

From 0fc5801e5e8aa2998ad5af1189ff53b8645c827f Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 12:15:15 +0200
Subject: [PATCH 2/6] lib: Add MissingParameterException::getParameter and
 ::setParameter ...

... for getting/setting the name of the missing parameter which caused the exception.

refs #8886
---
 .../Exception/MissingParameterException.php   | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/library/Icinga/Exception/MissingParameterException.php b/library/Icinga/Exception/MissingParameterException.php
index 6ccd28dc3..4377ef103 100644
--- a/library/Icinga/Exception/MissingParameterException.php
+++ b/library/Icinga/Exception/MissingParameterException.php
@@ -8,4 +8,33 @@ namespace Icinga\Exception;
  */
 class MissingParameterException extends IcingaException
 {
+    /**
+     * Name of the missing parameter
+     *
+     * @var string
+     */
+    protected $parameter;
+
+    /**
+     * Get the name of the missing parameter
+     *
+     * @return string
+     */
+    public function getParameter()
+    {
+        return $this->parameter;
+    }
+
+    /**
+     * Set the name of the missing parameter
+     *
+     * @param   string  $name
+     *
+     * @return  $this
+     */
+    public function setParameter($name)
+    {
+        $this->parameter = (string) $name;
+        return $this;
+    }
 }

From 93b1a35de0e08692c4107d0f1d5726661b55e3b0 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 12:17:59 +0200
Subject: [PATCH 3/6] lib: Add UrlParams::req()

UrlParams::req() should be used for requiring a mandatory URL parameter.

refs #8886
---
 library/Icinga/Web/UrlParams.php | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/library/Icinga/Web/UrlParams.php b/library/Icinga/Web/UrlParams.php
index 5c2a79d05..a38c1a229 100644
--- a/library/Icinga/Web/UrlParams.php
+++ b/library/Icinga/Web/UrlParams.php
@@ -3,6 +3,8 @@
 
 namespace Icinga\Web;
 
+use Icinga\Exception\MissingParameterException;
+
 class UrlParams
 {
     protected $separator = '&';
@@ -42,6 +44,29 @@ class UrlParams
         return rawurldecode($this->params[ end($this->index[$param]) ][ 1 ]);
     }
 
+    /**
+     * Require a parameter
+     *
+     * @param   string  $name               Name of the parameter
+     * @param   bool    $strict             Whether the parameter's value must not be the empty string
+     *
+     * @return  mixed
+     *
+     * @throws  MissingParameterException   If the parameter was not given
+     */
+    public function req($name, $strict = true)
+    {
+        if ($this->has($name)) {
+            $value = $this->get($name);
+            if (! $strict || strlen($value) > 0) {
+                return $value;
+            }
+        }
+        $e = new MissingParameterException(t('Required parameter \'%s\' missing'), $name);
+        $e->setParameter($name);
+        throw $e;
+    }
+
     /**
      * Get all instances of the given parameter
      *

From 002e793a536efea9da7a3bad99250ce1e9d5656c Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 12:20:37 +0200
Subject: [PATCH 4/6] lib: Add Params::req()

Params::req() should be used for requiring a mandatory CLI parameter.

refs #8886
---
 library/Icinga/Cli/Params.php | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/library/Icinga/Cli/Params.php b/library/Icinga/Cli/Params.php
index 27a1df9a1..34dd5e177 100644
--- a/library/Icinga/Cli/Params.php
+++ b/library/Icinga/Cli/Params.php
@@ -3,6 +3,8 @@
 
 namespace Icinga\Cli;
 
+use Icinga\Exception\MissingParameterException;
+
 /**
  * Params
  *
@@ -155,6 +157,29 @@ class Params
         return $default;
     }
 
+    /**
+     * Require a parameter
+     *
+     * @param   string  $name               Name of the parameter
+     * @param   bool    $strict             Whether the parameter's value must not be the empty string
+     *
+     * @return  mixed
+     *
+     * @throws  MissingParameterException   If the parameter was not given
+     */
+    public function req($name, $strict = true)
+    {
+        if ($this->has($name)) {
+            $value = $this->get($name);
+            if (! $strict || strlen($value) > 0) {
+                return $value;
+            }
+        }
+        $e = new MissingParameterException(t('Required parameter \'%s\' missing'), $name);
+        $e->setParameter($name);
+        throw $e;
+    }
+
     /**
      * Set a value for the given option
      *

From dfd8c91827a0f7f8ed383c518c53113e2c5ace44 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 12:25:46 +0200
Subject: [PATCH 5/6] Add PHPDoc to ActionController::$params

---
 library/Icinga/Web/Controller/ActionController.php | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php
index 89a56e745..f40b8d538 100644
--- a/library/Icinga/Web/Controller/ActionController.php
+++ b/library/Icinga/Web/Controller/ActionController.php
@@ -55,6 +55,11 @@ class ActionController extends Zend_Controller_Action
      */
     private $auth;
 
+    /**
+     * URL parameters
+     *
+     * @var UrlParams
+     */
     protected $params;
 
     /**

From 25736cf76e214f20ac14e87993d1908f1b0cfd65 Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Tue, 7 Apr 2015 12:27:19 +0200
Subject: [PATCH 6/6] Return HTTP 400 on MissingParameterException

refs #8886
---
 application/controllers/ErrorController.php | 26 ++++++++++++++-------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php
index 6b75c6488..a77d36f4f 100644
--- a/application/controllers/ErrorController.php
+++ b/application/controllers/ErrorController.php
@@ -3,6 +3,7 @@
 
 use Icinga\Application\Icinga;
 use Icinga\Application\Logger;
+use Icinga\Exception\MissingParameterException;
 use Icinga\Security\SecurityException;
 use Icinga\Web\Controller\ActionController;
 
@@ -42,19 +43,26 @@ class ErrorController extends ActionController
                 }
 
                 break;
-            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER:
-                if ($exception instanceof SecurityException) {
-                    $this->getResponse()->setHttpResponseCode(403);
-                    $this->view->message = $exception->getMessage();
-                    break;
-                }
-                // Move to default
             default:
+                switch (true) {
+                    case $exception instanceof SecurityException:
+                        $this->getResponse()->setHttpResponseCode(403);
+                        break;
+                    case $exception instanceof MissingParameterException:
+                        $this->getResponse()->setHttpResponseCode(400);
+                        $this->getResponse()->setHeader(
+                            'X-Status-Reason',
+                            'Missing parameter ' . $exception->getParameter()
+                        );
+                        break;
+                    default:
+                        $this->getResponse()->setHttpResponseCode(500);
+                        break;
+                }
                 $title = preg_replace('/\r?\n.*$/s', '', $exception->getMessage());
-                $this->getResponse()->setHttpResponseCode(500);
                 $this->view->title = 'Server error: ' . $title;
                 $this->view->message = $exception->getMessage();
-                if ($this->getInvokeArg('displayExceptions') == true) {
+                if ($this->getInvokeArg('displayExceptions')) {
                     $this->view->stackTrace = $exception->getTraceAsString();
                 }
                 break;