aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Response.php
diff options
context:
space:
mode:
authorCharles <sircharlesaze@gmail.com>2020-01-09 10:55:03 +0100
committerCharles <sircharlesaze@gmail.com>2020-01-09 13:09:38 +0100
commit04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa (patch)
tree5c691241355c943a3c68ddb06b8cf8c60aa11319 /srcs/phpmyadmin/libraries/classes/Response.php
parent7e0d85db834d6351ed85d01e5126ac31dc510b86 (diff)
downloadft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.tar.gz
ft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.tar.bz2
ft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.zip
phpmyadmin working
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Response.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Response.php614
1 files changed, 614 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Response.php b/srcs/phpmyadmin/libraries/classes/Response.php
new file mode 100644
index 0000000..be9313b
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Response.php
@@ -0,0 +1,614 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Manages the rendering of pages in PMA
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin;
+
+use PhpMyAdmin\Core;
+use PhpMyAdmin\Footer;
+use PhpMyAdmin\Header;
+use PhpMyAdmin\Message;
+use PhpMyAdmin\OutputBuffering;
+
+/**
+ * Singleton class used to manage the rendering of pages in PMA
+ *
+ * @package PhpMyAdmin
+ */
+class Response
+{
+ /**
+ * Response instance
+ *
+ * @access private
+ * @static
+ * @var Response
+ */
+ private static $_instance;
+ /**
+ * Header instance
+ *
+ * @access private
+ * @var Header
+ */
+ private $_header;
+ /**
+ * HTML data to be used in the response
+ *
+ * @access private
+ * @var string
+ */
+ private $_HTML;
+ /**
+ * An array of JSON key-value pairs
+ * to be sent back for ajax requests
+ *
+ * @access private
+ * @var array
+ */
+ private $_JSON;
+ /**
+ * PhpMyAdmin\Footer instance
+ *
+ * @access private
+ * @var Footer
+ */
+ private $_footer;
+ /**
+ * Whether we are servicing an ajax request.
+ *
+ * @access private
+ * @var bool
+ */
+ private $_isAjax;
+ /**
+ * Whether response object is disabled
+ *
+ * @access private
+ * @var bool
+ */
+ private $_isDisabled;
+ /**
+ * Whether there were any errors during the processing of the request
+ * Only used for ajax responses
+ *
+ * @access private
+ * @var bool
+ */
+ private $_isSuccess;
+ /**
+ * Workaround for PHP bug
+ *
+ * @access private
+ * @var string|bool
+ */
+ private $_CWD;
+
+ /**
+ * @var array<int, string>
+ * @see http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+ */
+ protected static $httpStatusMessages = [
+ // Informational
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+ 102 => 'Processing',
+ 103 => 'Early Hints',
+ // Success
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+ 207 => 'Multi-Status',
+ 208 => 'Already Reported',
+ 226 => 'IM Used',
+ // Redirection
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+ 308 => 'Permanent Redirect',
+ // Client Error
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Payload Too Large',
+ 414 => 'URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 421 => 'Misdirected Request',
+ 422 => 'Unprocessable Entity',
+ 423 => 'Locked',
+ 424 => 'Failed Dependency',
+ 425 => 'Too Early',
+ 426 => 'Upgrade Required',
+ 427 => 'Unassigned',
+ 428 => 'Precondition Required',
+ 429 => 'Too Many Requests',
+ 430 => 'Unassigned',
+ 431 => 'Request Header Fields Too Large',
+ 451 => 'Unavailable For Legal Reasons',
+ // Server Error
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 506 => 'Variant Also Negotiates',
+ 507 => 'Insufficient Storage',
+ 508 => 'Loop Detected',
+ 509 => 'Unassigned',
+ 510 => 'Not Extended',
+ 511 => 'Network Authentication Required',
+ ];
+
+ /**
+ * Creates a new class instance
+ */
+ private function __construct()
+ {
+ if (! defined('TESTSUITE')) {
+ $buffer = OutputBuffering::getInstance();
+ $buffer->start();
+ register_shutdown_function([$this, 'response']);
+ }
+ $this->_header = new Header();
+ $this->_HTML = '';
+ $this->_JSON = [];
+ $this->_footer = new Footer();
+
+ $this->_isSuccess = true;
+ $this->_isDisabled = false;
+ $this->setAjax(! empty($_REQUEST['ajax_request']));
+ $this->_CWD = getcwd();
+ }
+
+ /**
+ * Set the ajax flag to indicate whether
+ * we are servicing an ajax request
+ *
+ * @param bool $isAjax Whether we are servicing an ajax request
+ *
+ * @return void
+ */
+ public function setAjax(bool $isAjax): void
+ {
+ $this->_isAjax = $isAjax;
+ $this->_header->setAjax($this->_isAjax);
+ $this->_footer->setAjax($this->_isAjax);
+ }
+
+ /**
+ * Returns the singleton Response object
+ *
+ * @return Response object
+ */
+ public static function getInstance()
+ {
+ if (empty(self::$_instance)) {
+ self::$_instance = new Response();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Set the status of an ajax response,
+ * whether it is a success or an error
+ *
+ * @param bool $state Whether the request was successfully processed
+ *
+ * @return void
+ */
+ public function setRequestStatus(bool $state): void
+ {
+ $this->_isSuccess = ($state === true);
+ }
+
+ /**
+ * Returns true or false depending on whether
+ * we are servicing an ajax request
+ *
+ * @return bool
+ */
+ public function isAjax(): bool
+ {
+ return $this->_isAjax;
+ }
+
+ /**
+ * Returns the path to the current working directory
+ * Necessary to work around a PHP bug where the CWD is
+ * reset after the initial script exits
+ *
+ * @return string
+ */
+ public function getCWD()
+ {
+ return $this->_CWD;
+ }
+
+ /**
+ * Disables the rendering of the header
+ * and the footer in responses
+ *
+ * @return void
+ */
+ public function disable()
+ {
+ $this->_header->disable();
+ $this->_footer->disable();
+ $this->_isDisabled = true;
+ }
+
+ /**
+ * Returns a PhpMyAdmin\Header object
+ *
+ * @return Header
+ */
+ public function getHeader()
+ {
+ return $this->_header;
+ }
+
+ /**
+ * Returns a PhpMyAdmin\Footer object
+ *
+ * @return Footer
+ */
+ public function getFooter()
+ {
+ return $this->_footer;
+ }
+
+ /**
+ * Add HTML code to the response
+ *
+ * @param string $content A string to be appended to
+ * the current output buffer
+ *
+ * @return void
+ */
+ public function addHTML($content)
+ {
+ if (is_array($content)) {
+ foreach ($content as $msg) {
+ $this->addHTML($msg);
+ }
+ } elseif ($content instanceof Message) {
+ $this->_HTML .= $content->getDisplay();
+ } else {
+ $this->_HTML .= $content;
+ }
+ }
+
+ /**
+ * Add JSON code to the response
+ *
+ * @param mixed $json Either a key (string) or an
+ * array or key-value pairs
+ * @param mixed $value Null, if passing an array in $json otherwise
+ * it's a string value to the key
+ *
+ * @return void
+ */
+ public function addJSON($json, $value = null)
+ {
+ if (is_array($json)) {
+ foreach ($json as $key => $value) {
+ $this->addJSON($key, $value);
+ }
+ } else {
+ if ($value instanceof Message) {
+ $this->_JSON[$json] = $value->getDisplay();
+ } else {
+ $this->_JSON[$json] = $value;
+ }
+ }
+ }
+
+ /**
+ * Renders the HTML response text
+ *
+ * @return string
+ */
+ private function _getDisplay()
+ {
+ // The header may contain nothing at all,
+ // if its content was already rendered
+ // and, in this case, the header will be
+ // in the content part of the request
+ $retval = $this->_header->getDisplay();
+ $retval .= $this->_HTML;
+ $retval .= $this->_footer->getDisplay();
+ return $retval;
+ }
+
+ /**
+ * Sends an HTML response to the browser
+ *
+ * @return void
+ */
+ private function _htmlResponse()
+ {
+ echo $this->_getDisplay();
+ }
+
+ /**
+ * Sends a JSON response to the browser
+ *
+ * @return void
+ */
+ private function _ajaxResponse()
+ {
+ /* Avoid wrapping in case we're disabled */
+ if ($this->_isDisabled) {
+ echo $this->_getDisplay();
+ return;
+ }
+
+ if (! isset($this->_JSON['message'])) {
+ $this->_JSON['message'] = $this->_getDisplay();
+ } elseif ($this->_JSON['message'] instanceof Message) {
+ $this->_JSON['message'] = $this->_JSON['message']->getDisplay();
+ }
+
+ if ($this->_isSuccess) {
+ $this->_JSON['success'] = true;
+ } else {
+ $this->_JSON['success'] = false;
+ $this->_JSON['error'] = $this->_JSON['message'];
+ unset($this->_JSON['message']);
+ }
+
+ if ($this->_isSuccess) {
+ $this->addJSON('title', '<title>' . $this->getHeader()->getPageTitle() . '</title>');
+
+ if (isset($GLOBALS['dbi'])) {
+ $menuHash = $this->getHeader()->getMenu()->getHash();
+ $this->addJSON('menuHash', $menuHash);
+ $hashes = [];
+ if (isset($_REQUEST['menuHashes'])) {
+ $hashes = explode('-', $_REQUEST['menuHashes']);
+ }
+ if (! in_array($menuHash, $hashes)) {
+ $this->addJSON(
+ 'menu',
+ $this->getHeader()
+ ->getMenu()
+ ->getDisplay()
+ );
+ }
+ }
+
+ $this->addJSON('scripts', $this->getHeader()->getScripts()->getFiles());
+ $this->addJSON('selflink', $this->getFooter()->getSelfUrl());
+ $this->addJSON('displayMessage', $this->getHeader()->getMessage());
+
+ $debug = $this->_footer->getDebugMessage();
+ if (empty($_REQUEST['no_debug'])
+ && strlen($debug) > 0
+ ) {
+ $this->addJSON('debug', $debug);
+ }
+
+ $errors = $this->_footer->getErrorMessages();
+ if (strlen($errors) > 0) {
+ $this->addJSON('errors', $errors);
+ }
+ $promptPhpErrors = $GLOBALS['error_handler']->hasErrorsForPrompt();
+ $this->addJSON('promptPhpErrors', $promptPhpErrors);
+
+ if (empty($GLOBALS['error_message'])) {
+ // set current db, table and sql query in the querywindow
+ // (this is for the bottom console)
+ $query = '';
+ $maxChars = $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'];
+ if (isset($GLOBALS['sql_query'])
+ && mb_strlen($GLOBALS['sql_query']) < $maxChars
+ ) {
+ $query = $GLOBALS['sql_query'];
+ }
+ $this->addJSON(
+ 'reloadQuerywindow',
+ [
+ 'db' => Core::ifSetOr($GLOBALS['db'], ''),
+ 'table' => Core::ifSetOr($GLOBALS['table'], ''),
+ 'sql_query' => $query,
+ ]
+ );
+ if (! empty($GLOBALS['focus_querywindow'])) {
+ $this->addJSON('_focusQuerywindow', $query);
+ }
+ if (! empty($GLOBALS['reload'])) {
+ $this->addJSON('reloadNavigation', 1);
+ }
+ $this->addJSON('params', $this->getHeader()->getJsParams());
+ }
+ }
+
+ // Set the Content-Type header to JSON so that jQuery parses the
+ // response correctly.
+ Core::headerJSON();
+
+ $result = json_encode($this->_JSON);
+ if ($result === false) {
+ switch (json_last_error()) {
+ case JSON_ERROR_NONE:
+ $error = 'No errors';
+ break;
+ case JSON_ERROR_DEPTH:
+ $error = 'Maximum stack depth exceeded';
+ break;
+ case JSON_ERROR_STATE_MISMATCH:
+ $error = 'Underflow or the modes mismatch';
+ break;
+ case JSON_ERROR_CTRL_CHAR:
+ $error = 'Unexpected control character found';
+ break;
+ case JSON_ERROR_SYNTAX:
+ $error = 'Syntax error, malformed JSON';
+ break;
+ case JSON_ERROR_UTF8:
+ $error = 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ break;
+ case JSON_ERROR_RECURSION:
+ $error = 'One or more recursive references in the value to be encoded';
+ break;
+ case JSON_ERROR_INF_OR_NAN:
+ $error = 'One or more NAN or INF values in the value to be encoded';
+ break;
+ case JSON_ERROR_UNSUPPORTED_TYPE:
+ $error = 'A value of a type that cannot be encoded was given';
+ break;
+ default:
+ $error = 'Unknown error';
+ break;
+ }
+ echo json_encode([
+ 'success' => false,
+ 'error' => 'JSON encoding failed: ' . $error,
+ ]);
+ } else {
+ echo $result;
+ }
+ }
+
+ /**
+ * Sends an HTML response to the browser
+ *
+ * @return void
+ */
+ public function response()
+ {
+ chdir($this->getCWD());
+ $buffer = OutputBuffering::getInstance();
+ if (empty($this->_HTML)) {
+ $this->_HTML = $buffer->getContents();
+ }
+ if ($this->isAjax()) {
+ $this->_ajaxResponse();
+ } else {
+ $this->_htmlResponse();
+ }
+ $buffer->flush();
+ exit;
+ }
+
+ /**
+ * Wrapper around PHP's header() function.
+ *
+ * @param string $text header string
+ *
+ * @return void
+ */
+ public function header($text)
+ {
+ header($text);
+ }
+
+ /**
+ * Wrapper around PHP's headers_sent() function.
+ *
+ * @return bool
+ */
+ public function headersSent()
+ {
+ return headers_sent();
+ }
+
+ /**
+ * Wrapper around PHP's http_response_code() function.
+ *
+ * @param int $response_code will set the response code.
+ *
+ * @return void
+ */
+ public function httpResponseCode($response_code)
+ {
+ http_response_code($response_code);
+ }
+
+ /**
+ * Sets http response code.
+ *
+ * @param int $responseCode will set the response code.
+ *
+ * @return void
+ */
+ public function setHttpResponseCode(int $responseCode): void
+ {
+ $this->httpResponseCode($responseCode);
+ $header = 'status: ' . $responseCode . ' ';
+ if (isset(static::$httpStatusMessages[$responseCode])) {
+ $header .= static::$httpStatusMessages[$responseCode];
+ } else {
+ $header .= 'Web server is down';
+ }
+ if (PHP_SAPI !== 'cgi-fcgi') {
+ $this->header($header);
+ }
+ }
+
+ /**
+ * Generate header for 303
+ *
+ * @param string $location will set location to redirect.
+ *
+ * @return void
+ */
+ public function generateHeader303($location)
+ {
+ $this->setHttpResponseCode(303);
+ $this->header('Location: ' . $location);
+ if (! defined('TESTSUITE')) {
+ exit;
+ }
+ }
+
+ /**
+ * Configures response for the login page
+ *
+ * @return bool Whether caller should exit
+ */
+ public function loginPage()
+ {
+ /* Handle AJAX redirection */
+ if ($this->isAjax()) {
+ $this->setRequestStatus(false);
+ // redirect_flag redirects to the login page
+ $this->addJSON('redirect_flag', '1');
+ return true;
+ }
+
+ $this->getFooter()->setMinimal();
+ $header = $this->getHeader();
+ $header->setBodyId('loginform');
+ $header->setTitle('phpMyAdmin');
+ $header->disableMenuAndConsole();
+ $header->disableWarnings();
+ return false;
+ }
+}