diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
commit | 8ca6cc32b2c789a3149861159ad258f2cb9491e3 (patch) | |
tree | 2492de6f1528dd44eaa169a5c1555026d9cb75ec /library/Icinga/Web/Response | |
parent | Initial commit. (diff) | |
download | icingaweb2-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.php | 429 | ||||
-rw-r--r-- | library/Icinga/Web/Response/JsonResponse.php | 239 |
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; + } +} |