Removed the ability to pass a key into stashFile(), which simplifies the stash row...
[lhc/web/wiklou.git] / includes / upload / UploadFromStash.php
1 <?php
2 /**
3 * Implements uploading from previously stored file.
4 *
5 * @file
6 * @ingroup upload
7 * @author Bryan Tong Minh
8 */
9
10 class UploadFromStash extends UploadBase {
11 protected $mFileKey, $mVirtualTempPath, $mFileProps, $mSourceType;
12
13 // an instance of UploadStash
14 private $stash;
15
16 //LocalFile repo
17 private $repo;
18
19 public function __construct( $user = false, $stash = false, $repo = false ) {
20 // user object. sometimes this won't exist, as when running from cron.
21 $this->user = $user;
22
23 if( $repo ) {
24 $this->repo = $repo;
25 } else {
26 $this->repo = RepoGroup::singleton()->getLocalRepo();
27 }
28
29 if( $stash ) {
30 $this->stash = $stash;
31 } else {
32 wfDebug( __METHOD__ . " creating new UploadStash instance for " . $user->getId() . "\n" );
33 $this->stash = new UploadStash( $this->repo, $this->user );
34 }
35
36 return true;
37 }
38
39 public static function isValidKey( $key ) {
40 // this is checked in more detail in UploadStash
41 return preg_match( UploadStash::KEY_FORMAT_REGEX, $key ) ? true : false;
42 }
43
44 /**
45 * @param $request WebRequest
46 *
47 * @return Boolean
48 */
49 public static function isValidRequest( $request ) {
50 // this passes wpSessionKey to getText() as a default when wpFileKey isn't set.
51 // wpSessionKey has no default which guarantees failure if both are missing
52 // (though that should have been caught earlier)
53 return self::isValidKey( $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) ) );
54 }
55
56 public function initialize( $key, $name = 'upload_file' ) {
57 /**
58 * Confirming a temporarily stashed upload.
59 * We don't want path names to be forged, so we keep
60 * them in the session on the server and just give
61 * an opaque key to the user agent.
62 */
63 $metadata = $this->stash->getMetadata( $key );
64 $this->initializePathInfo( $name,
65 $this->getRealPath ( $metadata['us_path'] ),
66 $metadata['us_size'],
67 false
68 );
69
70 $this->mFileKey = $key;
71 $this->mVirtualTempPath = $metadata['us_path'];
72 $this->mFileProps = $this->stash->getFileProps( $key );
73 $this->mSourceType = $metadata['us_source_type'];
74 }
75
76 /**
77 * @param $request WebRequest
78 */
79 public function initializeFromRequest( &$request ) {
80 // sends wpSessionKey as a default when wpFileKey is missing
81 $fileKey = $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) );
82
83 // chooses one of wpDestFile, wpUploadFile, filename in that order.
84 $desiredDestName = $request->getText( 'wpDestFile', $request->getText( 'wpUploadFile', $request->getText( 'filename' ) ) );
85
86 return $this->initialize( $fileKey, $desiredDestName );
87 }
88
89 public function getSourceType() {
90 return $this->mSourceType;
91 }
92
93 /**
94 * File has been previously verified so no need to do so again.
95 *
96 * @return bool
97 */
98 protected function verifyFile() {
99 return true;
100 }
101
102 /**
103 * There is no need to stash the image twice
104 */
105 public function stashFile() {
106 if ( $this->mLocalFile ) {
107 return $this->mLocalFile;
108 }
109 return parent::stashFile();
110 }
111
112 /**
113 * Alias for stashFile
114 */
115 public function stashSession() {
116 return $this->stashFile();
117 }
118
119 /**
120 * Remove a temporarily kept file stashed by saveTempUploadedFile().
121 * @return success
122 */
123 public function unsaveUploadedFile() {
124 return $this->stash->removeFile( $this->mFileKey );
125 }
126
127 /**
128 * Perform the upload, then remove the database record afterward.
129 */
130 public function performUpload( $comment, $pageText, $watch, $user ) {
131 $rv = parent::performUpload( $comment, $pageText, $watch, $user );
132 $this->unsaveUploadedFile();
133 return $rv;
134 }
135
136 /**
137 * Append a chunk to the temporary file.
138 *
139 * @return void
140 */
141 public function appendChunk($chunk, $chunkSize, $offset) {
142 //to use $this->getFileSize() here, db needs to be updated
143 //in appendToUploadFile for that
144 $fileSize = $this->stash->getFile( $this->mFileKey )->getSize();
145 if ( $fileSize + $chunkSize > $this->getMaxUploadSize()) {
146 $status = Status::newFatal( 'file-too-large' );
147 } else {
148 //append chunk
149 if ( $fileSize == $offset ) {
150 $status = $this->appendToUploadFile( $chunk,
151 $this->mVirtualTempPath );
152 } else {
153 $status = Status::newFatal( 'invalid-chunk-offset' );
154 }
155 }
156 return $status;
157 }
158
159 /**
160 * Append the final chunk and ready file for parent::performUpload()
161 * @return void
162 */
163 public function finalizeFile() {
164 $this->appendFinish ( $this->mVirtualTempPath );
165 $this->cleanupTempFile();
166 $this->mTempPath = $this->getRealPath( $this->mVirtualTempPath );
167 }
168 }