public function ProxySubscriber::checkFileOrigin in Stage File Proxy 8
Fetch the file from it's origin.
Parameters
\Symfony\Component\HttpKernel\Event\GetResponseEvent $event: The event to process.
File
- src/
EventSubscriber/ ProxySubscriber.php, line 86
Class
- ProxySubscriber
- Stage file proxy subscriber for controller requests.
Namespace
Drupal\stage_file_proxy\EventSubscriberCode
public function checkFileOrigin(GetResponseEvent $event) {
$config = $this->configFactory
->get('stage_file_proxy.settings');
// Get the origin server.
$server = $config
->get('origin');
// Quit if no origin given.
if (!$server) {
return;
}
// Quit if we are the origin, ignore http(s).
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;
}
// Disallow directory traversal.
if (in_array('..', explode('/', $request_path))) {
return;
}
// Moving to parent directory is insane here, so prevent that.
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;
}
}
// Note if the origin server files location is different. This
// must be the exact path for the remote site's public file
// system path, and defaults to the local public file system path.
$remote_file_dir = trim($config
->get('origin_dir'));
if (!$remote_file_dir) {
$remote_file_dir = $file_dir;
}
$request_path = rawurldecode($request_path);
// Path relative to file directory. Used for hotlinking.
$relative_path = mb_substr($request_path, mb_strlen($file_dir) + 1);
// If file is fetched and use_imagecache_root is set, original is used.
$paths = [
$relative_path,
];
// Webp support.
$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;
// Is this imagecache? Request the root file and let imagecache resize.
// We check this first so locally added files have precedence.
$original_path = $this->manager
->styleOriginalPath($relative_path, TRUE);
if ($original_path && !$is_webp) {
if (file_exists($original_path)) {
// Imagecache can generate it without our help.
return;
}
if ($config
->get('use_imagecache_root')) {
// Config says: Fetch the original.
$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)) {
// Refresh this request & let the web server work out mime type, etc.
$location = Url::fromUri('base://' . $request_path, [
'query' => $query_parameters,
'absolute' => TRUE,
])
->toString();
// Avoid redirection caching in upstream proxies.
header("Cache-Control: must-revalidate, no-cache, post-check=0, pre-check=0, private");
}
if (isset($location)) {
header("Location: {$location}");
exit;
}
}
}