32use Wikimedia\Timestamp\TimestampFormat as TS;
45 private readonly
Parser $parser,
51 parent::__construct( $article,
$context );
75 ContentSecurityPolicy::sendRestrictiveHeader();
77 $response = $request->response();
78 $config = $this->context->getConfig();
80 if ( $this->
getOutput()->checkLastModified(
90 $smaxage = $request->getIntOrNull(
'smaxage' );
91 if ( $smaxage ===
null ) {
93 $contentType ===
'text/css' ||
94 $contentType ===
'application/json' ||
95 $contentType ===
'text/javascript'
108 $response->header( $this->
getOutput()->getVaryHeader() );
112 $privateCache = !$this->permissionManager->isEveryoneAllowed(
'read' ) &&
113 ( $smaxage === 0 || $request->getSession()->isPersistent() );
115 $privateCache = $privateCache || $this->
getUser()->isRegistered();
116 $mode = $privateCache ?
'private' :
'public';
118 'Cache-Control: ' . $mode .
', s-maxage=' . $smaxage .
', max-age=' . $maxage
126 if ( $title->isUserConfigPage() && $contentType !==
'text/x-wiki' ) {
129 $rootPage = strtok( $title->getText(),
'/' );
130 $userFromTitle = $this->userFactory->newFromName( $rootPage, UserRigorOptions::RIGOR_USABLE );
131 if ( !$userFromTitle || !$userFromTitle->isRegistered() ) {
132 $elevated = $this->
getAuthority()->isAllowed(
'editinterface' );
133 $elevatedText = $elevated ?
'by elevated ' :
'';
134 $log = LoggerFactory::getInstance(
"security" );
136 "Unsafe JS/CSS/Json {$elevatedText}load - {user} loaded {title} with {ctype}",
139 'title' => $title->getPrefixedDBkey(),
140 'ctype' => $contentType,
141 'elevated' => $elevated
154 $pageRestrictions = $this->restrictionStore->getRestrictions( $title,
'edit' );
156 $contentType ===
'text/javascript' &&
157 !$title->isUserJsConfigPage() &&
159 !in_array(
'sysop', $pageRestrictions ) &&
160 !in_array(
'editprotected', $pageRestrictions )
163 $log = LoggerFactory::getInstance(
"security" );
164 $log->info(
"Blocked loading unprotected JS {title} for {user}",
167 'title' => $title->getPrefixedDBkey(),
173 $response->header(
'Content-type: ' . $contentType .
'; charset=UTF-8' );
181 if ( $text ===
false && $contentType ===
'text/x-wiki' ) {
182 $response->statusHeader( 404 );
185 if ( !$this->
getHookRunner()->onRawPageViewBeforeOutput( $this, $text ) ) {
186 wfDebug( __METHOD__ .
": RawPageViewBeforeOutput hook broke raw page output." );
206 $rev = $this->revisionLookup->getRevisionByTitle( $title, $this->
getOldId() );
208 $lastMod =
wfTimestamp( TS::RFC2822, $rev->getTimestamp() );
209 $request->response()->header(
"Last-modified: $lastMod" );
213 $slot = $this->
getRequest()->getText(
'slot' );
215 if ( $rev->hasSlot( $slot ) ) {
216 $content = $rev->getContent( $slot );
221 $content = $rev->getContent( SlotRecord::MAIN );
224 if ( $content ===
null ) {
226 } elseif ( !$content instanceof
TextContent && !method_exists( $content,
'getText' ) ) {
230 "Unsupported Media Type",
"The requested page uses the content model `"
231 . $content->getModel() .
"` which is not supported via this interface."
236 $section = $request->getIntOrNull(
'section' );
237 if ( $section !==
null ) {
238 $content = $content->getSection( $section );
241 if ( $content !==
null && $content !==
false ) {
243 $text = $content->getText();
248 if ( $text !==
false && $text !==
'' && $request->getRawVal(
'templates' ) ===
'expand' ) {
249 $text = $this->parser->preprocess(
265 $oldId = $this->
getRequest()->getInt(
'oldid' );
266 $rl = $this->revisionLookup;
267 switch ( $this->
getRequest()->getText(
'direction' ) ) {
269 # output next revision, or nothing if there isn't one
272 $oldRev = $rl->getRevisionById( $oldId );
274 $nextRev = $rl->getNextRevision( $oldRev );
277 $oldId = $nextRev ? $nextRev->getId() : -1;
280 # output previous revision, or nothing if there isn't one
283 # get the current revision so we can get the penultimate one
286 $oldRev = $rl->getRevisionById( $oldId );
288 $prevRev = $rl->getPreviousRevision( $oldRev );
290 $oldId = $prevRev ? $prevRev->getId() : -1;
312 $gen = $this->
getRequest()->getRawVal(
'gen' );
313 if ( $gen ==
'js' ) {
314 $ctype =
'text/javascript';
315 } elseif ( $gen ==
'css' ) {
320 static $allowedCTypes = [
325 'application/x-zope-edit',
328 if (
$ctype ==
'' || !in_array(
$ctype, $allowedCTypes ) ) {
337class_alias( RawAction::class,
'RawAction' );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
wfTimestamp( $outputtype=TS::UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Content object implementation for representing flat text.
A class containing constants representing the names of configuration variables.
const CdnMaxAge
Name constant for the CdnMaxAge setting, for use with Config::get()
const ForcedRawSMaxage
Name constant for the ForcedRawSMaxage setting, for use with Config::get()
Legacy class representing an editable page and handling UI for some page actions.
Handle sending Content-Security-Policy headers.
Interface for objects which can provide a MediaWiki context on request.