MediaWiki REL1_28
RawAction.php
Go to the documentation of this file.
1<?php
36 public function getName() {
37 return 'raw';
38 }
39
40 public function requiresWrite() {
41 return false;
42 }
43
44 public function requiresUnblock() {
45 return false;
46 }
47
48 function onView() {
49 $this->getOutput()->disable();
50 $request = $this->getRequest();
51 $response = $request->response();
52 $config = $this->context->getConfig();
53
54 if ( !$request->checkUrlExtension() ) {
55 return;
56 }
57
58 if ( $this->getOutput()->checkLastModified( $this->page->getTouched() ) ) {
59 return; // Client cache fresh and headers sent, nothing more to do.
60 }
61
62 $gen = $request->getVal( 'gen' );
63 if ( $gen == 'css' || $gen == 'js' ) {
64 $this->gen = true;
65 }
66
67 $contentType = $this->getContentType();
68
69 $maxage = $request->getInt( 'maxage', $config->get( 'SquidMaxage' ) );
70 $smaxage = $request->getIntOrNull( 'smaxage' );
71 if ( $smaxage === null ) {
72 if ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
73 // CSS/JS raw content has its own CDN max age configuration.
74 // Note: Title::getCdnUrls() includes action=raw for css/js pages,
75 // so if using the canonical url, this will get HTCP purges.
76 $smaxage = intval( $config->get( 'ForcedRawSMaxage' ) );
77 } else {
78 // No CDN cache for anything else
79 $smaxage = 0;
80 }
81 }
82
83 // Set standard Vary headers so cache varies on cookies and such (T125283)
84 $response->header( $this->getOutput()->getVaryHeader() );
85 if ( $config->get( 'UseKeyHeader' ) ) {
86 $response->header( $this->getOutput()->getKeyHeader() );
87 }
88
89 $response->header( 'Content-type: ' . $contentType . '; charset=UTF-8' );
90 // Output may contain user-specific data;
91 // vary generated content for open sessions on private wikis
92 $privateCache = !User::isEveryoneAllowed( 'read' ) &&
93 ( $smaxage == 0 || MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent() );
94 // Don't accidentally cache cookies if user is logged in (T55032)
95 $privateCache = $privateCache || $this->getUser()->isLoggedIn();
96 $mode = $privateCache ? 'private' : 'public';
97 $response->header(
98 'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage
99 );
100
101 $text = $this->getRawText();
102
103 // Don't return a 404 response for CSS or JavaScript;
104 // 404s aren't generally cached and it would create
105 // extra hits when user CSS/JS are on and the user doesn't
106 // have the pages.
107 if ( $text === false && $contentType == 'text/x-wiki' ) {
108 $response->statusHeader( 404 );
109 }
110
111 if ( !Hooks::run( 'RawPageViewBeforeOutput', [ &$this, &$text ] ) ) {
112 wfDebug( __METHOD__ . ": RawPageViewBeforeOutput hook broke raw page output.\n" );
113 }
114
115 echo $text;
116 }
117
124 public function getRawText() {
126
127 $text = false;
128 $title = $this->getTitle();
129 $request = $this->getRequest();
130
131 // If it's a MediaWiki message we can just hit the message cache
132 if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) {
133 // The first "true" is to use the database, the second is to use
134 // the content langue and the last one is to specify the message
135 // key already contains the language in it ("/de", etc.).
136 $text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true );
137 // If the message doesn't exist, return a blank
138 if ( $text === false ) {
139 $text = '';
140 }
141 } else {
142 // Get it from the DB
144 if ( $rev ) {
145 $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() );
146 $request->response()->header( "Last-modified: $lastmod" );
147
148 // Public-only due to cache headers
149 $content = $rev->getContent();
150
151 if ( $content === null ) {
152 // revision not found (or suppressed)
153 $text = false;
154 } elseif ( !$content instanceof TextContent ) {
155 // non-text content
156 wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
157 . $content->getModel() . "` which is not supported via this interface." );
158 die();
159 } else {
160 // want a section?
161 $section = $request->getIntOrNull( 'section' );
162 if ( $section !== null ) {
163 $content = $content->getSection( $section );
164 }
165
166 if ( $content === null || $content === false ) {
167 // section not found (or section not supported, e.g. for JS and CSS)
168 $text = false;
169 } else {
170 $text = $content->getNativeData();
171 }
172 }
173 }
174 }
175
176 if ( $text !== false && $text !== '' && $request->getVal( 'templates' ) === 'expand' ) {
177 $text = $wgParser->preprocess(
178 $text,
179 $title,
181 );
182 }
183
184 return $text;
185 }
186
192 public function getOldId() {
193 $oldid = $this->getRequest()->getInt( 'oldid' );
194 switch ( $this->getRequest()->getText( 'direction' ) ) {
195 case 'next':
196 # output next revision, or nothing if there isn't one
197 $nextid = 0;
198 if ( $oldid ) {
199 $nextid = $this->getTitle()->getNextRevisionID( $oldid );
200 }
201 $oldid = $nextid ?: -1;
202 break;
203 case 'prev':
204 # output previous revision, or nothing if there isn't one
205 if ( !$oldid ) {
206 # get the current revision so we can get the penultimate one
207 $oldid = $this->page->getLatest();
208 }
209 $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
210 $oldid = $previd ?: -1;
211 break;
212 case 'cur':
213 $oldid = 0;
214 break;
215 }
216
217 return $oldid;
218 }
219
225 public function getContentType() {
226 $ctype = $this->getRequest()->getVal( 'ctype' );
227
228 if ( $ctype == '' ) {
229 $gen = $this->getRequest()->getVal( 'gen' );
230 if ( $gen == 'js' ) {
231 $ctype = 'text/javascript';
232 } elseif ( $gen == 'css' ) {
233 $ctype = 'text/css';
234 }
235 }
236
237 $allowedCTypes = [ 'text/x-wiki', 'text/javascript', 'text/css', 'application/x-zope-edit' ];
238 if ( $ctype == '' || !in_array( $ctype, $allowedCTypes ) ) {
239 $ctype = 'text/x-wiki';
240 }
241
242 return $ctype;
243 }
244}
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.
$wgParser
Definition Setup.php:821
getTitle()
Shortcut to get the Title object from the page.
Definition Action.php:246
getContext()
Get the IContextSource in use here.
Definition Action.php:178
getOutput()
Get the OutputPage being used for this instance.
Definition Action.php:207
getUser()
Shortcut to get the User being used for this instance.
Definition Action.php:217
getRequest()
Get the WebRequest being used for this instance.
Definition Action.php:197
getConfig()
Get the Config object.
An action which just does something, without showing a form first.
static singleton()
Get the signleton instance of this class.
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
A simple method to retrieve the plain source of an article, using "action=raw" in the GET request str...
Definition RawAction.php:35
getContentType()
Get the content type to use for the response.
getRawText()
Get the text that should be returned, or false if the page or revision was not found.
getName()
Return the name of the action this object responds to.
Definition RawAction.php:36
requiresWrite()
Whether this action requires the wiki not to be locked.
Definition RawAction.php:40
onView()
Show something on GET request.
Definition RawAction.php:48
requiresUnblock()
Whether this action can still be executed by a blocked user.
Definition RawAction.php:44
getOldId()
Get the ID of the revision that should used to get the text.
static newFromTitle(LinkTarget $linkTarget, $id=0, $flags=0)
Load either the current, or a specified, revision that's attached to a given link target.
Definition Revision.php:128
Content object implementation for representing flat text.
when a variable name is used in a it is silently declared as a new local masking the global
Definition design.txt:95
const NS_MEDIAWIKI
Definition Defines.php:64
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:986
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content $content
Definition hooks.txt:1094
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition hooks.txt:2685
namespace are movable Hooks may change this value to override the return value of MWNamespace::isMovable(). 'NewDifferenceEngine' do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk page
Definition hooks.txt:2543
this hook is for auditing only $response
Definition hooks.txt:805
usually copyright or history_copyright This message must be in HTML not wikitext if the section is included from a template $section
Definition hooks.txt:2901
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
Definition hooks.txt:1734
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
const TS_RFC2822
RFC 2822 format, for E-mail and HTTP headers.
Definition defines.php:21