61 private const MAX_US_PROPS_SIZE = 65535;
97 $this->user = $user ?? RequestContext::getMain()->getUser();
113 public function getFile( $key, $noAuth =
false ) {
114 if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
116 wfMessage(
'uploadstash-bad-path-bad-format', $key )
120 if ( !$noAuth && !$this->user->isRegistered() ) {
126 if ( !isset( $this->fileMetadata[$key] ) ) {
133 if ( !isset( $this->fileMetadata[$key] ) ) {
135 wfMessage(
'uploadstash-file-not-found', $key )
144 isset( $this->fileMetadata[$key][
'us_props'] ) && strlen( $this->fileMetadata[$key][
'us_props'] )
146 $this->fileProps[$key] = unserialize( $this->fileMetadata[$key][
'us_props'] );
148 wfDebug( __METHOD__ .
" fetched props for $key from file" );
149 $path = $this->fileMetadata[$key][
'us_path'];
150 $this->fileProps[$key] = $this->repo->getFileProps(
$path );
154 if ( !$this->files[$key]->exists() ) {
155 wfDebug( __METHOD__ .
" tried to get file at $key, but it doesn't exist" );
162 if ( !$noAuth && $this->fileMetadata[$key][
'us_user'] != $this->user->getId() ) {
164 wfMessage(
'uploadstash-wrong-owner', $key )
168 return $this->files[$key];
180 return $this->fileMetadata[$key];
192 return $this->fileProps[$key];
209 if ( !is_file(
$path ) ) {
210 wfDebug( __METHOD__ .
" tried to stash file at '$path', but it doesn't exist" );
218 $mwProps =
new MWFileProps( MediaWikiServices::getInstance()->getMimeAnalyzer() );
221 wfDebug( __METHOD__ .
" stashing file at '$path'" );
225 $extension = self::getExtensionForPath(
$path );
226 if ( !preg_match(
"/\\.\\Q$extension\\E$/",
$path ) ) {
227 $pathWithGoodExtension =
"$path.$extension";
229 $pathWithGoodExtension =
$path;
237 [ $usec, $sec ] = explode(
' ', microtime() );
238 $usec = substr( $usec, 2 );
239 $key = Wikimedia\base_convert( $sec . $usec, 10, 36 ) .
'.' .
240 Wikimedia\base_convert( (
string)mt_rand(), 10, 36 ) .
'.' .
241 $this->user->getId() .
'.' .
246 if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
248 wfMessage(
'uploadstash-bad-path-bad-format', $key )
252 wfDebug( __METHOD__ .
" key for '$path': $key" );
255 $storeStatus = $this->repo->storeTemp( basename( $pathWithGoodExtension ),
$path );
257 if ( !$storeStatus->isOK() ) {
266 $error = $storeStatus->getErrorsArray();
267 $error = reset( $error );
268 if ( !count( $error ) ) {
269 $error = $storeStatus->getWarningsArray();
270 $error = reset( $error );
271 if ( !count( $error ) ) {
272 $error = [
'unknown',
'no error recorded' ];
277 $errorMsg = array_shift( $error );
280 $stashPath = $storeStatus->value;
283 if ( !$this->user->isRegistered() ) {
290 wfDebug( __METHOD__ .
" inserting $stashPath under $key" );
291 $dbw = $this->repo->getPrimaryDB();
293 $serializedFileProps = serialize(
$fileProps );
294 if ( strlen( $serializedFileProps ) > self::MAX_US_PROPS_SIZE ) {
299 $serializedFileProps = serialize(
$fileProps );
303 'us_user' => $this->user->getId(),
305 'us_orig_path' =>
$path,
306 'us_path' => $stashPath,
307 'us_props' => $dbw->encodeBlob( $serializedFileProps ),
315 'us_source_type' => $sourceType,
316 'us_timestamp' => $dbw->timestamp(),
317 'us_status' =>
'finished'
320 $dbw->newInsertQueryBuilder()
321 ->insertInto(
'uploadstash' )
323 ->caller( __METHOD__ )->execute();
327 $insertRow[
'us_id'] = $dbw->insertId();
329 $this->fileMetadata[$key] = $insertRow;
331 # create the UploadStashFile object for this file.
345 if ( !$this->user->isRegistered() ) {
351 wfDebug( __METHOD__ .
' clearing all rows for user ' . $this->user->getId() );
352 $dbw = $this->repo->getPrimaryDB();
353 $dbw->newDeleteQueryBuilder()
354 ->deleteFrom(
'uploadstash' )
355 ->where( [
'us_user' => $this->user->getId() ] )
356 ->caller( __METHOD__ )->execute();
360 $this->fileMetadata = [];
374 if ( !$this->user->isRegistered() ) {
380 $dbw = $this->repo->getPrimaryDB();
384 $row = $dbw->newSelectQueryBuilder()
385 ->select(
'us_user' )
386 ->from(
'uploadstash' )
387 ->where( [
'us_key' => $key ] )
388 ->caller( __METHOD__ )->fetchRow();
392 wfMessage(
'uploadstash-no-such-key', $key )
396 if ( $row->us_user != $this->user->getId() ) {
398 wfMessage(
'uploadstash-wrong-owner', $key )
412 wfDebug( __METHOD__ .
" clearing row $key" );
417 $dbw = $this->repo->getPrimaryDB();
419 $dbw->newDeleteQueryBuilder()
420 ->deleteFrom(
'uploadstash' )
421 ->where( [
'us_key' => $key ] )
422 ->caller( __METHOD__ )->execute();
427 $this->files[$key]->remove();
429 unset( $this->files[$key] );
430 unset( $this->fileMetadata[$key] );
442 if ( !$this->user->isRegistered() ) {
448 $res = $this->repo->getReplicaDB()->newSelectQueryBuilder()
450 ->from(
'uploadstash' )
451 ->where( [
'us_user' => $this->user->getId() ] )
452 ->caller( __METHOD__ )->fetchResultSet();
454 if ( $res->numRows() == 0 ) {
461 foreach ( $res as $row ) {
462 $keys[] = $row->us_key;
478 $prohibitedFileExtensions = MediaWikiServices::getInstance()
479 ->getMainConfig()->get( MainConfigNames::ProhibitedFileExtensions );
481 $n = strrpos(
$path,
'.' );
483 if ( $n !==
false ) {
484 $extension = $n ? substr(
$path, $n + 1 ) :
'';
487 $magic = MediaWikiServices::getInstance()->getMimeAnalyzer();
488 $mimeType = $magic->guessMimeType(
$path );
489 $extension = $magic->getExtensionFromMimeTypeOrNull( $mimeType ) ??
'';
492 $extension = File::normalizeExtension( $extension );
493 if ( in_array( $extension, $prohibitedFileExtensions ) ) {
515 $dbr = $this->repo->getPrimaryDB();
517 $dbr = $this->repo->getReplicaDB();
520 $row = $dbr->newSelectQueryBuilder()
522 'us_user',
'us_key',
'us_orig_path',
'us_path',
'us_props',
523 'us_size',
'us_sha1',
'us_mime',
'us_media_type',
524 'us_image_width',
'us_image_height',
'us_image_bits',
525 'us_source_type',
'us_timestamp',
'us_status',
527 ->from(
'uploadstash' )
528 ->where( [
'us_key' => $key ] )
529 ->caller( __METHOD__ )->fetchRow();
531 if ( !is_object( $row ) ) {
536 $this->fileMetadata[$key] = (array)$row;
537 $this->fileMetadata[$key][
'us_props'] = $dbr->decodeBlob( $row->us_props );
552 $this->fileMetadata[$key][
'us_path'],
554 $this->fileMetadata[$key][
'us_sha1']
556 if ( $file->getSize() === 0 ) {
561 $this->files[$key] = $file;
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
getFile()
Get the file for this page, if one exists.
Base class for file repositories.
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
MimeMagic helper wrapper.
Group all the pieces relevant to the context of a request into one instance.
A class containing constants representing the names of configuration variables.
UploadStash is intended to accomplish a few things:
static getExtensionForPath( $path)
Find or guess extension – ensuring that our extension matches our MIME type.
removeFile( $key)
Remove a particular file from the stash.
fetchFileMetadata( $key, $readFromDB=DB_REPLICA)
Helper function: do the actual database query to fetch file metadata.
getFileProps( $key)
Getter for fileProps.
clear()
Remove all files from the stash.
array $fileMetadata
cache of the file metadata that's stored in the database
array $fileProps
fileprops cache
listFiles()
List all files in the stash.
__construct(FileRepo $repo, UserIdentity $user=null)
Represents a temporary filestore, with metadata in the database.
getMetadata( $key)
Getter for file metadata.
removeFileNoAuth( $key)
Remove a file (see removeFile), but doesn't check ownership first.
initFile( $key)
Helper function: Initialize the UploadStashFile for a given file.
stashFile( $path, $sourceType=null, $fileProps=null)
Stash a file in a temp directory and record that we did this in the database, along with other metada...
getFile( $key, $noAuth=false)
Get a file and its metadata from the stash.
LocalRepo $repo
repository that this uses to store temp files public because we sometimes need to get a LocalFile wit...
array $files
array of initialized repo objects