diff --git a/.gitignore b/.gitignore index 6841414751..52a98f192f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Upload/save dirs /upload/ /save/ +/tmp/ # For setup script /config/ # ctags @@ -22,8 +23,9 @@ phpmyadmin.wpj .idea .netbeans *.sw[op] -# IIS files +# Web server files web.config +.htaccess # Locales /locale/ # Backups diff --git a/ChangeLog b/ChangeLog index 843ed25048..5e2f3532e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,13 @@ phpMyAdmin - ChangeLog - issue #12485 Do not show warning about short blowfish_secret if none is set - issue #12251 Fixed random logouts due to wrong cookie path - issue #12480 Fixed editing of ENUM/SET/DECIMAL fields structure +- issue #12497 Missing escaping of configuration used in SQL (hide_db and only_db) +- issue #12476 Add error checking in reading advisory rules file +- issue #12477 Add checking missing elements and confirming element types from json_decode +- issue #12251 Automatically save SQL query in browser local storage rather than in cookie +- issue #12292 Unable to edit transformations +- issue #12502 Remove unused paramenter when connecting to MySQLi +- issue #12303 Fix number formatting with different settings of precision in PHP 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/js/functions.js b/js/functions.js index 0304126695..bace1bf56d 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1164,7 +1164,9 @@ function insertQuery(queryType) } return; } else if (queryType == "saved") { - if ($.cookie('auto_saved_sql')) { + if (isStorageSupported('localStorage') && typeof window.localStorage.auto_saved_sql != 'undefined') { + setQuery(window.localStorage.auto_saved_sql); + } else if ($.cookie('auto_saved_sql')) { setQuery($.cookie('auto_saved_sql')); } else { PMA_ajaxShowMessage(PMA_messages.strNoAutoSavedQuery); diff --git a/js/sql.js b/js/sql.js index 8a8ee57320..c379420d31 100644 --- a/js/sql.js +++ b/js/sql.js @@ -36,6 +36,23 @@ function PMA_urlencode(str) } } +/** + * Saves SQL query in local storage or cooie + * + * @param string SQL query + * @return void + */ +function PMA_autosaveSQL(query) +{ + if (query) { + if (isStorageSupported('localStorage')) { + window.localStorage.auto_saved_sql = query; + } else { + $.cookie('auto_saved_sql', query); + } + } +} + /** * Get the field name for the current field. Required to construct the query * for grid editing @@ -135,17 +152,11 @@ AJAX.registerOnload('sql.js', function () { $(function () { if (codemirror_editor) { codemirror_editor.on('change', function () { - var query = codemirror_editor.getValue(); - if (query) { - $.cookie('auto_saved_sql', query); - } + PMA_autosaveSQL(codemirror_editor.getValue()); }); } else { $('#sqlquery').on('input propertychange', function () { - var query = $('#sqlquery').val(); - if (query) { - $.cookie('auto_saved_sql', query); - } + PMA_autosaveSQL($('#sqlquery').val()); }); } }); diff --git a/libraries/Advisor.php b/libraries/Advisor.php index 59742b2f6c..cfe4fa65e5 100644 --- a/libraries/Advisor.php +++ b/libraries/Advisor.php @@ -455,10 +455,20 @@ class Advisor */ public static function parseRulesFile() { - $file = file('libraries/advisory_rules.txt', FILE_IGNORE_NEW_LINES); + $filename = 'libraries/advisory_rules.txt'; + $file = file($filename, FILE_IGNORE_NEW_LINES); + $errors = array(); $rules = array(); $lines = array(); + + if ($file === FALSE) { + $errors[] = __( + 'Error in reading file: The file \'' . $filename .'\' does not exist or is not readable' + ); + return array('rules' => $rules, 'lines' => $lines, 'errors' => $errors); + } + $ruleSyntax = array( 'name', 'formula', 'test', 'issue', 'recommendation', 'justification' ); diff --git a/libraries/Linter.php b/libraries/Linter.php index 422141e615..ed53ce2187 100644 --- a/libraries/Linter.php +++ b/libraries/Linter.php @@ -51,7 +51,7 @@ class Linter // (which is actually a new line) aren't going to be processed at // all. $len = ($str instanceof UtfString) ? - $str->length() : strlen($len); + $str->length() : strlen($str); $lines = array(0); for ($i = 0; $i < $len; ++$i) { diff --git a/libraries/Util.php b/libraries/Util.php index 7b65f5a770..5e2a4a3c5b 100644 --- a/libraries/Util.php +++ b/libraries/Util.php @@ -1604,17 +1604,13 @@ class Util $value = round($value / (self::pow(1000, $d, 'pow') / $dh)) /$dh; $unit = $units[$d]; - // If we don't want any zeros after the comma just add the thousand separator - if ($noTrailingZero) { - $localizedValue = self::localizeNumber( - preg_replace('/(?<=\d)(?=(\d{3})+(?!\d))/', ',', $value) - ); - } else { - //number_format is not multibyte safe, str_replace is safe - $localizedValue = self::localizeNumber( - number_format($value, $digits_right) - ); + // number_format is not multibyte safe, str_replace is safe + $formattedValue = number_format($value, $digits_right); + // If we don't want any zeros, remove them now + if ($noTrailingZero && strpos($formattedValue, '.') !== false) { + $formattedValue = preg_replace('/\.?0+$/', '', $formattedValue); } + $localizedValue = self::localizeNumber($formattedValue); if ($originalValue != 0 && floatval($value) == 0) { return ' <' . self::localizeNumber((1 / self::pow(10, $digits_right))) @@ -4672,7 +4668,7 @@ class Util ->render( array( 'pos' => $pos, - 'unlim_num_rows' => $_REQUEST['unlim_num_rows'], + 'unlim_num_rows' => intval($_REQUEST['unlim_num_rows']), 'rows' => $rows, 'sql_query' => $sql_query, ) diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 9ec0fc32cd..0a04b5e618 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -107,6 +107,13 @@ PMA_checkExtensions(); ini_set('default_charset', 'utf-8'); mb_internal_encoding('utf-8'); +/** + * Set precision to sane value, with higher values + * things behave slightly unexpectedly, for example + * round(1.2, 2) returns 1.199999999999999956. + */ +ini_set('precision', 14); + /** * the relation lib, tracker needs it */ @@ -455,9 +462,15 @@ PMA_setGlobalDbOrTable('table'); */ if (PMA_isValid($_REQUEST['selected_recent_table'])) { $recent_table = json_decode($_REQUEST['selected_recent_table'], true); - $GLOBALS['db'] = $recent_table['db']; + + $GLOBALS['db'] + = (array_key_exists('db', $recent_table) && is_string($recent_table['db'])) ? + $recent_table['db'] : ''; $GLOBALS['url_params']['db'] = $GLOBALS['db']; - $GLOBALS['table'] = $recent_table['table']; + + $GLOBALS['table'] + = (array_key_exists('table', $recent_table) && is_string($recent_table['table'])) ? + $recent_table['table'] : ''; $GLOBALS['url_params']['table'] = $GLOBALS['table']; } diff --git a/libraries/dbi/DBIMysqli.php b/libraries/dbi/DBIMysqli.php index 0b98c85218..f310d9c85b 100644 --- a/libraries/dbi/DBIMysqli.php +++ b/libraries/dbi/DBIMysqli.php @@ -64,7 +64,6 @@ class DBIMysqli implements DBIExtension * @param string $host mysql hostname * @param string $user mysql user name * @param string $password mysql user password - * @param string $dbname database name * @param int $server_port server port * @param string $server_socket server socket * @param int $client_flags client flags of connection @@ -73,7 +72,7 @@ class DBIMysqli implements DBIExtension * @return bool */ private function _realConnect( - $link, $host, $user, $password, $dbname, $server_port, + $link, $host, $user, $password, $server_port, $server_socket, $client_flags = null, $persistent = false ) { global $cfg; @@ -89,7 +88,7 @@ class DBIMysqli implements DBIExtension $host, $user, $password, - $dbname, + '', $server_port, $server_socket ); @@ -99,7 +98,7 @@ class DBIMysqli implements DBIExtension $host, $user, $password, - $dbname, + '', $server_port, $server_socket, $client_flags @@ -185,7 +184,6 @@ class DBIMysqli implements DBIExtension $cfg['Server']['host'], $user, $password, - false, $server_port, $server_socket, $client_flags @@ -201,7 +199,6 @@ class DBIMysqli implements DBIExtension $cfg['Server']['host'], $user, '', - false, $server_port, $server_socket, $client_flags @@ -213,7 +210,6 @@ class DBIMysqli implements DBIExtension $server['host'], $user, $password, - false, $server_port, $server_socket ); diff --git a/libraries/navigation/nodes/Node.php b/libraries/navigation/nodes/Node.php index 0e186c6498..de6b1d2d62 100644 --- a/libraries/navigation/nodes/Node.php +++ b/libraries/navigation/nodes/Node.php @@ -721,7 +721,9 @@ class Node if (!empty($GLOBALS['cfg']['Server']['hide_db'])) { $whereClause .= "AND " . Util::backquote($columnName) - . " NOT REGEXP '" . $GLOBALS['cfg']['Server']['hide_db'] . "' "; + . " NOT REGEXP '" + . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['hide_db'], true) + . "' "; } if (!empty($GLOBALS['cfg']['Server']['only_db'])) { @@ -735,7 +737,7 @@ class Node foreach ($GLOBALS['cfg']['Server']['only_db'] as $each_only_db) { $subClauses[] = " " . Util::backquote($columnName) . " LIKE '" - . $each_only_db . "' "; + . Util::sqlAddSlashes($each_only_db, true) . "' "; } $whereClause .= implode("OR", $subClauses) . ") "; } diff --git a/libraries/sanitizing.lib.php b/libraries/sanitizing.lib.php index c906eeee9e..4591bf3da2 100644 --- a/libraries/sanitizing.lib.php +++ b/libraries/sanitizing.lib.php @@ -166,7 +166,7 @@ function PMA_sanitize($message, $escape = false, $safe = false) '[sup]' => '', '[/sup]' => '', // used in common.inc.php: - '[conferr]' => '', // used in libraries/Util.php '[dochelpicon]' => PMA\libraries\Util::getImage('b_help.png', __('Documentation')), ); diff --git a/po/pt_BR.po b/po/pt_BR.po index 983d9e5522..5d0df4e01c 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -4,8 +4,8 @@ msgstr "" "Project-Id-Version: phpMyAdmin 4.6.5-dev\n" "Report-Msgid-Bugs-To: translators@phpmyadmin.net\n" "POT-Creation-Date: 2016-08-17 11:29+0200\n" -"PO-Revision-Date: 2016-08-22 02:16+0000\n" -"Last-Translator: Lucius Gaitán \n" +"PO-Revision-Date: 2016-08-29 00:24+0000\n" +"Last-Translator: Diego Bemquerer Castro \n" "Language-Team: Portuguese (Brazil) " "\n" "Language: pt_BR\n" @@ -3694,8 +3694,9 @@ msgid "Unknown error in file upload." msgstr "Erro desconhecido no carregamento do arquivo." #: libraries/File.php:424 +#, fuzzy msgid "File is a symbolic link" -msgstr "" +msgstr "O arquivo é um link simbólico" #: libraries/File.php:470 msgid "Error moving the uploaded file, see [doc@faq1-11]FAQ 1.11[/doc]." diff --git a/templates/columns_definitions/transformation_option.phtml b/templates/columns_definitions/transformation_option.phtml index 91d97ca1a0..bb19e3f0b9 100644 --- a/templates/columns_definitions/transformation_option.phtml +++ b/templates/columns_definitions/transformation_option.phtml @@ -5,5 +5,5 @@ size="16" class="textfield" value="" /> \ No newline at end of file + htmlspecialchars($mime_map[$columnMeta['Field']][$options_key]) + : '' ?>" /> diff --git a/test/bootstrap-dist.php b/test/bootstrap-dist.php index 1b2e45059f..0188e49b05 100644 --- a/test/bootstrap-dist.php +++ b/test/bootstrap-dist.php @@ -6,6 +6,13 @@ * @package PhpMyAdmin-test */ +/** + * Set precision to sane value, with higher values + * things behave slightly unexpectedly, for example + * round(1.2, 2) returns 1.199999999999999956. + */ +ini_set('precision', 14); + // Let PHP complain about all errors error_reporting(E_ALL); diff --git a/test/libraries/common/PMA_formatNumberByteDown_test.php b/test/libraries/common/PMA_formatNumberByteDown_test.php index 138db8c49d..604e59b3e3 100644 --- a/test/libraries/common/PMA_formatNumberByteDown_test.php +++ b/test/libraries/common/PMA_formatNumberByteDown_test.php @@ -70,6 +70,30 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase array(0.003, 3, 3, '3 m'), array(-0.003, 6, 0, '-3,000 µ'), array(100.98, 0, 2, '100.98'), + array(21010101, 0, 2, '21,010,101.00'), + array(20000, 2, 2, '20 k'), + array(20011, 2, 2, '20.01 k'), + ); + } + + /** + * Core test for formatNumber + * + * + * @param float $a Value to format + * @param int $b Sensitiveness + * @param int $c Number of decimals to retain + * @param array $d Expected value + * + * @return void + */ + private function assertFormatNumber($a, $b, $c, $d) + { + $this->assertEquals( + $d, + (string) PMA\libraries\Util::formatNumber( + $a, $b, $c, false + ) ); } @@ -87,12 +111,21 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase */ public function testFormatNumber($a, $b, $c, $d) { - $this->assertEquals( - $d, - (string) PMA\libraries\Util::formatNumber( - $a, $b, $c, false - ) - ); + $this->assertFormatNumber($a, $b, $c, $d); + + // Test with various precisions + $old_precision = ini_get('precision'); + ini_set('precision', 20); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 14); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 10); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 5); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', -1); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', $old_precision); } /**