MediaWiki  REL1_23
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         # Note: If using a canonical url for userpage css/js, we send an HTCP purge.
00082         if ( $smaxage === null ) {
00083             if ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
00084                 $smaxage = intval( $wgForcedRawSMaxage );
00085             } else {
00086                 $smaxage = 0;
00087             }
00088         }
00089 
00090         $maxage = $request->getInt( 'maxage', $wgSquidMaxage );
00091 
00092         $response = $request->response();
00093 
00094         $response->header( 'Content-type: ' . $contentType . '; charset=UTF-8' );
00095         # Output may contain user-specific data;
00096         # vary generated content for open sessions on private wikis
00097         $privateCache = !User::isEveryoneAllowed( 'read' ) && ( $smaxage == 0 || session_id() != '' );
00098         // Bug 53032 - make this private if user is logged in,
00099         // so we don't accidentally cache cookies
00100         $privateCache = $privateCache ?: $this->getUser()->isLoggedIn();
00101         # allow the client to cache this for 24 hours
00102         $mode = $privateCache ? 'private' : 'public';
00103         $response->header(
00104             'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage
00105         );
00106 
00107         $text = $this->getRawText();
00108 
00109         if ( $text === false && $contentType == 'text/x-wiki' ) {
00110             # Don't return a 404 response for CSS or JavaScript;
00111             # 404s aren't generally cached and it would create
00112             # extra hits when user CSS/JS are on and the user doesn't
00113             # have the pages.
00114             $response->header( 'HTTP/1.x 404 Not Found' );
00115         }
00116 
00117         if ( !wfRunHooks( 'RawPageViewBeforeOutput', array( &$this, &$text ) ) ) {
00118             wfDebug( __METHOD__ . ": RawPageViewBeforeOutput hook broke raw page output.\n" );
00119         }
00120 
00121         echo $text;
00122     }
00123 
00130     public function getRawText() {
00131         global $wgParser;
00132 
00133         # No longer used
00134         if ( $this->mGen ) {
00135             return '';
00136         }
00137 
00138         $text = false;
00139         $title = $this->getTitle();
00140         $request = $this->getRequest();
00141 
00142         // If it's a MediaWiki message we can just hit the message cache
00143         if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) {
00144             // The first "true" is to use the database, the second is to use
00145             // the content langue and the last one is to specify the message
00146             // key already contains the language in it ("/de", etc.).
00147             $text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true );
00148             // If the message doesn't exist, return a blank
00149             if ( $text === false ) {
00150                 $text = '';
00151             }
00152         } else {
00153             // Get it from the DB
00154             $rev = Revision::newFromTitle( $title, $this->getOldId() );
00155             if ( $rev ) {
00156                 $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() );
00157                 $request->response()->header( "Last-modified: $lastmod" );
00158 
00159                 // Public-only due to cache headers
00160                 $content = $rev->getContent();
00161 
00162                 if ( $content === null ) {
00163                     // revision not found (or suppressed)
00164                     $text = false;
00165                 } elseif ( !$content instanceof TextContent ) {
00166                     // non-text content
00167                     wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
00168                         . $content->getModel() . "` which is not supported via this interface." );
00169                     die();
00170                 } else {
00171                     // want a section?
00172                     $section = $request->getIntOrNull( 'section' );
00173                     if ( $section !== null ) {
00174                         $content = $content->getSection( $section );
00175                     }
00176 
00177                     if ( $content === null || $content === false ) {
00178                         // section not found (or section not supported, e.g. for JS and CSS)
00179                         $text = false;
00180                     } else {
00181                         $text = $content->getNativeData();
00182                     }
00183                 }
00184             }
00185         }
00186 
00187         if ( $text !== false && $text !== '' && $request->getVal( 'templates' ) === 'expand' ) {
00188             $text = $wgParser->preprocess(
00189                 $text,
00190                 $title,
00191                 ParserOptions::newFromContext( $this->getContext() )
00192             );
00193         }
00194 
00195         return $text;
00196     }
00197 
00203     public function getOldId() {
00204         $oldid = $this->getRequest()->getInt( 'oldid' );
00205         switch ( $this->getRequest()->getText( 'direction' ) ) {
00206             case 'next':
00207                 # output next revision, or nothing if there isn't one
00208                 if ( $oldid ) {
00209                     $oldid = $this->getTitle()->getNextRevisionID( $oldid );
00210                 }
00211                 $oldid = $oldid ? $oldid : -1;
00212                 break;
00213             case 'prev':
00214                 # output previous revision, or nothing if there isn't one
00215                 if ( !$oldid ) {
00216                     # get the current revision so we can get the penultimate one
00217                     $oldid = $this->page->getLatest();
00218                 }
00219                 $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
00220                 $oldid = $prev ? $prev : -1;
00221                 break;
00222             case 'cur':
00223                 $oldid = 0;
00224                 break;
00225         }
00226 
00227         return $oldid;
00228     }
00229 
00235     public function getContentType() {
00236         $ctype = $this->getRequest()->getVal( 'ctype' );
00237 
00238         if ( $ctype == '' ) {
00239             $gen = $this->getRequest()->getVal( 'gen' );
00240             if ( $gen == 'js' ) {
00241                 $ctype = 'text/javascript';
00242             } elseif ( $gen == 'css' ) {
00243                 $ctype = 'text/css';
00244             }
00245         }
00246 
00247         $allowedCTypes = array( 'text/x-wiki', 'text/javascript', 'text/css', 'application/x-zope-edit' );
00248         if ( $ctype == '' || !in_array( $ctype, $allowedCTypes ) ) {
00249             $ctype = 'text/x-wiki';
00250         }
00251 
00252         return $ctype;
00253     }
00254 }
00255 
00261 class RawPage extends RawAction {
00262     public $mOldId;
00263 
00268     function __construct( Page $page, $request = false ) {
00269         wfDeprecated( __CLASS__, '1.19' );
00270         parent::__construct( $page );
00271 
00272         if ( $request !== false ) {
00273             $context = new DerivativeContext( $this->getContext() );
00274             $context->setRequest( $request );
00275             $this->context = $context;
00276         }
00277     }
00278 
00279     public function view() {
00280         $this->onView();
00281     }
00282 
00283     public function getOldId() {
00284         # Some extensions like to set $mOldId
00285         if ( $this->mOldId !== null ) {
00286             return $this->mOldId;
00287         }
00288 
00289         return parent::getOldId();
00290     }
00291 }