8cb22ce5c9170418b6d4b18919df1b5d28bc3552
[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 if( $user ) {
33 wfDebug( __METHOD__ . " creating new UploadStash instance for " . $user->getId() . "\n" );
34 } else {
35 wfDebug( __METHOD__ . " creating new UploadStash instance with no user\n" );
36 }
37
38 $this->stash = new UploadStash( $this->repo, $this->user );
39 }
40
41 return true;
42 }
43
44 public static function isValidKey( $key ) {
45 // this is checked in more detail in UploadStash
46 return (bool)preg_match( UploadStash::KEY_FORMAT_REGEX, $key );
47 }
48
49 /**
50 * @param $request WebRequest
51 *
52 * @return Boolean
53 */
54 public static function isValidRequest( $request ) {
55 // this passes wpSessionKey to getText() as a default when wpFileKey isn't set.
56 // wpSessionKey has no default which guarantees failure if both are missing
57 // (though that should have been caught earlier)
58 return self::isValidKey( $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) ) );
59 }
60
61 public function initialize( $key, $name = 'upload_file' ) {
62 /**
63 * Confirming a temporarily stashed upload.
64 * We don't want path names to be forged, so we keep
65 * them in the session on the server and just give
66 * an opaque key to the user agent.
67 */
68 $metadata = $this->stash->getMetadata( $key );
69 $this->initializePathInfo( $name,
70 $this->getRealPath ( $metadata['us_path'] ),
71 $metadata['us_size'],
72 false
73 );
74
75 $this->mFileKey = $key;
76 $this->mVirtualTempPath = $metadata['us_path'];
77 $this->mFileProps = $this->stash->getFileProps( $key );
78 $this->mSourceType = $metadata['us_source_type'];
79 }
80
81 /**
82 * @param $request WebRequest
83 */
84 public function initializeFromRequest( &$request ) {
85 // sends wpSessionKey as a default when wpFileKey is missing
86 $fileKey = $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) );
87
88 // chooses one of wpDestFile, wpUploadFile, filename in that order.
89 $desiredDestName = $request->getText( 'wpDestFile', $request->getText( 'wpUploadFile', $request->getText( 'filename' ) ) );
90
91 return $this->initialize( $fileKey, $desiredDestName );
92 }
93
94 public function getSourceType() {
95 return $this->mSourceType;
96 }
97
98 /**
99 * File has been previously verified so no need to do so again.
100 *
101 * @return bool
102 */
103 protected function verifyFile() {
104 return true;
105 }
106
107 /**
108 * Stash the file.
109 */
110 public function stashFile() {
111 // replace mLocalFile with an instance of UploadStashFile, which adds some methods
112 // that are useful for stashed files.
113 $this->mLocalFile = parent::stashFile();
114 return $this->mLocalFile;
115 }
116
117 /**
118 * Alias for stashFile
119 */
120 public function stashSession() {
121 return $this->stashFile();
122 }
123
124 /**
125 * Remove a temporarily kept file stashed by saveTempUploadedFile().
126 * @return success
127 */
128 public function unsaveUploadedFile() {
129 return $this->stash->removeFile( $this->mFileKey );
130 }
131
132 /**
133 * Perform the upload, then remove the database record afterward.
134 */
135 public function performUpload( $comment, $pageText, $watch, $user ) {
136 $rv = parent::performUpload( $comment, $pageText, $watch, $user );
137 $this->unsaveUploadedFile();
138 return $rv;
139 }
140
141 /**
142 * Append a chunk to the temporary file.
143 *
144 * @return void
145 */
146 public function appendChunk($chunk, $chunkSize, $offset) {
147 //to use $this->getFileSize() here, db needs to be updated
148 //in appendToUploadFile for that
149 $fileSize = $this->stash->getFile( $this->mFileKey )->getSize();
150 if ( $fileSize + $chunkSize > $this->getMaxUploadSize()) {
151 $status = Status::newFatal( 'file-too-large' );
152 } else {
153 //append chunk
154 if ( $fileSize == $offset ) {
155 $status = $this->appendToUploadFile( $chunk,
156 $this->mVirtualTempPath );
157 } else {
158 $status = Status::newFatal( 'invalid-chunk-offset' );
159 }
160 }
161 return $status;
162 }
163
164 /**
165 * Append the final chunk and ready file for parent::performUpload()
166 * @return void
167 */
168 public function finalizeFile() {
169 $this->appendFinish ( $this->mVirtualTempPath );
170 $this->cleanupTempFile();
171 $this->mTempPath = $this->getRealPath( $this->mVirtualTempPath );
172 }
173 }