MediaWiki  REL1_22
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;
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 == 'text/javascript' ) {
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::isEveryoneAllowed( '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         $ctype = $this->getRequest()->getVal( 'ctype' );
00228 
00229         if ( $ctype == '' ) {
00230             $gen = $this->getRequest()->getVal( 'gen' );
00231             if ( $gen == 'js' ) {
00232                 $ctype = 'text/javascript';
00233             } elseif ( $gen == 'css' ) {
00234                 $ctype = 'text/css';
00235             }
00236         }
00237 
00238         $allowedCTypes = array( 'text/x-wiki', 'text/javascript', 'text/css', 'application/x-zope-edit' );
00239         if ( $ctype == '' || !in_array( $ctype, $allowedCTypes ) ) {
00240             $ctype = 'text/x-wiki';
00241         }
00242 
00243         return $ctype;
00244     }
00245 }
00246 
00252 class RawPage extends RawAction {
00253     public $mOldId;
00254 
00259     function __construct( Page $page, $request = false ) {
00260         wfDeprecated( __CLASS__, '1.19' );
00261         parent::__construct( $page );
00262 
00263         if ( $request !== false ) {
00264             $context = new DerivativeContext( $this->getContext() );
00265             $context->setRequest( $request );
00266             $this->context = $context;
00267         }
00268     }
00269 
00270     public function view() {
00271         $this->onView();
00272     }
00273 
00274     public function getOldId() {
00275         # Some extensions like to set $mOldId
00276         if ( $this->mOldId !== null ) {
00277             return $this->mOldId;
00278         }
00279         return parent::getOldId();
00280     }
00281 }