http://www.mediawiki.org/wiki/Special:Code/MediaWiki/70137
Revision: 70137
Author: btongminh
Date: 2010-07-29 13:53:51 +0000 (Thu, 29 Jul 2010)
Log Message:
-----------
Made asynchronous upload by URL working, partly. Hid it behind
$wgAllowAsyncCopyUploads. If there are no errors then everything works
expected; the same if there are unrecoverable errors. User intervention to
solve warnings is not yet possible, because $_SESSION is not available in
runJobs. This also means that async with leavemessage = false is broken.
Other changes:
* Moved verifyPermissions check in ApiUpload down pending r70135 implementation
in the API.
* In User::leaveMessage: append message to end of talk page; add a newline
before the heading
Modified Paths:
--------------
trunk/phase3/includes/DefaultSettings.php
trunk/phase3/includes/User.php
trunk/phase3/includes/api/ApiUpload.php
trunk/phase3/includes/job/UploadFromUrlJob.php
trunk/phase3/includes/upload/UploadFromUrl.php
Modified: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php 2010-07-29 13:47:44 UTC (rev
70136)
+++ trunk/phase3/includes/DefaultSettings.php 2010-07-29 13:53:51 UTC (rev
70137)
@@ -425,6 +425,11 @@
* The timeout for copy uploads is set by $wgHTTPTimeout.
*/
$wgAllowCopyUploads = false;
+/**
+ * Allow asynchronous copy uploads.
+ * This feature is experimental.
+ */
+$wgAllowAsyncCopyUploads = false;
/**
* Max size for uploads, in bytes. Applies to all uploads.
Modified: trunk/phase3/includes/User.php
===================================================================
--- trunk/phase3/includes/User.php 2010-07-29 13:47:44 UTC (rev 70136)
+++ trunk/phase3/includes/User.php 2010-07-29 13:53:51 UTC (rev 70137)
@@ -3767,7 +3767,7 @@
if ( !$template
|| $template->getNamespace() !==
NS_TEMPLATE
|| !$template->exists() ) {
- $text = "== $subject ==\n\n$text\n\n--
$signature";
+ $text = "\n== $subject ==\n\n$text\n\n--
$signature";
} else {
$text = '{{'. $template->getText()
. " | subject=$subject | body=$text |
signature=$signature }}";
@@ -3812,7 +3812,7 @@
$flags = $article->checkFlags( $flags );
if ( $flags & EDIT_UPDATE ) {
- $text .= $article->getContent();
+ $text = $article->getContent() . $text;
}
$dbw = wfGetDB( DB_MASTER );
Modified: trunk/phase3/includes/api/ApiUpload.php
===================================================================
--- trunk/phase3/includes/api/ApiUpload.php 2010-07-29 13:47:44 UTC (rev
70136)
+++ trunk/phase3/includes/api/ApiUpload.php 2010-07-29 13:53:51 UTC (rev
70137)
@@ -59,12 +59,6 @@
// First check permission to upload
$this->checkPermissions( $wgUser );
- // Check permission to upload this file
- $permErrors = $this->mUpload->verifyPermissions( $wgUser );
- if ( $permErrors !== true ) {
- // Todo: more specific error message
- $this->dieUsageMsg( array( 'badaccess-groups' ) );
- }
// Fetch the file
$status = $this->mUpload->fetchFile();
@@ -76,6 +70,13 @@
// Check if the uploaded file is sane
$this->verifyUpload();
+
+ // Check permission to upload this file
+ $permErrors = $this->mUpload->verifyPermissions( $wgUser );
+ if ( $permErrors !== true ) {
+ // Todo: stash the upload and allow choosing a new name
+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
+ }
// Check warnings if necessary
$warnings = $this->checkForWarnings();
@@ -198,9 +199,6 @@
$this->dieUsage( 'The filename is not allowed',
'illegal-filename',
0, array( 'filename' =>
$verification['filtered'] ) );
break;
- case UploadBase::OVERWRITE_EXISTING_FILE:
- $this->dieUsage( 'Overwriting an existing file
is not allowed', 'overwrite' );
- break;
case UploadBase::VERIFICATION_ERROR:
$this->getResult()->setIndexedTagName(
$verification['details'], 'detail' );
$this->dieUsage( 'This file did not pass file
verification', 'verification-error',
@@ -286,9 +284,19 @@
if ( !$status->isGood() ) {
$error = $status->getErrorsArray();
- $this->getResult()->setIndexedTagName( $error, 'error'
);
+
+ if ( count( $error ) == 1 && $error[0][0] == 'async' ) {
+ // The upload can not be performed right now,
because the user
+ // requested so
+ return array(
+ 'result' => 'Queued',
+ 'sessionkey' => $error[0][1],
+ );
+ } else {
+ $this->getResult()->setIndexedTagName( $error,
'error' );
- $this->dieUsage( 'An internal error occurred',
'internal-error', 0, $error );
+ $this->dieUsage( 'An internal error occurred',
'internal-error', 0, $error );
+ }
}
$file = $this->mUpload->getLocalFile();
@@ -331,15 +339,22 @@
'ignorewarnings' => false,
'file' => null,
'url' => null,
- 'asyncdownload' => false,
- 'leavemessage' => false,
+
'sessionkey' => null,
);
+
+ global $wgAllowAsyncCopyUploads;
+ if ( $wgAllowAsyncCopyUploads ) {
+ $params += array(
+ 'asyncdownload' => false,
+ 'leavemessage' => false,
+ );
+ }
return $params;
}
public function getParamDescription() {
- return array(
+ $params = array(
'filename' => 'Target filename',
'token' => 'Edit token. You can get one of these
through prop=info',
'comment' => 'Upload comment. Also used as the initial
page text for new files if "text" is not specified',
@@ -349,10 +364,19 @@
'ignorewarnings' => 'Ignore any warnings',
'file' => 'File contents',
'url' => 'Url to fetch the file from',
- 'asyncdownload' => 'Make fetching a URL asyncronous',
- 'leavemessage' => 'If asyncdownload is used, leave a
message on the user talk page if finished',
'sessionkey' => 'Session key returned by a previous
upload that failed due to warnings',
);
+
+ global $wgAllowAsyncCopyUploads;
+ if ( $wgAllowAsyncCopyUploads ) {
+ $params += array(
+ 'asyncdownload' => 'Make fetching a URL
asynchronous',
+ 'leavemessage' => 'If asyncdownload is used,
leave a message on the user talk page if finished',
+ );
+ }
+
+ return $params;
+
}
public function getDescription() {
Modified: trunk/phase3/includes/job/UploadFromUrlJob.php
===================================================================
--- trunk/phase3/includes/job/UploadFromUrlJob.php 2010-07-29 13:47:44 UTC
(rev 70136)
+++ trunk/phase3/includes/job/UploadFromUrlJob.php 2010-07-29 13:53:51 UTC
(rev 70137)
@@ -10,6 +10,8 @@
* @ingroup JobQueue
*/
class UploadFromUrlJob extends Job {
+ public $upload;
+ protected $user;
public function __construct( $title, $params, $id = 0 ) {
parent::__construct( 'uploadFromUrl', $title, $params, $id );
@@ -17,8 +19,8 @@
public function run() {
# Initialize this object and the upload object
- $upload = new UploadFromUrl();
- $upload->initialize(
+ $this->upload = new UploadFromUrl();
+ $this->upload->initialize(
$this->title->getText(),
$this->params['url'],
false
@@ -26,34 +28,47 @@
$this->user = User::newFromName( $this->params['userName'] );
# Fetch the file
- $status = $upload->fetchFile();
+ $status = $this->upload->fetchFile();
if ( !$status->isOk() ) {
$this->leaveMessage( $status );
return;
}
+ # Verify upload
+ $result = $this->upload->verifyUpload();
+ if ( $result['status'] != UploadBase::OK ) {
+ $status = $this->upload->convertVerifyErrorToStatus(
$result );
+ $this->leaveMessage( $status );
+ return;
+ }
+
# Check warnings
if ( !$this->params['ignoreWarnings'] ) {
- $warnings = $this->checkWarnings();
+ $warnings = $this->upload->checkWarnings();
if ( $warnings ) {
if ( $this->params['leaveMessage'] ) {
$this->user->leaveUserMessage(
wfMsg( 'upload-warning-subj' ),
- wfMsg( 'upload-warning-msg',
$this->params['sessionKey'] )
+ wfMsg( 'upload-warning-msg',
+
$this->params['sessionKey'],
+ $this->params['url'] )
);
} else {
$this->storeResultInSession( 'Warning',
'warnings', $warnings );
}
+
+ // FIXME: stash in session
return;
}
}
# Perform the upload
- $status = $upload->performUpload(
+ $status = $this->upload->performUpload(
$this->params['comment'],
$this->params['pageText'],
- $this->params['watch']
+ $this->params['watch'],
+ $this->user
);
$this->leaveMessage( $status );
}
@@ -67,13 +82,17 @@
protected function leaveMessage( $status ) {
if ( $this->params['leaveMessage'] ) {
if ( $status->isGood() ) {
- $file = $this->getLocalFile();
-
- $this->user->leaveUserMessage( wfMsg(
'successfulupload' ),
- wfMsg( 'upload-success-msg',
$file->getDescriptionUrl() ) );
+ $this->user->leaveUserMessage( wfMsg(
'upload-success-subj' ),
+ wfMsg( 'upload-success-msg',
+
$this->upload->getTitle()->getText(),
+ $this->params['url']
+ ) );
} else {
$this->user->leaveUserMessage( wfMsg(
'upload-failure-subj' ),
- wfMsg( 'upload-failure-msg',
$status->getWikiText() ) );
+ wfMsg( 'upload-failure-msg',
+ $status->getWikiText(),
+ $this->params['url']
+ ) );
}
} else {
if ( $status->isOk() ) {
@@ -89,6 +108,7 @@
/**
* Store a result in the session data
+ * THIS IS BROKEN. $_SESSION does not exist when using runJobs.php
*
* @param $result string The result (Success|Warning|Failure)
* @param $dataKey string The key of the extra data
Modified: trunk/phase3/includes/upload/UploadFromUrl.php
===================================================================
--- trunk/phase3/includes/upload/UploadFromUrl.php 2010-07-29 13:47:44 UTC
(rev 70136)
+++ trunk/phase3/includes/upload/UploadFromUrl.php 2010-07-29 13:53:51 UTC
(rev 70137)
@@ -10,6 +10,7 @@
*/
class UploadFromUrl extends UploadBase {
protected $mAsync, $mUrl;
+ protected $mIgnoreWarnings = true;
/**
* Checks if the user is allowed to use the upload-by-URL feature. If
the
@@ -40,12 +41,12 @@
* asynchronous download.
*/
public function initialize( $name, $url, $async = false ) {
- global $wgUser;
+ global $wgAllowAsyncCopyUploads;
$this->mUrl = $url;
- $this->mAsync = $async;
+ $this->mAsync = $wgAllowAsyncCopyUploads ? $async : false;
- $tempPath = $async ? null : $this->makeTemporaryFile();
+ $tempPath = $this->mAsync ? null : $this->makeTemporaryFile();
# File size and removeTempFile will be filled in later
$this->initializePathInfo( $name, $tempPath, 0, false );
}
@@ -88,9 +89,20 @@
}
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' );
}
+ /**
+ * Save the result of a HTTP request to the temporary file
+ *
+ * @param $req HttpRequest
+ * @return Status
+ */
private function saveTempFile( $req ) {
if ( $this->mTempPath === false ) {
return Status::newFatal( 'tmp-create-error' );
@@ -103,6 +115,10 @@
return Status::newGood();
}
+ /**
+ * Download the file, save it to the temporary file and update the file
+ * size and set $mRemoveTempFile to true.
+ */
protected function reallyFetchFile() {
$req = HttpRequest::factory( $this->mUrl );
$status = $req->execute();
@@ -120,6 +136,44 @@
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();
+ }
+
+ /**
+ * 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 );
+ }
+
+ /**
+ * 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 );
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs