Simplify handling of long URLs in Util::linkOrButton

We no longer create form, but rather rather tag the link to be handled
as POST on the client side.

This way the code is way simpler without need on any special case
handling on server side.

Fixes #13649

Signed-off-by: Michal Čihař <michal@cihar.com>
(cherry picked from commit 3b9fb2b664)
Signed-off-by: Maurício Meneghini Fauth <mauriciofauth@gmail.com>
This commit is contained in:
Michal Čihař 2017-11-16 13:04:46 +01:00 committed by Maurício Meneghini Fauth
parent c75166c3a9
commit be7d5ee738
6 changed files with 34 additions and 190 deletions

View File

@ -283,6 +283,9 @@ var AJAX = {
var params = 'ajax_request=true&ajax_page_request=true';
if (! isLink) {
params += '&' + $(this).serialize();
} else if (AJAX.source.attr('data-post')) {
params += '&' + AJAX.source.attr('data-post');
isLink = false;
}
if (! (history && history.pushState)) {
// Add a list of menu hashes that we have in the cache to the request

View File

@ -662,18 +662,7 @@ function confirmLink(theLink, theSqlQuery)
var is_confirmed = confirm(PMA_sprintf(PMA_messages.strDoYouReally, theSqlQuery));
if (is_confirmed) {
if ($(theLink).hasClass('formLinkSubmit')) {
var name = 'is_js_confirmed';
if ($(theLink).attr('href').indexOf('usesubform') != -1) {
var matches = $(theLink).attr('href').substr('#').match(/usesubform\[(\d+)\]/i);
if (matches != null) {
name = 'subform[' + matches[1] + '][is_js_confirmed]';
}
}
$(theLink).parents('form').append('<input type="hidden" name="' + name + '" value="1" />');
} else if (typeof(theLink.href) != 'undefined') {
if (typeof(theLink.href) !== 'undefined') {
theLink.href += '&is_js_confirmed=1';
} else if (typeof(theLink.form) != 'undefined') {
theLink.form.action += '?is_js_confirmed=1';
@ -4159,7 +4148,6 @@ AJAX.registerOnload('functions.js', function () {
*/
AJAX.registerTeardown('functions.js', function () {
$(document).off('change', 'select.pageselector');
$(document).off('click', 'a.formLinkSubmit');
$('#update_recent_tables').unbind('ready');
$('#sync_favorite_tables').unbind('ready');
});
@ -4206,16 +4194,6 @@ AJAX.registerOnload('functions.js', function () {
*/
PMA_init_slider();
/**
* Enables the text generated by PMA\libraries\Util::linkOrButton() to be clickable
*/
$(document).on('click', 'a.formLinkSubmit', function (e) {
if (! $(this).hasClass('requireConfirm')) {
submitFormLink($(this));
return false;
}
});
var $updateRecentTables = $('#update_recent_tables');
if ($updateRecentTables.length) {
$.get(

View File

@ -225,10 +225,6 @@ AJAX.registerTeardown('gis_data_editor.js', function () {
});
AJAX.registerOnload('gis_data_editor.js', function () {
// Remove the class that is added due to the URL being too long.
$('span.open_gis_editor a').removeClass('formLinkSubmit');
/**
* Prepares and insert the GIS data to the input field on clicking 'copy'.
*/

View File

@ -168,23 +168,18 @@ AJAX.registerOnload('sql.js', function () {
var $link = $(this);
$link.PMA_confirm(question, $link.attr('href'), function (url) {
$msgbox = PMA_ajaxShowMessage();
if ($link.hasClass('formLinkSubmit')) {
submitFormLink($link);
} else {
var params = {
'ajax_request': true,
'is_js_confirmed': true,
'token': PMA_commonParams.get('token')
};
$.post(url, params, function (data) {
if (data.success) {
PMA_ajaxShowMessage(data.message);
$link.closest('tr').remove();
} else {
PMA_ajaxShowMessage(data.error, false);
}
});
var params = 'ajax_request=1&is_js_confirmed=1';
if ($link.attr('data-post')) {
params += '&' + $link.attr('data-post');
}
$.post(url, params, function (data) {
if (data.success) {
PMA_ajaxShowMessage(data.message);
$link.closest('tr').remove();
} else {
PMA_ajaxShowMessage(data.error, false);
}
});
});
});

View File

@ -1819,89 +1819,28 @@ class Util
}
}
if (($url_length <= $GLOBALS['cfg']['LinkLengthLimit'])
&& $in_suhosin_limits
&& ! $force_button
$tag_params_strings = array();
if (($url_length > $GLOBALS['cfg']['LinkLengthLimit'])
|| ! $in_suhosin_limits
|| $force_button
) {
$tag_params_strings = array();
foreach ($tag_params as $par_name => $par_value) {
// htmlspecialchars() only on non javascript
$par_value = mb_substr($par_name, 0, 2) == 'on'
? $par_value
: htmlspecialchars($par_value);
$tag_params_strings[] = $par_name . '="' . $par_value . '"';
}
$parts = explode('?', $url, 2);
/*
* The data-post indicates that client should do POST
* this is handled in js/ajax.js
*/
$tag_params_strings[] = 'data-post="' . (isset($parts[1]) ? $parts[1] : '') . '"';
$url = $parts[0];
}
// no whitespace within an <a> else Safari will make it part of the link
$ret = '<a href="' . $url . '" '
. implode(' ', $tag_params_strings) . '>'
. $message . $displayed_message . '</a>';
} else {
// no spaces (line breaks) at all
// or after the hidden fields
// IE will display them all
foreach ($tag_params as $par_name => $par_value) {
$tag_params_strings[] = $par_name . '="' . htmlspecialchars($par_value) . '"';
}
if (! isset($query_parts)) {
$query_parts = self::splitURLQuery($url);
}
$url_parts = parse_url($url);
if ($new_form) {
if ($target) {
$target = ' target="' . $target . '"';
}
$ret = '<form action="' . $url_parts['path'] . '" class="link"'
. ' method="post"' . $target . ' style="display: inline;">';
$ret .= URL::getHiddenInputs();
$subname_open = '';
$subname_close = '';
$submit_link = '#';
} else {
$query_parts[] = 'redirect=' . $url_parts['path'];
$query_parts[] = 'token=' . $_SESSION[' PMA_token '];
if (empty($GLOBALS['subform_counter'])) {
$GLOBALS['subform_counter'] = 0;
}
$GLOBALS['subform_counter']++;
$ret = '';
$subname_open = 'subform[' . $GLOBALS['subform_counter'] . '][';
$subname_close = ']';
$submit_link = '#usesubform[' . $GLOBALS['subform_counter']
. ']=1';
}
foreach ($query_parts as $query_pair) {
list($eachvar, $eachval) = explode('=', $query_pair);
$ret .= '<input type="hidden" name="' . $subname_open . $eachvar
. $subname_close . '" value="'
. htmlspecialchars(urldecode($eachval)) . '" />';
} // end while
if (empty($tag_params['class'])) {
$tag_params['class'] = 'formLinkSubmit';
} else {
$tag_params['class'] .= ' formLinkSubmit';
}
$tag_params_strings = array();
foreach ($tag_params as $par_name => $par_value) {
// htmlspecialchars() only on non javascript
$par_value = mb_substr($par_name, 0, 2) == 'on'
? $par_value
: htmlspecialchars($par_value);
$tag_params_strings[] = $par_name . '="' . $par_value . '"';
}
$ret .= "\n" . '<a href="' . $submit_link . '" '
. implode(' ', $tag_params_strings) . '>'
. $message . ' ' . $displayed_message . '</a>' . "\n";
if ($new_form) {
$ret .= '</form>';
}
} // end if... else...
return $ret;
// no whitespace within an <a> else Safari will make it part of the link
return '<a href="' . $url . '" '
. implode(' ', $tag_params_strings) . '>'
. $message . $displayed_message . '</a>';
} // end of the 'linkOrButton()' function
/**

View File

@ -156,58 +156,6 @@ foreach (get_defined_vars() as $key => $value) {
}
unset($key, $value, $variables_whitelist);
/**
* Subforms - some functions need to be called by form, cause of the limited URL
* length, but if this functions inside another form you cannot just open a new
* form - so phpMyAdmin uses 'arrays' inside this form
*
* <code>
* <form ...>
* ... main form elements ...
* <input type="hidden" name="subform[action1][id]" value="1" />
* ... other subform data ...
* <input type="submit" name="usesubform[action1]" value="do action1" />
* ... other subforms ...
* <input type="hidden" name="subform[actionX][id]" value="X" />
* ... other subform data ...
* <input type="submit" name="usesubform[actionX]" value="do actionX" />
* ... main form elements ...
* <input type="submit" name="main_action" value="submit form" />
* </form>
* </code>
*
* so we now check if a subform is submitted
*/
$__redirect = null;
if (isset($_POST['usesubform']) && ! defined('PMA_MINIMUM_COMMON')) {
// if a subform is present and should be used
// the rest of the form is deprecated
$subform_id = key($_POST['usesubform']);
$subform = $_POST['subform'][$subform_id];
$_POST = $subform;
$_REQUEST = $subform;
/**
* some subforms need another page than the main form, so we will just
* include this page at the end of this script - we use $__redirect to
* track this
*/
if (isset($_POST['redirect'])
&& $_POST['redirect'] != basename($PMA_PHP_SELF)
) {
$__redirect = $_POST['redirect'];
unset($_POST['redirect']);
}
unset($subform_id, $subform);
} else {
// Note: here we overwrite $_REQUEST so that it does not contain cookies,
// because another application for the same domain could have set
// a cookie (with a compatible path) that overrides a variable
// we expect from GET or POST.
// We'll refer to cookies explicitly with the $_COOKIE syntax.
$_REQUEST = array_merge($_GET, $_POST);
}
// end check if a subform is submitted
/**
* check timezone setting
* this could produce an E_WARNING - but only once,
@ -323,13 +271,6 @@ $goto_whitelist = array(
'user_password.php',
);
/**
* check $__redirect against whitelist
*/
if (! PMA_checkPageValidity($__redirect, $goto_whitelist)) {
$__redirect = null;
}
/**
* holds page that should be displayed
* @global string $GLOBALS['goto']
@ -941,14 +882,6 @@ if (count($_REQUEST) > 1000) {
$GLOBALS['is_superuser']
= isset($GLOBALS['dbi']) && $GLOBALS['dbi']->isSuperuser();
if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) {
/**
* include subform target page
*/
include $__redirect;
exit();
}
// If Zero configuration mode enabled, check PMA tables in current db.
if (! defined('PMA_MINIMUM_COMMON')
&& ! empty($GLOBALS['server'])