View source
<?php
namespace Drupal\restrict_ip\Service;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Path\PathMatcherInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\restrict_ip\Mapper\RestrictIpMapperInterface;
use Drupal\user\UserDataInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class RestrictIpService implements RestrictIpServiceInterface {
private $blocked;
protected $currentUser;
protected $currentPath;
protected $config;
private $currentUserIp;
protected $mapper;
protected $pathMatcher;
protected $moduleHandler;
protected $userData;
public function __construct(AccountProxyInterface $currentUser, CurrentPathStack $currentPathStack, ConfigFactoryInterface $configFactory, RequestStack $requestStack, RestrictIpMapperInterface $restrictIpMapper, PathMatcherInterface $pathMatcher, ModuleHandlerInterface $moduleHandler, UserDataInterface $userData = NULL) {
$this->currentUser = $currentUser;
$this->mapper = $restrictIpMapper;
$this->pathMatcher = $pathMatcher;
$this->moduleHandler = $moduleHandler;
$this->userData = $userData;
$this->currentPath = strtolower($currentPathStack
->getPath());
$this->config = $configFactory
->get('restrict_ip.settings');
$this->currentUserIp = $requestStack
->getCurrentRequest()
->getClientIp();
}
public function userIsBlocked() {
if ($this
->allowAccessByPermission()) {
return FALSE;
}
return $this->blocked;
}
public function testForBlock($runInCli = FALSE) {
$this->blocked = FALSE;
if ($this->config
->get('enable')) {
$this->blocked = TRUE;
if (PHP_SAPI != 'cli' || $runInCli) {
$access_denied = TRUE;
if ($this
->allowAccessWhitelistedPath()) {
$access_denied = FALSE;
}
elseif ($this
->allowAccessBlacklistedPath()) {
$access_denied = FALSE;
}
elseif ($this
->allowAccessWhitelistedIp()) {
$access_denied = FALSE;
}
elseif ($this->moduleHandler
->moduleExists('ip2country')) {
if ($this
->allowAccessWhitelistCountry()) {
$access_denied = FALSE;
}
elseif ($this
->allowAccessBlacklistCountry()) {
$access_denied = FALSE;
}
}
if ($access_denied) {
if (PHP_SAPI != 'cli') {
$_SESSION['restrict_ip'] = TRUE;
}
}
else {
$this->blocked = FALSE;
}
}
}
}
public function cleanIpAddressInput($input) {
$ip_addresses = trim($input);
$ip_addresses = preg_replace('/(\\/\\/|#).+/', '', $ip_addresses);
$ip_addresses = preg_replace('~/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/~', '', $ip_addresses);
$addresses = explode(PHP_EOL, $ip_addresses);
$return = [];
foreach ($addresses as $ip_address) {
$trimmed = trim($ip_address);
if (strlen($trimmed)) {
$return[] = $trimmed;
}
}
return $return;
}
public function getCurrentUserIp() {
return $this->currentUserIp;
}
public function getCurrentPath() {
return $this->currentPath;
}
public function getWhitelistedIpAddresses() {
$ip_addresses = $this->mapper
->getWhitelistedIpAddresses();
return is_array($ip_addresses) ? $ip_addresses : [];
}
public function saveWhitelistedIpAddresses(array $ipAddresses, $overwriteExisting = TRUE) {
$this->mapper
->saveWhitelistedIpAddresses($ipAddresses, $overwriteExisting);
}
public function getWhitelistedPagePaths() {
$whitelisted_paths = $this->mapper
->getWhitelistedPaths();
return is_array($whitelisted_paths) ? $whitelisted_paths : [];
}
public function saveWhitelistedPagePaths(array $whitelistedPaths, $overwriteExisting = TRUE) {
$this->mapper
->saveWhitelistedPaths($whitelistedPaths, $overwriteExisting);
}
public function getBlacklistedPagePaths() {
$blacklisted_paths = $this->mapper
->getBlacklistedPaths();
return is_array($blacklisted_paths) ? $blacklisted_paths : [];
}
public function saveBlacklistedPagePaths(array $blacklistedPaths, $overwriteExisting = TRUE) {
$this->mapper
->saveBlacklistedPaths($blacklistedPaths, $overwriteExisting);
}
protected function ip2CountryGetCurrentUserCountry() {
return ip2country_get_country($this->currentUserIp);
}
private function allowAccessByPermission() {
static $allow_access;
if (is_null($allow_access)) {
$allow_access = [];
}
if (!isset($allow_access[$this->currentPath])) {
$allow_access[$this->currentPath] = FALSE;
if ($this->config
->get('allow_role_bypass')) {
$current_path = $this->currentPath;
if ($this->currentUser
->hasPermission('bypass ip restriction') || in_array($current_path, array(
'/user',
'/user/login',
'/user/password',
'/user/logout',
'/user/register',
)) || strpos($current_path, '/user/reset/') === 0) {
$allow_access[$this->currentPath] = TRUE;
}
}
}
return $allow_access[$this->currentPath];
}
private function allowAccessWhitelistedPath() {
$allow_access = FALSE;
if ($this->config
->get('white_black_list') == 1) {
$whitelisted_pages = $this
->getWhitelistedPagePaths();
$current_whitelist = FALSE;
if (count($whitelisted_pages)) {
foreach ($whitelisted_pages as $whitelisted_page) {
if ($this->pathMatcher
->matchPath($this->currentPath, $whitelisted_page)) {
$current_whitelist = TRUE;
}
}
}
if ($current_whitelist) {
$allow_access = TRUE;
}
}
return $allow_access;
}
private function allowAccessBlacklistedPath() {
$allow_access = FALSE;
if ($this->config
->get('white_black_list') == 2) {
$blacklisted_pages = $this
->getBlacklistedPagePaths();
$current_blacklist = FALSE;
if (count($blacklisted_pages)) {
foreach ($blacklisted_pages as $blacklisted_page) {
if ($this->pathMatcher
->matchPath($this->currentPath, $blacklisted_page)) {
$current_blacklist = TRUE;
}
}
}
if (!$current_blacklist) {
$allow_access = TRUE;
}
}
return $allow_access;
}
private function allowAccessWhitelistedIp() {
$ip_whitelist = $this
->buildWhitelistedIpAddresses();
if (count($ip_whitelist)) {
foreach ($ip_whitelist as $whitelisted_address) {
if ($this
->testWhitelistedIp($whitelisted_address)) {
return TRUE;
}
}
}
return FALSE;
}
private function allowAccessWhitelistCountry() {
$allow_access = FALSE;
if ($this->config
->get('country_white_black_list') == 1) {
$country_code = $this
->ip2CountryGetCurrentUserCountry();
if ($country_code) {
$countries = explode(':', $this->config
->get('country_list'));
return in_array(strtoupper($country_code), $countries);
}
}
return FALSE;
}
private function allowAccessBlacklistCountry() {
$allow_access = FALSE;
if ($this->config
->get('country_white_black_list') == 2) {
$country_code = $this
->ip2CountryGetCurrentUserCountry();
if ($country_code) {
$countries = explode(':', $this->config
->get('country_list'));
return !in_array(strtoupper($country_code), $countries);
}
}
return FALSE;
}
private function buildWhitelistedIpAddresses() {
$ip_addresses = $this
->getWhitelistedIpAddresses();
$ip_whitelist = $this->config
->get('ip_whitelist');
if (count($ip_whitelist)) {
$ip_addresses = array_merge($ip_addresses, $ip_whitelist);
}
return $ip_addresses;
}
private function testWhitelistedIp($whitelisted_ip) {
if ($whitelisted_ip == $this
->getCurrentUserIp()) {
return TRUE;
}
$pieces = explode('-', $whitelisted_ip);
if (count($pieces) == 2) {
$start_ip = $pieces[0];
$end_ip = $pieces[1];
$start_pieces = explode('.', $start_ip);
if (count($start_pieces) === 4) {
$user_pieces = explode('.', $this->currentUserIp);
for ($i = 0; $i < 3; $i++) {
if ((int) $user_pieces[$i] !== (int) $start_pieces[$i]) {
return FALSE;
}
}
$start_final_chunk = (int) array_pop($start_pieces);
$end_pieces = explode('.', $end_ip);
$end_final_chunk = (int) array_pop($end_pieces);
$user_final_chunk = (int) array_pop($user_pieces);
if ($user_final_chunk >= $start_final_chunk && $user_final_chunk <= $end_final_chunk) {
return TRUE;
}
}
}
return FALSE;
}
}