Wiki Upload Fix

From WolfTech
Revision as of 12:11, 4 May 2009 by Rjhodson (talk | contribs)
Jump to navigation Jump to search

How It Works

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>' );
	}