summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Web/Response
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:39:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:39:39 +0000
commit8ca6cc32b2c789a3149861159ad258f2cb9491e3 (patch)
tree2492de6f1528dd44eaa169a5c1555026d9cb75ec /library/Icinga/Web/Response
parentInitial commit. (diff)
downloadicingaweb2-upstream.tar.xz
icingaweb2-upstream.zip
Adding upstream version 2.11.4.upstream/2.11.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--library/Icinga/Web/Response.php429
-rw-r--r--library/Icinga/Web/Response/JsonResponse.php239
2 files changed, 668 insertions, 0 deletions
diff --git a/library/Icinga/Web/Response.php b/library/Icinga/Web/Response.php
new file mode 100644
index 0000000..df0b842
--- /dev/null
+++ b/library/Icinga/Web/Response.php
@@ -0,0 +1,429 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Web;
+
+use Zend_Controller_Response_Http;
+use Icinga\Application\Icinga;
+use Icinga\Web\Response\JsonResponse;
+
+/**
+ * A HTTP response
+ */
+class Response extends Zend_Controller_Response_Http
+{
+ /**
+ * The default content type being used for responses
+ *
+ * @var string
+ */
+ const DEFAULT_CONTENT_TYPE = 'text/html; charset=UTF-8';
+
+ /**
+ * Auto-refresh interval
+ *
+ * @var int
+ */
+ protected $autoRefreshInterval;
+
+ /**
+ * Set of cookies which are to be sent to the client
+ *
+ * @var CookieSet
+ */
+ protected $cookies;
+
+ /**
+ * Redirect URL
+ *
+ * @var Url|null
+ */
+ protected $redirectUrl;
+
+ /**
+ * Request
+ *
+ * @var Request
+ */
+ protected $request;
+
+ /**
+ * Whether to instruct the client to reload the window
+ *
+ * @var bool
+ */
+ protected $reloadWindow;
+
+ /**
+ * Whether to instruct client side script code to reload CSS
+ *
+ * @var bool
+ */
+ protected $reloadCss;
+
+ /**
+ * Whether to send the rerender layout header on XHR
+ *
+ * @var bool
+ */
+ protected $rerenderLayout = false;
+
+ /**
+ * Whether to send the current window ID to the client
+ *
+ * @var bool
+ */
+ protected $overrideWindowId = false;
+
+ /**
+ * Get the auto-refresh interval
+ *
+ * @return int
+ */
+ public function getAutoRefreshInterval()
+ {
+ return $this->autoRefreshInterval;
+ }
+
+ /**
+ * Set the auto-refresh interval
+ *
+ * @param int $autoRefreshInterval
+ *
+ * @return $this
+ */
+ public function setAutoRefreshInterval($autoRefreshInterval)
+ {
+ $this->autoRefreshInterval = $autoRefreshInterval;
+ return $this;
+ }
+
+ /**
+ * Get the set of cookies which are to be sent to the client
+ *
+ * @return CookieSet
+ */
+ public function getCookies()
+ {
+ if ($this->cookies === null) {
+ $this->cookies = new CookieSet();
+ }
+ return $this->cookies;
+ }
+
+ /**
+ * Get the cookie with the given name from the set of cookies which are to be sent to the client
+ *
+ * @param string $name The name of the cookie
+ *
+ * @return Cookie|null The cookie with the given name or null if the cookie does not exist
+ */
+ public function getCookie($name)
+ {
+ return $this->getCookies()->get($name);
+ }
+
+ /**
+ * Set the given cookie for sending it to the client
+ *
+ * @param Cookie $cookie The cookie to send to the client
+ *
+ * @return $this
+ */
+ public function setCookie(Cookie $cookie)
+ {
+ $this->getCookies()->add($cookie);
+ return $this;
+ }
+
+ /**
+ * Get the redirect URL
+ *
+ * @return Url|null
+ */
+ protected function getRedirectUrl()
+ {
+ return $this->redirectUrl;
+ }
+
+ /**
+ * Set the redirect URL
+ *
+ * Unlike {@link setRedirect()} this method only sets a redirect URL on the response for later usage.
+ * {@link prepare()} will take care of the correct redirect handling and HTTP headers on XHR and "normal" browser
+ * requests.
+ *
+ * @param string|Url $redirectUrl
+ *
+ * @return $this
+ */
+ protected function setRedirectUrl($redirectUrl)
+ {
+ if (! $redirectUrl instanceof Url) {
+ $redirectUrl = Url::fromPath((string) $redirectUrl);
+ }
+ $redirectUrl->getParams()->setSeparator('&');
+ $this->redirectUrl = $redirectUrl;
+ return $this;
+ }
+
+ /**
+ * Get an array of all header values for the given name
+ *
+ * @param string $name The name of the header
+ * @param bool $lastOnly If this is true, the last value will be returned as a string
+ *
+ * @return null|array|string
+ */
+ public function getHeader($name, $lastOnly = false)
+ {
+ $result = ($lastOnly ? null : array());
+ $headers = $this->getHeaders();
+ foreach ($headers as $header) {
+ if ($header['name'] === $name) {
+ if ($lastOnly) {
+ $result = $header['value'];
+ } else {
+ $result[] = $header['value'];
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get the request
+ *
+ * @return Request
+ */
+ public function getRequest()
+ {
+ if ($this->request === null) {
+ $this->request = Icinga::app()->getRequest();
+ }
+ return $this->request;
+ }
+
+ /**
+ * Get whether to instruct the client to reload the window
+ *
+ * @return bool
+ */
+ public function isWindowReloaded()
+ {
+ return $this->reloadWindow;
+ }
+
+ /**
+ * Set whether to instruct the client to reload the window
+ *
+ * @param bool $reloadWindow
+ *
+ * @return $this
+ */
+ public function setReloadWindow($reloadWindow)
+ {
+ $this->reloadWindow = $reloadWindow;
+
+ return $this;
+ }
+
+ /**
+ * Get whether to instruct client side script code to reload CSS
+ *
+ * @return bool
+ */
+ public function isReloadCss()
+ {
+ return $this->reloadCss;
+ }
+
+ /**
+ * Set whether to instruct client side script code to reload CSS
+ *
+ * @param bool $reloadCss
+ *
+ * @return $this
+ */
+ public function setReloadCss($reloadCss)
+ {
+ $this->reloadCss = $reloadCss;
+ return $this;
+ }
+
+ /**
+ * Get whether to send the rerender layout header on XHR
+ *
+ * @return bool
+ */
+ public function getRerenderLayout()
+ {
+ return $this->rerenderLayout;
+ }
+
+ /**
+ * Get whether to send the rerender layout header on XHR
+ *
+ * @param bool $rerenderLayout
+ *
+ * @return $this
+ */
+ public function setRerenderLayout($rerenderLayout = true)
+ {
+ $this->rerenderLayout = (bool) $rerenderLayout;
+ return $this;
+ }
+
+ /**
+ * Get whether to send the current window ID to the client
+ *
+ * @return bool
+ */
+ public function getOverrideWindowId()
+ {
+ return $this->overrideWindowId;
+ }
+
+ /**
+ * Set whether to send the current window ID to the client
+ *
+ * @param bool $overrideWindowId
+ *
+ * @return $this
+ */
+ public function setOverrideWindowId($overrideWindowId = true)
+ {
+ $this->overrideWindowId = $overrideWindowId;
+ return $this;
+ }
+
+ /**
+ * Entry point for HTTP responses in JSON format
+ *
+ * @return JsonResponse
+ */
+ public function json()
+ {
+ $response = new JsonResponse();
+ $response->copyMetaDataFrom($this);
+ return $response;
+ }
+
+ /**
+ * Prepare the request before sending
+ */
+ protected function prepare()
+ {
+ $redirectUrl = $this->getRedirectUrl();
+ if ($this->getRequest()->isXmlHttpRequest()) {
+ if ($redirectUrl !== null) {
+ if ($this->getRequest()->isGet() && Icinga::app()->getViewRenderer()->view->compact) {
+ $redirectUrl->getParams()->set('showCompact', true);
+ }
+
+ $this->setHeader('X-Icinga-Redirect', rawurlencode($redirectUrl->getAbsoluteUrl()), true);
+ if ($this->getRerenderLayout()) {
+ $this->setHeader('X-Icinga-Rerender-Layout', 'yes', true);
+ }
+ }
+ if ($this->getOverrideWindowId()) {
+ $this->setHeader('X-Icinga-WindowId', Window::getInstance()->getId(), true);
+ }
+ if ($this->getRerenderLayout()) {
+ $this->setHeader('X-Icinga-Container', 'layout', true);
+ }
+ if ($this->isWindowReloaded()) {
+ $this->setHeader('X-Icinga-Reload-Window', 'yes', true);
+ }
+ if ($this->isReloadCss()) {
+ $this->setHeader('X-Icinga-Reload-Css', 'now', true);
+ }
+ if (($autoRefreshInterval = $this->getAutoRefreshInterval()) !== null) {
+ $this->setHeader('X-Icinga-Refresh', $autoRefreshInterval, true);
+ }
+
+ $notifications = Notification::getInstance();
+ if ($notifications->hasMessages()) {
+ $notificationList = array();
+ foreach ($notifications->popMessages() as $m) {
+ $notificationList[] = rawurlencode($m->type . ' ' . $m->message);
+ }
+ $this->setHeader('X-Icinga-Notification', implode('&', $notificationList), true);
+ }
+ } else {
+ if ($redirectUrl !== null) {
+ $this->setRedirect($redirectUrl->getAbsoluteUrl());
+ }
+ }
+
+ if (! $this->getHeader('Content-Type', true)) {
+ $this->setHeader('Content-Type', static::DEFAULT_CONTENT_TYPE);
+ }
+ }
+
+ /**
+ * Redirect to the given URL and exit immediately
+ *
+ * @param string|Url $url
+ */
+ public function redirectAndExit($url)
+ {
+ $this->setRedirectUrl($url);
+
+ $session = Session::getSession();
+ if ($session->hasChanged()) {
+ $session->write();
+ }
+
+ $this->sendHeaders();
+ exit;
+ }
+
+ /**
+ * Send the cookies to the client
+ */
+ public function sendCookies()
+ {
+ foreach ($this->getCookies() as $cookie) {
+ /** @var Cookie $cookie */
+ setcookie(
+ $cookie->getName(),
+ $cookie->getValue() ?? '',
+ $cookie->getExpire() ?? 0,
+ $cookie->getPath(),
+ $cookie->getDomain() ?? '',
+ $cookie->isSecure(),
+ $cookie->isHttpOnly() ?? true
+ );
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function sendHeaders()
+ {
+ $this->prepare();
+ if (! $this->getRequest()->isApiRequest()) {
+ $this->sendCookies();
+ }
+ return parent::sendHeaders();
+ }
+
+ /**
+ * Copies non-body-related response data from $response
+ *
+ * @param Response $response
+ *
+ * @return $this
+ */
+ protected function copyMetaDataFrom(self $response)
+ {
+ $this->_headers = $response->_headers;
+ $this->_headersRaw = $response->_headersRaw;
+ $this->_httpResponseCode = $response->_httpResponseCode;
+ $this->headersSentThrowsException = $response->headersSentThrowsException;
+ return $this;
+ }
+}
diff --git a/library/Icinga/Web/Response/JsonResponse.php b/library/Icinga/Web/Response/JsonResponse.php
new file mode 100644
index 0000000..f914f2c
--- /dev/null
+++ b/library/Icinga/Web/Response/JsonResponse.php
@@ -0,0 +1,239 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Web\Response;
+
+use Icinga\Util\Json;
+use Zend_Controller_Action_HelperBroker;
+use Icinga\Web\Response;
+
+/**
+ * HTTP response in JSON format
+ */
+class JsonResponse extends Response
+{
+ /**
+ * {@inheritdoc}
+ */
+ const DEFAULT_CONTENT_TYPE = 'application/json';
+
+ /**
+ * Status identifier for failed API calls due to an error on the server
+ *
+ * @var string
+ */
+ const STATUS_ERROR = 'error';
+
+ /**
+ * Status identifier for rejected API calls most due to invalid data or call conditions
+ *
+ * @var string
+ */
+ const STATUS_FAIL = 'fail';
+
+ /**
+ * Status identifier for successful API requests
+ *
+ * @var string
+ */
+ const STATUS_SUCCESS = 'success';
+
+ /**
+ * JSON encoding options
+ *
+ * @var int
+ */
+ protected $encodingOptions = 0;
+
+ /**
+ * Whether to automatically sanitize invalid UTF-8 (if any)
+ *
+ * @var bool
+ */
+ protected $autoSanitize = false;
+
+ /**
+ * Error message if the API call failed due to a server error
+ *
+ * @var string|null
+ */
+ protected $errorMessage;
+
+ /**
+ * Fail data for rejected API calls
+ *
+ * @var array|null
+ */
+ protected $failData;
+
+ /**
+ * API request status
+ *
+ * @var string
+ */
+ protected $status;
+
+ /**
+ * Success data for successful API requests
+ *
+ * @var array|null
+ */
+ protected $successData;
+
+ /**
+ * Get the JSON encoding options
+ *
+ * @return int
+ */
+ public function getEncodingOptions()
+ {
+ return $this->encodingOptions;
+ }
+
+ /**
+ * Set the JSON encoding options
+ *
+ * @param int $encodingOptions
+ *
+ * @return $this
+ */
+ public function setEncodingOptions($encodingOptions)
+ {
+ $this->encodingOptions = (int) $encodingOptions;
+ return $this;
+ }
+
+ /**
+ * Get whether to automatically sanitize invalid UTF-8 (if any)
+ *
+ * @return bool
+ */
+ public function getAutoSanitize()
+ {
+ return $this->autoSanitize;
+ }
+
+ /**
+ * Set whether to automatically sanitize invalid UTF-8 (if any)
+ *
+ * @param bool $autoSanitize
+ *
+ * @return $this
+ */
+ public function setAutoSanitize($autoSanitize = true)
+ {
+ $this->autoSanitize = $autoSanitize;
+
+ return $this;
+ }
+
+ /**
+ * Get the error message if the API call failed due to a server error
+ *
+ * @return string|null
+ */
+ public function getErrorMessage()
+ {
+ return $this->errorMessage;
+ }
+
+ /**
+ * Set the error message if the API call failed due to a server error
+ *
+ * @param string $errorMessage
+ *
+ * @return $this
+ */
+ public function setErrorMessage($errorMessage)
+ {
+ $this->errorMessage = (string) $errorMessage;
+ $this->status = static::STATUS_ERROR;
+ return $this;
+ }
+
+ /**
+ * Get the fail data for rejected API calls
+ *
+ * @return array|null
+ */
+ public function getFailData()
+ {
+ return (! is_array($this->failData) || empty($this->failData)) ? null : $this->failData;
+ }
+
+ /**
+ * Set the fail data for rejected API calls
+ *
+ * @param array $failData
+ *
+ * @return $this
+ */
+ public function setFailData(array $failData)
+ {
+ $this->failData = $failData;
+ $this->status = static::STATUS_FAIL;
+ return $this;
+ }
+
+ /**
+ * Get the data for successful API requests
+ *
+ * @return array|null
+ */
+ public function getSuccessData()
+ {
+ return (! is_array($this->successData) || empty($this->successData)) ? null : $this->successData;
+ }
+
+ /**
+ * Set the data for successful API requests
+ *
+ * @param array $successData
+ *
+ * @return $this
+ */
+ public function setSuccessData(array $successData = null)
+ {
+ $this->successData = $successData;
+ $this->status = static::STATUS_SUCCESS;
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function outputBody()
+ {
+ $body = array(
+ 'status' => $this->status
+ );
+ switch ($this->status) {
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case static::STATUS_ERROR:
+ $body['message'] = $this->getErrorMessage();
+ // Fallthrough
+ case static::STATUS_FAIL:
+ $failData = $this->getFailData();
+ if ($failData !== null || $this->status === static::STATUS_FAIL) {
+ $body['data'] = $failData;
+ }
+ break;
+ case static::STATUS_SUCCESS:
+ $body['data'] = $this->getSuccessData();
+ break;
+ }
+ echo $this->getAutoSanitize()
+ ? Json::sanitize($body, $this->getEncodingOptions())
+ : Json::encode($body, $this->getEncodingOptions());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function sendResponse()
+ {
+ Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);
+ parent::sendResponse();
+ exit;
+ }
+}