View source
<?php
namespace Drupal\fast404;
use Drupal\Core\Site\Settings;
use Drupal\Core\Database\Database;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Component\Render\FormattableMarkup;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
class Fast404 {
use StringTranslationTrait;
public $respond404 = FALSE;
public $request;
public $loadHtml = TRUE;
public function __construct(Request $request) {
$this->request = $request;
}
public function extensionCheck() {
$path = $this->request
->getPathInfo();
if (!isset($path) || $path == '/') {
return;
}
if (strpos($path, 'styles/')) {
if (!Settings::get('fast404_allow_anon_imagecache', TRUE)) {
$cookies = $this->request->cookies
->all();
if (isset($cookies) && is_array($cookies)) {
foreach ($cookies as $cookie) {
if (stristr($cookie, 'SESS')) {
return;
}
}
}
}
else {
return;
}
}
if (Settings::get('fast404_url_whitelisting', FALSE)) {
$trimmed_path = ltrim($path, '/');
$allowed = Settings::get('fast404_whitelist', []);
if (in_array($trimmed_path, $allowed)) {
return TRUE;
}
}
$string_whitelist = Settings::get('fast404_string_whitelisting', FALSE);
if (is_array($string_whitelist)) {
foreach ($string_whitelist as $str) {
if (strstr($path, $str) !== FALSE) {
return;
}
}
}
$extensions = Settings::get('fast404_exts', '/^(?!robots).*\\.(txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i');
if (isset($extensions) && preg_match($extensions, $path, $m)) {
$this->loadHtml = FALSE;
$this
->blockPath();
return;
}
}
public function pathCheck() {
if (!Settings::get('fast404_path_check', FALSE)) {
return;
}
$path = $this->request
->getPathInfo();
if (!isset($path) || $path == '/') {
return;
}
$sql = "SELECT pattern_outline FROM {router} WHERE :path LIKE CONCAT(pattern_outline, '%') AND pattern_outline != '/'";
$result = Database::getConnection()
->query($sql, [
':path' => $path,
])
->fetchField();
if ($result) {
return;
}
$path_noslash = rtrim($path, '/');
$sql = "SELECT pid FROM {url_alias} WHERE alias = :alias";
$result = Database::getConnection()
->query($sql, [
':alias' => $path_noslash,
])
->fetchField();
if ($result) {
return;
}
$this
->blockPath();
}
public function blockPath() {
$this->respond404 = TRUE;
}
public function isPathBlocked() {
if ($this
->isCli()) {
return FALSE;
}
return $this->respond404;
}
public function response($return = FALSE) {
$message = Settings::get('fast404_html', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>');
$return_gone = Settings::get('fast404_return_gone', FALSE);
$custom_404_path = Settings::get('fast404_HTML_error_page', FALSE);
if ($return_gone) {
header((Settings::get('fast404_HTTP_status_method', 'mod_php') == 'FastCGI' ? 'Status:' : 'HTTP/1.0') . ' 410 Gone');
}
else {
header((Settings::get('fast404_HTTP_status_method', 'mod_php') == 'FastCGI' ? 'Status:' : 'HTTP/1.0') . ' 404 Not Found');
}
if (($this->loadHtml || Settings::get('fast404_HTML_error_all_paths', FALSE) === TRUE) && file_exists($custom_404_path)) {
$message = @file_get_contents($custom_404_path, FALSE);
}
$response = new Response(new FormattableMarkup($message, [
'@path' => $this->request
->getPathInfo(),
]), 404);
if ($return) {
return $response;
}
else {
$response
->send();
throw new ServiceUnavailableHttpException(3, $this
->t('The requested URL "@path" was not found on this server. Try again shortly.', [
'@path' => $this->request
->getPathInfo(),
]));
}
}
protected function isCli() {
return PHP_SAPI === 'cli';
}
}