3 declare(strict_types
=1);
5 namespace PhpMyAdmin\Controllers\Server
;
8 use PhpMyAdmin\Controllers\AbstractController
;
9 use PhpMyAdmin\DatabaseInterface
;
10 use PhpMyAdmin\Html\Generator
;
11 use PhpMyAdmin\Response
;
12 use PhpMyAdmin\Template
;
14 use Williamdes\MariaDBMySQLKBS\KBException
;
15 use Williamdes\MariaDBMySQLKBS\Search
as KBSearch
;
17 use function htmlspecialchars
;
19 use function in_array
;
20 use function is_numeric
;
21 use function mb_strtolower
;
23 use function preg_match
;
24 use function str_replace
;
25 use function strtolower
;
29 * Handles viewing and editing server variables
31 class VariablesController
extends AbstractController
33 /** @var DatabaseInterface */
37 * @param Response $response
38 * @param DatabaseInterface $dbi
40 public function __construct($response, Template
$template, $dbi)
42 parent
::__construct($response, $template);
46 public function index(): void
48 $params = ['filter' => $_GET['filter'] ??
null];
52 $filterValue = ! empty($params['filter']) ?
$params['filter'] : '';
54 $this->addScriptFiles(['server/variables.js']);
57 $serverVarsResult = $this->dbi
->tryQuery('SHOW SESSION VARIABLES;');
58 if ($serverVarsResult !== false) {
59 $serverVarsSession = [];
60 while ($arr = $this->dbi
->fetchRow($serverVarsResult)) {
61 $serverVarsSession[$arr[0]] = $arr[1];
63 $this->dbi
->freeResult($serverVarsResult);
65 $serverVars = $this->dbi
->fetchResult('SHOW GLOBAL VARIABLES;', 0, 1);
67 // list of static (i.e. non-editable) system variables
68 $staticVariables = KBSearch
::getStaticVariables();
70 foreach ($serverVars as $name => $value) {
71 $hasSessionValue = isset($serverVarsSession[$name])
72 && $serverVarsSession[$name] !== $value;
73 $docLink = Generator
::linkToVarDocumentation(
75 $this->dbi
->isMariaDB(),
76 str_replace('_', ' ', $name)
79 [$formattedValue, $isEscaped] = $this->formatVariable($name, $value);
80 if ($hasSessionValue) {
81 [$sessionFormattedValue] = $this->formatVariable(
83 $serverVarsSession[$name]
89 'is_editable' => ! in_array(strtolower($name), $staticVariables),
90 'doc_link' => $docLink,
91 'value' => $formattedValue,
92 'is_escaped' => $isEscaped,
93 'has_session_value' => $hasSessionValue,
94 'session_value' => $sessionFormattedValue ??
null,
99 $this->render('server/variables/index', [
100 'variables' => $variables,
101 'filter_value' => $filterValue,
102 'is_superuser' => $this->dbi
->isSuperuser(),
103 'is_mariadb' => $this->dbi
->isMariaDB(),
108 * Handle the AJAX request for a single variable value
110 * @param array $params Request parameters
112 public function getValue(array $params): void
114 if (! $this->response
->isAjax()) {
118 // Send with correct charset
119 header('Content-Type: text/html; charset=UTF-8');
120 // Do not use double quotes inside the query to avoid a problem
121 // when server is running in ANSI_QUOTES sql_mode
122 $varValue = $this->dbi
->fetchSingleRow(
123 'SHOW GLOBAL VARIABLES WHERE Variable_name=\''
124 . $this->dbi
->escapeString($params['name']) . '\';',
130 $type = KBSearch
::getVariableType($params['name']);
131 if ($type !== 'byte') {
132 throw new KBException('Not a type=byte');
135 $json['message'] = implode(
137 Util
::formatByteDown($varValue[1], 3, 3)
139 } catch (KBException
$e) {
140 $json['message'] = $varValue[1];
143 $this->response
->addJSON($json);
147 * Handle the AJAX request for setting value for a single variable
149 * @param array $vars Request parameters
151 public function setValue(array $vars): void
154 'varName' => $vars['name'],
155 'varValue' => $_POST['varValue'] ??
null,
158 if (! $this->response
->isAjax()) {
162 $value = $params['varValue'];
165 $type = KBSearch
::getVariableType($params['varName']);
166 if ($type !== 'byte' ||
! preg_match(
167 '/^\s*(\d+(\.\d+)?)\s*(mb|kb|mib|kib|gb|gib)\s*$/i',
171 throw new KBException('Not a type=byte or regex not matching');
182 $value = (float) $matches[1] * pow(
184 $exp[mb_strtolower($matches[3])]
186 } catch (KBException
$e) {
187 $value = $this->dbi
->escapeString($value);
190 if (! is_numeric($value)) {
191 $value = "'" . $value . "'";
195 if (! preg_match('/[^a-zA-Z0-9_]+/', $params['varName'])
196 && $this->dbi
->query(
197 'SET GLOBAL ' . $params['varName'] . ' = ' . $value
200 // Some values are rounded down etc.
201 $varValue = $this->dbi
->fetchSingleRow(
202 'SHOW GLOBAL VARIABLES WHERE Variable_name="'
203 . $this->dbi
->escapeString($params['varName'])
207 [$formattedValue, $isHtmlFormatted] = $this->formatVariable(
212 if ($isHtmlFormatted === false) {
213 $json['variable'] = htmlspecialchars($formattedValue);
215 $json['variable'] = $formattedValue;
218 $this->response
->setRequestStatus(false);
219 $json['error'] = __('Setting variable failed');
222 $this->response
->addJSON($json);
228 * @param string $name variable name
229 * @param int|string $value variable value
231 * @return array formatted string and bool if string is HTML formatted
233 private function formatVariable($name, $value): array
235 $isHtmlFormatted = false;
236 $formattedValue = $value;
238 if (is_numeric($value)) {
240 $type = KBSearch
::getVariableType($name);
241 if ($type !== 'byte') {
242 throw new KBException('Not a type=byte or regex not matching');
245 $isHtmlFormatted = true;
246 $formattedValue = trim(
247 $this->template
->render(
248 'server/variables/format_variable',
250 'valueTitle' => Util
::formatNumber($value, 0),
251 'value' => implode(' ', Util
::formatByteDown($value, 3, 3)),
255 } catch (KBException
$e) {
256 $formattedValue = Util
::formatNumber($value, 0);