75 private const MAX_SERVE_BYTES = 1_048_576;
89 parent::__construct(
'UploadStash',
'upload' );
91 $this->httpRequestFactory = $httpRequestFactory;
92 $this->urlUtils = $urlUtils;
93 $this->dbProvider = $dbProvider;
110 $this->stash = $this->localRepo->getUploadStash( $this->
getUser() );
113 if ( $subPage ===
null || $subPage ===
'' ) {
114 $this->showUploads();
132 $params = $this->parseKey( $key );
133 if (
$params[
'type'] ===
'thumb' ) {
134 $this->outputThumbFromStash(
$params[
'file'],
$params[
'params'] );
136 $this->outputLocalFile(
$params[
'file'] );
141 $message = $e->getMessage();
142 }
catch ( Exception $e ) {
144 $message = $e->getMessage();
159 private function parseKey( $key ) {
160 $type = strtok( $key,
'/' );
162 if ( $type !==
'file' && $type !==
'thumb' ) {
164 $this->
msg(
'uploadstash-bad-path-unknown-type', $type )
167 $fileName = strtok(
'/' );
168 $thumbPart = strtok(
'/' );
169 $file = $this->stash->getFile( $fileName );
170 if ( $type ===
'thumb' ) {
171 $srcNamePos = strrpos( $thumbPart, $fileName );
172 if ( $srcNamePos ===
false || $srcNamePos < 1 ) {
174 $this->
msg(
'uploadstash-bad-path-unrecognized-thumb-name' )
177 $paramString = substr( $thumbPart, 0, $srcNamePos - 1 );
181 $params = $handler->parseParamString( $paramString );
187 return [
'file' => $file,
'type' => $type,
'params' =>
$params ];
195 return [
'file' => $file,
'type' => $type ];
204 private function outputThumbFromStash( $file,
$params ) {
210 if ( $file->
getRepo()->getThumbProxyUrl()
213 $this->outputRemoteScaledThumb( $file,
$params );
215 $this->outputLocallyScaledThumb( $file,
$params );
225 private function outputLocallyScaledThumb( $file,
$params ) {
230 if ( !$thumbnailImage ) {
232 $this->
msg(
'uploadstash-file-not-found-no-thumb' )
237 if ( !$thumbnailImage->getStoragePath() ) {
239 $this->
msg(
'uploadstash-file-not-found-no-local-path' )
246 $this->stash->repo, $thumbnailImage->getStoragePath(),
false );
248 $this->outputLocalFile( $thumbFile );
267 private function outputRemoteScaledThumb( $file,
$params ) {
275 $thumbProxyUrl = $file->
getRepo()->getThumbProxyUrl();
276 if ( strlen( $thumbProxyUrl ) ) {
277 $scalerThumbUrl = $thumbProxyUrl .
'temp/' . $file->
getUrlRel() .
278 '/' . rawurlencode( $scalerThumbName );
279 $secret = $file->
getRepo()->getThumbProxySecret();
286 if ( preg_match(
'/^\/\//', $scalerBaseUrl ) ) {
290 $scalerBaseUrl = $this->urlUtils->expand( $scalerBaseUrl,
PROTO_CANONICAL );
293 $scalerThumbUrl = $scalerBaseUrl .
'/' . $file->
getUrlRel() .
294 '/' . rawurlencode( $scalerThumbName );
304 $req = $this->httpRequestFactory->create( $scalerThumbUrl, $httpOptions, __METHOD__ );
307 if ( strlen( $secret ) ) {
308 $req->setHeader(
'X-Swift-Secret', $secret );
311 $status = $req->execute();
312 if ( !$status->isOK() ) {
315 'uploadstash-file-not-found-no-remote-thumb',
316 $status->getMessage(),
321 $contentType = $req->getResponseHeader(
"content-type" );
322 if ( !$contentType ) {
324 $this->
msg(
'uploadstash-file-not-found-missing-content-type' )
328 $this->outputContents( $req->getContent(), $contentType );
339 private function outputLocalFile(
File $file ) {
340 if ( $file->
getSize() > self::MAX_SERVE_BYTES ) {
342 $this->
msg(
'uploadstash-file-too-large', self::MAX_SERVE_BYTES )
347 [
'Content-Transfer-Encoding: binary',
348 'Expires: Sun, 17-Jan-2038 19:14:07 GMT' ]
359 private function outputContents( $content, $contentType ) {
360 $size = strlen( $content );
361 if ( $size > self::MAX_SERVE_BYTES ) {
363 $this->
msg(
'uploadstash-file-too-large', self::MAX_SERVE_BYTES )
368 self::outputFileHeaders( $contentType, $size );
381 private static function outputFileHeaders( $contentType, $size ) {
382 header(
"Content-Type: $contentType",
true );
383 header(
'Content-Transfer-Encoding: binary',
true );
384 header(
'Expires: Sun, 17-Jan-2038 19:14:07 GMT',
true );
386 header(
'Cache-Control: private' );
387 header(
"Content-Length: $size",
true );
394 private function showUploads() {
402 $form = HTMLForm::factory(
'ooui', [
408 ], $this->
getContext(),
'clearStashedUploads' );
410 $form->setSubmitDestructive();
411 $form->setSubmitCallback(
function ( $formData, $form ) {
412 if ( isset( $formData[
'Clear'] ) ) {
413 wfDebug(
'stash has: ' . print_r( $this->stash->listFiles(),
true ) );
415 if ( !$this->stash->clear() ) {
416 return Status::newFatal(
'uploadstash-errclear' );
420 return Status::newGood();
422 $form->setSubmitTextMsg(
'uploadstash-clear' );
424 $form->prepareForm();
425 $formResult = $form->tryAuthorizedSubmit();
429 $refreshHtml = $linkRenderer->makeKnownLink(
431 $this->
msg(
'uploadstash-refresh' )->text()
433 $pager =
new UploadStashPager(
440 if ( $pager->getNumRows() ) {
442 $this->
getOutput()->addParserOutputContent( $pager->getFullOutput() );
443 $form->displayForm( $formResult );
444 $this->
getOutput()->addHTML( Html::rawElement(
'p', [], $refreshHtml ) );
446 $this->
getOutput()->addHTML( Html::rawElement(
'p', [],