/**
* 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) {
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);
rename($existing = $tempFile, $newName = $oldDbFile);
// delete original archive
if ($unlink) {
unlink($path);
}
} catch (Exception $ex) {
// remove downloaded files
if (file_exists($outputPath)) {
unlink($outputPath);
}
unlink($path);
throw $ex;
}
}