diff --git a/ChangeLog b/ChangeLog
index 65cc9cf577..0acc4f5fc7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,28 @@
phpMyAdmin - ChangeLog
======================
+4.8.3 (2018-08-22)
+- issue #14314 Error when naming a database '0'
+- issue #14333 Fix NULL as default not shown
+- issue #14229 Fixes issue with recent table list
+- issue #14045 Fix slow performance on DB structure filtering
+- issue #14327 Fix Editing server variable not showing save or cancel option
+- issue #14377 Populate options for view create and edit
+- issue #14171 2FA configuration fails if PHP doesn't have GD support
+- issue #14390 Can't unhide tables
+- issue #14382 "Visualize GIS data" icon missing
+- issue #14435 Event scheduler status toggle doesn't work
+- issue #14365 View not working on multiple servers
+- issue #14207 Partition actions in table structure do not work
+- issue #14375 Fixes ERR_BLOCKED_BY_XSS_AUDITOR on export table
+- issue #14552 Blank message shown instead of MySQL error when adding trigger and other locations
+- issue #14525 Fix PHP 7.3 warning: "continue" in "switch" is equal to "break"
+- issue #14554 Icon missing when creating a new trigger, routine, and event
+- issue #14422 Table comment not showing since 4.8.1
+- issue #14426 Drop table doesn't work when you copy tables to another database
+- issue #14581 Escaped HTML in 'Add a new server' setup
+- issue #14548 [security] HTML injection in import warning messages, see PMASA-2018-5
+
4.8.2 (2018-06-21)
- issue #14370 WHERE 0 causes Fatal error
- issue #14225 Fix missing index icon
diff --git a/README b/README
index 614f90c8c0..10f5102d09 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
phpMyAdmin - Readme
===================
-Version 4.8.2
+Version 4.8.3
A web interface for MySQL and MariaDB.
diff --git a/doc/conf.py b/doc/conf.py
index 09b1740027..669ae7a9e6 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -51,7 +51,7 @@ copyright = u'2012 - 2018, The phpMyAdmin devel team'
# built documents.
#
# The short X.Y version.
-version = '4.8.2'
+version = '4.8.3'
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/js/functions.js b/js/functions.js
index 698dfb2208..0cbb39e4ec 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -155,7 +155,7 @@ function PMA_addDatepicker ($this_element, type, options) {
}
}
};
- if (type == "time") {
+ if (type == 'time') {
$this_element.timepicker($.extend(defaultOptions, options));
// Add a tip regarding entering MySQL allowed-values for TIME data-type
PMA_tooltip($this_element, 'input', PMA_messages.strMysqlAllowedValuesTipTime);
@@ -674,7 +674,7 @@ function confirmLink (theLink, theSqlQuery) {
if (is_confirmed) {
if (typeof(theLink.href) !== 'undefined') {
theLink.href += PMA_commonParams.get('arg_separator') + 'is_js_confirmed=1';
- } else if (typeof(theLink.form) != 'undefined') {
+ } else if (typeof(theLink.form) !== 'undefined') {
theLink.form.action += '?is_js_confirmed=1';
}
}
@@ -3738,9 +3738,9 @@ function indexEditorDialog (url, title, callback_success, callback_failure) {
var $form = $('#index_frm');
var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
PMA_prepareForAjaxRequest($form);
- //User wants to submit the form
- $.post($form.attr('action'), $form.serialize() + PMA_commonParams.get('arg_separator') + "do_save_data=1", function (data) {
- var $sqlqueryresults = $(".sqlqueryresults");
+ // User wants to submit the form
+ $.post($form.attr('action'), $form.serialize() + PMA_commonParams.get('arg_separator') + 'do_save_data=1', function (data) {
+ var $sqlqueryresults = $('.sqlqueryresults');
if ($sqlqueryresults.length !== 0) {
$sqlqueryresults.remove();
}
@@ -4032,8 +4032,8 @@ var toggleButton = function ($obj) {
addClass = 'on';
}
- var params = { 'ajax_request': true };
- $.post(url, params, function (data) {
+ var parts = url.split('?');
+ $.post(parts[0], parts[1] + '&ajax_request=true', function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxRemoveMessage($msg);
$container
@@ -4543,7 +4543,8 @@ function PMA_createViewDialog ($this) {
var $msg = PMA_ajaxShowMessage();
var syntaxHighlighter = null;
var sep = PMA_commonParams.get('arg_separator');
- $.get($this.attr('href') + sep + 'ajax_request=1' + sep + 'ajax_dialog=1', function (data) {
+ params = $this.getPostData();
+ $.get($this.attr('href') + sep + 'ajax_request=1' + sep + 'ajax_dialog=1' + sep + params, function (data) {
if (typeof data !== 'undefined' && data.success === true) {
PMA_ajaxRemoveMessage($msg);
var buttonOptions = {};
@@ -4700,18 +4701,20 @@ $(document).on('keyup', '#filterText', function () {
var count = 0;
$('[data-filter-row]').each(function () {
var $row = $(this);
- console.log($row);
/* Can not use data() here as it does magic conversion to int for numeric values */
if ($row.attr('data-filter-row').indexOf(filterInput) > -1) {
count += 1;
$row.show();
- $row.find('input.checkall').removeClass('row-hidden').trigger('change');
+ $row.find('input.checkall').removeClass('row-hidden');
} else {
$row.hide();
- $row.find('input.checkall').addClass('row-hidden').prop('checked', false).trigger('change');
+ $row.find('input.checkall').addClass('row-hidden').prop('checked', false);
$row.removeClass('marked');
}
});
+ setTimeout(function () {
+ $(checkboxes_sel).trigger('change');
+ }, 300);
$('#filter-rows-count').html(count);
});
AJAX.registerOnload('functions.js', function () {
@@ -4940,7 +4943,7 @@ AJAX.registerOnload('functions.js', function () {
* .attr(name, value) - Sets a particular attribute of the IMG
* tag to the given value
*/
-function PMA_getImage(image, alternate, attributes) {
+function PMA_getImage (image, alternate, attributes) {
// custom image object, it will eventually be returned by this functions
var retval = {
data: {
@@ -5020,18 +5023,17 @@ function PMA_getImage(image, alternate, attributes) {
* @param {object} value Configuration value.
* @param {boolean} only_local Configuration type.
*/
-function configSet(key, value, only_local)
-{
+function configSet (key, value, only_local) {
only_local = (typeof only_local !== 'undefined') ? only_local : false;
var serialized = JSON.stringify(value);
localStorage.setItem(key, serialized);
$.ajax({
- url: "ajax.php",
- type: "POST",
- dataType: "json",
+ url: 'ajax.php',
+ type: 'POST',
+ dataType: 'json',
data: {
key: key,
- type: "config-set",
+ type: 'config-set',
server: PMA_commonParams.get('server'),
value: serialized,
},
@@ -5058,8 +5060,7 @@ function configSet(key, value, only_local)
*
* @return {object} Configuration value.
*/
-function configGet(key, cached)
-{
+function configGet (key, cached) {
cached = (typeof cached !== 'undefined') ? cached : true;
var value = localStorage.getItem(key);
if (cached && value !== undefined && value !== null) {
@@ -5073,11 +5074,11 @@ function configGet(key, cached)
// processing cannot continue until that value is found.
// Another solution is to provide a callback as a parameter.
async: false,
- url: "ajax.php",
- type: "POST",
- dataType: "json",
+ url: 'ajax.php',
+ type: 'POST',
+ dataType: 'json',
data: {
- type: "config-get",
+ type: 'config-get',
server: PMA_commonParams.get('server'),
key: key
},
@@ -5097,7 +5098,7 @@ function configGet(key, cached)
/**
* Return POST data as stored by Util::linkOrButton
*/
-jQuery.fn.getPostData = function() {
+jQuery.fn.getPostData = function () {
var dataPost = this.attr('data-post');
// Strip possible leading ?
if (dataPost !== undefined && dataPost.substring(0,1) == '?') {
diff --git a/js/server_variables.js b/js/server_variables.js
index af4812acf6..6b7f01faf1 100644
--- a/js/server_variables.js
+++ b/js/server_variables.js
@@ -14,7 +14,7 @@ AJAX.registerOnload('server_variables.js', function () {
var $cancelLink = $('a.cancelLink');
$('#serverVariables').find('.var-name').find('a').append(
- $('#docImage').clone().show()
+ $('#docImage').clone().css('display', 'inline-block')
);
/* Launches the variable editor */
@@ -29,11 +29,11 @@ AJAX.registerOnload('server_variables.js', function () {
var $cell = $link.parent();
var $valueCell = $link.parents('.var-row').find('.var-value');
var varName = $link.data('variable');
- var $mySaveLink = $saveLink.clone().show();
- var $myCancelLink = $cancelLink.clone().show();
+
+ var $mySaveLink = $saveLink.clone().css('display', 'inline-block');
+ var $myCancelLink = $cancelLink.clone().css('display', 'inline-block');
var $msgbox = PMA_ajaxShowMessage();
var $myEditLink = $cell.find('a.editLink');
-
$cell.addClass('edit'); // variable is being edited
$myEditLink.remove(); // remove edit link
@@ -87,7 +87,9 @@ AJAX.registerOnload('server_variables.js', function () {
);
// Save and replace content
$cell
- .html($links);
+ .html($links)
+ .children()
+ .css('display', 'flex');
$valueCell
.data('content', $valueCell.html())
.html($editor)
diff --git a/js/tbl_structure.js b/js/tbl_structure.js
index bb26f3b8bb..42b4f9ac4e 100644
--- a/js/tbl_structure.js
+++ b/js/tbl_structure.js
@@ -421,10 +421,7 @@ AJAX.registerOnload('tbl_structure.js', function () {
var $link = $(this);
function submitPartitionAction (url) {
- var params = {
- 'ajax_request' : true,
- 'ajax_page_request' : true
- };
+ var params = 'ajax_request=true&ajax_page_request=true&' + $link.getPostData();
PMA_ajaxShowMessage();
AJAX.source = $link;
$.post(url, params, AJAX.responseHandler);
diff --git a/libraries/classes/Config.php b/libraries/classes/Config.php
index 0c8d6642b0..41758bd5e9 100644
--- a/libraries/classes/Config.php
+++ b/libraries/classes/Config.php
@@ -116,7 +116,7 @@ class Config
*/
public function checkSystem()
{
- $this->set('PMA_VERSION', '4.8.2');
+ $this->set('PMA_VERSION', '4.8.3');
/* Major version */
$this->set(
'PMA_MAJOR_VERSION',
diff --git a/libraries/classes/Config/FormDisplay.php b/libraries/classes/Config/FormDisplay.php
index 9cc114da6e..4bfc82d316 100644
--- a/libraries/classes/Config/FormDisplay.php
+++ b/libraries/classes/Config/FormDisplay.php
@@ -655,7 +655,8 @@ class FormDisplay
if (! $successfully_validated) {
$this->_errors[$work_path][] = __('Incorrect value!');
$result = false;
- continue;
+ // "continue" for the $form->fields foreach-loop
+ continue 2;
}
break;
case 'string':
diff --git a/libraries/classes/Controllers/Server/ServerDatabasesController.php b/libraries/classes/Controllers/Server/ServerDatabasesController.php
index 800f714339..67128347a5 100644
--- a/libraries/classes/Controllers/Server/ServerDatabasesController.php
+++ b/libraries/classes/Controllers/Server/ServerDatabasesController.php
@@ -72,7 +72,7 @@ class ServerDatabasesController extends Controller
include_once 'libraries/replication.inc.php';
- if (! empty($_POST['new_db'])
+ if (isset($_POST['new_db'])
&& $response->isAjax()
) {
$this->createDatabaseAction();
diff --git a/libraries/classes/DatabaseInterface.php b/libraries/classes/DatabaseInterface.php
index 36695978ba..095545020f 100644
--- a/libraries/classes/DatabaseInterface.php
+++ b/libraries/classes/DatabaseInterface.php
@@ -876,7 +876,7 @@ class DatabaseInterface
AS SCHEMA_DATA_FREE';
}
$sql .= '
- FROM `information_schema`.SCHEMATA s';
+ FROM `information_schema`.SCHEMATA s ';
if ($force_stats) {
$sql .= '
LEFT JOIN `information_schema`.TABLES t
diff --git a/libraries/classes/Display/Results.php b/libraries/classes/Display/Results.php
index 84c8c3f7d9..2d815eff8e 100644
--- a/libraries/classes/Display/Results.php
+++ b/libraries/classes/Display/Results.php
@@ -5019,7 +5019,9 @@ class Results
'tbl_gis_visualization.php'
. Url::getCommon($_url_params),
Util::getIcon(
- 'b_globe.gif', __('Visualize GIS data'), true
+ 'b_globe',
+ __('Visualize GIS data'),
+ true
)
)
. "\n";
diff --git a/libraries/classes/Export.php b/libraries/classes/Export.php
index 1f48b5f0c9..c250be0e73 100644
--- a/libraries/classes/Export.php
+++ b/libraries/classes/Export.php
@@ -520,11 +520,11 @@ class Export
foreach($_POST as $name => $value) {
if (is_array($value)) {
foreach($value as $val) {
- $refreshButton .= '';
+ $refreshButton .= '';
}
}
else {
- $refreshButton .= '';
+ $refreshButton .= '';
}
}
$refreshButton .= '';
diff --git a/libraries/classes/Header.php b/libraries/classes/Header.php
index d5bfb98b68..f989d85235 100644
--- a/libraries/classes/Header.php
+++ b/libraries/classes/Header.php
@@ -474,7 +474,7 @@ class Header
$retval .= '
';
$retval .= $this->getMessage();
}
- if ($this->_isEnabled && isset($_REQUEST['recent_table']) && strlen($_REQUEST['recent_table'])) {
+ if ($this->_isEnabled && empty($_REQUEST['recent_table'])) {
$retval .= $this->_addRecentTable(
$GLOBALS['db'],
$GLOBALS['table']
diff --git a/libraries/classes/MultSubmits.php b/libraries/classes/MultSubmits.php
index 915ef9766d..fb694a28b7 100644
--- a/libraries/classes/MultSubmits.php
+++ b/libraries/classes/MultSubmits.php
@@ -401,7 +401,7 @@ class MultSubmits
$html .= '
';
$html .= '
';
$html .= '
';
- $html .= '
';
+ $html .= '
';
$html .= '
';
$html .= '
';
$html .= '
';
diff --git a/libraries/classes/Navigation/Navigation.php b/libraries/classes/Navigation/Navigation.php
index c4a297bee6..146860f6b1 100644
--- a/libraries/classes/Navigation/Navigation.php
+++ b/libraries/classes/Navigation/Navigation.php
@@ -233,8 +233,8 @@ class Navigation
$html .= '
'
- . Util::getIcon('show.png', __('Show'))
- . ' | ';
+ . Util::getIcon('show', __('Show'))
+ . '';
}
$html .= '';
$first = false;
diff --git a/libraries/classes/Plugins/TwoFactor/Application.php b/libraries/classes/Plugins/TwoFactor/Application.php
index 3056af3e46..c739b98080 100644
--- a/libraries/classes/Plugins/TwoFactor/Application.php
+++ b/libraries/classes/Plugins/TwoFactor/Application.php
@@ -91,15 +91,30 @@ class Application extends TwoFactorPlugin
public function setup()
{
$secret = $this->_twofactor->config['settings']['secret'];
- $inlineUrl = $this->_google2fa->getQRCodeInline(
- 'phpMyAdmin (' . $this->getAppId(false) . ')',
- $this->_twofactor->user,
- $secret
- );
- return Template::get('login/twofactor/application_configure')->render([
- 'image' => $inlineUrl,
- 'secret' => $secret
- ]);
+ $renderArray = ['secret' => $secret];
+ if (extension_loaded('gd')) {
+ $inlineUrl = $this->_google2fa->getQRCodeInline(
+ 'phpMyAdmin (' . $this->getAppId(false) . ')',
+ $this->_twofactor->user,
+ $secret
+ );
+ $renderArray['image'] = $inlineUrl;
+ } else {
+ $inlineUrl = $this->_google2fa->getQRCodeUrl(
+ 'phpMyAdmin (' . $this->getAppId(false) . ')',
+ $this->_twofactor->user,
+ $secret
+ );
+ trigger_error(
+ __(
+ 'The gd PHP extension was not found.'
+ . ' The QRcode can not be displayed without the gd PHP extension.'
+ ),
+ E_USER_WARNING
+ );
+ $renderArray['url'] = $inlineUrl;
+ }
+ return Template::get('login/twofactor/application_configure')->render($renderArray);
}
/**
diff --git a/libraries/classes/Rte/Events.php b/libraries/classes/Rte/Events.php
index c47ca5f104..3f10c638c2 100644
--- a/libraries/classes/Rte/Events.php
+++ b/libraries/classes/Rte/Events.php
@@ -123,7 +123,7 @@ class Events
htmlspecialchars($drop_item)
)
. '
'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError();
} else {
$result = $GLOBALS['dbi']->tryQuery($item_query);
if (! $result) {
@@ -132,7 +132,7 @@ class Events
htmlspecialchars($item_query)
)
. '
'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError();
// We dropped the old item, but were unable to create
// the new one. Try to restore the backup query
$result = $GLOBALS['dbi']->tryQuery($create_item);
@@ -163,7 +163,7 @@ class Events
htmlspecialchars($item_query)
)
. '
'
- . __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
+ . __('MySQL said: ') . $GLOBALS['dbi']->getError();
} else {
$message = Message::success(
__('Event %1$s has been created.')
diff --git a/libraries/classes/Rte/Footer.php b/libraries/classes/Rte/Footer.php
index 43dbb8b63c..2fdb2583df 100644
--- a/libraries/classes/Rte/Footer.php
+++ b/libraries/classes/Rte/Footer.php
@@ -30,7 +30,7 @@ class Footer
{
global $db, $table, $url_query;
- $icon = mb_strtolower($name) . '_add.png';
+ $icon = mb_strtolower($name) . '_add';
$retval = "";
$retval .= "\n";
$retval .= "