+/**
+ * Convert pathinfo type parameter, into normal request parameters
+ *
+ * So for example, if the request was redirected from
+ * /w/images/thumb/a/ab/Foo.png/120px-Foo.png. The $thumbRel parameter
+ * of this function would be set to "a/ab/Foo.png/120px-Foo.png".
+ * This method is responsible for turning that into an array
+ * with the folowing keys:
+ * * f => the filename (Foo.png)
+ * * rel404 => the whole thing (a/ab/Foo.png/120px-Foo.png)
+ * * archived => 1 (If the request is for an archived thumb)
+ * * temp => 1 (If the file is in the "temporary" zone)
+ * * thumbName => the thumbnail name, including parameters (120px-Foo.png)
+ *
+ * Transform specific parameters are set later via wfExtractThumbParams().
+ *
+ * @param string $thumbRel Thumbnail path relative to the thumb zone
+ * @return array|null Associative params array or null
+ */
+function wfExtractThumbRequestInfo( $thumbRel ) {
+ $repo = RepoGroup::singleton()->getLocalRepo();
+
+ $hashDirReg = $subdirReg = '';
+ $hashLevels = $repo->getHashLevels();
+ for ( $i = 0; $i < $hashLevels; $i++ ) {
+ $subdirReg .= '[0-9a-f]';
+ $hashDirReg .= "$subdirReg/";
+ }
+
+ // Check if this is a thumbnail of an original in the local file repo
+ if ( preg_match( "!^((archive/)?$hashDirReg([^/]*)/([^/]*))$!", $thumbRel, $m ) ) {
+ list( /*all*/, $rel, $archOrTemp, $filename, $thumbname ) = $m;
+ // Check if this is a thumbnail of an temp file in the local file repo
+ } elseif ( preg_match( "!^(temp/)($hashDirReg([^/]*)/([^/]*))$!", $thumbRel, $m ) ) {
+ list( /*all*/, $archOrTemp, $rel, $filename, $thumbname ) = $m;
+ } else {
+ return null; // not a valid looking thumbnail request
+ }
+
+ $params = [ 'f' => $filename, 'rel404' => $rel ];
+ if ( $archOrTemp === 'archive/' ) {
+ $params['archived'] = 1;
+ } elseif ( $archOrTemp === 'temp/' ) {
+ $params['temp'] = 1;
+ }
+
+ $params['thumbName'] = $thumbname;
+ return $params;
+}
+
+/**
+ * Convert a thumbnail name (122px-foo.png) to parameters, using
+ * file handler.
+ *
+ * @param File $file File object for file in question
+ * @param array $params Array of parameters so far
+ * @return array Parameters array with more parameters
+ */
+function wfExtractThumbParams( $file, $params ) {
+ if ( !isset( $params['thumbName'] ) ) {
+ throw new InvalidArgumentException( "No thumbnail name passed to wfExtractThumbParams" );
+ }
+
+ $thumbname = $params['thumbName'];
+ unset( $params['thumbName'] );
+
+ // FIXME: Files in the temp zone don't set a MIME type, which means
+ // they don't have a handler. Which means we can't parse the param
+ // string. However, not a big issue as what good is a param string
+ // if you have no handler to make use of the param string and
+ // actually generate the thumbnail.
+ $handler = $file->getHandler();
+
+ // Based on UploadStash::parseKey
+ $fileNamePos = strrpos( $thumbname, $params['f'] );
+ if ( $fileNamePos === false ) {
+ // Maybe using a short filename? (see FileRepo::nameForThumb)
+ $fileNamePos = strrpos( $thumbname, 'thumbnail' );
+ }
+
+ if ( $handler && $fileNamePos !== false ) {
+ $paramString = substr( $thumbname, 0, $fileNamePos - 1 );
+ $extraParams = $handler->parseParamString( $paramString );
+ if ( $extraParams !== false ) {
+ return $params + $extraParams;
+ }
+ }
+
+ // As a last ditch fallback, use the traditional common parameters
+ if ( preg_match( '!^(page(\d*)-)*(\d*)px-[^/]*$!', $thumbname, $matches ) ) {
+ list( /* all */, /* pagefull */, $pagenum, $size ) = $matches;
+ $params['width'] = $size;
+ if ( $pagenum ) {
+ $params['page'] = $pagenum;
+ }
+ return $params; // valid thumbnail URL
+ }
+ return null;
+}
+
+/**
+ * Output a thumbnail generation error message
+ *
+ * @param int $status
+ * @param string $msgText Plain text (will be html escaped)
+ * @return void
+ */
+function wfThumbErrorText( $status, $msgText ) {
+ wfThumbError( $status, htmlspecialchars( $msgText ) );
+}
+
+/**
+ * Output a thumbnail generation error message
+ *
+ * @param int $status
+ * @param string $msgHtml HTML
+ * @param string $msgText Short error description, for internal logging. Defaults to $msgHtml.
+ * Only used for HTTP 500 errors.
+ * @param array $context Error context, for internal logging. Only used for HTTP 500 errors.
+ * @return void
+ */
+function wfThumbError( $status, $msgHtml, $msgText = null, $context = [] ) {