59 private const MAX_US_PROPS_SIZE = 65535;
95 $this->user = $user ?? RequestContext::getMain()->getUser();
111 public function getFile( $key, $noAuth =
false ) {
112 if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
114 wfMessage(
'uploadstash-bad-path-bad-format', $key )
118 if ( !$noAuth && !$this->user->isRegistered() ) {
124 if ( !isset( $this->fileMetadata[$key] ) ) {
131 if ( !isset( $this->fileMetadata[$key] ) ) {
133 wfMessage(
'uploadstash-file-not-found', $key )
142 isset( $this->fileMetadata[$key][
'us_props'] ) && strlen( $this->fileMetadata[$key][
'us_props'] )
144 $this->fileProps[$key] = unserialize( $this->fileMetadata[$key][
'us_props'] );
146 wfDebug( __METHOD__ .
" fetched props for $key from file" );
147 $path = $this->fileMetadata[$key][
'us_path'];
148 $this->fileProps[$key] = $this->repo->getFileProps(
$path );
152 if ( !$this->files[$key]->exists() ) {
153 wfDebug( __METHOD__ .
" tried to get file at $key, but it doesn't exist" );
160 if ( !$noAuth && $this->fileMetadata[$key][
'us_user'] != $this->user->getId() ) {
162 wfMessage(
'uploadstash-wrong-owner', $key )
166 return $this->files[$key];
178 return $this->fileMetadata[$key];
190 return $this->fileProps[$key];
207 if ( !is_file(
$path ) ) {
208 wfDebug( __METHOD__ .
" tried to stash file at '$path', but it doesn't exist" );
219 wfDebug( __METHOD__ .
" stashing file at '$path'" );
224 if ( !preg_match(
"/\\.\\Q$extension\\E$/",
$path ) ) {
225 $pathWithGoodExtension =
"$path.$extension";
227 $pathWithGoodExtension =
$path;
235 [ $usec, $sec ] = explode(
' ', microtime() );
236 $usec = substr( $usec, 2 );
237 $key = \Wikimedia\base_convert( $sec . $usec, 10, 36 ) .
'.' .
238 \Wikimedia\base_convert( (
string)mt_rand(), 10, 36 ) .
'.' .
239 $this->user->getId() .
'.' .
244 if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
246 wfMessage(
'uploadstash-bad-path-bad-format', $key )
250 wfDebug( __METHOD__ .
" key for '$path': $key" );
253 $storeStatus = $this->repo->storeTemp( basename( $pathWithGoodExtension ),
$path );
255 if ( !$storeStatus->isOK() ) {
264 foreach ( $storeStatus->getMessages(
'error' ) as $msg ) {
267 foreach ( $storeStatus->getMessages(
'warning' ) as $msg ) {
273 $stashPath = $storeStatus->value;
276 if ( !$this->user->isRegistered() ) {
283 wfDebug( __METHOD__ .
" inserting $stashPath under $key" );
284 $dbw = $this->repo->getPrimaryDB();
286 $serializedFileProps = serialize(
$fileProps );
287 if ( strlen( $serializedFileProps ) > self::MAX_US_PROPS_SIZE ) {
292 $serializedFileProps = serialize(
$fileProps );
296 'us_user' => $this->user->getId(),
298 'us_orig_path' =>
$path,
299 'us_path' => $stashPath,
300 'us_props' => $dbw->encodeBlob( $serializedFileProps ),
308 'us_source_type' => $sourceType,
309 'us_timestamp' => $dbw->timestamp(),
310 'us_status' =>
'finished'
313 $dbw->newInsertQueryBuilder()
314 ->insertInto(
'uploadstash' )
316 ->caller( __METHOD__ )->execute();
320 $insertRow[
'us_id'] = $dbw->insertId();
322 $this->fileMetadata[$key] = $insertRow;
324 # create the UploadStashFile object for this file.
338 if ( !$this->user->isRegistered() ) {
344 wfDebug( __METHOD__ .
' clearing all rows for user ' . $this->user->getId() );
345 $dbw = $this->repo->getPrimaryDB();
346 $dbw->newDeleteQueryBuilder()
347 ->deleteFrom(
'uploadstash' )
348 ->where( [
'us_user' => $this->user->getId() ] )
349 ->caller( __METHOD__ )->execute();
353 $this->fileMetadata = [];
367 if ( !$this->user->isRegistered() ) {
373 $dbw = $this->repo->getPrimaryDB();
377 $row = $dbw->newSelectQueryBuilder()
378 ->select(
'us_user' )
379 ->from(
'uploadstash' )
380 ->where( [
'us_key' => $key ] )
381 ->caller( __METHOD__ )->fetchRow();
385 wfMessage(
'uploadstash-no-such-key', $key )
389 if ( $row->us_user != $this->user->getId() ) {
391 wfMessage(
'uploadstash-wrong-owner', $key )
405 wfDebug( __METHOD__ .
" clearing row $key" );
410 $dbw = $this->repo->getPrimaryDB();
412 $dbw->newDeleteQueryBuilder()
413 ->deleteFrom(
'uploadstash' )
414 ->where( [
'us_key' => $key ] )
415 ->caller( __METHOD__ )->execute();
420 $this->files[$key]->remove();
422 unset( $this->files[$key] );
423 unset( $this->fileMetadata[$key] );
435 if ( !$this->user->isRegistered() ) {
441 return $this->repo->getReplicaDB()->newSelectQueryBuilder()
443 ->from(
'uploadstash' )
444 ->where( [
'us_user' => $this->user->getId() ] )
445 ->caller( __METHOD__ )
446 ->fetchFieldValues();
462 $n = strrpos(
$path,
'.' );
464 if ( $n !==
false ) {
465 $extension = $n ? substr(
$path, $n + 1 ) :
'';
469 $mimeType = $magic->guessMimeType(
$path );
470 $extension = $magic->getExtensionFromMimeTypeOrNull( $mimeType ) ??
'';
473 $extension = File::normalizeExtension( $extension );
474 if ( in_array( $extension, $prohibitedFileExtensions ) ) {
496 $dbr = $this->repo->getPrimaryDB();
498 $dbr = $this->repo->getReplicaDB();
501 $row = $dbr->newSelectQueryBuilder()
503 'us_user',
'us_key',
'us_orig_path',
'us_path',
'us_props',
504 'us_size',
'us_sha1',
'us_mime',
'us_media_type',
505 'us_image_width',
'us_image_height',
'us_image_bits',
506 'us_source_type',
'us_timestamp',
'us_status',
508 ->from(
'uploadstash' )
509 ->where( [
'us_key' => $key ] )
510 ->caller( __METHOD__ )->fetchRow();
512 if ( !is_object( $row ) ) {
517 $this->fileMetadata[$key] = (array)$row;
518 $this->fileMetadata[$key][
'us_props'] = $dbr->decodeBlob( $row->us_props );
533 $this->fileMetadata[$key][
'us_path'],
535 $this->fileMetadata[$key][
'us_sha1'],
536 $this->fileMetadata[$key][
'us_mime'] ??
false
538 if ( $file->getSize() === 0 ) {
543 $this->files[$key] = $file;
550class_alias( UploadStash::class,
'UploadStash' );
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.
if(!defined('MW_SETUP_CALLBACK'))
Group all the pieces relevant to the context of a request into one instance.
A class containing constants representing the names of configuration variables.
const ProhibitedFileExtensions
Name constant for the ProhibitedFileExtensions setting, for use with Config::get()