+
+
+
+
+
+ {response != null ? : null}
+
+
+
This page implements a completely private lookup tool for domain names, IP addresses and
+ Autonymous System Numbers (ASNs). Only the relevant registry sees your query: your browser will
+ directly
+ connect to the registry's RDAP server using an encrypted HTTPS connection to protect the
+ confidentiality of
+ your query. If you click the "Follow referral to registrar's RDAP
+ record" checkbox, then the
+ sponsoring
+ registrar may also see your query.
+
+ - Click here for more information about
+ what RDAP is
+ and how it differs from traditional Whois.
+
+ - Most generic TLDs now support RDAP, but only a few ccTLDs have deployed RDAP so far. To see
+ which TLDs
+ support RDAP, click here.
+
+ - There is no bootstrap registry for top-level domains or ICANN-accredited registrars; instead
+ these queries are sent to the
+
+ {"{"}root,registrars{"}"}.rdap.org servers
+ .
+
+ - To submit feedback, click here. Please contact the
+ relevant
+ registry or registrar if you have an issue with the content of an RDAP response.
+
+ - This tool is Free Software; for the license, click here. To fork a
+ copy of the git
+ repository, click
+ here.
+
+ - This page uses ipaddr.js by whitequark.
+
+
+
+
+ >
+ >
+ );
+};
+
+export default Index;
diff --git a/src/rdap.ts b/src/rdap.ts
new file mode 100644
index 0000000..e5ef314
--- /dev/null
+++ b/src/rdap.ts
@@ -0,0 +1,740 @@
+import ipaddr from "ipaddr.js";
+import {registryURLs, rdapStatusInfo, placeholders} from "./constants";
+import type {Uri} from "./types";
+
+// keeps track of how many registries we've loaded
+let loadedRegistries = 0;
+
+// registry data is stored in this
+let registryData = {};
+
+// keeps track of the elements we've created so we can assign a unique ID
+let elementCounter = 123456;
+
+const cardTitles = {
+ "domain": "Domain Name",
+ "ip network": "IP Network",
+ "nameserver": "Nameserver",
+ "entity": "Entity",
+ "autnum": "AS Number",
+};
+
+export function domainMatch(tld: string, domain: string): boolean {
+ return domain.toUpperCase().endsWith(`.${tld.toUpperCase()}`);
+}
+
+export function asnMatch(range, asn) {
+ var [min, max] = range.split('-', 2);
+ min = parseInt(min);
+ max = parseInt(max);
+
+ return (asn >= min && asn <= max);
+}
+
+export function entityMatch(tag: string, handle: string) {
+ return handle.toUpperCase().endsWith('-' + tag.toUpperCase());
+}
+
+export function ipMatch(prefix: string, ip: string) {
+ var parsedIp = ipaddr.parse(ip);
+ let cidr = ipaddr.parseCIDR(prefix);
+ return (parsedIp.kind() == cidr[0].kind() && parsedIp.match(cidr));
+}
+
+// return the first HTTPS url, or the first URL
+export function getBestURL(urls: string[]): string {
+ urls.forEach((url) => {
+ if (url.startsWith('https://'))
+ return url;
+ })
+ return urls[0]!;
+}
+
+// given a URL, injects that URL into the query input,
+// and initiates an RDAP query
+export function runQuery(url) {
+ var type = document.getElementById('type');
+
+ for (var i = 0; i < type.options.length; i++) if ('url' == type.options[i].value) type.selectedIndex = i;
+ document.getElementById('object').value = url;
+ doQuery();
+}
+
+export function showSpinner(msg) {
+ msg = msg ? msg : 'Loading...';
+
+ var div = document.getElementById('output-div');
+ div.innerHTML = '';
+
+ var spinner = document.createElement('div');
+ spinner.classList.add('spinner-border');
+ spinner.role = 'status';
+ var span = spinner.appendChild(document.createElement('span'));
+ span.classList.add('sr-only');
+ span.appendChild(document.createTextNode(msg));
+
+ div.appendChild(spinner);
+
+ var msgDiv = document.createElement('div');
+ msgDiv.id = 'spinner-msg';
+ msgDiv.appendChild(document.createTextNode(msg));
+ div.appendChild(msgDiv);
+}
+
+// export function handleError(error) {
+// var div = document.getElementById('output-div');
+// div.innerHTML = '';
+// div.appendChild(createErrorNode(error));
+// }
+
+export function createErrorNode(error) {
+ el = document.createElement('p');
+ el.classList.add('error', 'alert', 'alert-warning');
+ el.appendChild(document.createTextNode(error));
+
+ return el;
+}
+
+// process an RDAP object. Argument is a JSON object, return
+// value is an element that can be inserted into the page
+export function processObject(object, toplevel, followReferral = true) {
+ if (!object) {
+ console.log(object);
+ return false;
+ }
+
+ var dl = document.createElement('dl');
+
+ switch (object.objectClassName) {
+ case 'domain':
+ processDomain(object, dl, toplevel);
+ break;
+
+ case 'nameserver':
+ processNameserver(object, dl, toplevel);
+ break;
+
+ case 'entity':
+ processEntity(object, dl, toplevel);
+ break;
+
+ case 'autnum':
+ processAutnum(object, dl, toplevel);
+ break;
+
+ case 'ip network':
+ processIp(object, dl, toplevel);
+ break;
+
+ default:
+ if (object.errorCode) {
+ return createErrorNode(object.errorCode + ' error: ' + object.title);
+
+ } else {
+ processUnknown(object, dl, toplevel);
+
+ }
+ }
+
+ var card = document.createElement('div');
+ card.classList.add('card');
+
+ var titleText = '';
+ if (object.unicodeName) {
+ titleText = object.unicodeName.toUpperCase();
+
+ } else if (object.ldhName) {
+ titleText = object.ldhName.toUpperCase();
+
+ } else if (object.handle) {
+ titleText = object.handle.toUpperCase();
+
+ }
+
+ if (object.handle && object.handle != titleText) titleText += ' (' + object.handle + ')';
+
+ if (titleText.length > 0) {
+ titleText = cardTitles[object.objectClassName] + ' ' + titleText;
+
+ } else if (!toplevel) {
+ titleText = cardTitles[object.objectClassName];
+
+ } else {
+ titleText = 'Response';
+
+ }
+
+ var title = document.createElement('div');
+ title.classList.add('card-header', 'font-weight-bold');
+ title.appendChild(document.createTextNode(titleText));
+ card.appendChild(title);
+
+ var body = document.createElement('div');
+ body.classList.add('card-body');
+
+ body.appendChild(dl);
+
+ card.appendChild(body);
+ return card;
+}
+
+// simplify the process of adding a name => value to a definition list
+export function addProperty(dl, name, value) {
+
+ var dt = document.createElement('dt');
+ dt.classList.add('rdap-property-name');
+ dt.appendChild(document.createTextNode(name));
+ dl.appendChild(dt);
+
+ var dd = document.createElement('dd');
+ dd.classList.add('rdap-property-value');
+ if (value instanceof Node) {
+ dd.appendChild(value);
+
+ } else {
+ dd.appendChild(document.createTextNode(String(value)));
+
+ }
+ dl.appendChild(dd);
+}
+
+// called by the individual object processors, since all RDAP objects have a similar set of
+// properties. the first argument is the RDAP object and the second is the