package be.dnsbelgium.rdap.sample.service;
import be.dnsbelgium.core.DomainName;
import be.dnsbelgium.core.TelephoneNumber;
import be.dnsbelgium.rdap.core.Domain;
import be.dnsbelgium.rdap.core.*;
import be.dnsbelgium.rdap.sample.dto.*;
import be.dnsbelgium.rdap.sample.error.InternalServerError;
import be.dnsbelgium.rdap.sample.error.QuotaReachedError;
import be.dnsbelgium.rdap.sample.parser.WhoisDomainParser;
import be.dnsbelgium.rdap.sample.parser.WhoisHostListParser;
import be.dnsbelgium.rdap.sample.parser.WhoisRegistrarListParser;
import be.dnsbelgium.rdap.service.impl.DefaultDomainService;
import be.dnsbelgium.vcard.Contact;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.whois.WhoisClient;
import org.joda.time.DateTime;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GtldWhoisService extends DefaultDomainService {
public static final String NO_MATCH = "% No match";
public static final String QUOTA_EXCEEDED = "% Quota exceeded";
public static final String DOMAIN_NOT_FOUND = "Domain not found";
private Entity whoisContactEntity(be.dnsbelgium.rdap.sample.dto.Contact contact, Entity.Role role) {
List<Entity.Role> roles = new ArrayList<>();
roles.add(role);
Contact.Builder builder = new Contact.Builder();
builder.addEmailAddress(contact.email);
builder.setFormattedName(contact.name == null ? contact.organization : contact.name)
.addStreet(contact.address.street)
.addStreet(contact.address.street2)
.addStreet(contact.address.street3)
.setLocality(contact.address.city)
.setCountry(contact.address.countryCode)
.setRegion(contact.address.region)
.setPostalCode(contact.address.postalCode)
.setOrganization(contact.organization);
if (contact.phone != null) {
try {
builder.addTelephoneNumber(TelephoneNumber.of(contact.phone));
} catch (IllegalArgumentException iae) {
System.out.println("iae = " + iae);
}
}
if (contact.fax != null) {
try {
builder.addFaxNumber(TelephoneNumber.of(contact.fax));
} catch (IllegalArgumentException iae) {
System.out.println("iae = " + iae);
}
}
return new Entity(null, null, null, null, Entity.OBJECT_CLASS_NAME, null, null, null, contact.id, builder.build(), roles, null, null);
}
private Entity whoisRegistrarEntity(WhoisRegistrar registrar, Entity.Role role) {
List<Entity.Role> roles = new ArrayList<>();
roles.add(role);
Contact.Builder builder = new Contact.Builder();
builder.setFormattedName(registrar.name)
.addEmailAddress(registrar.email)
.addStreet(registrar.address.street)
.addStreet(registrar.address.street2)
.addStreet(registrar.address.street3)
.setLocality(registrar.address.city)
.setCountry(registrar.address.countryCode)
.setRegion(registrar.address.region)
.setPostalCode(registrar.address.postalCode)
.setOrganization(registrar.name);
if (registrar.phone != null) {
try {
builder.addTelephoneNumber(TelephoneNumber.of(registrar.phone));
} catch (IllegalArgumentException iae) {
System.out.println("iae = " + iae);
}
}
if (registrar.fax != null) {
try {
builder.addFaxNumber(TelephoneNumber.of(registrar.fax));
} catch (IllegalArgumentException iae) {
System.out.println("iae = " + iae);
}
}
//reghandle not found in response data
return new Entity(null, null, null, null, Entity.OBJECT_CLASS_NAME, null, null, null, registrar.ianaId, builder.build(), roles, null, null);
}
@Override
public Domain getDomainImpl(DomainName domainName) throws RDAPError {
try {
String tld = domainName.getTLDLabel().getStringValue();
WhoisClient whoisClient = new WhoisClient();
whoisClient.setDefaultTimeout(10000);
whoisClient.setConnectTimeout(5000);
whoisClient.connect("whois.nic." + tld, 43);
whoisClient.setSoTimeout(10000);
String query = domainName.getStringValue();
String whoisData = whoisClient.query(query);
if (StringUtils.strip(whoisData).startsWith(QUOTA_EXCEEDED)) {
throw new QuotaReachedError();
}
if (StringUtils.strip(whoisData).startsWith(NO_MATCH)) {
return null;
}
if (StringUtils.strip(whoisData).startsWith(DOMAIN_NOT_FOUND)) {
return null;
}
WhoisDomainParser parser = new WhoisDomainParser();
WhoisDomain whoisDomain = parser.parse(whoisData);
if (whoisDomain == null || whoisDomain.domain == null || StringUtils.isEmpty(whoisDomain.domain.uLabel)) {
throw new InternalServerError("Unrecognized result");
}
return convert(whoisDomain, tld);
} catch (IOException e) {
throw new InternalServerError(e.getMessage());
}
}
public Domain convert(WhoisDomain whoisDomain, String tld) throws RDAPError {
List<Entity> entities = new ArrayList<>();
entities.add(whoisContactEntity(whoisDomain.registrant, Entity.Role.Default.REGISTRANT));
for (be.dnsbelgium.rdap.sample.dto.Contact contact : whoisDomain.admin) {
entities.add(whoisContactEntity(contact, Entity.Role.Default.ADMINISTRATIVE));
}
for (be.dnsbelgium.rdap.sample.dto.Contact contact : whoisDomain.tech) {
entities.add(whoisContactEntity(contact, Entity.Role.Default.TECHNICAL));
}
WhoisRegistrar whoisRegistrar = getRegistrar(tld, whoisDomain.sponsoringRegistrar.name);
entities.add(whoisRegistrarEntity(whoisRegistrar, Entity.Role.Default.REGISTRAR));
List<Nameserver> nameservers = new ArrayList<>();
for (String nameserverName : whoisDomain.nameservers) {
DomainName nameServer = DomainName.of(nameserverName);
List<InetAddress> inetAddresses = new ArrayList<>();
if (tld.equals(nameServer.getTLDLabel().getStringValue())) {
WhoisHost whoisHost = getHost(tld, nameserverName);
if (whoisHost != null) {
for (IpAddress ipAddress : whoisHost.ipAddressList) {
try {
inetAddresses.add(InetAddress.getByName(ipAddress.isIpv4() ? ipAddress.ip4 : ipAddress.ip6));
} catch (UnknownHostException e) {
System.out.println("e = " + e);
}
}
}
}
nameservers.add(new Nameserver(null, null, null, null, null, null, null, null, DomainName.of(nameserverName).toLDH(),
DomainName.of(nameserverName).toUnicode(), inetAddresses.isEmpty() ? null : new Nameserver.IpAddresses(inetAddresses)));
}
SecureDNS secureDNS = null;
if (whoisDomain.dnssec != null && !whoisDomain.dnssec.keys.isEmpty()) {
List<SecureDNS.DSData> dsDatas = new ArrayList<>();
for (DnsSecKey ds : whoisDomain.dnssec.keys) {
dsDatas.add(new SecureDNS.DSData(Integer.parseInt(ds.dsKeyTag), Integer.parseInt(ds.algorithm), ds.digest, Integer.parseInt(ds.digestType), null, null));
}
secureDNS = new SecureDNS(true, true, 1, dsDatas, null);
}
ArrayList<Event> events = new ArrayList<>();
if (whoisDomain.domain.creationDate != null) {
events.add(new Event(Event.Action.Default.REGISTRATION, null, new DateTime(whoisDomain.domain.creationDate), null));
}
if (whoisDomain.domain.updatedDate != null) {
events.add(new Event(Event.Action.Default.LAST_CHANGED, null, new DateTime(whoisDomain.domain.updatedDate), null));
}
List<Status> statusses = new ArrayList<>();
statusses.addAll(whoisDomain.domain.statusList);
DomainName port43 = null;
if (!StringUtils.isEmpty(whoisDomain.whoisServer)) {
port43 = DomainName.of(whoisDomain.whoisServer);
} else {
port43 = DomainName.of("whois.nic." + tld);
}
return new Domain(null, null, null, null, events, statusses, port43, null, DomainName.of(whoisDomain.domain.name), DomainName.of(whoisDomain.domain.uLabel), null, nameservers, secureDNS, entities, null, null);
}
private WhoisRegistrar getRegistrar(String tld, String registrar) throws RDAPError {
try {
WhoisClient whoisClient = new WhoisClient();
whoisClient.setDefaultTimeout(10000);
whoisClient.setConnectTimeout(5000);
whoisClient.connect("whois.nic." + tld, 43);
whoisClient.setSoTimeout(10000);
String query = "registrar " + registrar;
String whoisData = whoisClient.query(query);
if (StringUtils.strip(whoisData).startsWith(QUOTA_EXCEEDED)) {
throw new QuotaReachedError();
}
if (StringUtils.strip(whoisData).startsWith(NO_MATCH)) {
return null;
}
WhoisRegistrarListParser parser = new WhoisRegistrarListParser();
List<WhoisRegistrar> results = parser.parseResult(whoisData);
for (Iterator<WhoisRegistrar> iterator = results.iterator(); iterator.hasNext(); ) {
WhoisRegistrar whoisRegistrar = iterator.next();
if (!whoisRegistrar.name.equals(registrar)) {
iterator.remove();
}
}
if (results.isEmpty()) {
return null;
}
return results.iterator().next();
} catch (IOException e) {
throw new InternalServerError(e.getMessage());
}
}
private WhoisHost getHost(String tld, String host) throws RDAPError {
try {
WhoisClient whoisClient = new WhoisClient();
whoisClient.setDefaultTimeout(10000);
whoisClient.setConnectTimeout(5000);
whoisClient.connect("whois.nic." + tld, 43);
whoisClient.setSoTimeout(10000);
String query = "nameserver " + host;
String whoisData = whoisClient.query(query);
if (StringUtils.strip(whoisData).startsWith(QUOTA_EXCEEDED)) {
throw new QuotaReachedError();
}
if (StringUtils.strip(whoisData).startsWith(NO_MATCH)) {
return null;
}
WhoisHostListParser parser = new WhoisHostListParser();
List<WhoisHost> results = parser.parseResult(whoisData);
for (Iterator<WhoisHost> iterator = results.iterator(); iterator.hasNext(); ) {
WhoisHost whoisHost = iterator.next();
if (!whoisHost.name.equals(host)) {
iterator.remove();
}
}
if (results.isEmpty()) {
return null;
}
return results.iterator().next();
} catch (IOException e) {
throw new InternalServerError(e.getMessage());
}
}
}