Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.41% covered (warning)
63.41%
26 / 41
44.44% covered (danger)
44.44%
4 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
UploadFromStash
65.00% covered (warning)
65.00%
26 / 40
44.44% covered (danger)
44.44%
4 / 9
24.65
0.00% covered (danger)
0.00%
0 / 1
 __construct
70.00% covered (warning)
70.00%
7 / 10
0.00% covered (danger)
0.00%
0 / 1
4.43
 isValidKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isValidRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 initialize
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
3.00
 initializeFromRequest
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getSourceType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTempFileSha1Base36
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 unsaveUploadedFile
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 postProcessUpload
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Backend for uploading files from previously stored file.
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 * @ingroup Upload
8 */
9
10namespace MediaWiki\Upload;
11
12use LogicException;
13use MediaWiki\FileRepo\LocalRepo;
14use MediaWiki\MediaWikiServices;
15use MediaWiki\Request\WebRequest;
16use MediaWiki\Upload\Exception\UploadStashBadPathException;
17use MediaWiki\User\UserIdentity;
18
19/**
20 * Implements uploading from previously stored file.
21 *
22 * @ingroup Upload
23 * @author Bryan Tong Minh
24 */
25class UploadFromStash extends UploadBase {
26    /** @var string */
27    protected $mFileKey;
28    /** @var string */
29    protected $mVirtualTempPath;
30    /** @var string */
31    protected $mSourceType;
32
33    /** @var UploadStash */
34    private $stash;
35
36    /** @var LocalRepo */
37    private $repo;
38
39    /**
40     * @param UserIdentity|null $user Default: null Sometimes this won't exist, as when running from cron.
41     * @param UploadStash|false $stash Default: false
42     * @param LocalRepo|false $repo Default: false
43     */
44    public function __construct( ?UserIdentity $user = null, $stash = false, $repo = false ) {
45        if ( $repo ) {
46            $this->repo = $repo;
47        } else {
48            $this->repo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
49        }
50
51        if ( $stash ) {
52            $this->stash = $stash;
53        } else {
54            if ( $user ) {
55                wfDebug( __METHOD__ . " creating new UploadStash instance for " . $user->getId() );
56            } else {
57                wfDebug( __METHOD__ . " creating new UploadStash instance with no user" );
58            }
59
60            $this->stash = new UploadStash( $this->repo, $user );
61        }
62        parent::__construct();
63    }
64
65    /**
66     * @param string $key
67     * @return bool
68     */
69    public static function isValidKey( $key ) {
70        // this is checked in more detail in UploadStash
71        return (bool)preg_match( UploadStash::KEY_FORMAT_REGEX, $key );
72    }
73
74    /**
75     * @param WebRequest $request
76     * @return bool
77     */
78    public static function isValidRequest( $request ) {
79        // this passes wpSessionKey to getText() as a default when wpFileKey isn't set.
80        // wpSessionKey has no default which guarantees failure if both are missing
81        // (though that should have been caught earlier)
82        return self::isValidKey( $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) ) );
83    }
84
85    /**
86     * @param string $key
87     * @param string $name
88     * @param bool $initTempFile
89     */
90    public function initialize( $key, $name = 'upload_file', $initTempFile = true ) {
91        /**
92         * Confirming a temporarily stashed upload.
93         * We don't want path names to be forged, so we keep
94         * them in the session on the server and just give
95         * an opaque key to the user agent.
96         */
97        $metadata = $this->stash->getMetadata( $key );
98        $tempPath = $initTempFile ? $this->getRealPath( $metadata['us_path'] ) : null;
99        if ( $tempPath === false ) {
100            throw new UploadStashBadPathException( wfMessage( 'uploadstash-bad-path' ) );
101        }
102        $this->initializePathInfo( $name,
103            $tempPath,
104            $metadata['us_size'],
105            false
106        );
107
108        $this->mFileKey = $key;
109        $this->mVirtualTempPath = $metadata['us_path'];
110        $this->mFileProps = $this->stash->getFileProps( $key );
111        $this->mSourceType = $metadata['us_source_type'];
112        $this->mStashFile = $this->stash->getFile( $key );
113    }
114
115    /**
116     * @param WebRequest &$request
117     */
118    public function initializeFromRequest( &$request ) {
119        // sends wpSessionKey as a default when wpFileKey is missing
120        $fileKey = $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) );
121
122        // chooses one of wpDestFile, wpUploadFile, filename in that order.
123        $desiredDestName = $request->getText(
124            'wpDestFile',
125            $request->getText( 'wpUploadFile', $request->getText( 'filename' ) )
126        );
127
128        $this->initialize( $fileKey, $desiredDestName );
129    }
130
131    /**
132     * @return string
133     */
134    public function getSourceType() {
135        return $this->mSourceType;
136    }
137
138    /**
139     * Get the base 36 SHA1 of the file
140     * @return string
141     */
142    public function getTempFileSha1Base36() {
143        // phan doesn't like us accessing this directly since in
144        // parent class this can be null, however we always set this in
145        // this class so it is safe. Add a check to keep phan happy.
146        if ( !is_array( $this->mFileProps ) ) {
147            throw new LogicException( "mFileProps should never be null" );
148        } else {
149            return $this->mFileProps['sha1'];
150        }
151    }
152
153    /**
154     * Remove a temporarily kept file stashed by saveTempUploadedFile().
155     * @return bool Success
156     */
157    public function unsaveUploadedFile() {
158        $this->mStashFile = null;
159        return $this->stash->removeFile( $this->mFileKey );
160    }
161
162    /**
163     * Remove the database record after a successful upload.
164     */
165    public function postProcessUpload() {
166        parent::postProcessUpload();
167        $this->unsaveUploadedFile();
168    }
169}
170
171/** @deprecated class alias since 1.46 */
172class_alias( UploadFromStash::class, 'UploadFromStash' );