Skip to content

Commit b9af2e5

Browse files
authored
Merge pull request #164 from dwightwatson/maxmind-database
Fix MaxMind database fetching
2 parents 9577c9d + af106a6 commit b9af2e5

File tree

3 files changed

+89
-30
lines changed

3 files changed

+89
-30
lines changed

config/geoip.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
'maxmind_database' => [
5555
'class' => \Torann\GeoIP\Services\MaxMindDatabase::class,
5656
'database_path' => storage_path('app/geoip.mmdb'),
57-
'update_url' => 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz',
57+
'update_url' => sprintf('https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%s&suffix=tar.gz', env('MAXMIND_LICENSE_KEY')),
5858
'locales' => ['en'],
5959
],
6060

@@ -72,7 +72,7 @@
7272
'continent_path' => storage_path('app/continents.json'),
7373
'lang' => 'en',
7474
],
75-
75+
7676
'ipgeolocation' => [
7777
'class' => \Torann\GeoIP\Services\IPGeoLocation::class,
7878
'secure' => true,

src/Services/MaxMindDatabase.php

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Torann\GeoIP\Services;
44

5+
use PharData;
56
use Exception;
67
use GeoIp2\Database\Reader;
78

@@ -66,27 +67,97 @@ public function update()
6667
throw new Exception('Database path not set in config file.');
6768
}
6869

69-
// Get settings
70-
$url = $this->config('update_url');
71-
$path = $this->config('database_path');
70+
$this->withTemporaryDirectory(function ($directory) {
71+
$tarFile = sprintf('%s/maxmind.tar.gz', $directory);
7272

73-
// Get header response
74-
$headers = get_headers($url);
73+
file_put_contents($tarFile, fopen($this->config('update_url'), 'r'));
7574

76-
if (substr($headers[0], 9, 3) != '200') {
77-
throw new Exception('Unable to download database. (' . substr($headers[0], 13) . ')');
75+
$archive = new PharData($tarFile);
76+
77+
$file = $this->findDatabaseFile($archive);
78+
79+
$relativePath = "{$archive->getFilename()}/{$file->getFilename()}";
80+
81+
$archive->extractTo($directory, $relativePath);
82+
83+
file_put_contents($this->config('database_path'), fopen("{$directory}/{$relativePath}", 'r'));
84+
});
85+
86+
return "Database file ({$this->config('database_path')}) updated.";
87+
}
88+
89+
/**
90+
* Provide a temporary directory to perform operations in and and ensure
91+
* it is removed afterwards.
92+
*
93+
* @param callable $callback
94+
* @return void
95+
*/
96+
protected function withTemporaryDirectory(callable $callback)
97+
{
98+
$directory = tempnam(sys_get_temp_dir(), 'maxmind');
99+
100+
if (file_exists($directory)) {
101+
unlink($directory);
102+
}
103+
104+
mkdir($directory);
105+
106+
try {
107+
$callback($directory);
108+
} finally {
109+
$this->deleteDirectory($directory);
110+
}
111+
}
112+
113+
/**
114+
* Recursively search the given archive to find the .mmdb file.
115+
*
116+
* @param \PharData $archive
117+
* @return mixed
118+
* @throws \Exception
119+
*/
120+
protected function findDatabaseFile($archive)
121+
{
122+
foreach ($archive as $file) {
123+
if ($file->isDir()) {
124+
return $this->findDatabaseFile(new PharData($file->getPathName()));
125+
}
126+
127+
if (pathinfo($file, PATHINFO_EXTENSION) === 'mmdb') {
128+
return $file;
129+
}
78130
}
79131

80-
// Download zipped database to a system temp file
81-
$tmpFile = tempnam(sys_get_temp_dir(), 'maxmind');
82-
file_put_contents($tmpFile, fopen($url, 'r'));
132+
throw new Exception('Database file could not be found within archive.');
133+
}
83134

84-
// Unzip and save database
85-
file_put_contents($path, gzopen($tmpFile, 'r'));
135+
/**
136+
* Recursively delete the given directory.
137+
*
138+
* @param string $directory
139+
* @return mixed
140+
*/
141+
protected function deleteDirectory(string $directory)
142+
{
143+
if (!file_exists($directory)) {
144+
return true;
145+
}
86146

87-
// Remove temp file
88-
@unlink($tmpFile);
147+
if (!is_dir($directory)) {
148+
return unlink($directory);
149+
}
150+
151+
foreach (scandir($directory) as $item) {
152+
if ($item == '.' || $item == '..') {
153+
continue;
154+
}
155+
156+
if (!$this->deleteDirectory($directory . DIRECTORY_SEPARATOR . $item)) {
157+
return false;
158+
}
159+
}
89160

90-
return "Database file ({$path}) updated.";
161+
return rmdir($directory);
91162
}
92163
}

tests/Services/MaxMindDatabaseTest.php

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,6 @@ public function shouldReturnInvalidLocation()
4646
}
4747
}
4848

49-
/**
50-
* @test
51-
*/
52-
public function shouldUpdateLocalDatabase()
53-
{
54-
list($service, $config) = $this->getService();
55-
56-
$this->assertEquals($service->update(), "Database file ({$config['database_path']}) updated.");
57-
58-
@unlink($config['database_path']);
59-
}
60-
6149
protected function getService()
6250
{
6351
$config = $this->getConfig()['services']['maxmind_database'];
@@ -66,4 +54,4 @@ protected function getService()
6654

6755
return [$service, $config];
6856
}
69-
}
57+
}

0 commit comments

Comments
 (0)