require_once( 'includes/Defines.php' );
require_once( './LocalSettings.php' );
require_once( 'includes/Setup.php' );
+require_once( 'includes/StreamFile.php' );
if( !isset( $_SERVER['PATH_INFO'] ) ) {
wfForbidden();
}
# Write file
-$type = wfGetType( $filename );
-if ( $type ) {
- header('Content-type: '.$type);
-} else {
- header('Content-type: application/x-wiki');
-}
-
-readfile( $filename );
-
-function wfGetType( $filename ) {
- # There's probably a better way to do this
- $types = <<<END_STRING
-application/andrew-inset ez
-application/mac-binhex40 hqx
-application/mac-compactpro cpt
-application/mathml+xml mathml
-application/msword doc
-application/octet-stream bin dms lha lzh exe class so dll
-application/oda oda
-application/ogg ogg
-application/pdf pdf
-application/postscript ai eps ps
-application/rdf+xml rdf
-application/smil smi smil
-application/srgs gram
-application/srgs+xml grxml
-application/vnd.mif mif
-application/vnd.ms-excel xls
-application/vnd.ms-powerpoint ppt
-application/vnd.wap.wbxml wbxml
-application/vnd.wap.wmlc wmlc
-application/vnd.wap.wmlscriptc wmlsc
-application/voicexml+xml vxml
-application/x-bcpio bcpio
-application/x-cdlink vcd
-application/x-chess-pgn pgn
-application/x-cpio cpio
-application/x-csh csh
-application/x-director dcr dir dxr
-application/x-dvi dvi
-application/x-futuresplash spl
-application/x-gtar gtar
-application/x-hdf hdf
-application/x-javascript js
-application/x-koan skp skd skt skm
-application/x-latex latex
-application/x-netcdf nc cdf
-application/x-sh sh
-application/x-shar shar
-application/x-shockwave-flash swf
-application/x-stuffit sit
-application/x-sv4cpio sv4cpio
-application/x-sv4crc sv4crc
-application/x-tar tar
-application/x-tcl tcl
-application/x-tex tex
-application/x-texinfo texinfo texi
-application/x-troff t tr roff
-application/x-troff-man man
-application/x-troff-me me
-application/x-troff-ms ms
-application/x-ustar ustar
-application/x-wais-source src
-application/xhtml+xml xhtml xht
-application/xslt+xml xslt
-application/xml xml xsl
-application/xml-dtd dtd
-application/zip zip
-audio/basic au snd
-audio/midi mid midi kar
-audio/mpeg mpga mp2 mp3
-audio/x-aiff aif aiff aifc
-audio/x-mpegurl m3u
-audio/x-pn-realaudio ram rm
-audio/x-pn-realaudio-plugin rpm
-audio/x-realaudio ra
-audio/x-wav wav
-chemical/x-pdb pdb
-chemical/x-xyz xyz
-image/bmp bmp
-image/cgm cgm
-image/gif gif
-image/ief ief
-image/jpeg jpeg jpg jpe
-image/png png
-image/svg+xml svg
-image/tiff tiff tif
-image/vnd.djvu djvu djv
-image/vnd.wap.wbmp wbmp
-image/x-cmu-raster ras
-image/x-icon ico
-image/x-portable-anymap pnm
-image/x-portable-bitmap pbm
-image/x-portable-graymap pgm
-image/x-portable-pixmap ppm
-image/x-rgb rgb
-image/x-xbitmap xbm
-image/x-xpixmap xpm
-image/x-xwindowdump xwd
-model/iges igs iges
-model/mesh msh mesh silo
-model/vrml wrl vrml
-text/calendar ics ifb
-text/css css
-text/richtext rtx
-text/rtf rtf
-text/sgml sgml sgm
-text/tab-separated-values tsv
-text/vnd.wap.wml wml
-text/vnd.wap.wmlscript wmls
-text/x-setext etx
-video/mpeg mpeg mpg mpe
-video/quicktime qt mov
-video/vnd.mpegurl mxu
-video/x-msvideo avi
-video/x-sgi-movie movie
-x-conference/x-cooltalk ice
-END_STRING;
- // Needed for windows servers who use \r\n not \n
- $endl = "
-";
- $types = explode( $endl, $types );
- if ( !preg_match( "/\.([^.]*?)$/", $filename, $matches ) ) {
- return false;
- }
-
- foreach( $types as $type ) {
- $extensions = explode( " ", $type );
- for ( $i=1; $i<count( $extensions ); $i++ ) {
- if ( $extensions[$i] == $matches[1] ) {
- return $extensions[0];
- }
- }
- }
- return false;
-}
+wfStreamFile( $filename );
function wfForbidden() {
header( 'HTTP/1.0 403 Forbidden' );
/** Cache shared metadata in memcached. Don't do this if the commons wiki is in a different memcached domain */
$wgCacheSharedUploads = true;
+/**
+ * Give a path here to use thumb.php for thumbnail generation on client request, instead of
+ * generating them on render and outputting a static URL. This is necessary if some of your
+ * apache servers don't have read/write access to the thumbnail path.
+ *
+ * Example:
+ * $wgThumnailScriptPath = "{$wgScriptPath}/thumb.php";
+ */
+$wgThumbnailScriptPath = false;
+$wgSharedThumbnailScriptPath = false;
+
+
/**
* Set the following to false especially if you have a set of files that need to
* be accessible by all wikis, and you do not want to use the hash (path/a/aa/)
/**
* Obsolete factory function, use constructor
*/
- function newFromTitle( &$title ) {
+ function newFromTitle( $title ) {
return new Image( $title );
}
- function Image( &$title ) {
+ function Image( $title ) {
$this->title =& $title;
$this->name = $title->getDBkey();
$this->height = $commonsCachedValues['height'];
$this->bits = $commonsCachedValues['bits'];
$this->type = $commonsCachedValues['type'];
+ $this->size = $commonsCachedValues['size'];
$this->fromSharedDirectory = true;
$this->dataLoaded = true;
}
$this->height = $cachedValues['height'];
$this->bits = $cachedValues['bits'];
$this->type = $cachedValues['type'];
+ $this->size = $cachedValues['size'];
$this->fromSharedDirectory = false;
$this->dataLoaded = true;
}
'width' => $this->width,
'height' => $this->height,
'bits' => $this->bits,
- 'type' => $this->type);
+ 'type' => $this->type,
+ 'size' => $this->size);
$wgMemc->set( $keys[0], $cachedValues );
}
* Load metadata from the file itself
*/
function loadFromFile() {
- global $wgUseSharedUploads, $wgSharedUploadDirectory;
+ global $wgUseSharedUploads, $wgSharedUploadDirectory, $wgLang;
$fname = 'Image::loadFromFile';
wfProfileIn( $fname );
$this->imagePath = $this->getFullPath();
$this->fileExists = file_exists( $this->imagePath );
$gis = false;
- # If the file is not found, and a non-wiki shared upload directory is used, look for it there.
+ # If the file is not found, and a shared upload directory is used, look for it there.
if (!$this->fileExists && $wgUseSharedUploads && $wgSharedUploadDirectory) {
# In case we're on a wgCapitalLinks=false wiki, we
# capitalize the first letter of the filename before
# looking it up in the shared repository.
- $this->name = $wgLang->ucfirst($name);
-
- $this->imagePath = $this->getFullPath(true);
- $this->fileExists = file_exists( $this->imagePath);
- $this->fromSharedDirectory = true;
+ $sharedImage = Image::newFromName( $wgLang->ucfirst($this->name) );
+ $this->fileExists = file_exists( $sharedImage->getFullPath(true) );
+ if ( $this->fileExists ) {
+ $this->name = $sharedImage->name;
+ $this->imagePath = $this->getFulPath(true);
+ $this->fromSharedDirectory = true;
+ }
}
if ( $this->fileExists ) {
if ( $height == -1 ) {
return $this->renderThumb( $width );
}
+ $this->load();
if ( $width < $this->width ) {
$thumbheight = $this->height * $width / $this->width;
$thumbwidth = $width;
$path = '/common/images/' . $icon;
$filepath = $wgStyleDirectory . $path;
if( file_exists( $filepath ) ) {
- return new ThumbnailImage( $filepath, $wgStylePath . $path );
+ return new ThumbnailImage( $wgStylePath . $path, 120, 120 );
}
}
return null;
* @return ThumbnailImage
* @access private
*/
- function /* private */ renderThumb( $width ) {
+ function /* private */ renderThumb( $width, $useScript = true ) {
global $wgImageMagickConvertCommand;
global $wgUseImageMagick;
global $wgUseSquid, $wgInternalServer;
-
+ global $wgThumbnailScriptPath, $wgSharedThumbnailScriptPath;
+
$width = IntVal( $width );
+ $this->load();
$thumbName = $this->thumbName( $width, $this->fromSharedDirectory );
$thumbPath = wfImageThumbDir( $thumbName, 'thumb', $this->fromSharedDirectory ).'/'.$thumbName;
$thumbUrl = $this->thumbUrl( $width );
if( $width > $this->width && !$this->mustRender() ) {
# Don't make an image bigger than the source
- return new ThumbnailImage( $this->getImagePath(), $this->getViewURL() );
+ return new ThumbnailImage( $this->getViewURL(), $this->getWidth(), $this->getHeight() );
+ }
+
+ $height = floor( $this->height * ( $width/$this->width ) );
+
+ // Generate thumb.php URL if possible
+ $thumbScript = false;
+ $scriptUrl = false;
+
+ if ( $this->fromSharedDirectory ) {
+ if ( $wgSharedThumbnailScriptPath ) {
+ $thumbScript = $wgSharedThumbnailScriptPath;
+ }
+ } else {
+ if ( $wgThumbnailScriptPath ) {
+ $thumbScript = $wgThumbnailScriptPath;
+ }
+ }
+ if ( $thumbScript ) {
+ $scriptUrl = $thumbScript . '?f=' . urlencode( $this->name ) . '&w=' . urlencode( $width );
+ if ( $useScript ) {
+ // Use thumb.php to render the image
+ return new ThumbnailImage( , $width, $height );
+ }
}
if ( (! file_exists( $thumbPath ) ) || ( filemtime($thumbPath) < filemtime($this->imagePath) ) ) {
return 'Image type not supported';
break;
}
- $height = floor( $this->height * ( $width/$this->width ) );
if ( $truecolor ) {
$dst_image = imagecreatetruecolor( $width, $height );
} else {
$urlArr = Array(
$wgInternalServer.$thumbUrl
);
+ if ( $scriptUrl ) {
+ $urlArr[] = $scriptUrl;
+ }
wfPurgeSquidServers($urlArr);
}
}
- return new ThumbnailImage( $thumbPath, $thumbUrl );
+ return new ThumbnailImage( $thumbUrl, $width, $height );
} // END OF function createThumb
/**
* Returns the image directory of an image
* If the directory does not exist, it is created.
* The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
*
* @param string $fname file name of the image file
* @access public
* Returns the image directory of an image's thubnail
* If the directory does not exist, it is created.
* The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
*
* @param string $fname file name of the thumbnail file, including file size prefix
* @param string $subdir (optional) subdirectory of the image upload directory that should be used for storing the thumbnail. Default is 'thumb'
* Returns the image directory of an image's old version
* If the directory does not exist, it is created.
* The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
*
* @param string $fname file name of the thumbnail file, including file size prefix
* @param string $subdir (optional) subdirectory of the image upload directory that should be used for storing the old version. Default is 'archive'
* @param string $url URL path to the thumb
* @access private
*/
- function ThumbnailImage( $path, $url ) {
+ function ThumbnailImage( $url, $width, $height ) {
$this->url = $url;
- $this->path = $path;
- $size = @getimagesize( $this->path );
- if( $size ) {
- $this->width = $size[0];
- $this->height = $size[1];
- } else {
- $this->width = 0;
- $this->height = 0;
- }
+ $this->width = $width;
+ $this->height = $height;
}
/**
return $html;
}
- /**
- * Return the size of the thumbnail file, in bytes or false if the file
- * can't be stat().
- * @access public
- */
- function getSize() {
- $st = stat( $this->path );
- if( $st ) {
- return $st['size'];
- } else {
- return false;
- }
- }
}
?>
/**
- * isEmpty() returns false iff the gallery doesn't contain any images
+ * isEmpty() returns true if the gallery contains no images
*/
function isEmpty() {
return empty( $this->mImages );
} else {
$nb = wfMsg( 'filemissing' );
}
- $nb = htmlspecialchars( $nb ) . '<br />';
+ $nb = htmlspecialchars( $nb ) . "<br />\n";
} else {
$nb = '';
}
$textlink = $this->mShowFilename ?
- $sk->makeKnownLinkObj( $nt, htmlspecialchars( $wgLang->truncate( $nt->getText(), 20, '...' ) ) ) . '<br />' :
+ $sk->makeKnownLinkObj( $nt, htmlspecialchars( $wgLang->truncate( $nt->getText(), 20, '...' ) ) ) . "<br />\n" :
'' ;
$s .= ($i%4==0) ? '<tr>' : '';
$img = Image::newFromTitle( $nt );
$ul = $sk->makeLinkObj( Title::makeTitle( NS_USER, $ut ), $ut );
- $gallery->add( $img, $ul.'<br /><i>'.$wgLang->timeanddate( $s->img_timestamp, true ).'</i><br />' );
+ $gallery->add( $img, "$ul<br />\n<i>".$wgLang->timeanddate( $s->img_timestamp, true )."</i><br />\n" );
- $timestamp = wfTImestamp( TS_MW, $s->img_timestamp );
+ $timestamp = wfTimestamp( TS_MW, $s->img_timestamp );
if( empty( $firstTimestamp ) ) {
$firstTimestamp = $timestamp;
}
--- /dev/null
+<?php
+
+function wfStreamFile( $fname ) {
+ global $wgSquidMaxage;
+ $stat = stat( $fname );
+ if ( !$stat ) {
+ header( 'HTTP/1.0 404 Not Found' );
+ echo "<html><body>
+<h1>File not found</h1>
+<p>Although this PHP script ({$_SERVER['SCRIPT_NAME']}) exists, the file requested for output
+does not.</p>
+</body></html>";
+ return;
+ }
+
+
+ $type = wfGetType( $fname );
+ if ( $type ) {
+ header("Content-type: $type");
+ } else {
+ header('Content-type: application/x-wiki');
+ }
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) );
+ header( "Cache-Control: s-maxage=$wgSquidMaxage, must-revalidate, max-age=0" );
+ readfile( $fname );
+ exit;
+}
+
+function wfGetType( $filename ) {
+ # There's probably a better way to do this
+ $types = <<<END_STRING
+application/andrew-inset ez
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/mathml+xml mathml
+application/msword doc
+application/octet-stream bin dms lha lzh exe class so dll
+application/oda oda
+application/ogg ogg
+application/pdf pdf
+application/postscript ai eps ps
+application/rdf+xml rdf
+application/smil smi smil
+application/srgs gram
+application/srgs+xml grxml
+application/vnd.mif mif
+application/vnd.ms-excel xls
+application/vnd.ms-powerpoint ppt
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/voicexml+xml vxml
+application/x-bcpio bcpio
+application/x-cdlink vcd
+application/x-chess-pgn pgn
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-futuresplash spl
+application/x-gtar gtar
+application/x-hdf hdf
+application/x-javascript js
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/xhtml+xml xhtml xht
+application/xslt+xml xslt
+application/xml xml xsl
+application/xml-dtd dtd
+application/zip zip
+audio/basic au snd
+audio/midi mid midi kar
+audio/mpeg mpga mp2 mp3
+audio/x-aiff aif aiff aifc
+audio/x-mpegurl m3u
+audio/x-pn-realaudio ram rm
+audio/x-pn-realaudio-plugin rpm
+audio/x-realaudio ra
+audio/x-wav wav
+chemical/x-pdb pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm cgm
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/png png
+image/svg+xml svg
+image/tiff tiff tif
+image/vnd.djvu djvu djv
+image/vnd.wap.wbmp wbmp
+image/x-cmu-raster ras
+image/x-icon ico
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+model/iges igs iges
+model/mesh msh mesh silo
+model/vrml wrl vrml
+text/calendar ics ifb
+text/css css
+text/richtext rtx
+text/rtf rtf
+text/sgml sgml sgm
+text/tab-separated-values tsv
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-setext etx
+video/mpeg mpeg mpg mpe
+video/quicktime qt mov
+video/vnd.mpegurl mxu
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
+END_STRING;
+ // Needed for windows servers who use \r\n not \n
+ $endl = "
+";
+ $types = explode( $endl, $types );
+ if ( !preg_match( "/\.([^.]*?)$/", $filename, $matches ) ) {
+ return false;
+ }
+
+ foreach( $types as $type ) {
+ $extensions = explode( " ", $type );
+ for ( $i=1; $i<count( $extensions ); $i++ ) {
+ if ( $extensions[$i] == $matches[1] ) {
+ return $extensions[0];
+ }
+ }
+ }
+ return false;
+}
+
+?>
--- /dev/null
+<?php
+
+/**
+ * PHP script to stream out an image thumbnail.
+ * If the file exists, we make do with abridged MediaWiki initialisation.
+ */
+
+unset( $IP );
+define( 'MEDIAWIKI', true );
+require_once( './includes/Defines.php' );
+require_once( './LocalSettings.php' );
+require_once( 'Image.php' );
+require_once( 'StreamFile.php' );
+
+// Get input parameters
+
+if ( get_magic_quotes_gpc() ) {
+ $fileName = stripslashes( $_REQUEST['f'] );
+ $width = stripslashes( $_REQUEST['w'] );
+} else {
+ $fileName = $_REQUEST['f'];
+ $width = $_REQUEST['w'];
+}
+
+// Some basic input validation
+
+$width = intval( $width );
+$fileName = str_replace( '/', '_', $fileName );
+
+// Work out paths, carefully avoiding constructing an Image object because that won't work yet
+
+$imagePath = wfImageDir( $fileName ) . '/' . $fileName;
+$thumbName = "{$width}px-$fileName";
+if ( preg_match( '/\.svg$/', $fileName ) ) {
+ $thumbName .= '.png';
+}
+$thumbPath = wfImageThumbDir( $thumbName ) . '/' . $thumbName;
+
+if ( file_exists( $thumbPath ) && filemtime( $thumbPath ) >= filemtime( $imagePath ) ) {
+ wfStreamFile( $thumbPath );
+ exit;
+}
+
+// OK, no valid thumbnail, time to get out the heavy machinery
+require_once( 'Setup.php' );
+
+// Force renderThumb() to actually do something
+$wgThumbnailScriptPath = false;
+$wgSharedThumbnailScriptPath = false;
+
+$img = Image::newFromName( $fileName );
+if ( $img ) {
+ $thumb = $img->renderThumb( $width );
+} else {
+ $thumb = false;
+}
+
+if ( $thumb ) {
+ wfStreamFile( $thumb->path );
+} else {
+ $badtitle = wfMsg( 'badtitle' );
+ $badtitletext = wfMsg( 'badtitletext' );
+ echo "<html><head>
+ <title>$badtitle</title>
+ <body>
+<h1>$badtitle</h1>
+<p>$badtitletext</p>
+</body></html>";
+}
+
+
+?>