MediaWiki  REL1_21
RawAction.php
Go to the documentation of this file.
00001 <?php
00035 class RawAction extends FormlessAction {
00036         private $mGen;
00037 
00038         public function getName() {
00039                 return 'raw';
00040         }
00041 
00042         public function requiresWrite() {
00043                 return false;
00044         }
00045 
00046         public function requiresUnblock() {
00047                 return false;
00048         }
00049 
00050         function onView() {
00051                 global $wgSquidMaxage, $wgForcedRawSMaxage, $wgJsMimeType;
00052 
00053                 $this->getOutput()->disable();
00054                 $request = $this->getRequest();
00055 
00056                 if ( !$request->checkUrlExtension() ) {
00057                         return;
00058                 }
00059 
00060                 if ( $this->getOutput()->checkLastModified( $this->page->getTouched() ) ) {
00061                         return; // Client cache fresh and headers sent, nothing more to do.
00062                 }
00063 
00064                 # special case for 'generated' raw things: user css/js
00065                 # This is deprecated and will only return empty content
00066                 $gen = $request->getVal( 'gen' );
00067                 $smaxage = $request->getIntOrNull( 'smaxage' );
00068 
00069                 if ( $gen == 'css' || $gen == 'js' ) {
00070                         $this->mGen = $gen;
00071                         if ( $smaxage === null ) {
00072                                 $smaxage = $wgSquidMaxage;
00073                         }
00074                 } else {
00075                         $this->mGen = false;
00076                 }
00077 
00078                 $contentType = $this->getContentType();
00079 
00080                 # Force caching for CSS and JS raw content, default: 5 minutes
00081                 if ( $smaxage === null ) {
00082                         if ( $contentType == 'text/css' || $contentType == $wgJsMimeType ) {
00083                                 $smaxage = intval( $wgForcedRawSMaxage );
00084                         } else {
00085                                 $smaxage = 0;
00086                         }
00087                 }
00088 
00089                 $maxage = $request->getInt( 'maxage', $wgSquidMaxage );
00090 
00091                 $response = $request->response();
00092 
00093                 $response->header( 'Content-type: ' . $contentType . '; charset=UTF-8' );
00094                 # Output may contain user-specific data;
00095                 # vary generated content for open sessions on private wikis
00096                 $privateCache = !User::groupHasPermission( '*', 'read' ) && ( $smaxage == 0 || session_id() != '' );
00097                 // Bug 53032 - make this private if user is logged in,
00098                 // so we don't accidentally cache cookies
00099                 $privateCache = $privateCache ?: $this->getUser()->isLoggedIn();
00100                 # allow the client to cache this for 24 hours
00101                 $mode = $privateCache ? 'private' : 'public';
00102                 $response->header( 'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage );
00103 
00104                 $text = $this->getRawText();
00105 
00106                 if ( $text === false && $contentType == 'text/x-wiki' ) {
00107                         # Don't return a 404 response for CSS or JavaScript;
00108                         # 404s aren't generally cached and it would create
00109                         # extra hits when user CSS/JS are on and the user doesn't
00110                         # have the pages.
00111                         $response->header( 'HTTP/1.x 404 Not Found' );
00112                 }
00113 
00114                 if ( !wfRunHooks( 'RawPageViewBeforeOutput', array( &$this, &$text ) ) ) {
00115                         wfDebug( __METHOD__ . ": RawPageViewBeforeOutput hook broke raw page output.\n" );
00116                 }
00117 
00118                 echo $text;
00119         }
00120 
00127         public function getRawText() {
00128                 global $wgParser;
00129 
00130                 # No longer used
00131                 if( $this->mGen ) {
00132                         return '';
00133                 }
00134 
00135                 $text = false;
00136                 $title = $this->getTitle();
00137                 $request = $this->getRequest();
00138 
00139                 // If it's a MediaWiki message we can just hit the message cache
00140                 if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) {
00141                         // The first "true" is to use the database, the second is to use the content langue
00142                         // and the last one is to specify the message key already contains the language in it ("/de", etc.)
00143                         $text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true );
00144                         // If the message doesn't exist, return a blank
00145                         if ( $text === false ) {
00146                                 $text = '';
00147                         }
00148                 } else {
00149                         // Get it from the DB
00150                         $rev = Revision::newFromTitle( $title, $this->getOldId() );
00151                         if ( $rev ) {
00152                                 $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() );
00153                                 $request->response()->header( "Last-modified: $lastmod" );
00154 
00155                                 // Public-only due to cache headers
00156                                 $content = $rev->getContent();
00157 
00158                                 if ( $content === null ) {
00159                                         // revision not found (or suppressed)
00160                                         $text = false;
00161                                 } elseif ( !$content instanceof TextContent ) {
00162                                         // non-text content
00163                                         wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
00164                                                                                 . $content->getModel() . "` which is not supported via this interface." );
00165                                         die();
00166                                 } else {
00167                                         // want a section?
00168                                         $section = $request->getIntOrNull( 'section' );
00169                                         if ( $section !== null ) {
00170                                                 $content = $content->getSection( $section );
00171                                         }
00172 
00173                                         if ( $content === null || $content === false ) {
00174                                                 // section not found (or section not supported, e.g. for JS and CSS)
00175                                                 $text = false;
00176                                         } else {
00177                                                 $text = $content->getNativeData();
00178                                         }
00179                                 }
00180                         }
00181                 }
00182 
00183                 if ( $text !== false && $text !== '' && $request->getVal( 'templates' ) === 'expand' ) {
00184                         $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
00185                 }
00186 
00187                 return $text;
00188         }
00189 
00195         public function getOldId() {
00196                 $oldid = $this->getRequest()->getInt( 'oldid' );
00197                 switch ( $this->getRequest()->getText( 'direction' ) ) {
00198                         case 'next':
00199                                 # output next revision, or nothing if there isn't one
00200                                 if( $oldid ) {
00201                                         $oldid = $this->getTitle()->getNextRevisionId( $oldid );
00202                                 }
00203                                 $oldid = $oldid ? $oldid : -1;
00204                                 break;
00205                         case 'prev':
00206                                 # output previous revision, or nothing if there isn't one
00207                                 if( !$oldid ) {
00208                                         # get the current revision so we can get the penultimate one
00209                                         $oldid = $this->page->getLatest();
00210                                 }
00211                                 $prev = $this->getTitle()->getPreviousRevisionId( $oldid );
00212                                 $oldid = $prev ? $prev : -1;
00213                                 break;
00214                         case 'cur':
00215                                 $oldid = 0;
00216                                 break;
00217                 }
00218                 return $oldid;
00219         }
00220 
00226         public function getContentType() {
00227                 global $wgJsMimeType;
00228 
00229                 $ctype = $this->getRequest()->getVal( 'ctype' );
00230 
00231                 if ( $ctype == '' ) {
00232                         $gen = $this->getRequest()->getVal( 'gen' );
00233                         if ( $gen == 'js' ) {
00234                                 $ctype = $wgJsMimeType;
00235                         } elseif ( $gen == 'css' ) {
00236                                 $ctype = 'text/css';
00237                         }
00238                 }
00239 
00240                 $allowedCTypes = array( 'text/x-wiki', $wgJsMimeType, 'text/css', 'application/x-zope-edit' );
00241                 if ( $ctype == '' || !in_array( $ctype, $allowedCTypes ) ) {
00242                         $ctype = 'text/x-wiki';
00243                 }
00244 
00245                 return $ctype;
00246         }
00247 }
00248 
00254 class RawPage extends RawAction {
00255         public $mOldId;
00256 
00257         function __construct( Page $page, $request = false ) {
00258                 wfDeprecated( __CLASS__, '1.19' );
00259                 parent::__construct( $page );
00260 
00261                 if ( $request !== false ) {
00262                         $context = new DerivativeContext( $this->getContext() );
00263                         $context->setRequest( $request );
00264                         $this->context = $context;
00265                 }
00266         }
00267 
00268         public function view() {
00269                 $this->onView();
00270         }
00271 
00272         public function getOldId() {
00273                 # Some extensions like to set $mOldId
00274                 if ( $this->mOldId !== null ) {
00275                         return $this->mOldId;
00276                 }
00277                 return parent::getOldId();
00278         }
00279 }