mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +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();
|
||||
|
|
|
@ -255,7 +255,7 @@ public class DomainWhoisResponseTest {
|
|||
@Test
|
||||
public void getPlainTextOutputTest() {
|
||||
DomainWhoisResponse domainWhoisResponse =
|
||||
new DomainWhoisResponse(domainResource, clock.nowUtc());
|
||||
new DomainWhoisResponse(domainResource, false, clock.nowUtc());
|
||||
assertThat(
|
||||
domainWhoisResponse.getResponse(
|
||||
false,
|
||||
|
@ -263,11 +263,22 @@ public class DomainWhoisResponseTest {
|
|||
.isEqualTo(WhoisResponseResults.create(loadFile("whois_domain.txt"), 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPlainTextOutputTest_fullOutput() {
|
||||
DomainWhoisResponse domainWhoisResponse =
|
||||
new DomainWhoisResponse(domainResource, true, clock.nowUtc());
|
||||
assertThat(
|
||||
domainWhoisResponse.getResponse(
|
||||
false,
|
||||
"Doodle Disclaimer\nI exist so that carriage return\nin disclaimer can be tested."))
|
||||
.isEqualTo(WhoisResponseResults.create(loadFile("whois_domain_full_output.txt"), 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addImplicitOkStatusTest() {
|
||||
DomainWhoisResponse domainWhoisResponse =
|
||||
new DomainWhoisResponse(
|
||||
domainResource.asBuilder().setStatusValues(null).build(), clock.nowUtc());
|
||||
domainResource.asBuilder().setStatusValues(null).build(), false, clock.nowUtc());
|
||||
assertThat(
|
||||
domainWhoisResponse
|
||||
.getResponse(
|
||||
|
|
|
@ -554,7 +554,7 @@ public class WhoisActionTest {
|
|||
persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4"));
|
||||
WhoisAction action = newWhoisAction("ns1.cat.lol");
|
||||
action.whoisReader = mock(WhoisReader.class);
|
||||
when(action.whoisReader.readCommand(any(Reader.class), any(DateTime.class)))
|
||||
when(action.whoisReader.readCommand(any(Reader.class), eq(false), any(DateTime.class)))
|
||||
.thenThrow(new IOException("missing cat interface"));
|
||||
action.whoisMetrics = mock(WhoisMetrics.class);
|
||||
|
||||
|
@ -574,11 +574,15 @@ public class WhoisActionTest {
|
|||
persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4"));
|
||||
WhoisAction action = newWhoisAction("ns1.cat.lol");
|
||||
WhoisResponse expectedResponse =
|
||||
action.whoisReader.readCommand(action.input, clock.nowUtc()).executeQuery(clock.nowUtc());
|
||||
action
|
||||
.whoisReader
|
||||
.readCommand(action.input, false, clock.nowUtc())
|
||||
.executeQuery(clock.nowUtc());
|
||||
|
||||
WhoisReader mockReader = mock(WhoisReader.class);
|
||||
WhoisCommand mockCommand = mock(WhoisCommand.class);
|
||||
when(mockReader.readCommand(any(Reader.class), any(DateTime.class))).thenReturn(mockCommand);
|
||||
when(mockReader.readCommand(any(Reader.class), eq(false), any(DateTime.class)))
|
||||
.thenReturn(mockCommand);
|
||||
when(mockCommand.executeQuery(any(DateTime.class)))
|
||||
.thenThrow(new DatastoreFailureException("Expected transient exception #1"))
|
||||
.thenThrow(new DatastoreTimeoutException("Expected transient exception #2"))
|
||||
|
|
|
@ -358,7 +358,7 @@ public class WhoisHttpActionTest {
|
|||
persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4"));
|
||||
WhoisHttpAction action = newWhoisHttpAction("ns1.cat.lol");
|
||||
action.whoisReader = mock(WhoisReader.class);
|
||||
when(action.whoisReader.readCommand(any(Reader.class), any(DateTime.class)))
|
||||
when(action.whoisReader.readCommand(any(Reader.class), eq(false), any(DateTime.class)))
|
||||
.thenThrow(new IOException("missing cat interface"));
|
||||
action.whoisMetrics = mock(WhoisMetrics.class);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public class WhoisReaderTest {
|
|||
<T> T readCommand(String commandStr) throws Exception {
|
||||
return (T)
|
||||
new WhoisReader(new WhoisCommandFactory())
|
||||
.readCommand(new StringReader(commandStr), clock.nowUtc());
|
||||
.readCommand(new StringReader(commandStr), false, clock.nowUtc());
|
||||
}
|
||||
|
||||
void assertLoadsExampleTld(String commandString) throws Exception {
|
||||
|
|
66
javatests/google/registry/whois/testdata/whois_domain_full_output.txt
vendored
Normal file
66
javatests/google/registry/whois/testdata/whois_domain_full_output.txt
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
Domain Name: example.tld
|
||||
Registry Domain ID: 3-TLD
|
||||
Registrar WHOIS Server: whois.nic.fakewhois.example
|
||||
Registrar URL: http://my.fake.url
|
||||
Updated Date: 2009-05-29T20:13:00Z
|
||||
Creation Date: 2000-10-08T00:45:00Z
|
||||
Registry Expiry Date: 2010-10-08T00:44:59Z
|
||||
Registrar: New Registrar
|
||||
Registrar IANA ID: 5555555
|
||||
Registrar Abuse Contact Email: jakedoe@theregistrar.com
|
||||
Registrar Abuse Contact Phone: +1.2125551216
|
||||
Domain Status: addPeriod https://icann.org/epp#addPeriod
|
||||
Domain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited
|
||||
Domain Status: clientRenewProhibited https://icann.org/epp#clientRenewProhibited
|
||||
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
|
||||
Domain Status: serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited
|
||||
Domain Status: transferPeriod https://icann.org/epp#transferPeriod
|
||||
Registry Registrant ID: 4-TLD
|
||||
Registrant Name: EXAMPLE REGISTRANT
|
||||
Registrant Organization: Tom & Jerry Corp.
|
||||
Registrant Street: 123 EXAMPLE STREET
|
||||
Registrant City: ANYTOWN
|
||||
Registrant State/Province: AP
|
||||
Registrant Postal Code: A1A1A1
|
||||
Registrant Country: EX
|
||||
Registrant Phone: +1.5555551212
|
||||
Registrant Phone Ext: 1234
|
||||
Registrant Fax: +1.5555551213
|
||||
Registrant Fax Ext: 4321
|
||||
Registrant Email: EMAIL@EXAMPLE.tld
|
||||
Registry Admin ID: 5-TLD
|
||||
Admin Name: EXAMPLE REGISTRANT ADMINISTRATIVE
|
||||
Admin Organization: EXAMPLE REGISTRANT ORGANIZATION
|
||||
Admin Street: 123 EXAMPLE STREET
|
||||
Admin City: ANYTOWN
|
||||
Admin State/Province: AP
|
||||
Admin Postal Code: A1A1A1
|
||||
Admin Country: EX
|
||||
Admin Phone: +1.5555551212
|
||||
Admin Phone Ext: 1234
|
||||
Admin Fax: +1.5555551213
|
||||
Admin Email: EMAIL@EXAMPLE.tld
|
||||
Registry Tech ID: 6-TLD
|
||||
Tech Name: EXAMPLE REGISTRAR TECHNICAL
|
||||
Tech Organization: EXAMPLE REGISTRAR LLC
|
||||
Tech Street: 123 EXAMPLE STREET
|
||||
Tech City: ANYTOWN
|
||||
Tech State/Province: AP
|
||||
Tech Postal Code: A1A1A1
|
||||
Tech Country: EX
|
||||
Tech Phone: +1.1235551234
|
||||
Tech Phone Ext: 1234
|
||||
Tech Fax: +1.5555551213
|
||||
Tech Fax Ext: 93
|
||||
Tech Email: EMAIL@EXAMPLE.tld
|
||||
Name Server: ns01.exampleregistrar.tld
|
||||
Name Server: ns02.exampleregistrar.tld
|
||||
DNSSEC: signedDelegation
|
||||
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
|
||||
>>> Last update of WHOIS database: 2009-05-29T20:15:00Z <<<
|
||||
|
||||
For more information on Whois status codes, please visit https://icann.org/epp
|
||||
|
||||
Doodle Disclaimer
|
||||
I exist so that carriage return
|
||||
in disclaimer can be tested.
|
Loading…
Add table
Add a link
Reference in a new issue