Merge branch 'QA_4_6'

This commit is contained in:
Michal Čihař 2016-09-19 10:51:50 +02:00
commit 7fc28626fd
11 changed files with 121 additions and 35 deletions

View File

@ -64,6 +64,9 @@ phpMyAdmin - ChangeLog
- issue #12320 Copying a user does not copy usergroup
- issue #12272 Adding a new row with default enum goes to no selection when you want to add more then 2 rows
- issue #12487 Drag and drop import prevents file dropping to blob column file selector on the insert tab
- issue #12554 Absence of scrolling makes it impossible to read longer text values in grid editing
- issue #12530 "Edit routine" crashes when the current user is not the definer, even if privileges are adequate
- issue #12300 Export selective tables by-default dumps Events also
4.6.4 (2016-08-16)
- issue [security] Weaknesses with cookie encryption, see PMASA-2016-29

View File

@ -545,6 +545,16 @@ function toggle_table_select(row) {
}
}
function handleAddProcCheckbox() {
if ($('#table_structure_all').is(':checked') === true
&& $('#table_data_all').is(':checked') === true
) {
$('#checkbox_sql_procedure_function').prop('checked', true);
} else {
$('#checkbox_sql_procedure_function').prop('checked', false);
}
}
AJAX.registerOnload('export.js', function () {
/**
* For SQL plugin, if "CREATE TABLE options" is checked/unchecked, check/uncheck each of its sub-options
@ -584,26 +594,31 @@ AJAX.registerOnload('export.js', function () {
$('input[name="table_select[]"]').on('change', function() {
toggle_table_select($(this).closest('tr'));
check_table_select_all();
handleAddProcCheckbox();
});
$('input[name="table_structure[]"]').on('change', function() {
check_table_selected($(this).closest('tr'));
check_table_select_all();
handleAddProcCheckbox();
});
$('input[name="table_data[]"]').on('change', function() {
check_table_selected($(this).closest('tr'));
check_table_select_all();
handleAddProcCheckbox();
});
$('#table_structure_all').on('change', function() {
toggle_table_select_all_str();
check_selected_tables();
handleAddProcCheckbox();
});
$('#table_data_all').on('change', function() {
toggle_table_select_all_data();
check_selected_tables();
handleAddProcCheckbox();
});
if ($("input[name='export_type']").val() == 'database') {
@ -810,6 +825,8 @@ AJAX.registerOnload('export.js', function () {
toggle_quick_or_custom();
toggle_structure_data_opts();
toggle_sql_include_comments();
check_table_select_all();
handleAddProcCheckbox();
/**
* Initially disables the "Dump some row(s)" sub-options

View File

@ -390,6 +390,8 @@ $js_messages['strDeleting'] = __('Deleting');
$js_messages['MissingReturn']
= __('The definition of a stored function must contain a RETURN statement!');
$js_messages['strExport'] = __('Export');
$js_messages['NoExportable']
= __('No routine is exportable. Required privileges may be lacking.');
/* For ENUM/SET editor*/
$js_messages['enum_editor'] = __('ENUM/SET editor');

View File

@ -128,6 +128,11 @@ RTE.COMMON = {
var count = export_anchors.length;
var returnCount = 0;
// No routine is exportable (due to privilege issues)
if (count === 0) {
PMA_ajaxShowMessage(PMA_messages.NoExportable);
}
export_anchors.each(function () {
$.get($(this).attr('href'), {'ajax_request': true}, function (data) {
returnCount++;
@ -149,6 +154,7 @@ RTE.COMMON = {
} else {
$.get($this.attr('href'), {'ajax_request': true}, showExport);
}
PMA_ajaxRemoveMessage($msg);
function showExport(data) {
if (data.success === true) {

View File

@ -1748,10 +1748,11 @@ class DatabaseInterface
* @param string $db db name
* @param string $which PROCEDURE | FUNCTION | EVENT | VIEW
* @param string $name the procedure|function|event|view name
* @param object $link MySQL link
*
* @return string the definition
*/
public function getDefinition($db, $which, $name)
public function getDefinition($db, $which, $name, $link = null)
{
$returned_field = array(
'PROCEDURE' => 'Create Procedure',
@ -1762,7 +1763,7 @@ class DatabaseInterface
$query = 'SHOW CREATE ' . $which . ' '
. Util::backquote($db) . '.'
. Util::backquote($name);
return($this->fetchValue($query, 0, $returned_field[$which]));
return($this->fetchValue($query, 0, $returned_field[$which], $link));
}
/**

View File

@ -44,15 +44,16 @@ function PMA_RTE_handleExport($export_data)
} else {
$_db = htmlspecialchars(PMA\libraries\Util::backquote($db));
$message = __('Error in processing request:') . ' '
. sprintf(PMA_RTE_getWord('not_found'), $item_name, $_db);
$response = Message::error($message);
. sprintf(PMA_RTE_getWord('no_view'), $item_name, $_db);
$message = Message::error($message);
if ($GLOBALS['is_ajax_request'] == true) {
$response = PMA\libraries\Response::getInstance();
$response->setRequestStatus(false);
$response->addJSON('message', $message);
exit;
} else {
$response->display();
$message->display();
}
}
} // end PMA_RTE_handleExport()
@ -70,6 +71,9 @@ function PMA_EVN_handleExport()
if (! empty($_GET['export_item']) && ! empty($_GET['item_name'])) {
$item_name = $_GET['item_name'];
$export_data = $GLOBALS['dbi']->getDefinition($db, 'EVENT', $item_name);
if (! $export_data) {
$export_data = false;
}
PMA_RTE_handleExport($export_data);
}
} // end PMA_EVN_handleExport()
@ -89,13 +93,20 @@ function PMA_RTN_handleExport()
&& ! empty($_GET['item_type'])
) {
if ($_GET['item_type'] == 'FUNCTION' || $_GET['item_type'] == 'PROCEDURE') {
$export_data = "DELIMITER $$\n"
. $GLOBALS['dbi']->getDefinition(
$rtn_definition
= $GLOBALS['dbi']->getDefinition(
$db,
$_GET['item_type'],
$_GET['item_name']
)
. "$$\nDELIMITER ;\n";
);
if (! $rtn_definition) {
$export_data = false;
} else {
$export_data = "DELIMITER $$\n"
. $rtn_definition
. "$$\nDELIMITER ;\n";
}
PMA_RTE_handleExport($export_data);
}
}

View File

@ -204,9 +204,24 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
$retval .= " </strong>\n";
$retval .= " </td>\n";
$retval .= " <td>\n";
// this is for our purpose to decide whether to
// show the edit link or not, so we need the DEFINER for the routine
$where = "ROUTINE_SCHEMA " . PMA\libraries\Util::getCollateForIS() . "="
. "'" . PMA\libraries\Util::sqlAddSlashes($db) . "' "
. "AND SPECIFIC_NAME='" . PMA\libraries\Util::sqlAddSlashes($routine['name']) . "'"
. "AND ROUTINE_TYPE='" . PMA\libraries\Util::sqlAddSlashes($routine['type']) . "'";
$query = "SELECT `DEFINER` FROM INFORMATION_SCHEMA.ROUTINES WHERE $where;";
$routine_definer = $GLOBALS['dbi']->fetchValue($query, 0, 0, $GLOBALS['controllink']);
$curr_user = $GLOBALS['dbi']->getCurrentUser();
// Since editing a procedure involved dropping and recreating, check also for
// CREATE ROUTINE privilege to avoid lost procedures.
if (PMA\libraries\Util::currentUserHasPrivilege('CREATE ROUTINE', $db)) {
if ((PMA\libraries\Util::currentUserHasPrivilege('CREATE ROUTINE', $db)
&& $curr_user == $routine_definer)
|| $GLOBALS['is_superuser']
) {
$retval .= ' <a ' . $ajax_class['edit']
. ' href="db_routines.php'
. $url_query
@ -233,7 +248,7 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
// otherwise we can execute it directly.
$definition = $GLOBALS['dbi']->getDefinition(
$db, $routine['type'], $routine['name']
$db, $routine['type'], $routine['name'], $GLOBALS['controllink']
);
if ($definition !== false) {
$parser = new SqlParser\Parser($definition);
@ -271,14 +286,21 @@ function PMA_RTN_getRowForList($routine, $rowclass = '')
$retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= ' <a ' . $ajax_class['export']
. ' href="db_routines.php'
. $url_query
. '&amp;export_item=1'
. '&amp;item_name='
. urlencode($routine['name'])
. '&amp;' . $type_link
. '">' . $titles['Export'] . "</a>\n";
if ((PMA\libraries\Util::currentUserHasPrivilege('CREATE ROUTINE', $db)
&& $curr_user == $routine_definer)
|| $GLOBALS['is_superuser']
) {
$retval .= ' <a ' . $ajax_class['export']
. ' href="db_routines.php'
. $url_query
. '&amp;export_item=1'
. '&amp;item_name='
. urlencode($routine['name'])
. '&amp;' . $type_link
. '">' . $titles['Export'] . "</a>\n";
} else {
$retval .= " {$titles['NoExport']}\n";
}
$retval .= " </td>\n";
$retval .= " <td>\n";
$retval .= ' <a ' . $ajax_class['drop']

View File

@ -157,12 +157,13 @@ function PMA_RTN_handleEditor()
} else {
$message = __('Error in processing request:') . ' ';
$message .= sprintf(
PMA_RTE_getWord('not_found'),
PMA_RTE_getWord('no_edit'),
htmlspecialchars(
PMA\libraries\Util::backquote($_REQUEST['item_name'])
),
htmlspecialchars(PMA\libraries\Util::backquote($db))
);
$message = Message::error($message);
if ($GLOBALS['is_ajax_request']) {
$response = PMA\libraries\Response::getInstance();
@ -564,16 +565,23 @@ function PMA_RTN_getDataFromRequest()
* This function will generate the values that are required to complete
* the "Edit routine" form given the name of a routine.
*
* @param string $name The name of the routine.
* @param string $type Type of routine (ROUTINE|PROCEDURE)
* @param bool $all Whether to return all data or just
* the info about parameters.
* @param string $name The name of the routine.
* @param string $type Type of routine (ROUTINE|PROCEDURE)
* @param bool $all Whether to return all data or just
* the info about parameters.
* @param bool $control Where to use Controllink to query for
* routine information
*
* @return array Data necessary to create the routine editor.
*/
function PMA_RTN_getDataFromName($name, $type, $all = true)
function PMA_RTN_getDataFromName($name, $type, $all = true, $control = false)
{
global $db;
$link = null;
if ($control) {
$link = $GLOBALS['controllink'];
}
$retval = array();
@ -587,7 +595,7 @@ function PMA_RTN_getDataFromName($name, $type, $all = true)
. "AND ROUTINE_TYPE='" . PMA\libraries\Util::sqlAddSlashes($type) . "'";
$query = "SELECT $fields FROM INFORMATION_SCHEMA.ROUTINES WHERE $where;";
$routine = $GLOBALS['dbi']->fetchSingleRow($query);
$routine = $GLOBALS['dbi']->fetchSingleRow($query, 'ASSOC', $link);
if (! $routine) {
return false;
@ -597,13 +605,19 @@ function PMA_RTN_getDataFromName($name, $type, $all = true)
$retval['item_name'] = $routine['SPECIFIC_NAME'];
$retval['item_type'] = $routine['ROUTINE_TYPE'];
$parser = new SqlParser\Parser(
$GLOBALS['dbi']->getDefinition(
$definition
= $GLOBALS['dbi']->getDefinition(
$db,
$routine['ROUTINE_TYPE'],
$routine['SPECIFIC_NAME']
)
);
$routine['SPECIFIC_NAME'],
$link
);
if ($definition == NULL) {
return false;
}
$parser = new SqlParser\Parser($definition);
/**
* @var CreateStatement $stmt
@ -1283,7 +1297,7 @@ function PMA_RTN_handleExecute()
if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['item_name'])) {
// Build the queries
$routine = PMA_RTN_getDataFromName(
$_REQUEST['item_name'], $_REQUEST['item_type'], false
$_REQUEST['item_name'], $_REQUEST['item_type'], false, true
);
if ($routine === false) {
$message = __('Error in processing request:') . ' ';
@ -1481,7 +1495,7 @@ function PMA_RTN_handleExecute()
* Display the execute form for a routine.
*/
$routine = PMA_RTN_getDataFromName(
$_GET['item_name'], $_GET['item_type'], true
$_GET['item_name'], $_GET['item_type'], true, true
);
if ($routine !== false) {
$form = PMA_RTN_getExecuteForm($routine);

View File

@ -31,6 +31,14 @@ function PMA_RTE_getWord($index)
'no_create' => __(
'You do not have the necessary privileges to create a routine'
),
'no_edit' => __(
'No routine with name %1$s found in database %2$s. '
. 'You might be lacking the necessary privileges to edit this routine'
),
'no_view' => __(
'No routine with name %1$s found in database %2$s. '
. 'You might be lacking the necessary privileges to view/export this routine'
),
'not_found' => __('No routine with name %1$s found in database %2$s'),
'nothing' => __('There are no routines to display.'),
'title' => __('Routines'),

View File

@ -2325,7 +2325,8 @@ fieldset .disabled-field td {
}
.cEdit .edit_box {
overflow: hidden;
overflow-x: hidden;
overflow-y: scroll;
padding: 0;
}

View File

@ -2875,7 +2875,8 @@ fieldset .disabled-field td {
}
.cEdit .edit_box {
overflow: hidden;
overflow-x: hidden;
overflow-y: scroll;
padding: 0;
margin: 0;
}