Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/GeoIp2/LocationProvider/GeoIp2.php')
-rw-r--r--plugins/GeoIp2/LocationProvider/GeoIp2.php266
1 files changed, 266 insertions, 0 deletions
diff --git a/plugins/GeoIp2/LocationProvider/GeoIp2.php b/plugins/GeoIp2/LocationProvider/GeoIp2.php
new file mode 100644
index 0000000000..838adbb9e5
--- /dev/null
+++ b/plugins/GeoIp2/LocationProvider/GeoIp2.php
@@ -0,0 +1,266 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\GeoIp2\LocationProvider;
+
+use Exception;
+use Piwik\Option;
+use Piwik\Piwik;
+use Piwik\Plugins\UserCountry\LocationProvider;
+
+/**
+ * Base type for all GeoIP 2 LocationProviders.
+ *
+ */
+abstract class GeoIp2 extends LocationProvider
+{
+ const GEO_LITE_URL = 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz';
+ const TEST_IP = '194.57.91.215';
+ const SWITCH_TO_ISO_REGIONS_OPTION_NAME = 'usercountry.switchtoisoregions';
+
+ public static $geoIPDatabaseDir = 'misc';
+
+ /**
+ * Cached region name array. Data is from geoipregionvars.php.
+ *
+ * @var array
+ */
+ private static $regionNames = null;
+
+ /**
+ * Stores possible database file names categorized by the type of information
+ * GeoIP databases hold.
+ *
+ * @var array
+ */
+ public static $dbNames = array(
+ 'loc' => array('GeoIP2-City.mmdb', 'GeoIP2-Enterprise.mmdb', 'GeoLite2-City.mmdb', 'GeoIP2-Country.mmdb', 'GeoLite2-Country.mmdb'),
+ 'isp' => array('GeoIP2-ISP.mmdb'),
+ );
+
+ /**
+ * Returns true if this provider has been setup correctly, the error message if not.
+ *
+ * @return bool|string
+ */
+ public function isWorking()
+ {
+ // test with an example IP to make sure the provider is working
+ // NOTE: At the moment only country, region & city info is tested.
+ try {
+ $supportedInfo = $this->getSupportedLocationInfo();
+
+ list($testIp, $expectedResult) = self::getTestIpAndResult();
+
+ // get location using test IP
+ $location = $this->getLocation(array('ip' => $testIp));
+
+ // check that result is the same as expected
+ $isResultCorrect = true;
+ foreach ($expectedResult as $key => $value) {
+ // if this provider is not configured to support this information type, skip it
+ if (empty($supportedInfo[$key])) {
+ continue;
+ }
+
+ if (empty($location[$key])
+ || $location[$key] != $value
+ ) {
+ $isResultCorrect = false;
+ }
+ }
+
+ if (!$isResultCorrect) {
+ $unknown = Piwik::translate('General_Unknown');
+
+ $location = "'"
+ . (empty($location[self::CITY_NAME_KEY]) ? $unknown : $location[self::CITY_NAME_KEY])
+ . ", "
+ . (empty($location[self::REGION_CODE_KEY]) ? $unknown : $location[self::REGION_CODE_KEY])
+ . ", "
+ . (empty($location[self::COUNTRY_CODE_KEY]) ? $unknown : $location[self::COUNTRY_CODE_KEY])
+ . "'";
+
+ $expectedLocation = "'" . $expectedResult[self::CITY_NAME_KEY] . ", "
+ . $expectedResult[self::REGION_CODE_KEY] . ", "
+ . $expectedResult[self::COUNTRY_CODE_KEY] . "'";
+
+ $bind = array($testIp, $location, $expectedLocation);
+ return Piwik::translate('UserCountry_TestIPLocatorFailed', $bind);
+ }
+
+ return true;
+ } catch (Exception $ex) {
+ return $ex->getMessage();
+ }
+ }
+
+ /**
+ * Returns the path of an existing GeoIP 2 database or false if none can be found.
+ *
+ * @param array $possibleFileNames The list of possible file names for the GeoIP database.
+ * @return string|false
+ */
+ public static function getPathToGeoIpDatabase($possibleFileNames)
+ {
+ foreach ($possibleFileNames as $filename) {
+ $path = self::getPathForGeoIpDatabase($filename);
+ if (file_exists($path)) {
+ return $path;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns full path for a GeoIP 2 database managed by Piwik.
+ *
+ * @param string $filename Name of the .dat file.
+ * @return string
+ */
+ public static function getPathForGeoIpDatabase($filename)
+ {
+ return PIWIK_INCLUDE_PATH . '/' . self::$geoIPDatabaseDir . '/' . $filename;
+ }
+
+ /**
+ * Returns test IP used by isWorking and expected result.
+ *
+ * @return array eg. array('1.2.3.4', array(self::COUNTRY_CODE_KEY => ...))
+ */
+ private static function getTestIpAndResult()
+ {
+ static $result = null;
+ if (is_null($result)) {
+ $expected = array(self::COUNTRY_CODE_KEY => 'FR',
+ self::REGION_CODE_KEY => 'BFC',
+ self::CITY_NAME_KEY => 'Besançon');
+ $result = array(self::TEST_IP, $expected);
+ }
+ return $result;
+ }
+
+ public function activate()
+ {
+ $option = Option::get(self::SWITCH_TO_ISO_REGIONS_OPTION_NAME);
+ if (empty($option)) {
+ Option::set(self::SWITCH_TO_ISO_REGIONS_OPTION_NAME, time());
+ }
+ }
+
+ /**
+ * Returns true if there is a GeoIP 2 database in the 'misc' directory.
+ *
+ * @return bool
+ */
+ public static function isDatabaseInstalled()
+ {
+ return self::getPathToGeoIpDatabase(self::$dbNames['loc'])
+ || self::getPathToGeoIpDatabase(self::$dbNames['isp']);
+ }
+
+ /**
+ * Returns the type of GeoIP 2 database ('loc' or 'isp') based on the
+ * filename (eg, 'GeoLite2-City.mmdb', 'GeoIP2-ISP.mmdb', etc).
+ *
+ * @param string $filename
+ * @return string|false 'loc', 'isp' or false if cannot find a database type.
+ */
+ public static function getGeoIPDatabaseTypeFromFilename($filename)
+ {
+ foreach (self::$dbNames as $key => $names) {
+ foreach ($names as $name) {
+ if ($name === $filename) {
+ return $key;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a region name for a country code + region code.
+ *
+ * @param string $countryCode
+ * @param string $regionCode
+ * @return string The region name or 'Unknown' (translated).
+ */
+ public static function getRegionNameFromCodes($countryCode, $regionCode)
+ {
+ $regionNames = self::getRegionNames();
+
+ $countryCode = strtoupper($countryCode);
+ $regionCode = strtoupper($regionCode);
+
+ if (isset($regionNames[$countryCode][$regionCode])) {
+ return $regionNames[$countryCode][$regionCode];
+ } else {
+ return Piwik::translate('General_Unknown');
+ }
+ }
+
+ /**
+ * Returns an array of region names mapped by country code & region code.
+ *
+ * @return array
+ */
+ public static function getRegionNames()
+ {
+ if (is_null(self::$regionNames)) {
+ self::$regionNames = require_once __DIR__ . '/../data/isoRegionNames.php';
+ }
+
+ return self::$regionNames;
+ }
+
+ /**
+ * Converts an old FIPS region code to ISO
+ *
+ * @param string $countryCode
+ * @param string $fipsRegionCode
+ * @param bool $returnOriginalIfNotFound return given region code if no mapping was found
+ * @return array
+ */
+ public static function convertRegionCodeToIso($countryCode, $fipsRegionCode, $returnOriginalIfNotFound = false)
+ {
+ static $mapping;
+ if(empty($mapping)) {
+ $mapping = include __DIR__ . '/../data/regionMapping.php';
+ }
+ $countryCode = strtoupper($countryCode);
+ if (empty($countryCode) || in_array($countryCode, ['EU', 'AP', 'A1', 'A2'])) {
+ return ['', ''];
+ }
+ if (in_array($countryCode, ['US', 'CA'])) { // US and CA always haven been iso codes
+ return [$countryCode, $fipsRegionCode];
+ }
+ if ($countryCode == 'TI') {
+ $countryCode = 'CN';
+ $fipsRegionCode = '14';
+ }
+ $isoRegionCode = $returnOriginalIfNotFound ? $fipsRegionCode : '';
+ if (!empty($fipsRegionCode) && !empty($mapping[$countryCode][$fipsRegionCode])) {
+ $isoRegionCode = $mapping[$countryCode][$fipsRegionCode];
+ }
+ return [$countryCode, $isoRegionCode];
+ }
+
+ /**
+ * Returns an IP address from an array that was passed into getLocation. This
+ * will return an IPv4 address or IPv6 address.
+ *
+ * @param array $info Must have 'ip' key.
+ * @return string|null
+ */
+ protected function getIpFromInfo($info)
+ {
+ $ip = \Piwik\Network\IP::fromStringIP($info['ip']);
+
+ return $ip->toString();
+ }
+} \ No newline at end of file