77 private const MAX_SERVE_BYTES = 1_048_576;
91 parent::__construct(
'UploadStash',
'upload' );
93 $this->httpRequestFactory = $httpRequestFactory;
94 $this->urlUtils = $urlUtils;
95 $this->dbProvider = $dbProvider;
112 $this->stash = $this->localRepo->getUploadStash( $this->
getUser() );
115 if ( $subPage ===
null || $subPage ===
'' ) {
116 $this->showUploads();
134 $params = $this->parseKey( $key );
135 if (
$params[
'type'] ===
'thumb' ) {
136 $this->outputThumbFromStash(
$params[
'file'],
$params[
'params'] );
138 $this->outputLocalFile(
$params[
'file'] );
143 $message = $e->getMessage();
144 }
catch ( Exception $e ) {
146 $message = $e->getMessage();
161 private function parseKey( $key ) {
162 $type = strtok( $key,
'/' );
164 if ( $type !==
'file' && $type !==
'thumb' ) {
166 $this->
msg(
'uploadstash-bad-path-unknown-type', $type )
169 $fileName = strtok(
'/' );
170 $thumbPart = strtok(
'/' );
171 $file = $this->stash->getFile( $fileName );
172 if ( $type ===
'thumb' ) {
173 $srcNamePos = strrpos( $thumbPart, $fileName );
174 if ( $srcNamePos ===
false || $srcNamePos < 1 ) {
176 $this->
msg(
'uploadstash-bad-path-unrecognized-thumb-name' )
179 $paramString = substr( $thumbPart, 0, $srcNamePos - 1 );
183 $params = $handler->parseParamString( $paramString );
189 return [
'file' => $file,
'type' => $type,
'params' =>
$params ];
197 return [
'file' => $file,
'type' => $type ];
206 private function outputThumbFromStash( $file,
$params ) {
212 if ( $file->
getRepo()->getThumbProxyUrl()
215 $this->outputRemoteScaledThumb( $file,
$params );
217 $this->outputLocallyScaledThumb( $file,
$params );
227 private function outputLocallyScaledThumb( $file,
$params ) {
232 if ( !$thumbnailImage ) {
234 $this->
msg(
'uploadstash-file-not-found-no-thumb' )
239 if ( !$thumbnailImage->getStoragePath() ) {
241 $this->
msg(
'uploadstash-file-not-found-no-local-path' )
248 $this->stash->repo, $thumbnailImage->getStoragePath(),
false );
250 $this->outputLocalFile( $thumbFile );
269 private function outputRemoteScaledThumb( $file,
$params ) {
277 $thumbProxyUrl = $file->
getRepo()->getThumbProxyUrl();
278 if ( strlen( $thumbProxyUrl ) ) {
279 $scalerThumbUrl = $thumbProxyUrl .
'temp/' . $file->
getUrlRel() .
280 '/' . rawurlencode( $scalerThumbName );
281 $secret = $file->
getRepo()->getThumbProxySecret();
288 if ( preg_match(
'/^\/\//', $scalerBaseUrl ) ) {
292 $scalerBaseUrl = $this->urlUtils->expand( $scalerBaseUrl,
PROTO_CANONICAL );
295 $scalerThumbUrl = $scalerBaseUrl .
'/' . $file->
getUrlRel() .
296 '/' . rawurlencode( $scalerThumbName );
306 $req = $this->httpRequestFactory->create( $scalerThumbUrl, $httpOptions, __METHOD__ );
309 if ( strlen( $secret ) ) {
310 $req->setHeader(
'X-Swift-Secret', $secret );
313 $status = $req->execute();
314 if ( !$status->isOK() ) {
315 $errors = $status->getErrorsArray();
318 'uploadstash-file-not-found-no-remote-thumb',
319 print_r( $errors, 1 ),
324 $contentType = $req->getResponseHeader(
"content-type" );
325 if ( !$contentType ) {
327 $this->
msg(
'uploadstash-file-not-found-missing-content-type' )
331 $this->outputContents( $req->getContent(), $contentType );
342 private function outputLocalFile(
File $file ) {
343 if ( $file->
getSize() > self::MAX_SERVE_BYTES ) {
345 $this->
msg(
'uploadstash-file-too-large', self::MAX_SERVE_BYTES )
350 [
'Content-Transfer-Encoding: binary',
351 'Expires: Sun, 17-Jan-2038 19:14:07 GMT' ]
362 private function outputContents( $content, $contentType ) {
363 $size = strlen( $content );
364 if ( $size > self::MAX_SERVE_BYTES ) {
366 $this->
msg(
'uploadstash-file-too-large', self::MAX_SERVE_BYTES )
371 self::outputFileHeaders( $contentType, $size );
384 private static function outputFileHeaders( $contentType, $size ) {
385 header(
"Content-Type: $contentType",
true );
386 header(
'Content-Transfer-Encoding: binary',
true );
387 header(
'Expires: Sun, 17-Jan-2038 19:14:07 GMT',
true );
389 header(
'Cache-Control: private' );
390 header(
"Content-Length: $size",
true );
397 private function showUploads() {
405 $form = HTMLForm::factory(
'ooui', [
411 ], $this->
getContext(),
'clearStashedUploads' );
413 $form->setSubmitDestructive();
414 $form->setSubmitCallback(
function ( $formData, $form ) {
415 if ( isset( $formData[
'Clear'] ) ) {
416 wfDebug(
'stash has: ' . print_r( $this->stash->listFiles(),
true ) );
418 if ( !$this->stash->clear() ) {
419 return Status::newFatal(
'uploadstash-errclear' );
423 return Status::newGood();
425 $form->setSubmitTextMsg(
'uploadstash-clear' );
427 $form->prepareForm();
428 $formResult = $form->tryAuthorizedSubmit();
432 $refreshHtml = $linkRenderer->makeKnownLink(
434 $this->
msg(
'uploadstash-refresh' )->text()
436 $pager =
new UploadStashPager(
443 if ( $pager->getNumRows() ) {
445 $this->
getOutput()->addParserOutputContent( $pager->getFullOutput() );
446 $form->displayForm( $formResult );
447 $this->
getOutput()->addHTML( Html::rawElement(
'p', [], $refreshHtml ) );
449 $this->
getOutput()->addHTML( Html::rawElement(
'p', [],