Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gbicann committed Oct 29, 2024
2 parents 604090f + a8ede42 commit 9327f68
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 61 deletions.
232 changes: 179 additions & 53 deletions assets/spa.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ rdapValidator.setTestCompleteCallback(function() {
window.history.pushState(null, window.title, url.href);

document.getElementById("tree").appendChild(jsonToHTML(rdapValidator.lastTestedResponse, "response-$"));

if (canReport()) {
document.getElementById("report-button").disabled = false;
}
});

function jsonToHTML(value, path, objectIsReallyArray) {
Expand All @@ -31,6 +35,7 @@ function jsonToHTML(value, path, objectIsReallyArray) {
const k = Object.keys(value).at(i);

const details = div.appendChild(document.createElement("details"));
details.open = false;

const summary = jsonToHTML(true === objectIsReallyArray ? parseInt(k) : k);
summary.classList.add("json-key");
Expand Down Expand Up @@ -104,6 +109,65 @@ function scrollParentToChild(parent, child) {

}

function JSONPathParent(path) {
if (0 === path.length) {
return undefined;
}

switch(path.charAt(path.length-1)) {
case '$':
return undefined;

case ']':
return path.replace(/\[\d+\]$/, '');

default:
return path.replace(/\.[^\.]+$/, '');
}
}

function expand(el) {
if ("details" == el.localName) {
el.open = true;
}
el.childNodes.forEach(expand);
}

function reveal(el) {
if (el instanceof HTMLElement) {
if ("details" == el.localName) {
el.open = true;

} else if ("body" === el.localName) {
return;

}

reveal(el.parentNode);
}
}

function clickFunction() {

document.getElementById("result-container").removeAttribute("hidden");

Array.from(document.getElementById("results").childNodes).forEach((e) => e.parentNode.removeChild(e));
Array.from(document.getElementById("tree").childNodes).forEach((e) => e.parentNode.removeChild(e));

rdapValidator.testURL(
document.getElementById("url").value,
document.getElementById("response-type").value,
document.getElementById("server-type").value
);
};

function canReport() {
return (
"domain" === rdapValidator.lastTestedResponseType &&
["vanilla", "gtld-registry", "gtld-registrar"].includes(rdapValidator.lastTestedServerType)
);
};

rdapValidator.setResultCallback(function(result, message, path, ref) {

if (false !== result && document.getElementById("errors-only").checked) return;
Expand Down Expand Up @@ -162,58 +226,6 @@ rdapValidator.setResultCallback(function(result, message, path, ref) {
}
});

function JSONPathParent(path) {
if (0 === path.length) {
return undefined;
}

switch(path.charAt(path.length-1)) {
case '$':
return undefined;

case ']':
return path.replace(/\[\d+\]$/, '');

default:
return path.replace(/\.[^\.]+$/, '');
}
}

function expand(el) {
if ("details" == el.localName) {
el.open = true;
}
el.childNodes.forEach(expand);
}

function reveal(el) {
if (el instanceof HTMLElement) {
if ("details" == el.localName) {
el.open = true;

} else if ("body" === el.localName) {
return;

}

reveal(el.parentNode);
}
}

function clickFunction() {

document.getElementById("result-container").removeAttribute("hidden");

Array.from(document.getElementById("results").childNodes).forEach((e) => e.parentNode.removeChild(e));
Array.from(document.getElementById("tree").childNodes).forEach((e) => e.parentNode.removeChild(e));

rdapValidator.testURL(
document.getElementById("url").value,
document.getElementById("response-type").value,
document.getElementById("server-type").value
);
};

const responseTypeSelect = document.getElementById("response-type");

Object.keys(rdapValidator.responseTypes).forEach(function(type) {
Expand Down Expand Up @@ -255,4 +267,118 @@ let doTest = false;
}
});

if (doTest) document.getElementById("button").click();
const button = document.getElementById("button");

button.disabled = false;

if (doTest) button.click();

const sendEmailTo = function(entity) {
let lastTestedURL = rdapValidator.testedURL;

let email;

try {
lastTestedURL = rdapValidator.lastTestedResponse.links.filter(l => "self" == l.rel && "application/rdap+json" == l.type).shift().href;

email = entity.vcardArray[1].filter(p => "EMAIL" === p[0].toUpperCase()).shift()[3];

} catch (e) {
alert(`Unable to extract URL and/or email address: ${e}`);

}

const url = new URL("mailto:"+email);

let subject, body;

if (rdapValidator.errors < 1) {
subject = 'No issues with your RDAP server';
body = [
"Hey there, I tested your RDAP server using the RDAP Validator at this URL:",
"",
document.location.href,
"",
"And everything looks fine! Thanks for your care and attention.",
"",
];

} else {
subject = `I found ${self.errors} error(s) with your RDAP server`;

body = [
"***NOTE TO SENDER: PLEASE BE POLITE!***",
"",
"Hey there, I found an issue with your RDAP server using the RDAP Validator at this URL:",
"",
document.location.href,
"",
`Tested URL: ${lastTestedURL}`,
`Response Type: ${rdapValidator.responseTypes[rdapValidator.lastTestedResponseType]}`,
`Server Type: ${rdapValidator.serverTypes[rdapValidator.lastTestedServerType]}`,
"",
"List of errors:",
"",
];

rdapValidator.log.forEach(function(msg) {
if (false === msg[0]) {
body.push(`Error: ${msg[1]}`);
if ("$" !== msg[2]) body.push(`JSON Path: ${msg[2]}`);
if (msg[3]) body.push(`Reference: ${msg[3]}`);
body.push("");
}
});

body.push("Server response:", "");

Object.keys(rdapValidator.lastTestedResponseHeaders).forEach(function(k) {
body.push(k + ": " + rdapValidator.lastTestedResponseHeaders[k]);
});
body.push("");
body = body.concat(JSON.stringify(rdapValidator.lastTestedResponse, null, " ").split("\n"));

}

subject = escape(subject);
body = escape(body.join("\n"));

url.search = `?subject=${subject}&body=${body}`;

const iframe = document.createElement('iframe');
iframe.setAttribute('src', url.toString());
iframe.style.setProperty('display', 'none');

document.body.appendChild(iframe);
};

document.getElementById("report-button").addEventListener("click", function() {
if (canReport()) {
if (["vanilla", "gtld-registry"].includes(rdapValidator.lastTestedServerType)) {
const tld = rdapValidator.lastTestedObject.split(".").pop();
fetch(`https://rdap.iana.org/domain/${tld}`).then(
res => res.json().then(function (record) {
try {
const entity = record.entities.filter(e => e.roles.includes("technical")).shift();
sendEmailTo(entity);

} catch (e) {
console.log(e);

}
})
);
} else if ("gtld-registrar" === rdapValidator.lastTestedServerType) {
try {
const rar = rdapValidator.lastTestedResponse.entities.filter(e => e.roles.includes("registrar")).shift();
const gurid = rar.publicIds.filter(id => "IANA Registrar ID" === id.type).shift().identifier;

fetch(`https://registrars.rdap.org/entity/${gurid}-iana`).then(res => res.json().then(entity => sendEmailTo(entity)));

} catch (e) {
console.log(e);

}
}
}
});
5 changes: 4 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@

<br>

<p><input class="btn btn-secondary" id="button" type="button" value="Test"></p>
<p>
<input class="btn btn-secondary" id="button" type="button" value="Test" disabled>
<input class="btn btn-secondary" id="report-button" type="button" value="Report..." disabled title="Send a copy of this report to the registry/registrar...">
</p>
</form>

<div id="result-container" hidden>
Expand Down
41 changes: 34 additions & 7 deletions lib/rdap-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ self.version = '0.0.1';
self.testURL = function(url, type, serverType) {

self.errors = 0;
self.log = [];

if (!self.responseTypes.hasOwnProperty(type)) {
self.add(false, "Invalid response type '" + type + "'.");
Expand All @@ -37,6 +38,7 @@ self.testURL = function(url, type, serverType) {
self.lastTestedURL = url;
self.lastTestedResponseType = type;
self.lastTestedServerType = serverType;
self.lastTestedObject = null;

self.msg("Sending request...");

Expand Down Expand Up @@ -138,6 +140,8 @@ self.validateResponse = function(record, url, type, serverType) {

name = self.nameFromPath(url);

self.lastTestedObject = name;

switch (serverType) {
case "gtld-registry": self.validateGTLDRegistryDomain(record, name); break;
case "gtld-registrar": self.validateGTLDRegistrarDomain(record, name); break;
Expand All @@ -151,6 +155,8 @@ self.validateResponse = function(record, url, type, serverType) {

name = self.nameFromPath(url);

self.lastTestedObject = name;

switch (serverType) {
case "gtld-registry": self.validateGTLDNameserver(record, name); break;
case "rir": self.validateRIRNameserver(record, name); break;
Expand All @@ -163,6 +169,8 @@ self.validateResponse = function(record, url, type, serverType) {

const handle = decodeURI((new URL(url)).pathname.split("/").pop());

self.lastTestedObject = handle;

switch (serverType) {
case "gtld-registry": self.validateGTLDEntity(record, handle); break;
case "rir": self.validateRIREntity(record, handle); break;
Expand Down Expand Up @@ -1710,8 +1718,8 @@ self.validateGTLDRegistrarDomain = function(domain, name) {
self.pushPath(".entities");

const rant = (
domain.hasOwnProperty("entities") && self.isArray(domain.entities)
? domain.entities : []
domain.hasOwnProperty("entities") && self.isArray(domain.entities)
? domain.entities : []
).filter((e) =>
self.isObject(e) &&
e.hasOwnProperty("roles") &&
Expand Down Expand Up @@ -2004,7 +2012,12 @@ self.validateGTLDRegistrarEntity = function(rar) {
rar.hasOwnProperty("publicIds"),
"The registrar entity MUST have the 'publicIds' property.",
"page=4",
)) return;
)) {
self.popPath(".publicIds");
return;
}

self.popPath(".publicIds");

self.pushPath("[?('IANA Registrar ID' == @.type)][0]");

Expand All @@ -2016,7 +2029,10 @@ self.validateGTLDRegistrarEntity = function(rar) {
1 === ids.length,
"The registrar entity MUST have exactly one Public ID object with the '" + type + "' type.",
"page=4",
)) return;
)) {
self.popPath(".type");
return;
}

self.popPath(".type");

Expand All @@ -2036,7 +2052,7 @@ self.validateGTLDRegistrarEntity = function(rar) {

self.popPath(".identifier");

self.popPath();
self.popPath("[?('IANA Registrar ID' == @.type)][0]");

self.msg("This tool does not validate the IANA Registrar ID, please refer to https://www.iana.org/assignments/registrar-ids/registrar-ids.xhtml.");

Expand Down Expand Up @@ -2312,6 +2328,7 @@ self.pushPath = function (segment) {
self.popPath = function(last) {
if (last !== undefined && last !== self.path[self.path.length - 1]) {
console.warn("WARNING: last item in path is not '" + last + "'");
new Error().stack.split("\n").slice(1).forEach(l => console.warn(l));
}

self.path.pop();
Expand Down Expand Up @@ -2731,11 +2748,21 @@ self.setTestCompleteCallback = function(callback) {
self.add = function(result, message, ref) {
if (false === result) self.errors++;

const path = self.getPath();
const refURL = null === result ? null : self.ref(ref);

self.log.push([
result,
message,
path,
refURL,
]);

self.resultCallback(
result,
message,
self.getPath(),
null === result ? null : self.ref(ref),
path,
refURL,
);

return result;
Expand Down

0 comments on commit 9327f68

Please sign in to comment.