ManageController.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. declare(strict_types=1);
  3. namespace PhpMyAdmin\Controllers\Preferences;
  4. use PhpMyAdmin\Config\ConfigFile;
  5. use PhpMyAdmin\Config\Forms\User\UserFormList;
  6. use PhpMyAdmin\Controllers\AbstractController;
  7. use PhpMyAdmin\Core;
  8. use PhpMyAdmin\File;
  9. use PhpMyAdmin\Message;
  10. use PhpMyAdmin\Relation;
  11. use PhpMyAdmin\Response;
  12. use PhpMyAdmin\Template;
  13. use PhpMyAdmin\ThemeManager;
  14. use PhpMyAdmin\UserPreferences;
  15. use PhpMyAdmin\Util;
  16. use const JSON_PRETTY_PRINT;
  17. use const PHP_URL_PATH;
  18. use const UPLOAD_ERR_OK;
  19. use function array_merge;
  20. use function define;
  21. use function file_exists;
  22. use function is_array;
  23. use function is_uploaded_file;
  24. use function json_decode;
  25. use function json_encode;
  26. use function mb_strpos;
  27. use function mb_substr;
  28. use function parse_url;
  29. use function str_replace;
  30. use function urlencode;
  31. use function var_export;
  32. /**
  33. * User preferences management page.
  34. */
  35. class ManageController extends AbstractController
  36. {
  37. /** @var UserPreferences */
  38. private $userPreferences;
  39. /** @var Relation */
  40. private $relation;
  41. /**
  42. * @param Response $response
  43. */
  44. public function __construct(
  45. $response,
  46. Template $template,
  47. UserPreferences $userPreferences,
  48. Relation $relation
  49. ) {
  50. parent::__construct($response, $template);
  51. $this->userPreferences = $userPreferences;
  52. $this->relation = $relation;
  53. }
  54. public function index(): void
  55. {
  56. global $cf, $error, $filename, $json, $PMA_Config, $lang, $max_upload_size;
  57. global $new_config, $config, $return_url, $form_display, $all_ok, $params, $query, $route;
  58. $cf = new ConfigFile($PMA_Config->baseSettings);
  59. $this->userPreferences->pageInit($cf);
  60. $error = '';
  61. if (isset($_POST['submit_export'], $_POST['export_type']) && $_POST['export_type'] === 'text_file') {
  62. // export to JSON file
  63. $this->response->disable();
  64. $filename = 'phpMyAdmin-config-' . urlencode(Core::getenv('HTTP_HOST')) . '.json';
  65. Core::downloadHeader($filename, 'application/json');
  66. $settings = $this->userPreferences->load();
  67. echo json_encode($settings['config_data'], JSON_PRETTY_PRINT);
  68. return;
  69. }
  70. if (isset($_POST['submit_export'], $_POST['export_type']) && $_POST['export_type'] === 'php_file') {
  71. // export to JSON file
  72. $this->response->disable();
  73. $filename = 'phpMyAdmin-config-' . urlencode(Core::getenv('HTTP_HOST')) . '.php';
  74. Core::downloadHeader($filename, 'application/php');
  75. $settings = $this->userPreferences->load();
  76. echo '/* ' . __('phpMyAdmin configuration snippet') . " */\n\n";
  77. echo '/* ' . __('Paste it to your config.inc.php') . " */\n\n";
  78. foreach ($settings['config_data'] as $key => $val) {
  79. echo '$cfg[\'' . str_replace('/', '\'][\'', $key) . '\'] = ';
  80. echo var_export($val, true) . ";\n";
  81. }
  82. return;
  83. }
  84. if (isset($_POST['submit_get_json'])) {
  85. $settings = $this->userPreferences->load();
  86. $this->response->addJSON('prefs', json_encode($settings['config_data']));
  87. $this->response->addJSON('mtime', $settings['mtime']);
  88. return;
  89. }
  90. if (isset($_POST['submit_import'])) {
  91. // load from JSON file
  92. $json = '';
  93. if (isset($_POST['import_type'], $_FILES['import_file'])
  94. && $_POST['import_type'] === 'text_file'
  95. && $_FILES['import_file']['error'] == UPLOAD_ERR_OK
  96. && is_uploaded_file($_FILES['import_file']['tmp_name'])
  97. ) {
  98. $importHandle = new File($_FILES['import_file']['tmp_name']);
  99. $importHandle->checkUploadedFile();
  100. if ($importHandle->isError()) {
  101. $error = $importHandle->getError();
  102. } else {
  103. // read JSON from uploaded file
  104. $json = $importHandle->getRawContent();
  105. }
  106. } else {
  107. // read from POST value (json)
  108. $json = $_POST['json'] ?? null;
  109. }
  110. // hide header message
  111. $_SESSION['userprefs_autoload'] = true;
  112. $config = json_decode($json, true);
  113. $return_url = $_POST['return_url'] ?? null;
  114. if (! is_array($config)) {
  115. if (! isset($error)) {
  116. $error = __('Could not import configuration');
  117. }
  118. } else {
  119. // sanitize input values: treat them as though
  120. // they came from HTTP POST request
  121. $form_display = new UserFormList($cf);
  122. $new_config = $cf->getFlatDefaultConfig();
  123. if (! empty($_POST['import_merge'])) {
  124. $new_config = array_merge($new_config, $cf->getConfigArray());
  125. }
  126. $new_config = array_merge($new_config, $config);
  127. $_POST_bak = $_POST;
  128. foreach ($new_config as $k => $v) {
  129. $_POST[str_replace('/', '-', (string) $k)] = $v;
  130. }
  131. $cf->resetConfigData();
  132. $all_ok = $form_display->process(true, false);
  133. $all_ok = $all_ok && ! $form_display->hasErrors();
  134. $_POST = $_POST_bak;
  135. if (! $all_ok && isset($_POST['fix_errors'])) {
  136. $form_display->fixErrors();
  137. $all_ok = true;
  138. }
  139. if (! $all_ok) {
  140. // mimic original form and post json in a hidden field
  141. $cfgRelation = $this->relation->getRelationsParam();
  142. echo $this->template->render('preferences/header', [
  143. 'route' => $route,
  144. 'is_saved' => ! empty($_GET['saved']),
  145. 'has_config_storage' => $cfgRelation['userconfigwork'],
  146. ]);
  147. echo $this->template->render('preferences/manage/error', [
  148. 'form_errors' => $form_display->displayErrors(),
  149. 'json' => $json,
  150. 'import_merge' => $_POST['import_merge'] ?? null,
  151. 'return_url' => $return_url,
  152. ]);
  153. return;
  154. }
  155. // check for ThemeDefault
  156. $params = [];
  157. $tmanager = ThemeManager::getInstance();
  158. if (isset($config['ThemeDefault'])
  159. && $tmanager->theme->getId() != $config['ThemeDefault']
  160. && $tmanager->checkTheme($config['ThemeDefault'])
  161. ) {
  162. $tmanager->setActiveTheme($config['ThemeDefault']);
  163. $tmanager->setThemeCookie();
  164. }
  165. if (isset($config['lang'])
  166. && $config['lang'] != $lang
  167. ) {
  168. $params['lang'] = $config['lang'];
  169. }
  170. // save settings
  171. $result = $this->userPreferences->save($cf->getConfigArray());
  172. if ($result === true) {
  173. if ($return_url) {
  174. $query = Util::splitURLQuery($return_url);
  175. $return_url = parse_url($return_url, PHP_URL_PATH);
  176. foreach ($query as $q) {
  177. $pos = mb_strpos($q, '=');
  178. $k = mb_substr($q, 0, (int) $pos);
  179. if ($k === 'token') {
  180. continue;
  181. }
  182. $params[$k] = mb_substr($q, $pos + 1);
  183. }
  184. } else {
  185. $return_url = 'index.php?route=/preferences/manage';
  186. }
  187. // reload config
  188. $PMA_Config->loadUserPreferences();
  189. $this->userPreferences->redirect($return_url ?? '', $params);
  190. return;
  191. }
  192. $error = $result;
  193. }
  194. } elseif (isset($_POST['submit_clear'])) {
  195. $result = $this->userPreferences->save([]);
  196. if ($result === true) {
  197. $params = [];
  198. $PMA_Config->removeCookie('pma_collaction_connection');
  199. $PMA_Config->removeCookie('pma_lang');
  200. $this->userPreferences->redirect('index.php?route=/preferences/manage', $params);
  201. return;
  202. } else {
  203. $error = $result;
  204. }
  205. return;
  206. }
  207. $this->addScriptFiles(['config.js']);
  208. $cfgRelation = $this->relation->getRelationsParam();
  209. echo $this->template->render('preferences/header', [
  210. 'route' => $route,
  211. 'is_saved' => ! empty($_GET['saved']),
  212. 'has_config_storage' => $cfgRelation['userconfigwork'],
  213. ]);
  214. if ($error) {
  215. if (! $error instanceof Message) {
  216. $error = Message::error($error);
  217. }
  218. $error->getDisplay();
  219. }
  220. echo $this->template->render('preferences/manage/main', [
  221. 'error' => $error,
  222. 'max_upload_size' => $max_upload_size,
  223. 'exists_setup_and_not_exists_config' => @file_exists(ROOT_PATH . 'setup/index.php')
  224. && ! @file_exists(CONFIG_FILE),
  225. ]);
  226. if ($this->response->isAjax()) {
  227. $this->response->addJSON('disableNaviSettings', true);
  228. } else {
  229. define('PMA_DISABLE_NAVI_SETTINGS', true);
  230. }
  231. }
  232. }