forked from GithubBackups/vichan
Merge pull request #933 from Zankaria/dep-inj-dns-2
Dependecy injected DNS
This commit is contained in:
commit
2a9f47105d
21
inc/Data/Driver/Dns/DnsDriver.php
Normal file
21
inc/Data/Driver/Dns/DnsDriver.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace Vichan\Data\Driver\Dns;
|
||||
|
||||
|
||||
interface DnsDriver {
|
||||
/**
|
||||
* Resolve a domain name to 1 or more ips.
|
||||
*
|
||||
* @param string $name Domain name.
|
||||
* @return ?array Returns an array of IPv4 and IPv6 addresses or null on error.
|
||||
*/
|
||||
public function nameToIPs(string $name): ?array;
|
||||
|
||||
/**
|
||||
* Resolve an ip address to a domain name.
|
||||
*
|
||||
* @param string $ip Ip address.
|
||||
* @return ?array Returns the domain names or null on error.
|
||||
*/
|
||||
public function IPToNames(string $ip): ?array;
|
||||
}
|
43
inc/Data/Driver/Dns/HostDnsDriver.php
Normal file
43
inc/Data/Driver/Dns/HostDnsDriver.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace Vichan\Data\Driver\Dns;
|
||||
|
||||
|
||||
/**
|
||||
* Relies on the `host` command line executable.
|
||||
*/
|
||||
class HostDnsDriver implements DnsDriver {
|
||||
private int $timeout;
|
||||
|
||||
private static function matchOrEmpty(string $pattern, string $subject): array {
|
||||
$ret = \preg_match_all($pattern, $subject, $out);
|
||||
if ($ret === false || $ret === 0) {
|
||||
return [];
|
||||
}
|
||||
return $out[1];
|
||||
}
|
||||
|
||||
public function __construct(int $timeout) {
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
public function nameToIPs(string $name): ?array {
|
||||
$ret = shell_exec_error("host -W {$this->timeout} {$name}");
|
||||
if ($ret === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ipv4 = self::matchOrEmpty('/has address ([^\s]+)/', $ret);
|
||||
$ipv6 = self::matchOrEmpty('/has IPv6 address ([^\s]+)/', $ret);
|
||||
return \array_merge($ipv4, $ipv6);
|
||||
}
|
||||
|
||||
public function IPToNames(string $ip): ?array {
|
||||
$ret = shell_exec_error("host -W {$this->timeout} {$ip}");
|
||||
if ($ret === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$names = self::matchOrEmpty('/domain name pointer ([^\s]+)\./', $ret);
|
||||
return \array_map(fn($n) => \strtolower(\rtrim($n, '.')), $names);
|
||||
}
|
||||
}
|
50
inc/Data/Driver/Dns/LibcDnsDriver.php
Normal file
50
inc/Data/Driver/Dns/LibcDnsDriver.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace Vichan\Data\Driver\Dns;
|
||||
|
||||
|
||||
/**
|
||||
* For the love of god never use this implementation if you can.
|
||||
*/
|
||||
class LibcDnsDriver implements DnsDriver {
|
||||
public function __construct(int $timeout) {
|
||||
// Try to impose a very frail timeout https://www.php.net/manual/en/function.gethostbyname.php#118841
|
||||
\putenv("RES_OPTIONS=retrans:1 retry:1 timeout:{$timeout} attempts:1");
|
||||
}
|
||||
|
||||
public function nameToIPs(string $name): ?array {
|
||||
$ret = \dns_get_record($name, DNS_A | DNS_AAAA);
|
||||
if ($ret === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ips = [];
|
||||
foreach ($ret as $dns_record) {
|
||||
if ($dns_record['type'] == 'A') {
|
||||
$ips[] = $dns_record['ip'];
|
||||
} elseif ($dns_record['type'] == 'AAAA') {
|
||||
$ips[] = $dns_record['ipv6'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($ips)) {
|
||||
return [];
|
||||
} else {
|
||||
// Stable return order.
|
||||
\sort($ips, \SORT_STRING);
|
||||
return $ips;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the love of god never use this.
|
||||
* https://www.php.net/manual/en/function.gethostbyaddr.php#57553
|
||||
*/
|
||||
public function IPToNames(string $ip): ?array {
|
||||
$ret = \gethostbyaddr($ip);
|
||||
if ($ret === $ip || $ret === false) {
|
||||
return null;
|
||||
}
|
||||
// Case extravaganza: https://www.php.net/manual/en/function.gethostbyaddr.php#123563
|
||||
return [ \strtolower($ret) ];
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace Vichan\Service;
|
||||
|
||||
use Throwable;
|
||||
use Vichan\Data\Driver\Dns\DnsDriver;
|
||||
use Vichan\Data\Driver\LogDriver;
|
||||
|
||||
/**
|
||||
@ -24,6 +25,11 @@ class FilterService {
|
||||
*/
|
||||
private LogDriver $logger;
|
||||
|
||||
/**
|
||||
* @var DnsDriver Dns driver for reverse DNS lookup.
|
||||
*/
|
||||
private DnsDriver $dns_resolver;
|
||||
|
||||
|
||||
/**
|
||||
* Filter service constructor
|
||||
@ -31,11 +37,13 @@ class FilterService {
|
||||
* @param array<int, array<string, mixed>> $filters The config filters.
|
||||
* @param FloodService $floodService The FloodService.
|
||||
* @param LogDriver $logger The LogDriver.
|
||||
* @param DnsDriver $dns_resolver DnsResolver for hostname matching.
|
||||
*/
|
||||
public function __construct(array $filters, FloodService $floodService, LogDriver $logger) {
|
||||
public function __construct(array $filters, FloodService $floodService, LogDriver $logger, DnsDriver $dns_resolver) {
|
||||
$this->filters = $filters;
|
||||
$this->floodService = $floodService;
|
||||
$this->logger = $logger;
|
||||
$this->dns_resolver = $dns_resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,13 +268,17 @@ class FilterService {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hostname = \rDNS($post['ip']);
|
||||
if ($hostname === $post['ip']) {
|
||||
$this->logger->log(LogDriver::WARNING, "RDNS lookup failed for IP: {$post['ip']}");
|
||||
$hostnames = $this->dns_resolver->IPToNames($post['ip']);
|
||||
if ($hostnames === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->checkRegex($value, $hostname, 'RDNS');
|
||||
foreach ($hostnames as $name) {
|
||||
if ($this->checkRegex($value, $name, 'RDNS')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case 'agent':
|
||||
$this->validateType($value, 'array', 'Agent condition list');
|
||||
return $this->matchAgentCondition($value);
|
||||
|
215
inc/Service/IpBlacklistService.php
Normal file
215
inc/Service/IpBlacklistService.php
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
namespace Vichan\Service;
|
||||
|
||||
use Vichan\Data\Driver\CacheDriver;
|
||||
use Vichan\Data\Driver\Dns\DnsDriver;
|
||||
use Lifo\IP\IP;
|
||||
|
||||
|
||||
class IpBlacklistService {
|
||||
private const DNS_CACHE_TIMEOUT = 3600; // 1 hour.
|
||||
|
||||
private DnsDriver $resolver;
|
||||
private CacheDriver $cache;
|
||||
private array $blacklist_providers;
|
||||
private array $exceptions;
|
||||
private bool $rdns_validate;
|
||||
|
||||
|
||||
private static function buildDnsCacheKey(string $host) {
|
||||
return 'dns_queries_dns_' . \strtolower($host);
|
||||
}
|
||||
|
||||
private static function buildRDnsCacheKey(string $ip) {
|
||||
return "dns_queries_rdns_$ip";
|
||||
}
|
||||
|
||||
private static function reverseIpv4Octets(string $ip): ?string {
|
||||
$ret = \filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4);
|
||||
if ($ret === false) {
|
||||
return null;
|
||||
}
|
||||
return \implode('.', \array_reverse(\explode('.', $ip)));
|
||||
}
|
||||
|
||||
private static function reverseIpv6Octets(string $ip): ?string {
|
||||
$ret = \filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6);
|
||||
if ($ret === false) {
|
||||
return null;
|
||||
}
|
||||
return \strrev(\implode(".", \str_split(\str_replace(':', '', IP::inet_expand($ip)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the name/host to resolve to discover if an ip is the host via DNS blacklists.
|
||||
*/
|
||||
private static function buildEndpoint(string $host, string $ip) {
|
||||
$replaced = 0;
|
||||
// See inc/config.php for the meaning of '%'.
|
||||
$lookup = \str_replace('%', $ip, $host, $replaced);
|
||||
if ($replaced !== 0) {
|
||||
return $lookup;
|
||||
}
|
||||
return "$ip.$host";
|
||||
}
|
||||
|
||||
private static function filterIp(string $str): string|false {
|
||||
return \filter_var($str, \FILTER_VALIDATE_IP);
|
||||
}
|
||||
|
||||
private function isIpWhitelisted(string $ip): bool {
|
||||
if (\in_array($ip, $this->exceptions)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE) !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function isIpBlacklistedImpl(string $ip, string $rip): ?string {
|
||||
foreach ($this->blacklist_providers as $blacklist) {
|
||||
$blacklist_host = $blacklist;
|
||||
if (\is_array($blacklist)) {
|
||||
$blacklist_host = $blacklist[0];
|
||||
}
|
||||
|
||||
// The name that will be looked up.
|
||||
$name = self::buildEndpoint($blacklist_host, $rip);
|
||||
|
||||
// Do the actual check.
|
||||
$is_blacklisted = $this->checkNameResolves($name);
|
||||
|
||||
if ($is_blacklisted) {
|
||||
// Pick the strategy to deal with this blacklisted host.
|
||||
|
||||
if (!isset($blacklist[1])) {
|
||||
// Just block them.
|
||||
return $blacklist_host;
|
||||
} elseif (\is_array($blacklist[1])) {
|
||||
// Check if the blacklist applies only to some IPs.
|
||||
foreach ($blacklist[1] as $octet_or_ip) {
|
||||
if ($ip == $octet_or_ip || $ip == "127.0.0.$octet_or_ip") {
|
||||
return $blacklist_host;
|
||||
}
|
||||
}
|
||||
} elseif (\is_callable($blacklist[1])) {
|
||||
// Custom user provided function.
|
||||
if ($blacklist[1]($ip)) {
|
||||
return $blacklist_host;
|
||||
}
|
||||
} else {
|
||||
// Check if the blacklist only applies to a specific IP.
|
||||
if ($ip == $blacklist[1] || $ip == "127.0.0.{$blacklist[1]}") {
|
||||
return $blacklist_host;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function checkNameResolves(string $name): bool {
|
||||
$value = $this->cache->get(self::buildDnsCacheKey($name));
|
||||
if ($value === null) {
|
||||
$value = !empty($this->resolver->nameToIps(self::buildDnsCacheKey($name)));
|
||||
$this->cache->set(self::buildDnsCacheKey($name), $value, self::DNS_CACHE_TIMEOUT);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a DNS accessor.
|
||||
*
|
||||
* @param DnsDriver $resolver DNS driver.
|
||||
* @param CacheDriver $cache Cache driver.
|
||||
* @param array $blacklists Array of DNS blacklist providers.
|
||||
* @param array $exceptions Exceptions to the blacklists.
|
||||
* @param bool $rdns_validate If to validate the Reverse DNS queries results.
|
||||
*/
|
||||
public function __construct(DnsDriver $resolver, CacheDriver $cache, array $blacklist_providers, array $exceptions, bool $rdns_validate) {
|
||||
$this->resolver = $resolver;
|
||||
$this->cache = $cache;
|
||||
$this->blacklist_providers = $blacklist_providers;
|
||||
$this->exceptions = $exceptions;
|
||||
$this->rdns_validate = $rdns_validate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given IP known to a blacklist and not whitelisted?
|
||||
* Documentation: https://github.com/vichan-devel/vichan/wiki/dnsbl
|
||||
*
|
||||
* @param string $ip The ip to lookup.
|
||||
* @return ?string Returns the hit blacklist if the IP is a in known blacklist. Null if the IP is not blacklisted.
|
||||
* @throws InvalidArgumentException Throws if $ip is not a valid IPv4 or IPv6 address.
|
||||
*/
|
||||
public function isIpBlacklisted(string $ip): ?string {
|
||||
$rev_ip = false;
|
||||
$ret = self::reverseIpv4Octets($ip);
|
||||
if ($ret !== null) {
|
||||
$rev_ip = $ret;
|
||||
}
|
||||
$ret = self::reverseIpv6Octets($ip);
|
||||
if ($ret !== null) {
|
||||
$rev_ip = $ret;
|
||||
}
|
||||
|
||||
if ($rev_ip === false) {
|
||||
throw new \InvalidArgumentException("'$ip' is not a valid ip address");
|
||||
}
|
||||
|
||||
if ($this->isIpWhitelisted($ip)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->isIpBlacklistedImpl($ip, $rev_ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the Reverse DNS lookup (rDNS) of the given IP.
|
||||
* This function can be slow since may validate the response.
|
||||
*
|
||||
* @param string $ip The ip to lookup.
|
||||
* @return array The hostnames of the given ip.
|
||||
* @throws InvalidArgumentException Throws if $ip is not a valid IPv4 or IPv6 address.
|
||||
*/
|
||||
public function ipToNames(string $ip): ?array {
|
||||
$ret = self::filterIp($ip);
|
||||
if ($ret === false) {
|
||||
throw new \InvalidArgumentException("'$ip' is not a valid ip address");
|
||||
}
|
||||
|
||||
$names = $this->cache->get(self::buildRDnsCacheKey($ret));
|
||||
if ($names !== null) {
|
||||
return $names;
|
||||
}
|
||||
|
||||
$names = $this->resolver->IpToNames($ret);
|
||||
if ($names === false) {
|
||||
$this->cache->set(self::buildRDnsCacheKey($ret), [], self::DNS_CACHE_TIMEOUT);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Do we bother with validating the result?
|
||||
if (!$this->rdns_validate) {
|
||||
$this->cache->set(self::buildRDnsCacheKey($ret), $names, self::DNS_CACHE_TIMEOUT);
|
||||
return $names;
|
||||
}
|
||||
|
||||
// Filter out the names that do not resolve to the given ip.
|
||||
$acc = [];
|
||||
foreach ($names as $name) {
|
||||
// Validate the response.
|
||||
$resolved_ips = $this->resolver->nameToIps($name);
|
||||
if ($resolved_ips !== null && \is_array($ret, $resolved_ips)) {
|
||||
$acc[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$this->cache->set(self::buildRDnsCacheKey($ret), $acc, self::DNS_CACHE_TIMEOUT);
|
||||
return $acc;
|
||||
}
|
||||
}
|
@ -3,10 +3,12 @@ namespace Vichan;
|
||||
|
||||
use Vichan\Controller\FloodManager;
|
||||
use Vichan\Data\Driver\{CacheDriver, HttpDriver, ErrorLogLogDriver, FileLogDriver, LogDriver, StderrLogDriver, SyslogLogDriver};
|
||||
use Vichan\Data\Driver\Dns\{DnsDriver, HostDnsDriver, LibcDnsDriver};
|
||||
use Vichan\Data\{FloodQueries, IpNoteQueries, UserPostQueries, ReportQueries};
|
||||
use Vichan\Service\FilterService;
|
||||
use Vichan\Service\FloodService;
|
||||
use Vichan\Service\HCaptchaQuery;
|
||||
use Vichan\Service\IpBlacklistService;
|
||||
use Vichan\Service\SecureImageCaptchaQuery;
|
||||
use Vichan\Service\ReCaptchaQuery;
|
||||
use Vichan\Service\YandexCaptchaQuery;
|
||||
@ -71,6 +73,14 @@ function build_context(array $config): Context {
|
||||
);
|
||||
},
|
||||
CacheDriver::class => fn(): CacheDriver => \Cache::getCache(),
|
||||
DnsDriver::class => function(Context $c) {
|
||||
$config = $c->get('config');
|
||||
if ($config['dns_system']) {
|
||||
return new HostDnsDriver(2);
|
||||
} else {
|
||||
return new LibcDnsDriver(2);
|
||||
}
|
||||
},
|
||||
\PDO::class => function(): \PDO {
|
||||
global $pdo;
|
||||
// Ensure the PDO is initialized.
|
||||
@ -99,7 +109,8 @@ function build_context(array $config): Context {
|
||||
FilterService::class => fn(Context $c): FilterService => new FilterService(
|
||||
$c->get('config')['filters'],
|
||||
$c->get(FloodService::class),
|
||||
$c->get(LogDriver::class)
|
||||
$c->get(LogDriver::class),
|
||||
$c->get(DnsDriver::class)
|
||||
),
|
||||
FloodManager::class => fn(Context $c): FloodManager => new FloodManager(
|
||||
$c->get(FilterService::class),
|
||||
@ -107,6 +118,16 @@ function build_context(array $config): Context {
|
||||
$c->get(IpNoteQueries::class),
|
||||
$c->get(LogDriver::class)
|
||||
),
|
||||
IpBlacklistService::class => function(Context $c): IpBlacklistService {
|
||||
$config = $c->get('config');
|
||||
return new IpBlacklistService(
|
||||
$c->get(DnsDriver::class),
|
||||
$c->get(CacheDriver::class),
|
||||
$config['dnsbl'],
|
||||
$config['dnsbl_exceptions'],
|
||||
$config['fcrdns']
|
||||
);
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -1767,61 +1767,6 @@ function buildJavascript() {
|
||||
file_write($config['file_script'], $script);
|
||||
}
|
||||
|
||||
function checkDNSBL() {
|
||||
global $config;
|
||||
|
||||
if (isIPv6())
|
||||
return; // No IPv6 support yet.
|
||||
|
||||
if (!isset($_SERVER['REMOTE_ADDR']))
|
||||
return; // Fix your web server configuration
|
||||
|
||||
if (preg_match("/^(::(ffff:)?)?(127\.|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|0\.|255\.)/", $_SERVER['REMOTE_ADDR']))
|
||||
return; // It's pointless to check for local IP addresses in dnsbls, isn't it?
|
||||
|
||||
if (in_array($_SERVER['REMOTE_ADDR'], $config['dnsbl_exceptions']))
|
||||
return;
|
||||
|
||||
$ipaddr = ReverseIPOctets($_SERVER['REMOTE_ADDR']);
|
||||
|
||||
foreach ($config['dnsbl'] as $blacklist) {
|
||||
if (!is_array($blacklist))
|
||||
$blacklist = array($blacklist);
|
||||
|
||||
if (($lookup = str_replace('%', $ipaddr, $blacklist[0])) == $blacklist[0])
|
||||
$lookup = $ipaddr . '.' . $blacklist[0];
|
||||
|
||||
if (!$ip = DNS($lookup))
|
||||
continue; // not in list
|
||||
|
||||
$blacklist_name = isset($blacklist[2]) ? $blacklist[2] : $blacklist[0];
|
||||
|
||||
if (!isset($blacklist[1])) {
|
||||
// If you're listed at all, you're blocked.
|
||||
error(sprintf($config['error']['dnsbl'], $blacklist_name));
|
||||
} elseif (is_array($blacklist[1])) {
|
||||
foreach ($blacklist[1] as $octet) {
|
||||
if ($ip == $octet || $ip == '127.0.0.' . $octet)
|
||||
error(sprintf($config['error']['dnsbl'], $blacklist_name));
|
||||
}
|
||||
} elseif (is_callable($blacklist[1])) {
|
||||
if ($blacklist[1]($ip))
|
||||
error(sprintf($config['error']['dnsbl'], $blacklist_name));
|
||||
} else {
|
||||
if ($ip == $blacklist[1] || $ip == '127.0.0.' . $blacklist[1])
|
||||
error(sprintf($config['error']['dnsbl'], $blacklist_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isIPv6() {
|
||||
return strstr($_SERVER['REMOTE_ADDR'], ':') !== false;
|
||||
}
|
||||
|
||||
function ReverseIPOctets($ip) {
|
||||
return implode('.', array_reverse(explode('.', $ip)));
|
||||
}
|
||||
|
||||
function wordfilters(&$body) {
|
||||
global $config;
|
||||
|
||||
@ -2512,60 +2457,6 @@ function undoImage(array $post) {
|
||||
}
|
||||
}
|
||||
|
||||
function rDNS($ip_addr) {
|
||||
global $config;
|
||||
|
||||
if ($config['cache']['enabled'] && ($host = cache::get('rdns_' . $ip_addr))) {
|
||||
return $host;
|
||||
}
|
||||
|
||||
if (!$config['dns_system']) {
|
||||
$host = gethostbyaddr($ip_addr);
|
||||
} else {
|
||||
$resp = shell_exec_error('host -W 3 ' . $ip_addr);
|
||||
if (preg_match('/domain name pointer ([^\s]+)$/', $resp, $m))
|
||||
$host = $m[1];
|
||||
else
|
||||
$host = $ip_addr;
|
||||
}
|
||||
|
||||
$isip = filter_var($host, FILTER_VALIDATE_IP);
|
||||
|
||||
if ($config['fcrdns'] && !$isip && DNS($host) != $ip_addr) {
|
||||
$host = $ip_addr;
|
||||
}
|
||||
|
||||
if ($config['cache']['enabled'])
|
||||
cache::set('rdns_' . $ip_addr, $host);
|
||||
|
||||
return $host;
|
||||
}
|
||||
|
||||
function DNS($host) {
|
||||
global $config;
|
||||
|
||||
if ($config['cache']['enabled'] && ($ip_addr = cache::get('dns_' . $host))) {
|
||||
return $ip_addr != '?' ? $ip_addr : false;
|
||||
}
|
||||
|
||||
if (!$config['dns_system']) {
|
||||
$ip_addr = gethostbyname($host);
|
||||
if ($ip_addr == $host)
|
||||
$ip_addr = false;
|
||||
} else {
|
||||
$resp = shell_exec_error('host -W 1 ' . $host);
|
||||
if (preg_match('/has address ([^\s]+)$/', $resp, $m))
|
||||
$ip_addr = $m[1];
|
||||
else
|
||||
$ip_addr = false;
|
||||
}
|
||||
|
||||
if ($config['cache']['enabled'])
|
||||
cache::set('dns_' . $host, $ip_addr !== false ? $ip_addr : '?');
|
||||
|
||||
return $ip_addr;
|
||||
}
|
||||
|
||||
function shell_exec_error($command, $suppress_stdout = false) {
|
||||
global $config, $debug;
|
||||
|
||||
|
@ -6,6 +6,7 @@ use Vichan\Context;
|
||||
use Vichan\Data\{IpNoteQueries, UserPostQueries, ReportQueries};
|
||||
use Vichan\Functions\{Format, Net};
|
||||
use Vichan\Data\Driver\{CacheDriver, LogDriver};
|
||||
use Vichan\Data\Driver\Dns\DnsDriver;
|
||||
|
||||
defined('TINYBOARD') or exit;
|
||||
|
||||
@ -971,7 +972,16 @@ function mod_user_posts_by_ip(Context $ctx, string $cip, ?string $encoded_cursor
|
||||
}
|
||||
|
||||
if ($config['mod']['dns_lookup'] && empty($config['ipcrypt_key'])) {
|
||||
$args['hostname'] = rDNS($ip);
|
||||
$resolver = $ctx->get(DnsDriver::class);
|
||||
$names = $resolver->IPToNames($ip);
|
||||
|
||||
if (!empty($names)) {
|
||||
if (count($names) === 1) {
|
||||
$args['hostname'] = $names[0];
|
||||
} else {
|
||||
$args['hostname'] = $names;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPermission($config['mod']['view_ban'])) {
|
||||
|
18
post.php
18
post.php
@ -5,10 +5,9 @@
|
||||
|
||||
require_once 'inc/bootstrap.php';
|
||||
|
||||
use Vichan\{Context, WebDependencyFactory};
|
||||
use Vichan\Data\Driver\{LogDriver, HttpDriver};
|
||||
use Vichan\Data\ReportQueries;
|
||||
use Vichan\Service\{RemoteCaptchaQuery, SecureImageCaptchaQuery};
|
||||
use Vichan\Service\{IpBlacklistService, RemoteCaptchaQuery, SecureImageCaptchaQuery};
|
||||
use Vichan\Functions\{Format, IP};
|
||||
|
||||
/**
|
||||
@ -373,7 +372,10 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
}
|
||||
|
||||
checkDNSBL();
|
||||
$blacklist = $context->get(IpBlacklistService::class)->isIpBlacklisted($_SERVER['REMOTE_ADDR']);
|
||||
if ($blacklist !== false) {
|
||||
error(\sprintf($config['error']['dnsbl'], $blacklist));
|
||||
}
|
||||
|
||||
// Check if board exists
|
||||
if (!openBoard($_POST['board']))
|
||||
@ -468,7 +470,10 @@ if (isset($_POST['delete'])) {
|
||||
}
|
||||
}
|
||||
|
||||
checkDNSBL();
|
||||
$blacklist = $context->get(IpBlacklistService::class)->isIpBlacklisted($_SERVER['REMOTE_ADDR']);
|
||||
if ($blacklist !== false) {
|
||||
error(\sprintf($config['error']['dnsbl'], $blacklist));
|
||||
}
|
||||
|
||||
// Check if board exists
|
||||
if (!openBoard($_POST['board']))
|
||||
@ -661,7 +666,10 @@ if (isset($_POST['delete'])) {
|
||||
(!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER']))))
|
||||
error($config['error']['referer']);
|
||||
|
||||
checkDNSBL();
|
||||
$blacklist = $context->get(IpBlacklistService::class)->isIpBlacklisted($_SERVER['REMOTE_ADDR']);
|
||||
if ($blacklist !== false) {
|
||||
error(\sprintf($config['error']['dnsbl'], $blacklist));
|
||||
}
|
||||
|
||||
|
||||
if ($post['mod'] = isset($_POST['mod']) && $_POST['mod']) {
|
||||
|
@ -16,8 +16,14 @@
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="subtitle">
|
||||
{% if subtitle %}
|
||||
{% if subtitle is iterable %}
|
||||
{% for s in subtitle %}
|
||||
{{ s }}{% if not loop.last %}<br>{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{ subtitle }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if mod and not hide_dashboard_link %}<p><a href="?/">{% trans %}Return to dashboard{% endtrans %}</a></p>{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
Loading…
x
Reference in New Issue
Block a user