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