Wiki Upload Fix

From WolfTech
Jump to navigation Jump to search

How It Works

NEWEST CHANGES AT BOTTOM

The idea behind this is that the fopen(), fclose(), fread() calls that MediaWiki uses don't have access to the /tmp/ directory where uploaded files are temporarily stored. The move_uploaded_file() function however does have access to move PHP uploaded files out of the /tmp. What we're doing here is taking the uploaded file from the /tmp directory, uploading it to a local location we can access, then substituting server's temporary $_FILES[file]['tmp_name'] variable with where we've put the new file. The wiki has access to this folder and therefore can do all the necessary checks.

The only thing we need to make sure gets done is cleanup of the files sitting in our tmp directory, thus we edit the files below to take care of that.

Code Changes

Make sure there is a "tmp" folder in the main folder of your Wiki directory. Give it the AFS permissions necessary to be writeable by the Engineering web servers.

Open includes/SpecialUpload.php and find:

		$status = $this->mLocalFile->upload( $this->mTempPath, $this->mComment, $pageText, 
			File::DELETE_SOURCE, $this->mFileProps );
		if ( !$status->isGood() ) {
			$this->showError( $status->getWikiText() );
		} else {
			if ( $this->mWatchthis ) {
				global $wgUser;
				$wgUser->addWatch( $this->mLocalFile->getTitle() );
			}
			// Success, redirect to description page
			$wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() );
			$img = null; // @todo: added to avoid passing a ref to null - should this be defined somewhere?
			wfRunHooks( 'UploadComplete', array( &$img ) );
		}

Replace with:

		$status = $this->mLocalFile->upload( $this->mTempPath, $this->mComment, $pageText, 
			File::DELETE_SOURCE, $this->mFileProps );
			echo $this->mTempPath;
		if ( !$status->isGood() ) {
			$this->showError( $status->getWikiText() );
		} else {
			if ( $this->mWatchthis ) {
				global $wgUser;
				$wgUser->addWatch( $this->mLocalFile->getTitle() );
			}
			// Success, redirect to description page
			$this->cleanupTempFile();
			$wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() );
			$img = null; // @todo: added to avoid passing a ref to null - should this be defined somewhere?
			wfRunHooks( 'UploadComplete', array( &$img ) );
		}

Also in includes\SpecialUpload.php find:

	function uploadError( $error ) {
		global $wgOut;
		$wgOut->addHTML( "<h2>" . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" );
		$wgOut->addHTML( "<span class='error'>{$error}</span>\n" );
	}

Replace with:

	function uploadError( $error ) {
		global $wgOut;
		$this->mRemoveTempFile = file_exists( $this->mTempPath );
		$this->cleanupTempFile();
		$wgOut->addHTML( "<h2>" . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" );
		$wgOut->addHTML( "<span class='error'>{$error}</span>\n" );
	}

Open includes/WebRequest.php and find:

	function getFileTempname( $key ) {
		if( !isset( $_FILES[$key] ) ) {
			return NULL;
		}
		return $_FILES[$key]['tmp_name'];
	}

Replace with:

	function getFileTempname( $key ) {
		if( !isset( $_FILES[$key] ) ) {
			return NULL;
		}
		
		if (preg_match('#^/tmp/php#', $_FILES[$key]['tmp_name'])){
			if (move_uploaded_file($_FILES[$key]['tmp_name'], $GLOBALS['IP'] . $_FILES[$key]['tmp_name'])){
				$_FILES[$key]['tmp_name'] = $GLOBALS['IP'] . $_FILES[$key]['tmp_name'];
			}
		}
		
		return $_FILES[$key]['tmp_name'];
	}

Code Changes for version 1.14

Create a folder in the wiki root called tmp

Open includes\WebRequest.php and find (approx. line 557):

	function getFileTempname( $key ) {
		if( !isset( $_FILES[$key] ) ) {
			return NULL;
		}
		return $_FILES[$key]['tmp_name'];
	}

Replace with:

	function getFileTempname( $key ) {
		if( !isset( $_FILES[$key] ) ) {
			return NULL;
		}
		
		if (preg_match('#^/tmp/php#', $_FILES[$key]['tmp_name'])){
			unlink(substr($_FILES[$key]['tmp_name'], 1));
			if (move_uploaded_file($_FILES[$key]['tmp_name'], substr($_FILES[$key]['tmp_name'], 1))){
				$_FILES[$key]['tmp_name'] = substr($_FILES[$key]['tmp_name'], 1);
			}
		}
		
		return $_FILES[$key]['tmp_name'];
	}

Open includes\specials\SpecialUpload.php and add this function:

function cleanTempDir() {
		unlink($this->mTempPath);
	}

Next, find the following (approx. line 575):

wfRunHooks( 'UploadComplete', array( &$this ) );
return self::SUCCESS;

Replace with:

wfRunHooks( 'UploadComplete', array( &$this ) );
$this->cleanTempDir();
return self::SUCCESS;

Also find (approx. line 879):

	function uploadError( $error ) {
		global $wgOut;
		$wgOut->addHTML( '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" );
		$wgOut->addHTML( '<span class="error">' . $error . '</span>' );
	}

Replace with:

	function uploadError( $error ) {
		global $wgOut;
		$this->cleanTempDir();
		$wgOut->addHTML( '<h2>' . wfMsgHtml( 'uploadwarning' ) . "</h2>\n" );
		$wgOut->addHTML( '<span class="error">' . $error . '</span>' );
	}

Code Changes for version 1.21

Create a folder in the wiki root called tmp

Open includes\WebRequest.php and find the WebRequestUpload constructor (approx. line 1152):

	public function __construct( $request, $key ) {
		$this->request = $request;
		$this->doesExist = isset( $_FILES[$key] );
		if ( $this->doesExist ) {
			$this->fileInfo = $_FILES[$key];
		}
	}

Replace with:

	public function __construct( $request, $key ) {
		$this->request = $request;
		$this->doesExist = isset( $_FILES[$key] );
		if ( $this->doesExist ) {
			$this->fileInfo = $_FILES[$key];
			
			if (preg_match('#^/tmp/php#', $this->fileInfo['tmp_name'])){
				unlink(substr($this->fileInfo['tmp_name'], 1));
				if (move_uploaded_file($this->fileInfo['tmp_name'], substr($this->fileInfo['tmp_name'], 1))){
					$this->fileInfo['tmp_name'] = substr($this->fileInfo['tmp_name'], 1);
				}
			}
		}
	}

Open includes\upload\UploadBase.php and add this function:

/*WOLFTECH ADDITION TO DEAL WITH OPEN_BASEDIR*/
	function cleanTempDir() {
		unlink($this->mTempPath);
	}

Next, find the method performUpload (approx. line 672) and add in the cleanup call before it returns. Find:

wfProfileOut( __METHOD__ );
		return $status;

Replace with:

$this->cleanTempDir();
		
		wfProfileOut( __METHOD__ );
		return $status;

Next, find the method stashFile (approx. line 833) and add in the cleanup call before it returns. Find:

wfProfileOut( __METHOD__ );
		return $file;

Replace with:

$this->cleanTempDir();
		
		wfProfileOut( __METHOD__ );
		return $file;

In the LocalSettings.php file, comment out the $wgUseImageMagick variable