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