domain-watchdog/src/Service/RDAPService.php

645 lines
22 KiB
PHP
Raw Normal View History

2024-07-13 23:57:07 +02:00
<?php
namespace App\Service;
use App\Config\EventAction;
2024-07-24 18:52:19 +02:00
use App\Config\TldType;
2024-07-13 23:57:07 +02:00
use App\Entity\Domain;
use App\Entity\DomainEntity;
use App\Entity\DomainEvent;
use App\Entity\Entity;
use App\Entity\EntityEvent;
use App\Entity\Nameserver;
use App\Entity\NameserverEntity;
2024-07-18 19:13:06 +02:00
use App\Entity\RdapServer;
2024-07-19 18:59:21 +02:00
use App\Entity\Tld;
2024-07-13 23:57:07 +02:00
use App\Repository\DomainEntityRepository;
use App\Repository\DomainEventRepository;
use App\Repository\DomainRepository;
use App\Repository\EntityEventRepository;
use App\Repository\EntityRepository;
use App\Repository\NameserverEntityRepository;
use App\Repository\NameserverRepository;
2024-07-18 19:13:06 +02:00
use App\Repository\RdapServerRepository;
2024-07-19 18:59:21 +02:00
use App\Repository\TldRepository;
2024-07-13 23:57:07 +02:00
use Doctrine\ORM\EntityManagerInterface;
2024-07-19 18:59:21 +02:00
use Doctrine\ORM\Exception\ORMException;
2024-08-04 04:39:05 +02:00
use Psr\Log\LoggerInterface;
2024-08-07 16:21:41 +02:00
use Symfony\Component\HttpClient\Exception\ClientException;
2024-08-06 21:43:37 +02:00
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2024-08-19 18:06:11 +02:00
use Symfony\Component\Yaml\Yaml;
2024-07-19 01:17:33 +02:00
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
2024-07-25 16:19:57 +02:00
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
2024-07-19 01:17:33 +02:00
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
2024-07-13 23:57:07 +02:00
use Symfony\Contracts\HttpClient\HttpClientInterface;
2024-07-14 21:15:13 +02:00
readonly class RDAPService
2024-07-13 23:57:07 +02:00
{
2024-07-25 00:58:19 +02:00
/**
* @see https://www.iana.org/domains/root/db
*/
2024-08-02 23:24:52 +02:00
public const ISO_TLD_EXCEPTION = ['ac', 'eu', 'uk', 'su', 'tp'];
public const INFRA_TLD = ['arpa'];
public const SPONSORED_TLD = [
2024-07-25 00:58:19 +02:00
'aero',
'asia',
'cat',
'coop',
'edu',
'gov',
'int',
'jobs',
'mil',
'museum',
'post',
'tel',
'travel',
'xxx',
];
2024-08-02 23:24:52 +02:00
public const TEST_TLD = [
2024-07-24 18:52:19 +02:00
'xn--kgbechtv',
'xn--hgbk6aj7f53bba',
'xn--0zwm56d',
'xn--g6w251d',
'xn--80akhbyknj4f',
'xn--11b5bs3a9aj6g',
'xn--jxalpdlp',
'xn--9t4b11yi5a',
'xn--deba0ad',
'xn--zckzah',
2024-08-02 23:24:52 +02:00
'xn--hlcj6aya9esc7a',
2024-07-24 18:52:19 +02:00
];
2024-07-13 23:57:07 +02:00
private const IMPORTANT_EVENTS = [EventAction::Deletion->value, EventAction::Expiration->value];
private const IMPORTANT_STATUS = [
'redemption period',
'pending delete',
'pending create',
'pending renew',
'pending restore',
'pending transfer',
'pending update',
'add period',
];
2024-08-02 23:24:52 +02:00
public function __construct(private HttpClientInterface $client,
private EntityRepository $entityRepository,
private DomainRepository $domainRepository,
private DomainEventRepository $domainEventRepository,
private NameserverRepository $nameserverRepository,
private NameserverEntityRepository $nameserverEntityRepository,
private EntityEventRepository $entityEventRepository,
private DomainEntityRepository $domainEntityRepository,
private RdapServerRepository $rdapServerRepository,
private TldRepository $tldRepository,
2024-08-04 04:39:05 +02:00
private EntityManagerInterface $em,
2024-08-22 18:11:07 +02:00
private LoggerInterface $logger,
2024-08-25 03:31:09 +02:00
private StatService $statService
2024-08-02 23:24:52 +02:00
) {
2024-07-13 23:57:07 +02:00
}
2024-07-25 20:21:57 +02:00
/**
* Determines if a domain name needs special attention.
* These domain names are those whose last event was expiration or deletion.
2024-08-02 23:24:52 +02:00
*
* @throws \Exception
2024-07-25 20:21:57 +02:00
*/
public static function isToBeWatchClosely(Domain $domain): bool
2024-07-25 20:21:57 +02:00
{
$status = $domain->getStatus();
if ((!empty($status) && count(array_intersect($status, self::IMPORTANT_STATUS))) || $domain->getDeleted()) {
return true;
}
2024-07-25 20:21:57 +02:00
/** @var DomainEvent[] $events */
$events = $domain->getEvents()
2024-08-02 23:24:52 +02:00
->filter(fn (DomainEvent $e) => $e->getDate() <= new \DateTimeImmutable('now'))
2024-07-25 20:21:57 +02:00
->toArray();
2024-08-03 00:06:38 +02:00
usort($events, fn (DomainEvent $e1, DomainEvent $e2) => $e2->getDate() <=> $e1->getDate());
2024-07-25 20:21:57 +02:00
return !empty($events) && in_array($events[0]->getAction(), self::IMPORTANT_EVENTS);
}
2024-07-14 11:20:04 +02:00
/**
2024-07-25 16:19:57 +02:00
* @throws HttpExceptionInterface
* @throws TransportExceptionInterface
* @throws DecodingExceptionInterface
2024-08-07 16:29:37 +02:00
* @throws \Throwable
2024-07-14 11:20:04 +02:00
*/
public function registerDomains(array $domains): void
{
foreach ($domains as $fqdn) {
2024-07-18 19:13:06 +02:00
$this->registerDomain($fqdn);
}
}
/**
2024-07-25 16:19:57 +02:00
* @throws TransportExceptionInterface
2024-08-07 16:21:41 +02:00
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
2024-07-25 16:19:57 +02:00
* @throws DecodingExceptionInterface
2024-08-07 16:21:41 +02:00
* @throws ClientExceptionInterface
2024-08-07 16:29:37 +02:00
* @throws \Throwable
*/
public function registerDomain(string $fqdn): Domain
2024-07-13 23:57:07 +02:00
{
2024-07-26 21:10:06 +02:00
$idnDomain = strtolower(idn_to_ascii($fqdn));
2024-08-04 04:39:05 +02:00
2024-07-19 18:59:21 +02:00
$tld = $this->getTld($idnDomain);
2024-07-18 19:13:06 +02:00
2024-08-04 04:39:05 +02:00
$this->logger->info('An update request for domain name {idnDomain} is requested.', [
'idnDomain' => $idnDomain,
]);
2024-07-18 19:13:06 +02:00
/** @var RdapServer|null $rdapServer */
2024-08-02 23:24:52 +02:00
$rdapServer = $this->rdapServerRepository->findOneBy(['tld' => $tld], ['updatedAt' => 'DESC']);
2024-07-18 19:13:06 +02:00
2024-08-02 23:24:52 +02:00
if (null === $rdapServer) {
2024-08-06 21:43:37 +02:00
throw new NotFoundHttpException('Unable to determine which RDAP server to contact');
2024-08-02 23:24:52 +02:00
}
2024-07-13 23:57:07 +02:00
2024-07-25 16:19:57 +02:00
/** @var ?Domain $domain */
2024-08-02 23:24:52 +02:00
$domain = $this->domainRepository->findOneBy(['ldhName' => $idnDomain]);
2024-07-25 16:19:57 +02:00
2024-08-04 04:39:05 +02:00
$rdapServerUrl = $rdapServer->getUrl();
$this->logger->notice('An RDAP query to update the domain name {idnDomain} will be made to {server}.', [
'idnDomain' => $idnDomain,
'server' => $rdapServerUrl,
]);
2024-07-14 11:20:04 +02:00
try {
2024-08-25 03:31:09 +02:00
$this->statService->incrementStat('stats.rdap_queries.count');
2024-08-22 18:11:07 +02:00
2024-07-14 11:20:04 +02:00
$res = $this->client->request(
2024-08-04 04:39:05 +02:00
'GET', $rdapServerUrl.'domain/'.$idnDomain
2024-07-14 11:20:04 +02:00
)->toArray();
2024-08-07 16:29:37 +02:00
} catch (\Throwable $e) {
if ($e instanceof ClientException && 404 === $e->getResponse()->getStatusCode()) {
2024-08-10 23:06:03 +02:00
if (null !== $domain) {
$this->logger->notice('The domain name {idnDomain} has been deleted from the WHOIS database.', [
'idnDomain' => $idnDomain,
]);
$domain->setDeleted(true)
->updateTimestamps();
$this->em->persist($domain);
$this->em->flush();
}
2024-08-07 16:29:37 +02:00
throw new NotFoundHttpException('The domain name is not present in the WHOIS database.');
}
2024-07-25 16:19:57 +02:00
throw $e;
2024-07-14 11:20:04 +02:00
}
2024-07-13 23:57:07 +02:00
2024-08-02 23:24:52 +02:00
if (null === $domain) {
$domain = new Domain();
2024-08-04 04:39:05 +02:00
$this->logger->info('The domain name {idnDomain} was not known to this Domain Watchdog instance.', [
'idnDomain' => $idnDomain,
]);
2024-08-02 23:24:52 +02:00
}
2024-08-04 04:39:05 +02:00
2024-07-26 21:10:06 +02:00
$domain->setTld($tld)->setLdhName($idnDomain)->setDeleted(false);
2024-07-13 23:57:07 +02:00
2024-08-02 23:24:52 +02:00
if (array_key_exists('status', $res)) {
$domain->setStatus($res['status']);
2024-08-04 14:45:27 +02:00
} else {
$this->logger->warning('The domain name {idnDomain} has no WHOIS status.', [
'idnDomain' => $idnDomain,
]);
2024-08-02 23:24:52 +02:00
}
2024-08-04 14:45:27 +02:00
2024-08-02 23:24:52 +02:00
if (array_key_exists('handle', $res)) {
$domain->setHandle($res['handle']);
2024-08-04 14:45:27 +02:00
} else {
$this->logger->warning('The domain name {idnDomain} has no handle key.', [
'idnDomain' => $idnDomain,
]);
2024-08-02 23:24:52 +02:00
}
$this->em->persist($domain);
$this->em->flush();
2024-07-13 23:57:07 +02:00
2024-09-01 21:26:07 +02:00
/** @var DomainEvent $event */
foreach ($domain->getEvents()->getIterator() as $event) {
$event->setDeleted(true);
}
if(!empty($res["events"])) {
foreach ($res['events'] as $rdapEvent) {
if ($rdapEvent['eventAction'] === EventAction::LastUpdateOfRDAPDatabase->value) {
continue;
}
$event = $this->domainEventRepository->findOneBy([
'action' => $rdapEvent['eventAction'],
'date' => new \DateTimeImmutable($rdapEvent['eventDate']),
'domain' => $domain,
]);
if (null === $event) {
$event = new DomainEvent();
}
$domain->addEvent($event
->setAction($rdapEvent['eventAction'])
->setDate(new \DateTimeImmutable($rdapEvent['eventDate']))
->setDeleted(false)
);
2024-08-02 23:24:52 +02:00
}
2024-07-13 23:57:07 +02:00
}
/** @var DomainEntity $domainEntity */
foreach ($domain->getDomainEntities()->getIterator() as $domainEntity) {
$domainEntity->setDeleted(true);
}
2024-07-23 03:13:51 +02:00
if (array_key_exists('entities', $res) && is_array($res['entities'])) {
foreach ($res['entities'] as $rdapEntity) {
2024-08-02 23:24:52 +02:00
if (!array_key_exists('handle', $rdapEntity) || '' === $rdapEntity['handle']) {
continue;
}
2024-07-23 03:13:51 +02:00
2024-07-14 00:06:58 +02:00
$entity = $this->registerEntity($rdapEntity);
2024-07-13 23:57:07 +02:00
$this->em->persist($entity);
$this->em->flush();
2024-07-23 03:13:51 +02:00
$domainEntity = $this->domainEntityRepository->findOneBy([
2024-08-02 23:24:52 +02:00
'domain' => $domain,
'entity' => $entity,
2024-07-13 23:57:07 +02:00
]);
2024-07-23 03:13:51 +02:00
2024-08-02 23:24:52 +02:00
if (null === $domainEntity) {
$domainEntity = new DomainEntity();
}
2024-07-23 03:13:51 +02:00
$roles = array_map(
2024-08-02 23:24:52 +02:00
fn ($e) => $e['roles'],
2024-07-23 03:13:51 +02:00
array_filter(
$res['entities'],
2024-08-02 23:24:52 +02:00
fn ($e) => array_key_exists('handle', $e) && $e['handle'] === $rdapEntity['handle']
)
);
2024-08-04 14:45:27 +02:00
/*
* Flatten the array
*/
2024-08-02 23:24:52 +02:00
if (count($roles) !== count($roles, COUNT_RECURSIVE)) {
$roles = array_merge(...$roles);
}
2024-07-13 23:57:07 +02:00
2024-07-23 03:13:51 +02:00
$domain->addDomainEntity($domainEntity
->setDomain($domain)
2024-07-13 23:57:07 +02:00
->setEntity($entity)
->setRoles($roles)
->setDeleted(false)
);
2024-07-23 03:13:51 +02:00
$this->em->persist($domainEntity);
$this->em->flush();
2024-07-13 23:57:07 +02:00
}
2024-07-23 03:13:51 +02:00
}
2024-07-13 23:57:07 +02:00
2024-07-23 03:13:51 +02:00
if (array_key_exists('nameservers', $res) && is_array($res['nameservers'])) {
2024-08-17 18:22:24 +02:00
$domain->getNameservers()->clear();
2024-07-23 03:13:51 +02:00
foreach ($res['nameservers'] as $rdapNameserver) {
$nameserver = $this->nameserverRepository->findOneBy([
2024-08-02 23:24:52 +02:00
'ldhName' => strtolower($rdapNameserver['ldhName']),
2024-07-23 03:13:51 +02:00
]);
$domainNS = $domain->getNameservers()->findFirst(fn (int $key, Nameserver $ns) => $ns->getLdhName() === $rdapNameserver['ldhName']);
if (null !== $domainNS) {
$nameserver = $domainNS;
}
2024-08-02 23:24:52 +02:00
if (null === $nameserver) {
$nameserver = new Nameserver();
}
2024-07-23 03:13:51 +02:00
$nameserver->setLdhName($rdapNameserver['ldhName']);
if (!array_key_exists('entities', $rdapNameserver) || !is_array($rdapNameserver['entities'])) {
$domain->addNameserver($nameserver);
continue;
}
foreach ($rdapNameserver['entities'] as $rdapEntity) {
2024-08-02 23:24:52 +02:00
if (!array_key_exists('handle', $rdapEntity) || '' === $rdapEntity['handle']) {
continue;
}
2024-07-23 03:13:51 +02:00
$entity = $this->registerEntity($rdapEntity);
$this->em->persist($entity);
$this->em->flush();
$nameserverEntity = $this->nameserverEntityRepository->findOneBy([
2024-08-02 23:24:52 +02:00
'nameserver' => $nameserver,
'entity' => $entity,
2024-07-23 03:13:51 +02:00
]);
2024-08-02 23:24:52 +02:00
if (null === $nameserverEntity) {
$nameserverEntity = new NameserverEntity();
}
2024-07-23 03:13:51 +02:00
$roles = array_merge(
...array_map(
2024-08-02 23:24:52 +02:00
fn (array $e): array => $e['roles'],
2024-07-23 03:13:51 +02:00
array_filter(
$rdapNameserver['entities'],
2024-08-02 23:24:52 +02:00
fn ($e) => array_key_exists('handle', $e) && $e['handle'] === $rdapEntity['handle']
2024-07-23 03:13:51 +02:00
)
)
);
$nameserver->addNameserverEntity($nameserverEntity
->setNameserver($nameserver)
->setEntity($entity)
->setStatus($rdapNameserver['status'])
->setRoles($roles));
}
$domain->addNameserver($nameserver);
}
2024-08-04 14:45:27 +02:00
} else {
$this->logger->warning('The domain name {idnDomain} has no nameservers.', [
'idnDomain' => $idnDomain,
]);
2024-07-13 23:57:07 +02:00
}
$domain->updateTimestamps();
2024-07-13 23:57:07 +02:00
$this->em->persist($domain);
$this->em->flush();
return $domain;
2024-07-13 23:57:07 +02:00
}
2024-07-19 18:59:21 +02:00
private function getTld($domain): ?object
2024-07-13 23:57:07 +02:00
{
$lastDotPosition = strrpos($domain, '.');
2024-08-02 23:24:52 +02:00
if (false === $lastDotPosition) {
2024-08-06 21:43:37 +02:00
throw new BadRequestException('Domain must contain at least one dot');
2024-07-13 23:57:07 +02:00
}
2024-08-28 23:21:19 +02:00
$tld = strtolower(idn_to_ascii(substr($domain, $lastDotPosition + 1)));
2024-07-19 18:59:21 +02:00
2024-08-02 23:24:52 +02:00
return $this->tldRepository->findOneBy(['tld' => $tld]);
2024-07-13 23:57:07 +02:00
}
2024-07-14 11:20:04 +02:00
/**
2024-08-02 23:24:52 +02:00
* @throws \Exception
2024-07-14 11:20:04 +02:00
*/
2024-07-14 00:06:58 +02:00
private function registerEntity(array $rdapEntity): Entity
2024-07-13 23:57:07 +02:00
{
$entity = $this->entityRepository->findOneBy([
2024-08-02 23:24:52 +02:00
'handle' => $rdapEntity['handle'],
2024-07-13 23:57:07 +02:00
]);
2024-08-02 23:24:52 +02:00
if (null === $entity) {
$entity = new Entity();
2024-08-15 19:54:36 +02:00
2024-08-04 14:45:27 +02:00
$this->logger->info('The entity {handle} was not known to this Domain Watchdog instance.', [
'handle' => $rdapEntity['handle'],
]);
2024-08-02 23:24:52 +02:00
}
2024-07-13 23:57:07 +02:00
$entity->setHandle($rdapEntity['handle']);
2024-07-23 03:05:35 +02:00
if (array_key_exists('vcardArray', $rdapEntity)) {
if (empty($entity->getJCard())) {
$entity->setJCard($rdapEntity['vcardArray']);
} else {
$properties = [];
foreach ($rdapEntity['vcardArray'][1] as $prop) {
$properties[$prop[0]] = $prop;
}
foreach ($entity->getJCard()[1] as $prop) {
$properties[$prop[0]] = $prop;
}
2024-08-02 23:24:52 +02:00
$entity->setJCard(['vcard', array_values($properties)]);
2024-07-13 23:57:07 +02:00
}
}
2024-08-02 23:24:52 +02:00
if (!array_key_exists('events', $rdapEntity)) {
return $entity;
}
2024-07-13 23:57:07 +02:00
2024-09-01 21:26:07 +02:00
/** @var EntityEvent $event */
foreach ($entity->getEvents()->getIterator() as $event) {
$event->setDeleted(true);
}
$this->em->persist($entity);
$this->em->flush();
2024-07-13 23:57:07 +02:00
foreach ($rdapEntity['events'] as $rdapEntityEvent) {
2024-08-02 23:24:52 +02:00
$eventAction = $rdapEntityEvent['eventAction'];
if ($eventAction === EventAction::LastChanged->value || $eventAction === EventAction::LastUpdateOfRDAPDatabase->value) {
continue;
}
2024-07-13 23:57:07 +02:00
$event = $this->entityEventRepository->findOneBy([
2024-08-02 23:24:52 +02:00
'action' => $rdapEntityEvent['eventAction'],
'date' => new \DateTimeImmutable($rdapEntityEvent['eventDate']),
2024-07-13 23:57:07 +02:00
]);
2024-08-02 23:24:52 +02:00
if (null !== $event) {
2024-09-01 21:26:07 +02:00
$event->setDeleted(false);
2024-08-02 23:24:52 +02:00
continue;
}
2024-07-13 23:57:07 +02:00
$entity->addEvent(
(new EntityEvent())
->setEntity($entity)
2024-08-02 23:24:52 +02:00
->setAction($rdapEntityEvent['eventAction'])
2024-09-01 21:26:07 +02:00
->setDate(new \DateTimeImmutable($rdapEntityEvent['eventDate']))
->setDeleted(false));
2024-07-13 23:57:07 +02:00
}
2024-08-02 23:24:52 +02:00
2024-07-13 23:57:07 +02:00
return $entity;
}
2024-07-18 19:13:06 +02:00
2024-07-19 01:17:33 +02:00
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
2024-07-19 18:59:21 +02:00
* @throws ORMException
2024-07-19 01:17:33 +02:00
*/
2024-08-19 18:06:11 +02:00
public function updateRDAPServersFromIANA(): void
2024-07-18 19:13:06 +02:00
{
2024-08-19 18:06:11 +02:00
$this->logger->info('Start of update the RDAP server list from IANA.');
2024-08-04 04:39:05 +02:00
2024-07-18 19:13:06 +02:00
$dnsRoot = $this->client->request(
'GET', 'https://data.iana.org/rdap/dns.json'
)->toArray();
2024-08-19 18:06:11 +02:00
$this->updateRDAPServers($dnsRoot);
}
/**
* @throws ORMException
* @throws \Exception
2024-08-19 18:06:11 +02:00
*/
private function updateRDAPServers(array $dnsRoot): void
{
2024-07-18 19:13:06 +02:00
foreach ($dnsRoot['services'] as $service) {
foreach ($service[0] as $tld) {
2024-08-02 23:24:52 +02:00
if ('' === $tld) {
continue;
}
2024-07-19 18:59:21 +02:00
$tldReference = $this->em->getReference(Tld::class, $tld);
2024-07-18 19:13:06 +02:00
foreach ($service[1] as $rdapServerUrl) {
2024-08-02 23:24:52 +02:00
$server = $this->rdapServerRepository->findOneBy(['tld' => $tldReference, 'url' => $rdapServerUrl]);
if (null === $server) {
$server = new RdapServer();
}
$server
->setTld($tldReference)
->setUrl($rdapServerUrl)
->setUpdatedAt(new \DateTimeImmutable(array_key_exists('publication', $dnsRoot) ? $dnsRoot['publication'] : 'now'));
2024-07-18 19:13:06 +02:00
$this->em->persist($server);
}
}
}
$this->em->flush();
}
2024-07-19 18:59:21 +02:00
/**
* @throws ORMException
*/
public function updateRDAPServersFromFile(string $fileName): void
{
if (!file_exists($fileName)) {
return;
}
$this->logger->info('Start of update the RDAP server list from custom config file.');
$this->updateRDAPServers(Yaml::parseFile($fileName));
}
2024-07-19 18:59:21 +02:00
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function updateTldListIANA(): void
{
2024-08-04 04:39:05 +02:00
$this->logger->info('Start of retrieval of the list of TLDs according to IANA.');
2024-07-19 18:59:21 +02:00
$tldList = array_map(
2024-08-02 23:24:52 +02:00
fn ($tld) => strtolower($tld),
2024-07-19 18:59:21 +02:00
explode(PHP_EOL,
$this->client->request(
'GET', 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt'
)->getContent()
));
array_shift($tldList);
2024-07-24 18:52:19 +02:00
foreach ($tldList as $tld) {
2024-08-02 23:24:52 +02:00
if ('' === $tld) {
continue;
}
2024-07-25 17:03:00 +02:00
2024-07-24 18:52:19 +02:00
$tldEntity = $this->tldRepository->findOneBy(['tld' => $tld]);
2024-07-25 17:03:00 +02:00
2024-08-02 23:24:52 +02:00
if (null === $tldEntity) {
2024-07-25 17:03:00 +02:00
$tldEntity = new Tld();
$tldEntity->setTld($tld);
2024-08-04 04:39:05 +02:00
$this->logger->notice('New TLD detected according to IANA ({tld}).', [
'tld' => $tld,
]);
2024-07-25 17:03:00 +02:00
}
2024-07-24 18:52:19 +02:00
2024-07-24 22:17:54 +02:00
$type = $this->getTldType($tld);
2024-07-25 17:03:00 +02:00
2024-08-02 23:24:52 +02:00
if (null !== $type) {
2024-07-24 22:17:54 +02:00
$tldEntity->setType($type);
2024-08-02 23:24:52 +02:00
} elseif (null === $tldEntity->isContractTerminated()) { // ICANN managed, must be a ccTLD
2024-07-24 22:17:54 +02:00
$tldEntity->setType(TldType::ccTLD);
} else {
$tldEntity->setType(TldType::gTLD);
2024-07-24 21:58:45 +02:00
}
2024-07-24 18:52:19 +02:00
$this->em->persist($tldEntity);
2024-07-19 18:59:21 +02:00
}
$this->em->flush();
}
2024-07-24 18:52:19 +02:00
private function getTldType(string $tld): ?TldType
{
2024-08-02 23:24:52 +02:00
if (in_array($tld, self::ISO_TLD_EXCEPTION)) {
return TldType::ccTLD;
}
if (in_array(strtolower($tld), self::INFRA_TLD)) {
return TldType::iTLD;
}
if (in_array(strtolower($tld), self::SPONSORED_TLD)) {
return TldType::sTLD;
}
if (in_array(strtolower($tld), self::TEST_TLD)) {
return TldType::tTLD;
}
2024-07-24 18:52:19 +02:00
2024-07-24 21:58:45 +02:00
return null;
2024-07-24 18:52:19 +02:00
}
2024-07-19 18:59:21 +02:00
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
* @throws DecodingExceptionInterface
2024-08-02 23:24:52 +02:00
* @throws \Exception
2024-07-19 18:59:21 +02:00
*/
public function updateGTldListICANN(): void
{
2024-08-04 04:39:05 +02:00
$this->logger->info('Start of retrieval of the list of gTLDs according to ICANN.');
2024-07-19 18:59:21 +02:00
$gTldList = $this->client->request(
'GET', 'https://www.icann.org/resources/registries/gtlds/v2/gtlds.json'
)->toArray()['gTLDs'];
foreach ($gTldList as $gTld) {
2024-08-02 23:24:52 +02:00
if ('' === $gTld['gTLD']) {
continue;
}
2024-07-24 18:52:19 +02:00
/** @var Tld $gtTldEntity */
$gtTldEntity = $this->tldRepository->findOneBy(['tld' => $gTld['gTLD']]);
2024-07-25 17:03:00 +02:00
if (null == $gtTldEntity) {
$gtTldEntity = new Tld();
$gtTldEntity->setTld($gTld['gTLD']);
2024-08-04 04:39:05 +02:00
$this->logger->notice('New gTLD detected according to ICANN ({tld}).', [
'tld' => $gTld['gTLD'],
]);
2024-07-25 17:03:00 +02:00
}
2024-07-19 18:59:21 +02:00
2024-07-24 21:58:45 +02:00
$gtTldEntity
->setContractTerminated($gTld['contractTerminated'])
2024-07-19 18:59:21 +02:00
->setRegistryOperator($gTld['registryOperator'])
2024-07-25 17:03:00 +02:00
->setSpecification13($gTld['specification13'])
->setType(TldType::gTLD);
2024-07-24 18:52:19 +02:00
2024-08-02 23:24:52 +02:00
if (null !== $gTld['removalDate']) {
$gtTldEntity->setRemovalDate(new \DateTimeImmutable($gTld['removalDate']));
}
if (null !== $gTld['delegationDate']) {
$gtTldEntity->setDelegationDate(new \DateTimeImmutable($gTld['delegationDate']));
}
if (null !== $gTld['dateOfContractSignature']) {
$gtTldEntity->setDateOfContractSignature(new \DateTimeImmutable($gTld['dateOfContractSignature']));
}
2024-07-19 18:59:21 +02:00
$this->em->persist($gtTldEntity);
}
2024-07-25 17:03:00 +02:00
2024-07-19 18:59:21 +02:00
$this->em->flush();
}
2024-08-02 23:24:52 +02:00
}