1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2022 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Http\RequestHandlers; 21 22use Fig\Http\Message\StatusCodeInterface; 23use Fisharebest\Webtrees\Registry; 24use Fisharebest\Webtrees\Validator; 25use Psr\Http\Message\ResponseInterface; 26use Psr\Http\Message\ServerRequestInterface; 27use Psr\Http\Server\RequestHandlerInterface; 28 29use function redirect; 30 31/** 32 * Create a thumbnail of a media file. 33 */ 34class MediaFileThumbnail implements RequestHandlerInterface 35{ 36 /** 37 * Show an image/thumbnail, with/without a watermark. 38 * 39 * @param ServerRequestInterface $request 40 * 41 * @return ResponseInterface 42 */ 43 public function handle(ServerRequestInterface $request): ResponseInterface 44 { 45 $tree = Validator::attributes($request)->tree(); 46 $user = Validator::attributes($request)->user(); 47 48 $params = $request->getQueryParams(); 49 $xref = Validator::queryParams($request)->isXref()->string('xref'); 50 $fact_id = Validator::queryParams($request)->string('fact_id'); 51 $media = Registry::mediaFactory()->make($xref, $tree); 52 53 if ($media === null) { 54 return Registry::imageFactory()->replacementImageResponse((string) StatusCodeInterface::STATUS_NOT_FOUND); 55 } 56 57 if (!$media->canShow()) { 58 return Registry::imageFactory()->replacementImageResponse((string) StatusCodeInterface::STATUS_FORBIDDEN); 59 } 60 61 foreach ($media->mediaFiles() as $media_file) { 62 if ($media_file->factId() === $fact_id) { 63 if ($media_file->isExternal()) { 64 return redirect($media_file->filename()); 65 } 66 67 // Validate HTTP signature 68 unset($params['route']); 69 $params['tree'] = $media_file->media()->tree()->name(); 70 71 if ($media_file->signature($params) !== $params['s']) { 72 return Registry::imageFactory()->replacementImageResponse((string) StatusCodeInterface::STATUS_FORBIDDEN) 73 ->withHeader('x-signature-exception', 'Signature mismatch'); 74 } 75 76 $image_factory = Registry::imageFactory(); 77 78 $response = $image_factory->mediaFileThumbnailResponse( 79 $media_file, 80 (int) $params['w'], 81 (int) $params['h'], 82 $params['fit'], 83 $image_factory->fileNeedsWatermark($media_file, $user) 84 ); 85 86 return $response->withHeader('cache-control', 'public,max-age=31536000'); 87 } 88 } 89 90 return Registry::imageFactory()->replacementImageResponse((string) StatusCodeInterface::STATUS_NOT_FOUND); 91 } 92} 93