%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/self/root/home/bitrix/www/bitrix/modules/main/lib/service/geoip/
Upload File :
Create Path :
Current File : //proc/self/root/home/bitrix/www/bitrix/modules/main/lib/service/geoip/manager.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2017 Bitrix
 */
namespace Bitrix\Main\Service\GeoIp;

use Bitrix\Main\Application;
use Bitrix\Main\Event;
use Bitrix\Main\IO\File;
use Bitrix\Main\Loader;
use Bitrix\Main\EventResult;
use Bitrix\Main\Text\Encoding;
use Bitrix\Main\Web\Json;

/**
 * Class for working with geolocation information.
 * @package Bitrix\Main\Service\GeoIp
 */
final class Manager
{
	/** @var array | null  */
	private static $handlers = null;

	/** @var Result */
	private static $data = array();

	/** @var bool */
	private static $logErrors = false;

	/** @var bool */
	private static $useCookie = false;

	/**
	 * Constant for parameters who information not available.
	 */
	const INFO_NOT_AVAILABLE = null;

	const COOKIE_NAME = 'BX_GEO_IP';
	const COOKIE_EXPIRED = 86400; //day

	/**
	 * Get the two letter country code.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getCountryCode($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('countryCode'));
		return $resultData !== null ? $resultData->getGeoData()->countryCode : '';
	}

	/**
	 * Get the full country name.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getCountryName($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('countryName'));
		return $resultData !== null ? $resultData->getGeoData()->countryName : '';
	}

	/**
	 * Get the full city name.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string|null
	 */
	public static function getCityName($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('cityName'));
		return $resultData !== null ? $resultData->getGeoData()->cityName : '';
	}

	/**
	 * Get the Postal Code, FSA or Zip Code.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string|null
	 */
	public static function getCityPostCode($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('zipCode'));
		return $resultData !== null ? $resultData->getGeoData()->zipCode : '';
	}

	/**
	 * Get geo-position attribute.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return array|null
	 */
	public static function getGeoPosition($ip = '', $lang = '')
	{
		$data = self::getDataResult($ip, $lang, array('latitude', 'longitude'));

		if (
			$data !== null
			&& $data->getGeoData()->latitude != self::INFO_NOT_AVAILABLE
			&&  $data->getGeoData()->longitude != self::INFO_NOT_AVAILABLE
		)
		{
			$result = Array(
				'latitude' => $data->getGeoData()->latitude,
				'longitude' => $data->getGeoData()->longitude,
			);
		}
		else
		{
			$result = self::INFO_NOT_AVAILABLE;
		}
		
		return $result;
	}

	/**
	 * Get the Latitude as signed double.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getGeoPositionLatitude($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('latitude'));
		return $resultData !== null ? $resultData->getGeoData()->latitude : '';
	}
	
	/**
	 * Get the Longitude as signed double.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getGeoPositionLongitude($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('longitude'));
		return $resultData !== null ? $resultData->getGeoData()->longitude : '';
	}
	
	/**
	 * Get the organization name.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getOrganizationName($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('organizationName'));
		return $resultData !== null ? $resultData->getGeoData()->organizationName : '';
	}
	
	/**
	 * Get the Internet Service Provider (ISP) name.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string
	 */
	public static function getIspName($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('ispName'));
		return $resultData !== null ? $resultData->getGeoData()->ispName : '';
	}

	/**
	 * Get the time zone for country and region code combo.
	 * @param string $ip Ip address.
	 * @param string $lang Language identifier.
	 * @return string|null
	 */
	public static function getTimezoneName($ip = '', $lang = '')
	{
		$resultData = self::getDataResult($ip, $lang, array('timezone'));
		return $resultData !== null ? $resultData->getGeoData()->timezone : '';
	}
	
	/**
	 * Get the all available information about geolocation.
	 *
	 * @param string  $ip Ip address.
	 * @param string  $lang Language identifier.
	 * @param array $required Required fields for result data.
	 * @return Result | null
	 */
	public static function getDataResult($ip = '', $lang = '', array $required = array())
	{
		$result = null;

		if(strlen($ip) <= 0)
			$ip = self::getRealIp();

		if(self::$useCookie && !isset(self::$data[$ip]))
			self::$data[$ip] = self::getCookie($ip);

		if(isset(self::$data[$ip]) && is_array(self::$data[$ip]))
		{
			/** @var Result $dataResult */
			foreach(self::$data[$ip] as $data)
			{
				if(is_object($data) && ($data instanceof Data))
				{
					if(empty($required) || self::hasDataAllRequiredFields($required, $data))
					{
						if(strlen($lang) <= 0 || $data->lang == $lang)
						{
							$result = new Result();
							$result->setGeoData($data);
							break;
						}
					}
				}
			}
		}
		else
		{
			self::$data[$ip] = array();
		}

		if(!$result)
		{
			if(self::$handlers === null)
				self::initHandlers();

			/** @var Base $handler */
			foreach(self::$handlers as $handler)
			{
				if(!$handler->isInstalled())
					continue;

				if(!$handler->isActive())
					continue;

				if(strlen($lang) > 0)
					if(!in_array($lang, $handler->getSupportedLanguages()))
						continue;

				if(!empty($required) && !self::hasDataAllRequiredFields($required, $handler->getProvidingData()))
					continue;

				$dataResult = $handler->getDataResult($ip, $lang);

				if(!$dataResult)
					continue;

				if(!$dataResult->isSuccess())
				{
					if(self::$logErrors)
					{
						$eventLog = new \CEventLog;

						$eventLog->Add(array(
							"SEVERITY" => \CEventLog::SEVERITY_ERROR,
							"AUDIT_TYPE_ID" => 'MAIN_SERVICES_GEOIP_GETDATA_ERROR',
							"MODULE_ID" => "main",
							"ITEM_ID" => $ip.'('.$lang.')',
							"DESCRIPTION" => 'Handler id: '.$handler->getId()."\n<br>".implode("\n<br>",$dataResult->getErrorMessages()),
						));
					}

					continue;
				}

				$geoData = $dataResult->getGeoData();
				$geoData->handlerClass = get_class($handler);
				$result = $dataResult;
				self::$data[$ip][$geoData->handlerClass] = $result->getGeoData();

				if(self::$useCookie)
					self::setCookie($ip, self::$data[$ip]);

				break;
			}
		}

		return $result;
	}

	/**
	 * @param $ip
	 * @return bool| Result[]
	 */
	private static function getCookie($ip)
	{
		$name = self::getCookieName($ip);
		$cookieData = Application::getInstance()->getContext()->getRequest()->getCookieRaw($name);

		if(!$cookieData)
			return false;

		if(function_exists('gzuncompress'))
			$cookieData = @\gzuncompress($cookieData);

		if(!$cookieData)
			return false;

		try
		{
			$cookieData = Json::decode($cookieData);
		}
		catch(\Exception $e)
		{
			$cookieData = false;
		}

		if(!is_array($cookieData))
			return false;

		$result = array();

		foreach($cookieData as $class => $data)
		{
			$tmpData = new Data();

			foreach($data as $attr => $value)
				if(property_exists($tmpData, $attr))
					$tmpData->$attr = $value;

			$result[$class] = $tmpData;
		}

		return !empty($result) ? $result : false;
	}

	/**
	 * @param string $ip
	 * @param Data[] $geoData
	 * @return bool
	 */
	private static function setCookie($ip, $geoData)
	{
		$cookieData = array();

		foreach($geoData as $class => $data)
		{
			$cookieData[$class] = array();
			$values = get_object_vars($data);

			foreach($values as $attr => $value)
				if($value !== self::INFO_NOT_AVAILABLE)
					$cookieData[$class][$attr] = $value;
		}

		$cookieData = Json::encode($cookieData);

		if(function_exists('gzcompress'))
			$cookieData = \gzcompress($cookieData, 9);

		return setcookie(
			self::getCookieName($ip),
			$cookieData,
			time()+self::COOKIE_EXPIRED,
			'/'
		);
	}

	/**
	 * @param string $ip
	 * @return string
	 */
	private static function getCookieName($ip)
	{
		return self::COOKIE_NAME.'_'.str_replace('.', '_',$ip);
	}

	/**
	 * @param array $required
	 * @param Data|ProvidingData $geoData
	 * @return bool
	 */
	private static function hasDataAllRequiredFields(array $required, $geoData)
	{
		if(empty($required))
			return true;

		$vars = get_object_vars($geoData);

		foreach($required as $field)
			if($vars[$field] === self::INFO_NOT_AVAILABLE)
				return false;

		return true;
	}

	private static function initHandlers()
	{
		if(self::$handlers !== null)
			return;

		self::$handlers = array();
		$handlersList = array();
		$buildInHandlers = array(
			'\Bitrix\Main\Service\GeoIp\MaxMind' => 'lib/service/geoip/maxmind.php',
			'\Bitrix\Main\Service\GeoIp\Extension' => 'lib/service/geoip/extension.php',
			'\Bitrix\Main\Service\GeoIp\SypexGeo' => 'lib/service/geoip/sypexgeo.php'
		);

		Loader::registerAutoLoadClasses('main', $buildInHandlers);

		$handlersFields = array();
		$res = HandlerTable::getList();

		while($row = $res->fetch())
			$handlersFields[$row['CLASS_NAME']] = $row;

		foreach($buildInHandlers as $class => $file)
		{
			if(self::isHandlerClassValid($class))
			{
				$fields = isset($handlersFields[$class]) ? $handlersFields[$class] : array();
				$handlersList[$class] = new $class($fields);
				$handlersSort[$class] = $handlersList[$class]->getSort();
			}
		}

		$event = new Event('main', 'onMainGeoIpHandlersBuildList');
		$event->send();
		$resultList = $event->getResults();

		if (is_array($resultList) && !empty($resultList))
		{
			$customClasses = array();

			foreach ($resultList as $eventResult)
			{
				/** @var  EventResult $eventResult*/
				if ($eventResult->getType() != EventResult::SUCCESS)
					continue;

				$params = $eventResult->getParameters();

				if(!empty($params) && is_array($params))
					$customClasses = array_merge($customClasses, $params);
			}

			if(!empty($customClasses))
			{
				Loader::registerAutoLoadClasses(null, $customClasses);

				foreach($customClasses as $class => $file)
				{
					if(!File::isFileExists(\Bitrix\Main\Application::getDocumentRoot().'/'.$file))
					{
						continue;
					}

					if(self::isHandlerClassValid($class))
					{
						$fields = isset($handlersFields[$class]) ? $handlersFields[$class] : array();
						$handlersList[$class] = new $class($fields);
						$handlersSort[$class] = $handlersList[$class]->getSort();
					}
				}
			}
		}

		asort($handlersSort, SORT_NUMERIC);

		foreach($handlersSort as $class => $sort)
			self::$handlers[$class] = $handlersList[$class];
	}

	/**
	 * @param string $className
	 * @return bool
	 */
	private static function isHandlerClassValid($className)
	{
		if(!class_exists($className))
			return false;

		if(!is_subclass_of($className, '\Bitrix\Main\Service\GeoIp\Base'))
			return false;

		return true;
	}

	/**
	 * @return string | false Ip address.
	 */
	public static function getRealIp()
	{
		$ip = false;
		$xForwarded = Application::getInstance()->getContext()->getServer()->get('HTTP_X_FORWARDED_FOR');

		if (!empty($xForwarded))
		{
			$ips = explode (", ", $xForwarded);
			$fCount = count($ips);

			for ($i = 0; $i < $fCount; $i++)
			{
				if (!preg_match("/^(10|172\\.16|192\\.168)\\./", $ips[$i]))
				{
					$ip = $ips[$i];
					break;
				}
			}
		}

		if(!$ip)
		{
			$ip = trim(Application::getInstance()->getContext()->getRequest()->getRemoteAddress());
		}

		return $ip;
	}

	/**
	 * @return Base[] Handlers list.
	 */

	public static function getHandlers()
	{
		if(self::$handlers === null)
			self::initHandlers();

		return self::$handlers;
	}

	/**
	 * @param string $className. Class name of handler.
	 * @return Base | null Handler.
	 */
	public static function getHandlerByClassName($className)
	{
		if(self::$handlers === null)
			self::initHandlers();

		return isset(self::$handlers[$className]) ? self::$handlers[$className] : null;
	}

	/**
	 * Turn on / off error logging for debugging purposes.
	 * @param bool $isLog
	 */
	public static function setLogErrors($isLog)
	{
		self::$logErrors = $isLog;
	}

	/**
	 * Turn on / off storing geolocation info in cookie for performance purposes.
	 * @param bool $isUse
	 */
	public static function useCookieToStoreInfo($isUse)
	{
		self::$useCookie = $isUse;
	}

	/**
	 * @param Base $handler
	 * @return string Config HTML for admin interface form.
	 */
	public static function getHandlerAdminConfigHtml(Base $handler)
	{
		$result = '';
		$adminFields = $handler->getConfigForAdmin();

		foreach($adminFields as $field)
		{
			if($field['TYPE'] == 'COLSPAN2')
			{
				$heading = isset($field['HEADING']) && $field['HEADING'] == true ? ' class="heading"' : '';
				$result .= '<tr'.$heading.'><td colspan="2">'.$field['TITLE'];
			}
			elseif($field['TYPE'] == 'TEXT' || $field['TYPE'] == 'CHECKBOX')
			{
				$required = isset($field['REQUIRED']) && $field['REQUIRED'] == true ? ' class="adm-detail-required-field"' : '';
				$disabled = isset($field['DISABLED']) && $field['DISABLED'] == true ? ' disabled' : '';
				$value = isset($field['VALUE']) ? ' value="'.$field['VALUE'].'"' : '';
				$name = isset($field['NAME']) ? ' name="'.$field['NAME'].'"' : '';
				$title = isset($field['TITLE']) ? ' title="'.$field['TITLE'].'"' : '';

				$result .= '<tr'.$required.'><td width="40%">'.$field['TITLE'].':</td><td width="60%">';

				if($field['TYPE'] == 'TEXT')
				{
					$result .= '<input type="text" size="45" maxlength="255"'.$name.$value.$disabled.$title.'>';
				}
				elseif($field['TYPE'] == 'CHECKBOX')
				{
					$checked = isset($field['CHECKED']) && $field['CHECKED'] == true ? ' checked' : '';
					$result .= '<input type="checkbox"'.$name.$value.$checked.$disabled.$title.'>';
				}
			}

			$result .= '</td></tr>';
		}

		return $result;
	}

	/**
	 * @param string $ip
	 * @param string $lang
	 * @param array $required
	 * @return DataResult|null
	 * @deprecated
	 */
	public static function getData($ip = '', $lang = '', array $required = array())
	{
		$dataResult = self::getDataResult($ip, $lang, $required);

		if(!$dataResult)
			return null;

		$result = new DataResult();

		foreach($dataResult as $attr => $value)
			if(property_exists($result, $attr))
				$result->$attr = $value;

		return $result;
	}
}

Zerion Mini Shell 1.0