return;
}
+// Pathinfo can be used for stupid things. We don't support it for api.php at
+// all, so error out if it's present.
+if ( isset( $_SERVER['PATH_INFO'] ) && $_SERVER['PATH_INFO'] != '' ) {
+ $correctUrl = wfAppendQuery( wfScript( 'api' ), $wgRequest->getQueryValues() );
+ $correctUrl = wfExpandUrl( $correctUrl, PROTO_CANONICAL );
+ header( "Location: $correctUrl", true, 301 );
+ echo 'This endpoint does not support "path info", i.e. extra text between "api.php"'
+ . 'and the "?". Remove any such text and try again.';
+ die( 1 );
+}
+
// Verify that the API has not been disabled
if ( !$wgEnableAPI ) {
header( $_SERVER['SERVER_PROTOCOL'] . ' 500 MediaWiki configuration Error', true, 500 );
$wgOut->disable();
$mimetype = $this->contentType();
header( "Content-type: $mimetype; charset=UTF-8" );
+
+ // Set a sane filename
+ $exts = MimeMagic::singleton()->getExtensionsForType( $mimetype );
+ $ext = $exts ? strtok( $exts, ' ' ) : 'xml';
+ header( "Content-Disposition: inline; filename=\"feed.{$ext}\"" );
+
if ( $wgVaryOnXFP ) {
$wgOut->addVaryHeader( 'X-Forwarded-Proto' );
}
*/
abstract public function getMimeType();
+ /**
+ * Return a filename for this module's output.
+ * @note If $this->getIsWrappedHtml() || $this->getIsHtml(), you'll very
+ * likely want to fall back to this class's version.
+ * @since 1.27
+ * @return string Generally this should be "api-result.$ext", and must be
+ * encoded for inclusion in a Content-Disposition header's filename parameter.
+ */
+ public function getFilename() {
+ if ( $this->getIsWrappedHtml() ) {
+ return 'api-result-wrapped.json';
+ } elseif ( $this->getIsHtml() ) {
+ return 'api-result.html';
+ } else {
+ $exts = MimeMagic::singleton()->getExtensionsForType( $this->getMimeType() );
+ $ext = $exts ? strtok( $exts, ' ' ) : strtolower( $this->mFormat );
+ return "api-result.$ext";
+ }
+ }
+
/**
* Get the internal format name
* @return string
if ( $apiFrameOptions ) {
$this->getMain()->getRequest()->response()->header( "X-Frame-Options: $apiFrameOptions" );
}
+
+ // Set a Content-Disposition header so something downloading an API
+ // response uses a halfway-sensible filename (T128209).
+ $filename = $this->getFilename();
+ $this->getMain()->getRequest()->response()->header(
+ "Content-Disposition: inline; filename=\"{$filename}\""
+ );
}
/**
return $data['mime'];
}
+ public function getFilename() {
+ $data = $this->getResult()->getResultData();
+ if ( isset( $data['error'] ) ) {
+ return $this->errorFallback->getFilename();
+ } elseif ( !isset( $data['filename'] ) || $this->getIsWrappedHtml() || $this->getIsHtml() ) {
+ return parent::getFilename();
+ } else {
+ return $data['filename'];
+ }
+ }
+
public function initPrinter( $unused = false ) {
$data = $this->getResult()->getResultData();
if ( isset( $data['error'] ) || isset( $data['errors'] ) ) {
if ( $params['wrap'] ) {
$data = [
'mime' => 'text/html',
+ 'filename' => 'api-help.html',
'help' => $html,
];
ApiResult::setSubelementsList( $data, 'help' );
$result->reset();
$result->addValue( null, 'text', $html, ApiResult::NO_SIZE_CHECK );
$result->addValue( null, 'mime', 'text/html', ApiResult::NO_SIZE_CHECK );
+ $result->addValue( null, 'filename', 'api-help.html', ApiResult::NO_SIZE_CHECK );
}
}
// Raw formatter will handle this
$result->addValue( null, 'text', $sink, ApiResult::NO_SIZE_CHECK );
$result->addValue( null, 'mime', 'text/xml', ApiResult::NO_SIZE_CHECK );
+ $result->addValue( null, 'filename', 'export.xml', ApiResult::NO_SIZE_CHECK );
} else {
$result->addValue( 'query', 'export', $sink, ApiResult::NO_SIZE_CHECK );
$result->addValue( 'query', ApiResult::META_BC_SUBELEMENTS, [ 'export' ] );