mirror of
https://github.com/google/nomulus.git
synced 2025-05-15 08:57:12 +02:00
Add ability to show full WHOIS output in nomulus command
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=197731992
This commit is contained in:
parent
ac500652ac
commit
86dd6bd59e
15 changed files with 181 additions and 62 deletions
|
@ -36,11 +36,14 @@ final class WhoisQueryCommand implements RemoteApiCommand {
|
|||
description = "When set, output will be Unicode")
|
||||
private boolean unicode;
|
||||
|
||||
@Parameter(names = "--full_output", description = "When set, the full output will be displayed")
|
||||
private boolean fullOutput;
|
||||
|
||||
@Inject
|
||||
Whois whois;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println(whois.lookup(Joiner.on(' ').join(mainParameters), unicode));
|
||||
System.out.println(whois.lookup(Joiner.on(' ').join(mainParameters), unicode, fullOutput));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,11 @@ import org.joda.time.DateTime;
|
|||
/** Represents a WHOIS lookup on a domain name (i.e. SLD). */
|
||||
public class DomainLookupCommand extends DomainOrHostLookupCommand {
|
||||
|
||||
public DomainLookupCommand(InternetDomainName domainName) {
|
||||
private final boolean fullOutput;
|
||||
|
||||
public DomainLookupCommand(InternetDomainName domainName, boolean fullOutput) {
|
||||
super(domainName, "Domain");
|
||||
this.fullOutput = fullOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,6 +36,6 @@ public class DomainLookupCommand extends DomainOrHostLookupCommand {
|
|||
final DomainResource domainResource =
|
||||
loadByForeignKeyCached(DomainResource.class, domainName.toString(), now);
|
||||
return Optional.ofNullable(
|
||||
domainResource == null ? null : new DomainWhoisResponse(domainResource, now));
|
||||
domainResource == null ? null : new DomainWhoisResponse(domainResource, fullOutput, now));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import google.registry.model.EppResource;
|
|||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
|
@ -54,10 +56,14 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
|||
/** Domain which was the target of this WHOIS command. */
|
||||
private final DomainResource domain;
|
||||
|
||||
/** Whether the full WHOIS output is to be displayed. */
|
||||
private final boolean fullOutput;
|
||||
|
||||
/** Creates new WHOIS domain response on the given domain. */
|
||||
DomainWhoisResponse(DomainResource domain, DateTime timestamp) {
|
||||
DomainWhoisResponse(DomainResource domain, boolean fullOutput, DateTime timestamp) {
|
||||
super(timestamp);
|
||||
this.domain = checkNotNull(domain, "domain");
|
||||
this.fullOutput = fullOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,7 +81,7 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
|||
.stream()
|
||||
.filter(RegistrarContact::getVisibleInDomainWhoisAsAbuse)
|
||||
.findFirst();
|
||||
String plaintext =
|
||||
DomainEmitter domainEmitter =
|
||||
new DomainEmitter()
|
||||
.emitField(
|
||||
"Domain Name",
|
||||
|
@ -98,19 +104,32 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
|||
"Registrar Abuse Contact Phone",
|
||||
abuseContact.map(RegistrarContact::getPhoneNumber).orElse(null))
|
||||
.emitStatusValues(domain.getStatusValues(), domain.getGracePeriods())
|
||||
.emitContact("Registrant", domain.getRegistrant(), preferUnicode)
|
||||
.emitSet(
|
||||
"Name Server",
|
||||
domain.loadNameserverFullyQualifiedHostNames(),
|
||||
hostName -> maybeFormatHostname(hostName, preferUnicode))
|
||||
.emitField(
|
||||
"DNSSEC", isNullOrEmpty(domain.getDsData()) ? "unsigned" : "signedDelegation")
|
||||
.emitWicfLink()
|
||||
.emitLastUpdated(getTimestamp())
|
||||
.emitAwipMessage()
|
||||
.emitFooter(disclaimer)
|
||||
.toString();
|
||||
return WhoisResponseResults.create(plaintext, 1);
|
||||
.emitContact(
|
||||
"Registrant", Optional.of(domain.getRegistrant()), preferUnicode, fullOutput);
|
||||
if (fullOutput) {
|
||||
domainEmitter
|
||||
.emitContact("Admin", getContactReference(Type.ADMIN), preferUnicode, fullOutput)
|
||||
.emitContact("Tech", getContactReference(Type.TECH), preferUnicode, fullOutput)
|
||||
.emitContact("Billing", getContactReference(Type.BILLING), preferUnicode, fullOutput);
|
||||
}
|
||||
domainEmitter
|
||||
.emitSet(
|
||||
"Name Server",
|
||||
domain.loadNameserverFullyQualifiedHostNames(),
|
||||
hostName -> maybeFormatHostname(hostName, preferUnicode))
|
||||
.emitField("DNSSEC", isNullOrEmpty(domain.getDsData()) ? "unsigned" : "signedDelegation")
|
||||
.emitWicfLink()
|
||||
.emitLastUpdated(getTimestamp())
|
||||
.emitAwipMessage()
|
||||
.emitFooter(disclaimer);
|
||||
return WhoisResponseResults.create(domainEmitter.toString(), 1);
|
||||
}
|
||||
|
||||
/** Returns the contact of the given type. */
|
||||
private Optional<Key<ContactResource>> getContactReference(Type type) {
|
||||
Optional<DesignatedContact> contactOfType =
|
||||
domain.getContacts().stream().filter(d -> d.getType() == type).findFirst();
|
||||
return contactOfType.map(DesignatedContact::getContactKey);
|
||||
}
|
||||
|
||||
/** Output emitter with logic for domains. */
|
||||
|
@ -127,14 +146,17 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
|||
|
||||
/** Emit the contact entry of the given type. */
|
||||
DomainEmitter emitContact(
|
||||
String contactType, @Nullable Key<ContactResource> contact, boolean preferUnicode) {
|
||||
if (contact == null) {
|
||||
String contactType,
|
||||
Optional<Key<ContactResource>> contact,
|
||||
boolean preferUnicode,
|
||||
boolean fullOutput) {
|
||||
if (!contact.isPresent()) {
|
||||
return this;
|
||||
}
|
||||
// If we refer to a contact that doesn't exist, that's a bug. It means referential integrity
|
||||
// has somehow been broken. We skip the rest of this contact, but log it to hopefully bring it
|
||||
// someone's attention.
|
||||
ContactResource contactResource = EppResource.loadCached(contact);
|
||||
ContactResource contactResource = EppResource.loadCached(contact.get());
|
||||
if (contactResource == null) {
|
||||
logger.severefmt(
|
||||
"(BUG) Broken reference found from domain %s to contact %s",
|
||||
|
@ -146,9 +168,23 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
|||
preferUnicode,
|
||||
contactResource.getLocalizedPostalInfo(),
|
||||
contactResource.getInternationalizedPostalInfo());
|
||||
if (postalInfo != null) {
|
||||
emitFieldIfDefined(ImmutableList.of(contactType, "Organization"), postalInfo.getOrg());
|
||||
emitRegistrantAddress(contactType, postalInfo.getAddress());
|
||||
if (fullOutput) {
|
||||
// If the full output is to be displayed, show all fields for all contact types.
|
||||
// ICANN Consistent Labeling & Display policy requires that this be the ROID.
|
||||
emitField(ImmutableList.of("Registry", contactType, "ID"), contactResource.getRepoId());
|
||||
if (postalInfo != null) {
|
||||
emitFieldIfDefined(ImmutableList.of(contactType, "Name"), postalInfo.getName());
|
||||
emitFieldIfDefined(ImmutableList.of(contactType, "Organization"), postalInfo.getOrg());
|
||||
emitAddress(contactType, postalInfo.getAddress(), fullOutput);
|
||||
}
|
||||
emitPhone(contactType, "Phone", contactResource.getVoiceNumber());
|
||||
emitPhone(contactType, "Fax", contactResource.getFaxNumber());
|
||||
emitField(ImmutableList.of(contactType, "Email"), contactResource.getEmailAddress());
|
||||
} else {
|
||||
if (postalInfo != null) {
|
||||
emitFieldIfDefined(ImmutableList.of(contactType, "Organization"), postalInfo.getOrg());
|
||||
emitAddress(contactType, postalInfo.getAddress(), fullOutput);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -48,12 +48,13 @@ class RegistrarWhoisResponse extends WhoisResponseImpl {
|
|||
String plaintext =
|
||||
new RegistrarEmitter()
|
||||
.emitField("Registrar", registrar.getRegistrarName())
|
||||
.emitRegistrarAddress(
|
||||
.emitAddress(
|
||||
null,
|
||||
chooseByUnicodePreference(
|
||||
preferUnicode,
|
||||
registrar.getLocalizedAddress(),
|
||||
registrar.getInternationalizedAddress()))
|
||||
registrar.getInternationalizedAddress()),
|
||||
true)
|
||||
.emitPhonesAndEmail(
|
||||
registrar.getPhoneNumber(), registrar.getFaxNumber(), registrar.getEmailAddress())
|
||||
.emitField("Registrar WHOIS Server", registrar.getWhoisServer())
|
||||
|
|
|
@ -36,11 +36,11 @@ public final class Whois {
|
|||
}
|
||||
|
||||
/** Performs a WHOIS lookup on a plaintext query string. */
|
||||
public String lookup(String query, boolean preferUnicode) {
|
||||
public String lookup(String query, boolean preferUnicode, boolean fullOutput) {
|
||||
DateTime now = clock.nowUtc();
|
||||
try {
|
||||
return whoisReader
|
||||
.readCommand(new StringReader(query), now)
|
||||
.readCommand(new StringReader(query), fullOutput, now)
|
||||
.executeQuery(now)
|
||||
.getResponse(preferUnicode, disclaimer)
|
||||
.plainTextOutput();
|
||||
|
|
|
@ -80,7 +80,7 @@ public class WhoisAction implements Runnable {
|
|||
String responseText;
|
||||
final DateTime now = clock.nowUtc();
|
||||
try {
|
||||
final WhoisCommand command = whoisReader.readCommand(input, now);
|
||||
final WhoisCommand command = whoisReader.readCommand(input, false, now);
|
||||
metricBuilder.setCommand(command);
|
||||
WhoisResponseResults results =
|
||||
retrier.callWithRetry(
|
||||
|
|
|
@ -27,8 +27,8 @@ import java.net.InetAddress;
|
|||
public class WhoisCommandFactory {
|
||||
|
||||
/** Returns a new {@link WhoisCommand} to perform a domain lookup on the specified domain name. */
|
||||
public WhoisCommand domainLookup(InternetDomainName domainName) {
|
||||
return new DomainLookupCommand(domainName);
|
||||
public WhoisCommand domainLookup(InternetDomainName domainName, boolean fullOutput) {
|
||||
return new DomainLookupCommand(domainName, fullOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,7 +151,7 @@ public final class WhoisHttpAction implements Runnable {
|
|||
String commandText =
|
||||
decode(JOINER.join(SLASHER.split(path.substring(PATH.length())))) + "\r\n";
|
||||
DateTime now = clock.nowUtc();
|
||||
WhoisCommand command = whoisReader.readCommand(new StringReader(commandText), now);
|
||||
WhoisCommand command = whoisReader.readCommand(new StringReader(commandText), false, now);
|
||||
metricBuilder.setCommand(command);
|
||||
sendResponse(SC_OK, command.executeQuery(now));
|
||||
} catch (WhoisException e) {
|
||||
|
|
|
@ -82,21 +82,22 @@ class WhoisReader {
|
|||
}
|
||||
|
||||
/**
|
||||
* Read a command from some source to produce a new instance of
|
||||
* WhoisCommand.
|
||||
* Read a command from some source to produce a new instance of WhoisCommand.
|
||||
*
|
||||
* @throws IOException If the command could not be read from the reader.
|
||||
* @throws WhoisException If the command could not be parsed as a WhoisCommand.
|
||||
*/
|
||||
WhoisCommand readCommand(Reader reader, DateTime now) throws IOException, WhoisException {
|
||||
return parseCommand(CharStreams.toString(checkNotNull(reader, "reader")), now);
|
||||
WhoisCommand readCommand(Reader reader, boolean fullOutput, DateTime now)
|
||||
throws IOException, WhoisException {
|
||||
return parseCommand(CharStreams.toString(checkNotNull(reader, "reader")), fullOutput, now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a WHOIS command string, parse it into its command type and target string. See class level
|
||||
* comments for a full description of the command syntax accepted.
|
||||
*/
|
||||
private WhoisCommand parseCommand(String command, DateTime now) throws WhoisException {
|
||||
private WhoisCommand parseCommand(String command, boolean fullOutput, DateTime now)
|
||||
throws WhoisException {
|
||||
// Split the string into tokens based on whitespace.
|
||||
List<String> tokens = filterEmptyStrings(command.split("\\s"));
|
||||
if (tokens.isEmpty()) {
|
||||
|
@ -115,8 +116,8 @@ class WhoisReader {
|
|||
// Try to parse the argument as a domain name.
|
||||
try {
|
||||
logger.infofmt("Attempting domain lookup command using domain name %s", tokens.get(1));
|
||||
return commandFactory.domainLookup(InternetDomainName.from(
|
||||
canonicalizeDomainName(tokens.get(1))));
|
||||
return commandFactory.domainLookup(
|
||||
InternetDomainName.from(canonicalizeDomainName(tokens.get(1))), fullOutput);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// If we can't interpret the argument as a host name, then return an error.
|
||||
throw new WhoisException(now, SC_BAD_REQUEST, String.format(
|
||||
|
@ -194,7 +195,7 @@ class WhoisReader {
|
|||
// (SLD) and we should do a domain lookup on it.
|
||||
if (targetName.parent().equals(tld.get())) {
|
||||
logger.infofmt("Attempting domain lookup using %s as a domain name", targetName);
|
||||
return commandFactory.domainLookup(targetName);
|
||||
return commandFactory.domainLookup(targetName, fullOutput);
|
||||
}
|
||||
|
||||
// The target is more than one level above the TLD, so we'll assume it's a nameserver.
|
||||
|
|
|
@ -134,24 +134,18 @@ abstract class WhoisResponseImpl implements WhoisResponse {
|
|||
return emitField(Joiner.on(' ').join(nameParts), value);
|
||||
}
|
||||
|
||||
/** Emit registrar address. */
|
||||
E emitRegistrarAddress(@Nullable String prefix, @Nullable Address address) {
|
||||
prefix = isNullOrEmpty(prefix) ? "" : prefix + " ";
|
||||
if (address != null) {
|
||||
emitList(prefix + "Street", address.getStreet());
|
||||
emitField(prefix + "City", address.getCity());
|
||||
emitField(prefix + "State/Province", address.getState());
|
||||
emitField(prefix + "Postal Code", address.getZip());
|
||||
emitField(prefix + "Country", address.getCountryCode());
|
||||
}
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
/** Emit registrant address. */
|
||||
E emitRegistrantAddress(@Nullable String prefix, @Nullable Address address) {
|
||||
/** Emit a contact address. */
|
||||
E emitAddress(@Nullable String prefix, @Nullable Address address, boolean fullOutput) {
|
||||
prefix = isNullOrEmpty(prefix) ? "" : prefix + " ";
|
||||
if (address != null) {
|
||||
if (fullOutput) {
|
||||
emitList(prefix + "Street", address.getStreet());
|
||||
emitField(prefix + "City", address.getCity());
|
||||
}
|
||||
emitField(prefix + "State/Province", address.getState());
|
||||
if (fullOutput) {
|
||||
emitField(prefix + "Postal Code", address.getZip());
|
||||
}
|
||||
emitField(prefix + "Country", address.getCountryCode());
|
||||
}
|
||||
return thisCastToDerived();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue