PDF rausgenommen
This commit is contained in:
20
msd2/tracking/piwik/plugins/GeoIp2/Columns/Region.php
Normal file
20
msd2/tracking/piwik/plugins/GeoIp2/Columns/Region.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?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\Columns;
|
||||
|
||||
class Region extends \Piwik\Plugins\UserCountry\Columns\Region
|
||||
{
|
||||
protected $columnType = 'char(3) DEFAULT NULL';
|
||||
protected $segmentName = '';
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
// do not remove region column when plugin is deactivated
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\GeoIp2\Commands;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Option;
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\UserCountry\LocationProvider;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ConvertRegionCodesToIso extends ConsoleCommand
|
||||
{
|
||||
const OPTION_NAME = 'regioncodes_converted';
|
||||
const MAPPING_TABLE_NAME = 'fips2iso';
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('usercountry:convert-region-codes');
|
||||
$this->setDescription("Convert FIPS region codes saved by GeoIP legacy provider to ISO.");
|
||||
}
|
||||
|
||||
public function isEnabled()
|
||||
{
|
||||
return (LocationProvider::getCurrentProvider() instanceof GeoIp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return void|int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// chick if option is set to disable second run
|
||||
if (Option::get(self::OPTION_NAME)) {
|
||||
$output->writeln('Converting region codes already done.');
|
||||
return;
|
||||
}
|
||||
|
||||
$output->setDecorated(true);
|
||||
|
||||
$output->write('Creating mapping table in database');
|
||||
|
||||
Db::query('DROP table if exists ' . self::MAPPING_TABLE_NAME);
|
||||
|
||||
DbHelper::createTable(self::MAPPING_TABLE_NAME,
|
||||
"`country_code` VARCHAR(2) NOT NULL,
|
||||
`fips_code` VARCHAR(2) NOT NULL,
|
||||
`iso_code` VARCHAR(4) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`country_code`, `fips_code`)");
|
||||
|
||||
$output->writeln(' <fg=green>✓</>');
|
||||
|
||||
$mappings = include __DIR__ . '/../data/regionMapping.php';
|
||||
|
||||
$output->write('Inserting mapping data ');
|
||||
|
||||
$counter = 0;
|
||||
foreach ($mappings as $country => $regionMapping) {
|
||||
foreach ($regionMapping as $fips => $iso) {
|
||||
if ($fips == $iso) {
|
||||
continue; // nothing needs to be changed, so ignore the mapping
|
||||
}
|
||||
|
||||
Db::query('INSERT INTO `'.Common::prefixTable(self::MAPPING_TABLE_NAME).'` VALUES (?, ?, ?)', [$country, $fips, $iso]);
|
||||
$counter++;
|
||||
if ($counter%50 == 0) {
|
||||
$output->write('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output->writeln(' <fg=green>✓</>');
|
||||
|
||||
$output->writeln('Updating Matomo log tables:');
|
||||
|
||||
$activationTime = Option::get(GeoIp2::SWITCH_TO_ISO_REGIONS_OPTION_NAME);
|
||||
$activationDateTime = date('Y-m-d H:i:s', $activationTime);
|
||||
|
||||
// fix country and region of tibet so it wil be updated correctly afterwards
|
||||
$tibetFixQuery = 'UPDATE %s SET location_country = "cn", location_region = "14" WHERE location_country = "ti"';
|
||||
|
||||
// replace invalid country codes used by GeoIP Legacy
|
||||
$fixInvalidCountriesQuery = 'UPDATE %s SET location_country = "" WHERE location_country IN("AP", "EU", "A1", "A2")';
|
||||
|
||||
$query = "UPDATE %s INNER JOIN %s ON location_country = country_code AND location_region = fips_code SET location_region = iso_code
|
||||
WHERE `%s` < ?";
|
||||
|
||||
$logTables = ['log_visit' => 'visit_first_action_time', 'log_conversion' => 'server_time'];
|
||||
|
||||
foreach ($logTables as $logTable => $dateField) {
|
||||
$output->write('- Updating ' . $logTable);
|
||||
|
||||
Db::query(sprintf($tibetFixQuery, Common::prefixTable($logTable)));
|
||||
Db::query(sprintf($fixInvalidCountriesQuery, Common::prefixTable($logTable)));
|
||||
|
||||
$sql = sprintf($query, Common::prefixTable($logTable), Common::prefixTable(self::MAPPING_TABLE_NAME), $dateField);
|
||||
Db::query($sql, $activationDateTime);
|
||||
|
||||
$output->writeln(' <fg=green>✓</>');
|
||||
}
|
||||
|
||||
$output->write('Removing mapping table from database ');
|
||||
Db::dropTables(Common::prefixTable(self::MAPPING_TABLE_NAME));
|
||||
$output->writeln(' <fg=green>✓</>');
|
||||
|
||||
// save option to prevent a second run
|
||||
Option::set(self::OPTION_NAME, true);
|
||||
|
||||
$output->writeln('All region codes converted.');
|
||||
}
|
||||
|
||||
|
||||
}
|
673
msd2/tracking/piwik/plugins/GeoIp2/GeoIP2AutoUpdater.php
Normal file
673
msd2/tracking/piwik/plugins/GeoIp2/GeoIP2AutoUpdater.php
Normal file
@ -0,0 +1,673 @@
|
||||
<?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;
|
||||
|
||||
require_once PIWIK_INCLUDE_PATH . "/core/ScheduledTask.php"; // for the tracker which doesn't include this file
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Date;
|
||||
use Piwik\Filesystem;
|
||||
use Piwik\Http;
|
||||
use Piwik\Log;
|
||||
use Piwik\Option;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2 AS LocationProviderGeoIp2;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2\Php;
|
||||
use Piwik\Plugins\UserCountry\GeoIPAutoUpdater;
|
||||
use Piwik\Scheduler\Scheduler;
|
||||
use Piwik\Scheduler\Task;
|
||||
use Piwik\Scheduler\Timetable;
|
||||
use Piwik\Scheduler\Schedule\Monthly;
|
||||
use Piwik\Scheduler\Schedule\Weekly;
|
||||
use Piwik\SettingsPiwik;
|
||||
use Piwik\Unzip;
|
||||
|
||||
/**
|
||||
* Used to automatically update installed GeoIP 2 databases, and manages the updater's
|
||||
* scheduled task.
|
||||
*/
|
||||
class GeoIP2AutoUpdater extends Task
|
||||
{
|
||||
const SCHEDULE_PERIOD_MONTHLY = 'month';
|
||||
const SCHEDULE_PERIOD_WEEKLY = 'week';
|
||||
|
||||
const SCHEDULE_PERIOD_OPTION_NAME = 'geoip2.updater_period';
|
||||
|
||||
const LOC_URL_OPTION_NAME = 'geoip2.loc_db_url';
|
||||
const ISP_URL_OPTION_NAME = 'geoip2.isp_db_url';
|
||||
|
||||
const LAST_RUN_TIME_OPTION_NAME = 'geoip2.updater_last_run_time';
|
||||
|
||||
private static $urlOptions = array(
|
||||
'loc' => self::LOC_URL_OPTION_NAME,
|
||||
'isp' => self::ISP_URL_OPTION_NAME,
|
||||
);
|
||||
|
||||
/**
|
||||
* PHP Error caught through a custom error handler while trying to use a downloaded
|
||||
* GeoIP 2 database. See catchGeoIPError for more info.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $unzipPhpError = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (!SettingsPiwik::isInternetEnabled()) {
|
||||
// no automatic updates possible if no internet available
|
||||
return;
|
||||
}
|
||||
|
||||
$schedulePeriodStr = self::getSchedulePeriod();
|
||||
|
||||
// created the scheduledtime instance, also, since GeoIP 2 updates are done on tuesdays,
|
||||
// get new DBs on Wednesday
|
||||
switch ($schedulePeriodStr) {
|
||||
case self::SCHEDULE_PERIOD_WEEKLY:
|
||||
$schedulePeriod = new Weekly();
|
||||
$schedulePeriod->setDay(3);
|
||||
break;
|
||||
case self::SCHEDULE_PERIOD_MONTHLY:
|
||||
default:
|
||||
$schedulePeriod = new Monthly();
|
||||
$schedulePeriod->setDayOfWeek(3, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
parent::__construct($this, 'update', null, $schedulePeriod, Task::LOWEST_PRIORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to download new location & ISP GeoIP databases and
|
||||
* replace the existing ones w/ them.
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
Option::set(self::LAST_RUN_TIME_OPTION_NAME, Date::factory('today')->getTimestamp());
|
||||
|
||||
$locUrl = Option::get(self::LOC_URL_OPTION_NAME);
|
||||
if (!empty($locUrl)) {
|
||||
$this->downloadFile('loc', $locUrl);
|
||||
}
|
||||
|
||||
$ispUrl = Option::get(self::ISP_URL_OPTION_NAME);
|
||||
if (!empty($ispUrl)) {
|
||||
$this->downloadFile('isp', $ispUrl);
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
// message will already be prefixed w/ 'GeoIP2AutoUpdater: '
|
||||
Log::error($ex);
|
||||
$this->performRedundantDbChecks();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$this->performRedundantDbChecks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a GeoIP 2 database archive, extracts the .mmdb file and overwrites the existing
|
||||
* old database.
|
||||
*
|
||||
* If something happens that causes the download to fail, no exception is thrown, but
|
||||
* an error is logged.
|
||||
*
|
||||
* @param string $dbType
|
||||
* @param string $url URL to the database to download. The type of database is determined
|
||||
* from this URL.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function downloadFile($dbType, $url)
|
||||
{
|
||||
$url = trim($url);
|
||||
|
||||
$ext = GeoIP2AutoUpdater::getGeoIPUrlExtension($url);
|
||||
|
||||
// NOTE: using the first item in $dbNames[$dbType] makes sure GeoLiteCity will be renamed to GeoIPCity
|
||||
$zippedFilename = LocationProviderGeoIp2::$dbNames[$dbType][0] . '.' . $ext;
|
||||
|
||||
$zippedOutputPath = LocationProviderGeoIp2::getPathForGeoIpDatabase($zippedFilename);
|
||||
|
||||
$url = self::removeDateFromUrl($url);
|
||||
|
||||
// download zipped file to misc dir
|
||||
try {
|
||||
$success = Http::sendHttpRequest($url, $timeout = 3600, $userAgent = null, $zippedOutputPath);
|
||||
} catch (Exception $ex) {
|
||||
throw new Exception("GeoIP2AutoUpdater: failed to download '$url' to "
|
||||
. "'$zippedOutputPath': " . $ex->getMessage());
|
||||
}
|
||||
|
||||
if ($success !== true) {
|
||||
throw new Exception("GeoIP2AutoUpdater: failed to download '$url' to "
|
||||
. "'$zippedOutputPath'! (Unknown error)");
|
||||
}
|
||||
|
||||
Log::info("GeoIP2AutoUpdater: successfully downloaded '%s'", $url);
|
||||
|
||||
try {
|
||||
self::unzipDownloadedFile($zippedOutputPath, $dbType, $unlink = true);
|
||||
} catch (Exception $ex) {
|
||||
throw new Exception("GeoIP2AutoUpdater: failed to unzip '$zippedOutputPath' after "
|
||||
. "downloading " . "'$url': " . $ex->getMessage());
|
||||
}
|
||||
|
||||
Log::info("GeoIP2AutoUpdater: successfully updated GeoIP 2 database '%s'", $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzips a downloaded GeoIP 2 database. Only unzips .gz & .tar.gz files.
|
||||
*
|
||||
* @param string $path Path to zipped file.
|
||||
* @param bool $unlink Whether to unlink archive or not.
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function unzipDownloadedFile($path, $dbType, $unlink = false)
|
||||
{
|
||||
// extract file
|
||||
if (substr($path, -7, 7) == '.tar.gz') {
|
||||
// find the .dat file in the tar archive
|
||||
$unzip = Unzip::factory('tar.gz', $path);
|
||||
$content = $unzip->listContent();
|
||||
|
||||
if (empty($content)) {
|
||||
throw new Exception(Piwik::translate('UserCountry_CannotListContent',
|
||||
array("'$path'", $unzip->errorInfo())));
|
||||
}
|
||||
|
||||
$fileToExtract = null;
|
||||
foreach ($content as $info) {
|
||||
$archivedPath = $info['filename'];
|
||||
if (in_array(basename($archivedPath), LocationProviderGeoIp2::$dbNames[$dbType])) {
|
||||
$fileToExtract = $archivedPath;
|
||||
}
|
||||
}
|
||||
|
||||
if ($fileToExtract === null) {
|
||||
throw new Exception(Piwik::translate('GeoIp2_CannotFindGeoIPDatabaseInArchive',
|
||||
array("'$path'")));
|
||||
}
|
||||
|
||||
// extract JUST the .dat file
|
||||
$unzipped = $unzip->extractInString($fileToExtract);
|
||||
|
||||
if (empty($unzipped)) {
|
||||
throw new Exception(Piwik::translate('GeoIp2_CannotUnzipGeoIPFile',
|
||||
array("'$path'", $unzip->errorInfo())));
|
||||
}
|
||||
|
||||
$dbFilename = basename($fileToExtract);
|
||||
$tempFilename = $dbFilename . '.new';
|
||||
$outputPath = LocationProviderGeoIp2::getPathForGeoIpDatabase($tempFilename);
|
||||
|
||||
// write unzipped to file
|
||||
$fd = fopen($outputPath, 'wb');
|
||||
fwrite($fd, $unzipped);
|
||||
fclose($fd);
|
||||
} else if (substr($path, -3, 3) == '.gz') {
|
||||
$unzip = Unzip::factory('gz', $path);
|
||||
|
||||
$dbFilename = basename($path);
|
||||
$tempFilename = $dbFilename . '.new';
|
||||
$outputPath = LocationProviderGeoIp2::getPathForGeoIpDatabase($tempFilename);
|
||||
|
||||
$success = $unzip->extract($outputPath);
|
||||
|
||||
if ($success !== true) {
|
||||
throw new Exception(Piwik::translate('UserCountry_CannotUnzipDatFile',
|
||||
array("'$path'", $unzip->errorInfo())));
|
||||
}
|
||||
} else {
|
||||
$ext = end(explode(basename($path), '.', 2));
|
||||
throw new Exception(Piwik::translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
|
||||
}
|
||||
|
||||
try {
|
||||
// test that the new archive is a valid GeoIP 2 database
|
||||
if (empty($dbFilename) || false === LocationProviderGeoIp2::getGeoIPDatabaseTypeFromFilename($dbFilename)) {
|
||||
throw new Exception("Unexpected GeoIP 2 archive file name '$path'.");
|
||||
}
|
||||
|
||||
$customDbNames = array(
|
||||
'loc' => array(),
|
||||
'isp' => array()
|
||||
);
|
||||
$customDbNames[$dbType] = array($tempFilename);
|
||||
|
||||
$phpProvider = new Php($customDbNames);
|
||||
|
||||
try {
|
||||
$location = $phpProvider->getLocation(array('ip' => LocationProviderGeoIp2::TEST_IP));
|
||||
} catch (\Exception $e) {
|
||||
Log::info("GeoIP2AutoUpdater: Encountered exception when testing newly downloaded" .
|
||||
" GeoIP 2 database: %s", $e->getMessage());
|
||||
|
||||
throw new Exception(Piwik::translate('UserCountry_ThisUrlIsNotAValidGeoIPDB'));
|
||||
}
|
||||
|
||||
if (empty($location)) {
|
||||
throw new Exception(Piwik::translate('UserCountry_ThisUrlIsNotAValidGeoIPDB'));
|
||||
}
|
||||
|
||||
// delete the existing GeoIP database (if any) and rename the downloaded file
|
||||
$oldDbFile = LocationProviderGeoIp2::getPathForGeoIpDatabase($dbFilename);
|
||||
if (file_exists($oldDbFile)) {
|
||||
unlink($oldDbFile);
|
||||
}
|
||||
|
||||
$tempFile = LocationProviderGeoIp2::getPathForGeoIpDatabase($tempFilename);
|
||||
if (@rename($tempFile, $oldDbFile) !== true) {
|
||||
//In case the $tempfile cannot be renamed, we copy the file.
|
||||
copy($tempFile, $oldDbFile);
|
||||
unlink($tempFile);
|
||||
}
|
||||
|
||||
// delete original archive
|
||||
if ($unlink) {
|
||||
unlink($path);
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
// remove downloaded files
|
||||
if (file_exists($outputPath)) {
|
||||
unlink($outputPath);
|
||||
}
|
||||
unlink($path);
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the options used by this class based on query parameter values.
|
||||
*
|
||||
* See setUpdaterOptions for query params used.
|
||||
*/
|
||||
public static function setUpdaterOptionsFromUrl()
|
||||
{
|
||||
$options = array(
|
||||
'loc' => Common::getRequestVar('loc_db', false, 'string'),
|
||||
'isp' => Common::getRequestVar('isp_db', false, 'string'),
|
||||
'period' => Common::getRequestVar('period', false, 'string'),
|
||||
);
|
||||
|
||||
foreach (self::$urlOptions as $optionKey => $optionName) {
|
||||
$options[$optionKey] = Common::unsanitizeInputValue($options[$optionKey]); // URLs should not be sanitized
|
||||
}
|
||||
|
||||
self::setUpdaterOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the options used by this class based on the elements in $options.
|
||||
*
|
||||
* The following elements of $options are used:
|
||||
* 'loc' - URL for location database.
|
||||
* 'isp' - URL for ISP database.
|
||||
* 'org' - URL for Organization database.
|
||||
* 'period' - 'weekly' or 'monthly'. When to run the updates.
|
||||
*
|
||||
* @param array $options
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function setUpdaterOptions($options)
|
||||
{
|
||||
// set url options
|
||||
foreach (self::$urlOptions as $optionKey => $optionName) {
|
||||
if (!isset($options[$optionKey])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = $options[$optionKey];
|
||||
$url = self::removeDateFromUrl($url);
|
||||
|
||||
Option::set($optionName, $url);
|
||||
}
|
||||
|
||||
// set period option
|
||||
if (!empty($options['period'])) {
|
||||
$period = $options['period'];
|
||||
|
||||
if ($period != self::SCHEDULE_PERIOD_MONTHLY
|
||||
&& $period != self::SCHEDULE_PERIOD_WEEKLY
|
||||
) {
|
||||
throw new Exception(Piwik::translate(
|
||||
'UserCountry_InvalidGeoIPUpdatePeriod',
|
||||
array("'$period'", "'" . self::SCHEDULE_PERIOD_MONTHLY . "', '" . self::SCHEDULE_PERIOD_WEEKLY . "'")
|
||||
));
|
||||
}
|
||||
|
||||
Option::set(self::SCHEDULE_PERIOD_OPTION_NAME, $period);
|
||||
|
||||
/** @var Scheduler $scheduler */
|
||||
$scheduler = StaticContainer::getContainer()->get('Piwik\Scheduler\Scheduler');
|
||||
|
||||
$scheduler->rescheduleTaskAndRunTomorrow(new GeoIP2AutoUpdater());
|
||||
}
|
||||
|
||||
// clear option for GeoIP as not needed if GeoIP2 is set up
|
||||
GeoIPAutoUpdater::clearOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the auto-updater is setup to update at least one type of
|
||||
* database. False if otherwise.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUpdaterSetup()
|
||||
{
|
||||
if (Option::get(self::LOC_URL_OPTION_NAME) !== false
|
||||
|| Option::get(self::ISP_URL_OPTION_NAME) !== false
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the URLs used to update various GeoIP 2 database files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getConfiguredUrls()
|
||||
{
|
||||
$result = array();
|
||||
foreach (self::$urlOptions as $key => $optionName) {
|
||||
$result[$key] = Option::get($optionName);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the confiured URL (if any) for a type of database.
|
||||
*
|
||||
* @param string $key 'loc', 'isp' or 'org'
|
||||
* @throws Exception
|
||||
* @return string|false
|
||||
*/
|
||||
public static function getConfiguredUrl($key)
|
||||
{
|
||||
if (empty(self::$urlOptions[$key])) {
|
||||
throw new Exception("Invalid key $key");
|
||||
}
|
||||
$url = Option::get(self::$urlOptions[$key]);
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a GeoIP 2 database update.
|
||||
*/
|
||||
public static function performUpdate()
|
||||
{
|
||||
$instance = new GeoIP2AutoUpdater();
|
||||
$instance->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured update period, either 'week' or 'month'. Defaults to
|
||||
* 'month'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getSchedulePeriod()
|
||||
{
|
||||
$period = Option::get(self::SCHEDULE_PERIOD_OPTION_NAME);
|
||||
if ($period === false) {
|
||||
$period = self::SCHEDULE_PERIOD_MONTHLY;
|
||||
}
|
||||
return $period;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of strings for GeoIP 2 databases that have update URLs configured, but
|
||||
* are not present in the misc directory. Each string is a key describing the type of
|
||||
* database (ie, 'loc', 'isp' or 'org').
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getMissingDatabases()
|
||||
{
|
||||
$result = array();
|
||||
foreach (self::getConfiguredUrls() as $key => $url) {
|
||||
if (!empty($url)) {
|
||||
// if a database of the type does not exist, but there's a url to update, then
|
||||
// a database is missing
|
||||
$path = LocationProviderGeoIp2::getPathToGeoIpDatabase(
|
||||
LocationProviderGeoIp2::$dbNames[$key]);
|
||||
if ($path === false) {
|
||||
$result[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of a URL used to update a GeoIP 2 database, if it can be found.
|
||||
*/
|
||||
public static function getGeoIPUrlExtension($url)
|
||||
{
|
||||
// check for &suffix= query param that is special to MaxMind URLs
|
||||
if (preg_match('/suffix=([^&]+)/', $url, $matches)) {
|
||||
$ext = $matches[1];
|
||||
} else {
|
||||
// use basename of url
|
||||
$filenameParts = explode('.', basename($url), 2);
|
||||
if (count($filenameParts) > 1) {
|
||||
$ext = end($filenameParts);
|
||||
} else {
|
||||
$ext = reset($filenameParts);
|
||||
}
|
||||
}
|
||||
|
||||
self::checkForSupportedArchiveType($ext);
|
||||
|
||||
return $ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid downloading archive types we don't support. No point in downloading it,
|
||||
* if we can't unzip it...
|
||||
*
|
||||
* @param string $ext The URL file's extension.
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function checkForSupportedArchiveType($ext)
|
||||
{
|
||||
if ($ext != 'tar.gz'
|
||||
&& $ext != 'gz'
|
||||
&& $ext != 'mmdb.gz'
|
||||
) {
|
||||
throw new \Exception(Piwik::translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that checks if geolocation works with each installed database,
|
||||
* and if one or more doesn't, they are renamed to make sure tracking will work.
|
||||
* This is a safety measure used to make sure tracking isn't affected if strange
|
||||
* update errors occur.
|
||||
*
|
||||
* Databases are renamed to ${original}.broken .
|
||||
*
|
||||
* Note: method is protected for testability.
|
||||
*
|
||||
* @param $logErrors - only used to hide error logs during tests
|
||||
*/
|
||||
protected function performRedundantDbChecks($logErrors = true)
|
||||
{
|
||||
$databaseTypes = array_keys(LocationProviderGeoIp2::$dbNames);
|
||||
|
||||
foreach ($databaseTypes as $type) {
|
||||
$customNames = array(
|
||||
'loc' => array(),
|
||||
'isp' => array(),
|
||||
'org' => array()
|
||||
);
|
||||
$customNames[$type] = LocationProviderGeoIp2::$dbNames[$type];
|
||||
|
||||
// create provider that only uses the DB type we're testing
|
||||
$provider = new Php($customNames);
|
||||
|
||||
// test the provider. on error, we rename the broken DB.
|
||||
try {
|
||||
$location = $provider->getLocation(array('ip' => LocationProviderGeoIp2::TEST_IP));
|
||||
} catch (\Exception $e) {
|
||||
if($logErrors) {
|
||||
Log::error("GeoIP2AutoUpdater: Encountered exception when performing redundant tests on GeoIP2 "
|
||||
. "%s database: %s: %s", $type, $e->getMessage());
|
||||
}
|
||||
|
||||
// get the current filename for the DB and an available new one to rename it to
|
||||
list($oldPath, $newPath) = $this->getOldAndNewPathsForBrokenDb($customNames[$type]);
|
||||
|
||||
// rename the DB so tracking will not fail
|
||||
if ($oldPath !== false
|
||||
&& $newPath !== false
|
||||
) {
|
||||
if (file_exists($newPath)) {
|
||||
unlink($newPath);
|
||||
}
|
||||
|
||||
rename($oldPath, $newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to a GeoIP 2 database and a path to rename it to if it's broken.
|
||||
*
|
||||
* @param array $possibleDbNames The possible names of the database.
|
||||
* @return array Array with two elements, the path to the existing database, and
|
||||
* the path to rename it to if it is broken. The second will end
|
||||
* with something like .broken .
|
||||
*/
|
||||
private function getOldAndNewPathsForBrokenDb($possibleDbNames)
|
||||
{
|
||||
$pathToDb = LocationProviderGeoIp2::getPathToGeoIpDatabase($possibleDbNames);
|
||||
$newPath = false;
|
||||
|
||||
if ($pathToDb !== false) {
|
||||
$newPath = $pathToDb . ".broken";
|
||||
}
|
||||
|
||||
return array($pathToDb, $newPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom PHP error handler used to catch any PHP errors that occur when
|
||||
* testing a downloaded GeoIP 2 file.
|
||||
*
|
||||
* If we download a file that is supposed to be a GeoIP 2 database, we need to make
|
||||
* sure it is one. This is done simply by attempting to use it. If this fails, it
|
||||
* will most of the time fail as a PHP error, which we catch w/ this function
|
||||
* after it is passed to set_error_handler.
|
||||
*
|
||||
* The PHP error is stored in self::$unzipPhpError.
|
||||
*
|
||||
* @param int $errno
|
||||
* @param string $errstr
|
||||
* @param string $errfile
|
||||
* @param int $errline
|
||||
*/
|
||||
public static function catchGeoIPError($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
self::$unzipPhpError = array($errno, $errstr, $errfile, $errline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the auto updater was last run.
|
||||
*
|
||||
* @return Date|false
|
||||
*/
|
||||
public static function getLastRunTime()
|
||||
{
|
||||
$timestamp = Option::get(self::LAST_RUN_TIME_OPTION_NAME);
|
||||
return $timestamp === false ? false : Date::factory((int)$timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the &date=... query parameter if present in the URL. This query parameter
|
||||
* is in MaxMind URLs by default and will force the download of an old database.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
private static function removeDateFromUrl($url)
|
||||
{
|
||||
return preg_replace("/&date=[^&#]*/", '', $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next scheduled time for the auto updater.
|
||||
*
|
||||
* @return Date|false
|
||||
*/
|
||||
public static function getNextRunTime()
|
||||
{
|
||||
$task = new GeoIP2AutoUpdater();
|
||||
|
||||
$timetable = new Timetable();
|
||||
return $timetable->getScheduledTaskTime($task->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link Piwik\Scheduler\Schedule\Schedule::getRescheduledTime()}.
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
$nextScheduledTime = parent::getRescheduledTime();
|
||||
|
||||
// if a geoip 2 database is out of date, run the updater as soon as possible
|
||||
if ($this->isAtLeastOneGeoIpDbOutOfDate($nextScheduledTime)) {
|
||||
return time();
|
||||
}
|
||||
|
||||
return $nextScheduledTime;
|
||||
}
|
||||
|
||||
private function isAtLeastOneGeoIpDbOutOfDate($rescheduledTime)
|
||||
{
|
||||
$previousScheduledRuntime = $this->getPreviousScheduledTime($rescheduledTime)->setTime("00:00:00")->getTimestamp();
|
||||
|
||||
foreach (LocationProviderGeoIp2::$dbNames as $type => $dbNames) {
|
||||
$dbUrl = Option::get(self::$urlOptions[$type]);
|
||||
$dbPath = LocationProviderGeoIp2::getPathToGeoIpDatabase($dbNames);
|
||||
|
||||
// if there is a URL for this DB type and the GeoIP 2 DB file's last modified time is before
|
||||
// the time the updater should have been previously run, then **the file is out of date**
|
||||
if (!empty($dbUrl)
|
||||
&& filemtime($dbPath) < $previousScheduledRuntime
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getPreviousScheduledTime($rescheduledTime)
|
||||
{
|
||||
$updaterPeriod = self::getSchedulePeriod();
|
||||
|
||||
if ($updaterPeriod == self::SCHEDULE_PERIOD_WEEKLY) {
|
||||
return Date::factory($rescheduledTime)->subWeek(1);
|
||||
} else if ($updaterPeriod == self::SCHEDULE_PERIOD_MONTHLY) {
|
||||
return Date::factory($rescheduledTime)->subMonth(1);
|
||||
}
|
||||
throw new Exception("Unknown GeoIP 2 updater period found in database: %s", $updaterPeriod);
|
||||
}
|
||||
}
|
30
msd2/tracking/piwik/plugins/GeoIp2/GeoIp2.php
Normal file
30
msd2/tracking/piwik/plugins/GeoIp2/GeoIp2.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?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;
|
||||
|
||||
use Piwik\Plugins\UserCountry\LocationProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class GeoIp2 extends \Piwik\Plugin
|
||||
{
|
||||
public function isTrackerPlugin()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function deactivate()
|
||||
{
|
||||
// switch to default provider if GeoIP2 provider was in use
|
||||
if (LocationProvider::getCurrentProvider() instanceof \Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2) {
|
||||
LocationProvider::setCurrentProvider(LocationProvider\DefaultProvider::ID);
|
||||
}
|
||||
}
|
||||
}
|
265
msd2/tracking/piwik/plugins/GeoIp2/LocationProvider/GeoIp2.php
Normal file
265
msd2/tracking/piwik/plugins/GeoIp2/LocationProvider/GeoIp2.php
Normal file
@ -0,0 +1,265 @@
|
||||
<?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\Container\StaticContainer;
|
||||
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';
|
||||
|
||||
/**
|
||||
* 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-City-Africa.mmdb', 'GeoIP2-City-Asia-Pacific.mmdb', 'GeoIP2-City-Europe.mmdb', 'GeoIP2-City-North-America.mmdb', 'GeoIP2-City-South-America.mmdb', 'GeoIP2-Enterprise.mmdb', 'GeoIP2-Country.mmdb', 'GeoLite2-City.mmdb', 'GeoLite2-Country.mmdb'),
|
||||
'isp' => array('GeoIP2-ISP.mmdb', 'GeoLite2-ASN.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 StaticContainer::get('path.geoip2') . $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();
|
||||
}
|
||||
}
|
@ -0,0 +1,335 @@
|
||||
<?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\GeoIp2;
|
||||
|
||||
use GeoIp2\Database\Reader;
|
||||
use GeoIp2\Exception\AddressNotFoundException;
|
||||
use MaxMind\Db\Reader\InvalidDatabaseException;
|
||||
use Piwik\Log;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
|
||||
use Piwik\Plugins\Marketplace\Api\Exception;
|
||||
|
||||
/**
|
||||
* A LocationProvider that uses the PHP implementation of GeoIP 2.
|
||||
*
|
||||
*/
|
||||
class Php extends GeoIp2
|
||||
{
|
||||
const ID = 'geoip2php';
|
||||
const TITLE = 'GeoIP 2 (Php)';
|
||||
|
||||
/**
|
||||
* The GeoIP2 reader instances used. This array will contain at most two
|
||||
* of them: one for location info and one for ISP info
|
||||
*
|
||||
* Each instance is mapped w/ one of the following keys: 'loc', 'isp'
|
||||
*
|
||||
* @var array of GeoIP instances
|
||||
*/
|
||||
private $readerCache = array();
|
||||
|
||||
/**
|
||||
* Possible filenames for each type of GeoIP database. When looking for a database
|
||||
* file in the 'misc' subdirectory, files with these names will be looked for.
|
||||
*
|
||||
* This variable is an array mapping either the 'loc' or 'isp' strings with
|
||||
* an array of filenames.
|
||||
*
|
||||
* By default, this will be set to GeoIp2::$dbNames.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $customDbNames;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array|bool $customDbNames The possible filenames for each type of GeoIP database.
|
||||
* eg array(
|
||||
* 'loc' => array('GeoLite2-City.mmdb'),
|
||||
* 'isp' => array('GeoIP2.mmdb', 'GeoIP2-ISP.mmdb')
|
||||
* )
|
||||
* If a key is missing (or the parameter not supplied), then the
|
||||
* default database names are used.
|
||||
*/
|
||||
public function __construct($customDbNames = false)
|
||||
{
|
||||
$this->customDbNames = parent::$dbNames;
|
||||
if ($customDbNames !== false) {
|
||||
foreach ($this->customDbNames as $key => $names) {
|
||||
if (isset($customDbNames[$key])) {
|
||||
$this->customDbNames[$key] = $customDbNames[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a GeoIP 2 database to get a visitor's location based on their IP address.
|
||||
*
|
||||
* This function will return different results based on the data used. If a city
|
||||
* database is used, it may return the country code, region code, city name, area
|
||||
* code, latitude, longitude and postal code of the visitor.
|
||||
*
|
||||
* Alternatively, if used with a country database, only the country code will be
|
||||
* returned.
|
||||
*
|
||||
* @param array $info Must have an 'ip' field.
|
||||
* @return array|false
|
||||
*/
|
||||
public function getLocation($info)
|
||||
{
|
||||
$ip = $this->getIpFromInfo($info);
|
||||
|
||||
if (empty($ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$reader = $this->getGeoIpInstance('loc');
|
||||
if ($reader) {
|
||||
try {
|
||||
switch ($reader->metadata()->databaseType) {
|
||||
case 'GeoLite2-Country':
|
||||
case 'GeoIP2-Country':
|
||||
$lookupResult = $reader->country($ip);
|
||||
$this->setCountryResults($lookupResult, $result);
|
||||
break;
|
||||
case 'GeoIP2-Enterprise':
|
||||
case 'GeoLite2-City':
|
||||
case 'GeoIP2-City':
|
||||
case 'GeoIP2-City-Africa':
|
||||
case 'GeoIP2-City-Asia-Pacific':
|
||||
case 'GeoIP2-City-Europe':
|
||||
case 'GeoIP2-City-North-America':
|
||||
case 'GeoIP2-City-South-America':
|
||||
if ($reader->metadata()->databaseType === 'GeoIP2-Enterprise') {
|
||||
$lookupResult = $reader->enterprise($ip);
|
||||
} else {
|
||||
$lookupResult = $reader->city($ip);
|
||||
}
|
||||
$this->setCountryResults($lookupResult, $result);
|
||||
$this->setCityResults($lookupResult, $result);
|
||||
break;
|
||||
default: // unknown database type log warning
|
||||
Log::warning("Found unrecognized database type: %s", $reader->metadata()->databaseType);
|
||||
break;
|
||||
}
|
||||
} catch (AddressNotFoundException $e) {
|
||||
// ignore - do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: ISP & ORG require commercial dbs to test.
|
||||
$ispGeoIp = $this->getGeoIpInstance($key = 'isp');
|
||||
if ($ispGeoIp) {
|
||||
try {
|
||||
switch ($ispGeoIp->metadata()->databaseType) {
|
||||
case 'GeoIP2-ISP':
|
||||
$lookupResult = $ispGeoIp->isp($ip);
|
||||
$result[self::ISP_KEY] = $lookupResult->isp;
|
||||
$result[self::ORG_KEY] = $lookupResult->organization;
|
||||
break;
|
||||
case 'GeoLite2-ASN':
|
||||
$lookupResult = $ispGeoIp->asn($ip);
|
||||
$result[self::ISP_KEY] = $lookupResult->autonomousSystemOrganization;
|
||||
$result[self::ORG_KEY] = $lookupResult->autonomousSystemOrganization;
|
||||
break;
|
||||
}
|
||||
} catch (AddressNotFoundException $e) {
|
||||
// ignore - do nothing
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->completeLocationResult($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function setCountryResults($lookupResult, &$result)
|
||||
{
|
||||
$result[self::CONTINENT_NAME_KEY] = $lookupResult->continent->name;
|
||||
$result[self::CONTINENT_CODE_KEY] = strtoupper($lookupResult->continent->code);
|
||||
$result[self::COUNTRY_CODE_KEY] = strtoupper($lookupResult->country->isoCode);
|
||||
$result[self::COUNTRY_NAME_KEY] = $lookupResult->country->name;
|
||||
}
|
||||
|
||||
protected function setCityResults($lookupResult, &$result)
|
||||
{
|
||||
$result[self::CITY_NAME_KEY] = $lookupResult->city->name;
|
||||
$result[self::LATITUDE_KEY] = $lookupResult->location->latitude;
|
||||
$result[self::LONGITUDE_KEY] = $lookupResult->location->longitude;
|
||||
$result[self::POSTAL_CODE_KEY] = $lookupResult->postal->code;
|
||||
if (is_array($lookupResult->subdivisions) && count($lookupResult->subdivisions) > 0) {
|
||||
$subdivisions = $lookupResult->subdivisions;
|
||||
$subdivision = $this->determinSubdivision($subdivisions, $result[self::COUNTRY_CODE_KEY]);
|
||||
$result[self::REGION_CODE_KEY] = strtoupper($subdivision->isoCode);
|
||||
$result[self::REGION_NAME_KEY] = $subdivision->name;
|
||||
}
|
||||
}
|
||||
|
||||
protected function determinSubdivision($subdivisions, $countryCode)
|
||||
{
|
||||
if (in_array($countryCode, ['GB'])) {
|
||||
return end($subdivisions);
|
||||
}
|
||||
|
||||
return reset($subdivisions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this location provider is available. Piwik ships w/ the MaxMind
|
||||
* PHP library, so this provider is available if a location GeoIP database can be found.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
$path = self::getPathToGeoIpDatabase($this->customDbNames['loc']);
|
||||
return $path !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array describing the types of location information this provider will
|
||||
* return.
|
||||
*
|
||||
* The location info this provider supports depends on what GeoIP databases it can
|
||||
* find.
|
||||
*
|
||||
* This provider will always support country & continent information.
|
||||
*
|
||||
* If a region database is found, then region code & name information will be
|
||||
* supported.
|
||||
*
|
||||
* If a city database is found, then region code, region name, city name,
|
||||
* area code, latitude, longitude & postal code are all supported.
|
||||
*
|
||||
* If an ISP/organization database is found, ISP/organization information is supported.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedLocationInfo()
|
||||
{
|
||||
$result = array();
|
||||
|
||||
// country & continent info always available
|
||||
$result[self::CONTINENT_CODE_KEY] = true;
|
||||
$result[self::CONTINENT_NAME_KEY] = true;
|
||||
$result[self::COUNTRY_CODE_KEY] = true;
|
||||
$result[self::COUNTRY_NAME_KEY] = true;
|
||||
|
||||
$reader = $this->getGeoIpInstance($key = 'loc');
|
||||
if ($reader) {
|
||||
switch ($reader->metadata()->databaseType) {
|
||||
case 'GeoIP2-Enterprise':
|
||||
case 'GeoLite2-City':
|
||||
case 'GeoIP2-City':
|
||||
case 'GeoIP2-City-Africa':
|
||||
case 'GeoIP2-City-Asia-Pacific':
|
||||
case 'GeoIP2-City-Europe':
|
||||
case 'GeoIP2-City-North-America':
|
||||
case 'GeoIP2-City-South-America':
|
||||
$result[self::REGION_CODE_KEY] = true;
|
||||
$result[self::REGION_NAME_KEY] = true;
|
||||
$result[self::CITY_NAME_KEY] = true;
|
||||
$result[self::POSTAL_CODE_KEY] = true;
|
||||
$result[self::LATITUDE_KEY] = true;
|
||||
$result[self::LONGITUDE_KEY] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if isp info is available
|
||||
if ($this->getGeoIpInstance($key = 'isp')) {
|
||||
$result[self::ISP_KEY] = true;
|
||||
$result[self::ORG_KEY] = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about this location provider. Contains an id, title & description:
|
||||
*
|
||||
* array(
|
||||
* 'id' => 'geoip2_php',
|
||||
* 'title' => '...',
|
||||
* 'description' => '...'
|
||||
* );
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getInfo()
|
||||
{
|
||||
$desc = Piwik::translate('GeoIp2_LocationProviderDesc_Php') . '<br/><br/>';
|
||||
|
||||
if (extension_loaded('maxminddb')) {
|
||||
$desc .= Piwik::translate('GeoIp2_LocationProviderDesc_Php_WithExtension',
|
||||
array('<strong>', '</strong>'));
|
||||
}
|
||||
|
||||
$installDocs = '<a rel="noreferrer" target="_blank" href="https://matomo.org/faq/how-to/#faq_163">'
|
||||
. Piwik::translate('UserCountry_HowToInstallGeoIPDatabases')
|
||||
. '</a>';
|
||||
|
||||
$availableDatabaseTypes = array();
|
||||
if (self::getPathToGeoIpDatabase(['GeoIP2-City.mmdb', 'GeoIP2-City-Africa.mmdb', 'GeoIP2-City-Asia-Pacific.mmdb', 'GeoIP2-City-Europe.mmdb', 'GeoIP2-City-North-America.mmdb', 'GeoIP2-City-South-America.mmdb', 'GeoIP2-Enterprise.mmdb', 'GeoLite2-City.mmdb']) !== false) {
|
||||
$availableDatabaseTypes[] = Piwik::translate('UserCountry_City');
|
||||
}
|
||||
if (self::getPathToGeoIpDatabase(['GeoIP2-Country.mmdb', 'GeoLite2-Country.mmdb']) !== false) {
|
||||
$availableDatabaseTypes[] = Piwik::translate('UserCountry_Country');
|
||||
}
|
||||
if (self::getPathToGeoIpDatabase(self::$dbNames['isp']) !== false) {
|
||||
$availableDatabaseTypes[] = Piwik::translate('UserCountry_ISPDatabase');
|
||||
}
|
||||
|
||||
if (!empty($availableDatabaseTypes)) {
|
||||
$extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>: '
|
||||
. Piwik::translate('UserCountry_GeoIPImplHasAccessTo') . ': <strong>'
|
||||
. implode(', ', $availableDatabaseTypes) . '</strong>.';
|
||||
} else {
|
||||
$extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>: '
|
||||
. Piwik::translate('UserCountry_GeoIPNoDatabaseFound');
|
||||
}
|
||||
|
||||
return array('id' => self::ID,
|
||||
'title' => self::TITLE,
|
||||
'description' => $desc,
|
||||
'install_docs' => $installDocs,
|
||||
'extra_message' => $extraMessage,
|
||||
'order' => 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a GeoIP2 reader instance. Creates it if necessary.
|
||||
*
|
||||
* @param string $key 'loc' or 'isp'. Determines the type of GeoIP database
|
||||
* to load.
|
||||
* @return Reader|false
|
||||
*/
|
||||
private function getGeoIpInstance($key)
|
||||
{
|
||||
if (empty($this->readerCache[$key])) {
|
||||
$pathToDb = self::getPathToGeoIpDatabase($this->customDbNames[$key]);
|
||||
if ($pathToDb !== false) {
|
||||
try {
|
||||
$this->readerCache[$key] = new Reader($pathToDb);
|
||||
} catch (InvalidDatabaseException $e) {
|
||||
// ignore invalid database exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return empty($this->readerCache[$key]) ? false : $this->readerCache[$key];
|
||||
}
|
||||
}
|
@ -0,0 +1,343 @@
|
||||
<?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\GeoIp2;
|
||||
|
||||
use Piwik\Cache;
|
||||
use Piwik\Common;
|
||||
use Piwik\IP;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
|
||||
use Piwik\Plugins\UserCountry\LocationProvider;
|
||||
use Piwik\Plugins\GeoIp2\SystemSettings;
|
||||
use Piwik\Url;
|
||||
|
||||
/**
|
||||
* A LocationProvider that uses an GeoIP 2 module installed in an HTTP Server.
|
||||
*
|
||||
* To make this provider available, make sure mod_maxminddb / ngx_http_geoip2_module installed and active
|
||||
*/
|
||||
class ServerModule extends GeoIp2
|
||||
{
|
||||
const ID = 'geoip2server';
|
||||
const TITLE = 'GeoIP 2 (%s)';
|
||||
|
||||
public static $defaultGeoIpServerVars = array(
|
||||
parent::CONTINENT_CODE_KEY => 'MM_CONTINENT_CODE',
|
||||
parent::CONTINENT_NAME_KEY => 'MM_CONTINENT_NAME',
|
||||
parent::COUNTRY_CODE_KEY => 'MM_COUNTRY_CODE',
|
||||
parent::COUNTRY_NAME_KEY => 'MM_COUNTRY_NAME',
|
||||
parent::REGION_CODE_KEY => 'MM_REGION_CODE',
|
||||
parent::REGION_NAME_KEY => 'MM_REGION_NAME',
|
||||
parent::LATITUDE_KEY => 'MM_LATITUDE',
|
||||
parent::LONGITUDE_KEY => 'MM_LONGITUDE',
|
||||
parent::POSTAL_CODE_KEY => 'MM_POSTAL_CODE',
|
||||
parent::CITY_NAME_KEY => 'MM_CITY_NAME',
|
||||
parent::ISP_KEY => 'MM_ISP',
|
||||
parent::ORG_KEY => 'MM_ORG',
|
||||
);
|
||||
|
||||
/**
|
||||
* Uses a GeoIP 2 database to get a visitor's location based on their IP address.
|
||||
*
|
||||
* This function will return different results based on the data used and based
|
||||
* on how the GeoIP 2 module is configured.
|
||||
*
|
||||
* If a region database is used, it may return the country code, region code,
|
||||
* city name, area code, latitude, longitude and postal code of the visitor.
|
||||
*
|
||||
* Alternatively, only the country code may be returned for another database.
|
||||
*
|
||||
* If your HTTP server is not configured to include all GeoIP information, some
|
||||
* information will not be available to Piwik.
|
||||
*
|
||||
* @param array $info Must have an 'ip' field.
|
||||
* @return array
|
||||
*/
|
||||
public function getLocation($info)
|
||||
{
|
||||
$ip = $this->getIpFromInfo($info);
|
||||
|
||||
// geoip modules that are built into servers can't use a forced IP. in this case we try
|
||||
// to fallback to another version.
|
||||
$myIP = IP::getIpFromHeader();
|
||||
if (!self::isSameOrAnonymizedIp($ip, $myIP)
|
||||
&& (!isset($info['disable_fallbacks'])
|
||||
|| !$info['disable_fallbacks'])
|
||||
) {
|
||||
Common::printDebug("The request is for IP address: " . $info['ip'] . " but your IP is: $myIP. GeoIP 2 (Server Module) does not support this use case... ");
|
||||
$fallbacks = array(
|
||||
Php::ID
|
||||
);
|
||||
foreach ($fallbacks as $fallbackProviderId) {
|
||||
$otherProvider = LocationProvider::getProviderById($fallbackProviderId);
|
||||
if ($otherProvider) {
|
||||
Common::printDebug("Used $fallbackProviderId to detect this visitor IP");
|
||||
return $otherProvider->getLocation($info);
|
||||
}
|
||||
}
|
||||
Common::printDebug("FAILED to lookup the geo location of this IP address, as no fallback location providers is configured.");
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach (self::getGeoIpServerVars() as $resultKey => $geoipVarName) {
|
||||
if (!empty($_SERVER[$geoipVarName])) {
|
||||
$result[$resultKey] = $_SERVER[$geoipVarName];
|
||||
}
|
||||
}
|
||||
$this->completeLocationResult($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array describing the types of location information this provider will
|
||||
* return.
|
||||
*
|
||||
* There's no way to tell exactly what database the HTTP server is using, so we just
|
||||
* assume country and continent information is available. This can make diagnostics
|
||||
* a bit more difficult, unfortunately.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedLocationInfo()
|
||||
{
|
||||
$result = array();
|
||||
|
||||
// assume country info is always available. it's an error if it's not.
|
||||
$result[self::CONTINENT_CODE_KEY] = true;
|
||||
$result[self::CONTINENT_NAME_KEY] = true;
|
||||
$result[self::COUNTRY_CODE_KEY] = true;
|
||||
$result[self::COUNTRY_NAME_KEY] = true;
|
||||
|
||||
$result[self::REGION_CODE_KEY] = array_key_exists(self::getGeoIpServerVars(self::REGION_CODE_KEY), $_SERVER);
|
||||
$result[self::REGION_NAME_KEY] = array_key_exists(self::getGeoIpServerVars(self::REGION_NAME_KEY), $_SERVER);
|
||||
$result[self::LATITUDE_KEY] = array_key_exists(self::getGeoIpServerVars(self::LATITUDE_KEY), $_SERVER);
|
||||
$result[self::LONGITUDE_KEY] = array_key_exists(self::getGeoIpServerVars(self::LONGITUDE_KEY), $_SERVER);
|
||||
$result[self::POSTAL_CODE_KEY] = array_key_exists(self::getGeoIpServerVars(self::POSTAL_CODE_KEY), $_SERVER);
|
||||
$result[self::CITY_NAME_KEY] = array_key_exists(self::getGeoIpServerVars(self::CITY_NAME_KEY), $_SERVER);
|
||||
$result[self::ISP_KEY] = array_key_exists(self::getGeoIpServerVars(self::ISP_KEY), $_SERVER);
|
||||
$result[self::ORG_KEY] = array_key_exists(self::getGeoIpServerVars(self::ORG_KEY), $_SERVER);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an mod_maxminddb has been installed and MMDB_ADDR server variable is defined.
|
||||
*
|
||||
* There's a special check for the Apache module, but we can't check specifically
|
||||
* for anything else.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
if (function_exists('apache_get_modules')) {
|
||||
foreach (apache_get_modules() as $name) {
|
||||
if (strpos($name, 'maxminddb') !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$settings = self::getGeoIpServerVars();
|
||||
|
||||
$available = array_key_exists($settings[self::CONTINENT_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::COUNTRY_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::REGION_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::CITY_NAME_KEY], $_SERVER);
|
||||
|
||||
if ($available) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if not available return message w/ extra info
|
||||
if (!function_exists('apache_get_modules')) {
|
||||
return Piwik::translate('General_Note') . ': ' . Piwik::translate('UserCountry_AssumingNonApache');
|
||||
}
|
||||
|
||||
$message = "<strong>" . Piwik::translate('General_Note') . ': '
|
||||
. Piwik::translate('UserCountry_FoundApacheModules')
|
||||
. "</strong>:<br/><br/>\n<ul style=\"list-style:disc;margin-left:24px\">\n";
|
||||
foreach (apache_get_modules() as $name) {
|
||||
$message .= "<li>$name</li>\n";
|
||||
}
|
||||
$message .= "</ul>";
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the MMDB_ADDR server variable is defined.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isWorking()
|
||||
{
|
||||
$settings = self::getGeoIpServerVars();
|
||||
|
||||
$available = array_key_exists($settings[self::CONTINENT_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::COUNTRY_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::REGION_CODE_KEY], $_SERVER)
|
||||
|| array_key_exists($settings[self::CITY_NAME_KEY], $_SERVER);
|
||||
|
||||
if (!$available) {
|
||||
return Piwik::translate("UserCountry_CannotFindGeoIPServerVar", $settings[self::COUNTRY_CODE_KEY] . ' $_SERVER');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about this location provider. Contains an id, title & description:
|
||||
*
|
||||
* array(
|
||||
* 'id' => 'geoip_serverbased',
|
||||
* 'title' => '...',
|
||||
* 'description' => '...'
|
||||
* );
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getInfo()
|
||||
{
|
||||
if (function_exists('apache_note')) {
|
||||
$serverDesc = 'Apache';
|
||||
} else {
|
||||
$serverDesc = Piwik::translate('UserCountry_HttpServerModule');
|
||||
}
|
||||
|
||||
$title = sprintf(self::TITLE, $serverDesc);
|
||||
|
||||
$desc = Piwik::translate('GeoIp2_LocationProviderDesc_ServerModule', array('<strong>', '</strong>'))
|
||||
. '<br/><br/>'
|
||||
. Piwik::translate('UserCountry_GeoIpLocationProviderDesc_ServerBasedAnonWarn')
|
||||
. '<br/><br/>'
|
||||
. Piwik::translate('GeoIp2_LocationProviderDesc_ServerModule2',
|
||||
array('<strong>', '</strong>', '<strong>', '</strong>'));
|
||||
|
||||
$installDocs =
|
||||
'<a rel="noreferrer" target="_blank" href="https://maxmind.github.io/mod_maxminddb/">'
|
||||
. Piwik::translate('UserCountry_HowToInstallApacheModule')
|
||||
. '</a><br/>'
|
||||
. '<a rel="noreferrer" target="_blank" href="https://github.com/leev/ngx_http_geoip2_module/blob/master/README.md#installing">'
|
||||
. Piwik::translate('UserCountry_HowToInstallNginxModule')
|
||||
. '</a>';
|
||||
|
||||
$geoipServerVars = array();
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (in_array($key, self::getGeoIpServerVars())) {
|
||||
$geoipServerVars[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($geoipServerVars)) {
|
||||
$extraMessage = '<strong>' . Piwik::translate('UserCountry_GeoIPNoServerVars', '$_SERVER') . '</strong>';
|
||||
} else {
|
||||
$extraMessage = '<strong>' . Piwik::translate('UserCountry_GeoIPServerVarsFound', '$_SERVER')
|
||||
. ":</strong><br/><br/>\n<ul style=\"list-style:disc;margin-left:24px\">\n";
|
||||
foreach ($geoipServerVars as $key) {
|
||||
$extraMessage .= '<li>' . $key . "</li>\n";
|
||||
}
|
||||
$extraMessage .= '</ul>';
|
||||
}
|
||||
|
||||
$configUrl = Url::getCurrentQueryStringWithParametersModified(array(
|
||||
'module' => 'CoreAdminHome', 'action' => 'generalSettings'
|
||||
));
|
||||
$extraMessage .= '<br />'.Piwik::translate('GeoIp2_GeoIPVariablesConfigurationHere', ['<a href="'.$configUrl.'">', '</a>']);
|
||||
|
||||
return array('id' => self::ID,
|
||||
'title' => $title,
|
||||
'description' => $desc,
|
||||
'order' => 3,
|
||||
'install_docs' => $installDocs,
|
||||
'extra_message' => $extraMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two IP addresses are the same or if the first is the anonymized
|
||||
* version of the other.
|
||||
*
|
||||
* @param string $ip
|
||||
* @param string $currentIp This IP should not be anonymized.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSameOrAnonymizedIp($ip, $currentIp)
|
||||
{
|
||||
$ip = array_reverse(explode('.', $ip));
|
||||
$currentIp = array_reverse(explode('.', $currentIp));
|
||||
|
||||
if (count($ip) != count($currentIp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($ip as $i => $byte) {
|
||||
if ($byte == 0) {
|
||||
$currentIp[$i] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ip as $i => $byte) {
|
||||
if ($byte != $currentIp[$i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns currently configured server variable name for given type
|
||||
*
|
||||
* @param string|null $type
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected static function getGeoIpServerVars($type = null)
|
||||
{
|
||||
$storedSettings = self::getSystemSettingsValues();
|
||||
|
||||
if ($type === null) {
|
||||
return $storedSettings;
|
||||
}
|
||||
|
||||
if (array_key_exists($type, $storedSettings)) {
|
||||
return $storedSettings[$type];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected static function getSystemSettingsValues()
|
||||
{
|
||||
$cacheKey = 'geoip2variables';
|
||||
|
||||
// use eager cache if this data needs to be available on every tracking request
|
||||
$cache = Cache::getEagerCache();
|
||||
|
||||
if ($cache->contains($cacheKey)) {
|
||||
return $cache->fetch($cacheKey);
|
||||
}
|
||||
|
||||
$settingValues = self::$defaultGeoIpServerVars; // preset with defaults
|
||||
|
||||
try {
|
||||
$systemSettings = new SystemSettings();
|
||||
|
||||
foreach ($systemSettings->geoIp2variables as $name => $setting) {
|
||||
$settingValues[$name] = $setting->getValue();
|
||||
}
|
||||
|
||||
$cache->save($cacheKey, $settingValues);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
return $settingValues;
|
||||
}
|
||||
}
|
54
msd2/tracking/piwik/plugins/GeoIp2/SystemSettings.php
Normal file
54
msd2/tracking/piwik/plugins/GeoIp2/SystemSettings.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?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;
|
||||
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2\ServerModule;
|
||||
use Piwik\Plugins\UserCountry\UserCountry;
|
||||
use Piwik\Settings\Setting;
|
||||
use Piwik\Settings\FieldConfig;
|
||||
|
||||
/**
|
||||
* Defines Settings for UserCountry.
|
||||
*/
|
||||
class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
|
||||
{
|
||||
/** @var Setting[] */
|
||||
public $geoIp2variables;
|
||||
|
||||
/** @var Setting */
|
||||
public $useCustomVars;
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$this->title = Piwik::translate('GeoIp2_ServerBasedVariablesConfiguration');
|
||||
|
||||
$geoIpAdminEnabled = UserCountry::isGeoLocationAdminEnabled();
|
||||
|
||||
$this->useCustomVars = $this->makeSetting('geoip2usecustom', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
|
||||
$field->title = Piwik::translate('GeoIp2_ShowCustomServerVariablesConfig');
|
||||
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
|
||||
});
|
||||
$this->useCustomVars->setIsWritableByCurrentUser($geoIpAdminEnabled);
|
||||
|
||||
foreach (ServerModule::$defaultGeoIpServerVars as $name => $value) {
|
||||
$this->geoIp2variables[$name] = $this->createGeoIp2ServerVarSetting($name, $value);
|
||||
$this->geoIp2variables[$name]->setIsWritableByCurrentUser($geoIpAdminEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
private function createGeoIp2ServerVarSetting($name, $defaultValue)
|
||||
{
|
||||
return $this->makeSetting('geoip2var_'.$name, $default = $defaultValue, FieldConfig::TYPE_STRING, function (FieldConfig $field) use ($name) {
|
||||
$field->title = Piwik::translate('GeoIp2_ServerVariableFor', '<strong>' . str_replace('_', ' ', $name) . '</strong>');
|
||||
$field->uiControl = FieldConfig::UI_CONTROL_TEXT;
|
||||
$field->condition = 'geoip2usecustom==1';
|
||||
});
|
||||
}
|
||||
}
|
23
msd2/tracking/piwik/plugins/GeoIp2/Tasks.php
Normal file
23
msd2/tracking/piwik/plugins/GeoIp2/Tasks.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?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;
|
||||
|
||||
use Piwik\Plugins\UserCountry\UserCountry;
|
||||
use Piwik\SettingsPiwik;
|
||||
|
||||
class Tasks extends \Piwik\Plugin\Tasks
|
||||
{
|
||||
public function schedule()
|
||||
{
|
||||
// add the auto updater task if GeoIP admin is enabled
|
||||
if (UserCountry::isGeoLocationAdminEnabled() && SettingsPiwik::isInternetEnabled() === true) {
|
||||
$this->scheduleTask(new GeoIP2AutoUpdater());
|
||||
}
|
||||
}
|
||||
}
|
5
msd2/tracking/piwik/plugins/GeoIp2/config/config.php
Normal file
5
msd2/tracking/piwik/plugins/GeoIp2/config/config.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'path.geoip2' => DI\string('{path.root}/misc/'),
|
||||
];
|
5
msd2/tracking/piwik/plugins/GeoIp2/config/test.php
Normal file
5
msd2/tracking/piwik/plugins/GeoIp2/config/test.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'path.geoip2' => DI\string('{path.root}/tests/lib/geoip-files/'),
|
||||
];
|
5476
msd2/tracking/piwik/plugins/GeoIp2/data/isoRegionNames.php
Normal file
5476
msd2/tracking/piwik/plugins/GeoIp2/data/isoRegionNames.php
Normal file
File diff suppressed because it is too large
Load Diff
4635
msd2/tracking/piwik/plugins/GeoIp2/data/regionMapping.php
Normal file
4635
msd2/tracking/piwik/plugins/GeoIp2/data/regionMapping.php
Normal file
File diff suppressed because it is too large
Load Diff
14
msd2/tracking/piwik/plugins/GeoIp2/lang/de.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/de.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Im TAR Archiv %1$s konnte keine gültige GeoIP Datenbank gefunden werden!",
|
||||
"CannotUnzipGeoIPFile": "Konnte GeoIP-Datei in %1$s nicht entpacken: %2$s",
|
||||
"PluginDescription": "Liefert GeoIP 2 Standorterkennungsdienste.",
|
||||
"LocationProviderDesc_Php": "Diese Art der Standortbestimmung ist am einfachsten zu installieren, da Sie keine Serverkonfiguration benötigt (Ideal für Shared Hosting!). Sie verwendet eine GeoIP2-Datenbank und die PHP-API von MaxMind um den Standort eines Besuchers genau zu bestimmen.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Dieser Standorterkennungsdienst wird durch die installierte %1$smaxminddb%2$s Erweiterung beschleunigt.",
|
||||
"LocationProviderDesc_ServerModule": "Diese Art der Standortbestimmung verwendet das GeoIP2-Modul das auf ihrem HTTP-Server installiert ist. Diese ist am schnellsten und genauesten, aber %1$skann nur bei normalem Browser-Tracking benutzt werden%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Falls Sie Protokolldateien oder andere Dinge importieren welche IP-Adressen enthalten sollten Sie die %3$sPHP GeoIP 2 Implementierung%4$s nutzen und die %1$smaxminddb Erweiterung%2$s installieren.",
|
||||
"ServerBasedVariablesConfiguration": "Einstellungen für die Servervariablen die vom GeoIP 2 HTTP-Server-Modul benutzt werden.",
|
||||
"GeoIPVariablesConfigurationHere": "Sie können benutze Servervariablen %1$shier%2$s konfigurieren.",
|
||||
"ServerVariableFor": "Servervariable für %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/el.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/el.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Δεν βρέθηκε έγκυρη βάση GeoIP στο αρχείο tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "Δεν ήταν δυνατή η αποσυμπίεση του αρχείου GeoIP στο %1$s: %2$s",
|
||||
"PluginDescription": "Δίνει τους παρόχους τοποθεσιών GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Αυτός ο πάροχος τοποθεσιών είναι ο πιο απλός στην εγκατάσταση, καθώς δεν απαιτεί παραμετροποίηση στον διακομιστή (ιδανικός για μοιραζόμενη φιλοξενία!). Χρησιμοποιεί μια βάση GeoIP 2 και το PHP API της MaxMind για να καθορίσει με ακρίβεια την τοποθεσία των επισκεπτών σας.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Αυτός ο πάροχος τοποθεσίας αυξάνει την ταχύτητά του με την εγκατεστημένη επέκταση %1$smaxminddb%2$s.",
|
||||
"LocationProviderDesc_ServerModule": "Αυτός ο πάροχος τοποθεσίας χρησιμοποιεί το άρθρωμα GeoIP 2 που έχει εγκατασταθεί στον διακομιστή ιστού σας. Ο πάροχος είναι γρήγορος και ακριβής, αλλά %1$sμπορεί να χρησιμοποιηθεί μόνο με την κλασική παρακολούθηση μέσω του φυλλομετρητή σας.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Αν επιθυμείτε να εισαγάγετε αρχεία καταγραφής ή να κάνετε κάτι άλλο που απαιτεί τον ορισμό διευθύνσεων IP, χρησιμοποιήστε την %3$sPHP GeoIP 2 υλοποίηση%4$s και εγκαταστήστε την %1$sεπέκταση maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Παραμετροποίηση των μεταβλητών διακομιστή που χρησιμοποιούνται από τα αρθρώματα GeoIP 2 του διακομιστή",
|
||||
"GeoIPVariablesConfigurationHere": "Μπορείτε να παραμετροποιήσετε τις μεταβλητές διακομιστή που χρησιμοποιούνται %1$sεδώ%2$s.",
|
||||
"ServerVariableFor": "Μεταβλητή διακομιστή για %s"
|
||||
}
|
||||
}
|
15
msd2/tracking/piwik/plugins/GeoIp2/lang/en.json
Normal file
15
msd2/tracking/piwik/plugins/GeoIp2/lang/en.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "No valid GeoIP database could be found in tar archive %1$s!",
|
||||
"CannotUnzipGeoIPFile": "Could not unzip GeoIP file in %1$s: %2$s",
|
||||
"PluginDescription": "Provides GeoIP2 location providers.",
|
||||
"LocationProviderDesc_Php": "This location provider is the most simple to install as it does not require server configuration (ideal for shared hosting!). It uses a GeoIP 2 database and MaxMind's PHP API to accurately determine the location of your visitors.",
|
||||
"LocationProviderDesc_Php_WithExtension": "This location provider is speeded up by the installed %1$smaxminddb%2$s extension.",
|
||||
"LocationProviderDesc_ServerModule": "This location provider uses the GeoIP 2 module that has been installed in your HTTP server. This provider is fast and accurate, but %1$scan only be used with normal browser tracking.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "If you have to import log files or do something else that requires setting IP addresses, use the %3$sPHP GeoIP 2 implementation%4$s and install %1$smaxminddb extension%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Configuration for server variables used by GeoIP 2 server modules",
|
||||
"GeoIPVariablesConfigurationHere": "You can configure used server variables %1$shere%2$s.",
|
||||
"ShowCustomServerVariablesConfig": "I use the Geoip2 server module (Nginx, Apache...) and want to configure server variables",
|
||||
"ServerVariableFor": "Server variable for %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/es.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/es.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "No se pudo encontrar una base de datos GeoIP válida en el archivo tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "No se pudo descomprimir archivo GeoIP en %1$s: %2$s",
|
||||
"PluginDescription": "Suministra proveedores de localización GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Este proveedor de ubicación es el más sencillo de instalar, ya que no requiere configuración del servidor (¡ideal para alojamiento compartido!). Utiliza una base de datos GeoIP 2 y la API PHP de MaxMind para determinar con precisión la ubicación de sus visitantes.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Este proveedor de ubicación se acelera con la extensión %1$smaxminddb%2$s instalada.",
|
||||
"LocationProviderDesc_ServerModule": "Este proveedor de ubicación utiliza el módulo GeoIP 2 que se ha instalado en su servidor HTTP. Este proveedor es rápido y preciso, pero %1$ssolo se puede utilizar con la función de rastreo normal de su navegador.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Si tiene que importar archivos de registro u otras tareas que requieran configurar direcciones IP, use la %3$simplementación de PHP GeoIP 2%4$s e instale la %1$sextensión maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Configuración para variables de servidor utilizadas por los módulos de servidor GeoIP 2",
|
||||
"GeoIPVariablesConfigurationHere": "Puede configurar las variables de servidor usadas %1$saquí%2$s",
|
||||
"ServerVariableFor": "Variable del servidor para %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/fr.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/fr.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Aucune base de données GeoIP valide trouvée dans l'archive tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "Impossible de décompresser le fichier GeoIP dans %1$s: %2$s",
|
||||
"PluginDescription": "Fournit des services de localisation GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Ce service de localisation est le plus simple à installer et ne requiert aucune configuration du serveur (idéal pour les hébergements partagés!). Il utilise une base de données GeoIP 2 et l'API PHP MaxMind afin de déterminer précisément la localisation de vos visiteurs.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Ce service de localisation est plus performant grâce à l'installation de l'extension %1$smaxminddb%2$s.",
|
||||
"LocationProviderDesc_ServerModule": "Ce service de localisation utilise le module GeoIP 2 qui peut être installé sur votre serveur HTTP. Ce service est rapide est précis mais %1$speut uniquement être utilisé avec le système de suivit du navigateur classique. %2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Si vous devez importer des fichiers de journaux ou bien effectuer quoi que ce soit d'autre qui requiert la définition des adresses IP, utilisez %3$sl'implémentation PHP GeoIP 2%4$s et installez %1$sl'extension maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Configuration des variables serveur utilisées par le module GeoIP 2.",
|
||||
"GeoIPVariablesConfigurationHere": "Vous pouvez configurer les variables serveur utilisées %1$sici%2$s.",
|
||||
"ServerVariableFor": "Variable serveur pour %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/it.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/it.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Nell'archivio tar %1$s non è stato trovato un database GeoIP valido!",
|
||||
"CannotUnzipGeoIPFile": "impossibile scompattare il file geoIP in %1$s: %2$s",
|
||||
"PluginDescription": "Fornisce i provider di posizione GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Il provider di localizzazione è molto semplice da installare poiché non richiede una configurazione del server (ideale per gli hosting condivisi). Esso utilizza un database GeoIP 2 e un'API PHP di MaxMind per determinare con accuratezza la posizione dei tuoi visitatori.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Questo provider di posizione viene velocizzato dall'estensione installata %1$smaxminddb%2$s.",
|
||||
"LocationProviderDesc_ServerModule": "Questo provider di posizione utilizza il modulo GeoIP 2 che è stato installato nel tuo server HTTP. Questo provider è veloce e accurato, ma %1$s può solo essere utilizzato con il normale tracciamento del browser.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Se devi importare i file di log o fare qualcos'altro che richiede l'impostazione di indirizzi IP, usa %3$sl'implementazione PHP geoIP 2%4$s e installa %1$sl'estensione maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Configurazione per le variabili del server utilizzate dai moduli server di GeoIP 2",
|
||||
"GeoIPVariablesConfigurationHere": "Puoi configurare %1$squi%2$s le variabili del server utilizzate.",
|
||||
"ServerVariableFor": "Variabili del server per %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/ja.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/ja.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "TAR アーカイブ %1$sに有効な GeoIP データベースが見つかりません!",
|
||||
"CannotUnzipGeoIPFile": "%1$s の GeoIP ファイルを解凍できません: %2$s",
|
||||
"PluginDescription": "GeoIP2 ロケーションプロバイダを提供します。",
|
||||
"LocationProviderDesc_Php": "サーバー設定 が必要ないため(共有ホスティングに最適です!) 、この位置情報プロバイダーは非常に簡単にインストールできます。ビジターの位置情報を正確に決定するために、GeoIP2 データベースと MaxMind の PHP API を使用します。",
|
||||
"LocationProviderDesc_Php_WithExtension": "この位置情報プロバイダーは、インストールされた %1$smaxminddb%2$s 拡張により高速化されています。",
|
||||
"LocationProviderDesc_ServerModule": "このロケーションプロバイダーは、HTTP サーバーにインストールされている GeoIP2 モジュールを使用します。 このプロバイダは高速で正確ですが、%1$s通常のブラウザトラッキングでのみ使用できます。%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "ログファイルをインポートする必要がある場合やIPアドレスの設定が必要な場合は、 %3$sPHP GeoIP2 実装%4$s を使用し、%1$smaxminddb 拡張%2$sをインストールしてください。",
|
||||
"ServerBasedVariablesConfiguration": "GeoIP2 サーバーモジュールで使用されるサーバー変数の設定",
|
||||
"GeoIPVariablesConfigurationHere": "%1$sこちら%2$s で使用しているサーバー変数の設定ができます。",
|
||||
"ServerVariableFor": "%s のサーバー変数"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/pl.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/pl.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Archiwum tar %1$s nie zawiera poprawnej bazy GeoIP!",
|
||||
"CannotUnzipGeoIPFile": "Nie udało się rozpakować pliku GeoIP %1$s: %2$s",
|
||||
"PluginDescription": "Dostarcza dostawców lokalizacji GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Ten dostawca lokalizacji jest najprostszy w instalacji ponieważ nie wymaga konfiguracji serwera (idealne w hostingu współdzielonym!). Korzysta z bazy GeoIP2 i API PHP firmy MaxMind aby dokładnie określać lokalizację Twoich odwiedzających.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Ten dostawca lokalizacji przyspiesza dzięki zainstalowanemu rozszerzeniu %1$smaxminddb%2$s.",
|
||||
"LocationProviderDesc_ServerModule": "Ten dostawca lokalizacji wykorzystuje moduł GeoIP2 zainstalowany w Twoim serwerze WWW. Działa szybko i dokładnie, ale %1$smoże być wykorzystany przy śledzeniu ruchu przeglądarek.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Jeśli musisz zaimportować pliki logów lub zrobić coś innego, co wymaga ustawienia adresu IP, użyj %3$simplementacji PHP dla GeoIP2%4$s i zainstaluj %1$srozszerzenie maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Konfiguracja zmiennych serwera używanych przez moduł GeoIP2",
|
||||
"GeoIPVariablesConfigurationHere": "Tu możesz skonfigurować wykorzystywane %1$szmienne serwera%2$s",
|
||||
"ServerVariableFor": "Zmienna serwera określająca %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/pt.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/pt.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Não foi encontrada uma base de dados GeoIP válida no arquivo tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "Não foi possível extrair o ficheiro GeoIP em %1$s: %2$s",
|
||||
"PluginDescription": "Fornece fornecedores de localização GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Este fornecedor de localização é o mais simples de instalar e não requer configurações no servidor (ideal para alojamentos partilhados). Utiliza uma base de dados GeoIP 2 e a API PHP do MaxMind para determinar com precisão a localização dos seus visitantes.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Este fornecedor de localização é acelerado pela extensão %1$smaxminddb%2$s instalada.",
|
||||
"LocationProviderDesc_ServerModule": "Este fornecedor de localização utiliza o módulo GeoIP 2 que foi instalado no seu servidor HTTP. Este fornecedor é rápido e preciso, mas %1$ssó pode ser utilizado para um acompanhamento normal de navegadores.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Se tiver de importar ficheiros de registo ou fazer algo mais que necessite da definição de endereços de IP, utilize a %3$simplementação PHP do GeoIP 2%4$s e instale a %1$sextensão maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Configuração para variáveis do servidor utilizadas pelos módulos do servidor GeoIP 2",
|
||||
"GeoIPVariablesConfigurationHere": "Pode configurar as variáveis de servidor utilizadas %1$saqui%2$s.",
|
||||
"ServerVariableFor": "Variável do servidor para %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/ru.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/ru.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "В tar-архиве %1$s не найдено корректной базы данных GeoIP!",
|
||||
"CannotUnzipGeoIPFile": "Не получилось распаковать файл GeoIP за %1$s:%2$s",
|
||||
"PluginDescription": "Механизмы определения местонахождения GeoIP 2.",
|
||||
"LocationProviderDesc_Php": "Этот механизм определения местонахождения является наиболее простым в установке, поскольку не требует настройки сервера (идеально для виртуального хостинга!). Он использует базы данных GeoIP2 и PHP API от MaxMind, чтобы точно определить местоположение ваших посетителей.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Этот механизм определения местонахождения ускорен установленным расширением %1$smaxminddb%2$s.",
|
||||
"LocationProviderDesc_ServerModule": "Этот механизм определения местонахождения использует модуль GeoIP 2, установленный на ваш HTTP-сервер. Он быстр и точен, но %1$s может быть использован только при отслеживании обычных браузеров.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Если вам нужно импортировать лог-файлы или сделать что-то еще, требующее использование IP-адресов, используйте %3$sPHP GeoIp 2%4$s и установите расширение %1$smaxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Конфигурация серверных переменных, использованная модулями сервера GeoIP 2.",
|
||||
"GeoIPVariablesConfigurationHere": "Вы можете сконфигурировать используемые серверные переменные %1$s здесь %2$s.",
|
||||
"ServerVariableFor": "Серверная переменная для %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/sq.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/sq.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "S’u gjet dot bazë e vlefshme të dhënash GeoIP te arkivi tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "S’u shzipua dot kartela GeoIP te %1$s: %2$s",
|
||||
"PluginDescription": "Furnizon shërbime vendndodhjesh GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Ky furnizues vendndodhjesh është më i thjeshti për t’u instaluar, ngaqë s’lyp formësim shërbyesi (i përsosur për strehim të përbashkët!). Për përcaktimin me saktësi të vendndodhjes së vizitorëve tuaj, ai përdor një bazë të dhënash GeoIP 2 dhe API-n PHP të MaxMind-it.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Ky furnizues vendndodhjesh përshpejtohet nga zgjerimi %1$smaxminddb%2$s i instaluar.",
|
||||
"LocationProviderDesc_ServerModule": "Ky furnizues vendndodhjesh përdor modulin GeoIP 2 që është instaluar te shërbyesi juaj HTTP. Ky furnizues është i shpejtë dhe i përpiktë, por %1$smund të përdoret vetëm me ndjekje të zakonshme të shfletimit.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Nëse ju duhet të importoni kartela regjistër ose të bëni diçka tjetër që lyp caktim adresash IP, përdorni %3$ssendërtimin PHP GeoIP 2%4$s dhe instaloni %1$szgjerimin maxminddb%2$s.",
|
||||
"ServerBasedVariablesConfiguration": "Formësim për ndryshore shërbyesi të përdorura nga module GeoIP 2 shërbyesi",
|
||||
"GeoIPVariablesConfigurationHere": "Ndryshoret e shërbyesit që përdoren mund t’i formësoni nga %1$skëtu%2$s.",
|
||||
"ServerVariableFor": "Ndryshore shërbyesi për %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/sv.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/sv.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Tar-arkivet %1$sinnehåller ingen GeoIP-databas!",
|
||||
"CannotUnzipGeoIPFile": "Kan inte packa upp GeoIP-filen i %1$s: %2$s",
|
||||
"PluginDescription": "Tillhandahåller platstjänster för GeoIP2.",
|
||||
"LocationProviderDesc_Php": "Den här platstjänsten är enklast att installera och kräver ingen serverkonfiguration (perfekt för delade webbhotell!). Den använder en GeoIP 2-databas och MaxMinds PHP-API för att med stor precision fastställa dina besökares platser.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Den här platstjänsten kan göras snabbare med det installerade %1$smaxminddb%2$s-tillägget.",
|
||||
"LocationProviderDesc_ServerModule": "Den här platstjänsten använder GeoIP 2-modulen som installerats på din HTTP-server. Den här tjänsten är snabb och träffsäker, men %1$skan endast användas tillsammans med normal webbläsarspårning.%2$s",
|
||||
"LocationProviderDesc_ServerModule2": "Om du behöver importera loggfiler eller göra något annat som kräver IP-adresser: Använd %1$sPECL GeoIP (rekommenderas)%2$s eller %3$sPHP GeoIP%4$s.",
|
||||
"ServerBasedVariablesConfiguration": "Konfigurering av servervariabler som används av GeoIP 2-servermoduler",
|
||||
"GeoIPVariablesConfigurationHere": "Du kan konfigurera de använda servervariablerna %1$shär%2$s.",
|
||||
"ServerVariableFor": "Servervariabel för %s"
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/tr.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/tr.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "%1$s tar arşivi dosyasında geçerli bir GeoIP veritabanı bulunamadı!",
|
||||
"CannotUnzipGeoIPFile": "%1$s içindeki GeoIP arşivi dosyası ayıklanamadı: %2$s",
|
||||
"PluginDescription": "GeoIP2 konum hizmeti sağlayıcılarını sunar.",
|
||||
"LocationProviderDesc_Php": "Bu konum hizmeti sağlayıcısı, sunucu yapılandırması gerektirmediğinden kurulumu en kolay olanıdır (paylaşımlı barındırma için idealdir). GeoIP 2 veritabanı ve MaxMind PHP API uygulamasını kullanarak ziyaretçilerinizin konumunu büyük doğruluk ile belirler.",
|
||||
"LocationProviderDesc_Php_WithExtension": "Bu konum hizmeti sağlayıcısı %1$smaxminddb%2$s eklentisi kurularak hızlandırılmıştır.",
|
||||
"LocationProviderDesc_ServerModule": "Bu konum hizmeti sağlayıcısı HTTP sunucunuz üzerine kurulmuş GeoIP 2 modülünü kullanır. Bu hizmet sağlayıcı hızlı ve doğrudur ancak %1$syalnız normal web tarayıcı izlemesi ile kullanılabilir%2$s.",
|
||||
"LocationProviderDesc_ServerModule2": "Günlük dosyalarını içe aktarmak ya da IP adresinin ayarlanmasını gerektiren başka bir işlem yapmak zorundaysanız, %3$sPHP GeoIp 2 uygulamasını%4$s kullanarak %1$smaxminddb eklentisini%2$s kurun.",
|
||||
"ServerBasedVariablesConfiguration": "GeoIP 2 sunucu modülleri tarafından kullanılan sunucu değişkeni yapılandırması",
|
||||
"GeoIPVariablesConfigurationHere": "Kullanılan sunucu değişkenleri %1$sburadan%2$s yapılandırılabilir.",
|
||||
"ServerVariableFor": "%s için sunucu değişkeni"
|
||||
}
|
||||
}
|
7
msd2/tracking/piwik/plugins/GeoIp2/lang/vi.json
Normal file
7
msd2/tracking/piwik/plugins/GeoIp2/lang/vi.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "Không có cơ sở dữ liệu GeoIP hợp lệ trong kho lưu trữ tar %1$s!",
|
||||
"CannotUnzipGeoIPFile": "Không thể giải nén tệp GeoIP trong %1$s: %2$s",
|
||||
"PluginDescription": "Cung cấp vị trí nhà cung cấp GeoIP2."
|
||||
}
|
||||
}
|
14
msd2/tracking/piwik/plugins/GeoIp2/lang/zh-tw.json
Normal file
14
msd2/tracking/piwik/plugins/GeoIp2/lang/zh-tw.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"GeoIp2": {
|
||||
"CannotFindGeoIPDatabaseInArchive": "在 tar 壓縮檔 %1$s 中找不到可用的 GeoIP 資料庫。",
|
||||
"CannotUnzipGeoIPFile": "無法解壓縮 %1$s 中的 GeoIP 檔案:%2$s",
|
||||
"PluginDescription": "提供 GeoIP2 地理位置供應商。",
|
||||
"LocationProviderDesc_Php": "這個地理位置供應商是安裝方式最簡單的,因為它不需要更動任何伺服器設定(共享主機適用!)。它使用 GeoIP 2 資料庫和 MaxMind 的 PHP API 來精準的判別訪客的位置。",
|
||||
"LocationProviderDesc_Php_WithExtension": "這個地理位置供應商已透過安裝的 %1$smaxminddb%2$s 擴充功能加速。",
|
||||
"LocationProviderDesc_ServerModule": "這個地理位置供應商使用安裝在你 HTTP 伺服器上的 GeoIP 2 模組。這個供應商快又精準,但是%1$s只適用於一般瀏覽器上的追蹤%2$s。",
|
||||
"LocationProviderDesc_ServerModule2": "如果你需要匯入紀錄檔或是其他需要設定 IP 位址的事情,使用 %3$sPHP GeoIP 2 implementation%4$s 並安裝 %1$smaxminddb 擴充功能%2$s。",
|
||||
"ServerBasedVariablesConfiguration": "GeoIP 2 伺服器模組所使用的伺服器變數設定檔",
|
||||
"GeoIPVariablesConfigurationHere": "你可以在%1$s這裡%2$s設置已使用的伺服器變數。",
|
||||
"ServerVariableFor": "%s 的伺服器變數"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user