Skip to content

Commit d0af6f7

Browse files
committed
Use PharData to extract database from archive
1 parent b3bc9c9 commit d0af6f7

File tree

1 file changed

+87
-15
lines changed

1 file changed

+87
-15
lines changed

src/Services/MaxMindDatabase.php

Lines changed: 87 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,98 @@ 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+
if (is_null($file)) {
80+
throw new Exception('Database file could not be found within archive.');
81+
}
82+
83+
$relativePath = "{$archive->getFilename()}/{$file->getFilename()}";
84+
85+
$archive->extractTo($directory, $relativePath);
86+
87+
file_put_contents($this->config('database_path'), fopen("{$directory}/{$relativePath}", 'r'));
88+
});
89+
90+
return "Database file ({$this->config('database_path')}) updated.";
91+
}
92+
93+
/**
94+
* Provide a temporary directory to perform operations in and and ensure
95+
* it is removed afterwards.
96+
*
97+
* @param callable $callback
98+
* @return void
99+
*/
100+
protected function withTemporaryDirectory(callable $callback)
101+
{
102+
$directory = tempnam(sys_get_temp_dir(), 'maxmind');
103+
104+
if (file_exists($directory)) {
105+
unlink($directory);
106+
}
107+
108+
mkdir($directory);
109+
110+
try {
111+
$callback($directory);
112+
} finally {
113+
$this->deleteDirectory($directory);
78114
}
115+
}
79116

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'));
117+
/**
118+
* Recursively search the given archive to find the .mmdb file.
119+
*
120+
* @param \PharData $archive
121+
* @return mixed
122+
*/
123+
protected function findDatabaseFile($archive)
124+
{
125+
foreach ($archive as $file) {
126+
if ($file->isDir()) {
127+
return $this->findDatabaseFile(new PharData($file->getPathName()));
128+
}
83129

84-
// Unzip and save database
85-
file_put_contents($path, gzopen($tmpFile, 'r'));
130+
if (pathinfo($file, PATHINFO_EXTENSION) === 'mmdb') {
131+
return $file;
132+
}
133+
}
134+
}
86135

87-
// Remove temp file
88-
@unlink($tmpFile);
136+
/**
137+
* Recursively delete the given directory.
138+
*
139+
* @param string $directory
140+
* @return mixed
141+
*/
142+
protected function deleteDirectory(string $directory)
143+
{
144+
if (!file_exists($directory)) {
145+
return true;
146+
}
147+
148+
if (!is_dir($directory)) {
149+
return unlink($directory);
150+
}
151+
152+
foreach (scandir($directory) as $item) {
153+
if ($item == '.' || $item == '..') {
154+
continue;
155+
}
156+
157+
if (!$this->deleteDirectory($directory . DIRECTORY_SEPARATOR . $item)) {
158+
return false;
159+
}
160+
}
89161

90-
return "Database file ({$path}) updated.";
162+
return rmdir($directory);
91163
}
92164
}

0 commit comments

Comments
 (0)