* new FauxResponse class to help with unit testing
* Add append() method to FileRepo classes to enable chunked uploading * Change chunksessionkey to chunksession * Remove echo json stuff * Fix a multitude of bugs in my own code * still to test: mwEmbed use of chunked upload
This commit is contained in:
parent
c386434108
commit
c74fe71cd8
10 changed files with 263 additions and 142 deletions
|
|
@ -84,6 +84,7 @@ $wgAutoloadLocalClasses = array(
|
|||
'FakeTitle' => 'includes/FakeTitle.php',
|
||||
'FakeMemCachedClient' => 'includes/ObjectCache.php',
|
||||
'FauxRequest' => 'includes/WebRequest.php',
|
||||
'FauxResponse' => 'includes/WebResponse.php',
|
||||
'FeedItem' => 'includes/Feed.php',
|
||||
'FeedUtils' => 'includes/FeedUtils.php',
|
||||
'FileDeleteForm' => 'includes/FileDeleteForm.php',
|
||||
|
|
|
|||
|
|
@ -712,6 +712,7 @@ class WebRequest {
|
|||
class FauxRequest extends WebRequest {
|
||||
private $wasPosted = false;
|
||||
private $session = array();
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* @param $data Array of *non*-urlencoded key => value pairs, the
|
||||
|
|
@ -767,9 +768,8 @@ class FauxRequest extends WebRequest {
|
|||
}
|
||||
|
||||
public function getSessionData( $key ) {
|
||||
if( !isset( $this->session[$key] ) )
|
||||
return null;
|
||||
return $this->session[$key];
|
||||
if( isset( $this->session[$key] ) )
|
||||
return $this->session[$key];
|
||||
}
|
||||
|
||||
public function setSessionData( $key, $data ) {
|
||||
|
|
@ -780,4 +780,11 @@ class FauxRequest extends WebRequest {
|
|||
return false;
|
||||
}
|
||||
|
||||
public function response() {
|
||||
/* Lazy initialization of response object for this request */
|
||||
if ( !is_object( $this->response ) ) {
|
||||
$this->response = new FauxResponse;
|
||||
}
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
class WebResponse {
|
||||
|
||||
/**
|
||||
/**
|
||||
* Output a HTTP header, wrapper for PHP's
|
||||
* header()
|
||||
* @param $string String: header to output
|
||||
|
|
@ -58,3 +58,31 @@ class WebResponse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FauxResponse extends WebResponse {
|
||||
private $headers;
|
||||
private $cookies;
|
||||
|
||||
public function header($string, $replace=true) {
|
||||
list($key, $val) = explode(":", $string, 2);
|
||||
|
||||
if($replace || !isset($this->headers[$key])) {
|
||||
$this->headers[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
public function getheader($key) {
|
||||
return $this->headers[$key];
|
||||
}
|
||||
|
||||
public function setcookie( $name, $value, $expire = 0 ) {
|
||||
$this->cookies[$name] = $value;
|
||||
}
|
||||
|
||||
public function getcookie( $name ) {
|
||||
if ( isset($this->cookies[$name]) ) {
|
||||
return $this->cookies[$name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,10 @@ class ApiUpload extends ApiBase {
|
|||
public function execute() {
|
||||
global $wgUser, $wgAllowCopyUploads;
|
||||
|
||||
// Check whether upload is enabled
|
||||
if ( !UploadBase::isEnabled() )
|
||||
$this->dieUsageMsg( array( 'uploaddisabled' ) );
|
||||
|
||||
$this->getMain()->isWriteMode();
|
||||
$this->mParams = $this->extractRequestParams();
|
||||
$request = $this->getMain()->getRequest();
|
||||
|
|
@ -53,15 +57,27 @@ class ApiUpload extends ApiBase {
|
|||
// Add the uploaded file to the params array
|
||||
$this->mParams['file'] = $request->getFileName( 'file' );
|
||||
|
||||
// Check whether upload is enabled
|
||||
if ( !UploadBase::isEnabled() )
|
||||
$this->dieUsageMsg( array( 'uploaddisabled' ) );
|
||||
|
||||
// One and only one of the following parameters is needed
|
||||
$this->requireOnlyOneParameter( $this->mParams,
|
||||
'sessionkey', 'file', 'url', 'enablechunks' );
|
||||
|
||||
if ( $this->mParams['sessionkey'] ) {
|
||||
// Initialize $this->mUpload
|
||||
if ( $this->mParams['enablechunks'] ) {
|
||||
$this->mUpload = new UploadFromChunks();
|
||||
|
||||
$this->mUpload->initialize(
|
||||
$request->getVal( 'done', null ),
|
||||
$request->getVal( 'filename', null ),
|
||||
$request->getVal( 'chunksession', null ),
|
||||
$request->getFileTempName( 'chunk' ),
|
||||
$request->getFileSize( 'chunk' ),
|
||||
$request->getSessionData( 'wsUploadData' )
|
||||
);
|
||||
|
||||
if ( !$this->mUpload->status->isOK() ) {
|
||||
return $this->dieUsageMsg( $this->mUpload->status->getErrorsArray() );
|
||||
}
|
||||
} elseif ( $this->mParams['sessionkey'] ) {
|
||||
/**
|
||||
* Upload stashed in a previous request
|
||||
*/
|
||||
|
|
@ -72,30 +88,13 @@ class ApiUpload extends ApiBase {
|
|||
$this->mUpload = new UploadFromStash();
|
||||
$this->mUpload->initialize( $this->mParams['filename'],
|
||||
$_SESSION['wsUploadData'][$this->mParams['sessionkey']] );
|
||||
} else {
|
||||
} elseif ( isset( $this->mParams['filename'] ) ) {
|
||||
/**
|
||||
* Upload from url, etc
|
||||
* Parameter filename is required
|
||||
*/
|
||||
if ( !isset( $this->mParams['filename'] ) )
|
||||
$this->dieUsageMsg( array( 'missingparam', 'filename' ) );
|
||||
|
||||
// Initialize $this->mUpload
|
||||
if ( $this->mParams['enablechunks'] ) {
|
||||
$this->mUpload = new UploadFromChunks();
|
||||
$this->mUpload->initialize(
|
||||
$request->getVal( 'done', null ),
|
||||
$request->getVal( 'filename', null ),
|
||||
$request->getVal( 'chunksessionkey', null ),
|
||||
$request->getFileTempName( 'chunk' ),
|
||||
$request->getFileSize( 'chunk' ),
|
||||
$request->getSessionData( 'wsUploadData' )
|
||||
);
|
||||
|
||||
if ( !$this->mUpload->status->isOK() ) {
|
||||
return $this->dieUsageMsg( $this->mUpload->status->getErrorsArray() );
|
||||
}
|
||||
} elseif ( isset( $this->mParams['file'] ) ) {
|
||||
if ( isset( $this->mParams['file'] ) ) {
|
||||
$this->mUpload = new UploadFromFile();
|
||||
$this->mUpload->initialize(
|
||||
$this->mParams['filename'],
|
||||
|
|
@ -120,7 +119,7 @@ class ApiUpload extends ApiBase {
|
|||
return $this->dieUsage( $status->getWikiText(), 'fetchfileerror' );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else $this->dieUsageMsg( array( 'missingparam', 'filename' ) );
|
||||
|
||||
if ( !isset( $this->mUpload ) )
|
||||
$this->dieUsage( 'No upload module set', 'nomodule' );
|
||||
|
|
@ -242,6 +241,8 @@ class ApiUpload extends ApiBase {
|
|||
$this->getResult()->setIndexedTagName( $result['details'], 'error' );
|
||||
|
||||
$this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
|
||||
} elseif( isset($status->value->uploadUrl) ) {
|
||||
return $status->value;
|
||||
}
|
||||
|
||||
$file = $this->mUpload->getLocalFile();
|
||||
|
|
@ -272,7 +273,7 @@ class ApiUpload extends ApiBase {
|
|||
'ignorewarnings' => false,
|
||||
'file' => null,
|
||||
'enablechunks' => false,
|
||||
'chunksessionkey' => null,
|
||||
'chunksession' => null,
|
||||
'chunk' => null,
|
||||
'done' => false,
|
||||
'url' => null,
|
||||
|
|
@ -295,7 +296,7 @@ class ApiUpload extends ApiBase {
|
|||
'ignorewarnings' => 'Ignore any warnings',
|
||||
'file' => 'File contents',
|
||||
'enablechunks' => 'Set to use chunk mode; see http://firefogg.org/dev/chunk_post.html for protocol',
|
||||
'chunksessionkey' => 'The session key, established on the first contact during the chunked upload',
|
||||
'chunksession' => 'The session key, established on the first contact during the chunked upload',
|
||||
'chunk' => 'The data in this chunk of a chunked upload',
|
||||
'done' => 'Set to 1 on the last chunk of a chunked upload',
|
||||
'url' => 'Url to fetch the file from',
|
||||
|
|
|
|||
|
|
@ -227,6 +227,33 @@ class FSRepo extends FileRepo {
|
|||
return $status;
|
||||
}
|
||||
|
||||
function append( $srcPath, $toAppendPath ) {
|
||||
$status = $this->newGood();
|
||||
|
||||
// Resolve the virtual URL
|
||||
if ( self::isVirtualUrl( $srcPath ) ) {
|
||||
$srcPath = $this->resolveVirtualUrl( $srcPath );
|
||||
}
|
||||
// Make sure the files are there
|
||||
if ( !is_file( $srcPath ) )
|
||||
$status->fatal( 'append-src-filenotfound', $srcPath );
|
||||
|
||||
if ( !is_file( $toAppendPath ) )
|
||||
$status->fatal( 'append-toappend-filenotfound', $toAppendPath );
|
||||
|
||||
// Do the append
|
||||
if( file_put_contents( $srcPath, file_get_contents( $toAppendPath ), FILE_APPEND ) ) {
|
||||
$status->value = $srcPath;
|
||||
} else {
|
||||
$status->fatal( 'fileappenderror', $toAppendPath, $srcPath);
|
||||
}
|
||||
|
||||
// Remove the source file
|
||||
unlink( $toAppendPath );
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks existence of specified array of files.
|
||||
*
|
||||
|
|
@ -575,7 +602,7 @@ class FSRepo extends FileRepo {
|
|||
}
|
||||
return strtr( $param, $this->simpleCleanPairs );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chmod a file, supressing the warnings.
|
||||
* @param String $path The path to change
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ abstract class FileRepo {
|
|||
// Optional settings
|
||||
$this->initialCapital = MWNamespace::isCapitalized( NS_FILE );
|
||||
foreach ( array( 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
|
||||
'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection',
|
||||
'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection',
|
||||
'descriptionCacheExpiry', 'hashLevels', 'url', 'thumbUrl' ) as $var )
|
||||
{
|
||||
if ( isset( $info[$var] ) ) {
|
||||
|
|
@ -87,7 +87,7 @@ abstract class FileRepo {
|
|||
*
|
||||
* ignoreRedirect: If true, do not follow file redirects
|
||||
*
|
||||
* private: If true, return restricted (deleted) files if the current
|
||||
* private: If true, return restricted (deleted) files if the current
|
||||
* user is allowed to view them. Otherwise, such files will not
|
||||
* be found.
|
||||
*/
|
||||
|
|
@ -123,12 +123,12 @@ abstract class FileRepo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Now try redirects
|
||||
if ( !empty( $options['ignoreRedirect'] ) ) {
|
||||
return false;
|
||||
}
|
||||
$redir = $this->checkRedirect( $title );
|
||||
$redir = $this->checkRedirect( $title );
|
||||
if( $redir && $redir->getNamespace() == NS_FILE) {
|
||||
$img = $this->newFile( $redir );
|
||||
if( !$img ) {
|
||||
|
|
@ -141,9 +141,9 @@ abstract class FileRepo {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find many files at once.
|
||||
* Find many files at once.
|
||||
* @param array $items, an array of titles, or an array of findFile() options with
|
||||
* the "title" option giving the title. Example:
|
||||
*
|
||||
|
|
@ -168,7 +168,7 @@ abstract class FileRepo {
|
|||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new File object from the local repository
|
||||
* @param mixed $sha1 SHA-1 key
|
||||
|
|
@ -189,14 +189,14 @@ abstract class FileRepo {
|
|||
return call_user_func( $this->fileFactoryKey, $sha1, $this );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find an instance of the file with this key, created at the specified time
|
||||
* Returns false if the file does not exist. Repositories not supporting
|
||||
* version control should return false if the time is specified.
|
||||
*
|
||||
* @param string $sha1 string
|
||||
* @param array $options Option array, same as findFile().
|
||||
* @param array $options Option array, same as findFile().
|
||||
*/
|
||||
function findFileFromKey( $sha1, $options = array() ) {
|
||||
if ( !is_array( $options ) ) {
|
||||
|
|
@ -234,7 +234,7 @@ abstract class FileRepo {
|
|||
function getThumbScriptUrl() {
|
||||
return $this->thumbScriptUrl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the URL corresponding to one of the four basic zones
|
||||
* @param String $zone One of: public, deleted, temp, thumb
|
||||
|
|
@ -280,7 +280,7 @@ abstract class FileRepo {
|
|||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a relative path including trailing slash, e.g. f/fa/
|
||||
* If the repo is not hashed, returns an empty string
|
||||
|
|
@ -397,6 +397,8 @@ abstract class FileRepo {
|
|||
*/
|
||||
abstract function storeTemp( $originalName, $srcPath );
|
||||
|
||||
abstract function append( $srcPath, $toAppendPath );
|
||||
|
||||
/**
|
||||
* Remove a temporary file or mark it for garbage collection
|
||||
* @param string $virtualUrl The virtual URL returned by storeTemp
|
||||
|
|
@ -587,14 +589,14 @@ abstract class FileRepo {
|
|||
/**
|
||||
* Invalidates image redirect cache related to that image
|
||||
* Doesn't do anything for repositories that don't support image redirects.
|
||||
*
|
||||
*
|
||||
* STUB
|
||||
* @param Title $title Title of image
|
||||
*/
|
||||
*/
|
||||
function invalidateImageRedirect( $title ) {}
|
||||
|
||||
|
||||
/**
|
||||
* Get an array or iterator of file objects for files that have a given
|
||||
* Get an array or iterator of file objects for files that have a given
|
||||
* SHA-1 content hash.
|
||||
*
|
||||
* STUB
|
||||
|
|
@ -602,9 +604,9 @@ abstract class FileRepo {
|
|||
function findBySha1( $hash ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the human-readable name of the repo.
|
||||
* Get the human-readable name of the repo.
|
||||
* @return string
|
||||
*/
|
||||
public function getDisplayName() {
|
||||
|
|
@ -616,12 +618,12 @@ abstract class FileRepo {
|
|||
if ( !wfEmptyMsg( 'shared-repo-name-' . $this->name, $repoName ) ) {
|
||||
return $repoName;
|
||||
}
|
||||
return wfMsg( 'shared-repo' );
|
||||
return wfMsg( 'shared-repo' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a key on the primary cache for this repository.
|
||||
* Returns false if the repository's cache is not accessible at this site.
|
||||
* Returns false if the repository's cache is not accessible at this site.
|
||||
* The parameters are the parts of the key, as for wfMemcKey().
|
||||
*
|
||||
* STUB
|
||||
|
|
@ -631,7 +633,7 @@ abstract class FileRepo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a key for this repo in the local cache domain. These cache keys are
|
||||
* Get a key for this repo in the local cache domain. These cache keys are
|
||||
* not shared with remote instances of the repo.
|
||||
* The parameters are the parts of the key, as for wfMemcKey().
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
var $apiThumbCacheExpiry = 86400;
|
||||
protected $mQueryCache = array();
|
||||
protected $mFileExists = array();
|
||||
|
||||
|
||||
function __construct( $info ) {
|
||||
parent::__construct( $info );
|
||||
$this->mApiBase = $info['apibase']; // http://commons.wikimedia.org/w/api.php
|
||||
|
|
@ -42,7 +42,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
$this->thumbUrl = $this->url . '/thumb';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Per docs in FileRepo, this needs to return false if we don't support versioned
|
||||
* files. Well, we don't.
|
||||
|
|
@ -63,13 +63,16 @@ class ForeignAPIRepo extends FileRepo {
|
|||
function storeTemp( $originalName, $srcPath ) {
|
||||
return false;
|
||||
}
|
||||
function append( $srcPath, $toAppendPath ){
|
||||
return false;
|
||||
}
|
||||
function publishBatch( $triplets, $flags = 0 ) {
|
||||
return false;
|
||||
}
|
||||
function deleteBatch( $sourceDestPairs ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function fileExistsBatch( $files, $flags = 0 ) {
|
||||
$results = array();
|
||||
|
|
@ -99,10 +102,10 @@ class ForeignAPIRepo extends FileRepo {
|
|||
function getFileProps( $virtualUrl ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function queryImage( $query ) {
|
||||
$data = $this->fetchImageQuery( $query );
|
||||
|
||||
|
||||
if( isset( $data['query']['pages'] ) ) {
|
||||
foreach( $data['query']['pages'] as $pageid => $info ) {
|
||||
if( isset( $info['imageinfo'][0] ) ) {
|
||||
|
|
@ -112,10 +115,10 @@ class ForeignAPIRepo extends FileRepo {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function fetchImageQuery( $query ) {
|
||||
global $wgMemc;
|
||||
|
||||
|
||||
$url = $this->mApiBase .
|
||||
'?' .
|
||||
wfArrayToCgi(
|
||||
|
|
@ -123,7 +126,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
array(
|
||||
'format' => 'json',
|
||||
'action' => 'query' ) ) );
|
||||
|
||||
|
||||
if( !isset( $this->mQueryCache[$url] ) ) {
|
||||
$key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
|
||||
$data = $wgMemc->get( $key );
|
||||
|
|
@ -143,14 +146,14 @@ class ForeignAPIRepo extends FileRepo {
|
|||
}
|
||||
return FormatJson::decode( $this->mQueryCache[$url], true );
|
||||
}
|
||||
|
||||
|
||||
function getImageInfo( $title, $time = false ) {
|
||||
return $this->queryImage( array(
|
||||
'titles' => 'Image:' . $title->getText(),
|
||||
'iiprop' => 'timestamp|user|comment|url|size|sha1|metadata|mime',
|
||||
'prop' => 'imageinfo' ) );
|
||||
}
|
||||
|
||||
|
||||
function findBySha1( $hash ) {
|
||||
$results = $this->fetchImageQuery( array(
|
||||
'aisha1base36' => $hash,
|
||||
|
|
@ -164,7 +167,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function getThumbUrl( $name, $width=-1, $height=-1 ) {
|
||||
$info = $this->queryImage( array(
|
||||
'titles' => 'Image:' . $name,
|
||||
|
|
@ -179,14 +182,14 @@ class ForeignAPIRepo extends FileRepo {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getThumbUrlFromCache( $name, $width, $height ) {
|
||||
global $wgMemc, $wgUploadPath, $wgServer, $wgUploadDirectory;
|
||||
|
||||
|
||||
if ( !$this->canCacheThumbs() ) {
|
||||
return $this->getThumbUrl( $name, $width, $height );
|
||||
}
|
||||
|
||||
|
||||
$key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
|
||||
if ( $thumbUrl = $wgMemc->get($key) ) {
|
||||
wfDebug("Got thumb from local cache. $thumbUrl \n");
|
||||
|
|
@ -194,7 +197,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
}
|
||||
else {
|
||||
$foreignUrl = $this->getThumbUrl( $name, $width, $height );
|
||||
|
||||
|
||||
// We need the same filename as the remote one :)
|
||||
$fileName = rawurldecode( pathinfo( $foreignUrl, PATHINFO_BASENAME ) );
|
||||
$path = 'thumb/' . $this->getHashPath( $name ) . $name . "/";
|
||||
|
|
@ -213,7 +216,7 @@ class ForeignAPIRepo extends FileRepo {
|
|||
return $localUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see FileRepo::getZoneUrl()
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ class NullRepo extends FileRepo {
|
|||
function storeTemp( $originalName, $srcPath ) {
|
||||
return false;
|
||||
}
|
||||
function append( $srcPath, $toAppendPath ){
|
||||
return false;
|
||||
}
|
||||
function publishBatch( $triplets, $flags = 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ class UploadFromChunks extends UploadBase {
|
|||
protected $chunkMode; // INIT, CHUNK, DONE
|
||||
protected $sessionKey;
|
||||
protected $comment;
|
||||
protected $fileSize = 0;
|
||||
protected $repoPath;
|
||||
protected $pageText;
|
||||
protected $watch;
|
||||
|
|
@ -37,9 +36,8 @@ class UploadFromChunks extends UploadBase {
|
|||
throw new MWException( 'not implemented' );
|
||||
}
|
||||
|
||||
public function initialize( $done, $filename, $sessionKey, $path,
|
||||
$fileSize, $sessionData )
|
||||
{
|
||||
public function initialize( $done, $filename, $sessionKey, $path, $fileSize, $sessionData ) {
|
||||
global $wgTmpDirectory;
|
||||
$this->status = new Status;
|
||||
|
||||
$this->initFromSessionKey( $sessionKey, $sessionData );
|
||||
|
|
@ -47,7 +45,7 @@ class UploadFromChunks extends UploadBase {
|
|||
if ( !$this->sessionKey && !$done ) {
|
||||
// session key not set, init the chunk upload system:
|
||||
$this->chunkMode = self::INIT;
|
||||
$this->mDesiredDestName = $filename;
|
||||
$this->initializePathInfo( $filename, $path, 0, true);
|
||||
} else if ( $this->sessionKey && !$done ) {
|
||||
$this->chunkMode = self::CHUNK;
|
||||
} else if ( $this->sessionKey && $done ) {
|
||||
|
|
@ -55,7 +53,7 @@ class UploadFromChunks extends UploadBase {
|
|||
}
|
||||
if ( $this->chunkMode == self::CHUNK || $this->chunkMode == self::DONE ) {
|
||||
$this->mTempPath = $path;
|
||||
$this->fileSize += $fileSize;
|
||||
$this->mFileSize += $fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,24 +126,25 @@ class UploadFromChunks extends UploadBase {
|
|||
// a) the user must have requested the token to get here and
|
||||
// b) should only happen over POST
|
||||
// c) we need the token to validate chunks are coming from a non-xss request
|
||||
$token = urlencode( $wgUser->editToken() );
|
||||
echo FormatJson::encode( array(
|
||||
'uploadUrl' => wfExpandUrl( wfScript( 'api' ) ) . "?action=upload&" .
|
||||
"token={$token}&format=json&enablechunks=true&chunksessionkey=" .
|
||||
$this->setupChunkSession( $comment, $pageText, $watch ) ) );
|
||||
$wgOut->disable();
|
||||
return Status::newGood(
|
||||
array('uploadUrl' => wfExpandUrl( wfScript( 'api' ) ) . "?" .
|
||||
wfArrayToCGI(array('action' => 'upload',
|
||||
'token' => $wgUser->editToken(),
|
||||
'format' => 'json',
|
||||
'filename' => $pageText,
|
||||
'enablechunks' => 'true',
|
||||
'chunksession' => $this->setupChunkSession( $comment, $pageText, $watch ) ) ) ) );
|
||||
} else if ( $this->chunkMode == self::CHUNK ) {
|
||||
$status = $this->appendChunk();
|
||||
if ( !$status->isOK() ) {
|
||||
return $status;
|
||||
$this->appendChunk();
|
||||
if ( !$this->status->isOK() ) {
|
||||
return $this->status;
|
||||
}
|
||||
// return success:
|
||||
// firefogg expects a specific result
|
||||
// http://www.firefogg.org/dev/chunk_post.html
|
||||
echo FormatJson::encode(
|
||||
array( 'result' => 1, 'filesize' => $this->fileSize )
|
||||
return Status::newGood(
|
||||
array( 'result' => 1, 'filesize' => $this->mFileSize )
|
||||
);
|
||||
$wgOut->disable();
|
||||
} else if ( $this->chunkMode == self::DONE ) {
|
||||
if ( !$comment )
|
||||
$comment = $this->comment;
|
||||
|
|
@ -164,12 +163,9 @@ class UploadFromChunks extends UploadBase {
|
|||
|
||||
// firefogg expects a specific result
|
||||
// http://www.firefogg.org/dev/chunk_post.html
|
||||
echo FormatJson::encode( array(
|
||||
'result' => 1,
|
||||
'done' => 1,
|
||||
'resultUrl' => $file->getDescriptionUrl() )
|
||||
return Status::newGood(
|
||||
array('result' => 1, 'done' => 1, 'resultUrl' => $file->getDescriptionUrl() )
|
||||
);
|
||||
$wgOut->disable();
|
||||
}
|
||||
|
||||
return Status::newGood();
|
||||
|
|
@ -199,18 +195,18 @@ class UploadFromChunks extends UploadBase {
|
|||
if ( !$this->repoPath ) {
|
||||
$this->status = $this->saveTempUploadedFile( $this->mDesiredDestName, $this->mTempPath );
|
||||
|
||||
if ( $status->isOK() ) {
|
||||
$this->repoPath = $status->value;
|
||||
if ( $this->status->isOK() ) {
|
||||
$this->repoPath = $this->status->value;
|
||||
$_SESSION['wsUploadData'][$this->sessionKey]['repoPath'] = $this->repoPath;
|
||||
}
|
||||
return $status;
|
||||
return;
|
||||
}
|
||||
if ( $this->getRealPath( $this->repoPath ) ) {
|
||||
$this->status = $this->appendToUploadFile( $this->repoPath, $this->mTempPath );
|
||||
} else {
|
||||
$this->status = Status::newFatal( 'filenotfound', $this->repoPath );
|
||||
}
|
||||
if ( $this->fileSize > $wgMaxUploadSize )
|
||||
if ( $this->mFileSize > $wgMaxUploadSize )
|
||||
$this->status = Status::newFatal( 'largefileserver' );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,33 +9,10 @@ class UploadFromChunksTest extends ApiSetup {
|
|||
|
||||
$wgEnableUploads=true;
|
||||
ini_set('file_loads', true);
|
||||
}
|
||||
|
||||
function testGetTitle() {
|
||||
$filename = tempnam( wfTempDir(), "" );
|
||||
$c = new UploadFromChunks();
|
||||
$c->initialize(false, "temp.txt", null, $filename, 0, null);
|
||||
$this->assertEquals(null, $c->getTitle());
|
||||
|
||||
$c = new UploadFromChunks();
|
||||
$c->initialize(false, "temp.png", null, $filename, 0, null);
|
||||
$this->assertEquals(Title::makeTitleSafe(NS_FILE, "Temp.png"), $c->getTitle());
|
||||
}
|
||||
|
||||
function testGetEditToken() {
|
||||
}
|
||||
|
||||
function testInitFromSessionKey() {
|
||||
parent::setup();
|
||||
|
||||
}
|
||||
|
||||
function testInitialize() {
|
||||
}
|
||||
|
||||
function testSetupChunkSession() {
|
||||
}
|
||||
|
||||
|
||||
function makeChunk() {
|
||||
$file = tempnam( wfTempDir(), "" );
|
||||
$fh = fopen($file, "w");
|
||||
|
|
@ -53,58 +30,134 @@ class UploadFromChunksTest extends ApiSetup {
|
|||
}
|
||||
|
||||
function cleanChunk() {
|
||||
unlink($_FILES['chunk']['tmp_name']);
|
||||
if(file_exists($_FILES['chunk']['tmp_name']))
|
||||
unlink($_FILES['chunk']['tmp_name']);
|
||||
}
|
||||
|
||||
function doApiRequest($params) {
|
||||
$session = isset( $_SESSION ) ? $_SESSION : array();
|
||||
$req = new FauxRequest($params, true, $session);
|
||||
$module = new ApiMain($req, true);
|
||||
$module->execute();
|
||||
|
||||
return $module->getResultData();
|
||||
}
|
||||
|
||||
function testGetTitle() {
|
||||
$filename = tempnam( wfTempDir(), "" );
|
||||
$c = new UploadFromChunks();
|
||||
$c->initialize(false, "temp.txt", null, $filename, 0, null);
|
||||
$this->assertEquals(null, $c->getTitle());
|
||||
|
||||
$c = new UploadFromChunks();
|
||||
$c->initialize(false, "temp.png", null, $filename, 0, null);
|
||||
$this->assertEquals(Title::makeTitleSafe(NS_FILE, "Temp.png"), $c->getTitle());
|
||||
}
|
||||
|
||||
function testLogin() {
|
||||
$data = $this->doApiRequest(array('action' => 'login',
|
||||
"lgname" => self::$userName,
|
||||
"lgpassword" => self::$passWord ) );
|
||||
$this->assertArrayHasKey("login", $data);
|
||||
$this->assertArrayHasKey("result", $data['login']);
|
||||
$this->assertEquals("Success", $data['login']['result']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @depends testLogin
|
||||
*/
|
||||
function testGetEditToken($data) {
|
||||
global $wgUser;
|
||||
$wgUser = User::newFromName(self::$userName);
|
||||
$wgUser->load();
|
||||
|
||||
$data = $this->doApiRequest(array('action' => 'query',
|
||||
'prop' => 'info',
|
||||
'intoken' => 'edit'));
|
||||
}
|
||||
|
||||
function testSetupChunkSession() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @expectedException UsageException
|
||||
*/
|
||||
function testPerformUploadInitError() {
|
||||
global $wgUser;
|
||||
|
||||
$wgUser = User::newFromId(1);
|
||||
$token = $wgUser->editToken();
|
||||
$this->makeChunk();
|
||||
|
||||
$req = new FauxRequest(
|
||||
array('action' => 'upload',
|
||||
'enablechunks' => '1',
|
||||
'filename' => 'test.png',
|
||||
'token' => $token,
|
||||
));
|
||||
$module = new ApiMain($req, true);
|
||||
$module->execute();
|
||||
}
|
||||
|
||||
function testPerformUploadInitSuccess() {
|
||||
/**
|
||||
* @depends testLogin
|
||||
*/
|
||||
function testPerformUploadInitSuccess($login) {
|
||||
global $wgUser;
|
||||
|
||||
$wgUser = User::newFromId(1);
|
||||
$wgUser = User::newFromName(self::$userName);
|
||||
$token = $wgUser->editToken();
|
||||
$this->makeChunk();
|
||||
|
||||
$req = new FauxRequest(
|
||||
$data = $this->doApiRequest(
|
||||
array('action' => 'upload',
|
||||
'enablechunks' => '1',
|
||||
'filename' => 'test.png',
|
||||
'token' => $token,
|
||||
));
|
||||
$module = new ApiMain($req, true);
|
||||
$module->execute();
|
||||
|
||||
$this->assertArrayHasKey("upload", $data);
|
||||
$this->assertArrayHasKey("uploadUrl", $data['upload']);
|
||||
|
||||
return array('data' => $data, 'session' => $_SESSION, 'token' => $token);
|
||||
}
|
||||
|
||||
function testAppendToUploadFile() {
|
||||
/**
|
||||
* @depends testPerformUploadInitSuccess
|
||||
*/
|
||||
function testAppendChunk($combo) {
|
||||
global $wgUser;
|
||||
$data = $combo['data'];
|
||||
$_SESSION = $combo['session'];
|
||||
$wgUser = User::newFromName(self::$userName);
|
||||
$token = $wgUser->editToken();
|
||||
|
||||
$url = $data['upload']['uploadUrl'];
|
||||
$params = wfCgiToArray(substr($url, strpos($url, "?")));
|
||||
|
||||
for($i=0;$i<10;$i++) {
|
||||
$this->makeChunk();
|
||||
$data = $this->doApiRequest($params);
|
||||
$this->cleanChunk();
|
||||
}
|
||||
|
||||
return array('data' => $data, 'session' => $_SESSION, 'token' => $token, 'params' => $params);
|
||||
}
|
||||
|
||||
function testAppendChunk() {
|
||||
/**
|
||||
* @depends testAppendChunk
|
||||
*/
|
||||
function testUploadChunkDone($combo) {
|
||||
global $wgUser;
|
||||
$data = $combo['data'];
|
||||
$params = $combo['params'];
|
||||
$_SESSION = $combo['session'];
|
||||
$wgUser = User::newFromName(self::$userName);
|
||||
$token = $wgUser->editToken();
|
||||
|
||||
$params['done'] = 1;
|
||||
|
||||
$this->makeChunk();
|
||||
$data = $this->doApiRequest($params);
|
||||
$this->cleanChunk();
|
||||
}
|
||||
|
||||
function testPeformUploadChunk() {
|
||||
}
|
||||
|
||||
function testPeformUploadDone() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue