Movatterモバイル変換


[0]ホーム

URL:


MediaWiki master
SpecialUploadStash.php
Go to the documentation of this file.
1<?php
7namespaceMediaWiki\Specials;
8
9use Exception;
10useMediaWiki\Exception\HttpError;
11useMediaWiki\FileRepo\File\File;
12useMediaWiki\FileRepo\File\UnregisteredLocalFile;
13useMediaWiki\FileRepo\LocalRepo;
14useMediaWiki\FileRepo\RepoGroup;
15useMediaWiki\Html\Html;
16useMediaWiki\HTMLForm\HTMLForm;
17useMediaWiki\Http\HttpRequestFactory;
18useMediaWiki\MainConfigNames;
19use MediaWiki\Pager\UploadStashPager;
20useMediaWiki\Parser\ParserOptions;
21useMediaWiki\SpecialPage\UnlistedSpecialPage;
22useMediaWiki\Status\Status;
23useMediaWiki\Utils\UrlUtils;
24useSpecialUploadStashTooLargeException;
25useUploadStash;
26useUploadStashBadPathException;
27useUploadStashFileNotFoundException;
28useWikimedia\Rdbms\IConnectionProvider;
29
43classSpecialUploadStashextendsUnlistedSpecialPage {
45private $stash;
46
47privateLocalRepo $localRepo;
48privateHttpRequestFactory $httpRequestFactory;
49privateUrlUtils $urlUtils;
50privateIConnectionProvider $dbProvider;
51
62privateconst MAX_SERVE_BYTES = 1_048_576;// 1 MiB
63
64publicfunction__construct(
65RepoGroup $repoGroup,
66HttpRequestFactory $httpRequestFactory,
67UrlUtils $urlUtils,
68IConnectionProvider $dbProvider
69 ) {
70 parent::__construct('UploadStash','upload' );
71 $this->localRepo = $repoGroup->getLocalRepo();
72 $this->httpRequestFactory = $httpRequestFactory;
73 $this->urlUtils = $urlUtils;
74 $this->dbProvider = $dbProvider;
75 }
76
78publicfunctiondoesWrites() {
79returntrue;
80 }
81
88publicfunctionexecute( $subPage ) {
90
91// This is not set in constructor, because the context with the user is not safe to be set
92 $this->stash = $this->localRepo->getUploadStash( $this->getUser() );
93 $this->checkPermissions();
94
95if ( $subPage ===null || $subPage ==='' ) {
96 $this->showUploads();
97 }else {
98 $this->showUpload( $subPage );
99 }
100 }
101
109publicfunctionshowUpload( $key ) {
110// prevent callers from doing standard HTML output -- we'll take it from here
111 $this->getOutput()->disable();
112
113try {
114 $params = $this->parseKey( $key );
115if ( $params['type'] ==='thumb' ) {
116 $this->outputThumbFromStash( $params['file'], $params['params'] );
117 }else {
118 $this->outputLocalFile( $params['file'] );
119 }
120return;
122 $code = 404;
123 $message = $e->getMessage();
124 }catch ( Exception $e ) {
125 $code = 500;
126 $message = $e->getMessage();
127 }
128
129thrownewHttpError( $code, $message );
130 }
131
141privatefunction parseKey( $key ) {
142 $type = strtok( $key,'/' );
143
144if ( $type !=='file' && $type !=='thumb' ) {
145thrownewUploadStashBadPathException(
146 $this->msg('uploadstash-bad-path-unknown-type', $type )
147 );
148 }
149 $fileName = strtok('/' );
150 $thumbPart = strtok('/' );
151 $file = $this->stash->getFile( $fileName );
152if ( $type ==='thumb' ) {
153 $srcNamePos = strrpos( $thumbPart, $fileName );
154if ( $srcNamePos ===false || $srcNamePos < 1 ) {
155thrownewUploadStashBadPathException(
156 $this->msg('uploadstash-bad-path-unrecognized-thumb-name' )
157 );
158 }
159 $paramString = substr( $thumbPart, 0, $srcNamePos - 1 );
160
161 $handler = $file->getHandler();
162if ( $handler ) {
163 $params = $handler->parseParamString( $paramString );
164if ( $params ===false ) {
165// The params are invalid, but still try to show a thumb
166 $params = [];
167 }
168
169return ['file' => $file,'type' => $type,'params' =>$params ];
170 }else {
171thrownewUploadStashBadPathException(
172 $this->msg('uploadstash-bad-path-no-handler', $file->getMimeType(), $file->getPath() )
173 );
174 }
175 }
176
177return ['file' => $file,'type' => $type ];
178 }
179
186privatefunction outputThumbFromStash( $file, $params ) {
187// this config option, if it exists, points to a "scaler", as you might find in
188// the Wikimedia Foundation cluster. See outputRemoteScaledThumb(). This
189// is part of our horrible NFS-based system, we create a file on a mount
190// point here, but fetch the scaled file from somewhere else that
191// happens to share it over NFS.
192if ( $file->getRepo()->getThumbProxyUrl()
193 || $this->getConfig()->get(MainConfigNames::UploadStashScalerBaseUrl )
194 ) {
195 $this->outputRemoteScaledThumb( $file, $params );
196 }else {
197 $this->outputLocallyScaledThumb( $file, $params );
198 }
199 }
200
207privatefunction outputLocallyScaledThumb( $file, $params ) {
208// n.b. this is stupid, we insist on re-transforming the file every time we are invoked. We rely
209// on HTTP caching to ensure this doesn't happen.
210
211 $thumbnailImage = $file->transform( $params, File::RENDER_NOW );
212if ( !$thumbnailImage ) {
213thrownewUploadStashFileNotFoundException(
214 $this->msg('uploadstash-file-not-found-no-thumb' )
215 );
216 }
217
218// we should have just generated it locally
219if ( !$thumbnailImage->getStoragePath() ) {
220thrownewUploadStashFileNotFoundException(
221 $this->msg('uploadstash-file-not-found-no-local-path' )
222 );
223 }
224
225// now we should construct a File, so we can get MIME and other such info in a standard way
226// n.b. MIME type may be different from original (ogx original -> jpeg thumb)
227 $thumbFile =new UnregisteredLocalFile(false,
228 $this->stash->repo, $thumbnailImage->getStoragePath(),false );
229
230 $this->outputLocalFile( $thumbFile );
231 }
232
249privatefunction outputRemoteScaledThumb( $file, $params ) {
250// We need to use generateThumbName() instead of thumbName(), because
251// the suffix needs to match the file name for the remote thumbnailer
252// to work
253 $scalerThumbName = $file->generateThumbName( $file->getName(), $params );
254
255// If a thumb proxy is set up for the repo, we favor that, as that will
256// keep the request internal
257 $thumbProxyUrl = $file->getRepo()->getThumbProxyUrl();
258if ( $thumbProxyUrl !==null ) {
259 $scalerThumbUrl = $thumbProxyUrl .'temp/' . $file->getUrlRel() .
260'/' . rawurlencode( $scalerThumbName );
261 $secret = $file->getRepo()->getThumbProxySecret();
262 }else {
263// This option probably looks something like
264// '//upload.wikimedia.org/wikipedia/test/thumb/temp'. Do not use
265// trailing slash.
266 $scalerBaseUrl = $this->getConfig()->get(MainConfigNames::UploadStashScalerBaseUrl );
267
268if ( preg_match('/^\/\//', $scalerBaseUrl ) ) {
269// this is apparently a protocol-relative URL, which makes no sense in this context,
270// since this is used for communication that's internal to the application.
271// default to http.
272 $scalerBaseUrl = $this->urlUtils->expand( $scalerBaseUrl,PROTO_CANONICAL );
273 }
274
275 $scalerThumbUrl = $scalerBaseUrl .'/' . $file->getUrlRel() .
276'/' . rawurlencode( $scalerThumbName );
277 $secret =null;
278 }
279
280// make an http request based on wgUploadStashScalerBaseUrl to lazy-create
281// a thumbnail
282 $httpOptions = [
283'method' =>'GET',
284'timeout' => 5// T90599 attempt to time out cleanly
285 ];
286 $req = $this->httpRequestFactory->create( $scalerThumbUrl, $httpOptions, __METHOD__ );
287
288// Pass a secret key shared with the proxied service if any
289if ( $secret !==null ) {
290 $req->setHeader('X-Swift-Secret', $secret );
291 }
292
293 $status = $req->execute();
294if ( !$status->isOK() ) {
295thrownewUploadStashFileNotFoundException(
296 $this->msg(
297'uploadstash-file-not-found-no-remote-thumb',
298 $status->getMessage(),
299 $scalerThumbUrl
300 )
301 );
302 }
303 $contentType = $req->getResponseHeader("content-type" );
304if ( !$contentType ) {
305thrownewUploadStashFileNotFoundException(
306 $this->msg('uploadstash-file-not-found-missing-content-type' )
307 );
308 }
309
310 $this->outputContents( $req->getContent(), $contentType );
311 }
312
321privatefunction outputLocalFile( File $file ) {
322if ( $file->getSize() > self::MAX_SERVE_BYTES ) {
323thrownewSpecialUploadStashTooLargeException(
324 $this->msg('uploadstash-file-too-large', self::MAX_SERVE_BYTES )
325 );
326 }
327
328 $file->getRepo()->streamFileWithStatus( $file->getPath(),
329 ['Content-Transfer-Encoding: binary',
330'Expires: Sun, 17-Jan-2038 19:14:07 GMT' ]
331 );
332 }
333
341privatefunction outputContents( $content, $contentType ) {
342 $size = strlen( $content );
343if ( $size > self::MAX_SERVE_BYTES ) {
344thrownewSpecialUploadStashTooLargeException(
345 $this->msg('uploadstash-file-too-large', self::MAX_SERVE_BYTES )
346 );
347 }
348// Cancel output buffering and gzipping if set
349wfResetOutputBuffers();
350 self::outputFileHeaders( $contentType, $size );
351 print $content;
352 }
353
363privatestaticfunction outputFileHeaders( $contentType, $size ) {
364 header("Content-Type: $contentType",true );
365 header('Content-Transfer-Encoding: binary',true );
366 header('Expires: Sun, 17-Jan-2038 19:14:07 GMT',true );
367// T55032 - It shouldn't be a problem here, but let's be safe and not cache
368 header('Cache-Control: private' );
369 header("Content-Length: $size",true );
370 }
371
376privatefunction showUploads() {
377// sets the title, etc.
378 $this->setHeaders();
379 $this->outputHeader();
380 $this->getOutput()->addModuleStyles('mediawiki.special' );
381
382// create the form, which will also be used to execute a callback to process incoming form data
383// this design is extremely dubious, but supposedly HTMLForm is our standard now?
384
385 $form = HTMLForm::factory('ooui', [
386'Clear' => [
387'type' =>'hidden',
388'default' =>true,
389'name' =>'clear',
390 ]
391 ], $this->getContext(),'clearStashedUploads' );
392 $form->setTitle( $this->getPageTitle() );// Remove subpage
393 $form->setSubmitDestructive();
394 $form->setSubmitCallback(function ( $formData, $form ) {
395if ( isset( $formData['Clear'] ) ) {
396wfDebug('stash has: ' . print_r( $this->stash->listFiles(),true ) );
397
398if ( !$this->stash->clear() ) {
399return Status::newFatal('uploadstash-errclear' );
400 }
401 }
402
403return Status::newGood();
404 } );
405 $form->setSubmitTextMsg('uploadstash-clear' );
406
407 $form->prepareForm();
408 $formResult = $form->tryAuthorizedSubmit();
409
410// show the files + form, if there are any, or just say there are none
411 $linkRenderer = $this->getLinkRenderer();
412 $refreshHtml = $linkRenderer->makeKnownLink(
413 $this->getPageTitle(),
414 $this->msg('uploadstash-refresh' )->text()
415 );
416 $pager =new UploadStashPager(
417 $this->getContext(),
418 $linkRenderer,
419 $this->dbProvider,
420 $this->stash,
421 $this->localRepo
422 );
423if ( $pager->getNumRows() ) {
424 $pager->getForm();
425 $this->getOutput()->addParserOutputContent(
426 $pager->getFullOutput(),
427 ParserOptions::newFromContext( $this->getContext() )
428 );
429 $form->displayForm( $formResult );
430 $this->getOutput()->addHTML( Html::rawElement('p', [], $refreshHtml ) );
431 }else {
432 $this->getOutput()->addHTML( Html::rawElement('p', [],
433Html::element('span', [], $this->msg('uploadstash-nofiles' )->text() )
434 .' '
435 . $refreshHtml
436 ) );
437 }
438 }
439}
440
445class_alias( SpecialUploadStash::class,'SpecialUploadStash' );
PROTO_CANONICAL
const PROTO_CANONICAL
DefinitionDefines.php:223
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
DefinitionGlobalFunctions.php:632
wfResetOutputBuffers
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
DefinitionGlobalFunctions.php:1255
MediaWiki\Exception\HttpError
Show an error that looks like an HTTP server error.
DefinitionHttpError.php:23
MediaWiki\FileRepo\File\File
Implements some public methods and some protected utility functions which are required by multiple ch...
DefinitionFile.php:79
MediaWiki\FileRepo\File\UnregisteredLocalFile
File without associated database record.
DefinitionUnregisteredLocalFile.php:30
MediaWiki\FileRepo\LocalRepo
Local repository that stores files in the local filesystem and registers them in the wiki's own datab...
DefinitionLocalRepo.php:45
MediaWiki\FileRepo\RepoGroup
Prioritized list of file repositories.
DefinitionRepoGroup.php:29
MediaWiki\FileRepo\RepoGroup\getLocalRepo
getLocalRepo()
Get the local repository, i.e.
DefinitionRepoGroup.php:343
MediaWiki\HTMLForm\HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
DefinitionHTMLForm.php:195
MediaWiki\Html\Html
This class is a collection of static functions that serve two purposes:
DefinitionHtml.php:43
MediaWiki\Http\HttpRequestFactory
Factory creating MWHttpRequest objects.
DefinitionHttpRequestFactory.php:24
MediaWiki\MainConfigNames
A class containing constants representing the names of configuration variables.
DefinitionMainConfigNames.php:22
MediaWiki\MainConfigNames\UploadStashScalerBaseUrl
const UploadStashScalerBaseUrl
Name constant for the UploadStashScalerBaseUrl setting, for use with Config::get()
DefinitionMainConfigNames.php:215
MediaWiki\Parser\ParserOptions
Set options of the Parser.
DefinitionParserOptions.php:65
MediaWiki\SpecialPage\SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
DefinitionSpecialPage.php:685
MediaWiki\SpecialPage\SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
DefinitionSpecialPage.php:884
MediaWiki\SpecialPage\SpecialPage\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
DefinitionSpecialPage.php:1103
MediaWiki\SpecialPage\SpecialPage\getLinkRenderer
getLinkRenderer()
DefinitionSpecialPage.php:1113
MediaWiki\SpecialPage\SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
DefinitionSpecialPage.php:828
MediaWiki\SpecialPage\SpecialPage\checkPermissions
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
DefinitionSpecialPage.php:387
MediaWiki\SpecialPage\SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
DefinitionSpecialPage.php:949
MediaWiki\SpecialPage\SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
DefinitionSpecialPage.php:848
MediaWiki\SpecialPage\SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
DefinitionSpecialPage.php:985
MediaWiki\SpecialPage\SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
DefinitionSpecialPage.php:874
MediaWiki\SpecialPage\SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
DefinitionSpecialPage.php:773
MediaWiki\SpecialPage\UnlistedSpecialPage
Shortcut to construct a special page which is unlisted by default.
DefinitionUnlistedSpecialPage.php:19
MediaWiki\Specials\SpecialUploadStash
Web access for files temporarily stored by UploadStash.
DefinitionSpecialUploadStash.php:43
MediaWiki\Specials\SpecialUploadStash\doesWrites
doesWrites()
Indicates whether POST requests to this special page require write access to the wiki....
DefinitionSpecialUploadStash.php:78
MediaWiki\Specials\SpecialUploadStash\execute
execute( $subPage)
Execute page – can output a file directly or show a listing of them.
DefinitionSpecialUploadStash.php:88
MediaWiki\Specials\SpecialUploadStash\showUpload
showUpload( $key)
If file available in stash, cats it out to the client as a simple HTTP response.
DefinitionSpecialUploadStash.php:109
MediaWiki\Specials\SpecialUploadStash\__construct
__construct(RepoGroup $repoGroup, HttpRequestFactory $httpRequestFactory, UrlUtils $urlUtils, IConnectionProvider $dbProvider)
DefinitionSpecialUploadStash.php:64
MediaWiki\Status\Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
DefinitionStatus.php:44
MediaWiki\Utils\UrlUtils
A service to expand, parse, and otherwise manipulate URLs.
DefinitionUrlUtils.php:16
SpecialUploadStashTooLargeException
DefinitionSpecialUploadStashTooLargeException.php:12
UploadStashBadPathException
DefinitionUploadStashBadPathException.php:11
UploadStashFileNotFoundException
DefinitionUploadStashFileNotFoundException.php:11
UploadStash
UploadStash is intended to accomplish a few things:
DefinitionUploadStash.php:46
Wikimedia\Rdbms\IConnectionProvider
Provide primary and replica IDatabase connections.
DefinitionIConnectionProvider.php:21
MediaWiki\Html\element
element(SerializerNode $parent, SerializerNode $node, $contents)
DefinitionHtmlHelperTrait.php:38
MediaWiki\JobQueue\Jobs\$params
array $params
The job parameters.
DefinitionUploadJobTrait.php:38
MediaWiki\Specials

[8]ページ先頭

©2009-2025 Movatter.jp