View source
<?php
namespace Drupal\stage_file_proxy\EventSubscriber;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\Core\Url;
use Drupal\stage_file_proxy\EventDispatcher\AlterExcludedPathsEvent;
use Drupal\stage_file_proxy\FetchManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class ProxySubscriber implements EventSubscriberInterface {
protected $manager;
protected $logger;
protected $eventDispatcher;
protected $configFactory;
protected $requestStack;
public function __construct(FetchManagerInterface $manager, LoggerInterface $logger, EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory, RequestStack $request_stack) {
$this->manager = $manager;
$this->logger = $logger;
$this->eventDispatcher = $event_dispatcher;
$this->configFactory = $config_factory;
$this->requestStack = $request_stack;
}
public function checkFileOrigin(GetResponseEvent $event) {
$config = $this->configFactory
->get('stage_file_proxy.settings');
$server = $config
->get('origin');
if (!$server) {
return;
}
if (preg_replace('#^[a-z]*://#u', '', $server) === $event
->getRequest()
->getHost()) {
return;
}
$file_dir = $this->manager
->filePublicPath();
$request_path = $event
->getRequest()
->getPathInfo();
$request_path = mb_substr($request_path, 1);
if (strpos($request_path, '' . $file_dir) !== 0) {
return;
}
if (in_array('..', explode('/', $request_path))) {
return;
}
if (in_array('..', explode('/', $request_path))) {
return;
}
$alter_excluded_paths_event = new AlterExcludedPathsEvent([]);
$this->eventDispatcher
->dispatch('stage_file_proxy.alter_excluded_paths', $alter_excluded_paths_event);
$excluded_paths = $alter_excluded_paths_event
->getExcludedPaths();
foreach ($excluded_paths as $excluded_path) {
if (strpos($request_path, $excluded_path) !== FALSE) {
return;
}
}
$remote_file_dir = trim($config
->get('origin_dir'));
if (!$remote_file_dir) {
$remote_file_dir = $file_dir;
}
$request_path = rawurldecode($request_path);
$relative_path = mb_substr($request_path, mb_strlen($file_dir) + 1);
$paths = [
$relative_path,
];
$is_webp = FALSE;
if (strpos($relative_path, '.webp')) {
$paths[] = str_replace('.webp', '', $relative_path);
$is_webp = TRUE;
}
foreach ($paths as $relative_path) {
$fetch_path = $relative_path;
$original_path = $this->manager
->styleOriginalPath($relative_path, TRUE);
if ($original_path && !$is_webp) {
if (file_exists($original_path)) {
return;
}
if ($config
->get('use_imagecache_root')) {
$fetch_path = StreamWrapperManager::getTarget($original_path);
}
}
$query = $this->requestStack
->getCurrentRequest()->query
->all();
$query_parameters = UrlHelper::filterQueryParameters($query);
$options = [
'verify' => $config
->get('verify'),
];
if ($config
->get('hotlink')) {
$location = Url::fromUri("{$server}/{$remote_file_dir}/{$relative_path}", [
'query' => $query_parameters,
'absolute' => TRUE,
])
->toString();
}
elseif ($this->manager
->fetch($server, $remote_file_dir, $fetch_path, $options)) {
$location = Url::fromUri('base://' . $request_path, [
'query' => $query_parameters,
'absolute' => TRUE,
])
->toString();
header("Cache-Control: must-revalidate, no-cache, post-check=0, pre-check=0, private");
}
if (isset($location)) {
header("Location: {$location}");
exit;
}
}
}
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = [
'checkFileOrigin',
240,
];
return $events;
}
}