MediaWiki:Wikia.css

/*--HILITED USERNAMES LIST--*/

/*--Bureaucrats--*/ /*--a[href="/wiki/User:NAME"] { color: green !important; font-weight:bold;}--*/ a[href="/wiki/User:Green_Ninja"] { color: green !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: green !important; font-weight:bold;}--*/ a[href="/wiki/User:ZootyCutie"] { color: green !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: green !important; font-weight:bold;}--*/ a[href="/wiki/User:FlurrFood24"] { color: green !important;font-weight:bold;}

/*--Admins--*/ /*--a[href="/wiki/User:NAME"] { color: blue !important; font-weight:bold;}--*/ a[href="/wiki/User:Boogly22238"] { color: #000080 !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: #000080 !important; font-weight:bold;}--*/ a[href="/wiki/User:Hyperealistic_Gaben"] { color: #000080 !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: #000080 !important; font-weight:bold;}--*/ a[href="/wiki/User:Volectro"] { color: #000080 !important;font-weight:bold;} a[href="/wiki/User:Derekis"] { color: #000080 !important;font-weight:bold;}

/*--Chat Moderators--*/ /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ a[href="/wiki/User:Digipony"] { color: red !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ a[href="/wiki/User:CoolTeslo23"] { color: red !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ a[href="/wiki/User:AClockworkOrange"] { color: red !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ a[href="/wiki/User:SpongebobAtnight"] { color: red !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: red !important; font-weight:bold;}--*/ a[href="/wiki/User:D_MixHel_S"] { color: red !important;font-weight:bold;}

/*--Rollbacks--*/ /*--a[href="/wiki/User:NAME"] { color: orange !important; font-weight:bold;}--*/ a[href="/wiki/User:ToaMatau2004"] { color: orange !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: green !important; font-weight:bold;}--*/ a[hef="/wiki/User:Dadaw"] { color: orange !important;font-weight:bold;} /*--Bots--*/ /*--a[href="/wiki/User:NAME"] { color: Purple !important; font-weight:bold;}--*/ a[href="/wiki/User:Matau-bot"] { color: Purple !important;font-weight:bold;} /*--a[href="/wiki/User:NAME"] { color: Purple !important; font-weight:bold;}--*/ a[href="/wiki/User:Murpbot"] { color: Purple !important;font-weight:bold;}

.sprite.edit-pencil {background: none transparent\9 !important;} .sprite.edit-pencil {background: url('http://img1.wikia.nocookie.net/__cb20141204213134/mixels/images/e/e8/Small_cubit_redo.png') no-repeat !important;} --- D:\Programming\SVN\mediawiki\branches\REL1_16\phase3\includes\upload\UploadFromUrl.php	2011-07-18 22:30:47.856445300 +0100 +++ D:\Programming\SVN\wikia\trunk\includes\upload\UploadFromUrl.php	2011-08-17 15:28:12.862304700 +0100 @@ -1,10 +1,9 @@ <?php /** - * @file - * @ingroup upload - * * Implements uploading from a HTTP resource. * + * @file + * @ingroup upload * @author Bryan Tong Minh * @author Michael Dale */ @@ -8,8 +7,10 @@ * @author Bryan Tong Minh * @author Michael Dale */ + class UploadFromUrl extends UploadBase { -	protected $mTempDownloadPath; +	protected $mAsync, $mUrl; +	protected $mIgnoreWarnings = true; /** 	 * Checks if the user is allowed to use the upload-by-URL feature. If the @@ -23,6 +24,7 @@ 	/** 	 * Checks if the upload from URL feature is enabled +	 * @return bool */ 	public static function isEnabled { global $wgAllowCopyUploads; @@ -31,14 +33,22 @@ 	/** 	 * Entry point for API upload -	 */ -	public function initialize( $name, $url, $na, $nb = false ) { -		global $wgTmpDirectory; - -		$localFile = tempnam( $wgTmpDirectory, 'WEBUPLOAD' ); -		$this->initializePathInfo( $name, $localFile, 0, true ); - -		$this->mUrl = trim( $url ); +	 * +	 * @param $name string +	 * @param $url string +	 * @param $async mixed Whether the download should be performed +	 * asynchronous. False for synchronous, async or async-leavemessage for +	 * asynchronous download. +	 */ +	public function initialize( $name, $url, $async = false ) { +		global $wgAllowAsyncCopyUploads; + +		$this->mUrl = $url; +		$this->mAsync = $wgAllowAsyncCopyUploads ? $async : false; + +		$tempPath = $this->mAsync ? null : $this->makeTemporaryFile; +		# File size and removeTempFile will be filled in later +		$this->initializePathInfo( $name, $tempPath, 0, false ); } 	/** @@ -60,78 +70,140 @@ 	 * @param $request Object: WebRequest object */ 	public static function isValidRequest( $request ){ -		if( !$request->getVal( 'wpUploadFileURL' ) ) -			return false; -		// check that is a valid url: -		return self::isValidUrl( $request->getVal( 'wpUploadFileURL' ) ); +		global $wgUser; + +		$url = $request->getVal( 'wpUploadFileURL' ); +		return !empty( $url ) +			&& Http::isValidURI( $url ) +			&& $wgUser->isAllowed( 'upload_by_url' ); } -	public static function isValidUrl( $url ) { -		// Only allow HTTP or FTP for now -		return (bool)preg_match( '!^(http://|ftp://)!', $url ); + +	public function fetchFile { +		if ( !Http::isValidURI( $this->mUrl ) ) { +			return Status::newFatal( 'http-invalid-url' ); } +		if ( !$this->mAsync ) { +			return $this->reallyFetchFile; +		} +		return Status::newGood; +	} +	/** +	 * Create a new temporary file in the URL subdirectory of wfTempDir. +	 * +	 * @return string Path to the file +	 */ +	protected function makeTemporaryFile { +		return tempnam( wfTempDir, 'URL' ); +	} 	/** -	 * Do the real fetching stuff +	 * Save the result of a HTTP request to the temporary file +	 * +	 * @param $req MWHttpRequest +	 * @return Status */ -	function fetchFile { -		if( !self::isValidUrl( $this->mUrl ) ) { -			return Status::newFatal( 'upload-proto-error' ); +	private function saveTempFile( $req ) { +		if ( $this->mTempPath === false ) { +			return Status::newFatal( 'tmp-create-error' ); } -		$res = $this->curlCopy; -		if( $res !== true ) { -			return Status::newFatal( $res ); +		if ( file_put_contents( $this->mTempPath, $req->getContent ) === false ) { +			return Status::newFatal( 'tmp-write-error' ); } + +		$this->mFileSize = filesize( $this->mTempPath ); + 		return Status::newGood; } - 	/** -	 * Safe copy from URL -	 * Returns true if there was an error, false otherwise +	 * Download the file, save it to the temporary file and update the file +	 * size and set $mRemoveTempFile to true. */ -	private function curlCopy { -		global $wgOut; +	protected function reallyFetchFile { +		$req = HttpRequest::factory( $this->mUrl ); +		$status = $req->execute; -		# Open temporary file -		$this->mCurlDestHandle = @fopen( $this->mTempPath, "wb" ); -		if( $this->mCurlDestHandle === false ) { -			# Could not open temporary file to write in -			return 'upload-file-error'; -		} - -		$ch = curl_init; -		curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1.0); # Probably not needed, but apparently can work around some bug -		curl_setopt( $ch, CURLOPT_TIMEOUT, 10); # 10 seconds timeout -		curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT, 512); # 0.5KB per second minimum transfer speed -		curl_setopt( $ch, CURLOPT_URL, $this->mUrl); -		curl_setopt( $ch, CURLOPT_WRITEFUNCTION, array( $this, 'uploadCurlCallback' ) ); -		curl_exec( $ch ); -		$error = curl_errno( $ch ); -		curl_close( $ch ); +		if ( !$status->isOk ) { +			return $status; +		} -		fclose( $this->mCurlDestHandle ); -		unset( $this->mCurlDestHandle ); +		$status = $this->saveTempFile( $req ); +		if ( !$status->isGood ) { +			return $status; +		} +		$this->mRemoveTempFile = true; + +		return $status; +	} + +	/** +	 * Wrapper around the parent function in order to defer verifying the +	 * upload until the file really has been fetched. +	 */ +	public function verifyUpload { +		if ( $this->mAsync ) { +			return array( 'status' => self::OK ); +		} +		return parent::verifyUpload; +	} -		if( $error ) -			return "upload-curl-error$errornum"; +	/** +	 * Wrapper around the parent function in order to defer checking warnings +	 * until the file really has been fetched. +	 */ +	public function checkWarnings { +		if ( $this->mAsync ) { +			$this->mIgnoreWarnings = false; +			return array; +		} +		return parent::checkWarnings; +	} +	/** +	 * Wrapper around the parent function in order to defer checking protection +	 * until we are sure that the file can actually be uploaded +	 */ +	public function verifyPermissions( $user ) { +		if ( $this->mAsync ) { return true; } +		return parent::verifyPermissions( $user ); +	} 	/** -	 * Callback function for CURL-based web transfer -	 * Write data to file unless we've passed the length limit; -	 * if so, abort immediately. -	 * @access private -	 */ -	function uploadCurlCallback( $ch, $data ) { -		global $wgMaxUploadSize; -		$length = strlen( $data ); -		$this->mFileSize += $length; -		if( $this->mFileSize > $wgMaxUploadSize ) { -			return 0; +	 * Wrapper around the parent function in order to defer uploading to the +	 * job queue for asynchronous uploads +	 */ +	public function performUpload( $comment, $pageText, $watch, $user ) { +		if ( $this->mAsync ) { +			$sessionKey = $this->insertJob( $comment, $pageText, $watch, $user ); + +			$status = new Status; +			$status->error( 'async', $sessionKey ); +			return $status; } -		fwrite( $this->mCurlDestHandle, $data ); -		return $length; + +		return parent::performUpload( $comment, $pageText, $watch, $user ); } + + +	protected function insertJob( $comment, $pageText, $watch, $user ) { +		$sessionKey = $this->stashSession; +		$job = new UploadFromUrlJob( $this->getTitle, array( +			'url' => $this->mUrl, +			'comment' => $comment, +			'pageText' => $pageText, +			'watch' => $watch, +			'userName' => $user->getName, +			'leaveMessage' => $this->mAsync == 'async-leavemessage', +			'ignoreWarnings' => $this->mIgnoreWarnings, +			'sessionId' => session_id, +			'sessionKey' => $sessionKey, +		) ); +		$job->initializeSessionData; +		$job->insert; +		return $sessionKey; +	} body.page-User_FlurrFood24 {background-color:aqua; } body.page-User_FlurrFood24.background-dynamic.skin-oasis:after, body.page-User_FlurrFood24.background-dynamic.skin-oasis:before { background-image: url("http://img4.wikia.nocookie.net/__cb20150108145825/mixels/images/5/59/Orbitrons_logo.png"); + +