Remove ActionAjax

Bug: T42786
Change-Id: I8bda0c281e1f4abbffbddb80ac74a6d61a034d28
This commit is contained in:
Amir Sarabadani 2021-11-25 17:37:36 +01:00
parent c3891f1db3
commit 9bcd3fdfa5
12 changed files with 19 additions and 397 deletions

View file

@ -250,6 +250,7 @@ because of Phabricator reports.
post-parse and can be included by providing 'includeDebugInfo' option
to ParserOutput::getText. Thus, ParserOptions::enableLimitReport and
::getEnableLimitReport methods were deprecated.
* Ajax action that was deprecated in 1.27 now has been removed.
* …
=== Deprecations in 1.38 ===

View file

@ -15,8 +15,6 @@ $wgAutoloadLocalClasses = [
'AddChangeTag' => __DIR__ . '/maintenance/addChangeTag.php',
'AddRFCandPMIDInterwiki' => __DIR__ . '/maintenance/addRFCandPMIDInterwiki.php',
'AddSite' => __DIR__ . '/maintenance/addSite.php',
'AjaxDispatcher' => __DIR__ . '/includes/AjaxDispatcher.php',
'AjaxResponse' => __DIR__ . '/includes/AjaxResponse.php',
'AllMessagesTablePager' => __DIR__ . '/includes/specials/pagers/AllMessagesTablePager.php',
'AllTrans' => __DIR__ . '/maintenance/language/alltrans.php',
'AlphabeticPager' => __DIR__ . '/includes/pager/AlphabeticPager.php',

View file

@ -1,169 +0,0 @@
<?php
/**
* Handle ajax requests and send them to the proper handler.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Ajax
*/
use MediaWiki\MediaWikiServices;
// Use superglobals, but since it's deprecated, it's not worth fixing
// phpcs:disable MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals
/**
* @defgroup Ajax Ajax
*/
/**
* Object-Oriented Ajax functions.
* @ingroup Ajax
*/
class AjaxDispatcher {
/**
* The way the request was made, either a 'get' or a 'post'
* @var string
*/
private $mode;
/**
* Name of the requested handler
* @var string
*/
private $func_name;
/** Arguments passed
* @var array
*/
private $args;
/**
* @var Config
*/
private $config;
/**
* Load up our object with user supplied data
* @param Config $config
*/
public function __construct( Config $config ) {
$this->config = $config;
$this->mode = "";
if ( !empty( $_GET["rs"] ) ) {
$this->mode = "get";
}
if ( !empty( $_POST["rs"] ) ) {
$this->mode = "post";
}
switch ( $this->mode ) {
case 'get':
$this->func_name = $_GET["rs"] ?? '';
if ( !empty( $_GET["rsargs"] ) ) {
$this->args = $_GET["rsargs"];
} else {
$this->args = [];
}
break;
case 'post':
$this->func_name = $_POST["rs"] ?? '';
if ( !empty( $_POST["rsargs"] ) ) {
$this->args = $_POST["rsargs"];
} else {
$this->args = [];
}
break;
default:
return;
# Or we could throw an exception:
# throw new MWException( __METHOD__ . ' called without any data (mode empty).' );
}
}
/**
* Pass the request to our internal function.
* BEWARE! Data are passed as they have been supplied by the user,
* they should be carefully handled in the function processing the
* request.
*
* @param User $user
*/
public function performAction( User $user ) {
if ( empty( $this->mode ) ) {
return;
}
$permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
if ( !in_array( $this->func_name, $this->config->get( 'AjaxExportList' ) ) ) {
wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name );
wfHttpError(
400,
'Bad Request',
"unknown function " . $this->func_name
);
} elseif ( !$permissionManager->isEveryoneAllowed( 'read' ) &&
!$permissionManager->userHasRight( $user, 'read' )
) {
wfHttpError(
403,
'Forbidden',
'You are not allowed to view pages.' );
} else {
wfDebug( __METHOD__ . ' dispatching ' . $this->func_name );
try {
$result = call_user_func_array( $this->func_name, $this->args );
if ( $result === false || $result === null ) {
wfDebug( __METHOD__ . ' ERROR while dispatching ' .
$this->func_name . "(" . var_export( $this->args, true ) . "): " .
"no data returned" );
wfHttpError( 500, 'Internal Error',
"{$this->func_name} returned no data" );
} else {
if ( is_string( $result ) ) {
$result = new AjaxResponse( $result );
}
// Make sure DB commit succeeds before sending a response
$lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
$lbFactory->commitPrimaryChanges( __METHOD__ );
$result->sendHeaders();
$result->printText();
wfDebug( __METHOD__ . ' dispatch complete for ' . $this->func_name );
}
} catch ( Exception $e ) {
wfDebug( __METHOD__ . ' ERROR while dispatching ' .
$this->func_name . "(" . var_export( $this->args, true ) . "): " .
get_class( $e ) . ": " . $e->getMessage() );
if ( !headers_sent() ) {
wfHttpError( 500, 'Internal Error',
$e->getMessage() );
} else {
print $e->getMessage();
}
}
}
}
}

View file

@ -1,188 +0,0 @@
<?php
/**
* Response handler for Ajax requests.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Ajax
*/
use MediaWiki\MediaWikiServices;
/**
* Handle responses for Ajax requests (send headers, print
* content, that sort of thing)
*
* @ingroup Ajax
*/
class AjaxResponse {
/**
* Number of seconds to get the response cached by a proxy
* @var int
*/
private $mCacheDuration;
/**
* HTTP header Content-Type
* @var string
*/
private $mContentType;
/**
* Disables output. Can be set by calling $AjaxResponse->disable()
* @var bool
*/
private $mDisabled;
/**
* Date for the HTTP header Last-modified
* @var string|bool
*/
private $mLastModified;
/**
* HTTP response code
* @var int|string
*/
private $mResponseCode;
/**
* HTTP Vary header
* @var string
*/
private $mVary;
/**
* Content of our HTTP response
* @var string
*/
private $mText;
/**
* @var Config
*/
private $mConfig;
/**
* @param string|null $text
* @param Config|null $config
*/
public function __construct( $text = null, Config $config = null ) {
$this->mCacheDuration = null;
$this->mVary = null;
$this->mConfig = $config ?: MediaWikiServices::getInstance()->getMainConfig();
$this->mDisabled = false;
$this->mText = '';
$this->mResponseCode = 200;
$this->mLastModified = false;
$this->mContentType = 'application/x-wiki';
if ( $text ) {
$this->addText( $text );
}
}
/**
* Set the HTTP response code
* @param int|string $code
*/
public function setResponseCode( $code ) {
$this->mResponseCode = $code;
}
/**
* Set the HTTP header Content-Type
* @param string $type
*/
public function setContentType( $type ) {
$this->mContentType = $type;
}
/**
* Disable output.
*/
public function disable() {
$this->mDisabled = true;
}
/**
* Add content to the response
* @param string $text
*/
public function addText( $text ) {
if ( !$this->mDisabled && $text ) {
$this->mText .= $text;
}
}
/**
* Output text
*/
public function printText() {
if ( !$this->mDisabled ) {
print $this->mText;
}
}
/**
* Construct the header and output it
*/
public function sendHeaders() {
if ( $this->mResponseCode ) {
// For back-compat, it is supported that mResponseCode be a string like " 200 OK"
// (with leading space and the status message after). Cast response code to an integer
// to take advantage of PHP's conversion rules which will turn " 200 OK" into 200.
// https://www.php.net/manual/en/language.types.string.php#language.types.string.conversion
$n = intval( trim( $this->mResponseCode ) );
HttpStatus::header( $n );
}
header( "Content-Type: " . $this->mContentType );
if ( $this->mLastModified ) {
header( "Last-Modified: " . $this->mLastModified );
} else {
header( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" );
}
if ( $this->mCacheDuration ) {
# If CDN caches are configured, tell them to cache the response,
# and tell the client to always check with the CDN. Otherwise,
# tell the client to use a cached copy, without a way to purge it.
if ( $this->mConfig->get( 'UseCdn' ) ) {
# Expect explicit purge of the proxy cache, but require end user agents
# to revalidate against the proxy on each visit.
header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
} else {
# Let the client do the caching. Cache is not purged.
header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" );
header( "Cache-Control: s-maxage={$this->mCacheDuration}," .
"public,max-age={$this->mCacheDuration}" );
}
} else {
# always expired, always modified
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); // Date in the past
header( "Cache-Control: no-cache, must-revalidate" ); // HTTP/1.1
header( "Pragma: no-cache" ); // HTTP/1.0
}
if ( $this->mVary ) {
header( "Vary: " . $this->mVary );
}
}
}

View file

@ -9212,12 +9212,8 @@ $wgExemptFromUserRobotsControl = null;
// endregion End robot policy
/***************************************************************************/
// region AJAX, Action API and REST API
/** @name AJAX, Action API and REST API
*
* Note: The AJAX entry point which this section refers to is gradually being
* replaced by the Action API entry point, api.php. They are essentially
* equivalent. Both of them are used for dynamic client-side features, via XHR.
// region Action API and REST API
/** @name Action API and REST API
*/
/**
@ -9354,20 +9350,6 @@ $wgAPIUselessQueryPages = [
'LinkSearch', // list=exturlusage
];
/**
* Enable AJAX framework
*
* @deprecated (officially) since MediaWiki 1.31 and ignored since 1.32
*/
$wgUseAjax = true;
/**
* List of Ajax-callable functions.
* Extensions acting as Ajax callbacks must register here
* @deprecated (officially) since 1.27; use the API instead
*/
$wgAjaxExportList = [];
/**
* Enable AJAX check for file overwrite, pre-upload
*/

View file

@ -850,21 +850,6 @@ class MediaWiki {
$output = $this->context->getOutput();
$request = $this->context->getRequest();
// Send Ajax requests to the Ajax dispatcher.
if ( $request->getRawVal( 'action' ) === 'ajax' ) {
// Set a dummy title, because $wgTitle == null might break things
$title = Title::makeTitle( NS_SPECIAL, 'Badtitle/performing an AJAX call in '
. __METHOD__
);
$this->context->setTitle( $title );
$wgTitle = $title;
$dispatcher = new AjaxDispatcher( $this->config );
$dispatcher->performAction( $this->context->getUser() );
return;
}
// Get title from request parameters,
// is set on the fly by parseTitle the first time.
$title = $this->getTitle();

View file

@ -2231,7 +2231,7 @@ class OutputPage extends ContextSource {
public function couldBePublicCached() {
if ( !$this->cacheIsFinal ) {
// - The entry point handles its own caching and/or doesn't use OutputPage.
// (such as load.php, AjaxDispatcher, or MediaWiki\Rest\EntryPoint).
// (such as load.php, or MediaWiki\Rest\EntryPoint).
//
// - Or, we haven't finished processing the main part of the request yet
// (e.g. Action::show, SpecialPage::execute), and the state may still

View file

@ -196,6 +196,7 @@ class BlockManager {
} elseif ( count( $blocks ) === 1 ) {
return $blocks[ 0 ];
} else {
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
return new CompositeBlock( [
'address' => $ip,
'reason' => new Message( 'blockedtext-composite-reason' ),
@ -253,12 +254,14 @@ class BlockManager {
if ( !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) ) ) {
// Local list
if ( $this->isLocallyBlockedProxy( $ip ) ) {
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$blocks[] = new SystemBlock( [
'reason' => new Message( 'proxyblockreason' ),
'address' => $ip,
'systemBlock' => 'proxy',
] );
} elseif ( $isAnon && $this->isDnsBlacklisted( $ip ) ) {
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$blocks[] = new SystemBlock( [
'reason' => new Message( 'sorbsreason' ),
'address' => $ip,
@ -270,6 +273,7 @@ class BlockManager {
// Soft blocking
if ( $isAnon && IPUtils::isInRanges( $ip, $this->options->get( 'SoftBlockRanges' ) ) ) {
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$blocks[] = new SystemBlock( [
'address' => $ip,
'reason' => new Message( 'softblockrangesreason', [ $ip ] ),

View file

@ -269,6 +269,7 @@ class DatabaseBlock extends AbstractBlock {
$conds['ipb_address'][] = (string)$target;
$conds['ipb_address'] = array_unique( $conds['ipb_address'] );
$conds[] = self::getRangeCond( IPUtils::toHex( $target ) );
// @phan-suppress-next-line SecurityCheck-SQLInjection
$conds = $db->makeList( $conds, LIST_OR );
break;
@ -276,6 +277,7 @@ class DatabaseBlock extends AbstractBlock {
list( $start, $end ) = IPUtils::parseRange( $target );
$conds['ipb_address'][] = (string)$target;
$conds[] = self::getRangeCond( $start, $end );
// @phan-suppress-next-line SecurityCheck-SQLInjection
$conds = $db->makeList( $conds, LIST_OR );
break;

View file

@ -678,6 +678,7 @@ class ChangesList extends ContextSource {
$s .= ' <span class="' . $deletedClass . '">' .
$this->msg( 'rev-deleted-user' )->escaped() . '</span>';
} else {
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$s .= $this->getLanguage()->getDirMark() . Linker::userLink( $rc->mAttribs['rc_user'],
$rc->mAttribs['rc_user_text'] );
$s .= Linker::userToolLinks(

View file

@ -129,6 +129,7 @@ class WebInstallerOptions extends WebInstallerPage {
}
$skinHtml .=
'<div class="config-skins-item">' .
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$this->parent->getCheckBox( [
'var' => "skin-$skin",
'rawtext' => $screenshotText,
@ -222,6 +223,7 @@ class WebInstallerOptions extends WebInstallerPage {
} else {
$text = $ext;
}
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$extHtml .= $this->parent->getCheckBox( [
'var' => "ext-$ext",
'rawtext' => $text,

View file

@ -125,6 +125,7 @@ class LogPage {
if ( $this->updateRecentChanges ) {
$titleObj = SpecialPage::getTitleFor( 'Log', $this->type );
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
RecentChange::notifyLog(
$now, $titleObj, $this->performer, $this->getRcComment(), '',
$this->type, $this->action, $this->target, $this->comment,
@ -136,9 +137,10 @@ class LogPage {
return $newId;
}
# Notify external application via UDP.
# We send this to IRC but do not want to add it the RC table.
// Notify external application via UDP.
// We send this to IRC but do not want to add it the RC table.
$titleObj = SpecialPage::getTitleFor( 'Log', $this->type );
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$rc = RecentChange::newLogEntry(
$now, $titleObj, $this->performer, $this->getRcComment(), '',
$this->type, $this->action, $this->target, $this->comment,
@ -255,6 +257,7 @@ class LogPage {
$titleLink = self::getTitleLink( $title, $langObjOrNull );
if ( count( $params ) == 0 ) {
// @phan-suppress-next-line SecurityCheck-XSS
$rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )
->inLanguage( $langObj )->escaped();
} else {
@ -360,6 +363,7 @@ class LogPage {
$this->performer = $performer;
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$logEntry = new ManualLogEntry( $this->type, $action );
$logEntry->setTarget( $target );
$logEntry->setPerformer( $performer );