Security fix: Previously it was possible to include unprotected and even content...
[mediawiki.git] / includes / HTMLFileCache.php
bloba746681488a99ab3955a31ac45b0224b872b7ae6
1 <?php
2 /**
3 * Contain the HTMLFileCache class
4 * @addtogroup Cache
5 */
7 /**
8 * Handles talking to the file cache, putting stuff in and taking it back out.
9 * Mostly called from Article.php, also from DatabaseFunctions.php for the
10 * emergency abort/fallback to cache.
12 * Global options that affect this module:
13 * $wgCachePages
14 * $wgCacheEpoch
15 * $wgUseFileCache
16 * $wgFileCacheDirectory
17 * $wgUseGzip
19 class HTMLFileCache {
20 var $mTitle, $mFileCache;
22 function HTMLFileCache( &$title ) {
23 $this->mTitle =& $title;
24 $this->mFileCache = '';
27 function fileCacheName() {
28 global $wgFileCacheDirectory;
29 if( !$this->mFileCache ) {
30 $key = $this->mTitle->getPrefixedDbkey();
31 $hash = md5( $key );
32 $key = str_replace( '.', '%2E', urlencode( $key ) );
34 $hash1 = substr( $hash, 0, 1 );
35 $hash2 = substr( $hash, 0, 2 );
36 $this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
38 if($this->useGzip())
39 $this->mFileCache .= '.gz';
41 wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
43 return $this->mFileCache;
46 function isFileCached() {
47 return file_exists( $this->fileCacheName() );
50 function fileCacheTime() {
51 return wfTimestamp( TS_MW, filemtime( $this->fileCacheName() ) );
54 function isFileCacheGood( $timestamp ) {
55 global $wgCacheEpoch;
57 if( !$this->isFileCached() ) return false;
59 $cachetime = $this->fileCacheTime();
60 $good = (( $timestamp <= $cachetime ) &&
61 ( $wgCacheEpoch <= $cachetime ));
63 wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$timestamp} epoch {$wgCacheEpoch}, good $good\n");
64 return $good;
67 function useGzip() {
68 global $wgUseGzip;
69 return $wgUseGzip;
72 /* In handy string packages */
73 function fetchRawText() {
74 return file_get_contents( $this->fileCacheName() );
77 function fetchPageText() {
78 if( $this->useGzip() ) {
79 /* Why is there no gzfile_get_contents() or gzdecode()? */
80 return implode( '', gzfile( $this->fileCacheName() ) );
81 } else {
82 return $this->fetchRawText();
86 /* Working directory to/from output */
87 function loadFromFileCache() {
88 global $wgOut, $wgMimeType, $wgOutputEncoding, $wgContLanguageCode;
89 wfDebug(" loadFromFileCache()\n");
91 $filename=$this->fileCacheName();
92 $wgOut->sendCacheControl();
94 header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
95 header( "Content-language: $wgContLanguageCode" );
97 if( $this->useGzip() ) {
98 if( wfClientAcceptsGzip() ) {
99 header( 'Content-Encoding: gzip' );
100 } else {
101 /* Send uncompressed */
102 readgzfile( $filename );
103 return;
106 readfile( $filename );
109 function checkCacheDirs() {
110 $filename = $this->fileCacheName();
111 $mydir2=substr($filename,0,strrpos($filename,'/')); # subdirectory level 2
112 $mydir1=substr($mydir2,0,strrpos($mydir2,'/')); # subdirectory level 1
114 if(!file_exists($mydir1)) { mkdir($mydir1,0775); } # create if necessary
115 if(!file_exists($mydir2)) { mkdir($mydir2,0775); }
118 function saveToFileCache( $origtext ) {
119 $text = $origtext;
120 if(strcmp($text,'') == 0) return '';
122 wfDebug(" saveToFileCache()\n", false);
124 $this->checkCacheDirs();
126 $f = fopen( $this->fileCacheName(), 'w' );
127 if($f) {
128 $now = wfTimestampNow();
129 if( $this->useGzip() ) {
130 $rawtext = str_replace( '</html>',
131 '<!-- Cached/compressed '.$now." -->\n</html>",
132 $text );
133 $text = gzencode( $rawtext );
134 } else {
135 $text = str_replace( '</html>',
136 '<!-- Cached '.$now." -->\n</html>",
137 $text );
139 fwrite( $f, $text );
140 fclose( $f );
141 if( $this->useGzip() ) {
142 if( wfClientAcceptsGzip() ) {
143 header( 'Content-Encoding: gzip' );
144 return $text;
145 } else {
146 return $rawtext;
148 } else {
149 return $text;
152 return $text;