From: Tim Düsterhus Date: Tue, 16 Feb 2021 08:29:57 +0000 (+0100) Subject: Merge branch '5.3' X-Git-Tag: 5.4.0_Alpha_1~268^2~1 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=6824cd740c74bcefad73f0fb588d619f02f18f13;p=GitHub%2FWoltLab%2FWCF.git Merge branch '5.3' --- 6824cd740c74bcefad73f0fb588d619f02f18f13 diff --cc wcfsetup/install/files/lib/action/ImageProxyAction.class.php index 5b59751373,084c6ce318..a86b4fa88b --- a/wcfsetup/install/files/lib/action/ImageProxyAction.class.php +++ b/wcfsetup/install/files/lib/action/ImageProxyAction.class.php @@@ -1,9 -1,7 +1,10 @@@ - * @package WoltLabSuite\Core\Action - * @since 3.0 + * + * @author Matthias Schmidt + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @package WoltLabSuite\Core\Action + * @since 3.0 */ -class ImageProxyAction extends AbstractAction { - /** - * @inheritDoc - */ - public $neededModules = ['MODULE_IMAGE_PROXY']; - - /** - * The image key created by CryptoUtil::createSignedString() - * @var string - */ - public $key = ''; - - /** - * 10 Mebibyte - */ - const MAX_SIZE = (10 * (1 << 20)); - - /** - * @inheritDoc - */ - public function readParameters() { - parent::readParameters(); - - if (isset($_REQUEST['key'])) $this->key = StringUtil::trim($_REQUEST['key']); - } - - /** - * @inheritDoc - */ - public function execute() { - parent::execute(); - - if (isset($_SERVER['HTTP_VIA']) && strpos($_SERVER['HTTP_VIA'], 'wsc') !== false) throw new IllegalLinkException(); - - try { - $url = CryptoUtil::getValueFromSignedString($this->key); - if ($url === null) throw new IllegalLinkException(); - - $fileName = sha1($this->key); - $dir = WCF_DIR.'images/proxy/'.substr($fileName, 0, 2); - - // ensure that the directory exists - if (!file_exists($dir)) { - FileUtil::makePath($dir); - } - - // check whether we already downloaded the image - $fileLocation = null; - foreach (['png','jpg','gif'] as $extension) { - if (is_file($dir.'/'.$fileName.'.'.$extension)) { - $fileLocation = $dir.'/'.$fileName.'.'.$extension; - break; - } - } - - if ($fileLocation === null) { - $tmp = FileUtil::getTemporaryFilename('image_proxy_'); - - try { - // rewrite schemaless URLs to https - $scheme = parse_url($url, PHP_URL_SCHEME); - if (!$scheme) { - if (StringUtil::startsWith($url, '//')) { - $url = 'https:'.$url; - } - else { - throw new \DomainException(); - } - } - - // download image - try { - $client = HttpFactory::makeClient([ - 'timeout' => 10, - 'stream' => true, - ]); - $request = new Request('GET', $url, [ - 'via' => '1.1 wsc', - 'accept' => 'image/*', - 'range' => 'bytes=0-'.(self::MAX_SIZE - 1), - ]); - $response = $client->send($request); - - $file = new File($tmp); - while (!$response->getBody()->eof()) { - $file->write($response->getBody()->read(8192)); - - if ($response->getBody()->tell() >= self::MAX_SIZE) { - break; - } - } - $response->getBody()->close(); - $file->flush(); - $file->close(); - } - catch (TransferException $e) { - throw new \DomainException('Failed to request', 0, $e); - } - - // check file type - $imageData = @getimagesize($tmp); - if (!$imageData) throw new \DomainException(); - - switch ($imageData[2]) { - case IMAGETYPE_PNG: - $extension = 'png'; - break; - case IMAGETYPE_GIF: - $extension = 'gif'; - break; - case IMAGETYPE_JPEG: - $extension = 'jpg'; - break; - default: - throw new \DomainException(); - } - } - catch (\DomainException $e) { - // save a dummy image in case the server sent us junk, otherwise we might try to download the file over and over and over again. - // taken from the public domain gif at https://commons.wikimedia.org/wiki/File%3aBlank.gif - file_put_contents($tmp, "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xFF\xFF\xFF\x00\x00\x00\x21\xF9\x04\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B"); - $extension = 'gif'; - } - - $fileLocation = $dir.'/'.$fileName.'.'.$extension; - - rename($tmp, $fileLocation); - - // update mtime for correct expiration calculation - @touch($fileLocation); - } - - $path = FileUtil::getRelativePath(WCF_DIR, dirname($fileLocation)).basename($fileLocation); - - $this->executed(); - - HeaderUtil::redirect(WCF::getPath().$path, true, false); - exit; - } - catch (SystemException $e) { - \wcf\functions\exception\logThrowable($e); - throw new IllegalLinkException(); - } - catch (CryptoException $e) { - \wcf\functions\exception\logThrowable($e); - throw new IllegalLinkException(); - } - } +class ImageProxyAction extends AbstractAction +{ + /** + * @inheritDoc + */ + public $neededModules = ['MODULE_IMAGE_PROXY']; + + /** + * The image key created by CryptoUtil::createSignedString() + * @var string + */ + public $key = ''; + + /** + * 10 Mebibyte + */ + const MAX_SIZE = (10 * (1 << 20)); + + /** + * @inheritDoc + */ + public function readParameters() + { + parent::readParameters(); + + if (isset($_REQUEST['key'])) { + $this->key = StringUtil::trim($_REQUEST['key']); + } + } + + /** + * @inheritDoc + */ + public function execute() + { + parent::execute(); + + if (isset($_SERVER['HTTP_VIA']) && \strpos($_SERVER['HTTP_VIA'], 'wsc') !== false) { + throw new IllegalLinkException(); + } + + try { + $url = CryptoUtil::getValueFromSignedString($this->key); + if ($url === null) { + throw new IllegalLinkException(); + } + + $fileName = \sha1($this->key); + $dir = WCF_DIR . 'images/proxy/' . \substr($fileName, 0, 2); + + // ensure that the directory exists + if (!\file_exists($dir)) { + FileUtil::makePath($dir); + } + + // check whether we already downloaded the image + $fileLocation = null; + foreach (['png', 'jpg', 'gif'] as $extension) { + if (\is_file($dir . '/' . $fileName . '.' . $extension)) { + $fileLocation = $dir . '/' . $fileName . '.' . $extension; + break; + } + } + + if ($fileLocation === null) { + $tmp = FileUtil::getTemporaryFilename('image_proxy_'); + + try { + // rewrite schemaless URLs to https + $scheme = \parse_url($url, \PHP_URL_SCHEME); + if (!$scheme) { + if (StringUtil::startsWith($url, '//')) { + $url = 'https:' . $url; + } else { + throw new \DomainException(); + } + } + + // download image + try { - $client = HttpFactory::makeClientWithTimeout(10); ++ $client = HttpFactory::makeClient([ ++ RequestOptions::TIMEOUT => 10, ++ RequestOptions::STREAM => true, ++ ]); + $request = new Request('GET', $url, [ + 'via' => '1.1 wsc', + 'accept' => 'image/*', + 'range' => 'bytes=0-' . (self::MAX_SIZE - 1), + ]); + $response = $client->send($request); + + $file = new File($tmp); + while (!$response->getBody()->eof()) { + $file->write($response->getBody()->read(8192)); + + if ($response->getBody()->tell() >= self::MAX_SIZE) { + break; + } + } + $response->getBody()->close(); + $file->flush(); + $file->close(); + } catch (TransferException $e) { + throw new \DomainException('Failed to request', 0, $e); + } + + // check file type + $imageData = @\getimagesize($tmp); + if (!$imageData) { + throw new \DomainException(); + } + + switch ($imageData[2]) { + case \IMAGETYPE_PNG: + $extension = 'png'; + break; + case \IMAGETYPE_GIF: + $extension = 'gif'; + break; + case \IMAGETYPE_JPEG: + $extension = 'jpg'; + break; + default: + throw new \DomainException(); + } + } catch (\DomainException $e) { + // save a dummy image in case the server sent us junk, otherwise we might try to download the file over and over and over again. + // taken from the public domain gif at https://commons.wikimedia.org/wiki/File%3aBlank.gif + \file_put_contents( + $tmp, + "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xFF\xFF\xFF\x00\x00\x00\x21\xF9\x04\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3B" + ); + $extension = 'gif'; + } + + $fileLocation = $dir . '/' . $fileName . '.' . $extension; + + \rename($tmp, $fileLocation); + + // update mtime for correct expiration calculation + @\touch($fileLocation); + } + + $path = FileUtil::getRelativePath(WCF_DIR, \dirname($fileLocation)) . \basename($fileLocation); + + $this->executed(); + + HeaderUtil::redirect(WCF::getPath() . $path, true, false); + + exit; + } catch (SystemException $e) { + \wcf\functions\exception\logThrowable($e); + throw new IllegalLinkException(); + } catch (CryptoException $e) { + \wcf\functions\exception\logThrowable($e); + throw new IllegalLinkException(); + } + } }