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