<commit_before><?php
namespace wcf\action;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\Psr7\Request;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\SystemException;
use wcf\system\io\File;
use wcf\system\io\HttpFactory;
use wcf\system\WCF;
use wcf\util\exception\CryptoException;
use wcf\util\CryptoUtil;
use wcf\util\FileUtil;
use wcf\util\HeaderUtil;
use wcf\util\StringUtil;

/**
 * Proxies requests for embedded images.
 * 
 * @author	<NAME>
 * @copyright	2001-2019 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @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,
						]);
						$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';<commit_msg>Stream the response in ImageProxyAction<commit_after><?php
namespace wcf\action;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\Psr7\Request;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\SystemException;
use wcf\system\io\File;
use wcf\system\io\HttpFactory;
use wcf\system\WCF;
use wcf\util\exception\CryptoException;
use wcf\util\CryptoUtil;
use wcf\util\FileUtil;
use wcf\util\HeaderUtil;
use wcf\util\StringUtil;

/**
 * Proxies requests for embedded images.
 * 
 * @author	<NAME>
 * @copyright	2001-2019 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @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';
{'fraction_non_alphanumeric': 0.1738933373621393, 'fraction_numerical': 0.009971294757516241, 'mean_word_length': 2.8421358096343585, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2651245', 'n_tokens_mistral': 2833, 'n_tokens_neox': 2137, 'n_words': 447}