Page MenuHomePhorge

D1642.1775214102.diff
No OneTemporary

Authored By
Unknown
Size
16 KB
Referenced Files
None
Subscribers
None

D1642.1775214102.diff

diff --git a/src/app/Console/Commands/DataIP4Nets.php b/src/app/Console/Commands/DataIP4Nets.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/DataIP4Nets.php
@@ -0,0 +1,230 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+
+class DataIP4Nets extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'data:ip4nets';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Update IP4 Networks';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $rirs = [
+ 'afrinic' => 'ftp://ftp.afrinic.net/stats/afrinic/delegated-afrinic-latest',
+ 'apnic' => 'ftp://ftp.apnic.net/pub/apnic/stats/apnic/delegated-apnic-latest',
+ 'arin' => 'ftp://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest',
+ 'lacnic' => 'ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest',
+ 'ripencc' => 'ftp://ftp.ripe.net/ripe/stats/delegated-ripencc-latest'
+ ];
+
+ $today = Carbon::now()->toDateString();
+
+ foreach ($rirs as $rir => $url) {
+ $file = storage_path("{$rir}-{$today}");
+
+ if (!is_file($file)) {
+ $fp = fopen(storage_path("{$rir}-{$today}"), 'w');
+
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FILE, $fp);
+ curl_exec($curl);
+ curl_close($curl);
+ fclose($fp);
+
+ if (curl_errno($curl)) {
+ \Log::error("Request error on {$url}: " . curl_error($curl));
+ unlink($file);
+ continue;
+ }
+ }
+
+ $serial = $this->serialFromStatsFile($file);
+
+ if (!$serial) {
+ \Log::error("Can not derive serial from {$file}");
+ continue;
+ }
+
+ $numLines = $this->countLines($file);
+
+ if (!$numLines) {
+ \Log::error("No relevant lines could be found in {$file}");
+ continue;
+ }
+
+ $bar = \App\Utils::createProgressBar(
+ $this->output,
+ $numLines,
+ "Importing IPv4 Networks from {$file}"
+ );
+
+ $fp = fopen($file, 'r');
+
+ $nets = [];
+
+ while (!feof($fp)) {
+ $line = trim(fgets($fp));
+
+ if ($line == "") {
+ continue;
+ }
+
+ if ((int)$line) {
+ continue;
+ }
+
+ if ($line[0] == "#") {
+ continue;
+ }
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 7) {
+ continue;
+ }
+
+ if ($items[1] == "*") {
+ continue;
+ }
+
+ if ($items[2] != "ipv4") {
+ continue;
+ }
+
+ if ($items[5] == "00000000") {
+ $items[5] = "19700102";
+ }
+
+ if ($items[1] == "" || $items[1] == "ZZ") {
+ continue;
+ }
+
+ $bar->advance();
+
+ $mask = 32 - log($items[4], 2);
+
+ $net = \App\IP4Net::where(
+ [
+ 'net_number' => $items[3],
+ 'net_mask' => $mask,
+ 'net_broadcast' => long2ip((ip2long($items[3]) + 2 ** (32 - $mask)) - 1)
+ ]
+ )->first();
+
+ if ($net) {
+ $net->update(
+ [
+ 'country' => $items[1],
+ 'serial' => $serial
+ ]
+ );
+
+ continue;
+ }
+
+ $nets[] = [
+ 'net_number' => $items[3],
+ 'net_mask' => $mask,
+ 'net_broadcast' => long2ip((ip2long($items[3]) + 2 ** (32 - $mask)) - 1),
+ 'country' => $items[1],
+ 'serial' => $serial
+ ];
+
+ if (sizeof($nets) >= 100) {
+ \App\IP4Net::insert($nets);
+ $nets = [];
+ }
+ }
+
+ if (sizeof($nets) > 0) {
+ \App\IP4Net::insert($nets);
+ }
+
+ $bar->finish();
+
+ $this->info("DONE");
+ }
+ }
+
+ private function countLines($file)
+ {
+ $numLines = 0;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 3) {
+ continue;
+ }
+
+ if ($items[2] == "ipv4") {
+ $numLines++;
+ }
+ }
+
+ fclose($fh);
+
+ return $numLines;
+ }
+
+ private function serialFromStatsFile($file)
+ {
+ $serial = null;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 2) {
+ continue;
+ }
+
+ if ((int)$items[2]) {
+ $serial = (int)$items[2];
+ break;
+ }
+ }
+
+ fclose($fh);
+
+ return $serial;
+ }
+}
diff --git a/src/app/IP4Net.php b/src/app/IP4Net.php
new file mode 100644
--- /dev/null
+++ b/src/app/IP4Net.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\DB;
+
+class IP4Net extends Model
+{
+ protected $table = "ip4nets";
+
+ protected $fillable = [
+ 'net_number',
+ 'net_mask',
+ 'net_broadcast',
+ 'country',
+ 'serial'
+ ];
+}
diff --git a/src/app/Observers/UserObserver.php b/src/app/Observers/UserObserver.php
--- a/src/app/Observers/UserObserver.php
+++ b/src/app/Observers/UserObserver.php
@@ -50,7 +50,7 @@
public function created(User $user)
{
$settings = [
- 'country' => 'CH',
+ 'country' => \App\Utils::countryForRequest(),
'currency' => 'CHF',
/*
'first_name' => '',
diff --git a/src/app/Utils.php b/src/app/Utils.php
--- a/src/app/Utils.php
+++ b/src/app/Utils.php
@@ -11,6 +11,94 @@
*/
class Utils
{
+ /**
+ * Count the number of lines in a file.
+ *
+ * Useful for progress bars.
+ *
+ * @param string $file The filepath to count the lines of.
+ *
+ * @return int
+ */
+ public static function countLines($file)
+ {
+ $fh = fopen($file, 'rb');
+ $numLines = 0;
+
+ while (!feof($fh)) {
+ $numLines += substr_count(fread($fh, 8192), "\n");
+ }
+
+ fclose($fh);
+
+ return $numLines;
+ }
+
+ /**
+ * Return the country ISO code for an IP address.
+ *
+ * @return string
+ */
+ public static function countryForIP($ip)
+ {
+ $query = "
+ SELECT country FROM ip4nets
+ WHERE INET_ATON(net_number) <= INET_ATON(?)
+ AND INET_ATON(net_broadcast) >= INET_ATON(?)
+ ORDER BY INET_ATON(net_number), net_mask DESC LIMIT 1
+ ";
+
+ $nets = \Illuminate\Support\Facades\DB::select($query, [$ip, $ip]);
+
+ if ($nets->count() > 0) {
+ return $nets[0]->country;
+ }
+
+ return 'CH';
+ }
+
+ /**
+ * Return the country ISO code for the current request.
+ */
+ public static function countryForRequest()
+ {
+ $request = \request();
+
+ if (!$request) {
+ return 'CH';
+ }
+
+ $ip = $request->ip();
+
+ return self::countryForIP($ip);
+ }
+
+ /**
+ * Shortcut to creating a progress bar of a particular format with a particular message.
+ *
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @param int $count
+ * @param string $message
+ *
+ * @return \Symfony\Component\Console\Helper\ProgressBar
+ */
+ public static function createProgressBar($output, $count, $message = null)
+ {
+ $bar = $output->createProgressBar($count);
+
+ $bar->setFormat(
+ '%current:7s%/%max:7s% [%bar%] %percent:3s%% %elapsed:7s%/%estimated:-7s% %message% '
+ );
+
+ if ($message) {
+ $bar->setMessage($message . " ...");
+ }
+
+ $bar->start();
+
+ return $bar;
+ }
+
/**
* Return the number of days in the month prior to this one.
*
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -18,7 +18,6 @@
"barryvdh/laravel-dompdf": "^0.8.6",
"doctrine/dbal": "^2.9",
"fideloper/proxy": "^4.0",
- "geoip2/geoip2": "^2.9",
"iatstuti/laravel-nullable-fields": "*",
"kolab/net_ldap3": "dev-master",
"laravel/framework": "6.*",
@@ -31,7 +30,6 @@
"stripe/stripe-php": "^7.29",
"swooletw/laravel-swoole": "^2.6",
"torann/currency": "^1.0",
- "torann/geoip": "^1.0",
"tymon/jwt-auth": "^1.0"
},
"require-dev": {
diff --git a/src/config/geoip.php b/src/config/geoip.php
deleted file mode 100644
--- a/src/config/geoip.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-return [
-
- /*
- |--------------------------------------------------------------------------
- | Logging Configuration
- |--------------------------------------------------------------------------
- |
- | Here you may configure the log settings for when a location is not found
- | for the IP provided.
- |
- */
-
- 'log_failures' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Include Currency in Results
- |--------------------------------------------------------------------------
- |
- | When enabled the system will do it's best in deciding the user's currency
- | by matching their ISO code to a preset list of currencies.
- |
- */
-
- 'include_currency' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Default Service
- |--------------------------------------------------------------------------
- |
- | Here you may specify the default storage driver that should be used
- | by the framework.
- |
- | Supported: "maxmind_database", "maxmind_api", "ipapi"
- |
- */
-
- 'service' => 'maxmind_database',
-
- /*
- |--------------------------------------------------------------------------
- | Storage Specific Configuration
- |--------------------------------------------------------------------------
- |
- | Here you may configure as many storage drivers as you wish.
- |
- */
-
- 'services' => [
-
- 'maxmind_database' => [
- 'class' => \Torann\GeoIP\Services\MaxMindDatabase::class,
- 'database_path' => storage_path('app/geoip.mmdb'),
- 'update_url' => 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz',
- 'locales' => ['en'],
- ],
-
- 'maxmind_api' => [
- 'class' => \Torann\GeoIP\Services\MaxMindWebService::class,
- 'user_id' => env('MAXMIND_USER_ID'),
- 'license_key' => env('MAXMIND_LICENSE_KEY'),
- 'locales' => ['en'],
- ],
-
- 'ipapi' => [
- 'class' => \Torann\GeoIP\Services\IPApi::class,
- 'secure' => true,
- 'key' => env('IPAPI_KEY'),
- 'continent_path' => storage_path('app/continents.json'),
- 'lang' => 'en',
- ],
-
- 'ipgeolocation' => [
- 'class' => \Torann\GeoIP\Services\IPGeoLocation::class,
- 'secure' => true,
- 'key' => env('IPGEOLOCATION_KEY'),
- 'continent_path' => storage_path('app/continents.json'),
- 'lang' => 'en',
- ],
-
- 'ipdata' => [
- 'class' => \Torann\GeoIP\Services\IPData::class,
- 'key' => env('IPDATA_API_KEY'),
- 'secure' => true,
- ],
-
- 'ipfinder' => [
- 'class' => \Torann\GeoIP\Services\IPFinder::class,
- 'key' => env('IPFINDER_API_KEY'),
- 'secure' => true,
- 'locales' => ['en'],
- ],
-
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Default Cache Driver
- |--------------------------------------------------------------------------
- |
- | Here you may specify the type of caching that should be used
- | by the package.
- |
- | Options:
- |
- | all - All location are cached
- | some - Cache only the requesting user
- | none - Disable cached
- |
- */
-
- 'cache' => 'all',
-
- /*
- |--------------------------------------------------------------------------
- | Cache Tags
- |--------------------------------------------------------------------------
- |
- | Cache tags are not supported when using the file or database cache
- | drivers in Laravel. This is done so that only locations can be cleared.
- |
- */
-
- 'cache_tags' => false,
-
- /*
- |--------------------------------------------------------------------------
- | Cache Expiration
- |--------------------------------------------------------------------------
- |
- | Define how long cached location are valid.
- |
- */
-
- 'cache_expires' => 30,
-
- /*
- |--------------------------------------------------------------------------
- | Default Location
- |--------------------------------------------------------------------------
- |
- | Return when a location is not found.
- |
- */
-
- 'default_location' => [
- 'ip' => '127.0.0.0',
- 'iso_code' => 'CH',
- 'country' => 'Switzerland',
- 'city' => 'Zurich',
- 'state' => 'ZH',
- 'state_name' => 'Zurich',
- 'postal_code' => '8703',
- 'lat' => 47.30,
- 'lon' => 8.59,
- 'timezone' => 'Europe/Zurich',
- 'continent' => 'EU',
- 'default' => true,
- 'currency' => 'CHF',
- ],
-
-];
diff --git a/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php b/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php
new file mode 100644
--- /dev/null
+++ b/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php
@@ -0,0 +1,42 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+// phpcs:ignore
+class CreateIp4netsTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create(
+ 'ip4nets',
+ function (Blueprint $table) {
+ $table->bigIncrements('id');
+ $table->string('net_number', 15)->index();
+ $table->tinyInteger('net_mask')->unsigned();
+ $table->string('net_broadcast', 15)->index();
+ $table->string('country', 2)->nullable();
+ $table->bigInteger('serial')->unsigned();
+ $table->timestamps();
+
+ $table->index(['net_number', 'net_mask', 'net_broadcast']);
+ }
+ );
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('ip4nets');
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 11:01 AM (5 d, 2 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18823741
Default Alt Text
D1642.1775214102.diff (16 KB)

Event Timeline