const toolButtons = document.querySelectorAll(".tool-button"); const panels = document.querySelectorAll(".panel"); document.addEventListener("click", async (event) => { const button = event.target.closest("[data-copy-value]"); if (!button) { return; } const value = button.dataset.copyValue || ""; const originalLabel = button.textContent; try { await copyText(value); button.textContent = "Copied"; button.classList.add("copied"); setTimeout(() => { button.textContent = originalLabel; button.classList.remove("copied"); }, 1500); } catch (error) { button.textContent = "Copy failed"; setTimeout(() => { button.textContent = originalLabel; }, 1500); } }); toolButtons.forEach((button) => { button.addEventListener("click", () => { const target = button.dataset.tool; toolButtons.forEach((item) => item.classList.remove("active")); panels.forEach((panel) => panel.classList.remove("active")); button.classList.add("active"); document.getElementById(target).classList.add("active"); }); }); document.getElementById("tls-form").addEventListener("submit", async (event) => { event.preventDefault(); const form = new FormData(event.currentTarget); const action = event.submitter?.value || "generate"; await submitJSON("/api/tls/generate", { commonName: form.get("commonName"), organization: form.get("organization"), organizationalUnit: form.get("organizationalUnit"), locality: form.get("locality"), state: form.get("state"), country: form.get("country"), dnsNames: form.get("dnsNames"), validDays: Number(form.get("validDays")), keySize: Number(form.get("keySize")), }, renderTLSResult, document.getElementById("tls-result"), (data) => { if (action === "download") { downloadBase64File(data.zipBase64, data.zipFilename || "tls-materials.zip", "application/zip"); } }); }); document.getElementById("dns-form").addEventListener("submit", async (event) => { event.preventDefault(); const form = new FormData(event.currentTarget); await submitJSON("/api/dns/lookup", { host: form.get("host"), }, renderDNSResult, document.getElementById("dns-result")); }); document.getElementById("ssl-form").addEventListener("submit", async (event) => { event.preventDefault(); const form = new FormData(event.currentTarget); await submitJSON("/api/ssl/check", { url: form.get("url"), }, renderSSLResult, document.getElementById("ssl-result")); }); document.getElementById("pem-form").addEventListener("submit", async (event) => { event.preventDefault(); const form = new FormData(event.currentTarget); await submitJSON("/api/pem/check", { pem: form.get("pem"), }, renderPEMResult, document.getElementById("pem-result")); }); async function submitJSON(url, payload, renderer, target, onSuccess) { setLoading(target); try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(payload), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Request failed"); } target.classList.remove("empty", "error"); target.innerHTML = renderer(data); if (onSuccess) { onSuccess(data); } } catch (error) { target.classList.remove("empty"); target.classList.add("error"); target.textContent = error.message; } } function setLoading(target) { target.classList.remove("error"); target.classList.add("empty"); target.textContent = "Working..."; } function renderTLSResult(data) { return ` ${renderMetaGrid([ ["Subject", escapeHTML(data.subject)], ["Issuer", escapeHTML(data.issuer)], ["Serial Number", escapeHTML(data.serialNumber)], ["Valid From", escapeHTML(data.notBefore)], ["Valid Until", escapeHTML(data.notAfter)], ["Certificate Type", escapeHTML(data.isSelfSigned ? "Self-Signed" : "Signed")], ["Key Size", escapeHTML(`${data.keySize || ""}-bit RSA`)], ["Organization", escapeHTML((data.organization || []).join(", "))], ["OU", escapeHTML((data.ou || []).join(", "))], ["Locality", escapeHTML((data.locality || []).join(", "))], ["State / Province", escapeHTML((data.state || []).join(", "))], ["Country", escapeHTML((data.country || []).join(", "))], ["DNS Names", escapeHTML((data.dnsNames || []).join(", "))], ])} ${renderCopyablePEMBlock("Public Key PEM", data.publicKeyPem)} ${renderCopyablePEMBlock("Certificate Signing Request", data.csrPem)} ${renderCopyablePEMBlock("Self-Signed Certificate PEM", data.selfSignedCertificatePem || data.certificatePem)} ${renderCopyablePEMBlock("Private Key PEM", data.privateKeyPem)} `; } function renderDNSResult(data) { return ` ${renderMetaGrid([ ["Host", escapeHTML(data.host)], ["CNAME", escapeHTML(data.cname || "None")], ])} ${renderListBlock("A / AAAA", data.ips)} ${renderListBlock("TXT", data.txt)} ${renderListBlock("NS", data.ns)} ${renderListBlock("MX", (data.mx || []).map((record) => `${record.host} (pref ${record.pref})`))} ${renderErrorBlock(data.errors)} `; } function renderSSLResult(data) { const leaf = (data.chain || [])[0] || {}; return ` ${renderMetaGrid([ ["Requested URL", escapeHTML(data.url)], ["Server Name", escapeHTML(data.serverName)], ["TLS Version", escapeHTML(data.version)], ["Cipher Suite", escapeHTML(data.cipherSuite)], ["ALPN", escapeHTML(data.negotiatedProtocol || "None")], ["Leaf Subject", escapeHTML(leaf.subject || "")], ["Leaf Issuer", escapeHTML(leaf.issuer || "")], ["Leaf Valid Until", escapeHTML(leaf.notAfter || "")], ])}
${escapeHTML(JSON.stringify(data.chain, null, 2))}
${escapeHTML(data.certificatePem)}
${escapeHTML(value || "")}
No records returned.
"}