diff --git a/.gsoc/todo.txt b/.gsoc/todo.txt index 4736039f2..e36b79397 100644 --- a/.gsoc/todo.txt +++ b/.gsoc/todo.txt @@ -1,2 +1,4 @@ restore cache'ing in phpmyadmin.css.php make CSS for darkblue_orange +check input escaping, $cfg is no longer safe to use + diff --git a/export.php b/export.php index 5d487a107..59f57edc8 100644 --- a/export.php +++ b/export.php @@ -246,17 +246,20 @@ if ($asfile) { $pma_uri_parts = parse_url($cfg['PmaAbsoluteUri']); if ($export_type == 'server') { if (isset($remember_template)) { - $GLOBALS['PMA_Config']->setCookie('pma_server_filename_template', $filename_template); + $GLOBALS['PMA_Config']->setUserValue('pma_server_filename_template', + 'Export/file_template_server', $filename_template); } $filename = str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template)); } elseif ($export_type == 'database') { if (isset($remember_template)) { - $GLOBALS['PMA_Config']->setCookie('pma_db_filename_template', $filename_template); + $GLOBALS['PMA_Config']->setUserValue('pma_db_filename_template', + 'Export/file_template_database', $filename_template); } $filename = str_replace('__DB__', $db, str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template))); } else { if (isset($remember_template)) { - $GLOBALS['PMA_Config']->setCookie('pma_table_filename_template', $filename_template); + $GLOBALS['PMA_Config']->setUserValue('pma_table_filename_template', + 'Export/file_template_table', $filename_template); } $filename = str_replace('__TABLE__', $table, str_replace('__DB__', $db, str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template)))); } diff --git a/libraries/Config.class.php b/libraries/Config.class.php index c290e54de..d31c6e23c 100644 --- a/libraries/Config.class.php +++ b/libraries/Config.class.php @@ -24,6 +24,11 @@ class PMA_Config */ var $default_source = './libraries/config.default.php'; + /** + * @var array default configuration settings + */ + var $default = array(); + /** * @var array configuration settings */ @@ -321,6 +326,7 @@ class PMA_Config $this->default_server = $cfg['Servers'][1]; unset($cfg['Servers']); + $this->default = $cfg; $this->settings = PMA_array_merge_recursive($this->settings, $cfg); $this->error_config_default_file = false; @@ -431,8 +437,8 @@ class PMA_Config // cache user preferences, use database only when needed if (!isset($_SESSION['cache']['userprefs']) || $_SESSION['cache']['config_mtime'] < $config_mtime) { + // load required libraries require_once './libraries/user_preferences.lib.php'; - require_once './libraries/config/config_functions.lib.php'; $prefs = PMA_load_userprefs(); $_SESSION['cache']['userprefs'] = PMA_apply_userprefs($prefs['config_data']); $_SESSION['cache']['userprefs_mtime'] = $prefs['mtime']; @@ -447,7 +453,49 @@ class PMA_Config } $this->settings = PMA_array_merge_recursive($this->settings, $config_data); $GLOBALS['cfg'] = PMA_array_merge_recursive($GLOBALS['cfg'], $config_data); - $this->set('user_preferences_loaded', true); + $this->set('user_preferences', true); + } + + /** + * Sets config value which is stored in user preferences (if available) or in a cookie + * + * @param $cookie_name + * @param $cfg_path + * @param $new_cfg_value + * @return void + */ + function setUserValue($cookie_name, $cfg_path, $new_cfg_value) + { + // use permanent user preferences if possible + if ($this->get('user_preferences')) { + require_once './libraries/user_preferences.lib.php'; + PMA_persist_option($cfg_path, $new_cfg_value, PMA_array_read($cfg_path, $this->default)); + } else { + // fall back to cookies + $this->setCookie($cookie_name, $new_cfg_value, PMA_array_read($cfg_path, $this->settings)); + } + } + + /** + * Reads value stored by {@link setUserValue()} + * + * @param $cookie_name + * @param $cfg_value + * @return + */ + function getUserValue($cookie_name, $cfg_value) + { + $cookie_exists = isset($_COOKIE) && !empty($_COOKIE[$cookie_name]); + if ($this->get('user_preferences')) { + // user preferences value exists, remove cookie + if ($cookie_exists) { + $this->removeCookie($cookie_name); + } + } else if ($cookie_exists) { + return $_COOKIE[$cookie_name]; + } + // return value from $cfg array + return $cfg_value; } /** diff --git a/libraries/config/config_functions.lib.php b/libraries/config/config_functions.lib.php index 3c83bb730..8867c0654 100644 --- a/libraries/config/config_functions.lib.php +++ b/libraries/config/config_functions.lib.php @@ -6,91 +6,6 @@ * @package phpMyAdmin */ -/** - * Returns value of an element in $array given by $path. - * $path is a string describing position of an element in an associative array, - * eg. Servers/1/host refers to $array[Servers][1][host] - * - * @param string $path - * @param array $array - * @param mixed $default - * @return mixed array element or $default - */ -function PMA_array_read($path, $array, $default = null) -{ - $keys = explode('/', $path); - $value =& $array; - foreach ($keys as $key) { - if (!isset($value[$key])) { - return $default; - } - $value =& $value[$key]; - } - return $value; -} - -/** - * Stores value in an array - * - * @param string $path - * @param array &$array - * @param mixed $value - */ -function PMA_array_write($path, &$array, $value) -{ - $keys = explode('/', $path); - $last_key = array_pop($keys); - $a =& $array; - foreach ($keys as $key) { - if (!isset($a[$key])) { - $a[$key] = array(); - } - $a =& $a[$key]; - } - $a[$last_key] = $value; -} - -/** - * Removes value from an array - * - * @param string $path - * @param array &$array - * @param mixed $value - */ -function PMA_array_remove($path, &$array) -{ - $keys = explode('/', $path); - $keys_last = array_pop($keys); - $path = array(); - $depth = 0; - - $path[0] =& $array; - $found = true; - // go as deep as required or possible - foreach ($keys as $key) { - if (!isset($path[$depth][$key])) { - $found = false; - break; - } - $depth++; - $path[$depth] =& $path[$depth-1][$key]; - } - // if element found, remove it - if ($found) { - unset($path[$depth][$keys_last]); - $depth--; - } - - // remove empty nested arrays - for (; $depth >= 0; $depth--) { - if (!isset($path[$depth+1]) || count($path[$depth+1]) == 0) { - unset($path[$depth][$keys[$depth]]); - } else { - break; - } - } -} - /** * Returns sanitized language string, taking into account our special codes * for formatting. Takes variable number of arguments. @@ -197,33 +112,4 @@ function PMA_lang_link_replace($link, $text) return '' . $text . ''; } - -/** - * Reads user preferences field names - * - * @param array|null $forms - * @return array - */ -function PMA_read_userprefs_fieldnames(array $forms = null) -{ - static $names; - - // return cached results - if ($names !== null) { - return $names; - } - if (is_null($forms)) { - $forms = array(); - include 'libraries/config/user_preferences.forms.php'; - } - $names = array(); - foreach ($forms as $formset) { - foreach ($formset as $form) { - foreach ($form as $k => $v) { - $names[] = is_int($k) ? $v : $k; - } - } - } - return $names; -} ?> \ No newline at end of file diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index 39536ffdf..7235ce98d 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -166,8 +166,6 @@ $strConfigForm_Import_export = __('Import / export'); $strConfigForm_Import_export_desc = __('Set import and export directories and compression options'); $strConfigForm_Latex = __('LaTeX'); $strConfigForm_Latex_desc = __('Customize default options'); -$strConfigForm_Ldi = __('CSV using LOAD DATA'); -$strConfigForm_Ldi_desc = __('Customize default options'); $strConfigForm_Left_databases = __('Databases'); $strConfigForm_Left_databases_desc = __('Databases display options'); $strConfigForm_Left_frame = __('Navigation frame'); diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php index f07463cae..a8674d9f0 100644 --- a/libraries/config/setup.forms.php +++ b/libraries/config/setup.forms.php @@ -200,13 +200,14 @@ $forms['Import']['Sql'] = array('Import' => array( 'sql_compatibility', 'sql_no_auto_value_on_zero')); $forms['Import']['Csv'] = array('Import' => array( + ':group:' . __('CSV'), 'csv_replace', 'csv_ignore', 'csv_terminated', 'csv_enclosed', 'csv_escaped', - 'csv_col_names')); -$forms['Import']['Ldi'] = array('Import' => array( + 'csv_col_names', + ':group:' . __('CSV using LOAD DATA'), 'ldi_replace', 'ldi_ignore', 'ldi_terminated', diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php index 4ce0195fa..4e5466810 100644 --- a/libraries/config/user_preferences.forms.php +++ b/libraries/config/user_preferences.forms.php @@ -105,13 +105,14 @@ $forms['Import']['Sql'] = array( 'Import/sql_compatibility', 'Import/sql_no_auto_value_on_zero'); $forms['Import']['Csv'] = array( + ':group:' . __('CSV'), 'Import/csv_replace', 'Import/csv_ignore', 'Import/csv_terminated', 'Import/csv_enclosed', 'Import/csv_escaped', - 'Import/csv_col_names'); -$forms['Import']['Ldi'] = array( + 'Import/csv_col_names', + ':group:' . __('CSV using LOAD DATA'), 'Import/ldi_replace', 'Import/ldi_ignore', 'Import/ldi_terminated', diff --git a/libraries/core.lib.php b/libraries/core.lib.php index 12e28c531..55322367a 100644 --- a/libraries/core.lib.php +++ b/libraries/core.lib.php @@ -539,4 +539,89 @@ function PMA_getenv($var_name) { return ''; } + +/** + * Returns value of an element in $array given by $path. + * $path is a string describing position of an element in an associative array, + * eg. Servers/1/host refers to $array[Servers][1][host] + * + * @param string $path + * @param array $array + * @param mixed $default + * @return mixed array element or $default + */ +function PMA_array_read($path, $array, $default = null) +{ + $keys = explode('/', $path); + $value =& $array; + foreach ($keys as $key) { + if (!isset($value[$key])) { + return $default; + } + $value =& $value[$key]; + } + return $value; +} + +/** + * Stores value in an array + * + * @param string $path + * @param array &$array + * @param mixed $value + */ +function PMA_array_write($path, &$array, $value) +{ + $keys = explode('/', $path); + $last_key = array_pop($keys); + $a =& $array; + foreach ($keys as $key) { + if (!isset($a[$key])) { + $a[$key] = array(); + } + $a =& $a[$key]; + } + $a[$last_key] = $value; +} + +/** + * Removes value from an array + * + * @param string $path + * @param array &$array + * @param mixed $value + */ +function PMA_array_remove($path, &$array) +{ + $keys = explode('/', $path); + $keys_last = array_pop($keys); + $path = array(); + $depth = 0; + + $path[0] =& $array; + $found = true; + // go as deep as required or possible + foreach ($keys as $key) { + if (!isset($path[$depth][$key])) { + $found = false; + break; + } + $depth++; + $path[$depth] =& $path[$depth-1][$key]; + } + // if element found, remove it + if ($found) { + unset($path[$depth][$keys_last]); + $depth--; + } + + // remove empty nested arrays + for (; $depth >= 0; $depth--) { + if (!isset($path[$depth+1]) || count($path[$depth+1]) == 0) { + unset($path[$depth][$keys[$depth]]); + } else { + break; + } + } +} ?> diff --git a/libraries/display_export.lib.php b/libraries/display_export.lib.php index 54867f503..5d76d7a38 100644 --- a/libraries/display_export.lib.php +++ b/libraries/display_export.lib.php @@ -172,23 +172,17 @@ echo PMA_pluginGetJavascript($export_list); getUserValue( + 'pma_db_filename_template', + $GLOBALS['cfg']['Export']['file_template_database'])); } elseif ($export_type == 'table') { - if (isset($_COOKIE) && !empty($_COOKIE['pma_table_filename_template'])) { - echo htmlspecialchars($_COOKIE['pma_table_filename_template']); - } else { - echo $GLOBALS['cfg']['Export']['file_template_table']; - } + echo htmlspecialchars($GLOBALS['PMA_Config']->getUserValue( + 'pma_table_filename_template', + $GLOBALS['cfg']['Export']['file_template_table'])); } else { - if (isset($_COOKIE) && !empty($_COOKIE['pma_server_filename_template'])) { - echo htmlspecialchars($_COOKIE['pma_server_filename_template']); - } else { - echo $GLOBALS['cfg']['Export']['file_template_server']; - } + echo htmlspecialchars($GLOBALS['PMA_Config']->getUserValue( + 'pma_server_filename_template', + $GLOBALS['cfg']['Export']['file_template_server'])); } echo '"'; ?> diff --git a/libraries/user_preferences.lib.php b/libraries/user_preferences.lib.php index 71356ced7..90a5a2eb8 100644 --- a/libraries/user_preferences.lib.php +++ b/libraries/user_preferences.lib.php @@ -58,14 +58,13 @@ function PMA_load_userprefs() * @uses PMA_Message::rawError() * @uses PMA_sqlAddslashes() * @uses PMA_getRelationsParam() + * @param array $config_data * @return true|PMA_Message */ -function PMA_save_userprefs() +function PMA_save_userprefs(array $config_array) { $cfgRelation = PMA_getRelationsParam(); - $cf = ConfigFile::getInstance(); - - $config_data = serialize($cf->getConfigArray()); + $config_data = serialize($config_array); $query_table = PMA_backquote($cfgRelation['db']) . '.' . PMA_backquote($cfgRelation['userconfig']); $query = ' @@ -119,4 +118,57 @@ function PMA_apply_userprefs(array $config_data) } return $cfg; } + +/** + * Reads user preferences field names + * + * @param array|null $forms + * @return array + */ +function PMA_read_userprefs_fieldnames(array $forms = null) +{ + static $names; + + // return cached results + if ($names !== null) { + return $names; + } + if (is_null($forms)) { + $forms = array(); + include 'libraries/config/user_preferences.forms.php'; + } + $names = array(); + foreach ($forms as $formset) { + foreach ($formset as $form) { + foreach ($form as $k => $v) { + $names[] = is_int($k) ? $v : $k; + } + } + } + return $names; +} + +/** + * Updates one user preferences option (loads and saves to database). + * + * No validation is done! + * + * @param string $cfg_name + * @param mixed $value + * @return void + */ +function PMA_persist_option($path, $value, $default_value) +{ + $prefs = PMA_load_userprefs(); + if ($value === $default_value) { + if (isset($prefs['config_data'][$path])) { + unset($prefs['config_data'][$path]); + } else { + return; + } + } else { + $prefs['config_data'][$path] = $value; + } + PMA_save_userprefs($prefs['config_data']); +} ?> \ No newline at end of file diff --git a/setup/lib/common.inc.php b/setup/lib/common.inc.php index 5233cb373..99ab535e1 100644 --- a/setup/lib/common.inc.php +++ b/setup/lib/common.inc.php @@ -23,6 +23,7 @@ require_once './libraries/config/config_functions.lib.php'; require_once './libraries/config/messages.inc.php'; require_once './libraries/config/ConfigFile.class.php'; require_once './libraries/url_generating.lib.php'; +require_once './libraries/user_preferences.lib.php'; // use default error handler restore_error_handler(); diff --git a/user_preferences.php b/user_preferences.php index 69f3a318f..de1145283 100644 --- a/user_preferences.php +++ b/user_preferences.php @@ -113,7 +113,7 @@ if (!$form_display->process(false)) { } else { // save settings $old_settings = PMA_load_userprefs(); - $result = PMA_save_userprefs(); + $result = PMA_save_userprefs($cf->getConfigArray()); if ($result === true) { // compute differences and check whether left frame should be refreshed $old_settings = isset($old_settings['config_data'])