Returns full path for a GeoIP database managed by Piwik.
public static getPathForGeoIpDatabase ( string $filename ) : string | ||
$filename | string | Name of the .dat file. |
return | string |
/** * 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; } }
/** * 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 = 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']) { 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())); } } }