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:
-rw-r--r--CHANGELOG.md1
-rw-r--r--core/Updates/4.0.0-b1.php26
-rw-r--r--libs/MaxMindGeoIP/geoip.inc1953
-rw-r--r--libs/MaxMindGeoIP/geoipcity.inc241
-rw-r--r--plugins/GeoIp2/Columns/Region.php20
-rw-r--r--plugins/GeoIp2/Controller.php200
-rw-r--r--plugins/GeoIp2/GeoIP2AutoUpdater.php25
-rw-r--r--plugins/GeoIp2/GeoIp2.php23
-rw-r--r--plugins/GeoIp2/LocationProvider/GeoIp2/Php.php73
-rw-r--r--plugins/GeoIp2/LocationProvider/GeoIp2/ServerModule.php18
-rw-r--r--plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.controller.js (renamed from plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.controller.js)16
-rw-r--r--plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.directive.js (renamed from plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.directive.js)10
-rw-r--r--plugins/GeoIp2/lang/en.json48
-rw-r--r--plugins/GeoIp2/templates/_updaterManage.twig (renamed from plugins/UserCountry/templates/_updaterManage.twig)29
-rw-r--r--plugins/GeoIp2/templates/_updaterNextRunTime.twig9
-rw-r--r--plugins/GeoIp2/templates/configuration.twig48
-rw-r--r--plugins/GeoIp2/templates/setupguide.twig9
-rw-r--r--plugins/GeoIp2/tests/Unit/GeoIp2Test.php135
-rw-r--r--plugins/UserCountry/Archiver.php2
-rw-r--r--plugins/UserCountry/Columns/Region.php1
-rw-r--r--plugins/UserCountry/Controller.php390
-rw-r--r--plugins/UserCountry/Diagnostic/GeolocationDiagnostic.php5
-rw-r--r--plugins/UserCountry/GeoIPAutoUpdater.php731
-rw-r--r--plugins/UserCountry/LocationProvider.php20
-rw-r--r--plugins/UserCountry/LocationProvider/GeoIp.php254
-rw-r--r--plugins/UserCountry/LocationProvider/GeoIp/Pecl.php328
-rw-r--r--plugins/UserCountry/LocationProvider/GeoIp/Php.php388
-rw-r--r--plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php291
-rw-r--r--plugins/UserCountry/Reports/Base.php2
-rw-r--r--plugins/UserCountry/Reports/GetContinent.php1
-rw-r--r--plugins/UserCountry/Tasks.php21
-rw-r--r--plugins/UserCountry/UserCountry.php24
-rw-r--r--plugins/UserCountry/functions.php58
-rw-r--r--plugins/UserCountry/lang/en.json63
-rw-r--r--plugins/UserCountry/templates/_updaterNextRunTime.twig9
-rw-r--r--plugins/UserCountry/templates/adminIndex.twig108
-rw-r--r--plugins/UserCountry/tests/Integration/APITest.php4
-rw-r--r--plugins/UserCountry/tests/UI/UserCountry_spec.js35
-rw-r--r--plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_geoip2.png3
-rw-r--r--plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_no_providers.png3
-rw-r--r--plugins/UserCountry/tests/Unit/UserCountryTest.php122
-rw-r--r--tests/PHPUnit/Framework/TestingEnvironmentManipulator.php4
42 files changed, 757 insertions, 4994 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 315d4afa47..8a939cbb21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@ The Product Changelog at **[matomo.org/changelog](https://matomo.org/changelog)*
* The event `CustomPiwikJs.shouldAddTrackerFile` has been renamed to `CustomJsTracker.shouldAddTrackerFile`
* Public API class `Piwik\Plugins\CustomPiwikJs\TrackerUpdater` has been renamed to `Piwik\Plugins\CustomJsTracker\TrackerUpdater`
* API method `CustomPiwikJs.doesIncludePluginTrackersAutomatically` has been renamed to `CustomJsTracker.doesIncludePluginTrackersAutomatically`
+* GeoIP Legacy support has been fully removed. Users of GeoIP Legacy need to set up a new location provider like GeoIP2, otherwise the default location provider will be used.
## Matomo 3.13.1
diff --git a/core/Updates/4.0.0-b1.php b/core/Updates/4.0.0-b1.php
index 1405911a53..d1ea9f9602 100644
--- a/core/Updates/4.0.0-b1.php
+++ b/core/Updates/4.0.0-b1.php
@@ -9,7 +9,9 @@
namespace Piwik\Updates;
+use Piwik\Common;
use Piwik\Config;
+use Piwik\Plugins\UserCountry\LocationProvider;
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
use Piwik\Updater\Migration\Factory as MigrationFactory;
@@ -48,11 +50,35 @@ class Updates_4_0_0_b1 extends PiwikUpdates
$migrations[] = $this->migration->plugin->activate('CustomJsTracker');
}
+ if ($this->usesGeoIpLegacyLocationProvider()) {
+ // activate GeoIp2 plugin for users still using GeoIp2 Legacy (others might have it disabled on purpose)
+ $migrations[] = $this->migration->plugin->activate('GeoIp2');
+ }
+
+ // remove old options
+ $migrations[] = $this->migration->db->sql('DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name IN ("geoip.updater_period", "geoip.loc_db_url", "geoip.isp_db_url", "geoip.org_db_url")');
+
return $migrations;
}
public function doUpdate(Updater $updater)
{
$updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+
+ if ($this->usesGeoIpLegacyLocationProvider()) {
+ // switch to default provider if GeoIp Legacy was still in use
+ LocationProvider::setCurrentProvider(LocationProvider\DefaultProvider::ID);
+ }
+ }
+
+ protected function usesGeoIpLegacyLocationProvider()
+ {
+ $currentProvider = LocationProvider::getCurrentProviderId();
+
+ return in_array($currentProvider, [
+ 'geoip_pecl',
+ 'geoip_php',
+ 'geoip_serverbased',
+ ]);
}
}
diff --git a/libs/MaxMindGeoIP/geoip.inc b/libs/MaxMindGeoIP/geoip.inc
deleted file mode 100644
index 519e48d373..0000000000
--- a/libs/MaxMindGeoIP/geoip.inc
+++ /dev/null
@@ -1,1953 +0,0 @@
-<?php
-
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
-/* geoip.inc
- *
- * Copyright (C) 2007 MaxMind LLC
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-define("GEOIP_COUNTRY_BEGIN", 16776960);
-define("GEOIP_STATE_BEGIN_REV0", 16700000);
-define("GEOIP_STATE_BEGIN_REV1", 16000000);
-define("GEOIP_STANDARD", 0);
-define("GEOIP_MEMORY_CACHE", 1);
-define("GEOIP_SHARED_MEMORY", 2);
-define("STRUCTURE_INFO_MAX_SIZE", 20);
-define("DATABASE_INFO_MAX_SIZE", 100);
-if (!defined('GEOIP_COUNTRY_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_COUNTRY_EDITION", 1);
-}
-if (!defined('GEOIP_PROXY_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_PROXY_EDITION", 8);
-}
-if (!defined('GEOIP_ASNUM_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_ASNUM_EDITION", 9);
-}
-if (!defined('GEOIP_NETSPEED_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_NETSPEED_EDITION", 10);
-}
-if (!defined('GEOIP_REGION_EDITION_REV0')) {
- // GeoIP PECL installed?
- define("GEOIP_REGION_EDITION_REV0", 7);
-}
-if (!defined('GEOIP_REGION_EDITION_REV1')) {
- // GeoIP PECL installed?
- define("GEOIP_REGION_EDITION_REV1", 3);
-}
-if (!defined('GEOIP_CITY_EDITION_REV0')) {
- // GeoIP PECL installed?
- define("GEOIP_CITY_EDITION_REV0", 6);
-}
-if (!defined('GEOIP_CITY_EDITION_REV1')) {
- // GeoIP PECL installed?
- define("GEOIP_CITY_EDITION_REV1", 2);
-}
-if (!defined('GEOIP_ORG_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_ORG_EDITION", 5);
-}
-if (!defined('GEOIP_ISP_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_ISP_EDITION", 4);
-}
-define("SEGMENT_RECORD_LENGTH", 3);
-define("STANDARD_RECORD_LENGTH", 3);
-define("ORG_RECORD_LENGTH", 4);
-define("MAX_RECORD_LENGTH", 4);
-define("MAX_ORG_RECORD_LENGTH", 300);
-define("GEOIP_SHM_KEY", 0x4f415401);
-define("US_OFFSET", 1);
-define("CANADA_OFFSET", 677);
-define("WORLD_OFFSET", 1353);
-define("FIPS_RANGE", 360);
-if (!defined('GEOIP_UNKNOWN_SPEED')) {
- // GeoIP PECL installed?
- define("GEOIP_UNKNOWN_SPEED", 0);
-}
-if (!defined('GEOIP_DIALUP_SPEED')) {
- // GeoIP PECL installed?
- define("GEOIP_DIALUP_SPEED", 1);
-}
-if (!defined('GEOIP_CABLEDSL_SPEED')) {
- // GeoIP PECL installed?
- define("GEOIP_CABLEDSL_SPEED", 2);
-}
-if (!defined('GEOIP_CORPORATE_SPEED')) {
- // GeoIP PECL installed?
- define("GEOIP_CORPORATE_SPEED", 3);
-}
-if (!defined('GEOIP_DOMAIN_EDITION')) {
- // GeoIP PECL installed?
- define("GEOIP_DOMAIN_EDITION", 11);
-}
-//if (!defined('GEOIP_COUNTRY_EDITION_V6')) {
- // GeoIP PECL installed?
- define("GEOIP_COUNTRY_EDITION_V6", 12);
-//}
-define("GEOIP_LOCATIONA_EDITION", 13);
-define("GEOIP_ACCURACYRADIUS_EDITION", 14);
-define("GEOIP_CITYCOMBINED_EDITION", 15);
-define("GEOIP_CITY_EDITION_REV1_V6", 30);
-define("GEOIP_CITY_EDITION_REV0_V6", 31);
-if (!defined('GEOIP_NETSPEED_EDITION_REV1')) {
- // GeoIP PECL installed?
- define("GEOIP_NETSPEED_EDITION_REV1", 32);
-}
-define("GEOIP_NETSPEED_EDITION_REV1_V6", 33);
-define("GEOIP_USERTYPE_EDITION", 28);
-define("GEOIP_USERTYPE_EDITION_V6", 29);
-define("GEOIP_ASNUM_EDITION_V6", 21);
-define("GEOIP_ISP_EDITION_V6", 22);
-define("GEOIP_ORG_EDITION_V6", 23);
-define("GEOIP_DOMAIN_EDITION_V6", 24);
-
-define("CITYCOMBINED_FIXED_RECORD", 7);
-
-class GeoIP
-{
- public $flags;
- public $filehandle;
- public $memory_buffer;
- public $databaseType;
- public $databaseSegments;
- public $record_length;
- public $shmid;
- public $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
- "" => 0,
- "AP" => 1,
- "EU" => 2,
- "AD" => 3,
- "AE" => 4,
- "AF" => 5,
- "AG" => 6,
- "AI" => 7,
- "AL" => 8,
- "AM" => 9,
- "CW" => 10,
- "AO" => 11,
- "AQ" => 12,
- "AR" => 13,
- "AS" => 14,
- "AT" => 15,
- "AU" => 16,
- "AW" => 17,
- "AZ" => 18,
- "BA" => 19,
- "BB" => 20,
- "BD" => 21,
- "BE" => 22,
- "BF" => 23,
- "BG" => 24,
- "BH" => 25,
- "BI" => 26,
- "BJ" => 27,
- "BM" => 28,
- "BN" => 29,
- "BO" => 30,
- "BR" => 31,
- "BS" => 32,
- "BT" => 33,
- "BV" => 34,
- "BW" => 35,
- "BY" => 36,
- "BZ" => 37,
- "CA" => 38,
- "CC" => 39,
- "CD" => 40,
- "CF" => 41,
- "CG" => 42,
- "CH" => 43,
- "CI" => 44,
- "CK" => 45,
- "CL" => 46,
- "CM" => 47,
- "CN" => 48,
- "CO" => 49,
- "CR" => 50,
- "CU" => 51,
- "CV" => 52,
- "CX" => 53,
- "CY" => 54,
- "CZ" => 55,
- "DE" => 56,
- "DJ" => 57,
- "DK" => 58,
- "DM" => 59,
- "DO" => 60,
- "DZ" => 61,
- "EC" => 62,
- "EE" => 63,
- "EG" => 64,
- "EH" => 65,
- "ER" => 66,
- "ES" => 67,
- "ET" => 68,
- "FI" => 69,
- "FJ" => 70,
- "FK" => 71,
- "FM" => 72,
- "FO" => 73,
- "FR" => 74,
- "SX" => 75,
- "GA" => 76,
- "GB" => 77,
- "GD" => 78,
- "GE" => 79,
- "GF" => 80,
- "GH" => 81,
- "GI" => 82,
- "GL" => 83,
- "GM" => 84,
- "GN" => 85,
- "GP" => 86,
- "GQ" => 87,
- "GR" => 88,
- "GS" => 89,
- "GT" => 90,
- "GU" => 91,
- "GW" => 92,
- "GY" => 93,
- "HK" => 94,
- "HM" => 95,
- "HN" => 96,
- "HR" => 97,
- "HT" => 98,
- "HU" => 99,
- "ID" => 100,
- "IE" => 101,
- "IL" => 102,
- "IN" => 103,
- "IO" => 104,
- "IQ" => 105,
- "IR" => 106,
- "IS" => 107,
- "IT" => 108,
- "JM" => 109,
- "JO" => 110,
- "JP" => 111,
- "KE" => 112,
- "KG" => 113,
- "KH" => 114,
- "KI" => 115,
- "KM" => 116,
- "KN" => 117,
- "KP" => 118,
- "KR" => 119,
- "KW" => 120,
- "KY" => 121,
- "KZ" => 122,
- "LA" => 123,
- "LB" => 124,
- "LC" => 125,
- "LI" => 126,
- "LK" => 127,
- "LR" => 128,
- "LS" => 129,
- "LT" => 130,
- "LU" => 131,
- "LV" => 132,
- "LY" => 133,
- "MA" => 134,
- "MC" => 135,
- "MD" => 136,
- "MG" => 137,
- "MH" => 138,
- "MK" => 139,
- "ML" => 140,
- "MM" => 141,
- "MN" => 142,
- "MO" => 143,
- "MP" => 144,
- "MQ" => 145,
- "MR" => 146,
- "MS" => 147,
- "MT" => 148,
- "MU" => 149,
- "MV" => 150,
- "MW" => 151,
- "MX" => 152,
- "MY" => 153,
- "MZ" => 154,
- "NA" => 155,
- "NC" => 156,
- "NE" => 157,
- "NF" => 158,
- "NG" => 159,
- "NI" => 160,
- "NL" => 161,
- "NO" => 162,
- "NP" => 163,
- "NR" => 164,
- "NU" => 165,
- "NZ" => 166,
- "OM" => 167,
- "PA" => 168,
- "PE" => 169,
- "PF" => 170,
- "PG" => 171,
- "PH" => 172,
- "PK" => 173,
- "PL" => 174,
- "PM" => 175,
- "PN" => 176,
- "PR" => 177,
- "PS" => 178,
- "PT" => 179,
- "PW" => 180,
- "PY" => 181,
- "QA" => 182,
- "RE" => 183,
- "RO" => 184,
- "RU" => 185,
- "RW" => 186,
- "SA" => 187,
- "SB" => 188,
- "SC" => 189,
- "SD" => 190,
- "SE" => 191,
- "SG" => 192,
- "SH" => 193,
- "SI" => 194,
- "SJ" => 195,
- "SK" => 196,
- "SL" => 197,
- "SM" => 198,
- "SN" => 199,
- "SO" => 200,
- "SR" => 201,
- "ST" => 202,
- "SV" => 203,
- "SY" => 204,
- "SZ" => 205,
- "TC" => 206,
- "TD" => 207,
- "TF" => 208,
- "TG" => 209,
- "TH" => 210,
- "TJ" => 211,
- "TK" => 212,
- "TM" => 213,
- "TN" => 214,
- "TO" => 215,
- "TL" => 216,
- "TR" => 217,
- "TT" => 218,
- "TV" => 219,
- "TW" => 220,
- "TZ" => 221,
- "UA" => 222,
- "UG" => 223,
- "UM" => 224,
- "US" => 225,
- "UY" => 226,
- "UZ" => 227,
- "VA" => 228,
- "VC" => 229,
- "VE" => 230,
- "VG" => 231,
- "VI" => 232,
- "VN" => 233,
- "VU" => 234,
- "WF" => 235,
- "WS" => 236,
- "YE" => 237,
- "YT" => 238,
- "RS" => 239,
- "ZA" => 240,
- "ZM" => 241,
- "ME" => 242,
- "ZW" => 243,
- "A1" => 244,
- "A2" => 245,
- "O1" => 246,
- "AX" => 247,
- "GG" => 248,
- "IM" => 249,
- "JE" => 250,
- "BL" => 251,
- "MF" => 252,
- "BQ" => 253,
- "SS" => 254
- );
-
- public $GEOIP_COUNTRY_CODES = array(
- "",
- "AP",
- "EU",
- "AD",
- "AE",
- "AF",
- "AG",
- "AI",
- "AL",
- "AM",
- "CW",
- "AO",
- "AQ",
- "AR",
- "AS",
- "AT",
- "AU",
- "AW",
- "AZ",
- "BA",
- "BB",
- "BD",
- "BE",
- "BF",
- "BG",
- "BH",
- "BI",
- "BJ",
- "BM",
- "BN",
- "BO",
- "BR",
- "BS",
- "BT",
- "BV",
- "BW",
- "BY",
- "BZ",
- "CA",
- "CC",
- "CD",
- "CF",
- "CG",
- "CH",
- "CI",
- "CK",
- "CL",
- "CM",
- "CN",
- "CO",
- "CR",
- "CU",
- "CV",
- "CX",
- "CY",
- "CZ",
- "DE",
- "DJ",
- "DK",
- "DM",
- "DO",
- "DZ",
- "EC",
- "EE",
- "EG",
- "EH",
- "ER",
- "ES",
- "ET",
- "FI",
- "FJ",
- "FK",
- "FM",
- "FO",
- "FR",
- "SX",
- "GA",
- "GB",
- "GD",
- "GE",
- "GF",
- "GH",
- "GI",
- "GL",
- "GM",
- "GN",
- "GP",
- "GQ",
- "GR",
- "GS",
- "GT",
- "GU",
- "GW",
- "GY",
- "HK",
- "HM",
- "HN",
- "HR",
- "HT",
- "HU",
- "ID",
- "IE",
- "IL",
- "IN",
- "IO",
- "IQ",
- "IR",
- "IS",
- "IT",
- "JM",
- "JO",
- "JP",
- "KE",
- "KG",
- "KH",
- "KI",
- "KM",
- "KN",
- "KP",
- "KR",
- "KW",
- "KY",
- "KZ",
- "LA",
- "LB",
- "LC",
- "LI",
- "LK",
- "LR",
- "LS",
- "LT",
- "LU",
- "LV",
- "LY",
- "MA",
- "MC",
- "MD",
- "MG",
- "MH",
- "MK",
- "ML",
- "MM",
- "MN",
- "MO",
- "MP",
- "MQ",
- "MR",
- "MS",
- "MT",
- "MU",
- "MV",
- "MW",
- "MX",
- "MY",
- "MZ",
- "NA",
- "NC",
- "NE",
- "NF",
- "NG",
- "NI",
- "NL",
- "NO",
- "NP",
- "NR",
- "NU",
- "NZ",
- "OM",
- "PA",
- "PE",
- "PF",
- "PG",
- "PH",
- "PK",
- "PL",
- "PM",
- "PN",
- "PR",
- "PS",
- "PT",
- "PW",
- "PY",
- "QA",
- "RE",
- "RO",
- "RU",
- "RW",
- "SA",
- "SB",
- "SC",
- "SD",
- "SE",
- "SG",
- "SH",
- "SI",
- "SJ",
- "SK",
- "SL",
- "SM",
- "SN",
- "SO",
- "SR",
- "ST",
- "SV",
- "SY",
- "SZ",
- "TC",
- "TD",
- "TF",
- "TG",
- "TH",
- "TJ",
- "TK",
- "TM",
- "TN",
- "TO",
- "TL",
- "TR",
- "TT",
- "TV",
- "TW",
- "TZ",
- "UA",
- "UG",
- "UM",
- "US",
- "UY",
- "UZ",
- "VA",
- "VC",
- "VE",
- "VG",
- "VI",
- "VN",
- "VU",
- "WF",
- "WS",
- "YE",
- "YT",
- "RS",
- "ZA",
- "ZM",
- "ME",
- "ZW",
- "A1",
- "A2",
- "O1",
- "AX",
- "GG",
- "IM",
- "JE",
- "BL",
- "MF",
- "BQ",
- "SS",
- "O1"
- );
-
- public $GEOIP_COUNTRY_CODES3 = array(
- "",
- "AP",
- "EU",
- "AND",
- "ARE",
- "AFG",
- "ATG",
- "AIA",
- "ALB",
- "ARM",
- "CUW",
- "AGO",
- "ATA",
- "ARG",
- "ASM",
- "AUT",
- "AUS",
- "ABW",
- "AZE",
- "BIH",
- "BRB",
- "BGD",
- "BEL",
- "BFA",
- "BGR",
- "BHR",
- "BDI",
- "BEN",
- "BMU",
- "BRN",
- "BOL",
- "BRA",
- "BHS",
- "BTN",
- "BVT",
- "BWA",
- "BLR",
- "BLZ",
- "CAN",
- "CCK",
- "COD",
- "CAF",
- "COG",
- "CHE",
- "CIV",
- "COK",
- "CHL",
- "CMR",
- "CHN",
- "COL",
- "CRI",
- "CUB",
- "CPV",
- "CXR",
- "CYP",
- "CZE",
- "DEU",
- "DJI",
- "DNK",
- "DMA",
- "DOM",
- "DZA",
- "ECU",
- "EST",
- "EGY",
- "ESH",
- "ERI",
- "ESP",
- "ETH",
- "FIN",
- "FJI",
- "FLK",
- "FSM",
- "FRO",
- "FRA",
- "SXM",
- "GAB",
- "GBR",
- "GRD",
- "GEO",
- "GUF",
- "GHA",
- "GIB",
- "GRL",
- "GMB",
- "GIN",
- "GLP",
- "GNQ",
- "GRC",
- "SGS",
- "GTM",
- "GUM",
- "GNB",
- "GUY",
- "HKG",
- "HMD",
- "HND",
- "HRV",
- "HTI",
- "HUN",
- "IDN",
- "IRL",
- "ISR",
- "IND",
- "IOT",
- "IRQ",
- "IRN",
- "ISL",
- "ITA",
- "JAM",
- "JOR",
- "JPN",
- "KEN",
- "KGZ",
- "KHM",
- "KIR",
- "COM",
- "KNA",
- "PRK",
- "KOR",
- "KWT",
- "CYM",
- "KAZ",
- "LAO",
- "LBN",
- "LCA",
- "LIE",
- "LKA",
- "LBR",
- "LSO",
- "LTU",
- "LUX",
- "LVA",
- "LBY",
- "MAR",
- "MCO",
- "MDA",
- "MDG",
- "MHL",
- "MKD",
- "MLI",
- "MMR",
- "MNG",
- "MAC",
- "MNP",
- "MTQ",
- "MRT",
- "MSR",
- "MLT",
- "MUS",
- "MDV",
- "MWI",
- "MEX",
- "MYS",
- "MOZ",
- "NAM",
- "NCL",
- "NER",
- "NFK",
- "NGA",
- "NIC",
- "NLD",
- "NOR",
- "NPL",
- "NRU",
- "NIU",
- "NZL",
- "OMN",
- "PAN",
- "PER",
- "PYF",
- "PNG",
- "PHL",
- "PAK",
- "POL",
- "SPM",
- "PCN",
- "PRI",
- "PSE",
- "PRT",
- "PLW",
- "PRY",
- "QAT",
- "REU",
- "ROU",
- "RUS",
- "RWA",
- "SAU",
- "SLB",
- "SYC",
- "SDN",
- "SWE",
- "SGP",
- "SHN",
- "SVN",
- "SJM",
- "SVK",
- "SLE",
- "SMR",
- "SEN",
- "SOM",
- "SUR",
- "STP",
- "SLV",
- "SYR",
- "SWZ",
- "TCA",
- "TCD",
- "ATF",
- "TGO",
- "THA",
- "TJK",
- "TKL",
- "TKM",
- "TUN",
- "TON",
- "TLS",
- "TUR",
- "TTO",
- "TUV",
- "TWN",
- "TZA",
- "UKR",
- "UGA",
- "UMI",
- "USA",
- "URY",
- "UZB",
- "VAT",
- "VCT",
- "VEN",
- "VGB",
- "VIR",
- "VNM",
- "VUT",
- "WLF",
- "WSM",
- "YEM",
- "MYT",
- "SRB",
- "ZAF",
- "ZMB",
- "MNE",
- "ZWE",
- "A1",
- "A2",
- "O1",
- "ALA",
- "GGY",
- "IMN",
- "JEY",
- "BLM",
- "MAF",
- "BES",
- "SSD",
- "O1"
- );
-
- public $GEOIP_COUNTRY_NAMES = array(
- "",
- "Asia/Pacific Region",
- "Europe",
- "Andorra",
- "United Arab Emirates",
- "Afghanistan",
- "Antigua and Barbuda",
- "Anguilla",
- "Albania",
- "Armenia",
- "Curacao",
- "Angola",
- "Antarctica",
- "Argentina",
- "American Samoa",
- "Austria",
- "Australia",
- "Aruba",
- "Azerbaijan",
- "Bosnia and Herzegovina",
- "Barbados",
- "Bangladesh",
- "Belgium",
- "Burkina Faso",
- "Bulgaria",
- "Bahrain",
- "Burundi",
- "Benin",
- "Bermuda",
- "Brunei Darussalam",
- "Bolivia",
- "Brazil",
- "Bahamas",
- "Bhutan",
- "Bouvet Island",
- "Botswana",
- "Belarus",
- "Belize",
- "Canada",
- "Cocos (Keeling) Islands",
- "Congo, The Democratic Republic of the",
- "Central African Republic",
- "Congo",
- "Switzerland",
- "Cote D'Ivoire",
- "Cook Islands",
- "Chile",
- "Cameroon",
- "China",
- "Colombia",
- "Costa Rica",
- "Cuba",
- "Cape Verde",
- "Christmas Island",
- "Cyprus",
- "Czech Republic",
- "Germany",
- "Djibouti",
- "Denmark",
- "Dominica",
- "Dominican Republic",
- "Algeria",
- "Ecuador",
- "Estonia",
- "Egypt",
- "Western Sahara",
- "Eritrea",
- "Spain",
- "Ethiopia",
- "Finland",
- "Fiji",
- "Falkland Islands (Malvinas)",
- "Micronesia, Federated States of",
- "Faroe Islands",
- "France",
- "Sint Maarten (Dutch part)",
- "Gabon",
- "United Kingdom",
- "Grenada",
- "Georgia",
- "French Guiana",
- "Ghana",
- "Gibraltar",
- "Greenland",
- "Gambia",
- "Guinea",
- "Guadeloupe",
- "Equatorial Guinea",
- "Greece",
- "South Georgia and the South Sandwich Islands",
- "Guatemala",
- "Guam",
- "Guinea-Bissau",
- "Guyana",
- "Hong Kong",
- "Heard Island and McDonald Islands",
- "Honduras",
- "Croatia",
- "Haiti",
- "Hungary",
- "Indonesia",
- "Ireland",
- "Israel",
- "India",
- "British Indian Ocean Territory",
- "Iraq",
- "Iran, Islamic Republic of",
- "Iceland",
- "Italy",
- "Jamaica",
- "Jordan",
- "Japan",
- "Kenya",
- "Kyrgyzstan",
- "Cambodia",
- "Kiribati",
- "Comoros",
- "Saint Kitts and Nevis",
- "Korea, Democratic People's Republic of",
- "Korea, Republic of",
- "Kuwait",
- "Cayman Islands",
- "Kazakhstan",
- "Lao People's Democratic Republic",
- "Lebanon",
- "Saint Lucia",
- "Liechtenstein",
- "Sri Lanka",
- "Liberia",
- "Lesotho",
- "Lithuania",
- "Luxembourg",
- "Latvia",
- "Libya",
- "Morocco",
- "Monaco",
- "Moldova, Republic of",
- "Madagascar",
- "Marshall Islands",
- "Macedonia",
- "Mali",
- "Myanmar",
- "Mongolia",
- "Macau",
- "Northern Mariana Islands",
- "Martinique",
- "Mauritania",
- "Montserrat",
- "Malta",
- "Mauritius",
- "Maldives",
- "Malawi",
- "Mexico",
- "Malaysia",
- "Mozambique",
- "Namibia",
- "New Caledonia",
- "Niger",
- "Norfolk Island",
- "Nigeria",
- "Nicaragua",
- "Netherlands",
- "Norway",
- "Nepal",
- "Nauru",
- "Niue",
- "New Zealand",
- "Oman",
- "Panama",
- "Peru",
- "French Polynesia",
- "Papua New Guinea",
- "Philippines",
- "Pakistan",
- "Poland",
- "Saint Pierre and Miquelon",
- "Pitcairn Islands",
- "Puerto Rico",
- "Palestinian Territory",
- "Portugal",
- "Palau",
- "Paraguay",
- "Qatar",
- "Reunion",
- "Romania",
- "Russian Federation",
- "Rwanda",
- "Saudi Arabia",
- "Solomon Islands",
- "Seychelles",
- "Sudan",
- "Sweden",
- "Singapore",
- "Saint Helena",
- "Slovenia",
- "Svalbard and Jan Mayen",
- "Slovakia",
- "Sierra Leone",
- "San Marino",
- "Senegal",
- "Somalia",
- "Suriname",
- "Sao Tome and Principe",
- "El Salvador",
- "Syrian Arab Republic",
- "Swaziland",
- "Turks and Caicos Islands",
- "Chad",
- "French Southern Territories",
- "Togo",
- "Thailand",
- "Tajikistan",
- "Tokelau",
- "Turkmenistan",
- "Tunisia",
- "Tonga",
- "Timor-Leste",
- "Turkey",
- "Trinidad and Tobago",
- "Tuvalu",
- "Taiwan",
- "Tanzania, United Republic of",
- "Ukraine",
- "Uganda",
- "United States Minor Outlying Islands",
- "United States",
- "Uruguay",
- "Uzbekistan",
- "Holy See (Vatican City State)",
- "Saint Vincent and the Grenadines",
- "Venezuela",
- "Virgin Islands, British",
- "Virgin Islands, U.S.",
- "Vietnam",
- "Vanuatu",
- "Wallis and Futuna",
- "Samoa",
- "Yemen",
- "Mayotte",
- "Serbia",
- "South Africa",
- "Zambia",
- "Montenegro",
- "Zimbabwe",
- "Anonymous Proxy",
- "Satellite Provider",
- "Other",
- "Aland Islands",
- "Guernsey",
- "Isle of Man",
- "Jersey",
- "Saint Barthelemy",
- "Saint Martin",
- "Bonaire, Saint Eustatius and Saba",
- "South Sudan",
- "Other"
- );
-
- public $GEOIP_CONTINENT_CODES = array(
- "--",
- "AS",
- "EU",
- "EU",
- "AS",
- "AS",
- "NA",
- "NA",
- "EU",
- "AS",
- "NA",
- "AF",
- "AN",
- "SA",
- "OC",
- "EU",
- "OC",
- "NA",
- "AS",
- "EU",
- "NA",
- "AS",
- "EU",
- "AF",
- "EU",
- "AS",
- "AF",
- "AF",
- "NA",
- "AS",
- "SA",
- "SA",
- "NA",
- "AS",
- "AN",
- "AF",
- "EU",
- "NA",
- "NA",
- "AS",
- "AF",
- "AF",
- "AF",
- "EU",
- "AF",
- "OC",
- "SA",
- "AF",
- "AS",
- "SA",
- "NA",
- "NA",
- "AF",
- "AS",
- "AS",
- "EU",
- "EU",
- "AF",
- "EU",
- "NA",
- "NA",
- "AF",
- "SA",
- "EU",
- "AF",
- "AF",
- "AF",
- "EU",
- "AF",
- "EU",
- "OC",
- "SA",
- "OC",
- "EU",
- "EU",
- "NA",
- "AF",
- "EU",
- "NA",
- "AS",
- "SA",
- "AF",
- "EU",
- "NA",
- "AF",
- "AF",
- "NA",
- "AF",
- "EU",
- "AN",
- "NA",
- "OC",
- "AF",
- "SA",
- "AS",
- "AN",
- "NA",
- "EU",
- "NA",
- "EU",
- "AS",
- "EU",
- "AS",
- "AS",
- "AS",
- "AS",
- "AS",
- "EU",
- "EU",
- "NA",
- "AS",
- "AS",
- "AF",
- "AS",
- "AS",
- "OC",
- "AF",
- "NA",
- "AS",
- "AS",
- "AS",
- "NA",
- "AS",
- "AS",
- "AS",
- "NA",
- "EU",
- "AS",
- "AF",
- "AF",
- "EU",
- "EU",
- "EU",
- "AF",
- "AF",
- "EU",
- "EU",
- "AF",
- "OC",
- "EU",
- "AF",
- "AS",
- "AS",
- "AS",
- "OC",
- "NA",
- "AF",
- "NA",
- "EU",
- "AF",
- "AS",
- "AF",
- "NA",
- "AS",
- "AF",
- "AF",
- "OC",
- "AF",
- "OC",
- "AF",
- "NA",
- "EU",
- "EU",
- "AS",
- "OC",
- "OC",
- "OC",
- "AS",
- "NA",
- "SA",
- "OC",
- "OC",
- "AS",
- "AS",
- "EU",
- "NA",
- "OC",
- "NA",
- "AS",
- "EU",
- "OC",
- "SA",
- "AS",
- "AF",
- "EU",
- "EU",
- "AF",
- "AS",
- "OC",
- "AF",
- "AF",
- "EU",
- "AS",
- "AF",
- "EU",
- "EU",
- "EU",
- "AF",
- "EU",
- "AF",
- "AF",
- "SA",
- "AF",
- "NA",
- "AS",
- "AF",
- "NA",
- "AF",
- "AN",
- "AF",
- "AS",
- "AS",
- "OC",
- "AS",
- "AF",
- "OC",
- "AS",
- "EU",
- "NA",
- "OC",
- "AS",
- "AF",
- "EU",
- "AF",
- "OC",
- "NA",
- "SA",
- "AS",
- "EU",
- "NA",
- "SA",
- "NA",
- "NA",
- "AS",
- "OC",
- "OC",
- "OC",
- "AS",
- "AF",
- "EU",
- "AF",
- "AF",
- "EU",
- "AF",
- "--",
- "--",
- "--",
- "EU",
- "EU",
- "EU",
- "EU",
- "NA",
- "NA",
- "NA",
- "AF",
- "--"
- );
-}
-
-function geoip_load_shared_mem($file)
-{
- $fp = fopen($file, "rb");
- if (!$fp) {
- print "error opening $file: $php_errormsg\n";
- exit;
- }
- $s_array = fstat($fp);
- $size = $s_array['size'];
- if (($shmid = @shmop_open(GEOIP_SHM_KEY, "w", 0, 0))) {
- shmop_delete($shmid);
- shmop_close($shmid);
- }
- $shmid = shmop_open(GEOIP_SHM_KEY, "c", 0644, $size);
- shmop_write($shmid, fread($fp, $size), 0);
- shmop_close($shmid);
-}
-
-function _setup_segments($gi)
-{
- $gi->databaseType = GEOIP_COUNTRY_EDITION;
- $gi->record_length = STANDARD_RECORD_LENGTH;
- if ($gi->flags & GEOIP_SHARED_MEMORY) {
- $offset = @shmop_size($gi->shmid) - 3;
- for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
- $delim = @shmop_read($gi->shmid, $offset, 3);
- $offset += 3;
- if ($delim == (chr(255) . chr(255) . chr(255))) {
- $gi->databaseType = ord(@shmop_read($gi->shmid, $offset, 1));
- if ($gi->databaseType >= 106) {
- $gi->databaseType -= 105;
- }
- $offset++;
-
- if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
- $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
- } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
- $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
- } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
- || ($gi->databaseType == GEOIP_ORG_EDITION)
- || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
- || ($gi->databaseType == GEOIP_ISP_EDITION)
- || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
- || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
- || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
- || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
- || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
- || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
- || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
- || ($gi->databaseType == GEOIP_ASNUM_EDITION)
- || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
- ) {
- $gi->databaseSegments = 0;
- $buf = @shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
- for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
- $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
- }
- if (($gi->databaseType == GEOIP_ORG_EDITION)
- || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
- || ($gi->databaseType == GEOIP_ISP_EDITION)
- || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
- ) {
- $gi->record_length = ORG_RECORD_LENGTH;
- }
- }
- break;
- } else {
- $offset -= 4;
- }
- }
- if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
- ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
- ($gi->databaseType == GEOIP_PROXY_EDITION) ||
- ($gi->databaseType == GEOIP_NETSPEED_EDITION)
- ) {
- $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
- }
- } else {
- $filepos = ftell($gi->filehandle);
- fseek($gi->filehandle, -3, SEEK_END);
- for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
- $delim = fread($gi->filehandle, 3);
- if ($delim == (chr(255) . chr(255) . chr(255))) {
- $gi->databaseType = ord(fread($gi->filehandle, 1));
- if ($gi->databaseType >= 106) {
- $gi->databaseType -= 105;
- }
- if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
- $gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
- } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
- $gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
- } elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
- || ($gi->databaseType == GEOIP_ORG_EDITION)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
- || ($gi->databaseType == GEOIP_ISP_EDITION)
- || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
- || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
- || ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
- || ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
- || ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
- || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
- || ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
- || ($gi->databaseType == GEOIP_USERTYPE_EDITION)
- || ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
- || ($gi->databaseType == GEOIP_ASNUM_EDITION)
- || ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
- ) {
- $gi->databaseSegments = 0;
- $buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
- for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
- $gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
- }
- if (($gi->databaseType == GEOIP_ORG_EDITION)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION)
- || ($gi->databaseType == GEOIP_ISP_EDITION)
- || ($gi->databaseType == GEOIP_ORG_EDITION_V6)
- || ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
- || ($gi->databaseType == GEOIP_ISP_EDITION_V6)
- ) {
- $gi->record_length = ORG_RECORD_LENGTH;
- }
- }
- break;
- } else {
- fseek($gi->filehandle, -4, SEEK_CUR);
- }
- }
- if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
- ($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
- ($gi->databaseType == GEOIP_PROXY_EDITION) ||
- ($gi->databaseType == GEOIP_NETSPEED_EDITION)
- ) {
- $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
- }
- fseek($gi->filehandle, $filepos, SEEK_SET);
- }
- return $gi;
-}
-
-function geoip_open($filename, $flags)
-{
- $gi = new GeoIP;
- $gi->flags = $flags;
- if ($gi->flags & GEOIP_SHARED_MEMORY) {
- $gi->shmid = @shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
- } else {
- $gi->filehandle = fopen($filename, "rb") or die("Can not open $filename\n");
- if ($gi->flags & GEOIP_MEMORY_CACHE) {
- $s_array = fstat($gi->filehandle);
- $gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
- }
- }
-
- $gi = _setup_segments($gi);
- return $gi;
-}
-
-function geoip_close($gi)
-{
- if ($gi->flags & GEOIP_SHARED_MEMORY) {
- return true;
- }
-
- return fclose($gi->filehandle);
-}
-
-function geoip_country_id_by_name_v6($gi, $name)
-{
- $rec = dns_get_record($name, DNS_AAAA);
- if (!$rec) {
- return false;
- }
- $addr = $rec[0]["ipv6"];
- if (!$addr || $addr == $name) {
- return false;
- }
- return geoip_country_id_by_addr_v6($gi, $addr);
-}
-
-function geoip_country_id_by_name($gi, $name)
-{
- $addr = gethostbyname($name);
- if (!$addr || $addr == $name) {
- return false;
- }
- return geoip_country_id_by_addr($gi, $addr);
-}
-
-if (!function_exists('geoip_country_code_by_name_v6')) {
-// GeoIP PECL installed?
-function geoip_country_code_by_name_v6($gi, $name)
-{
- $country_id = geoip_country_id_by_name_v6($gi, $name);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_CODES[$country_id];
- }
- return false;
-}
-}
-if (!function_exists('geoip_country_code_by_name')) {
-// GeoIP PECL installed?
-function geoip_country_code_by_name($gi, $name)
-{
- $country_id = geoip_country_id_by_name($gi, $name);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_CODES[$country_id];
- }
- return false;
-}
-}
-
-if (!function_exists('geoip_country_name_by_name_v6')) {
-// GeoIP PECL installed?
-function geoip_country_name_by_name_v6($gi, $name)
-{
- $country_id = geoip_country_id_by_name_v6($gi, $name);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_NAMES[$country_id];
- }
- return false;
-}
-}
-if (!function_exists('geoip_country_name_by_name')) {
-// GeoIP PECL installed?
-function geoip_country_name_by_name($gi, $name)
-{
- $country_id = geoip_country_id_by_name($gi, $name);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_NAMES[$country_id];
- }
- return false;
-}
-}
-
-function geoip_country_id_by_addr_v6($gi, $addr)
-{
- $ipnum = inet_pton($addr);
- return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
-}
-
-function geoip_country_id_by_addr($gi, $addr)
-{
- $ipnum = ip2long($addr);
- return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
-}
-
-function geoip_country_code_by_addr_v6($gi, $addr)
-{
- $country_id = geoip_country_id_by_addr_v6($gi, $addr);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_CODES[$country_id];
- }
- return false;
-}
-
-function geoip_country_code_by_addr($gi, $addr)
-{
- if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
- $record = geoip_record_by_addr($gi, $addr);
- if ($record !== false) {
- return $record->country_code;
- }
- } else {
- $country_id = geoip_country_id_by_addr($gi, $addr);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_CODES[$country_id];
- }
- }
- return false;
-}
-
-function geoip_country_name_by_addr_v6($gi, $addr)
-{
- $country_id = geoip_country_id_by_addr_v6($gi, $addr);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_NAMES[$country_id];
- }
- return false;
-}
-
-function geoip_country_name_by_addr($gi, $addr)
-{
- if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
- $record = geoip_record_by_addr($gi, $addr);
- return $record->country_name;
- } else {
- $country_id = geoip_country_id_by_addr($gi, $addr);
- if ($country_id !== false) {
- return $gi->GEOIP_COUNTRY_NAMES[$country_id];
- }
- }
- return false;
-}
-
-function _geoip_seek_country_v6($gi, $ipnum)
-{
- # arrays from unpack start with offset 1
- # yet another php mystery. array_merge work around
- # this broken behaviour
- $v6vec = array_merge(unpack("C16", $ipnum));
-
- $offset = 0;
- for ($depth = 127; $depth >= 0; --$depth) {
- if ($gi->flags & GEOIP_MEMORY_CACHE) {
- $buf = _safe_substr(
- $gi->memory_buffer,
- 2 * $gi->record_length * $offset,
- 2 * $gi->record_length
- );
- } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
- $buf = @shmop_read(
- $gi->shmid,
- 2 * $gi->record_length * $offset,
- 2 * $gi->record_length
- );
- } else {
- fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
- or die("fseek failed");
- $buf = fread($gi->filehandle, 2 * $gi->record_length);
- }
- $x = array(0, 0);
- for ($i = 0; $i < 2; ++$i) {
- for ($j = 0; $j < $gi->record_length; ++$j) {
- $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
- }
- }
-
- $bnum = 127 - $depth;
- $idx = $bnum >> 3;
- $b_mask = 1 << ($bnum & 7 ^ 7);
- if (($v6vec[$idx] & $b_mask) > 0) {
- if ($x[1] >= $gi->databaseSegments) {
- return $x[1];
- }
- $offset = $x[1];
- } else {
- if ($x[0] >= $gi->databaseSegments) {
- return $x[0];
- }
- $offset = $x[0];
- }
- }
- trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
- return false;
-}
-
-function _geoip_seek_country($gi, $ipnum)
-{
- $offset = 0;
- for ($depth = 31; $depth >= 0; --$depth) {
- if ($gi->flags & GEOIP_MEMORY_CACHE) {
- $buf = _safe_substr(
- $gi->memory_buffer,
- 2 * $gi->record_length * $offset,
- 2 * $gi->record_length
- );
- } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
- $buf = @shmop_read(
- $gi->shmid,
- 2 * $gi->record_length * $offset,
- 2 * $gi->record_length
- );
- } else {
- fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
- or die("fseek failed");
- $buf = fread($gi->filehandle, 2 * $gi->record_length);
- }
- $x = array(0, 0);
- for ($i = 0; $i < 2; ++$i) {
- for ($j = 0; $j < $gi->record_length; ++$j) {
- $x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
- }
- }
- if ($ipnum & (1 << $depth)) {
- if ($x[1] >= $gi->databaseSegments) {
- return $x[1];
- }
- $offset = $x[1];
- } else {
- if ($x[0] >= $gi->databaseSegments) {
- return $x[0];
- }
- $offset = $x[0];
- }
- }
- trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
- return false;
-}
-
-function _common_get_org($gi, $seek_org)
-{
- $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
- if ($gi->flags & GEOIP_SHARED_MEMORY) {
- $org_buf = @shmop_read($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
- } else {
- fseek($gi->filehandle, $record_pointer, SEEK_SET);
- $org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);
- }
- $org_buf = _safe_substr($org_buf, 0, strpos($org_buf, "\0"));
- return $org_buf;
-}
-
-function _get_org_v6($gi, $ipnum)
-{
- $seek_org = _geoip_seek_country_v6($gi, $ipnum);
- if ($seek_org == $gi->databaseSegments) {
- return null;
- }
- return _common_get_org($gi, $seek_org);
-}
-
-function _get_org($gi, $ipnum)
-{
- $seek_org = _geoip_seek_country($gi, $ipnum);
- if ($seek_org == $gi->databaseSegments) {
- return null;
- }
- return _common_get_org($gi, $seek_org);
-}
-
-
-function geoip_name_by_addr_v6($gi, $addr)
-{
- if ($addr == null) {
- return 0;
- }
- $ipnum = inet_pton($addr);
- return _get_org_v6($gi, $ipnum);
-}
-
-function geoip_name_by_addr($gi, $addr)
-{
- if ($addr == null) {
- return 0;
- }
- $ipnum = ip2long($addr);
- return _get_org($gi, $ipnum);
-}
-
-function geoip_org_by_addr($gi, $addr)
-{
- return geoip_name_by_addr($gi, $addr);
-}
-
-function _get_region($gi, $ipnum)
-{
- if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
- $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV0;
- if ($seek_region >= 1000) {
- $country_code = "US";
- $region = chr(($seek_region - 1000) / 26 + 65) . chr(($seek_region - 1000) % 26 + 65);
- } else {
- $country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
- $region = "";
- }
- return array($country_code, $region);
- } elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
- $seek_region = _geoip_seek_country($gi, $ipnum) - GEOIP_STATE_BEGIN_REV1;
- if ($seek_region < US_OFFSET) {
- $country_code = "";
- $region = "";
- } elseif ($seek_region < CANADA_OFFSET) {
- $country_code = "US";
- $region = chr(($seek_region - US_OFFSET) / 26 + 65) . chr(($seek_region - US_OFFSET) % 26 + 65);
- } elseif ($seek_region < WORLD_OFFSET) {
- $country_code = "CA";
- $region = chr(($seek_region - CANADA_OFFSET) / 26 + 65) . chr(($seek_region - CANADA_OFFSET) % 26 + 65);
- } else {
- $country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
- $region = "";
- }
- return array($country_code, $region);
- }
-}
-
-function geoip_region_by_addr($gi, $addr)
-{
- if ($addr == null) {
- return 0;
- }
- $ipnum = ip2long($addr);
- return _get_region($gi, $ipnum);
-}
-
-if(!function_exists('getdnsattributes')) {
-function getdnsattributes($l, $ip)
-{
- $r = new Net_DNS_Resolver();
- $r->nameservers = array("ws1.maxmind.com");
- $p = $r->search($l . "." . $ip . ".s.maxmind.com", "TXT", "IN");
- $str = is_object($p->answer[0]) ? $p->answer[0]->string() : '';
- $str = substr($str, 1, -1);
- return $str;
-}
-}
-function _safe_substr($string, $start, $length)
-{
- // workaround php's broken substr, strpos, etc handling with
- // mbstring.func_overload and mbstring.internal_encoding
- $mbExists = extension_loaded('mbstring');
-
- if ($mbExists) {
- $enc = mb_internal_encoding();
- mb_internal_encoding('ISO-8859-1');
- }
-
- $buf = substr($string, $start, $length);
-
- if ($mbExists) {
- mb_internal_encoding($enc);
- }
-
- return $buf;
-}
diff --git a/libs/MaxMindGeoIP/geoipcity.inc b/libs/MaxMindGeoIP/geoipcity.inc
deleted file mode 100644
index 44ed49b878..0000000000
--- a/libs/MaxMindGeoIP/geoipcity.inc
+++ /dev/null
@@ -1,241 +0,0 @@
-<?php
-
-/* geoipcity.inc
- *
- * Copyright (C) 2013 MaxMind, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-define("FULL_RECORD_LENGTH", 50);
-
-require_once 'geoip.inc';
-require_once 'geoipregionvars.php';
-
-class geoiprecord
-{
- public $country_code;
- public $country_code3;
- public $country_name;
- public $region;
- public $city;
- public $postal_code;
- public $latitude;
- public $longitude;
- public $area_code;
- public $dma_code; # metro and dma code are the same. use metro_code
- public $metro_code;
- public $continent_code;
-}
-
-class geoipdnsrecord
-{
- public $country_code;
- public $country_code3;
- public $country_name;
- public $region;
- public $regionname;
- public $city;
- public $postal_code;
- public $latitude;
- public $longitude;
- public $areacode;
- public $dmacode;
- public $isp;
- public $org;
- public $metrocode;
-}
-
-function getrecordwithdnsservice($str)
-{
- $record = new geoipdnsrecord;
- $keyvalue = explode(";", $str);
- foreach ($keyvalue as $keyvalue2) {
- list($key, $value) = explode("=", $keyvalue2);
- if ($key == "co") {
- $record->country_code = $value;
- }
- if ($key == "ci") {
- $record->city = $value;
- }
- if ($key == "re") {
- $record->region = $value;
- }
- if ($key == "ac") {
- $record->areacode = $value;
- }
- if ($key == "dm" || $key == "me") {
- $record->dmacode = $value;
- $record->metrocode = $value;
- }
- if ($key == "is") {
- $record->isp = $value;
- }
- if ($key == "or") {
- $record->org = $value;
- }
- if ($key == "zi") {
- $record->postal_code = $value;
- }
- if ($key == "la") {
- $record->latitude = $value;
- }
- if ($key == "lo") {
- $record->longitude = $value;
- }
- }
- $number = $GLOBALS['GEOIP_COUNTRY_CODE_TO_NUMBER'][$record->country_code];
- $record->country_code3 = $GLOBALS['GEOIP_COUNTRY_CODES3'][$number];
- $record->country_name = $GLOBALS['GEOIP_COUNTRY_NAMES'][$number];
- if ($record->region != "") {
- if (($record->country_code == "US") || ($record->country_code == "CA")) {
- $record->regionname = $GLOBALS['ISO'][$record->country_code][$record->region];
- } else {
- $record->regionname = $GLOBALS['FIPS'][$record->country_code][$record->region];
- }
- }
- return $record;
-}
-
-
-function _get_record_v6($gi, $ipnum)
-{
- $seek_country = _geoip_seek_country_v6($gi, $ipnum);
- if ($seek_country == $gi->databaseSegments) {
- return null;
- }
- return _common_get_record($gi, $seek_country);
-}
-
-function _common_get_record($gi, $seek_country)
-{
- // workaround php's broken substr, strpos, etc handling with
- // mbstring.func_overload and mbstring.internal_encoding
- $mbExists = extension_loaded('mbstring');
- if ($mbExists) {
- $enc = mb_internal_encoding();
- mb_internal_encoding('ISO-8859-1');
- }
-
- $record_pointer = $seek_country + (2 * $gi->record_length - 1) * $gi->databaseSegments;
-
- if ($gi->flags & GEOIP_MEMORY_CACHE) {
- $record_buf = substr($gi->memory_buffer, $record_pointer, FULL_RECORD_LENGTH);
- } elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
- $record_buf = @shmop_read($gi->shmid, $record_pointer, FULL_RECORD_LENGTH);
- } else {
- fseek($gi->filehandle, $record_pointer, SEEK_SET);
- $record_buf = fread($gi->filehandle, FULL_RECORD_LENGTH);
- }
- $record = new geoiprecord;
- $record_buf_pos = 0;
- $char = ord(substr($record_buf, $record_buf_pos, 1));
- $record->country_code = $gi->GEOIP_COUNTRY_CODES[$char];
- $record->country_code3 = $gi->GEOIP_COUNTRY_CODES3[$char];
- $record->country_name = $gi->GEOIP_COUNTRY_NAMES[$char];
- $record->continent_code = $gi->GEOIP_CONTINENT_CODES[$char];
- $record_buf_pos++;
- $str_length = 0;
-
- // Get region
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- while ($char != 0) {
- $str_length++;
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- }
- if ($str_length > 0) {
- $record->region = substr($record_buf, $record_buf_pos, $str_length);
- }
- $record_buf_pos += $str_length + 1;
- $str_length = 0;
- // Get city
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- while ($char != 0) {
- $str_length++;
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- }
- if ($str_length > 0) {
- $record->city = substr($record_buf, $record_buf_pos, $str_length);
- }
- $record_buf_pos += $str_length + 1;
- $str_length = 0;
- // Get postal code
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- while ($char != 0) {
- $str_length++;
- $char = ord(substr($record_buf, $record_buf_pos + $str_length, 1));
- }
- if ($str_length > 0) {
- $record->postal_code = substr($record_buf, $record_buf_pos, $str_length);
- }
- $record_buf_pos += $str_length + 1;
- $str_length = 0;
- // Get latitude and longitude
- $latitude = 0;
- $longitude = 0;
- for ($j = 0; $j < 3; ++$j) {
- $char = ord(substr($record_buf, $record_buf_pos++, 1));
- $latitude += ($char << ($j * 8));
- }
- $record->latitude = ($latitude / 10000) - 180;
- for ($j = 0; $j < 3; ++$j) {
- $char = ord(substr($record_buf, $record_buf_pos++, 1));
- $longitude += ($char << ($j * 8));
- }
- $record->longitude = ($longitude / 10000) - 180;
- if (GEOIP_CITY_EDITION_REV1 == $gi->databaseType) {
- $metroarea_combo = 0;
- if ($record->country_code == "US") {
- for ($j = 0; $j < 3; ++$j) {
- $char = ord(substr($record_buf, $record_buf_pos++, 1));
- $metroarea_combo += ($char << ($j * 8));
- }
- $record->metro_code = $record->dma_code = floor($metroarea_combo / 1000);
- $record->area_code = $metroarea_combo % 1000;
- }
- }
- if ($mbExists) {
- mb_internal_encoding($enc);
- }
- return $record;
-}
-
-function GeoIP_record_by_addr_v6($gi, $addr)
-{
- if ($addr == null) {
- return 0;
- }
- $ipnum = inet_pton($addr);
- return _get_record_v6($gi, $ipnum);
-}
-
-function _get_record($gi, $ipnum)
-{
- $seek_country = _geoip_seek_country($gi, $ipnum);
- if ($seek_country == $gi->databaseSegments) {
- return null;
- }
- return _common_get_record($gi, $seek_country);
-}
-
-function GeoIP_record_by_addr($gi, $addr)
-{
- if ($addr == null) {
- return 0;
- }
- $ipnum = ip2long($addr);
- return _get_record($gi, $ipnum);
-}
diff --git a/plugins/GeoIp2/Columns/Region.php b/plugins/GeoIp2/Columns/Region.php
deleted file mode 100644
index 934251b60e..0000000000
--- a/plugins/GeoIp2/Columns/Region.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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
- }
-} \ No newline at end of file
diff --git a/plugins/GeoIp2/Controller.php b/plugins/GeoIp2/Controller.php
new file mode 100644
index 0000000000..2de183067e
--- /dev/null
+++ b/plugins/GeoIp2/Controller.php
@@ -0,0 +1,200 @@
+<?php
+namespace Piwik\Plugins\GeoIp2;
+
+use Piwik\Common;
+use Piwik\DataTable\Renderer\Json;
+use Piwik\Http;
+use Piwik\Piwik;
+use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
+use Piwik\Plugins\UserCountry\UserCountry;
+use Piwik\View;
+
+class Controller extends \Piwik\Plugin\ControllerAdmin
+{
+ /**
+ * Starts or continues download of DBIP-City.mmdb.
+ *
+ * To avoid a server/PHP timeout & to show progress of the download to the user, we
+ * use the HTTP Range header to download one chunk of the file at a time. After each
+ * chunk, it is the browser's responsibility to call the method again to continue the download.
+ *
+ * Input:
+ * 'continue' query param - if set to 1, will assume we are currently downloading & use
+ * Range: HTTP header to get another chunk of the file.
+ *
+ * Output (in JSON):
+ * 'current_size' - Current size of the partially downloaded file on disk.
+ * 'expected_file_size' - The expected finished file size as returned by the HTTP server.
+ * 'next_screen' - When the download finishes, this is the next screen that should be shown.
+ * 'error' - When an error occurs, the message is returned in this property.
+ */
+ public function downloadFreeDBIPLiteDB()
+ {
+ $this->dieIfGeolocationAdminIsDisabled();
+ Piwik::checkUserHasSuperUserAccess();
+
+ if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ $this->checkTokenInUrl();
+ Json::sendHeaderJSON();
+ $outputPath = GeoIp2::getPathForGeoIpDatabase('DBIP-City.mmdb') . '.gz';
+ try {
+ $result = Http::downloadChunk(
+ $url = GeoIp2::getDbIpLiteUrl(),
+ $outputPath,
+ $continue = Common::getRequestVar('continue', true, 'int')
+ );
+
+ // if the file is done
+ if ($result['current_size'] >= $result['expected_file_size']) {
+ try {
+ GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, 'loc', $url, $unlink = true);
+ } catch (\Exception $e) {
+ // remove downloaded file on error
+ unlink($outputPath);
+ throw $e;
+ }
+
+ // setup the auto updater
+ GeoIP2AutoUpdater::setUpdaterOptions(array(
+ 'loc' => GeoIp2::getDbIpLiteUrl(),
+ 'period' => GeoIP2AutoUpdater::SCHEDULE_PERIOD_MONTHLY,
+ ));
+
+ $result['settings'] = GeoIP2AutoUpdater::getConfiguredUrls();
+ }
+
+ return json_encode($result);
+ } catch (\Exception $ex) {
+ return json_encode(array('error' => $ex->getMessage()));
+ }
+ }
+ }
+
+ /**
+ * Sets the URLs used to download new versions of the installed GeoIP databases.
+ *
+ * Input (query params):
+ * 'loc_db' - URL for a GeoIP location database.
+ * 'isp_db' - URL for a GeoIP ISP database (optional).
+ * 'org_db' - URL for a GeoIP Org database (optional).
+ * 'period' - 'weekly' or 'monthly'. Determines how often update is run.
+ *
+ * Output (json):
+ * 'error' - if an error occurs its message is set as the resulting JSON object's
+ * 'error' property.
+ */
+ public function updateGeoIPLinks()
+ {
+ $this->dieIfGeolocationAdminIsDisabled();
+ Piwik::checkUserHasSuperUserAccess();
+ if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ Json::sendHeaderJSON();
+ try {
+ $this->checkTokenInUrl();
+
+ GeoIP2AutoUpdater::setUpdaterOptionsFromUrl();
+
+ // if there is a updater URL for a database, but its missing from the misc dir, tell
+ // the browser so it can download it next
+ $info = $this->getNextMissingDbUrlInfoGeoIp2();
+
+ if ($info !== false) {
+ return json_encode($info);
+ } else {
+ $view = new View("@GeoIp2/_updaterNextRunTime");
+ $view->nextRunTime = GeoIP2AutoUpdater::getNextRunTime();
+ $nextRunTimeHtml = $view->render();
+ return json_encode(array('nextRunTime' => $nextRunTimeHtml));
+ }
+ } catch (\Exception $ex) {
+ return json_encode(array('error' => $ex->getMessage()));
+ }
+ }
+ }
+
+ /**
+ * Starts or continues a download for a missing GeoIP database. A database is missing if
+ * it has an update URL configured, but the actual database is not available in the misc
+ * directory.
+ *
+ * Input:
+ * 'url' - The URL to download the database from.
+ * 'continue' - 1 if we're continuing a download, 0 if we're starting one.
+ *
+ * Output:
+ * 'error' - If an error occurs this describes the error.
+ * 'to_download' - The URL of a missing database that should be downloaded next (if any).
+ * 'to_download_label' - The label to use w/ the progress bar that describes what we're
+ * downloading.
+ * 'current_size' - Size of the current file on disk.
+ * 'expected_file_size' - Size of the completely downloaded file.
+ */
+ public function downloadMissingGeoIpDb()
+ {
+ $this->dieIfGeolocationAdminIsDisabled();
+ Piwik::checkUserHasSuperUserAccess();
+
+ if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ try {
+ $this->checkTokenInUrl();
+
+ Json::sendHeaderJSON();
+
+ // based on the database type (provided by the 'key' query param) determine the
+ // url & output file name
+ $key = Common::getRequestVar('key', null, 'string');
+
+ $url = GeoIP2AutoUpdater::getConfiguredUrl($key);
+ $filename = GeoIP2AutoUpdater::getZippedFilenameToDownloadTo($url, $key, GeoIP2AutoUpdater::getGeoIPUrlExtension($url));
+ $outputPath = GeoIp2::getPathForGeoIpDatabase($filename);
+
+ // download part of the file
+ $result = Http::downloadChunk(
+ $url, $outputPath, Common::getRequestVar('continue', true, 'int'));
+
+ // if the file is done
+ if ($result['current_size'] >= $result['expected_file_size']) {
+ GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, $key, $url, $unlink = true);
+
+ $info = $this->getNextMissingDbUrlInfoGeoIp2();
+ if ($info !== false) {
+ return json_encode($info);
+ }
+ }
+
+ return json_encode($result);
+ } catch (\Exception $ex) {
+ return json_encode(array('error' => $ex->getMessage()));
+ }
+ }
+ }
+
+ /**
+ * Gets information for the first missing GeoIP2 database (if any).
+ *
+ * @return array|bool
+ */
+ private function getNextMissingDbUrlInfoGeoIp2()
+ {
+ $missingDbs = GeoIP2AutoUpdater::getMissingDatabases();
+ if (!empty($missingDbs)) {
+ $missingDbKey = $missingDbs[0];
+ $url = GeoIP2AutoUpdater::getConfiguredUrl($missingDbKey);
+
+ $link = '<a href="' . $url . '">' . $url . '</a>';
+
+ return [
+ 'to_download' => $missingDbKey,
+ 'to_download_label' => Piwik::translate('GeoIp2_DownloadingDb', $link) . '...',
+ ];
+ }
+ return false;
+ }
+
+ private function dieIfGeolocationAdminIsDisabled()
+ {
+ if (!UserCountry::isGeoLocationAdminEnabled()) {
+ throw new \Exception('Geo location setting page has been disabled.');
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/GeoIp2/GeoIP2AutoUpdater.php b/plugins/GeoIp2/GeoIP2AutoUpdater.php
index 423256be83..dcc79dfdbd 100644
--- a/plugins/GeoIp2/GeoIP2AutoUpdater.php
+++ b/plugins/GeoIp2/GeoIP2AutoUpdater.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\GeoIp2;
require_once PIWIK_INCLUDE_PATH . "/core/ScheduledTask.php"; // for the tracker which doesn't include this file
use Exception;
+use GeoIp2\Database\Reader;
use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\Date;
@@ -21,7 +22,6 @@ 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;
@@ -200,7 +200,7 @@ class GeoIP2AutoUpdater extends Task
$content = $unzip->listContent();
if (empty($content)) {
- throw new Exception(Piwik::translate('UserCountry_CannotListContent',
+ throw new Exception(Piwik::translate('GeoIp2_CannotListContent',
array("'$path'", $unzip->errorInfo())));
}
@@ -253,7 +253,7 @@ class GeoIP2AutoUpdater extends Task
$success = $unzip->extract($outputPath);
if ($success !== true) {
- throw new Exception(Piwik::translate('UserCountry_CannotUnzipDatFile',
+ throw new Exception(Piwik::translate('General_CannotUnzipFile',
array("'$path'", $unzip->errorInfo())));
}
@@ -263,7 +263,7 @@ class GeoIP2AutoUpdater extends Task
}
} else {
$ext = end(explode(basename($path), '.', 2));
- throw new Exception(Piwik::translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
+ throw new Exception(Piwik::translate('GeoIp2_UnsupportedArchiveType', "'$ext'"));
}
try {
@@ -286,11 +286,11 @@ class GeoIP2AutoUpdater extends Task
Log::info("GeoIP2AutoUpdater: Encountered exception when testing newly downloaded" .
" GeoIP 2 database: %s", $e->getMessage());
- throw new Exception(Piwik::translate('UserCountry_ThisUrlIsNotAValidGeoIPDB'));
+ throw new Exception(Piwik::translate('GeoIp2_ThisUrlIsNotAValidGeoIPDB'));
}
if (empty($location)) {
- throw new Exception(Piwik::translate('UserCountry_ThisUrlIsNotAValidGeoIPDB'));
+ throw new Exception(Piwik::translate('GeoIp2_ThisUrlIsNotAValidGeoIPDB'));
}
// delete the existing GeoIP database (if any) and rename the downloaded file
@@ -403,7 +403,7 @@ class GeoIP2AutoUpdater extends Task
&& $period != self::SCHEDULE_PERIOD_WEEKLY
) {
throw new Exception(Piwik::translate(
- 'UserCountry_InvalidGeoIPUpdatePeriod',
+ 'GeoIp2_InvalidGeoIPUpdatePeriod',
array("'$period'", "'" . self::SCHEDULE_PERIOD_MONTHLY . "', '" . self::SCHEDULE_PERIOD_WEEKLY . "'")
));
}
@@ -415,9 +415,6 @@ class GeoIP2AutoUpdater extends Task
$scheduler->rescheduleTaskAndRunTomorrow(new GeoIP2AutoUpdater());
}
-
- // clear option for GeoIP as not needed if GeoIP2 is set up
- GeoIPAutoUpdater::clearOptions();
}
/**
@@ -559,7 +556,7 @@ class GeoIP2AutoUpdater extends Task
&& $ext != 'gz'
&& $ext != 'mmdb.gz'
) {
- throw new \Exception(Piwik::translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
+ throw new \Exception(Piwik::translate('GeoIp2_UnsupportedArchiveType', "'$ext'"));
}
}
@@ -592,9 +589,13 @@ class GeoIP2AutoUpdater extends Task
// test the provider. on error, we rename the broken DB.
try {
+ // check database directly, as location provider ignores invalid database errors
+ $pathToDb = LocationProviderGeoIp2::getPathToGeoIpDatabase($customNames);
+ $reader = new Reader($pathToDb);
+
$location = $provider->getLocation(array('ip' => LocationProviderGeoIp2::TEST_IP));
} catch (\Exception $e) {
- if($logErrors) {
+ if ($logErrors) {
Log::error("GeoIP2AutoUpdater: Encountered exception when performing redundant tests on GeoIP2 "
. "%s database: %s", $type, $e->getMessage());
}
diff --git a/plugins/GeoIp2/GeoIp2.php b/plugins/GeoIp2/GeoIp2.php
index 62562d8924..ffba09bd98 100644
--- a/plugins/GeoIp2/GeoIp2.php
+++ b/plugins/GeoIp2/GeoIp2.php
@@ -15,6 +15,14 @@ use Piwik\Plugins\UserCountry\LocationProvider;
*/
class GeoIp2 extends \Piwik\Plugin
{
+ public function registerEvents()
+ {
+ return array(
+ 'AssetManager.getJavaScriptFiles' => 'getJsFiles',
+ 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
+ );
+ }
+
public function isTrackerPlugin()
{
return true;
@@ -27,4 +35,19 @@ class GeoIp2 extends \Piwik\Plugin
LocationProvider::setCurrentProvider(LocationProvider\DefaultProvider::ID);
}
}
+
+ public function getJsFiles(&$jsFiles)
+ {
+ $jsFiles[] = "plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.controller.js";
+ $jsFiles[] = "plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.directive.js";
+ }
+
+ public function getClientSideTranslationKeys(&$translationKeys)
+ {
+ $translationKeys[] = "GeoIp2_FatalErrorDuringDownload";
+ $translationKeys[] = "GeoIp2_SetupAutomaticUpdatesOfGeoIP";
+ $translationKeys[] = "General_Done";
+ $translationKeys[] = "General_Save";
+ $translationKeys[] = "General_Continue";
+ }
}
diff --git a/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php b/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
index 310a273dc4..6a92f4f409 100644
--- a/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
+++ b/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
@@ -11,11 +11,17 @@ namespace Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
use MaxMind\Db\Reader\InvalidDatabaseException;
+use Piwik\Date;
use Piwik\Common;
use Piwik\Log;
use Piwik\Piwik;
+use Piwik\Plugin\Manager;
+use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater;
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
use Piwik\Plugins\Marketplace\Api\Exception;
+use Piwik\Plugins\UserCountry\LocationProvider;
+use Piwik\SettingsPiwik;
+use Piwik\View;
/**
* A LocationProvider that uses the PHP implementation of GeoIP 2.
@@ -391,16 +397,16 @@ class Php extends GeoIp2
}
if (isset($availableInfo[self::ISP_KEY]) && $availableInfo[self::ISP_KEY]) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_ISPDatabase');
+ $availableDatabaseTypes[] = Piwik::translate('GeoIp2_ISPDatabase');
}
if (!empty($availableDatabaseTypes)) {
$extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>:&nbsp;'
- . Piwik::translate('UserCountry_GeoIPImplHasAccessTo') . ':&nbsp;<strong>'
+ . Piwik::translate('GeoIp2_GeoIPImplHasAccessTo') . ':&nbsp;<strong>'
. implode(', ', $availableDatabaseTypes) . '</strong>.';
} else {
$extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>:&nbsp;'
- . Piwik::translate('UserCountry_GeoIPNoDatabaseFound');
+ . Piwik::translate('GeoIp2_GeoIPNoDatabaseFound');
}
return array('id' => self::ID,
@@ -411,6 +417,67 @@ class Php extends GeoIp2
'order' => 2);
}
+ public function renderConfiguration()
+ {
+ $view = new View('@GeoIp2/configuration.twig');
+ $today = Date::today();
+
+ $urls = GeoIP2AutoUpdater::getConfiguredUrls();
+ $view->geoIPLocUrl = $urls['loc'];
+ $view->geoIPIspUrl = $urls['isp'];
+ $view->geoIPUpdatePeriod = GeoIP2AutoUpdater::getSchedulePeriod();
+
+ $view->hasGeoIp2Provider = Manager::getInstance()->isPluginActivated('GeoIp2');
+
+ $geoIPDatabasesInstalled = $view->hasGeoIp2Provider ? GeoIp2::isDatabaseInstalled() : false;
+
+ $view->geoIPDatabasesInstalled = $geoIPDatabasesInstalled;
+ $view->updatePeriodOptions = [
+ 'month' => Piwik::translate('Intl_PeriodMonth'),
+ 'week' => Piwik::translate('Intl_PeriodWeek')
+ ];
+
+
+ // if using a server module, they are working and there are no databases
+ // in misc, then the databases are located outside of Matomo, so we cannot update them
+ $view->showGeoIPUpdateSection = true;
+ $currentProviderId = LocationProvider::getCurrentProviderId();
+ if (!$geoIPDatabasesInstalled
+ && in_array($currentProviderId, [GeoIp2\ServerModule::ID])
+ && LocationProvider::getCurrentProvider()->isWorking()
+ && LocationProvider::getCurrentProvider()->isAvailable()
+ ) {
+ $view->showGeoIPUpdateSection = false;
+ }
+
+ $view->isInternetEnabled = SettingsPiwik::isInternetEnabled();
+
+
+ $view->dbipLiteUrl = GeoIp2::getDbIpLiteUrl();
+ $view->dbipLiteFilename = "dbip-city-lite-{$today->toString('Y-m')}.mmdb";
+ $view->dbipLiteDesiredFilename = "DBIP-City.mmdb";
+ $view->nextRunTime = GeoIP2AutoUpdater::getNextRunTime();
+
+ $lastRunTime = GeoIP2AutoUpdater::getLastRunTime();
+
+ if ($lastRunTime !== false) {
+ $view->lastTimeUpdaterRun = '<strong>' . $lastRunTime->toString() . '</strong>';
+ }
+ return $view->render();
+ }
+
+ public function renderSetUpGuide()
+ {
+ $today = Date::today();
+ $view = new View('@GeoIp2/setupguide.twig');
+
+ $view->dbipLiteUrl = GeoIp2::getDbIpLiteUrl();
+ $view->dbipLiteFilename = "dbip-city-lite-{$today->toString('Y-m')}.mmdb";
+ $view->dbipLiteDesiredFilename = "DBIP-City.mmdb";
+
+ return $view->render();
+ }
+
/**
* Returns a GeoIP2 reader instance. Creates it if necessary.
*
diff --git a/plugins/GeoIp2/LocationProvider/GeoIp2/ServerModule.php b/plugins/GeoIp2/LocationProvider/GeoIp2/ServerModule.php
index 5e2facc549..5ebe6114ce 100644
--- a/plugins/GeoIp2/LocationProvider/GeoIp2/ServerModule.php
+++ b/plugins/GeoIp2/LocationProvider/GeoIp2/ServerModule.php
@@ -159,11 +159,11 @@ class ServerModule extends GeoIp2
// if not available return message w/ extra info
if (!function_exists('apache_get_modules')) {
- return Piwik::translate('General_Note') . ':&nbsp;' . Piwik::translate('UserCountry_AssumingNonApache');
+ return Piwik::translate('General_Note') . ':&nbsp;' . Piwik::translate('GeoIp2_AssumingNonApache');
}
$message = "<strong>" . Piwik::translate('General_Note') . ':&nbsp;'
- . Piwik::translate('UserCountry_FoundApacheModules')
+ . Piwik::translate('GeoIp2_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";
@@ -187,7 +187,7 @@ class ServerModule extends GeoIp2
|| array_key_exists($settings[self::CITY_NAME_KEY], $_SERVER);
if (!$available) {
- return Piwik::translate("UserCountry_CannotFindGeoIPServerVar", $settings[self::COUNTRY_CODE_KEY] . ' $_SERVER');
+ return Piwik::translate('GeoIp2_CannotFindGeoIPServerVar', $settings[self::COUNTRY_CODE_KEY] . ' $_SERVER');
}
return true;
@@ -209,24 +209,24 @@ class ServerModule extends GeoIp2
if (function_exists('apache_note')) {
$serverDesc = 'Apache';
} else {
- $serverDesc = Piwik::translate('UserCountry_HttpServerModule');
+ $serverDesc = Piwik::translate('GeoIp2_HttpServerModule');
}
$title = sprintf(self::TITLE, $serverDesc);
$desc = Piwik::translate('GeoIp2_LocationProviderDesc_ServerModule', array('<strong>', '</strong>'))
. '<br/><br/>'
- . Piwik::translate('UserCountry_GeoIpLocationProviderDesc_ServerBasedAnonWarn')
+ . Piwik::translate('GeoIp2_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')
+ . Piwik::translate('GeoIp2_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')
+ . Piwik::translate('GeoIp2_HowToInstallNginxModule')
. '</a>';
$geoipServerVars = array();
@@ -237,9 +237,9 @@ class ServerModule extends GeoIp2
}
if (empty($geoipServerVars)) {
- $extraMessage = '<strong>' . Piwik::translate('UserCountry_GeoIPNoServerVars', '$_SERVER') . '</strong>';
+ $extraMessage = '<strong>' . Piwik::translate('GeoIp2_GeoIPNoServerVars', '$_SERVER') . '</strong>';
} else {
- $extraMessage = '<strong>' . Piwik::translate('UserCountry_GeoIPServerVarsFound', '$_SERVER')
+ $extraMessage = '<strong>' . Piwik::translate('GeoIp2_GeoIPServerVarsFound', '$_SERVER')
. ":</strong><br/><br/>\n<ul style=\"list-style:disc;margin-left:24px\">\n";
foreach ($geoipServerVars as $key) {
$extraMessage .= '<li>' . $key . "</li>\n";
diff --git a/plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.controller.js b/plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.controller.js
index 677acec8a3..d52224d75a 100644
--- a/plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.controller.js
+++ b/plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.controller.js
@@ -5,11 +5,11 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
(function () {
- angular.module('piwikApp').controller('LocationProviderUpdaterController', LocationProviderUpdaterController);
+ angular.module('piwikApp').controller('Geoip2UpdaterController', Geoip2UpdaterController);
- LocationProviderUpdaterController.$inject = ['piwikApi', '$window'];
+ Geoip2UpdaterController.$inject = ['piwikApi', '$window'];
- function LocationProviderUpdaterController(piwikApi, $window) {
+ function Geoip2UpdaterController(piwikApi, $window) {
// remember to keep controller very simple. Create a service/factory (model) if needed
var self = this;
@@ -25,7 +25,7 @@
piwikApi.withTokenInUrl();
piwikApi.post({
- module: 'UserCountry',
+ module: 'GeoIp2',
action: action,
'continue': cont ? 1 : 0
}, data).then(function (response) {
@@ -44,7 +44,7 @@
}
}
}, function () {
- callback({error: _pk_translate('UserCountry_FatalErrorDuringDownload')});
+ callback({error: _pk_translate('GeoIp2_FatalErrorDuringDownload')});
});
};
@@ -56,7 +56,7 @@
// start download of free dbs
downloadNextChunk(
- 'downloadFreeGeoIPDB',
+ 'downloadFreeDBIPLiteDB',
'geoipdb-screen2-download',
'progressFreeDownload',
false,
@@ -81,7 +81,7 @@
this.geoipDatabaseInstalled = true;
// todo we need to replace this the proper way eventually
- $('#geoip-db-mangement .card-title').text(_pk_translate('UserCountry_SetupAutomaticUpdatesOfGeoIP'));
+ $('#geoip-db-mangement .card-title').text(_pk_translate('GeoIp2_SetupAutomaticUpdatesOfGeoIP'));
}
this.saveGeoIpLinks = function () {
@@ -135,7 +135,7 @@
piwikApi.withTokenInUrl();
piwikApi.post({
period: this.updatePeriod,
- module: 'UserCountry',
+ module: 'GeoIp2',
action: 'updateGeoIPLinks'
}, {
loc_db: this.locationDbUrl,
diff --git a/plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.directive.js b/plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.directive.js
index 441689f714..9b21145feb 100644
--- a/plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.directive.js
+++ b/plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.directive.js
@@ -7,19 +7,19 @@
/**
* Usage:
- * <div piwik-location-provider-selection>
+ * <div piwik-geoip2-updater>
*/
(function () {
- angular.module('piwikApp').directive('piwikLocationProviderUpdater', piwikLocationProviderUpdater);
+ angular.module('piwikApp').directive('piwikGeoip2Updater', piwikGeoip2Updater);
- piwikLocationProviderUpdater.$inject = ['piwik'];
+ piwikGeoip2Updater.$inject = ['piwik'];
- function piwikLocationProviderUpdater(piwik){
+ function piwikGeoip2Updater(piwik){
return {
restrict: 'A',
transclude: true,
- controller: 'LocationProviderUpdaterController',
+ controller: 'Geoip2UpdaterController',
controllerAs: 'locationUpdater',
template: '<div ng-transclude></div>',
compile: function (element, attrs) {
diff --git a/plugins/GeoIp2/lang/en.json b/plugins/GeoIp2/lang/en.json
index d0559328eb..158028266e 100644
--- a/plugins/GeoIp2/lang/en.json
+++ b/plugins/GeoIp2/lang/en.json
@@ -1,15 +1,57 @@
{
"GeoIp2": {
+ "AssumingNonApache": "Cannot find apache_get_modules function, assuming non-Apache webserver.",
"CannotFindGeoIPDatabaseInArchive": "No valid DBIP / GeoIP database could be found in tar archive %1$s!",
+ "CannotFindGeoIPServerVar": "The %s variable is not set. Your server may not be configured correctly.",
+ "CannotListContent": "Couldn't list content for %1$s: %2$s",
+ "CannotSetupGeoIPAutoUpdating": "It seems like you're storing your geolocation databases outside of Matomo (we can tell since there are no databases in the misc subdirectory, but your GeoIP is working). Matomo cannot automatically update your geolocation databases if they are located outside of the misc directory.",
"CannotUnzipGeoIPFile": "Could not unzip GeoIP file in %1$s: %2$s",
+ "DownloadingDb": "Downloading %s",
+ "DownloadNewDatabasesEvery": "Update databases every",
+ "FatalErrorDuringDownload": "A fatal error occurred while downloading this file. There might be something wrong with your internet connection, with the geolocation database you downloaded or Matomo. Try downloading and installing it manually.",
+ "FoundApacheModules": "Matomo found the following Apache modules",
+ "GeoIPImplHasAccessTo": "This GeoIP implementation has access to the following types of databases",
+ "GeoIPDatabases": "GeoIP Databases",
+ "GeoIPLocationProviderDesc_ServerBasedAnonWarn": "Note: IP anonymization has no effect on the locations reported by this provider. Before using it with IP anonymization, make sure this does not violate any privacy laws you may be subject to.",
+ "GeoIPLocationProviderNotRecommended": "Geolocation works, but you are not using one of the recommended providers.",
+ "GeoIPNoDatabaseFound": "This GeoIP implementation was not able to find any database.",
+ "GeoIPNoServerVars": "Matomo cannot find any GeoIP %s variables.",
+ "GeoIPServerVarsFound": "Matomo detects the following GeoIP %s variables",
+ "GeoIPUpdaterInstructions": "Enter the download links for your databases below. If you've purchased databases from %3$sdbip%4$s or %1$sMaxMind%2$s, you can find these links in your dbip or MaxMind account. Please contact your geolocation database provider if you have trouble accessing them.",
+ "GeoIPUpdaterIntro": "Matomo is currently managing updates for the following databases",
+ "GeoIPVariablesConfigurationHere": "You can configure used server variables %1$shere%2$s.",
+ "GeoLiteCityLink": "If you're using the dbip city lite database, use this link: %1$s%2$s%3$s",
+ "HowToSetupGeoIP": "How to setup accurate geolocation with dbip",
+ "HowToSetupGeoIP_Step1": "%1$sDownload%2$s the DBIP City Lite database from %3$sdbip%4$s.",
+ "HowToSetupGeoIP_Step2": "Extract this file and copy the result, %1$s into the %2$smisc%3$s Matomo subdirectory and rename it to %4$s (you can do this either by FTP or SSH).",
+ "HowToSetupGeoIP_Step3": "Reload this screen. The %1$sDBIP / GeoIP (PHP)%2$s provider will now be %3$sInstalled%4$s. Select it.",
+ "HowToSetupGeoIP_Step4": "And you're done! You've just setup Matomo to use DBIP which means you'll be able to see the regions and cities of your visitors along with very accurate country information.",
+ "HowToSetupGeoIPIntro": "You do not appear to have accurate Geolocation setup. This is a useful feature and without it you will not see accurate and complete location information for your visitors. Here's how you can quickly start using it:",
+ "HowToInstallApacheModule": "How do I install the GeoIP module for Apache?",
+ "HowToInstallNginxModule": "How do I install the GeoIP module for Nginx?",
+ "HttpServerModule": "HTTP Server Module",
+ "InvalidGeoIPUpdatePeriod": "Invalid period for the GeoIP updater: %1$s. Valid values are %2$s.",
+ "IPurchasedGeoIPDBs": "I purchased more accurate databases from %3$sdbip%4$s or %1$sMaxMind%2$s and want to setup automatic updates.",
+ "ISPDatabase": "ISP Database",
+ "IWantToDownloadFreeGeoIP": "I want to download the free DBIP database...",
"PluginDescription": "Provides DBIP / GeoIP2 location providers.",
+ "LocationDatabase": "Location Database",
+ "LocationDatabaseHint": "A location database is either a country, region or city database.",
"LocationProviderDesc_Php": "This location provider is the simplest to install as it does not require server configuration (ideal for shared hosting!). It uses a DBIP or 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.",
+ "NotManagingGeoIPDBs": "Matomo is currently not managing any DBIP or MaxMind databases.",
+ "UnsupportedArchiveType": "Encountered unsupported archive type %1$s.",
+ "UpdaterHasNotBeenRun": "The updater has never been run.",
+ "UpdaterIsNotScheduledToRun": "It is not scheduled to run in the future.",
+ "UpdaterScheduledForNextRun": "It is scheduled to run during the next cron core:archive command execution.",
+ "UpdaterWasLastRun": "The updater was last run on %s.",
+ "UpdaterWillRunNext": "It is next scheduled to run on %s.",
"ShowCustomServerVariablesConfig": "I use the Geoip2 server module (Nginx, Apache...) and want to configure server variables",
- "ServerVariableFor": "Server variable for %s"
+ "ServerBasedVariablesConfiguration": "Configuration for server variables used by GeoIP 2 server modules",
+ "ServerVariableFor": "Server variable for %s",
+ "SetupAutomaticUpdatesOfGeoIP": "Setup automatic updates of geolocation databases",
+ "ThisUrlIsNotAValidGeoIPDB": "The downloaded file is not a valid geolocation database. Please re-check the URL or download the file manually."
}
} \ No newline at end of file
diff --git a/plugins/UserCountry/templates/_updaterManage.twig b/plugins/GeoIp2/templates/_updaterManage.twig
index e624a97d9a..f110de26da 100644
--- a/plugins/UserCountry/templates/_updaterManage.twig
+++ b/plugins/GeoIp2/templates/_updaterManage.twig
@@ -1,53 +1,44 @@
<div ng-show="locationUpdater.geoipDatabaseInstalled" id="geoipdb-update-info">
<p>
- {{ 'UserCountry_GeoIPUpdaterInstructions'|translate('<a href="http://www.maxmind.com/?rId=piwik">','</a>','<a rel="noreferrer noopener" href="https://db-ip.com/?refid=mtm">','</a>')|raw }}
+ {{ 'GeoIp2_GeoIPUpdaterInstructions'|translate('<a href="http://www.maxmind.com/?rId=piwik">','</a>','<a rel="noreferrer noopener" href="https://db-ip.com/?refid=mtm">','</a>')|raw }}
<br/><br/>
- {% if dbipLiteUrl|default is not empty %}{{ 'UserCountry_GeoLiteCityLink'|translate('<a rel="noreferrer noopener" href="'~dbipLiteUrl|e('html_attr')~'">',dbipLiteUrl|e('html'),'</a>')|raw }}{% endif %}
+ {% if dbipLiteUrl|default is not empty %}{{ 'GeoIp2_GeoLiteCityLink'|translate('<a rel="noreferrer noopener" href="'~dbipLiteUrl|e('html_attr')~'">',dbipLiteUrl|e('html'),'</a>')|raw }}{% endif %}
<span ng-show="locationUpdater.geoipDatabaseInstalled">
- <br/><br/>{{ 'UserCountry_GeoIPUpdaterIntro'|translate }}:
+ <br/><br/>{{ 'GeoIp2_GeoIPUpdaterIntro'|translate }}:
</span>
</p>
<div piwik-field uicontrol="text" name="geoip-location-db"
ng-model="locationUpdater.locationDbUrl"
- introduction="{{ 'UserCountry_LocationDatabase'|translate|e('html_attr') }}"
+ introduction="{{ 'GeoIp2_LocationDatabase'|translate|e('html_attr') }}"
data-title="{{ 'Actions_ColumnDownloadURL'|translate|e('html_attr') }}"
value="{{ geoIPLocUrl }}"
- inline-help="{{ 'UserCountry_LocationDatabaseHint'|translate|e('html_attr') }}">
+ inline-help="{{ 'GeoIp2_LocationDatabaseHint'|translate|e('html_attr') }}">
</div>
<div piwik-field uicontrol="text" name="geoip-isp-db"
ng-model="locationUpdater.ispDbUrl"
- introduction="{{ 'UserCountry_ISPDatabase'|translate|e('html_attr') }}"
+ introduction="{{ 'GeoIp2_ISPDatabase'|translate|e('html_attr') }}"
data-title="{{ 'Actions_ColumnDownloadURL'|translate|e('html_attr') }}"
value="{{ geoIPIspUrl }}">
</div>
- {% if geoIPOrgUrl is defined %}
- <div piwik-field uicontrol="text" name="geoip-org-db"
- ng-model="locationUpdater.orgDbUrl"
- introduction="{{ 'UserCountry_OrgDatabase'|translate|e('html_attr') }}"
- data-title="{{ 'Actions_ColumnDownloadURL'|translate|e('html_attr') }}"
- value="{{ geoIPOrgUrl }}">
- </div>
- {% endif %}
-
<div id="locationProviderUpdatePeriodInlineHelp" class="inline-help-node">
{% if lastTimeUpdaterRun is defined and lastTimeUpdaterRun is not empty %}
- {{ 'UserCountry_UpdaterWasLastRun'|translate(lastTimeUpdaterRun)|raw }}
+ {{ 'GeoIp2_UpdaterWasLastRun'|translate(lastTimeUpdaterRun)|raw }}
{% else %}
- {{ 'UserCountry_UpdaterHasNotBeenRun'|translate }}
+ {{ 'GeoIp2_UpdaterHasNotBeenRun'|translate }}
{% endif %}
<br/><br/>
<div id="geoip-updater-next-run-time">
- {% include "@UserCountry/_updaterNextRunTime.twig" %}
+ {% include "@GeoIp2/_updaterNextRunTime.twig" %}
</div>
</div>
<div piwik-field uicontrol="radio" name="geoip-update-period"
ng-model="locationUpdater.updatePeriod"
- introduction="{{ 'UserCountry_DownloadNewDatabasesEvery'|translate|e('html_attr') }}"
+ introduction="{{ 'GeoIp2_DownloadNewDatabasesEvery'|translate|e('html_attr') }}"
value="{{ geoIPUpdatePeriod }}"
options="{{ updatePeriodOptions|json_encode }}"
inline-help="#locationProviderUpdatePeriodInlineHelp">
diff --git a/plugins/GeoIp2/templates/_updaterNextRunTime.twig b/plugins/GeoIp2/templates/_updaterNextRunTime.twig
new file mode 100644
index 0000000000..ab5b273be6
--- /dev/null
+++ b/plugins/GeoIp2/templates/_updaterNextRunTime.twig
@@ -0,0 +1,9 @@
+{% if nextRunTime|default is not empty %}
+ {% if date(nextRunTime.getTimestamp()) <= date() %}
+ {{ 'GeoIp2_UpdaterScheduledForNextRun'|translate }}
+ {% else %}
+ {{ 'GeoIp2_UpdaterWillRunNext'|translate('<strong>' ~ nextRunTime.toString() ~ '</strong>')|raw }}
+ {% endif %}
+{% else %}
+ {{ 'GeoIp2_UpdaterIsNotScheduledToRun'|translate }}
+{% endif %} \ No newline at end of file
diff --git a/plugins/GeoIp2/templates/configuration.twig b/plugins/GeoIp2/templates/configuration.twig
new file mode 100644
index 0000000000..729e0f112d
--- /dev/null
+++ b/plugins/GeoIp2/templates/configuration.twig
@@ -0,0 +1,48 @@
+<div piwik-content-block
+ content-title="{% if not geoIPDatabasesInstalled %}{{ 'GeoIp2_GeoIPDatabases'|translate|e('html_attr') }}{% else %}{{ 'GeoIp2_SetupAutomaticUpdatesOfGeoIP'|translate|e('html_attr') }}{% endif %}"
+ id="geoip-db-mangement">
+
+ <div piwik-geoip2-updater
+ geoip-database-installed="{% if geoIPDatabasesInstalled %}1{% else %}0{% endif %}">
+
+ {% if showGeoIPUpdateSection %}
+ {% if not geoIPDatabasesInstalled %}
+ <div ng-show="!locationUpdater.geoipDatabaseInstalled">
+ <div ng-show="locationUpdater.showPiwikNotManagingInfo">
+ <h3>{{ 'GeoIp2_NotManagingGeoIPDBs'|translate|e('html_attr') }}</h3>
+ <div id="manage-geoip-dbs">
+ <div class="row" id="geoipdb-screen1">
+ <div class="geoipdb-column-1 col s6">
+ <p>{{ 'GeoIp2_IWantToDownloadFreeGeoIP'|translate|raw }}</p>
+ </div>
+ <div class="geoipdb-column-2 col s6">
+ <p>{{ 'GeoIp2_IPurchasedGeoIPDBs'|translate('<a rel="noreferrer noopener" href="http://www.maxmind.com/en/geolocation_landing?rId=piwik">','</a>','<a rel="noreferrer noopener" href="https://db-ip.com/db/?refid=mtm">','</a>')|raw }}</p>
+ </div>
+ <div class="geoipdb-column-1 col s6">
+ <input type="button" class="btn"
+ ng-click="locationUpdater.startDownloadFreeGeoIp()"
+ value="{{ 'General_GetStarted'|translate }}..."/>
+ </div>
+ <div class="geoipdb-column-2 col s6">
+ <input type="button" class="btn"
+ ng-click="locationUpdater.startAutomaticUpdateGeoIp()"
+ value="{{ 'General_GetStarted'|translate }}..." id="start-automatic-update-geoip"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="geoipdb-screen2-download" ng-show="locationUpdater.showFreeDownload">
+ <div piwik-progressbar
+ label="{{ ('GeoIp2_DownloadingDb'|translate('<a href="'~dbipLiteUrl~'">'~dbipLiteFilename~'</a>') ~ '...')|json_encode }}"
+ progress="locationUpdater.progressFreeDownload">
+ </div>
+ </div>
+ </div>
+ {% endif %}
+
+ {% include "@GeoIp2/_updaterManage.twig" %}
+ {% else %}
+ <p class="form-description">{{ 'GeoIp2_CannotSetupGeoIPAutoUpdating'|translate }}</p>
+ {% endif %}
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/GeoIp2/templates/setupguide.twig b/plugins/GeoIp2/templates/setupguide.twig
new file mode 100644
index 0000000000..737ec17fb1
--- /dev/null
+++ b/plugins/GeoIp2/templates/setupguide.twig
@@ -0,0 +1,9 @@
+<h3 style="margin-top:0;">{{ 'GeoIp2_HowToSetupGeoIP'|translate }}</h3>
+<p>{{ 'GeoIp2_HowToSetupGeoIPIntro'|translate }}</p>
+<ul style="list-style:disc !important;margin-left:2em;">
+ <li style="list-style-type: disc !important;">{{ 'GeoIp2_HowToSetupGeoIP_Step1'|translate('<a rel="noreferrer noopener" href="'~dbipLiteUrl~'">','</a>','<a rel="noreferrer noopener" target="_blank" href="http://db-ip.com/?refid=mtm">','</a>')|raw }}</li>
+ <li style="list-style-type: disc !important;">{{ 'GeoIp2_HowToSetupGeoIP_Step2'|translate("'"~dbipLiteFilename~"'",'<strong>','</strong>','<strong>'~dbipLiteDesiredFilename~'</strong>')|raw }}</li>
+ <li style="list-style-type: disc !important;">{{ 'GeoIp2_HowToSetupGeoIP_Step3'|translate('<strong>','</strong>','<span style="color:green"><strong>','</strong></span>')|raw }}</li>
+ <li style="list-style-type: disc !important;">{{ 'GeoIp2_HowToSetupGeoIP_Step4'|translate }}</li>
+</ul>
+<p>&nbsp;</p> \ No newline at end of file
diff --git a/plugins/GeoIp2/tests/Unit/GeoIp2Test.php b/plugins/GeoIp2/tests/Unit/GeoIp2Test.php
new file mode 100644
index 0000000000..6b67150ef0
--- /dev/null
+++ b/plugins/GeoIp2/tests/Unit/GeoIp2Test.php
@@ -0,0 +1,135 @@
+<?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\UserCountry\tests\Unit;
+
+use Piwik\Container\StaticContainer;
+use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater;
+use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
+use Piwik\Plugins\UserCountry\LocationProvider;
+use Exception;
+
+class GeoIp2Test extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * Test that redundant checks work.
+ *
+ * @group Plugins
+ */
+ public function testGeoIpUpdaterRedundantChecks()
+ {
+ LocationProvider::$providers = null;
+
+ // create empty ISP file
+ $this->createEmptyISPFile();
+
+ // run redundant checks
+ $updater = new Piwik_GeoIp2_GeoIP2AutoUpdater_publictest();
+ $updater->performRedundantDbChecks();
+
+ // check that files are renamed correctly
+ $this->checkBrokenGeoIPState();
+
+ // create empty file again & run checks again
+ $this->createEmptyISPFile();
+ $updater->performRedundantDbChecks();
+
+ // check that w/ broken files already there, redundant checks still work correctly
+ $this->checkBrokenGeoIPState();
+ }
+
+ /**
+ * @group Plugins
+ *
+ * @dataProvider getInvalidGeoIpUrlsToTest
+ */
+ public function testGeoIpDownloadInvalidUrl($url)
+ {
+ // unset translations, otherwise Exception message will be translated
+ StaticContainer::get('Piwik\Translation\Translator')->reset();
+
+ $updater = new Piwik_GeoIp2_GeoIP2AutoUpdater_publictest();
+ try {
+ $updater->downloadFile('loc', $url);
+ $this->fail("Downloading invalid url succeeded!");
+ } catch (Exception $ex) {
+ $this->assertEquals("GeoIp2_UnsupportedArchiveType", $ex->getMessage());
+ }
+ }
+
+ public function getInvalidGeoIpUrlsToTest()
+ {
+ return array(array("http://localhost/tests/resources/geoip.tar"),
+ array("http://localhost/tests/resources/geoip.tar.bz2"),
+ array("http://localhost/tests/resources/geoip.dat"));
+ }
+
+ protected $backUpNames;
+
+ public function setUp()
+ {
+ $this->backUpNames = GeoIp2::$dbNames;
+
+ GeoIp2::$dbNames = [
+ 'loc' => ['DBIP-City.mmdb'],
+ 'isp' => ['DBIP-ISP.mmdb']
+ ];
+ }
+
+ public function tearDown()
+ {
+ GeoIp2::$dbNames = $this->backUpNames;
+
+ $geoIpDirPath = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
+ $filesToRemove = array('DBIP-ISP.mmdb.broken', 'DBIP-ISP.mmdb');
+
+ foreach ($filesToRemove as $name) {
+ $path = $geoIpDirPath . '/' . $name;
+ if (file_exists($path)) {
+ @unlink($path);
+ }
+ }
+ }
+
+ private function createEmptyISPFile()
+ {
+ $geoIpDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
+
+ $fd = fopen($geoIpDir . '/DBIP-ISP.mmdb', 'w');
+ fclose($fd);
+ }
+
+ private function checkBrokenGeoIPState()
+ {
+ $geoIpDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
+
+ $this->assertFalse(file_exists($geoIpDir . '/DBIP-City.mmdb.broken'));
+
+ $this->assertFalse(file_exists($geoIpDir . '/DBIP-ISP.mmdb'));
+ $this->assertTrue(file_exists($geoIpDir . '/DBIP-ISP.mmdb.broken'));
+ }
+}
+
+class Piwik_GeoIp2_GeoIP2AutoUpdater_publictest extends GeoIP2AutoUpdater
+{
+ public function __construct()
+ {
+ // empty
+ }
+
+ // during tests do not call the Log::error or they will be displayed in the output
+ public function performRedundantDbChecks($logErrors = false)
+ {
+ parent::performRedundantDbChecks($logErrors);
+ }
+
+ public function downloadFile($type, $url)
+ {
+ parent::downloadFile($type, $url);
+ }
+}
diff --git a/plugins/UserCountry/Archiver.php b/plugins/UserCountry/Archiver.php
index 16eca3bd26..1a15be4e54 100644
--- a/plugins/UserCountry/Archiver.php
+++ b/plugins/UserCountry/Archiver.php
@@ -9,11 +9,9 @@
namespace Piwik\Plugins\UserCountry;
-use Piwik\ArchiveProcessor;
use Piwik\DataArray;
use Piwik\DataTable;
use Piwik\Metrics;
-use Piwik\Plugins\UserCountry\LocationProvider;
class Archiver extends \Piwik\Plugin\Archiver
{
diff --git a/plugins/UserCountry/Columns/Region.php b/plugins/UserCountry/Columns/Region.php
index 21587dc4f2..71af217b53 100644
--- a/plugins/UserCountry/Columns/Region.php
+++ b/plugins/UserCountry/Columns/Region.php
@@ -16,6 +16,7 @@ use Piwik\Tracker\Action;
class Region extends Base
{
protected $columnName = 'location_region';
+ protected $columnType = 'char(3) DEFAULT NULL';
protected $type = self::TYPE_TEXT;
protected $category = 'UserCountry_VisitLocation';
protected $segmentName = 'regionCode';
diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php
index 97b5eadf92..5a980f5702 100644
--- a/plugins/UserCountry/Controller.php
+++ b/plugins/UserCountry/Controller.php
@@ -10,14 +10,9 @@ namespace Piwik\Plugins\UserCountry;
use Exception;
use Piwik\Common;
-use Piwik\DataTable\Renderer\Json;
-use Piwik\Http;
-use Piwik\Date;
use Piwik\IP;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
-use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider;
use Piwik\SettingsPiwik;
@@ -48,15 +43,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$view->locationProviders = $allProviderInfo;
$view->currentProviderId = LocationProvider::getCurrentProviderId();
$view->thisIP = IP::getIpFromHeader();
-
- if ($this->isGeoIp2Enabled()) {
- $geoIPDatabasesInstalled = GeoIp2::isDatabaseInstalled();
- } else {
- $geoIPDatabasesInstalled = GeoIp::isDatabaseInstalled();
- }
-
- $view->geoIPDatabasesInstalled = $geoIPDatabasesInstalled;
- $view->updatePeriodOptions = $this->getPeriodUpdateOptions();
+ $view->hasGeoIp2Provider = Manager::getInstance()->isPluginActivated('GeoIp2');
// check if there is a working provider (that isn't the default one)
$isThereWorkingProvider = false;
@@ -70,26 +57,14 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
}
$view->isThereWorkingProvider = $isThereWorkingProvider;
- $view->notUsingGeoIpPlugin = !Manager::getInstance()->isPluginActivated('GeoIp2')
- && !Manager::getInstance()->isPluginActivated('GeoIp');
-
- // if using either the Apache, Nginx or PECL module, they are working and there are no databases
- // in misc, then the databases are located outside of Piwik, so we cannot update them
- $view->showGeoIPUpdateSection = true;
- $currentProviderId = LocationProvider::getCurrentProviderId();
- if (!$geoIPDatabasesInstalled
- && in_array($currentProviderId, [GeoIp2\ServerModule::ID, GeoIp\ServerBased::ID, GeoIp\Pecl::ID])
- && $allProviderInfo[$currentProviderId]['status'] == LocationProvider::INSTALLED
- ) {
- $view->showGeoIPUpdateSection = false;
+ $configurations = $setUpGuides = '';
+ foreach (LocationProvider::getAllProviders() as $provider) {
+ $configurations .= $provider->renderConfiguration();
+ $setUpGuides .= $provider->renderSetUpGuide();
}
- if ($view->notUsingGeoIpPlugin) {
- $view->showGeoIPUpdateSection = false;
- }
-
- $view->isInternetEnabled = SettingsPiwik::isInternetEnabled();
- $this->setUpdaterManageVars($view);
+ $view->configurations = $configurations;
+ $view->setUpGuides = $setUpGuides;
$this->setBasicVariablesView($view);
$this->setBasicVariablesAdminView($view);
@@ -97,301 +72,6 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
}
/**
- * Starts or continues download of GeoLiteCity.dat.
- *
- * To avoid a server/PHP timeout & to show progress of the download to the user, we
- * use the HTTP Range header to download one chunk of the file at a time. After each
- * chunk, it is the browser's responsibility to call the method again to continue the download.
- *
- * Input:
- * 'continue' query param - if set to 1, will assume we are currently downloading & use
- * Range: HTTP header to get another chunk of the file.
- *
- * Output (in JSON):
- * 'current_size' - Current size of the partially downloaded file on disk.
- * 'expected_file_size' - The expected finished file size as returned by the HTTP server.
- * 'next_screen' - When the download finishes, this is the next screen that should be shown.
- * 'error' - When an error occurs, the message is returned in this property.
- */
- public function downloadFreeGeoIPDB()
- {
- $this->dieIfGeolocationAdminIsDisabled();
- Piwik::checkUserHasSuperUserAccess();
-
- if ($this->isGeoIp2Enabled()) {
- return $this->downloadFreeDBIPLiteDB();
- }
-
- if ($_SERVER["REQUEST_METHOD"] == "POST") {
- $this->checkTokenInUrl();
- Json::sendHeaderJSON();
- $outputPath = GeoIp::getPathForGeoIpDatabase('GeoIPCity.dat') . '.gz';
- try {
- $result = Http::downloadChunk(
- $url = GeoIp::GEO_LITE_URL,
- $outputPath,
- $continue = Common::getRequestVar('continue', true, 'int')
- );
-
- // if the file is done
- if ($result['current_size'] >= $result['expected_file_size']) {
- GeoIPAutoUpdater::unzipDownloadedFile($outputPath, $unlink = true);
-
- // setup the auto updater
- GeoIPAutoUpdater::setUpdaterOptions(array(
- 'loc' => GeoIp::GEO_LITE_URL,
- 'period' => GeoIPAutoUpdater::SCHEDULE_PERIOD_MONTHLY,
- ));
-
- // make sure to echo out the geoip updater management screen
- $result['settings'] = GeoIPAutoUpdater::getConfiguredUrls();
- }
-
- return json_encode($result);
- } catch (Exception $ex) {
- return json_encode(array('error' => $ex->getMessage()));
- }
- }
- }
-
- /**
- * Starts or continues download of DBIP-City.mmdb.
- *
- * To avoid a server/PHP timeout & to show progress of the download to the user, we
- * use the HTTP Range header to download one chunk of the file at a time. After each
- * chunk, it is the browser's responsibility to call the method again to continue the download.
- *
- * Input:
- * 'continue' query param - if set to 1, will assume we are currently downloading & use
- * Range: HTTP header to get another chunk of the file.
- *
- * Output (in JSON):
- * 'current_size' - Current size of the partially downloaded file on disk.
- * 'expected_file_size' - The expected finished file size as returned by the HTTP server.
- * 'next_screen' - When the download finishes, this is the next screen that should be shown.
- * 'error' - When an error occurs, the message is returned in this property.
- */
- public function downloadFreeDBIPLiteDB()
- {
- $this->dieIfGeolocationAdminIsDisabled();
- Piwik::checkUserHasSuperUserAccess();
- if ($_SERVER["REQUEST_METHOD"] == "POST") {
- $this->checkTokenInUrl();
- Json::sendHeaderJSON();
- $outputPath = GeoIp2::getPathForGeoIpDatabase('DBIP-City.mmdb') . '.gz';
- try {
- $result = Http::downloadChunk(
- $url = GeoIp2::getDbIpLiteUrl(),
- $outputPath,
- $continue = Common::getRequestVar('continue', true, 'int')
- );
-
- // if the file is done
- if ($result['current_size'] >= $result['expected_file_size']) {
- try {
- GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, 'loc', $url, $unlink = true);
- } catch (\Exception $e) {
- // remove downloaded file on error
- unlink($outputPath);
- throw $e;
- }
-
- // setup the auto updater
- GeoIP2AutoUpdater::setUpdaterOptions(array(
- 'loc' => GeoIp2::getDbIpLiteUrl(),
- 'period' => GeoIP2AutoUpdater::SCHEDULE_PERIOD_MONTHLY,
- ));
-
- $result['settings'] = GeoIP2AutoUpdater::getConfiguredUrls();
- }
-
- return json_encode($result);
- } catch (Exception $ex) {
- return json_encode(array('error' => $ex->getMessage()));
- }
- }
- }
-
- private function getPeriodUpdateOptions()
- {
- return array(
- 'month' => Piwik::translate('Intl_PeriodMonth'),
- 'week' => Piwik::translate('Intl_PeriodWeek')
- );
- }
-
- /**
- * Sets some variables needed by the _updaterManage.twig template.
- *
- * @param View $view
- */
- private function setUpdaterManageVars($view)
- {
- $view->isGeoIp2Available = $this->isGeoIp2Enabled();
-
- if ($this->isGeoIp2Enabled()) {
- // Get GeoIPLegacy Update information to show them
- $urls = GeoIPAutoUpdater::getConfiguredUrls();
- $today = Date::today();
-
- $view->geoIPLegacyLocUrl = $urls['loc'];
- $view->geoIPLegacyIspUrl = $urls['isp'];
- $view->geoIPLegacyOrgUrl = $urls['org'];
- $view->geoIPLegacyUpdatePeriod = GeoIPAutoUpdater::getSchedulePeriod();
-
- $urls = GeoIP2AutoUpdater::getConfiguredUrls();
-
- $view->geoIPLocUrl = $urls['loc'];
- $view->geoIPIspUrl = $urls['isp'];
- $view->geoIPUpdatePeriod = GeoIP2AutoUpdater::getSchedulePeriod();
-
- $view->dbipLiteUrl = GeoIp2::getDbIpLiteUrl();
- $view->dbipLiteFilename = "dbip-city-lite-{$today->toString('Y-m')}.mmdb";
- $view->dbipLiteDesiredFilename = "DBIP-City.mmdb";
- $view->nextRunTime = GeoIP2AutoUpdater::getNextRunTime();
-
- $lastRunTime = GeoIP2AutoUpdater::getLastRunTime();
- } else {
- $urls = GeoIPAutoUpdater::getConfiguredUrls();
-
- $view->geoIPLocUrl = $urls['loc'];
- $view->geoIPIspUrl = $urls['isp'];
- $view->geoIPOrgUrl = $urls['org'];
- $view->geoIPUpdatePeriod = GeoIPAutoUpdater::getSchedulePeriod();
-
- $view->geoLiteUrl = GeoIp::GEO_LITE_URL;
- $view->geoLiteFilename = 'GeoLiteCity.dat';
- $view->nextRunTime = GeoIPAutoUpdater::getNextRunTime();
-
- $lastRunTime = GeoIPAutoUpdater::getLastRunTime();
- }
-
- if ($lastRunTime !== false) {
- $view->lastTimeUpdaterRun = '<strong>' . $lastRunTime->toString() . '</strong>';
- }
- }
-
- /**
- * Sets the URLs used to download new versions of the installed GeoIP databases.
- *
- * Input (query params):
- * 'loc_db' - URL for a GeoIP location database.
- * 'isp_db' - URL for a GeoIP ISP database (optional).
- * 'org_db' - URL for a GeoIP Org database (optional).
- * 'period' - 'weekly' or 'monthly'. Determines how often update is run.
- *
- * Output (json):
- * 'error' - if an error occurs its message is set as the resulting JSON object's
- * 'error' property.
- */
- public function updateGeoIPLinks()
- {
- $this->dieIfGeolocationAdminIsDisabled();
- Piwik::checkUserHasSuperUserAccess();
- if ($_SERVER["REQUEST_METHOD"] == "POST") {
- Json::sendHeaderJSON();
- try {
- $this->checkTokenInUrl();
-
- if ($this->isGeoIp2Enabled()) {
- GeoIP2AutoUpdater::setUpdaterOptionsFromUrl();
- } else {
- GeoIPAutoUpdater::setUpdaterOptionsFromUrl();
- }
-
- // if there is a updater URL for a database, but its missing from the misc dir, tell
- // the browser so it can download it next
- $info = $this->getNextMissingDbUrlInfo();
- if ($info !== false) {
- return json_encode($info);
- } else {
- $view = new View("@UserCountry/_updaterNextRunTime");
- if ($this->isGeoIp2Enabled()) {
- $view->nextRunTime = GeoIP2AutoUpdater::getNextRunTime();
- } else {
- $view->nextRunTime = GeoIPAutoUpdater::getNextRunTime();
- }
- $nextRunTimeHtml = $view->render();
- return json_encode(array('nextRunTime' => $nextRunTimeHtml));
- }
- } catch (Exception $ex) {
- return json_encode(array('error' => $ex->getMessage()));
- }
- }
- }
-
- /**
- * Starts or continues a download for a missing GeoIP database. A database is missing if
- * it has an update URL configured, but the actual database is not available in the misc
- * directory.
- *
- * Input:
- * 'url' - The URL to download the database from.
- * 'continue' - 1 if we're continuing a download, 0 if we're starting one.
- *
- * Output:
- * 'error' - If an error occurs this describes the error.
- * 'to_download' - The URL of a missing database that should be downloaded next (if any).
- * 'to_download_label' - The label to use w/ the progress bar that describes what we're
- * downloading.
- * 'current_size' - Size of the current file on disk.
- * 'expected_file_size' - Size of the completely downloaded file.
- */
- public function downloadMissingGeoIpDb()
- {
- $this->dieIfGeolocationAdminIsDisabled();
- Piwik::checkUserHasSuperUserAccess();
- if ($_SERVER["REQUEST_METHOD"] == "POST") {
- try {
- $this->checkTokenInUrl();
-
- Json::sendHeaderJSON();
-
- // based on the database type (provided by the 'key' query param) determine the
- // url & output file name
- $key = Common::getRequestVar('key', null, 'string');
-
- if ($this->isGeoIp2Enabled()) {
- $url = GeoIP2AutoUpdater::getConfiguredUrl($key);
- $filename = GeoIP2AutoUpdater::getZippedFilenameToDownloadTo($url, $key, GeoIP2AutoUpdater::getGeoIPUrlExtension($url));
- $outputPath = GeoIp2::getPathForGeoIpDatabase($filename);
- } else {
- $url = GeoIPAutoUpdater::getConfiguredUrl($key);
- $ext = GeoIPAutoUpdater::getGeoIPUrlExtension($url);
- $filename = GeoIp::$dbNames[$key][0] . '.' . $ext;
-
- if (substr($filename, 0, 15) == 'GeoLiteCity.dat') {
- $filename = 'GeoIPCity.dat' . substr($filename, 15);
- }
- $outputPath = GeoIp::getPathForGeoIpDatabase($filename);
- }
-
- // download part of the file
- $result = Http::downloadChunk(
- $url, $outputPath, Common::getRequestVar('continue', true, 'int'));
-
- // if the file is done
- if ($result['current_size'] >= $result['expected_file_size']) {
- if ($this->isGeoIp2Enabled()) {
- GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, $key, $url, $unlink = true);
- } else {
- GeoIPAutoUpdater::unzipDownloadedFile($outputPath, $unlink = true);
- }
-
- $info = $this->getNextMissingDbUrlInfo();
- if ($info !== false) {
- return json_encode($info);
- }
- }
-
- return json_encode($result);
- } catch (Exception $ex) {
- return json_encode(array('error' => $ex->getMessage()));
- }
- }
- }
-
- /**
* Echo's a pretty formatted location using a specific LocationProvider.
*
* Input:
@@ -402,6 +82,9 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
*/
public function getLocationUsingProvider()
{
+ $this->dieIfGeolocationAdminIsDisabled();
+ Piwik::checkUserHasSuperUserAccess();
+
$providerId = Common::getRequestVar('id');
$provider = LocationProvider::getProviderById($providerId);
if (empty($provider)) {
@@ -429,63 +112,10 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
return $this->renderView($view);
}
- /**
- * Gets information for the first missing GeoIP database (if any).
- *
- * @return array|bool
- */
- private function getNextMissingDbUrlInfo()
- {
- if ($this->isGeoIp2Enabled()) {
- return $this->getNextMissingDbUrlInfoGeoIp2();
- }
-
- $missingDbs = GeoIPAutoUpdater::getMissingDatabases();
- if (!empty($missingDbs)) {
- $missingDbKey = $missingDbs[0];
- $url = GeoIPAutoUpdater::getConfiguredUrl($missingDbKey);
-
- $link = '<a href="' . $url . '">' . $url . '</a>';
-
- return array(
- 'to_download' => $missingDbKey,
- 'to_download_label' => Piwik::translate('UserCountry_DownloadingDb', $link) . '...',
- );
- }
- return false;
- }
-
- /**
- * Gets information for the first missing GeoIP2 database (if any).
- *
- * @return array|bool
- */
- private function getNextMissingDbUrlInfoGeoIp2()
- {
- $missingDbs = GeoIP2AutoUpdater::getMissingDatabases();
- if (!empty($missingDbs)) {
- $missingDbKey = $missingDbs[0];
- $url = GeoIP2AutoUpdater::getConfiguredUrl($missingDbKey);
-
- $link = '<a href="' . $url . '">' . $url . '</a>';
-
- return array(
- 'to_download' => $missingDbKey,
- 'to_download_label' => Piwik::translate('UserCountry_DownloadingDb', $link) . '...',
- );
- }
- return false;
- }
-
private function dieIfGeolocationAdminIsDisabled()
{
if (!UserCountry::isGeoLocationAdminEnabled()) {
throw new \Exception('Geo location setting page has been disabled.');
}
}
-
- private function isGeoIp2Enabled()
- {
- return Manager::getInstance()->isPluginActivated('GeoIp2');
- }
}
diff --git a/plugins/UserCountry/Diagnostic/GeolocationDiagnostic.php b/plugins/UserCountry/Diagnostic/GeolocationDiagnostic.php
index 15e502dfa9..18fe451100 100644
--- a/plugins/UserCountry/Diagnostic/GeolocationDiagnostic.php
+++ b/plugins/UserCountry/Diagnostic/GeolocationDiagnostic.php
@@ -44,7 +44,6 @@ class GeolocationDiagnostic implements Diagnostic
$allProviders = LocationProvider::getAllProviderInfo();
$isNotRecommendedProvider = in_array($currentProviderId, array(
LocationProvider\DefaultProvider::ID,
- LocationProvider\GeoIp\ServerBased::ID,
GeoIp2\ServerModule::ID));
$isProviderInstalled = (isset($allProviders[$currentProviderId]['status']) && $allProviders[$currentProviderId]['status'] == LocationProvider::INSTALLED);
@@ -53,8 +52,8 @@ class GeolocationDiagnostic implements Diagnostic
}
if ($isProviderInstalled) {
- $comment = $this->translator->translate('UserCountry_GeoIpLocationProviderNotRecomnended') . ' ';
- $message = Manager::getInstance()->isPluginActivated('GeoIp2') ? 'GeoIp2_LocationProviderDesc_ServerModule2' : 'UserCountry_GeoIpLocationProviderDesc_ServerBased2';
+ $comment = $this->translator->translate('GeoIp2_GeoIPLocationProviderNotRecommended') . ' ';
+ $message = 'GeoIp2_LocationProviderDesc_ServerModule2';
$comment .= $this->translator->translate($message, array(
'<a href="https://matomo.org/docs/geo-locate/" rel="noreferrer noopener" target="_blank">', '', '', '</a>'
));
diff --git a/plugins/UserCountry/GeoIPAutoUpdater.php b/plugins/UserCountry/GeoIPAutoUpdater.php
deleted file mode 100644
index bee89ac8fd..0000000000
--- a/plugins/UserCountry/GeoIPAutoUpdater.php
+++ /dev/null
@@ -1,731 +0,0 @@
-<?php
-/**
- * Piwik - 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\UserCountry;
-
-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\Http;
-use Piwik\Log;
-use Piwik\Option;
-use Piwik\Piwik;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp\Php;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-use Piwik\Plugins\UserCountry\LocationProvider;
-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;
-use Psr\Log\LoggerInterface;
-
-/**
- * Used to automatically update installed GeoIP databases, and manages the updater's
- * scheduled task.
- */
-class GeoIPAutoUpdater extends Task
-{
- const SCHEDULE_PERIOD_MONTHLY = 'month';
- const SCHEDULE_PERIOD_WEEKLY = 'week';
-
- const SCHEDULE_PERIOD_OPTION_NAME = 'geoip.updater_period';
- const LOC_URL_OPTION_NAME = 'geoip.loc_db_url';
- const ISP_URL_OPTION_NAME = 'geoip.isp_db_url';
- const ORG_URL_OPTION_NAME = 'geoip.org_db_url';
-
- const LAST_RUN_TIME_OPTION_NAME = 'geoip.updater_last_run_time';
-
- private static $urlOptions = array(
- 'loc' => self::LOC_URL_OPTION_NAME,
- 'isp' => self::ISP_URL_OPTION_NAME,
- 'org' => self::ORG_URL_OPTION_NAME,
- );
-
- /**
- * PHP Error caught through a custom error handler while trying to use a downloaded
- * GeoIP 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 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 & organization 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);
- }
-
- $orgUrl = Option::get(self::ORG_URL_OPTION_NAME);
- if (!empty($orgUrl)) {
- $this->downloadFile('org', $orgUrl);
- }
- } catch (Exception $ex) {
- // message will already be prefixed w/ 'GeoIPAutoUpdater: '
- StaticContainer::get(LoggerInterface::class)->error('Auto-update failed: {exception}', [
- 'exception' => $ex,
- 'ignoreInScreenWriter' => true,
- ]);
- $this->performRedundantDbChecks();
- throw $ex;
- }
-
- $this->performRedundantDbChecks();
- }
-
- /**
- * Downloads a GeoIP database archive, extracts the .dat 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);
-
- if (strpos($url, 'GeoLite')) {
- Log::info('GeoLite databases have been discontinued. Skipping download of '.$url.'. Consider switching to GeoIP 2.');
- return;
- }
-
- $ext = GeoIPAutoUpdater::getGeoIPUrlExtension($url);
-
- // NOTE: using the first item in $dbNames[$dbType] makes sure GeoLiteCity will be renamed to GeoIPCity
- $zippedFilename = GeoIp::$dbNames[$dbType][0] . '.' . $ext;
-
- $zippedOutputPath = GeoIp::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("GeoIPAutoUpdater: failed to download '$url' to "
- . "'$zippedOutputPath': " . $ex->getMessage());
- }
-
- if ($success !== true) {
- throw new Exception("GeoIPAutoUpdater: failed to download '$url' to "
- . "'$zippedOutputPath'! (Unknown error)");
- }
-
- Log::info("GeoIPAutoUpdater: successfully downloaded '%s'", $url);
-
- try {
- self::unzipDownloadedFile($zippedOutputPath, $unlink = true);
- } catch (Exception $ex) {
- throw new Exception("GeoIPAutoUpdater: failed to unzip '$zippedOutputPath' after "
- . "downloading " . "'$url': " . $ex->getMessage());
- }
-
- Log::info("GeoIPAutoUpdater: successfully updated GeoIP database '%s'", $url);
- }
-
- /**
- * Unzips a downloaded GeoIP 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, $unlink = false)
- {
- $parts = explode('.', basename($path));
- $filenameStart = $parts[0];
-
- $dbFilename = $filenameStart . '.dat';
- $tempFilename = $filenameStart . '.dat.new';
- $outputPath = GeoIp::getPathForGeoIpDatabase($tempFilename);
-
- // 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())));
- }
-
- $datFile = null;
- foreach ($content as $info) {
- $archivedPath = $info['filename'];
- if (basename($archivedPath) === $dbFilename) {
- $datFile = $archivedPath;
- }
- }
-
- if ($datFile === null) {
- throw new Exception(Piwik::translate('UserCountry_CannotFindGeoIPDatabaseInArchive',
- array($dbFilename, "'$path'")));
- }
-
- // extract JUST the .dat file
- $unzipped = $unzip->extractInString($datFile);
-
- if (empty($unzipped)) {
- throw new Exception(Piwik::translate('UserCountry_CannotUnzipDatFile',
- array("'$path'", $unzip->errorInfo())));
- }
-
- // 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);
- $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 database
- $dbType = GeoIp::getGeoIPDatabaseTypeFromFilename($dbFilename);
- if ($dbType === false) // sanity check
- {
- throw new Exception("Unexpected GeoIP archive file name '$path'.");
- }
-
- $customDbNames = array(
- 'loc' => array(),
- 'isp' => array(),
- 'org' => array()
- );
- $customDbNames[$dbType] = array($tempFilename);
-
- $phpProvider = new Php($customDbNames);
-
- $location = self::getTestLocationCatchPhpErrors($phpProvider);
-
- if (empty($location)
- || self::$unzipPhpError !== null
- ) {
- if (self::$unzipPhpError !== null) {
- list($errno, $errstr, $errfile, $errline) = self::$unzipPhpError;
- Log::info("GeoIPAutoUpdater: Encountered PHP error when testing newly downloaded" .
- " GeoIP database: %s: %s on line %s of %s.", $errno, $errstr, $errline, $errfile);
- }
-
- throw new Exception(Piwik::translate('UserCountry_ThisUrlIsNotAValidGeoIPDB'));
- }
-
- // delete the existing GeoIP database (if any) and rename the downloaded file
- $oldDbFile = GeoIp::getPathForGeoIpDatabase($dbFilename);
- if (file_exists($oldDbFile)) {
- unlink($oldDbFile);
- }
-
- $tempFile = GeoIp::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'),
- 'org' => Common::getRequestVar('org_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 GeoIPAutoUpdater());
- }
- }
-
- /**
- * Removes all options to disable any configured automatic updates
- */
- public static function clearOptions()
- {
- foreach (self::$urlOptions as $optionKey => $optionName) {
- Option::delete($optionName);
- }
- Option::delete(self::SCHEDULE_PERIOD_OPTION_NAME);
- }
-
- /**
- * 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
- || Option::get(self::ORG_URL_OPTION_NAME) !== false
- ) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Retrieves the URLs used to update various GeoIP 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 database update.
- */
- public static function performUpdate()
- {
- $instance = new GeoIPAutoUpdater();
- $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 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 = GeoIp::getPathToGeoIpDatabase(
- GeoIp::$dbNames[$key]);
- if ($path === false) {
- $result[] = $key;
- }
- }
- }
- return $result;
- }
-
- /**
- * Returns the extension of a URL used to update a GeoIP 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 != 'dat.gz'
- && $ext != 'mmdb.gz'
- ) {
- throw new \Exception(Piwik::translate('UserCountry_UnsupportedArchiveType', "'$ext'"));
- }
- }
-
- /**
- * Tests a location provider using a test IP address and catches PHP errors
- * (ie, notices) if they occur. PHP error information is held in self::$unzipPhpError.
- *
- * @param LocationProvider $provider The provider to test.
- * @return array|false $location The result of geolocation. False if no location
- * can be found.
- */
- private static function getTestLocationCatchPhpErrors($provider)
- {
- // note: in most cases where this will fail, the error will usually be a PHP fatal error/notice.
- // in order to delete the files in such a case (which can be caused by a man-in-the-middle attack)
- // we need to catch them, so we set a new error handler.
- self::$unzipPhpError = null;
- set_error_handler(array('Piwik\Plugins\UserCountry\GeoIPAutoUpdater', 'catchGeoIPError'));
-
- $location = $provider->getLocation(array('ip' => GeoIp::TEST_IP));
-
- restore_error_handler();
-
- return $location;
- }
-
- /**
- * 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(GeoIp::$dbNames);
-
- foreach ($databaseTypes as $type) {
- $customNames = array(
- 'loc' => array(),
- 'isp' => array(),
- 'org' => array()
- );
- $customNames[$type] = GeoIp::$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.
- self::getTestLocationCatchPhpErrors($provider);
- if (self::$unzipPhpError !== null) {
- list($errno, $errstr, $errfile, $errline) = self::$unzipPhpError;
-
- if ($logErrors) {
- StaticContainer::get(LoggerInterface::class)->error("GeoIPAutoUpdater: Encountered PHP error when performing redundant tests on GeoIP "
- . "{type} database: {errno}: {errstr} on line {errline} of {errfile}.", [
- 'ignoreInScreenWriter' => true,
- 'type' => $type,
- 'errno' => $errno,
- 'errstr' => $errstr,
- 'errline' => $errline,
- 'errfile' => $errfile,
- ]);
- }
-
- // 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 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 = GeoIp::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 file.
- *
- * If we download a file that is supposed to be a GeoIP 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 GeoIPAutoUpdater();
-
- $timetable = new Timetable();
- return $timetable->getScheduledTaskTime($task->getName());
- }
-
- /**
- * See {@link Piwik\Scheduler\Schedule\Schedule::getRescheduledTime()}.
- */
- public function getRescheduledTime()
- {
- $nextScheduledTime = parent::getRescheduledTime();
-
- // if a geoip 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 (GeoIp::$dbNames as $type => $dbNames) {
- $dbUrl = Option::get(self::$urlOptions[$type]);
- $dbPath = GeoIp::getPathToGeoIpDatabase($dbNames);
-
- // if there is a URL for this DB type and the GeoIP 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 updater period found in database: %s", $updaterPeriod);
- }
-}
diff --git a/plugins/UserCountry/LocationProvider.php b/plugins/UserCountry/LocationProvider.php
index 95f08a9a8d..106ec0afed 100644
--- a/plugins/UserCountry/LocationProvider.php
+++ b/plugins/UserCountry/LocationProvider.php
@@ -144,6 +144,26 @@ abstract class LocationProvider
abstract public function getSupportedLocationInfo();
/**
+ * Renders Configuration or Setup View to be attached to the provider list
+ *
+ * @return string
+ */
+ public function renderConfiguration()
+ {
+ return '';
+ }
+
+ /**
+ * Renders SetUp Guide, which will be shown above Geolocation admin, if there is no working provider
+ *
+ * @return string
+ */
+ public function renderSetUpGuide()
+ {
+ return '';
+ }
+
+ /**
* Method called when a provider gets activated.
*/
public function activate()
diff --git a/plugins/UserCountry/LocationProvider/GeoIp.php b/plugins/UserCountry/LocationProvider/GeoIp.php
deleted file mode 100644
index 44d0567634..0000000000
--- a/plugins/UserCountry/LocationProvider/GeoIp.php
+++ /dev/null
@@ -1,254 +0,0 @@
-<?php
-/**
- * Piwik - 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\UserCountry\LocationProvider;
-
-use Exception;
-use Piwik\Piwik;
-use Piwik\Plugin\Manager;
-use Piwik\Plugins\UserCountry\LocationProvider;
-
-/**
- * Base type for all GeoIP LocationProviders.
- *
- */
-abstract class GeoIp extends LocationProvider
-{
- /* For testing, use: 'http://piwik-team.s3.amazonaws.com/GeoLiteCity.dat.gz' */
- const GEO_LITE_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz';
- const TEST_IP = '194.57.91.215';
-
- public static $geoIPDatabaseDir = 'misc';
-
- /**
- * Stores possible database file names categorized by the type of information
- * GeoIP databases hold.
- *
- * @var array
- */
- public static $dbNames = array(
- 'loc' => array('GeoIPCity.dat', 'GeoLiteCity.dat', 'GeoIP.dat'),
- 'isp' => array('GeoIPISP.dat'),
- 'org' => array('GeoIPOrg.dat'),
- );
-
- /**
- * Cached region name array. Data is from geoipregionvars.php.
- *
- * @var array
- */
- private static $regionNames = null;
-
- /**
- * Attempts to fill in some missing information in a GeoIP location.
- *
- * This method will call LocationProvider::completeLocationResult and then
- * try to set the region name of the location if the country code & region
- * code are set.
- *
- * @param array $location The location information to modify.
- */
- public function completeLocationResult(&$location)
- {
- parent::completeLocationResult($location);
-
- // set region name if region code is set
- if (empty($location[self::REGION_NAME_KEY])
- && !empty($location[self::REGION_CODE_KEY])
- && !empty($location[self::COUNTRY_CODE_KEY])
- ) {
- $countryCode = $location[self::COUNTRY_CODE_KEY];
- $regionCode = (string)$location[self::REGION_CODE_KEY];
- $location[self::REGION_NAME_KEY] = self::getRegionNameFromCodes($countryCode, $regionCode);
- }
- }
-
- public function isVisible()
- {
- return !Manager::getInstance()->isPluginActivated('GeoIp2') || self::getCurrentProvider() instanceof GeoIp;
- }
-
- /**
- * Returns true if this provider has been setup correctly, the error message if
- * otherwise.
- *
- * @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 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);
-
- // ensure tibet is shown as region of china
- if ($countryCode == 'TI' && $regionCode == '1') {
- $regionCode = '14';
- $countryCode = 'CN';
- }
-
- 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)) {
- $GEOIP_REGION_NAME = array();
- require_once PIWIK_INCLUDE_PATH . '/libs/MaxMindGeoIP/geoipregionvars.php';
- self::$regionNames = $GEOIP_REGION_NAME;
- }
-
- return self::$regionNames;
- }
-
- /**
- * Returns the path of an existing GeoIP 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 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)) {
- // TODO: what happens when IP changes? should we get this information from piwik.org?
- $expected = array(self::COUNTRY_CODE_KEY => 'FR',
- self::REGION_CODE_KEY => 'A6',
- self::CITY_NAME_KEY => 'Besançon');
- $result = array(self::TEST_IP, $expected);
- }
- return $result;
- }
-
- /**
- * Returns true if there is a GeoIP database in the 'misc' directory.
- *
- * @return bool
- */
- public static function isDatabaseInstalled()
- {
- return self::getPathToGeoIpDatabase(self::$dbNames['loc'])
- || self::getPathToGeoIpDatabase(self::$dbNames['isp'])
- || self::getPathToGeoIpDatabase(self::$dbNames['org']);
- }
-
- /**
- * Returns the type of GeoIP database ('loc', 'isp' or 'org') based on the
- * filename (eg, 'GeoLiteCity.dat', 'GeoIPISP.dat', etc).
- *
- * @param string $filename
- * @return string|false 'loc', 'isp', 'org', 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;
- }
-} \ No newline at end of file
diff --git a/plugins/UserCountry/LocationProvider/GeoIp/Pecl.php b/plugins/UserCountry/LocationProvider/GeoIp/Pecl.php
deleted file mode 100644
index 26f1591cf3..0000000000
--- a/plugins/UserCountry/LocationProvider/GeoIp/Pecl.php
+++ /dev/null
@@ -1,328 +0,0 @@
-<?php
-/**
- * Piwik - 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\UserCountry\LocationProvider\GeoIp;
-
-use Piwik\Piwik;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-
-/**
- * A LocationProvider that uses the PECL implementation of GeoIP.
- *
- * FIXME: For some reason, if the PECL module is loaded & an organization DB is available, the PHP
- * module won't return organization info. If the PECL module is not loaded, organization info is returned.
- *
- */
-class Pecl extends GeoIp
-{
- const ID = 'geoip_pecl';
- const TITLE = 'GeoIP Legacy (PECL)';
-
- /**
- * For tests.
- */
- public static $forceDisable = false;
-
- /**
- * Uses the GeoIP PECL module to get a visitor's location based on their IP address.
- *
- * This function will return different results based on the data available. If a city
- * database can be detected by the PECL module, it may return the country code,
- * region code, city name, area code, latitude, longitude and postal code of the visitor.
- *
- * Alternatively, if only the country database can be detected, only the country code
- * will be returned.
- *
- * The GeoIP PECL module will detect the following filenames:
- * - GeoIP.dat
- * - GeoIPCity.dat
- * - GeoIPISP.dat
- * - GeoIPOrg.dat
- *
- * Note how GeoLiteCity.dat, the name for the GeoLite city database, is not detected
- * by the PECL module.
- *
- * @param array $info Must have an 'ip' field.
- * @return array
- */
- public function getLocation($info)
- {
- $ip = $this->getIpFromInfo($info);
-
- $result = array();
-
- // get location data
- if (self::isCityDatabaseAvailable()) {
- // Must hide errors because missing IPV6:
- $location = @geoip_record_by_name($ip);
- if (!empty($location)) {
- $result[self::COUNTRY_CODE_KEY] = $location['country_code'];
- $result[self::REGION_CODE_KEY] = $location['region'];
- $result[self::CITY_NAME_KEY] = utf8_encode($location['city']);
- $result[self::AREA_CODE_KEY] = $location['area_code'];
- $result[self::LATITUDE_KEY] = $location['latitude'];
- $result[self::LONGITUDE_KEY] = $location['longitude'];
- $result[self::POSTAL_CODE_KEY] = $location['postal_code'];
- }
- } else if (self::isRegionDatabaseAvailable()) {
- $location = @geoip_region_by_name($ip);
- if (!empty($location)) {
- $result[self::REGION_CODE_KEY] = $location['region'];
- $result[self::COUNTRY_CODE_KEY] = $location['country_code'];
- }
- } else {
- $result[self::COUNTRY_CODE_KEY] = @geoip_country_code_by_name($ip);
- }
-
- // get organization data if the org database is available
- if (self::isOrgDatabaseAvailable()) {
- $org = @geoip_org_by_name($ip);
- if ($org !== false) {
- $result[self::ORG_KEY] = utf8_encode($org);
- }
- }
-
- // get isp data if the isp database is available
- if (self::isISPDatabaseAvailable()) {
- $isp = @geoip_isp_by_name($ip);
- if ($isp !== false) {
- $result[self::ISP_KEY] = utf8_encode($isp);
- }
- }
-
- if (empty($result)) {
- return false;
- }
-
- $this->completeLocationResult($result);
- return $result;
- }
-
- /**
- * Returns true if the PECL module is installed and loaded, false if otherwise.
- *
- * @return bool
- */
- public function isAvailable()
- {
- return !self::$forceDisable && function_exists('geoip_db_avail');
- }
-
- /**
- * Returns true if the PECL module that is installed can be successfully used
- * to get the location of an IP address.
- *
- * @return bool
- */
- public function isWorking()
- {
- // if no no location database is available, this implementation is not setup correctly
- if (!self::isLocationDatabaseAvailable()) {
- $dbDir = dirname(geoip_db_filename(GEOIP_COUNTRY_EDITION)) . '/';
- $quotedDir = "'$dbDir'";
-
- // check if the directory the PECL module is looking for exists
- if (!is_dir($dbDir)) {
- return Piwik::translate('UserCountry_PeclGeoIPNoDBDir', array($quotedDir, "'geoip.custom_directory'"));
- }
-
- // check if the user named the city database GeoLiteCity.dat
- if (file_exists($dbDir . 'GeoLiteCity.dat')) {
- return Piwik::translate('UserCountry_PeclGeoLiteError',
- array($quotedDir, "'GeoLiteCity.dat'", "'GeoIPCity.dat'"));
- }
-
- return Piwik::translate('UserCountry_CannotFindPeclGeoIPDb',
- array($quotedDir, "'GeoIP.dat'", "'GeoIPCity.dat'"));
- }
-
- return parent::isWorking();
- }
-
- /**
- * 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 organization database is found, organization information is
- * supported.
- *
- * If an ISP database is found, ISP 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;
-
- if (self::isCityDatabaseAvailable()) {
- $result[self::REGION_CODE_KEY] = true;
- $result[self::REGION_NAME_KEY] = true;
- $result[self::CITY_NAME_KEY] = true;
- $result[self::AREA_CODE_KEY] = true;
- $result[self::LATITUDE_KEY] = true;
- $result[self::LONGITUDE_KEY] = true;
- $result[self::POSTAL_CODE_KEY] = true;
- } else if (self::isRegionDatabaseAvailable()) {
- $result[self::REGION_CODE_KEY] = true;
- $result[self::REGION_NAME_KEY] = true;
- }
-
- // check if organization info is available
- if (self::isOrgDatabaseAvailable()) {
- $result[self::ORG_KEY] = true;
- }
-
- // check if ISP info is available
- if (self::isISPDatabaseAvailable()) {
- $result[self::ISP_KEY] = true;
- }
-
- return $result;
- }
-
- /**
- * Returns information about this location provider. Contains an id, title & description:
- *
- * array(
- * 'id' => 'geoip_pecl',
- * 'title' => '...',
- * 'description' => '...'
- * );
- *
- * @return array
- */
- public function getInfo()
- {
- $desc = Piwik::translate('UserCountry_GeoIpLocationProviderDesc_Pecl1') . '<br/><br/>'
- . Piwik::translate('UserCountry_GeoIpLocationProviderDesc_Pecl2');
- $installDocs = '<a rel="noreferrer noopener" target="_blank" href="https://matomo.org/faq/how-to/#faq_164">'
- . Piwik::translate('UserCountry_HowToInstallGeoIpPecl')
- . '</a>';
-
- $extraMessage = false;
- if ($this->isAvailable()) {
- $peclDir = ini_get('geoip.custom_directory');
- if ($peclDir === false) {
- $extraMessage = Piwik::translate('UserCountry_GeoIPPeclCustomDirNotSet', "'geoip.custom_directory'");
- } else {
- $extraMessage = 'The \'geoip.custom_directory\' PHP ini option is set to \'' . $peclDir . '\'.';
- }
-
- $availableDatabaseTypes = array();
- if (self::isCityDatabaseAvailable()) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_City');
- }
- if (self::isRegionDatabaseAvailable()) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Region');
- }
- if (self::isCountryDatabaseAvailable()) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Country');
- }
- if (self::isISPDatabaseAvailable()) {
- $availableDatabaseTypes[] = 'ISP';
- }
- if (self::isOrgDatabaseAvailable()) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Organization');
- }
-
- $extraMessage .= '<br/><br/>' . Piwik::translate('UserCountry_GeoIPImplHasAccessTo') . ':&nbsp;<strong>'
- . implode(', ', $availableDatabaseTypes) . '</strong>.';
-
- $extraMessage = '<strong>' . Piwik::translate('General_Note') . ':&nbsp;</strong>' . $extraMessage;
- }
-
- return array('id' => self::ID,
- 'title' => self::TITLE,
- 'description' => $desc,
- 'install_docs' => $installDocs,
- 'extra_message' => $extraMessage,
- 'order' => 13);
- }
-
- /**
- * Returns true if the PECL module can detect a location database (either a country,
- * region or city will do).
- *
- * @return bool
- */
- public static function isLocationDatabaseAvailable()
- {
- return self::isCityDatabaseAvailable()
- || self::isRegionDatabaseAvailable()
- || self::isCountryDatabaseAvailable();
- }
-
- /**
- * Returns true if the PECL module can detect a city database.
- *
- * @return bool
- */
- public static function isCityDatabaseAvailable()
- {
- return geoip_db_avail(GEOIP_CITY_EDITION_REV0)
- || geoip_db_avail(GEOIP_CITY_EDITION_REV1);
- }
-
- /**
- * Returns true if the PECL module can detect a region database.
- *
- * @return bool
- */
- public static function isRegionDatabaseAvailable()
- {
- return geoip_db_avail(GEOIP_REGION_EDITION_REV0)
- || geoip_db_avail(GEOIP_REGION_EDITION_REV1);
- }
-
- /**
- * Returns true if the PECL module can detect a country database.
- *
- * @return bool
- */
- public static function isCountryDatabaseAvailable()
- {
- return geoip_db_avail(GEOIP_COUNTRY_EDITION);
- }
-
- /**
- * Returns true if the PECL module can detect an organization database.
- *
- * @return bool
- */
- public static function isOrgDatabaseAvailable()
- {
- return geoip_db_avail(GEOIP_ORG_EDITION);
- }
-
- /**
- * Returns true if the PECL module can detect an ISP database.
- *
- * @return bool
- */
- public static function isISPDatabaseAvailable()
- {
- return geoip_db_avail(GEOIP_ISP_EDITION);
- }
-}
diff --git a/plugins/UserCountry/LocationProvider/GeoIp/Php.php b/plugins/UserCountry/LocationProvider/GeoIp/Php.php
deleted file mode 100644
index 56cf7ce171..0000000000
--- a/plugins/UserCountry/LocationProvider/GeoIp/Php.php
+++ /dev/null
@@ -1,388 +0,0 @@
-<?php
-/**
- * Piwik - 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\UserCountry\LocationProvider\GeoIp;
-
-use Piwik\Log;
-use Piwik\Piwik;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-
-/**
- * A LocationProvider that uses the PHP implementation of GeoIP.
- *
- */
-class Php extends GeoIp
-{
- const ID = 'geoip_php';
- const TITLE = 'GeoIP Legacy (Php)';
-
- /**
- * The GeoIP database instances used. This array will contain at most three
- * of them: one for location info, one for ISP info and another for organization
- * info.
- *
- * Each instance is mapped w/ one of the following keys: 'loc', 'isp', 'org'
- *
- * @var array of GeoIP instances
- */
- private $geoIpCache = 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', 'isp' or 'org' strings with
- * an array of filenames.
- *
- * By default, this will be set to Php::$dbNames.
- *
- * @var array
- */
- private $customDbNames;
-
- /**
- * Constructor.
- *
- * @param array|bool $customDbNames The possible filenames for each type of GeoIP database.
- * eg array(
- * 'loc' => array('GeoLiteCity.dat'),
- * 'isp' => array('GeoIP.dat', 'GeoIPISP.dat')
- * 'org' => array('GeoIPOrg.dat')
- * )
- * 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];
- }
- }
- }
- }
-
- /**
- * Closes all open geoip instances.
- */
- public function __destruct()
- {
- foreach ($this->geoIpCache as $instance) {
- geoip_close($instance);
- }
- }
-
- /**
- * Uses a GeoIP 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
- */
- public function getLocation($info)
- {
- $ip = $this->getIpFromInfo($info);
- $isIPv6 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
-
- $result = array();
-
- $locationGeoIp = $this->getGeoIpInstance($key = 'loc');
- if ($locationGeoIp) {
- switch ($locationGeoIp->databaseType) {
- case GEOIP_CITY_EDITION_REV0: // city database type
- case GEOIP_CITY_EDITION_REV1:
- case GEOIP_CITYCOMBINED_EDITION:
- if ($isIPv6) {
- $location = geoip_record_by_addr_v6($locationGeoIp, $ip);
- } else {
- $location = geoip_record_by_addr($locationGeoIp, $ip);
- }
- if (!empty($location)) {
- $result[self::COUNTRY_CODE_KEY] = $location->country_code;
- $result[self::REGION_CODE_KEY] = $location->region;
- $result[self::CITY_NAME_KEY] = utf8_encode($location->city);
- $result[self::AREA_CODE_KEY] = $location->area_code;
- $result[self::LATITUDE_KEY] = $location->latitude;
- $result[self::LONGITUDE_KEY] = $location->longitude;
- $result[self::POSTAL_CODE_KEY] = $location->postal_code;
- }
- break;
- case GEOIP_REGION_EDITION_REV0: // region database type
- case GEOIP_REGION_EDITION_REV1:
- if ($isIPv6) {
- // NOTE: geoip_region_by_addr_v6 does not exist (yet?), so we
- // return the country code and an empty region code
- $location = array(geoip_country_code_by_addr_v6($locationGeoIp, $ip), '');
- } else {
- $location = geoip_region_by_addr($locationGeoIp, $ip);
- }
- if (!empty($location)) {
- $result[self::COUNTRY_CODE_KEY] = $location[0];
- $result[self::REGION_CODE_KEY] = $location[1];
- }
- break;
- case GEOIP_COUNTRY_EDITION: // country database type
- if ($isIPv6) {
- $result[self::COUNTRY_CODE_KEY] = geoip_country_code_by_addr_v6($locationGeoIp, $ip);
- } else {
- $result[self::COUNTRY_CODE_KEY] = geoip_country_code_by_addr($locationGeoIp, $ip);
- }
- break;
- default: // unknown database type, log warning and fallback to country edition
- Log::warning("Found unrecognized database type: %s", $locationGeoIp->databaseType);
-
- if ($isIPv6) {
- $result[self::COUNTRY_CODE_KEY] = geoip_country_code_by_addr_v6($locationGeoIp, $ip);
- } else {
- $result[self::COUNTRY_CODE_KEY] = geoip_country_code_by_addr($locationGeoIp, $ip);
- }
- break;
- }
- }
-
- // NOTE: ISP & ORG require commercial dbs to test. The code has been tested manually,
- // but not by system tests.
- $ispGeoIp = $this->getGeoIpInstance($key = 'isp');
- if ($ispGeoIp) {
- if ($isIPv6) {
- $isp = geoip_name_by_addr_v6($ispGeoIp, $ip);
- } else {
- $isp = geoip_org_by_addr($ispGeoIp, $ip);
- }
- if (!empty($isp)) {
- $result[self::ISP_KEY] = utf8_encode($isp);
- }
- }
-
- $orgGeoIp = $this->getGeoIpInstance($key = 'org');
- if ($orgGeoIp) {
- if ($isIPv6) {
- $org = geoip_name_by_addr_v6($orgGeoIp, $ip);
- } else {
- $org = geoip_org_by_addr($orgGeoIp, $ip);
- }
- if (!empty($org)) {
- $result[self::ORG_KEY] = utf8_encode($org);
- }
- }
-
- if (empty($result)) {
- return false;
- }
-
- $this->completeLocationResult($result);
- return $result;
- }
-
- /**
- * 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 true if this provider has been setup correctly, the error message if
- * otherwise.
- *
- * @return bool|string
- */
- public function isWorking()
- {
- if (!function_exists('mb_internal_encoding')) {
- return Piwik::translate('UserCountry_GeoIPCannotFindMbstringExtension',
- array('mb_internal_encoding', 'mbstring'));
- }
-
- $geoIpError = false;
- $catchGeoIpError = function ($errno, $errstr, $errfile, $errline) use (&$geoIpError) {
- $filename = basename($errfile);
- if ($filename == 'geoip.inc'
- || $filename == 'geoipcity.inc'
- ) {
- $geoIpError = array($errno, $errstr, $errfile, $errline);
- } else {
- throw new \Exception("Error in PHP GeoIP provider: $errstr on line $errline of $errfile"); // unexpected
- }
- };
-
- // catch GeoIP errors
- set_error_handler($catchGeoIpError);
- $result = parent::isWorking();
- restore_error_handler();
-
- if ($geoIpError) {
- list($errno, $errstr, $errfile, $errline) = $geoIpError;
- Log::warning("Got GeoIP error when testing PHP GeoIP location provider: %s(%s): %s", $errfile, $errline, $errstr);
-
- return Piwik::translate('UserCountry_GeoIPIncorrectDatabaseFormat');
- }
-
- return $result;
- }
-
- /**
- * 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 organization database is found, organization information is
- * supported.
- *
- * If an ISP database is found, ISP 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;
-
- $locationGeoIp = $this->getGeoIpInstance($key = 'loc');
- if ($locationGeoIp) {
- switch ($locationGeoIp->databaseType) {
- case GEOIP_CITY_EDITION_REV0: // city database type
- case GEOIP_CITY_EDITION_REV1:
- case GEOIP_CITYCOMBINED_EDITION:
- $result[self::REGION_CODE_KEY] = true;
- $result[self::REGION_NAME_KEY] = true;
- $result[self::CITY_NAME_KEY] = true;
- $result[self::AREA_CODE_KEY] = true;
- $result[self::LATITUDE_KEY] = true;
- $result[self::LONGITUDE_KEY] = true;
- $result[self::POSTAL_CODE_KEY] = true;
- break;
- case GEOIP_REGION_EDITION_REV0: // region database type
- case GEOIP_REGION_EDITION_REV1:
- $result[self::REGION_CODE_KEY] = true;
- $result[self::REGION_NAME_KEY] = true;
- break;
- default: // country or unknown database type
- break;
- }
- }
-
- // check if isp info is available
- if ($this->getGeoIpInstance($key = 'isp')) {
- $result[self::ISP_KEY] = true;
- }
-
- // check of org info is available
- if ($this->getGeoIpInstance($key = 'org')) {
- $result[self::ORG_KEY] = true;
- }
-
- return $result;
- }
-
- /**
- * Returns information about this location provider. Contains an id, title & description:
- *
- * array(
- * 'id' => 'geoip_php',
- * 'title' => '...',
- * 'description' => '...'
- * );
- *
- * @return array
- */
- public function getInfo()
- {
- $desc = Piwik::translate('UserCountry_GeoIpLocationProviderDesc_Php1') . '<br/><br/>'
- . Piwik::translate('UserCountry_GeoIpLocationProviderDesc_Php2',
- array('<strong>', '</strong>', '<strong>', '</strong>'));
- $installDocs = '<a rel="noreferrer noopener" target="_blank" href="https://matomo.org/faq/how-to/#faq_163">'
- . Piwik::translate('UserCountry_HowToInstallGeoIPDatabases')
- . '</a>';
-
- $availableDatabaseTypes = array();
- if (self::getPathToGeoIpDatabase(array('GeoIPCity.dat', 'GeoLiteCity.dat')) !== false) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_City');
- }
- if (self::getPathToGeoIpDatabase(array('GeoIPRegion.dat')) !== false) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Region');
- }
- if (self::getPathToGeoIpDatabase(array('GeoIPCountry.dat')) !== false) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Country');
- }
- if (self::getPathToGeoIpDatabase(array('GeoIPISP.dat')) !== false) {
- $availableDatabaseTypes[] = 'ISP';
- }
- if (self::getPathToGeoIpDatabase(array('GeoIPOrg.dat')) !== false) {
- $availableDatabaseTypes[] = Piwik::translate('UserCountry_Organization');
- }
-
- if (!empty($availableDatabaseTypes)) {
- $extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>:&nbsp;'
- . Piwik::translate('UserCountry_GeoIPImplHasAccessTo') . ':&nbsp;<strong>'
- . implode(', ', $availableDatabaseTypes) . '</strong>.';
- } else {
- $extraMessage = '<strong>' . Piwik::translate('General_Note') . '</strong>:&nbsp;'
- . Piwik::translate('UserCountry_GeoIPNoDatabaseFound') . '<strong>';
- }
-
- return array('id' => self::ID,
- 'title' => self::TITLE,
- 'description' => $desc,
- 'install_docs' => $installDocs,
- 'extra_message' => $extraMessage,
- 'order' => 12);
- }
-
- /**
- * Returns a GeoIP instance. Creates it if necessary.
- *
- * @param string $key 'loc', 'isp' or 'org'. Determines the type of GeoIP database
- * to load.
- * @return object|false
- */
- private function getGeoIpInstance($key)
- {
- if (empty($this->geoIpCache[$key])) {
- // make sure region names are loaded & saved first
- parent::getRegionNames();
- require_once PIWIK_INCLUDE_PATH . '/libs/MaxMindGeoIP/geoipcity.inc';
-
- $pathToDb = self::getPathToGeoIpDatabase($this->customDbNames[$key]);
- if ($pathToDb !== false) {
- $this->geoIpCache[$key] = geoip_open($pathToDb, GEOIP_STANDARD); // TODO support shared memory
- }
- }
-
- return empty($this->geoIpCache[$key]) ? false : $this->geoIpCache[$key];
- }
-}
-
diff --git a/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php b/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php
deleted file mode 100644
index 43c2356b46..0000000000
--- a/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php
+++ /dev/null
@@ -1,291 +0,0 @@
-<?php
-/**
- * Piwik - 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\UserCountry\LocationProvider\GeoIp;
-
-use Piwik\Common;
-use Piwik\IP;
-use Piwik\Piwik;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-use Piwik\Plugins\UserCountry\LocationProvider;
-
-/**
- * A LocationProvider that uses an GeoIP module installed in an HTTP Server.
- *
- * To make this provider available, make sure the GEOIP_ADDR server
- * variable is set.
- *
- */
-class ServerBased extends GeoIp
-{
- const ID = 'geoip_serverbased';
- const TITLE = 'GeoIP Legacy (%s)';
- const TEST_SERVER_VAR = 'GEOIP_ADDR';
- const TEST_SERVER_VAR_ALT = 'GEOIP_COUNTRY_CODE';
- const TEST_SERVER_VAR_ALT_IPV6 = 'GEOIP_COUNTRY_CODE_V6';
-
- private static $geoIpServerVars = array(
- parent::COUNTRY_CODE_KEY => 'GEOIP_COUNTRY_CODE',
- parent::COUNTRY_NAME_KEY => 'GEOIP_COUNTRY_NAME',
- parent::REGION_CODE_KEY => 'GEOIP_REGION',
- parent::REGION_NAME_KEY => 'GEOIP_REGION_NAME',
- parent::AREA_CODE_KEY => 'GEOIP_AREA_CODE',
- parent::LATITUDE_KEY => 'GEOIP_LATITUDE',
- parent::LONGITUDE_KEY => 'GEOIP_LONGITUDE',
- parent::POSTAL_CODE_KEY => 'GEOIP_POSTAL_CODE',
- );
-
- private static $geoIpUtfServerVars = array(
- parent::CITY_NAME_KEY => 'GEOIP_CITY',
- parent::ISP_KEY => 'GEOIP_ISP',
- parent::ORG_KEY => 'GEOIP_ORGANIZATION',
- );
-
- /**
- * Uses a GeoIP 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 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 Server Module (apache/nginx) does not support this use case... ");
- $fallbacks = array(
- Pecl::ID,
- 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. We recommend to configure Geolocation PECL module to fix this error.");
-
- return false;
- }
-
- $result = array();
- foreach (self::$geoIpServerVars as $resultKey => $geoipVarName) {
- if (!empty($_SERVER[$geoipVarName])) {
- $result[$resultKey] = $_SERVER[$geoipVarName];
- }
-
- $geoipVarNameV6 = $geoipVarName . '_V6';
- if (!empty($_SERVER[$geoipVarNameV6])) {
- $result[$resultKey] = $_SERVER[$geoipVarNameV6];
- }
- }
- foreach (self::$geoIpUtfServerVars as $resultKey => $geoipVarName) {
- if (!empty($_SERVER[$geoipVarName])) {
- $result[$resultKey] = utf8_encode($_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::COUNTRY_CODE_KEY] = true;
- $result[self::COUNTRY_NAME_KEY] = true;
- $result[self::CONTINENT_CODE_KEY] = true;
- $result[self::CONTINENT_NAME_KEY] = true;
-
- return $result;
- }
-
- /**
- * Checks if an HTTP server module has been installed. It checks by looking for
- * the GEOIP_ADDR server variable.
- *
- * There's a special check for the Apache module, but we can't check specifically
- * for anything else.
- *
- * @return bool|string
- */
- public function isAvailable()
- {
- // check if apache module is installed
- if (function_exists('apache_get_modules')) {
- foreach (apache_get_modules() as $name) {
- if (strpos($name, 'geoip') !== false) {
- return true;
- }
- }
- }
-
- $available = !empty($_SERVER[self::TEST_SERVER_VAR])
- || !empty($_SERVER[self::TEST_SERVER_VAR_ALT])
- || !empty($_SERVER[self::TEST_SERVER_VAR_ALT_IPV6])
- ;
-
- if ($available) {
- return true;
- }
-
- // if not available return message w/ extra info
- if (!function_exists('apache_get_modules')) {
- return Piwik::translate('General_Note') . ':&nbsp;' . Piwik::translate('UserCountry_AssumingNonApache');
- }
-
- $message = "<strong>" . Piwik::translate('General_Note') . ':&nbsp;'
- . 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 GEOIP_ADDR server variable is defined.
- *
- * @return bool
- */
- public function isWorking()
- {
- if (empty($_SERVER[self::TEST_SERVER_VAR])
- && empty($_SERVER[self::TEST_SERVER_VAR_ALT])
- && empty($_SERVER[self::TEST_SERVER_VAR_ALT_IPV6])
- ) {
- return Piwik::translate("UserCountry_CannotFindGeoIPServerVar", self::TEST_SERVER_VAR . ' $_SERVER');
- }
-
- return true; // can't check for another IP
- }
-
- /**
- * 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('UserCountry_GeoIpLocationProviderDesc_ServerBased1', array('<strong>', '</strong>'))
- . '<br/><br/>'
- . Piwik::translate('UserCountry_GeoIpLocationProviderDesc_ServerBasedAnonWarn')
- . '<br/><br/>'
- . Piwik::translate('UserCountry_GeoIpLocationProviderDesc_ServerBased2',
- array('<strong>', '</strong>', '<strong>', '</strong>'));
- $installDocs =
- '<a rel="noreferrer noopener" target="_blank" href="https://matomo.org/faq/how-to/#faq_165">'
- . Piwik::translate('UserCountry_HowToInstallApacheModule')
- . '</a><br/>'
- . '<a rel="noreferrer noopener" target="_blank" href="https://matomo.org/faq/how-to/#faq_166">'
- . Piwik::translate('UserCountry_HowToInstallNginxModule')
- . '</a>';
-
- $geoipServerVars = array();
- foreach ($_SERVER as $key => $value) {
- if (strpos($key, 'GEOIP') === 0) {
- $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>';
- }
-
- return array('id' => self::ID,
- 'title' => $title,
- 'description' => $desc,
- 'order' => 14,
- '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;
- }
-}
diff --git a/plugins/UserCountry/Reports/Base.php b/plugins/UserCountry/Reports/Base.php
index 15a3890633..c25c1b71f8 100644
--- a/plugins/UserCountry/Reports/Base.php
+++ b/plugins/UserCountry/Reports/Base.php
@@ -50,7 +50,7 @@ abstract class Base extends \Piwik\Plugin\Report
$footerMessage .= ' ' . Piwik::translate('UserCountry_NoDataForGeoIPReport2',
array('<a target="_blank" href="' . Url::getCurrentQueryStringWithParametersModified($params) . '">',
'</a>',
- '<a rel="noreferrer noopener" target="_blank" href="http://dev.maxmind.com/geoip/geolite?rId=piwik">',
+ '<a rel="noreferrer noopener" target="_blank" href="https://db-ip.com/?refid=mtm">',
'</a>'));
} else {
$footerMessage .= ' ' . Piwik::translate('UserCountry_ToGeolocateOldVisits',
diff --git a/plugins/UserCountry/Reports/GetContinent.php b/plugins/UserCountry/Reports/GetContinent.php
index 51f6fbc370..abd8d32707 100644
--- a/plugins/UserCountry/Reports/GetContinent.php
+++ b/plugins/UserCountry/Reports/GetContinent.php
@@ -12,7 +12,6 @@ use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\UserCountry\Columns\Continent;
use Piwik\Report\ReportWidgetFactory;
-use Piwik\Widget\WidgetContainerConfig;
use Piwik\Widget\WidgetsList;
class GetContinent extends Base
diff --git a/plugins/UserCountry/Tasks.php b/plugins/UserCountry/Tasks.php
deleted file mode 100644
index 73618b91be..0000000000
--- a/plugins/UserCountry/Tasks.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Piwik - 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\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 GeoIPAutoUpdater());
- }
- }
-} \ No newline at end of file
diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php
index 2d8c0bfce1..b88e5313a9 100644
--- a/plugins/UserCountry/UserCountry.php
+++ b/plugins/UserCountry/UserCountry.php
@@ -8,18 +8,10 @@
*/
namespace Piwik\Plugins\UserCountry;
-use Piwik\ArchiveProcessor;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Intl\Data\Provider\RegionDataProvider;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-use Piwik\Plugins\UserCountry\LocationProvider;
-use Piwik\Url;
-
-/**
- * @see plugins/UserCountry/GeoIPAutoUpdater.php
- */
-require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/GeoIPAutoUpdater.php';
+use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
/**
*
@@ -34,7 +26,6 @@ class UserCountry extends \Piwik\Plugin
return array(
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
- 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral',
'Insights.addReportToOverview' => 'addReportToInsightsOverview',
);
@@ -59,8 +50,6 @@ class UserCountry extends \Piwik\Plugin
{
$jsFiles[] = "plugins/UserCountry/angularjs/location-provider-selection/location-provider-selection.controller.js";
$jsFiles[] = "plugins/UserCountry/angularjs/location-provider-selection/location-provider-selection.directive.js";
- $jsFiles[] = "plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.controller.js";
- $jsFiles[] = "plugins/UserCountry/angularjs/location-provider-updater/location-provider-updater.directive.js";
}
/**
@@ -93,20 +82,11 @@ class UserCountry extends \Piwik\Plugin
public function isGeoIPWorking()
{
$provider = LocationProvider::getCurrentProvider();
- return $provider instanceof GeoIp
+ return $provider instanceof GeoIp2
&& $provider->isAvailable() === true
&& $provider->isWorking() === true;
}
- public function getClientSideTranslationKeys(&$translationKeys)
- {
- $translationKeys[] = "UserCountry_FatalErrorDuringDownload";
- $translationKeys[] = "UserCountry_SetupAutomaticUpdatesOfGeoIP";
- $translationKeys[] = "General_Done";
- $translationKeys[] = "General_Save";
- $translationKeys[] = "General_Continue";
- }
-
public static function isGeoLocationAdminEnabled()
{
return (bool) Config::getInstance()->General['enable_geolocation_admin'];
diff --git a/plugins/UserCountry/functions.php b/plugins/UserCountry/functions.php
index 6c24afb44c..0061a4e518 100644
--- a/plugins/UserCountry/functions.php
+++ b/plugins/UserCountry/functions.php
@@ -10,11 +10,9 @@
namespace Piwik\Plugins\UserCountry;
use Piwik\DataTable;
-use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
use Piwik\Tracker\Visit;
/**
@@ -118,21 +116,63 @@ function getElementFromStringArray($label, $separator, $index, $emptyValue = fal
*/
function getRegionNameFromCodes($countryCode, $regionCode)
{
- if (!Manager::getInstance()->isPluginActivated('GeoIp2') ||
- LocationProvider::getCurrentProvider() instanceof GeoIp) {
- return GeoIp::getRegionNameFromCodes($countryCode, $regionCode);
- }
-
$name = GeoIp2::getRegionNameFromCodes($countryCode, $regionCode);
- // fallback if no translation for with GeoIP2
+ // fallback if no translation with GeoIP2
if ($name == Piwik::translate('General_Unknown')) {
- $name = GeoIp::getRegionNameFromCodes($countryCode, $regionCode);
+ $name = getLegacyRegionNameFromCodes($countryCode, $regionCode);
}
return $name;
}
+
+/**
+ * Returns a region name for a country code + region code.
+ *
+ * @param string $countryCode
+ * @param string $regionCode
+ * @return string The region name or 'Unknown' (translated).
+ */
+function getLegacyRegionNameFromCodes($countryCode, $regionCode)
+{
+ $regionNames = getRegionNames();
+
+ $countryCode = strtoupper($countryCode);
+ $regionCode = strtoupper($regionCode);
+
+ // ensure tibet is shown as region of china
+ if ($countryCode == 'TI' && $regionCode == '1') {
+ $regionCode = '14';
+ $countryCode = 'CN';
+ }
+
+ 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
+ */
+function getRegionNames()
+{
+ static $regionNames;
+
+ if (is_null($regionNames)) {
+ $GEOIP_REGION_NAME = array();
+ require_once PIWIK_INCLUDE_PATH . '/libs/MaxMindGeoIP/geoipregionvars.php';
+ $regionNames = $GEOIP_REGION_NAME;
+ }
+
+ return $regionNames;
+}
+
+
/**
* Returns the region name using the label of a Visits by Region report.
*
diff --git a/plugins/UserCountry/lang/en.json b/plugins/UserCountry/lang/en.json
index 852293b84d..fc74a8a402 100644
--- a/plugins/UserCountry/lang/en.json
+++ b/plugins/UserCountry/lang/en.json
@@ -1,13 +1,6 @@
{
"UserCountry": {
- "AssumingNonApache": "Cannot find apache_get_modules function, assuming non-Apache webserver.",
- "CannotFindGeoIPDatabaseInArchive": "Cannot find %1$s file in tar archive %2$s!",
- "CannotFindGeoIPServerVar": "The %s variable is not set. Your server may not be configured correctly.",
- "CannotFindPeclGeoIPDb": "Could not find a country, region or city database for the GeoIP PECL module. Make sure your geolocation database is located in %1$s and is named %2$s or %3$s otherwise the PECL module will not notice it.",
- "CannotListContent": "Couldn't list content for %1$s: %2$s",
"CannotLocalizeLocalIP": "IP address %s is a local address and cannot be geolocated.",
- "CannotSetupGeoIPAutoUpdating": "It seems like you're storing your geolocation databases outside of Matomo (we can tell since there are no databases in the misc subdirectory, but your GeoIP is working). Matomo cannot automatically update your geolocation databases if they are located outside of the misc directory.",
- "CannotUnzipDatFile": "Could not unzip dat file in %1$s: %2$s",
"City": "City",
"CityAndCountry": "%1$s, %2$s",
"Continent": "Continent",
@@ -24,81 +17,29 @@
"DefaultLocationProviderDesc2": "This is not very accurate, so %1$swe recommend installing and using %2$sa geolocation database%3$s.%4$s",
"DefaultLocationProviderExplanation": "You are using the default location provider, which means Matomo will guess the visitor's location based on the language they use. %1$sRead this%2$s to learn how to setup more accurate geolocation.",
"DistinctCountries": "%s distinct countries",
- "DownloadingDb": "Downloading %s",
- "DownloadNewDatabasesEvery": "Update databases every",
- "FatalErrorDuringDownload": "A fatal error occurred while downloading this file. There might be something wrong with your internet connection, with the geolocation database you downloaded or Matomo. Try downloading and installing it manually.",
- "FoundApacheModules": "Matomo found the following Apache modules",
"FromDifferentCities": "different cities",
- "GeoIPCannotFindMbstringExtension": "Cannot find the %1$s function. Please make sure the %2$s extension is installed and loaded.",
- "GeoIPDatabases": "GeoIP Databases",
"GeoIPDocumentationSuffix": "In order to see data for this report, you must setup GeoIP in the Geolocation admin tab. The commercial %1$sMaxmind%2$s GeoIP databases are more accurate than the free ones. To see how accurate they are, click %3$shere%4$s.",
- "GeoIPNoDatabaseFound": "This GeoIP implementation was not able to find any database.",
- "GeoIPImplHasAccessTo": "This GeoIP implementation has access to the following types of databases",
- "GeoIPIncorrectDatabaseFormat": "Your geolocation database does not seem to have the correct format. It may be corrupt. Make sure you are using the binary version and try replacing it with another copy.",
- "GeoIpLocationProviderDesc_Pecl1": "This location provider uses a geolocation database and a PECL module to accurately and efficiently determine the location of your visitors.",
- "GeoIpLocationProviderDesc_Pecl2": "There are no limitations with this provider, so it is the one we recommend using.",
- "GeoIpLocationProviderDesc_Php1": "This location provider is the simplest to install as it does not require server configuration (ideal for shared hosting!). It uses a geolocation database and MaxMind's PHP API to accurately determine the location of your visitors.",
- "GeoIpLocationProviderDesc_Php2": "If your website gets a lot of traffic, you may find that this location provider is too slow. In this case, you should install the %1$sPECL extension%2$s or a %3$sserver module%4$s.",
- "GeoIpLocationProviderDesc_ServerBased1": "This location provider uses the GeoIP 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",
- "GeoIpLocationProviderDesc_ServerBased2": "If you have to import log files or do something else that requires setting IP addresses, use the %1$sPECL GeoIP implementation (recommended)%2$s or the %3$sPHP GeoIP implementation%4$s.",
- "GeoIpLocationProviderDesc_ServerBasedAnonWarn": "Note: IP anonymization has no effect on the locations reported by this provider. Before using it with IP anonymization, make sure this does not violate any privacy laws you may be subject to.",
- "GeoIpLocationProviderNotRecomnended": "Geolocation works, but you are not using one of the recommended providers.",
- "GeoIPNoServerVars": "Matomo cannot find any GeoIP %s variables.",
- "GeoIPPeclCustomDirNotSet": "The %s PHP ini option is not set.",
- "GeoIPServerVarsFound": "Matomo detects the following GeoIP %s variables",
- "GeoIPUpdaterInstructions": "Enter the download links for your databases below. If you've purchased databases from %3$sdbip%4$s or %1$sMaxMind%2$s, you can find these links in your dbip or MaxMind account. Please contact your geolocation database provider if you have trouble accessing them.",
- "GeoIPUpdaterIntro": "Matomo is currently managing updates for the following databases",
- "GeoLiteCityLink": "If you're using the dbip city lite database, use this link: %1$s%2$s%3$s",
"Geolocation": "Geolocation",
"GeolocationPageDesc": "On this page you can change how Matomo determines visitor locations.",
"getCityDocumentation": "This report shows the cities your visitors were in when they accessed your website.",
"getContinentDocumentation": "This report shows which continent your visitors were in when they accessed your website.",
"getCountryDocumentation": "This report shows which country your visitors were in when they accessed your website.",
"getRegionDocumentation": "This report shows which region your visitors were in when they accessed your website.",
- "HowToInstallApacheModule": "How do I install the GeoIP module for Apache?",
"HowToInstallGeoIPDatabases": "How do I get geolocation databases?",
- "HowToInstallGeoIpPecl": "How do I install the GeoIP PECL extension?",
- "HowToInstallNginxModule": "How do I install the GeoIP module for Nginx?",
- "HowToSetupGeoIP": "How to setup accurate geolocation with dbip",
- "HowToSetupGeoIP_Step1": "%1$sDownload%2$s the DBIP City Lite database from %3$sdbip%4$s.",
- "HowToSetupGeoIP_Step2": "Extract this file and copy the result, %1$s into the %2$smisc%3$s Matomo subdirectory and rename it to %4$s (you can do this either by FTP or SSH).",
- "HowToSetupGeoIP_Step3": "Reload this screen. The %1$sDBIP / GeoIP (PHP)%2$s provider will now be %3$sInstalled%4$s. Select it.",
- "HowToSetupGeoIP_Step4": "And you're done! You've just setup Matomo to use DBIP which means you'll be able to see the regions and cities of your visitors along with very accurate country information.",
- "HowToSetupGeoIPIntro": "You do not appear to have accurate Geolocation setup. This is a useful feature and without it you will not see accurate and complete location information for your visitors. Here's how you can quickly start using it:",
- "HttpServerModule": "HTTP Server Module",
- "InvalidGeoIPUpdatePeriod": "Invalid period for the GeoIP updater: %1$s. Valid values are %2$s.",
- "IPurchasedGeoIPDBs": "I purchased more accurate databases from %3$sdbip%4$s or %1$sMaxMind%2$s and want to setup automatic updates.",
- "ISPDatabase": "ISP Database",
- "IWantToDownloadFreeGeoIP": "I want to download the free DBIP database...",
"Latitude": "Latitude",
"Latitudes": "Latitudes",
"Location": "Location",
- "LocationDatabase": "Location Database",
- "LocationDatabaseHint": "A location database is either a country, region or city database.",
"LocationProvider": "Location Provider",
"Longitude": "Longitude",
"Longitudes": "Longitudes",
"NoDataForGeoIPReport1": "There is no data for this report because there is either no location data available or visitor IP addresses cannot be geolocated.",
"NoDataForGeoIPReport2": "To enable accurate geolocation, change the settings %1$shere%2$s and use a %3$scity level database%4$s.",
- "Organization": "Organization",
- "OrgDatabase": "Organization Database",
- "PeclGeoIPNoDBDir": "The PECL module is looking for databases in %1$s, but this directory does not exist. Please create it and add the geolocation databases to it. Alternatively, you can set %2$s to the correct directory in your php.ini file.",
- "PeclGeoLiteError": "Your geolocation database in %1$s is named %2$s. Unfortunately, the PECL module will not recognize it with this name. Please rename it to %3$s.",
- "PiwikNotManagingGeoIPDBs": "Matomo is not currently managing any DBIP or MaxMind databases.",
+ "NoProviders": "There are currently no additional geolocation providers available. Matomo recommends using the %1$sdbip%2$s databases, but this requires activating the GeoIp2 plugin. (Alternatively you can install a third party plugin that provides it's own geolocation functionality from the marketplace.)",
"PluginDescription": "Reports the location of your visitors: country, region, city and geographic coordinates (latitude\/longitude).",
"Region": "Region",
- "SetupAutomaticUpdatesOfGeoIP": "Setup automatic updates of geolocation databases",
"SubmenuLocations": "Locations",
"TestIPLocatorFailed": "Matomo tried checking the location of a known IP address (%1$s), but your server returned no information. This provider may not be configured correctly (the geolocation database may be named incorrectly or located in the wrong directory, for instance).",
- "ThisUrlIsNotAValidGeoIPDB": "The downloaded file is not a valid geolocation database. Please re-check the URL or download the file manually.",
"ToGeolocateOldVisits": "To get location data for your old visits, use the script described %1$shere%2$s.",
- "UnsupportedArchiveType": "Encountered unsupported archive type %1$s.",
- "UpdaterHasNotBeenRun": "The updater has never been run.",
- "UpdaterIsNotScheduledToRun": "It is not scheduled to run in the future.",
- "UpdaterScheduledForNextRun": "It is scheduled to run during the next cron core:archive command execution.",
- "UpdaterWasLastRun": "The updater was last run on %s.",
- "UpdaterWillRunNext": "It is next scheduled to run on %s.",
- "WidgetLocation": "Visitor Location",
- "InstallGeoIp2": "Matomo recommends using the %1$sdbip%2$s databases, but this requires using the GeoIp2 plugin. If you install and activate it (which will require a possibly long running update), you will be able to get started using %1$sdbip%2$s databases. (Ignore this if you are using a third party plugin that provides it's own geolocation functionality.)"
+ "WidgetLocation": "Visitor Location"
}
} \ No newline at end of file
diff --git a/plugins/UserCountry/templates/_updaterNextRunTime.twig b/plugins/UserCountry/templates/_updaterNextRunTime.twig
deleted file mode 100644
index 69882f08b4..0000000000
--- a/plugins/UserCountry/templates/_updaterNextRunTime.twig
+++ /dev/null
@@ -1,9 +0,0 @@
-{% if nextRunTime|default is not empty %}
- {% if date(nextRunTime.getTimestamp()) <= date() %}
- {{ 'UserCountry_UpdaterScheduledForNextRun'|translate }}
- {% else %}
- {{ 'UserCountry_UpdaterWillRunNext'|translate('<strong>' ~ nextRunTime.toString() ~ '</strong>')|raw }}
- {% endif %}
-{% else %}
- {{ 'UserCountry_UpdaterIsNotScheduledToRun'|translate }}
-{% endif %} \ No newline at end of file
diff --git a/plugins/UserCountry/templates/adminIndex.twig b/plugins/UserCountry/templates/adminIndex.twig
index f0a32da588..ca11eb6d06 100644
--- a/plugins/UserCountry/templates/adminIndex.twig
+++ b/plugins/UserCountry/templates/adminIndex.twig
@@ -15,19 +15,7 @@
<div piwik-location-provider-selection="{{ currentProviderId|e('html_attr') }}">
{% if not isThereWorkingProvider %}
- <h3 style="margin-top:0;">{{ 'UserCountry_HowToSetupGeoIP'|translate }}</h3>
- {% if dbipLiteUrl|default is not empty %}
- <p>{{ 'UserCountry_HowToSetupGeoIPIntro'|translate }}</p>
- <ul style="list-style:disc !important;margin-left:2em;">
- <li style="list-style-type: disc !important;">{{ 'UserCountry_HowToSetupGeoIP_Step1'|translate('<a rel="noreferrer noopener" href="'~dbipLiteUrl~'">','</a>','<a rel="noreferrer noopener" target="_blank" href="http://db-ip.com/?refid=mtm">','</a>')|raw }}</li>
- <li style="list-style-type: disc !important;">{{ 'UserCountry_HowToSetupGeoIP_Step2'|translate("'"~dbipLiteFilename~"'",'<strong>','</strong>','<strong>'~dbipLiteDesiredFilename~'</strong>')|raw }}</li>
- <li style="list-style-type: disc !important;">{{ 'UserCountry_HowToSetupGeoIP_Step3'|translate('<strong>','</strong>','<span style="color:green"><strong>','</strong></span>')|raw }}</li>
- <li style="list-style-type: disc !important;">{{ 'UserCountry_HowToSetupGeoIP_Step4'|translate }}</li>
- </ul>
- {% else %}
- <p>{{ 'UserCountry_InstallGeoIp2'|translate('<a rel="noreferrer noopener" target="_blank" href="http://db-ip.com/?refid=mtm">','</a>')|raw }}</p>
- {% endif %}
- <p>&nbsp;</p>
+ {{ setUpGuides|raw }}
{% endif %}
<div class="row">
@@ -97,95 +85,21 @@
</div>
{% endfor %}
- <div piwik-save-button onconfirm="locationSelector.save()" saving="locationSelector.isLoading"></div>
-
-</div>
-</div>
-
-{% if geoIPLegacyLocUrl is defined and geoIPLegacyLocUrl and isInternetEnabled %}
- {# The text in this part is not translatable on purpose, as it will be removed again soon #}
- <div piwik-content-block content-title="Automatic Updates for GeoIP Legacy">
-
- <p>Setting up automatic updates for GeoIP Legacy is no longer supported.</p>
-
- <div class="notification system notification-warning">
- {% if 'GeoLite' in geoIPLegacyLocUrl %}
- <div>Maxmind announced to discontinue updates to the GeoLite Legacy databases as of April 1, 2018.</div>
- {% endif %}
- <strong>Please consider switching to GeoIP 2 soon! GeoIP Legacy Support is deprecated and will be removed in one of the next major releases.</strong>
- </div>
-
- {% if geoIPLegacyLocUrl or geoIPLegacyIspUrl or geoIPLegacyOrgUrl %}
- <h3>GeoIP Legacy Auto Update</h3>
-
- <p>Your previous configuration for automatic updates for GeoIP legacy databases is still up and running. It will be automatically disabled and removed after switching to GeoIP2.</p>
-
- <p>Below you can find the current configuration:</p>
- {% if geoIPLegacyLocUrl %}<p>{{ 'UserCountry_LocationDatabase'|translate|e('html_attr') }}: {{ geoIPLegacyLocUrl }}</p>{% endif %}
- {% if geoIPLegacyIspUrl %}<p>{{ 'UserCountry_ISPDatabase'|translate|e('html_attr') }}: {{ geoIPLegacyIspUrl }}</p>{% endif %}
- {% if geoIPLegacyOrgUrl %}<p>{{ 'UserCountry_OrgDatabase'|translate|e('html_attr') }}: {{ geoIPLegacyOrgUrl }}</p>{% endif %}
- {% if geoIPLegacyUpdatePeriod %}<p>{{ 'UserCountry_DownloadNewDatabasesEvery'|translate|e('html_attr') }}: {{ geoIPLegacyUpdatePeriod }}</p>{% endif %}
-
- {% endif %}
+ {% if locationProviders|length == 1 %}
+ <div piwik-notification
+ noclear="true"
+ context="warning">
+ {{ 'UserCountry_NoProviders'|translate('<a rel="noreferrer noopener" href="https://db-ip.com/?refid=mtm">','</a>')|raw }}
</div>
-{% endif %}
-
-{% if isInternetEnabled and not notUsingGeoIpPlugin %}
- <div piwik-content-block
- content-title="{% if not geoIPDatabasesInstalled %}{{ 'UserCountry_GeoIPDatabases'|translate|e('html_attr') }}{% else %}{{ 'UserCountry_SetupAutomaticUpdatesOfGeoIP'|translate|e('html_attr') }}{% endif %}"
- id="geoip-db-mangement">
+ {% endif %}
- <div piwik-location-provider-updater
- geoip-database-installed="{% if geoIPDatabasesInstalled %}1{% else %}0{% endif %}">
+ <div piwik-save-button onconfirm="locationSelector.save()" saving="locationSelector.isLoading"></div>
- {% if showGeoIPUpdateSection %}
- {% if not geoIPDatabasesInstalled %}
- <div ng-show="!locationUpdater.geoipDatabaseInstalled">
- <div ng-show="locationUpdater.showPiwikNotManagingInfo">
- <h3>{{ 'UserCountry_PiwikNotManagingGeoIPDBs'|translate|e('html_attr') }}</h3>
- <div id="manage-geoip-dbs">
- <div class="row" id="geoipdb-screen1">
- <div class="geoipdb-column-1 col s6">
- <p>{{ 'UserCountry_IWantToDownloadFreeGeoIP'|translate|raw }}</p>
- </div>
- <div class="geoipdb-column-2 col s6">
- <p>{{ 'UserCountry_IPurchasedGeoIPDBs'|translate('<a rel="noreferrer noopener" href="http://www.maxmind.com/en/geolocation_landing?rId=piwik">','</a>','<a rel="noreferrer noopener" href="https://db-ip.com/db/?refid=mtm">','</a>')|raw }}</p>
- </div>
- <div class="geoipdb-column-1 col s6">
- <input type="button" class="btn"
- ng-click="locationUpdater.startDownloadFreeGeoIp()"
- value="{{ 'General_GetStarted'|translate }}..."/>
- </div>
- <div class="geoipdb-column-2 col s6">
- <input type="button" class="btn"
- ng-click="locationUpdater.startAutomaticUpdateGeoIp()"
- value="{{ 'General_GetStarted'|translate }}..." id="start-automatic-update-geoip"/>
- </div>
- </div>
- </div>
- </div>
- {% if dbipLiteUrl|default is not empty %}
- {% set downloadingDbLink %}<a href="{{ dbipLiteUrl|e('html_attr') }}">{{ dbipLiteFilename }}</a>{% endset %}
- {% else %}
- {% set downloadingDbLink = '' %}
- {% endif %}
- <div id="geoipdb-screen2-download" ng-show="locationUpdater.showFreeDownload">
- <div piwik-progressbar
- label="{{ ('UserCountry_DownloadingDb'|translate(downloadingDbLink) ~ '...')|json_encode }}"
- progress="locationUpdater.progressFreeDownload">
- </div>
- </div>
- </div>
- {% endif %}
+</div>
+</div>
- {% include "@UserCountry/_updaterManage.twig" %}
- {% else %}
- <p class="form-description">{{ 'UserCountry_CannotSetupGeoIPAutoUpdating'|translate }}</p>
- {% endif %}
- </div>
- </div>
-{% endif %}
+{{ configurations|raw }}
{% endblock %}
diff --git a/plugins/UserCountry/tests/Integration/APITest.php b/plugins/UserCountry/tests/Integration/APITest.php
index 43122a61a3..22f15b89bb 100644
--- a/plugins/UserCountry/tests/Integration/APITest.php
+++ b/plugins/UserCountry/tests/Integration/APITest.php
@@ -67,7 +67,7 @@ class APITest extends IntegrationTestCase
{
Access::getInstance()->setSuperUserAccess(false);
- $locationProvider = LocationProvider\GeoIp\Php::ID;
+ $locationProvider = GeoIp2\Php::ID;
$this->api->setLocationProvider($locationProvider);
}
@@ -78,7 +78,7 @@ class APITest extends IntegrationTestCase
{
Config::getInstance()->General['enable_geolocation_admin'] = 0;
- $locationProvider = LocationProvider\GeoIp\Php::ID;
+ $locationProvider = GeoIp2\Php::ID;
$this->api->setLocationProvider($locationProvider);
}
diff --git a/plugins/UserCountry/tests/UI/UserCountry_spec.js b/plugins/UserCountry/tests/UI/UserCountry_spec.js
new file mode 100644
index 0000000000..140b152ddf
--- /dev/null
+++ b/plugins/UserCountry/tests/UI/UserCountry_spec.js
@@ -0,0 +1,35 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * Screenshot integration tests.
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+describe("UserCountry", function () {
+
+ afterEach(function () {
+ delete testEnvironment.pluginsToUnload;
+ testEnvironment.save();
+ });
+
+ it('should show geolocation admin without additional providers', async function () {
+ testEnvironment.pluginsToUnload = ['GeoIp2'];
+ testEnvironment.save();
+
+ await page.goto("?module=UserCountry&action=adminIndex");
+
+ expect(await page.screenshotSelector('#content')).to.matchImage('admin_no_providers');
+ });
+
+ it('should show geolocation admin with GeoIP2 providers', async function () {
+ testEnvironment.pluginsToLoad = ['GeoIp2'];
+ testEnvironment.save();
+
+ await page.goto("?module=UserCountry&action=adminIndex");
+
+ expect(await page.screenshotSelector('#content')).to.matchImage('admin_geoip2');
+ });
+
+});
diff --git a/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_geoip2.png b/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_geoip2.png
new file mode 100644
index 0000000000..b2b9a0746d
--- /dev/null
+++ b/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_geoip2.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:80072ca5e400445105511d146c386428b68f4d0f812c054081f5fe5539a0bf9f
+size 237893
diff --git a/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_no_providers.png b/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_no_providers.png
new file mode 100644
index 0000000000..0e88b39b47
--- /dev/null
+++ b/plugins/UserCountry/tests/UI/expected-screenshots/UserCountry_admin_no_providers.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:31448253e042c0c4f62cd2232e1408529cde22595999d8355bde3ea955bcfd27
+size 67691
diff --git a/plugins/UserCountry/tests/Unit/UserCountryTest.php b/plugins/UserCountry/tests/Unit/UserCountryTest.php
index b28c5fc9d1..8f624c6ab4 100644
--- a/plugins/UserCountry/tests/Unit/UserCountryTest.php
+++ b/plugins/UserCountry/tests/Unit/UserCountryTest.php
@@ -10,11 +10,6 @@ namespace Piwik\Plugins\UserCountry\tests\Unit;
use Piwik\Container\StaticContainer;
use Piwik\Intl\Data\Provider\RegionDataProvider;
-use Piwik\Plugins\UserCountry\GeoIPAutoUpdater;
-use Piwik\Plugins\UserCountry\LocationProvider\GeoIp;
-use Piwik\Plugins\UserCountry\LocationProvider;
-use Exception;
-use Piwik\Tests\Framework\Fixture;
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/UserCountry.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
@@ -73,119 +68,4 @@ class UserCountryTest extends \PHPUnit\Framework\TestCase
$this->assertArrayHasKey($country, $countries, $filename);
}
}
-
- /**
- * Test that redundant checks work.
- *
- * @group Plugins
- */
- public function testGeoIpUpdaterRedundantChecks()
- {
- GeoIp::$geoIPDatabaseDir = 'tests/lib/geoip-files';
- LocationProvider::$providers = null;
-
- // create empty ISP & Org files
- $this->createEmptyISPOrgFiles();
-
- // run redundant checks
- $updater = new Piwik_UserCountry_GeoIPAutoUpdater_publictest();
- $updater->performRedundantDbChecks();
-
- // check that files are renamed correctly
- $this->checkBrokenGeoIPState();
-
- // create empty files again & run checks again
- $this->createEmptyISPOrgFiles();
- $updater->performRedundantDbChecks();
-
- // check that w/ broken files already there, redundant checks still work correctly
- $this->checkBrokenGeoIPState();
- }
-
- /**
- * @group Plugins
- *
- * @dataProvider getInvalidGeoIpUrlsToTest
- */
- public function testGeoIpDownloadInvalidUrl($url)
- {
- // unset translations, otherwise Exception message will be translated
- Fixture::resetTranslations();
-
- $updater = new Piwik_UserCountry_GeoIPAutoUpdater_publictest();
- try {
- $updater->downloadFile('loc', $url);
- $this->fail("Downloading invalid url succeeded!");
- } catch (Exception $ex) {
- $this->assertEquals("UserCountry_UnsupportedArchiveType", $ex->getMessage());
- }
- }
-
- public function getInvalidGeoIpUrlsToTest()
- {
- return array(array("http://localhost/tests/resources/geoip.tar"),
- array("http://localhost/tests/resources/geoip.tar.bz2"),
- array("http://localhost/tests/resources/geoip.dat"));
- }
-
- public function setUp()
- {
- // empty
- }
-
- public function tearDown()
- {
- $geoIpDirPath = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
- $filesToRemove = array('GeoIPISP.dat.broken', 'GeoIPOrg.dat.broken', 'GeoIPISP.dat', 'GeoIPOrg.dat');
-
- foreach ($filesToRemove as $name) {
- $path = $geoIpDirPath . '/' . $name;
- if (file_exists($path)) {
- @unlink($path);
- }
- }
- }
-
- private function createEmptyISPOrgFiles()
- {
- $geoIpDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
-
- $fd = fopen($geoIpDir . '/GeoIPISP.dat', 'w');
- fclose($fd);
-
- $fd = fopen($geoIpDir . '/GeoIPOrg.dat', 'w');
- fclose($fd);
- }
-
- private function checkBrokenGeoIPState()
- {
- $geoIpDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
-
- $this->assertFalse(file_exists($geoIpDir . '/GeoIPCity.dat.broken'));
-
- $this->assertFalse(file_exists($geoIpDir . '/GeoIPISP.dat'));
- $this->assertTrue(file_exists($geoIpDir . '/GeoIPISP.dat.broken'));
-
- $this->assertFalse(file_exists($geoIpDir . '/GeoIPOrg.dat'));
- $this->assertTrue(file_exists($geoIpDir . '/GeoIPOrg.dat.broken'));
- }
-}
-
-class Piwik_UserCountry_GeoIPAutoUpdater_publictest extends GeoIPAutoUpdater
-{
- public function __construct()
- {
- // empty
- }
-
- // during tests do not call the Log::error or they will be displayed in the output
- public function performRedundantDbChecks($logErrors = false)
- {
- parent::performRedundantDbChecks($logErrors);
- }
-
- public function downloadFile($type, $url)
- {
- parent::downloadFile($type, $url);
- }
-}
+} \ No newline at end of file
diff --git a/tests/PHPUnit/Framework/TestingEnvironmentManipulator.php b/tests/PHPUnit/Framework/TestingEnvironmentManipulator.php
index e9a5a9cb81..1138b3ca71 100644
--- a/tests/PHPUnit/Framework/TestingEnvironmentManipulator.php
+++ b/tests/PHPUnit/Framework/TestingEnvironmentManipulator.php
@@ -253,6 +253,10 @@ class TestingEnvironmentManipulator implements EnvironmentManipulator
$plugins = $this->getPluginAndRequiredPlugins($pluginName, $plugins);
}
+ $pluginsToUnload = $this->vars->pluginsToUnload ?? [];
+
+ $plugins = array_diff($plugins, $pluginsToUnload);
+
return $plugins;
}