diff --git a/js/ajax.js b/js/ajax.js index e74c4f225a..deadb4c750 100644 --- a/js/ajax.js +++ b/js/ajax.js @@ -276,6 +276,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 diff --git a/js/functions.js b/js/functions.js index b02abdea92..76545a6b68 100644 --- a/js/functions.js +++ b/js/functions.js @@ -665,18 +665,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(''); - } 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'; @@ -4074,7 +4063,6 @@ AJAX.registerOnload('functions.js', function () { */ AJAX.registerTeardown('functions.js', function () { $(document).off('change', 'select.pageselector'); - $(document).off('click', 'a.formLinkSubmit'); $('#update_recent_tables').off('ready'); $('#sync_favorite_tables').off('ready'); }); @@ -4119,16 +4107,6 @@ AJAX.registerOnload('functions.js', function () { */ PMA_init_slider(); - /** - * Enables the text generated by PhpMyAdmin\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( diff --git a/js/gis_data_editor.js b/js/gis_data_editor.js index 93ac847123..977520763c 100644 --- a/js/gis_data_editor.js +++ b/js/gis_data_editor.js @@ -221,9 +221,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'. */ diff --git a/js/sql.js b/js/sql.js index 7c175f9761..2a06186d18 100644 --- a/js/sql.js +++ b/js/sql.js @@ -187,22 +187,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 - }; - $.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); + } + }); }); }); diff --git a/libraries/classes/Display/Results.php b/libraries/classes/Display/Results.php index a35651d461..e01438264b 100644 --- a/libraries/classes/Display/Results.php +++ b/libraries/classes/Display/Results.php @@ -1863,9 +1863,7 @@ class Results . $tmp_txt . '" title="' . $tmp_txt . '" />'; $tmp_url = 'sql.php' . Url::getCommon($url_params_full_text); - return Util::linkOrButton( - $tmp_url, $tmp_image, array(), false - ); + return Util::linkOrButton($tmp_url, $tmp_image); } // end of the '_getFullOrPartialTextButtonOrLink()' function @@ -2324,8 +2322,7 @@ class Results . ''; return Util::linkOrButton( - $order_url, $inner_link_content, - $order_link_params, false, true + $order_url, $inner_link_content, $order_link_params ); } // end of the '_getSortOrderLink()' function @@ -4978,7 +4975,7 @@ class Results Util::getIcon( 'b_view_add.png', __('Create view'), true ), - array('class' => 'create_view' . $ajax_class), true, true, '' + array('class' => 'create_view' . $ajax_class) ) . '' . "\n"; } @@ -5024,10 +5021,7 @@ class Results Util::getIcon( 'b_insrow.png', __('Copy to clipboard'), true ), - array('id' => 'copyToClipBoard'), - true, - true, - 'copy_to_clip_board' + array('id' => 'copyToClipBoard') ); return $html; @@ -5048,8 +5042,6 @@ class Results 'b_print.png', __('Print'), true ), array('id' => 'printView'), - true, - true, 'print_view' ); @@ -5154,11 +5146,7 @@ class Results 'tbl_export.php' . Url::getCommon($_url_params), Util::getIcon( 'b_tblexport.png', __('Export'), true - ), - '', - true, - true, - '' + ) ) . "\n"; @@ -5167,11 +5155,7 @@ class Results 'tbl_chart.php' . Url::getCommon($_url_params), Util::getIcon( 'b_chart.png', __('Display chart'), true - ), - '', - true, - true, - '' + ) ) . "\n"; @@ -5192,11 +5176,7 @@ class Results . Url::getCommon($_url_params), Util::getIcon( 'b_globe.gif', __('Visualize GIS data'), true - ), - '', - true, - true, - '' + ) ) . "\n"; } @@ -5621,9 +5601,7 @@ class Results $ret .= '' - . Util::linkOrButton( - $edit_url, $edit_str, array(), false - ); + . Util::linkOrButton($edit_url, $edit_str); /* * Where clause for selecting this row uniquely is provided as * a hidden input. Used by jQuery scripts for handling grid editing @@ -5668,9 +5646,7 @@ class Results } $ret .= 'center print_ignore" ' . ' >' - . Util::linkOrButton( - $copy_url, $copy_str, array(), false - ); + . Util::linkOrButton($copy_url, $copy_str); /* * Where clause for selecting this row uniquely is provided as @@ -5719,8 +5695,7 @@ class Results . Util::linkOrButton( $del_url, $del_str, - array('class' => 'delete_row requireConfirm' . $ajax), - false + array('class' => 'delete_row requireConfirm' . $ajax) ) . '
' . $js_conf . '
' . ''; diff --git a/libraries/classes/InsertEdit.php b/libraries/classes/InsertEdit.php index 4eb779a12b..1aef365b57 100644 --- a/libraries/classes/InsertEdit.php +++ b/libraries/classes/InsertEdit.php @@ -1433,7 +1433,7 @@ class InsertEdit $edit_str = Util::getIcon('b_edit.png', __('Edit/Insert')); return '' . Util::linkOrButton( - '#', $edit_str, array(), false, false, '_blank' + '#', $edit_str, array(), '_blank' ) . ''; } diff --git a/libraries/classes/Util.php b/libraries/classes/Util.php index 46aaf42eff..2f538dc863 100644 --- a/libraries/classes/Util.php +++ b/libraries/classes/Util.php @@ -1052,8 +1052,6 @@ class Util htmlspecialchars('url.php?url=' . urlencode($url)), sprintf(__('Analyze Explain at %s'), 'mariadb.org'), array(), - true, - false, '_blank' ) . ' ]'; } @@ -1083,34 +1081,23 @@ class Util $php_link = ' [ ' . self::linkOrButton( 'import.php' . Url::getCommon($url_params), - __('Without PHP code'), - array(), - true, - false, - '', - true + __('Without PHP code') ) . ' ]'; $php_link .= ' [ ' . self::linkOrButton( 'import.php' . Url::getCommon($url_params), - __('Submit query'), - array(), - true, - false, - '', - true + __('Submit query') ) . ' ]'; } else { $php_params = $url_params; $php_params['show_as_php'] = 1; - $_message = __('Create PHP code'); $php_link = ' [ ' . self::linkOrButton( 'import.php' . Url::getCommon($php_params), - $_message + __('Create PHP code') ) . ' ]'; } @@ -1703,26 +1690,26 @@ class Util } /** - * Displays a link, or a button if the link's URL is too large, to - * accommodate some browsers' limitations + * Displays a link, or a link with code to trigger POST request. + * + * POST is used in following cases: + * + * - URL is too long + * - URL components are over Suhosin limits + * - There is SQL query in the parameters * * @param string $url the URL * @param string $message the link message * @param mixed $tag_params string: js confirmation * array: additional tag params (f.e. style="") - * @param boolean $new_form we set this to false when we are already in - * a form, to avoid generating nested forms - * @param boolean $strip_img whether to strip the image * @param string $target target - * @param boolean $force_button use a button even when the URL is not too long * * @return string the results to be echoed or saved in an array */ public static function linkOrButton( - $url, $message, $tag_params = array(), - $new_form = true, $strip_img = false, $target = '', $force_button = false + $url, $message, $tag_params = array(), $target = '' ) { - $url_length = mb_strlen($url); + $url_length = strlen($url); if (! is_array($tag_params)) { $tmp = $tag_params; @@ -1734,25 +1721,12 @@ class Util unset($tmp); } if (! empty($target)) { - $tag_params['target'] = htmlentities($target); + $tag_params['target'] = $target; if ($target === '_blank' && strncmp($url, 'url.php?', 8) == 0) { $tag_params['rel'] = 'noopener noreferrer'; } } - $displayed_message = ''; - // Add text if not already added - if (stristr($message, ''; - } - // Suhosin: Check that each query parameter is not above maximum $in_suhosin_limits = true; if ($url_length <= $GLOBALS['cfg']['LinkLengthLimit']) { @@ -1765,7 +1739,7 @@ class Util } list(, $eachval) = explode('=', $query_pair); - if (mb_strlen($eachval) > $suhosin_get_MaxValueLength + if (strlen($eachval) > $suhosin_get_MaxValueLength ) { $in_suhosin_limits = false; break; @@ -1774,81 +1748,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 + || strpos($url, 'sql_query=') !== false ) { - $tag_params_strings = array(); - foreach ($tag_params as $par_name => $par_value) { - $tag_params_strings[] = $par_name . '="' . htmlspecialchars($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 else Safari will make it part of the link - $ret = '' - . $message . $displayed_message . ''; - } 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 = ''; - } - } // end if... else... - - return $ret; + // no whitespace within an else Safari will make it part of the link + return '' + . $message . ''; } // end of the 'linkOrButton()' function /** diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 6b323bffe2..2826ed254b 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -145,59 +145,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 - * - * - *
- * ... main form elements ... - * - * ... other subform data ... - * - * ... other subforms ... - * - * ... other subform data ... - * - * ... main form elements ... - * - *
- *
- * - * 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 - - /******************************************************************************/ /* parsing configuration file LABEL_parsing_config_file */ @@ -300,13 +247,6 @@ $goto_whitelist = array( 'user_password.php', ); -/** - * check $__redirect against whitelist - */ -if (! Core::checkPageValidity($__redirect, $goto_whitelist)) { - $__redirect = null; -} - /** * holds page that should be displayed * @global string $GLOBALS['goto'] @@ -634,14 +574,6 @@ if (! defined('PMA_MINIMUM_COMMON')) { /* Tell tracker that it can actually work */ Tracker::enable(); -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']) diff --git a/templates/table/search/input_box.twig b/templates/table/search/input_box.twig index bea3180b7a..dd0c380abb 100644 --- a/templates/table/search/input_box.twig +++ b/templates/table/search/input_box.twig @@ -38,7 +38,7 @@ {% set edit_url = 'gis_data_editor.php' ~ Url_getCommon() %} {% set edit_str = Util_getIcon('b_edit.png', 'Edit/Insert'|trans) %} - {{ Util_linkOrButton(edit_url, edit_str, [], false, false, '_blank') }} + {{ Util_linkOrButton(edit_url, edit_str, [], '_blank') }} {% endif %} {% elseif column_type starts with 'enum' diff --git a/test/classes/Display/ResultsTest.php b/test/classes/Display/ResultsTest.php index 661236638f..ed0d820019 100644 --- a/test/classes/Display/ResultsTest.php +++ b/test/classes/Display/ResultsTest.php @@ -438,11 +438,11 @@ class ResultsTest extends PmaTestCase '%60customer%60.%60id%60+%3D+1', '' . '' - . ' Edit' . '' @@ -501,11 +501,11 @@ class ResultsTest extends PmaTestCase 'klass', '' - . ' Copy' . '' @@ -564,7 +564,7 @@ class ResultsTest extends PmaTestCase 'DELETE FROM `Data`.`customer` WHERE `customer`.`id` = 1', 'klass', '' - . ' ' - . '' + . '_action=update">' . ' Edit' . '
' - . 'Copy Copy' . '' - . ' Delete
', 'DELETE FROM `data`.`new` WHERE `new`.`id` = 1', '' - . ' Delete' . '
DELETE FROM `data`.`new` WHERE `new`.' . '`id` = 1
' - . 'Copy Copy' . '' . '' - . 'Edit Edit' . 'text' + ], + [ + ['index.php?some=parameter', 'text'], + 20, + 'text', + ], + [ + ['index.php', 'text', [], 'target'], + 1000, + 'text', + ], + [ + ['url.php?url=http://phpmyadmin.net/', 'text', [], '_blank'], + 1000, + 'text', + ], + ]; + } }