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