MediaWiki REL1_39
thumb.php
Go to the documentation of this file.
1<?php
31use Wikimedia\AtEase\AtEase;
32
33define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
34// T241340: thumb.php is included by thumb_handler.php which already defined
35// MW_ENTRY_POINT to 'thumb_handler'
36if ( !defined( 'MW_ENTRY_POINT' ) ) {
37 define( 'MW_ENTRY_POINT', 'thumb' );
38}
39require __DIR__ . '/includes/WebStart.php';
40
42
43function wfThumbMain() {
45
46 // Don't use fancy MIME detection, just check the file extension for jpg/gif/png
48
49 if ( defined( 'THUMB_HANDLER' ) ) {
50 // Called from thumb_handler.php via 404; extract params from the URI...
52 } else {
53 // Called directly, use $_GET params
54 wfStreamThumb( $wgRequest->getQueryValuesOnly() );
55 }
56
57 $mediawiki = new MediaWiki();
58 $mediawiki->doPostOutputShutdown();
59}
60
66function wfThumbHandle404() {
67 global $wgThumbPath;
68
69 if ( $wgThumbPath ) {
70 $relPath = WebRequest::getRequestPathSuffix( $wgThumbPath );
71 } else {
72 // Determine the request path relative to the thumbnail zone base
73 $repo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
74 $baseUrl = $repo->getZoneUrl( 'thumb' );
75 if ( substr( $baseUrl, 0, 1 ) === '/' ) {
76 $basePath = $baseUrl;
77 } else {
78 $basePath = parse_url( $baseUrl, PHP_URL_PATH );
79 }
80 $relPath = WebRequest::getRequestPathSuffix( $basePath );
81 }
82
83 $params = wfExtractThumbRequestInfo( $relPath ); // basic wiki URL param extracting
84 if ( $params == null ) {
85 wfThumbError( 400, 'The specified thumbnail parameters are not recognized.' );
86 return;
87 }
88
89 wfStreamThumb( $params ); // stream the thumbnail
90}
91
105function wfStreamThumb( array $params ) {
106 global $wgVaryOnXFP;
107 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
108
109 $headers = []; // HTTP headers to send
110
111 $fileName = $params['f'] ?? '';
112
113 // Backwards compatibility parameters
114 if ( isset( $params['w'] ) ) {
115 $params['width'] = $params['w'];
116 unset( $params['w'] );
117 }
118 if ( isset( $params['width'] ) && substr( $params['width'], -2 ) == 'px' ) {
119 // strip the px (pixel) suffix, if found
120 $params['width'] = substr( $params['width'], 0, -2 );
121 }
122 if ( isset( $params['p'] ) ) {
123 $params['page'] = $params['p'];
124 }
125
126 // Is this a thumb of an archived file?
127 $isOld = ( isset( $params['archived'] ) && $params['archived'] );
128 unset( $params['archived'] ); // handlers don't care
129
130 // Is this a thumb of a temp file?
131 $isTemp = ( isset( $params['temp'] ) && $params['temp'] );
132 unset( $params['temp'] ); // handlers don't care
133
134 // Some basic input validation
135 $fileName = strtr( $fileName, '\\/', '__' );
136 $localRepo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
137
138 // Actually fetch the image. Method depends on whether it is archived or not.
139 if ( $isTemp ) {
140 $repo = $localRepo->getTempRepo();
141 $img = new UnregisteredLocalFile( null, $repo,
142 # Temp files are hashed based on the name without the timestamp.
143 # The thumbnails will be hashed based on the entire name however.
144 # @todo fix this convention to actually be reasonable.
145 $repo->getZonePath( 'public' ) . '/' . $repo->getTempHashPath( $fileName ) . $fileName
146 );
147 } elseif ( $isOld ) {
148 // Format is <timestamp>!<name>
149 $bits = explode( '!', $fileName, 2 );
150 if ( count( $bits ) != 2 ) {
151 wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
152 return;
153 }
154 $title = Title::makeTitleSafe( NS_FILE, $bits[1] );
155 if ( !$title ) {
156 wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
157 return;
158 }
159 $img = $localRepo->newFromArchiveName( $title, $fileName );
160 } else {
161 $img = $localRepo->newFile( $fileName );
162 }
163
164 // Check the source file title
165 if ( !$img ) {
166 wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
167 return;
168 }
169
170 // Check permissions if there are read restrictions
171 $varyHeader = [];
172 if ( !in_array( 'read', $permissionManager->getGroupPermissions( [ '*' ] ), true ) ) {
173 $user = RequestContext::getMain()->getUser();
174 $imgTitle = $img->getTitle();
175
176 if ( !$imgTitle || !$permissionManager->userCan( 'read', $user, $imgTitle ) ) {
177 wfThumbError( 403, 'Access denied. You do not have permission to access ' .
178 'the source file.' );
179 return;
180 }
181 $headers[] = 'Cache-Control: private';
182 $varyHeader[] = 'Cookie';
183 }
184
185 // Check if the file is hidden
186 if ( $img->isDeleted( File::DELETED_FILE ) ) {
187 wfThumbErrorText( 404, "The source file '$fileName' does not exist." );
188 return;
189 }
190
191 // Do rendering parameters extraction from thumbnail name.
192 if ( isset( $params['thumbName'] ) ) {
193 $params = wfExtractThumbParams( $img, $params );
194 }
195 if ( $params == null ) {
196 wfThumbError( 400, 'The specified thumbnail parameters are not recognized.' );
197 return;
198 }
199
200 // Check the source file storage path
201 if ( !$img->exists() ) {
202 $redirectedLocation = false;
203 if ( !$isTemp ) {
204 // Check for file redirect
205 // Since redirects are associated with pages, not versions of files,
206 // we look for the most current version to see if its a redirect.
207 $possRedirFile = $localRepo->findFile( $img->getName() );
208 if ( $possRedirFile && $possRedirFile->getRedirected() !== null ) {
209 $redirTarget = $possRedirFile->getName();
210 $targetFile = $localRepo->newFile( Title::makeTitleSafe( NS_FILE, $redirTarget ) );
211 if ( $targetFile->exists() ) {
212 $newThumbName = $targetFile->thumbName( $params );
213 if ( $isOld ) {
215 $newThumbUrl = $targetFile->getArchiveThumbUrl(
216 $bits[0] . '!' . $targetFile->getName(), $newThumbName );
217 } else {
218 $newThumbUrl = $targetFile->getThumbUrl( $newThumbName );
219 }
220 $redirectedLocation = wfExpandUrl( $newThumbUrl, PROTO_CURRENT );
221 }
222 }
223 }
224
225 if ( $redirectedLocation ) {
226 // File has been moved. Give redirect.
227 $response = RequestContext::getMain()->getRequest()->response();
228 $response->statusHeader( 302 );
229 $response->header( 'Location: ' . $redirectedLocation );
230 $response->header( 'Expires: ' .
231 gmdate( 'D, d M Y H:i:s', time() + 12 * 3600 ) . ' GMT' );
232 if ( $wgVaryOnXFP ) {
233 $varyHeader[] = 'X-Forwarded-Proto';
234 }
235 if ( count( $varyHeader ) ) {
236 $response->header( 'Vary: ' . implode( ', ', $varyHeader ) );
237 }
238 $response->header( 'Content-Length: 0' );
239 return;
240 }
241
242 // If its not a redirect that has a target as a local file, give 404.
243 wfThumbErrorText( 404, "The source file '$fileName' does not exist." );
244 return;
245 } elseif ( $img->getPath() === false ) {
246 wfThumbErrorText( 400, "The source file '$fileName' is not locally accessible." );
247 return;
248 }
249
250 // Check IMS against the source file
251 // This means that clients can keep a cached copy even after it has been deleted on the server
252 if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
253 // Fix IE brokenness
254 $imsString = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
255 // Calculate time
256 AtEase::suppressWarnings();
257 $imsUnix = strtotime( $imsString );
258 AtEase::restoreWarnings();
259 if ( wfTimestamp( TS_UNIX, $img->getTimestamp() ) <= $imsUnix ) {
260 HttpStatus::header( 304 );
261 return;
262 }
263 }
264
265 $rel404 = $params['rel404'] ?? null;
266 unset( $params['r'] ); // ignore 'r' because we unconditionally pass File::RENDER
267 unset( $params['f'] ); // We're done with 'f' parameter.
268 unset( $params['rel404'] ); // moved to $rel404
269
270 // Get the normalized thumbnail name from the parameters...
271 try {
272 $thumbName = $img->thumbName( $params );
273 if ( !strlen( $thumbName ) ) { // invalid params?
275 'Empty return from File::thumbName'
276 );
277 }
278 $thumbName2 = $img->thumbName( $params, File::THUMB_FULL_NAME ); // b/c; "long" style
281 400,
282 'The specified thumbnail parameters are not valid: ' . $e->getMessage()
283 );
284 return;
285 } catch ( MWException $e ) {
286 wfThumbError( 500, $e->getHTML(), 'Exception caught while extracting thumb name',
287 [ 'exception' => $e ] );
288 return;
289 }
290
291 // For 404 handled thumbnails, we only use the base name of the URI
292 // for the thumb params and the parent directory for the source file name.
293 // Check that the zone relative path matches up so CDN caches won't pick
294 // up thumbs that would not be purged on source file deletion (T36231).
295 if ( $rel404 !== null ) { // thumbnail was handled via 404
296 if ( rawurldecode( $rel404 ) === $img->getThumbRel( $thumbName ) ) {
297 // Request for the canonical thumbnail name
298 } elseif ( rawurldecode( $rel404 ) === $img->getThumbRel( $thumbName2 ) ) {
299 // Request for the "long" thumbnail name; redirect to canonical name
300 $response = RequestContext::getMain()->getRequest()->response();
301 $response->statusHeader( 301 );
302 $response->header( 'Location: ' .
303 wfExpandUrl( $img->getThumbUrl( $thumbName ), PROTO_CURRENT ) );
304 $response->header( 'Expires: ' .
305 gmdate( 'D, d M Y H:i:s', time() + 7 * 86400 ) . ' GMT' );
306 if ( $wgVaryOnXFP ) {
307 $varyHeader[] = 'X-Forwarded-Proto';
308 }
309 if ( count( $varyHeader ) ) {
310 $response->header( 'Vary: ' . implode( ', ', $varyHeader ) );
311 }
312 return;
313 } else {
314 wfThumbErrorText( 404, "The given path of the specified thumbnail is incorrect;
315 expected '" . $img->getThumbRel( $thumbName ) . "' but got '" .
316 rawurldecode( $rel404 ) . "'." );
317 return;
318 }
319 }
320
321 $dispositionType = isset( $params['download'] ) ? 'attachment' : 'inline';
322
323 // Suggest a good name for users downloading this thumbnail
324 $headers[] =
325 'Content-Disposition: ' . $img->getThumbDisposition( $thumbName, $dispositionType );
326
327 if ( count( $varyHeader ) ) {
328 $headers[] = 'Vary: ' . implode( ', ', $varyHeader );
329 }
330
331 // Stream the file if it exists already...
332 $thumbPath = $img->getThumbPath( $thumbName );
333 if ( $img->getRepo()->fileExists( $thumbPath ) ) {
334 $starttime = microtime( true );
335 $status = $img->getRepo()->streamFileWithStatus( $thumbPath, $headers );
336 $streamtime = microtime( true ) - $starttime;
337
338 if ( $status->isOK() ) {
339 MediaWikiServices::getInstance()->getStatsdDataFactory()->timing(
340 'media.thumbnail.stream', $streamtime
341 );
342 } else {
343 wfThumbError( 500, 'Could not stream the file', null, [ 'file' => $thumbName,
344 'path' => $thumbPath, 'error' => $status->getWikiText( false, false, 'en' ) ] );
345 }
346 return;
347 }
348
349 $user = RequestContext::getMain()->getUser();
350 if ( !wfThumbIsStandard( $img, $params ) && $user->pingLimiter( 'renderfile-nonstandard' ) ) {
351 wfThumbError( 429, wfMessage( 'actionthrottledtext' )->parse() );
352 return;
353 } elseif ( $user->pingLimiter( 'renderfile' ) ) {
354 wfThumbError( 429, wfMessage( 'actionthrottledtext' )->parse() );
355 return;
356 }
357
358 $thumbProxyUrl = $img->getRepo()->getThumbProxyUrl();
359
360 if ( strlen( $thumbProxyUrl ) ) {
361 wfProxyThumbnailRequest( $img, $thumbName );
362 // No local fallback when in proxy mode
363 return;
364 } else {
365 // Generate the thumbnail locally
366 list( $thumb, $errorMsg ) = wfGenerateThumbnail( $img, $params, $thumbName, $thumbPath );
367 }
368
371 // Check for thumbnail generation errors...
372 $msg = wfMessage( 'thumbnail_error' );
373 $errorCode = 500;
374
375 if ( !$thumb ) {
376 $errorMsg = $errorMsg ?: $msg->rawParams( 'File::transform() returned false' )->escaped();
377 if ( $errorMsg instanceof MessageSpecifier &&
378 $errorMsg->getKey() === 'thumbnail_image-failure-limit'
379 ) {
380 $errorCode = 429;
381 }
382 } elseif ( $thumb->isError() ) {
383 $errorMsg = $thumb->getHtmlMsg();
384 $errorCode = $thumb->getHttpStatusCode();
385 } elseif ( !$thumb->hasFile() ) {
386 $errorMsg = $msg->rawParams( 'No path supplied in thumbnail object' )->escaped();
387 } elseif ( $thumb->fileIsSource() ) {
388 $errorMsg = $msg
389 ->rawParams( 'Image was not scaled, is the requested width bigger than the source?' )
390 ->escaped();
391 $errorCode = 400;
392 }
393
394 if ( $errorMsg !== false ) {
395 wfThumbError( $errorCode, $errorMsg, null, [ 'file' => $thumbName, 'path' => $thumbPath ] );
396 } else {
397 // Stream the file if there were no errors
398 $status = $thumb->streamFileWithStatus( $headers );
399 if ( !$status->isOK() ) {
400 wfThumbError( 500, 'Could not stream the file', null, [
401 'file' => $thumbName, 'path' => $thumbPath,
402 'error' => $status->getWikiText( false, false, 'en' ) ] );
403 }
404 }
405}
406
413function wfProxyThumbnailRequest( $img, $thumbName ) {
414 $thumbProxyUrl = $img->getRepo()->getThumbProxyUrl();
415
416 // Instead of generating the thumbnail ourselves, we proxy the request to another service
417 $thumbProxiedUrl = $thumbProxyUrl . $img->getThumbRel( $thumbName );
418
419 $req = MWHttpRequest::factory( $thumbProxiedUrl );
420 $secret = $img->getRepo()->getThumbProxySecret();
421
422 // Pass a secret key shared with the proxied service if any
423 if ( strlen( $secret ) ) {
424 $req->setHeader( 'X-Swift-Secret', $secret );
425 }
426
427 // Send request to proxied service
428 $status = $req->execute();
429
430 MediaWiki\HeaderCallback::warnIfHeadersSent();
431
432 // Simply serve the response from the proxied service as-is
433 header( 'HTTP/1.1 ' . $req->getStatus() );
434
435 $headers = $req->getResponseHeaders();
436
437 foreach ( $headers as $key => $values ) {
438 foreach ( $values as $value ) {
439 header( $key . ': ' . $value, false );
440 }
441 }
442
443 echo $req->getContent();
444}
445
455function wfGenerateThumbnail( File $file, array $params, $thumbName, $thumbPath ) {
457
458 $cache = ObjectCache::getLocalClusterInstance();
459 $key = $cache->makeKey(
460 'attempt-failures',
462 $file->getRepo()->getName(),
463 $file->getSha1(),
464 md5( $thumbName )
465 );
466
467 // Check if this file keeps failing to render
468 if ( $cache->get( $key ) >= 4 ) {
469 return [ false, wfMessage( 'thumbnail_image-failure-limit', 4 ) ];
470 }
471
472 $done = false;
473 // Record failures on PHP fatals in addition to caching exceptions
474 register_shutdown_function( static function () use ( $cache, &$done, $key ) {
475 if ( !$done ) { // transform() gave a fatal
476 // Randomize TTL to reduce stampedes
477 $cache->incrWithInit( $key, $cache::TTL_HOUR + mt_rand( 0, 300 ) );
478 }
479 } );
480
481 $thumb = false;
482 $errorHtml = false;
483
484 // guard thumbnail rendering with PoolCounter to avoid stampedes
485 // expensive files use a separate PoolCounter config so it is possible
486 // to set up a global limit on them
487 if ( $file->isExpensiveToThumbnail() ) {
488 $poolCounterType = 'FileRenderExpensive';
489 } else {
490 $poolCounterType = 'FileRender';
491 }
492
493 // Thumbnail isn't already there, so create the new thumbnail...
494 try {
495 $work = new PoolCounterWorkViaCallback( $poolCounterType, sha1( $file->getName() ),
496 [
497 'doWork' => static function () use ( $file, $params ) {
498 return $file->transform( $params, File::RENDER_NOW );
499 },
500 'doCachedWork' => static function () use ( $file, $params, $thumbPath ) {
501 // If the worker that finished made this thumbnail then use it.
502 // Otherwise, it probably made a different thumbnail for this file.
503 return $file->getRepo()->fileExists( $thumbPath )
504 ? $file->transform( $params, File::RENDER_NOW )
505 : false; // retry once more in exclusive mode
506 },
507 'error' => static function ( Status $status ) {
508 return wfMessage( 'generic-pool-error' )->parse() . '<hr>' . $status->getHTML();
509 }
510 ]
511 );
512 $result = $work->execute();
513 if ( $result instanceof MediaTransformOutput ) {
514 $thumb = $result;
515 } elseif ( is_string( $result ) ) { // error
516 $errorHtml = $result;
517 }
518 } catch ( Exception $e ) {
519 // Tried to select a page on a non-paged file?
520 }
521
523 $done = true; // no PHP fatal occurred
524
525 if ( !$thumb || $thumb->isError() ) {
526 // Randomize TTL to reduce stampedes
527 $cache->incrWithInit( $key, $cache::TTL_HOUR + mt_rand( 0, 300 ) );
528 }
529
530 return [ $thumb, $errorHtml ];
531}
532
552function wfExtractThumbRequestInfo( $thumbRel ) {
553 $repo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
554
555 $hashDirReg = $subdirReg = '';
556 $hashLevels = $repo->getHashLevels();
557 for ( $i = 0; $i < $hashLevels; $i++ ) {
558 $subdirReg .= '[0-9a-f]';
559 $hashDirReg .= "$subdirReg/";
560 }
561
562 // Check if this is a thumbnail of an original in the local file repo
563 if ( preg_match( "!^((archive/)?$hashDirReg([^/]*)/([^/]*))$!", $thumbRel, $m ) ) {
564 list( /*all*/, $rel, $archOrTemp, $filename, $thumbname ) = $m;
565 // Check if this is a thumbnail of an temp file in the local file repo
566 } elseif ( preg_match( "!^(temp/)($hashDirReg([^/]*)/([^/]*))$!", $thumbRel, $m ) ) {
567 list( /*all*/, $archOrTemp, $rel, $filename, $thumbname ) = $m;
568 } else {
569 return null; // not a valid looking thumbnail request
570 }
571
572 $params = [ 'f' => $filename, 'rel404' => $rel ];
573 if ( $archOrTemp === 'archive/' ) {
574 $params['archived'] = 1;
575 } elseif ( $archOrTemp === 'temp/' ) {
576 $params['temp'] = 1;
577 }
578
579 $params['thumbName'] = $thumbname;
580 return $params;
581}
582
591function wfExtractThumbParams( $file, $params ) {
592 if ( !isset( $params['thumbName'] ) ) {
593 throw new InvalidArgumentException( "No thumbnail name passed to wfExtractThumbParams" );
594 }
595
596 $thumbname = $params['thumbName'];
597 unset( $params['thumbName'] );
598
599 // FIXME: Files in the temp zone don't set a MIME type, which means
600 // they don't have a handler. Which means we can't parse the param
601 // string. However, not a big issue as what good is a param string
602 // if you have no handler to make use of the param string and
603 // actually generate the thumbnail.
604 $handler = $file->getHandler();
605
606 // Based on UploadStash::parseKey
607 $fileNamePos = strrpos( $thumbname, $params['f'] );
608 if ( $fileNamePos === false ) {
609 // Maybe using a short filename? (see FileRepo::nameForThumb)
610 $fileNamePos = strrpos( $thumbname, 'thumbnail' );
611 }
612
613 if ( $handler && $fileNamePos !== false ) {
614 $paramString = substr( $thumbname, 0, $fileNamePos - 1 );
615 $extraParams = $handler->parseParamString( $paramString );
616 if ( $extraParams !== false ) {
617 return $params + $extraParams;
618 }
619 }
620
621 // As a last ditch fallback, use the traditional common parameters
622 if ( preg_match( '!^(page(\d*)-)*(\d*)px-[^/]*$!', $thumbname, $matches ) ) {
623 list( /* all */, /* pagefull */, $pagenum, $size ) = $matches;
624 $params['width'] = $size;
625 if ( $pagenum ) {
626 $params['page'] = $pagenum;
627 }
628 return $params; // valid thumbnail URL
629 }
630 return null;
631}
632
640function wfThumbErrorText( $status, $msgText ) {
641 wfThumbError( $status, htmlspecialchars( $msgText, ENT_NOQUOTES ) );
642}
643
654function wfThumbError( $status, $msgHtml, $msgText = null, $context = [] ) {
655 global $wgShowHostnames;
656
657 MediaWiki\HeaderCallback::warnIfHeadersSent();
658
659 if ( headers_sent() ) {
660 LoggerFactory::getInstance( 'thumbnail' )->error(
661 'Error after output had been started. Output may be corrupt or truncated. ' .
662 'Original error: ' . ( $msgText ?: $msgHtml ) . " (Status $status)",
663 $context
664 );
665 return;
666 }
667
668 header( 'Cache-Control: no-cache' );
669 header( 'Content-Type: text/html; charset=utf-8' );
670 if ( $status == 400 || $status == 404 || $status == 429 ) {
671 HttpStatus::header( $status );
672 } elseif ( $status == 403 ) {
673 HttpStatus::header( 403 );
674 header( 'Vary: Cookie' );
675 } else {
676 LoggerFactory::getInstance( 'thumbnail' )->error( $msgText ?: $msgHtml, $context );
677 HttpStatus::header( 500 );
678 }
679 if ( $wgShowHostnames ) {
680 header( 'X-MW-Thumbnail-Renderer: ' . wfHostname() );
681 $url = htmlspecialchars(
682 $_SERVER['REQUEST_URI'] ?? '',
683 ENT_NOQUOTES
684 );
685 $hostname = htmlspecialchars( wfHostname(), ENT_NOQUOTES );
686 $debug = "<!-- $url -->\n<!-- $hostname -->\n";
687 } else {
688 $debug = '';
689 }
690 $content = <<<EOT
691<!DOCTYPE html>
692<html><head>
693<meta charset="UTF-8" />
694<title>Error generating thumbnail</title>
695</head>
696<body>
697<h1>Error generating thumbnail</h1>
698<p>
699$msgHtml
700</p>
701$debug
702</body>
703</html>
704
705EOT;
706 header( 'Content-Length: ' . strlen( $content ) );
707 echo $content;
708}
const NS_FILE
Definition Defines.php:70
const PROTO_CURRENT
Definition Defines.php:198
wfThumbIsStandard(File $file, array $params)
Returns true if these thumbnail parameters match one that MediaWiki requests from file description pa...
wfHostname()
Get host name of the current machine, for use in error reporting.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
global $wgRequest
Definition Setup.php:377
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:67
MediaWiki exception.
getHTML()
Format an HTML message for the current exception object.
Basic media transform error class.
MediaWiki exception thrown by some methods when the transform parameter array is invalid.
Base class for the output of MediaHandler::doTransform() and File::transform().
PSR-3 logger instance factory.
Service locator for MediaWiki core services.
Convenience class for dealing with PoolCounters using callbacks.
execute( $skipcache=false)
Get the result of the work (whatever it is), or the result of the error() function.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
File without associated database record.
$wgShowHostnames
Config variable stub for the ShowHostnames setting, for use by phpdoc and IDEs.
$wgThumbPath
Config variable stub for the ThumbPath setting, for use by phpdoc and IDEs.
$wgVaryOnXFP
Config variable stub for the VaryOnXFP setting, for use by phpdoc and IDEs.
$wgAttemptFailureEpoch
Config variable stub for the AttemptFailureEpoch setting, for use by phpdoc and IDEs.
$wgTrivialMimeDetection
Config variable stub for the TrivialMimeDetection setting, for use by phpdoc and IDEs.
$mediawiki
Definition img_auth.php:48
getKey()
Returns the message key.
$debug
Definition mcc.php:31
$cache
Definition mcc.php:33
A helper class for throttling authentication attempts.
$content
Definition router.php:76
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42
wfThumbHandle404()
Handle a thumbnail request via thumbnail file URL.
Definition thumb.php:66
wfThumbError( $status, $msgHtml, $msgText=null, $context=[])
Output a thumbnail generation error message.
Definition thumb.php:654
wfStreamThumb(array $params)
Stream a thumbnail specified by parameters.
Definition thumb.php:105
wfGenerateThumbnail(File $file, array $params, $thumbName, $thumbPath)
Actually try to generate a new thumbnail.
Definition thumb.php:455
wfProxyThumbnailRequest( $img, $thumbName)
Proxies thumbnail request to a service that handles thumbnailing.
Definition thumb.php:413
wfExtractThumbRequestInfo( $thumbRel)
Convert pathinfo type parameter, into normal request parameters.
Definition thumb.php:552
wfThumbMain()
Definition thumb.php:43
wfThumbErrorText( $status, $msgText)
Output a thumbnail generation error message.
Definition thumb.php:640
wfExtractThumbParams( $file, $params)
Convert a thumbnail name (122px-foo.png) to parameters, using file handler.
Definition thumb.php:591