| <?php |
|
|
| namespace Piwik\Plugins\GeoIp2; |
|
|
| use Piwik\Common; |
| use Piwik\DataTable\Renderer\Json; |
| use Piwik\Http; |
| use Piwik\Option; |
| use Piwik\Piwik; |
| use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2; |
| use Piwik\Plugins\UserCountry\UserCountry; |
| use Piwik\View; |
|
|
| class Controller extends \Piwik\Plugin\ControllerAdmin |
| { |
| private const DOWNLOAD_URL_OPTION_PREFIX = 'geoip2.download_url.'; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function downloadFreeDBIPLiteDB() |
| { |
| $this->dieIfGeolocationAdminIsDisabled(); |
| Piwik::checkUserHasSuperUserAccess(); |
|
|
| if ($_SERVER["REQUEST_METHOD"] == "POST") { |
| $this->checkTokenInUrl(); |
| Json::sendHeaderJSON(); |
| $outputPath = GeoIP2AutoUpdater::getTemporaryFolder('DBIP-City.mmdb.gz', true); |
| try { |
| $result = Http::downloadChunk( |
| $url = GeoIp2::getDbIpLiteUrl(), |
| $outputPath, |
| $continue = Common::getRequestVar('continue', true, 'int') |
| ); |
|
|
| |
| if ($result['current_size'] >= $result['expected_file_size']) { |
| try { |
| GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, 'loc', $url, $unlink = true); |
| } catch (\Exception $e) { |
| |
| unlink($outputPath); |
| throw $e; |
| } |
|
|
| |
| GeoIP2AutoUpdater::setUpdaterOptions(array( |
| 'loc' => GeoIp2::getDbIpLiteUrl(), |
| 'period' => GeoIP2AutoUpdater::SCHEDULE_PERIOD_MONTHLY, |
| )); |
|
|
| $result['settings'] = GeoIP2AutoUpdater::getConfiguredUrls(); |
| } |
|
|
| return (string) json_encode($result); |
| } catch (\Exception $ex) { |
| return (string) json_encode(array('error' => $ex->getMessage())); |
| } |
| } |
|
|
| return ''; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function updateGeoIPLinks() |
| { |
| $this->dieIfGeolocationAdminIsDisabled(); |
| Piwik::checkUserHasSuperUserAccess(); |
| if ($_SERVER["REQUEST_METHOD"] == "POST") { |
| Json::sendHeaderJSON(); |
| try { |
| $this->checkTokenInUrl(); |
|
|
| GeoIP2AutoUpdater::setUpdaterOptionsFromUrl(); |
|
|
| |
| |
| $info = $this->getNextMissingDbUrlInfoGeoIp2(); |
|
|
| if ($info !== false) { |
| return (string) json_encode($info); |
| } else { |
| $view = new View("@GeoIp2/_updaterNextRunTime"); |
| $view->nextRunTime = GeoIP2AutoUpdater::getNextRunTime(); |
| $nextRunTimeHtml = $view->render(); |
| return (string) json_encode(array('nextRunTime' => $nextRunTimeHtml)); |
| } |
| } catch (\Exception $ex) { |
| return (string) json_encode(array('error' => $ex->getMessage())); |
| } |
| } |
|
|
| return ''; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function downloadMissingGeoIpDb() |
| { |
| $this->dieIfGeolocationAdminIsDisabled(); |
| Piwik::checkUserHasSuperUserAccess(); |
|
|
| if ($_SERVER["REQUEST_METHOD"] == "POST") { |
| try { |
| $this->checkTokenInUrl(); |
|
|
| Json::sendHeaderJSON(); |
|
|
| |
| |
| $key = Common::getRequestVar('key', null, 'string'); |
| $isContinuation = Common::getRequestVar('continue', true, 'int'); |
|
|
| $url = GeoIP2AutoUpdater::getConfiguredUrl($key); |
| if (!is_string($url) || $url === '') { |
| throw new \Exception(Piwik::translate('General_DownloadFail_HttpRequestFail')); |
| } |
| $this->trackOrValidateConfiguredDownloadUrl($key, $url, $isContinuation); |
|
|
| $filename = GeoIP2AutoUpdater::getZippedFilenameToDownloadTo($url, $key, GeoIP2AutoUpdater::getGeoIPUrlExtension($url)); |
| $outputPath = GeoIP2AutoUpdater::getTemporaryFolder($filename, true); |
|
|
| |
| $result = Http::downloadChunk( |
| $url, |
| $outputPath, |
| $isContinuation |
| ); |
|
|
| |
| if ($result['current_size'] >= $result['expected_file_size']) { |
| $this->assertConfiguredUrlDidNotChangeDuringDownload($key, $url); |
| GeoIP2AutoUpdater::unzipDownloadedFile($outputPath, $key, $url, $unlink = true); |
| $this->deleteTrackedDownloadUrl($key); |
|
|
| $info = $this->getNextMissingDbUrlInfoGeoIp2(); |
| if ($info !== false) { |
| return (string) json_encode($info); |
| } |
| } |
|
|
| return (string) json_encode($result); |
| } catch (\Exception $ex) { |
| return (string) json_encode(array('error' => $ex->getMessage())); |
| } |
| } |
|
|
| return ''; |
| } |
|
|
| private function trackOrValidateConfiguredDownloadUrl(string $key, string $configuredUrl, int $isContinuation): void |
| { |
| $optionName = $this->getDownloadUrlOptionName($key); |
| $expectedUrl = Option::get($optionName); |
|
|
| if (!$isContinuation || empty($expectedUrl)) { |
| Option::set($optionName, (string) $configuredUrl); |
| return; |
| } |
|
|
| if ((string) $expectedUrl !== (string) $configuredUrl) { |
| $this->abortDownloadForChangedConfiguredUrl($key, (string) $expectedUrl, $configuredUrl); |
| } |
| } |
|
|
| private function assertConfiguredUrlDidNotChangeDuringDownload(string $key, string $expectedUrl): void |
| { |
| $configuredUrl = GeoIP2AutoUpdater::getConfiguredUrl($key); |
|
|
| if ((string) $configuredUrl !== (string) $expectedUrl) { |
| $this->abortDownloadForChangedConfiguredUrl($key, $expectedUrl, (string) $configuredUrl); |
| } |
| } |
|
|
| private function abortDownloadForChangedConfiguredUrl(string $key, string $expectedUrl, string $configuredUrl): void |
| { |
| $this->deleteDownloadedChunksForType($key, $expectedUrl, $configuredUrl); |
| $this->deleteTrackedDownloadUrl($key); |
|
|
| throw new \Exception(Piwik::translate('General_DownloadFail_HttpRequestFail')); |
| } |
|
|
| private function deleteDownloadedChunksForType(string $key, string $expectedUrl, string $configuredUrl): void |
| { |
| $pathsToDelete = []; |
|
|
| $expectedOutputPath = $this->getDownloadOutputPath($key, $expectedUrl); |
| if (!empty($expectedOutputPath)) { |
| $pathsToDelete[] = $expectedOutputPath; |
| } |
|
|
| $configuredOutputPath = $this->getDownloadOutputPath($key, $configuredUrl); |
| if (!empty($configuredOutputPath)) { |
| $pathsToDelete[] = $configuredOutputPath; |
| } |
|
|
| foreach (array_unique($pathsToDelete) as $downloadPath) { |
| if (!is_file($downloadPath)) { |
| continue; |
| } |
|
|
| @unlink($downloadPath); |
| Option::delete($downloadPath . '_expectedDownloadSize'); |
| } |
| } |
|
|
| private function getDownloadOutputPath(string $key, string $url): ?string |
| { |
| try { |
| $filename = GeoIP2AutoUpdater::getZippedFilenameToDownloadTo( |
| $url, |
| $key, |
| GeoIP2AutoUpdater::getGeoIPUrlExtension($url) |
| ); |
|
|
| return GeoIP2AutoUpdater::getTemporaryFolder($filename, true); |
| } catch (\Exception $e) { |
| return null; |
| } |
| } |
|
|
| private function getDownloadUrlOptionName(string $key): string |
| { |
| return self::DOWNLOAD_URL_OPTION_PREFIX . $key; |
| } |
|
|
| private function deleteTrackedDownloadUrl(string $key): void |
| { |
| Option::delete($this->getDownloadUrlOptionName($key)); |
| } |
|
|
| |
| |
| |
| |
| |
| private function getNextMissingDbUrlInfoGeoIp2() |
| { |
| $missingDbs = GeoIP2AutoUpdater::getMissingDatabases(); |
| if (!empty($missingDbs)) { |
| $missingDbKey = $missingDbs[0]; |
| $url = GeoIP2AutoUpdater::getConfiguredUrl($missingDbKey); |
|
|
| $link = '<a href="' . $url . '">' . $url . '</a>'; |
|
|
| return [ |
| 'to_download' => $missingDbKey, |
| 'to_download_label' => Piwik::translate('GeoIp2_DownloadingDb', $link) . '...', |
| ]; |
| } |
| return false; |
| } |
|
|
| private function dieIfGeolocationAdminIsDisabled(): void |
| { |
| if (!UserCountry::isGeoLocationAdminEnabled()) { |
| throw new \Exception('Geo location setting page has been disabled.'); |
| } |
| } |
| } |
|
|