';
}
if ( !$this->mDestWarningAck ) {
$warning .= self::getExistsWarning( $this->mLocalFile );
}
$warning .= $this->getDupeWarning( $this->mTempPath, $finalExt, $nt );
if( $warning != '' ) {
/**
* Stash the file in a temporary location; the user can choose
* to let it through and we'll complete the upload then.
*/
$resultDetails = array( 'warning' => $warning );
return self::UPLOAD_WARNING;
}
}
/**
* Try actually saving the thing...
* It will show an error form on failure.
*/
if( !$this->mForReUpload ) {
$pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
$this->mCopyrightStatus, $this->mCopyrightSource );
}
$status = $this->mLocalFile->upload( $this->mTempPath, $this->mComment, $pageText,
File::DELETE_SOURCE, $this->mFileProps );
if ( !$status->isGood() ) {
$resultDetails = array( 'internal' => $status->getWikiText() );
return self::INTERNAL_ERROR;
} else {
if ( $this->mWatchthis ) {
global $wgUser;
$wgUser->addWatch( $this->mLocalFile->getTitle() );
}
// Success, redirect to description page
$img = null; // @todo: added to avoid passing a ref to null - should this be defined somewhere?
wfRunHooks( 'UploadComplete', array( &$this ) );
return self::SUCCESS;
}
}
/**
* Do existence checks on a file and produce a warning
* This check is static and can be done pre-upload via AJAX
* Returns an HTML fragment consisting of one or more LI elements if there is a warning
* Returns an empty string if there is no warning
*/
static function getExistsWarning( $file ) {
global $wgUser, $wgContLang;
// Check for uppercase extension. We allow these filenames but check if an image
// with lowercase extension exists already
$warning = '';
$align = $wgContLang->isRtl() ? 'left' : 'right';
if( strpos( $file->getName(), '.' ) == false ) {
$partname = $file->getName();
$rawExtension = '';
} else {
$n = strrpos( $file->getName(), '.' );
$rawExtension = substr( $file->getName(), $n + 1 );
$partname = substr( $file->getName(), 0, $n );
}
$sk = $wgUser->getSkin();
if ( $rawExtension != $file->getExtension() ) {
// We're not using the normalized form of the extension.
// Normal form is lowercase, using most common of alternate
// extensions (eg 'jpg' rather than 'JPEG').
//
// Check for another file using the normalized form...
$nt_lc = Title::makeTitle( NS_FILE, $partname . '.' . $file->getExtension() );
$file_lc = wfLocalFile( $nt_lc );
} else {
$file_lc = false;
}
if( $file->exists() ) {
$dlink = $sk->makeKnownLinkObj( $file->getTitle() );
if ( $file->allowInlineDisplay() ) {
$dlink2 = $sk->makeImageLinkObj( $file->getTitle(), wfMsgExt( 'fileexists-thumb', 'parseinline' ),
$file->getName(), $align, array(), false, true );
} elseif ( !$file->allowInlineDisplay() && $file->isSafeFile() ) {
$icon = $file->iconThumb();
$dlink2 = '
';
break;
}
}
if ( $file->wasDeleted() && !$file->exists() ) {
# If the file existed before and was deleted, warn the user of this
# Don't bother doing so if the file exists now, however
$ltitle = SpecialPage::getTitleFor( 'Log' );
$llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ),
'type=delete&page=' . $file->getTitle()->getPrefixedUrl() );
$warning .= '
' . wfMsgWikiHtml( 'filewasdeleted', $llink ) . '
';
}
return $warning;
}
/**
* Get a list of warnings
*
* @param string local filename, e.g. 'file exists', 'non-descriptive filename'
* @return array list of warning messages
*/
static function ajaxGetExistsWarning( $filename ) {
$file = wfFindFile( $filename );
if( !$file ) {
// Force local file so we have an object to do further checks against
// if there isn't an exact match...
$file = wfLocalFile( $filename );
}
$s = ' ';
if ( $file ) {
$warning = self::getExistsWarning( $file );
if ( $warning !== '' ) {
$s = "
$warning
";
}
}
return $s;
}
/**
* Render a preview of a given license for the AJAX preview on upload
*
* @param string $license
* @return string
*/
public static function ajaxGetLicensePreview( $license ) {
global $wgParser, $wgUser;
$text = '{{' . $license . '}}';
$title = Title::makeTitle( NS_FILE, 'Sample.jpg' );
$options = ParserOptions::newFromUser( $wgUser );
// Expand subst: first, then live templates...
$text = $wgParser->preSaveTransform( $text, $title, $wgUser, $options );
$output = $wgParser->parse( $text, $title, $options );
return $output->getText();
}
/**
* Check for duplicate files and throw up a warning before the upload
* completes.
*/
function getDupeWarning( $tempfile, $extension, $destinationTitle ) {
$hash = File::sha1Base36( $tempfile );
$dupes = RepoGroup::singleton()->findBySha1( $hash );
$archivedImage = new ArchivedFile( null, 0, $hash.".$extension" );
if( $dupes ) {
global $wgOut;
$msg = "";
foreach( $dupes as $file ) {
$title = $file->getTitle();
# Don't throw the warning when the titles are the same, it's a reupload
# and highly redundant.
if ( !$title->equals( $destinationTitle ) || !$this->mForReUpload ) {
$msg .= $title->getPrefixedText() .
"|" . $title->getText() . "\n";
}
}
$msg .= "";
return "
\n";
} elseif ( $archivedImage->getID() > 0 ) {
global $wgOut;
$name = Title::makeTitle( NS_FILE, $archivedImage->getName() )->getPrefixedText();
return Xml::tags( 'li', null, wfMsgExt( 'file-deleted-duplicate', array( 'parseinline' ), array( $name ) ) );
} else {
return '';
}
}
/**
* Get a list of blacklisted filename prefixes from [[MediaWiki:filename-prefix-blacklist]]
*
* @return array list of prefixes
*/
public static function getFilenamePrefixBlacklist() {
$blacklist = array();
$message = wfMsgForContent( 'filename-prefix-blacklist' );
if( $message && !( wfEmptyMsg( 'filename-prefix-blacklist', $message ) || $message == '-' ) ) {
$lines = explode( "\n", $message );
foreach( $lines as $line ) {
// Remove comment lines
$comment = substr( trim( $line ), 0, 1 );
if ( $comment == '#' || $comment == '' ) {
continue;
}
// Remove additional comments after a prefix
$comment = strpos( $line, '#' );
if ( $comment > 0 ) {
$line = substr( $line, 0, $comment-1 );
}
$blacklist[] = trim( $line );
}
}
return $blacklist;
}
/**
* Stash a file in a temporary directory for later processing
* after the user has confirmed it.
*
* If the user doesn't explicitly cancel or accept, these files
* can accumulate in the temp directory.
*
* @param string $saveName - the destination filename
* @param string $tempName - the source temporary file to save
* @return string - full path the stashed file, or false on failure
* @access private
*/
function saveTempUploadedFile( $saveName, $tempName ) {
global $wgOut;
$repo = RepoGroup::singleton()->getLocalRepo();
$status = $repo->storeTemp( $saveName, $tempName );
if ( !$status->isGood() ) {
$this->showError( $status->getWikiText() );
return false;
} else {
return $status->value;
}
}
/**
* Stash a file in a temporary directory for later processing,
* and save the necessary descriptive info into the session.
* Returns a key value which will be passed through a form
* to pick up the path info on a later invocation.
*
* @return int
* @access private
*/
function stashSession() {
$stash = $this->saveTempUploadedFile( $this->mDestName, $this->mTempPath );
if( !$stash ) {
# Couldn't save the file.
return false;
}
$key = mt_rand( 0, 0x7fffffff );
$_SESSION['wsUploadData'][$key] = array(
'mTempPath' => $stash,
'mFileSize' => $this->mFileSize,
'mSrcName' => $this->mSrcName,
'mFileProps' => $this->mFileProps,
'version' => self::SESSION_VERSION,
);
return $key;
}
/**
* Remove a temporarily kept file stashed by saveTempUploadedFile().
* @access private
* @return success
*/
function unsaveUploadedFile() {
global $wgOut;
if( !$this->mTempPath ) return true; // nothing to delete
$repo = RepoGroup::singleton()->getLocalRepo();
$success = $repo->freeTemp( $this->mTempPath );
if ( ! $success ) {
$wgOut->showFileDeleteError( $this->mTempPath );
return false;
} else {
return true;
}
}
/* -------------------------------------------------------------- */
/**
* @param string $error as HTML
* @access private
*/
function uploadError( $error ) {
global $wgOut;
$wgOut->addHTML( '
' . wfMsgHtml( 'uploadwarning' ) . "
\n" );
$wgOut->addHTML( '' . $error . '' );
}
/**
* There's something wrong with this file, not enough to reject it
* totally but we require manual intervention to save it for real.
* Stash it away, then present a form asking to confirm or cancel.
*
* @param string $warning as HTML
* @access private
*/
function uploadWarning( $warning ) {
global $wgOut;
global $wgUseCopyrightUpload;
$this->mSessionKey = $this->stashSession();
if( !$this->mSessionKey ) {
# Couldn't save file; an error has been displayed so let's go.
return;
}
$wgOut->addHTML( '
\n" );
# Print a list of allowed file extensions, if so configured. We ignore
# MIME type here, it's incomprehensible to most people and too long.
global $wgCheckFileExtensions, $wgStrictFileExtensions,
$wgFileExtensions, $wgFileBlacklist;
$allowedExtensions = '';
if( $wgCheckFileExtensions ) {
if( $wgStrictFileExtensions ) {
# Everything not permitted is banned
$extensionsList =
'
" .
Xml::closeElement( 'table' ) .
Xml::hidden( 'wpDestFileWarningAck', '', array( 'id' => 'wpDestFileWarningAck' ) ) .
Xml::hidden( 'wpForReUpload', $this->mForReUpload, array( 'id' => 'wpForReUpload' ) ) .
Xml::closeElement( 'fieldset' ) .
Xml::closeElement( 'form' )
);
$uploadfooter = wfMsgNoTrans( 'uploadfooter' );
if( $uploadfooter != '-' && !wfEmptyMsg( 'uploadfooter', $uploadfooter ) ){
$wgOut->addWikiText( '' );
}
}
/* -------------------------------------------------------------- */
/**
* See if we should check the 'watch this page' checkbox on the form
* based on the user's preferences and whether we're being asked
* to create a new file or update an existing one.
*
* In the case where 'watch edits' is off but 'watch creations' is on,
* we'll leave the box unchecked.
*
* Note that the page target can be changed *on the form*, so our check
* state can get out of sync.
*/
function watchCheck() {
global $wgUser;
if( $wgUser->getOption( 'watchdefault' ) ) {
// Watch all edits!
return true;
}
$local = wfLocalFile( $this->mDesiredDestName );
if( $local && $local->exists() ) {
// We're uploading a new version of an existing file.
// No creation, so don't watch it if we're not already.
return $local->getTitle()->userIsWatching();
} else {
// New page should get watched if that's our option.
return $wgUser->getOption( 'watchcreations' );
}
}
/**
* Split a file into a base name and all dot-delimited 'extensions'
* on the end. Some web server configurations will fall back to
* earlier pseudo-'extensions' to determine type and execute
* scripts, so the blacklist needs to check them all.
*
* @return array
*/
public function splitExtensions( $filename ) {
$bits = explode( '.', $filename );
$basename = array_shift( $bits );
return array( $basename, $bits );
}
/**
* Perform case-insensitive match against a list of file extensions.
* Returns true if the extension is in the list.
*
* @param string $ext
* @param array $list
* @return bool
*/
function checkFileExtension( $ext, $list ) {
return in_array( strtolower( $ext ), $list );
}
/**
* Perform case-insensitive match against a list of file extensions.
* Returns true if any of the extensions are in the list.
*
* @param array $ext
* @param array $list
* @return bool
*/
public function checkFileExtensionList( $ext, $list ) {
foreach( $ext as $e ) {
if( in_array( strtolower( $e ), $list ) ) {
return true;
}
}
return false;
}
/**
* Verifies that it's ok to include the uploaded file
*
* @param string $tmpfile the full path of the temporary file to verify
* @param string $extension The filename extension that the file is to be served with
* @return mixed true of the file is verified, a WikiError object otherwise.
*/
function verify( $tmpfile, $extension ) {
#magically determine mime type
$magic = MimeMagic::singleton();
$mime = $magic->guessMimeType($tmpfile,false);
#check mime type, if desired
global $wgVerifyMimeType;
if ($wgVerifyMimeType) {
wfDebug ( "\n\nmime: <$mime> extension: <$extension>\n\n");
#check mime type against file extension
if( !self::verifyExtension( $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadcorrupt' );
}
#check mime type blacklist
global $wgMimeTypeBlacklist;
if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist) ) {
if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) );
}
# Check IE type
$fp = fopen( $tmpfile, 'rb' );
$chunk = fread( $fp, 256 );
fclose( $fp );
$extMime = $magic->guessTypesForExtension( $extension );
$ieTypes = $magic->getIEMimeTypes( $tmpfile, $chunk, $extMime );
foreach ( $ieTypes as $ieType ) {
if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
return new WikiErrorMsg( 'filetype-bad-ie-mime', $ieType );
}
}
}
}
#check for htmlish code and javascript
if( $this->detectScript ( $tmpfile, $mime, $extension ) ) {
return new WikiErrorMsg( 'uploadscripted' );
}
if( $extension == 'svg' || $mime == 'image/svg+xml' ) {
if( $this->detectScriptInSvg( $tmpfile ) ) {
return new WikiErrorMsg( 'uploadscripted' );
}
}
/**
* Scan the uploaded file for viruses
*/
$virus= $this->detectVirus($tmpfile);
if ( $virus ) {
return new WikiErrorMsg( 'uploadvirus', htmlspecialchars($virus) );
}
wfDebug( __METHOD__.": all clear; passing.\n" );
return true;
}
/**
* Checks if the mime type of the uploaded file matches the file extension.
*
* @param string $mime the mime type of the uploaded file
* @param string $extension The filename extension that the file is to be served with
* @return bool
*/
static function verifyExtension( $mime, $extension ) {
$magic = MimeMagic::singleton();
if ( ! $mime || $mime == 'unknown' || $mime == 'unknown/unknown' )
if ( ! $magic->isRecognizableExtension( $extension ) ) {
wfDebug( __METHOD__.": passing file with unknown detected mime type; " .
"unrecognized extension '$extension', can't verify\n" );
return true;
} else {
wfDebug( __METHOD__.": rejecting file with unknown detected mime type; ".
"recognized extension '$extension', so probably invalid file\n" );
return false;
}
$match= $magic->isMatchingExtension($extension,$mime);
if ($match===NULL) {
wfDebug( __METHOD__.": no file extension known for mime type $mime, passing file\n" );
return true;
} elseif ($match===true) {
wfDebug( __METHOD__.": mime type $mime matches extension $extension, passing file\n" );
#TODO: if it's a bitmap, make sure PHP or ImageMagic resp. can handle it!
return true;
} else {
wfDebug( __METHOD__.": mime type $mime mismatches file extension $extension, rejecting file\n" );
return false;
}
}
/**
* Heuristic for detecting files that *could* contain JavaScript instructions or
* things that may look like HTML to a browser and are thus
* potentially harmful. The present implementation will produce false positives in some situations.
*
* @param string $file Pathname to the temporary upload file
* @param string $mime The mime type of the file
* @param string $extension The extension of the file
* @return bool true if the file contains something looking like embedded scripts
*/
function detectScript($file, $mime, $extension) {
global $wgAllowTitlesInSVG;
#ugly hack: for text files, always look at the entire file.
#For binarie field, just check the first K.
if (strpos($mime,'text/')===0) $chunk = file_get_contents( $file );
else {
$fp = fopen( $file, 'rb' );
$chunk = fread( $fp, 1024 );
fclose( $fp );
}
$chunk= strtolower( $chunk );
if (!$chunk) return false;
#decode from UTF-16 if needed (could be used for obfuscation).
if (substr($chunk,0,2)=="\xfe\xff") $enc= "UTF-16BE";
elseif (substr($chunk,0,2)=="\xff\xfe") $enc= "UTF-16LE";
else $enc= NULL;
if ($enc) $chunk= iconv($enc,"ASCII//IGNORE",$chunk);
$chunk= trim($chunk);
#FIXME: convert from UTF-16 if necessarry!
wfDebug("SpecialUpload::detectScript: checking for embedded scripts and HTML stuff\n");
#check for HTML doctype
if (eregi("filterMatch;
}
/**
* @todo Replace this with a whitelist filter!
*/
function checkSvgScriptCallback( $element, $attribs ) {
$stripped = $this->stripXmlNamespace( $element );
if( $stripped == 'script' ) {
wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" );
return true;
}
foreach( $attribs as $attrib => $value ) {
$stripped = $this->stripXmlNamespace( $attrib );
if( substr( $stripped, 0, 2 ) == 'on' ) {
wfDebug( __METHOD__ . ": Found script attribute '$attrib'='value' in uploaded file.\n" );
return true;
}
if( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) {
wfDebug( __METHOD__ . ": Found script href attribute '$attrib'='$value' in uploaded file.\n" );
return true;
}
}
}
private function stripXmlNamespace( $name ) {
// 'http://www.w3.org/2000/svg:script' -> 'script'
$parts = explode( ':', strtolower( $name ) );
return array_pop( $parts );
}
/**
* Generic wrapper function for a virus scanner program.
* This relies on the $wgAntivirus and $wgAntivirusSetup variables.
* $wgAntivirusRequired may be used to deny upload if the scan fails.
*
* @param string $file Pathname to the temporary upload file
* @return mixed false if not virus is found, NULL if the scan fails or is disabled,
* or a string containing feedback from the virus scanner if a virus was found.
* If textual feedback is missing but a virus was found, this function returns true.
*/
function detectVirus($file) {
global $wgAntivirus, $wgAntivirusSetup, $wgAntivirusRequired, $wgOut;
if ( !$wgAntivirus ) {
wfDebug( __METHOD__.": virus scanner disabled\n");
return NULL;
}
if ( !$wgAntivirusSetup[$wgAntivirus] ) {
wfDebug( __METHOD__.": unknown virus scanner: $wgAntivirus\n" );
$wgOut->wrapWikiMsg( '
$1
', array( 'virus-badscanner', $wgAntivirus ) );
return wfMsg('virus-unknownscanner') . " $wgAntivirus";
}
# look up scanner configuration
$command = $wgAntivirusSetup[$wgAntivirus]["command"];
$exitCodeMap = $wgAntivirusSetup[$wgAntivirus]["codemap"];
$msgPattern = isset( $wgAntivirusSetup[$wgAntivirus]["messagepattern"] ) ?
$wgAntivirusSetup[$wgAntivirus]["messagepattern"] : null;
if ( strpos( $command,"%f" ) === false ) {
# simple pattern: append file to scan
$command .= " " . wfEscapeShellArg( $file );
} else {
# complex pattern: replace "%f" with file to scan
$command = str_replace( "%f", wfEscapeShellArg( $file ), $command );
}
wfDebug( __METHOD__.": running virus scan: $command \n" );
# execute virus scanner
$exitCode = false;
#NOTE: there's a 50 line workaround to make stderr redirection work on windows, too.
# that does not seem to be worth the pain.
# Ask me (Duesentrieb) about it if it's ever needed.
$output = array();
if ( wfIsWindows() ) {
exec( "$command", $output, $exitCode );
} else {
exec( "$command 2>&1", $output, $exitCode );
}
# map exit code to AV_xxx constants.
$mappedCode = $exitCode;
if ( $exitCodeMap ) {
if ( isset( $exitCodeMap[$exitCode] ) ) {
$mappedCode = $exitCodeMap[$exitCode];
} elseif ( isset( $exitCodeMap["*"] ) ) {
$mappedCode = $exitCodeMap["*"];
}
}
if ( $mappedCode === AV_SCAN_FAILED ) {
# scan failed (code was mapped to false by $exitCodeMap)
wfDebug( __METHOD__.": failed to scan $file (code $exitCode).\n" );
if ( $wgAntivirusRequired ) {
return wfMsg('virus-scanfailed', array( $exitCode ) );
} else {
return NULL;
}
} else if ( $mappedCode === AV_SCAN_ABORTED ) {
# scan failed because filetype is unknown (probably imune)
wfDebug( __METHOD__.": unsupported file type $file (code $exitCode).\n" );
return NULL;
} else if ( $mappedCode === AV_NO_VIRUS ) {
# no virus found
wfDebug( __METHOD__.": file passed virus scan.\n" );
return false;
} else {
$output = join( "\n", $output );
$output = trim( $output );
if ( !$output ) {
$output = true; #if there's no output, return true
} elseif ( $msgPattern ) {
$groups = array();
if ( preg_match( $msgPattern, $output, $groups ) ) {
if ( $groups[1] ) {
$output = $groups[1];
}
}
}
wfDebug( __METHOD__.": FOUND VIRUS! scanner feedback: $output \n" );
return $output;
}
}
/**
* Check if the temporary file is MacBinary-encoded, as some uploads
* from Internet Explorer on Mac OS Classic and Mac OS X will be.
* If so, the data fork will be extracted to a second temporary file,
* which will then be checked for validity and either kept or discarded.
*
* @access private
*/
function checkMacBinary() {
$macbin = new MacBinary( $this->mTempPath );
if( $macbin->isValid() ) {
$dataFile = tempnam( wfTempDir(), "WikiMacBinary" );
$dataHandle = fopen( $dataFile, 'wb' );
wfDebug( "SpecialUpload::checkMacBinary: Extracting MacBinary data fork to $dataFile\n" );
$macbin->extractData( $dataHandle );
$this->mTempPath = $dataFile;
$this->mFileSize = $macbin->dataForkLength();
// We'll have to manually remove the new file if it's not kept.
$this->mRemoveTempFile = true;
}
$macbin->close();
}
/**
* If we've modified the upload file we need to manually remove it
* on exit to clean up.
* @access private
*/
function cleanupTempFile() {
if ( $this->mRemoveTempFile && $this->mTempPath && file_exists( $this->mTempPath ) ) {
wfDebug( "SpecialUpload::cleanupTempFile: Removing temporary file {$this->mTempPath}\n" );
unlink( $this->mTempPath );
}
}
/**
* Check if there's an overwrite conflict and, if so, if restrictions
* forbid this user from performing the upload.
*
* @return mixed true on success, WikiError on failure
* @access private
*/
function checkOverwrite( $name ) {
$img = wfFindFile( $name );
$error = '';
if( $img ) {
global $wgUser, $wgOut;
if( $img->isLocal() ) {
if( !self::userCanReUpload( $wgUser, $img->name ) ) {
$error = 'fileexists-forbidden';
}
} else {
if( !$wgUser->isAllowed( 'reupload' ) ||
!$wgUser->isAllowed( 'reupload-shared' ) ) {
$error = "fileexists-shared-forbidden";
}
}
}
if( $error ) {
$errorText = wfMsg( $error, wfEscapeWikiText( $img->getName() ) );
return $errorText;
}
// Rockin', go ahead and upload
return true;
}
/**
* Check if a user is the last uploader
*
* @param User $user
* @param string $img, image name
* @return bool
*/
public static function userCanReUpload( User $user, $img ) {
if( $user->isAllowed( 'reupload' ) )
return true; // non-conditional
if( !$user->isAllowed( 'reupload-own' ) )
return false;
$dbr = wfGetDB( DB_SLAVE );
$row = $dbr->selectRow('image',
/* SELECT */ 'img_user',
/* WHERE */ array( 'img_name' => $img )
);
if ( !$row )
return false;
return $user->getId() == $row->img_user;
}
/**
* Display an error with a wikitext description
*/
function showError( $description ) {
global $wgOut;
$wgOut->setPageTitle( wfMsg( "internalerror" ) );
$wgOut->setRobotPolicy( "noindex,nofollow" );
$wgOut->setArticleRelated( false );
$wgOut->enableClientCache( false );
$wgOut->addWikiText( $description );
}
/**
* Get the initial image page text based on a comment and optional file status information
*/
static function getInitialPageText( $comment, $license, $copyStatus, $source ) {
global $wgUseCopyrightUpload;
if ( $wgUseCopyrightUpload ) {
if ( $license != '' ) {
$licensetxt = '== ' . wfMsgForContent( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n";
}
$pageText = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $comment . "\n" .
'== ' . wfMsgForContent ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" .
"$licensetxt" .
'== ' . wfMsgForContent ( 'filesource' ) . " ==\n" . $source ;
} else {
if ( $license != '' ) {
$filedesc = $comment == '' ? '' : '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $comment . "\n";
$pageText = $filedesc .
'== ' . wfMsgForContent ( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n";
} else {
$pageText = $comment;
}
}
return $pageText;
}
/**
* If there are rows in the deletion log for this file, show them,
* along with a nice little note for the user
*
* @param OutputPage $out
* @param string filename
*/
private function showDeletionLog( $out, $filename ) {
global $wgUser;
$loglist = new LogEventsList( $wgUser->getSkin(), $out );
$pager = new LogPager( $loglist, 'delete', false, $filename );
if( $pager->getNumRows() > 0 ) {
$out->addHTML( '