From e5195ba1f19a3e2ae597e8a11ad314f457c9773a Mon Sep 17 00:00:00 2001 From: dwindown Date: Fri, 1 Aug 2025 23:13:52 +0700 Subject: [PATCH] Initial commit: DNS Things - Comprehensive DNS utility website Features implemented: - Modular JavaScript architecture (theme.js, dns-tools.js, whois.js, punycode.js, ip-tools.js, main.js) - Responsive design with dark/light theme toggle - DNS Lookup and Reverse DNS Lookup tools - Whois Lookup functionality - IDN Punycode Converter with full Unicode support - Comprehensive IP Address Tools (validation, IPv4-to-IPv6 mapping, IPv6 compression/expansion) - Dynamic tab descriptions that change based on active tool - Mobile-responsive horizontal scrollable tabs - Copy-to-clipboard functionality for all results - Clean footer with dynamic year - IPv4-mapped IPv6 address explanation with clear warnings Technical improvements: - Separated concerns with modular JS files - Fixed browser compatibility issues with punycode library - Implemented proper error handling and user feedback - Added comprehensive input validation - Optimized for mobile devices with touch-friendly UI --- assets/css/main.css | 231 ++++++++++++++++++++++ assets/img/hero.webp | Bin 0 -> 76062 bytes assets/js/dns-tools.js | 262 ++++++++++++++++++++++++ assets/js/ip-tools.js | 437 +++++++++++++++++++++++++++++++++++++++++ assets/js/main.js | 33 ++++ assets/js/punycode.js | 176 +++++++++++++++++ assets/js/theme.js | 197 +++++++++++++++++++ assets/js/whois.js | 196 ++++++++++++++++++ index.html | 292 +++++++++++++++++++++++++++ 9 files changed, 1824 insertions(+) create mode 100644 assets/css/main.css create mode 100644 assets/img/hero.webp create mode 100644 assets/js/dns-tools.js create mode 100644 assets/js/ip-tools.js create mode 100644 assets/js/main.js create mode 100644 assets/js/punycode.js create mode 100644 assets/js/theme.js create mode 100644 assets/js/whois.js create mode 100644 index.html diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 0000000..ce93806 --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1,231 @@ +/* DNS Things - Main Styles */ + +/* Custom Tailwind Configuration */ +.tab-btn.active { + @apply bg-indigo-600 text-white shadow-md; +} + +.tab-content { + display: none; +} + +.tab-content.active { + display: block; +} + +/* Custom scrollbar for dark mode */ +.dark ::-webkit-scrollbar { + width: 8px; +} + +.dark ::-webkit-scrollbar-track { + background: #374151; +} + +.dark ::-webkit-scrollbar-thumb { + background: #6b7280; + border-radius: 4px; +} + +.dark ::-webkit-scrollbar-thumb:hover { + background: #9ca3af; +} + +/* Hero section adjustments */ +.hero-section { + min-height: 60vh; +} + +/* DNS Tools section */ +.dns-tools-section { + min-height: 70vh; +} + +/* Tab navigation */ +.tab-navigation { + min-width: 200px; +} + +/* Results styling */ +.dns-result-item { + transition: all 0.2s ease-in-out; +} + +.dns-result-item:hover { + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.dark .dns-result-item:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +/* Copy button animations */ +.copy-btn { + transition: all 0.2s ease-in-out; +} + +.copy-btn:hover { + transform: scale(1.05); +} + +/* Loading animations */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.loading-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .tab-navigation { + min-width: auto; + width: 100%; + } + + .hero-section { + min-height: 50vh; + } + + .dns-tools-section { + min-height: auto; + } +} + +/* Mobile Tab Navigation - Horizontal Scrollable */ +@media (max-width: 767px) { + /* Main container becomes vertical stack */ + .flex.flex-col.md\:flex-row.gap-8 { + flex-direction: column !important; + gap: 1rem !important; + } + + /* Tab container takes full width */ + .w-full.md\:w-1\/3.lg\:w-1\/4 { + width: 100% !important; + margin-bottom: 1rem; + order: 1; + } + + /* Content area takes full width */ + .w-full.md\:w-2\/3.lg\:w-3\/4 { + width: 100% !important; + order: 2; + } + + /* Tab buttons container becomes horizontal scrollable */ + .flex.flex-col.space-y-2.p-2.bg-gray-50.dark\:bg-gray-700.rounded-lg { + flex-direction: row !important; + overflow-x: auto; + overflow-y: hidden; + padding: 0.75rem !important; + gap: 0.5rem !important; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE/Edge */ + } + + /* Hide scrollbar for webkit browsers */ + .flex.flex-col.space-y-2.p-2.bg-gray-50.dark\:bg-gray-700.rounded-lg::-webkit-scrollbar { + display: none; + } + + /* Tab buttons optimized for mobile */ + .tab-btn { + flex-shrink: 0 !important; + white-space: nowrap !important; + min-width: auto !important; + padding: 0.5rem 1rem !important; + font-size: 0.875rem !important; + text-align: center !important; + margin: 0 !important; + } + + /* Remove space-y utility on mobile */ + .flex.flex-col.space-y-2.p-2.bg-gray-50.dark\:bg-gray-700.rounded-lg > * + * { + margin-top: 0 !important; + } +} + +/* Focus states for accessibility */ +.focus-ring:focus { + outline: 2px solid #6366f1; + outline-offset: 2px; +} + +/* Error and success states */ +.error-state { + border-color: #ef4444; + background-color: #fef2f2; +} + +.dark .error-state { + border-color: #dc2626; + background-color: #7f1d1d; +} + +.success-state { + border-color: #10b981; + background-color: #f0fdf4; +} + +.dark .success-state { + border-color: #059669; + background-color: #064e3b; +} + +/* IP Tools specific styles */ +.ip-validation-result { + max-width: 100%; + word-break: break-all; +} + +/* Subnet calculator grid */ +.subnet-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1rem; +} + +/* Punycode converter styles */ +.punycode-example { + font-family: 'Courier New', monospace; + font-size: 0.875rem; +} + +/* Whois result styles */ +.whois-badge { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; + font-size: 0.75rem; + font-weight: 500; +} + +.whois-badge.ipv4 { + background-color: #dbeafe; + color: #1e40af; +} + +.dark .whois-badge.ipv4 { + background-color: #1e3a8a; + color: #93c5fd; +} + +.whois-badge.ipv6 { + background-color: #e0e7ff; + color: #5b21b6; +} + +.dark .whois-badge.ipv6 { + background-color: #581c87; + color: #c4b5fd; +} diff --git a/assets/img/hero.webp b/assets/img/hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..5f57a6dd90e7a77e5e3776f931d06725db896360 GIT binary patch literal 76062 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 zwNE92P{{=RG(@^W`v7@KkI$5l9gP4000000000000000000000000000000000000 J00000005Dj#=!sp literal 0 HcmV?d00001 diff --git a/assets/js/dns-tools.js b/assets/js/dns-tools.js new file mode 100644 index 0000000..5b05719 --- /dev/null +++ b/assets/js/dns-tools.js @@ -0,0 +1,262 @@ +// DNS Things - DNS Tools Module + +// Initialize IP display functionality +async function initIPDisplay() { + const ipv4Element = document.getElementById('ipv4'); + const ipv6Element = document.getElementById('ipv6'); + + if (!ipv4Element || !ipv6Element) return; + + try { + // Fetch IPv4 + const ipv4Response = await fetch('https://api.ipify.org?format=json'); + const ipv4Data = await ipv4Response.json(); + ipv4Element.textContent = ipv4Data.ip; + } catch (error) { + ipv4Element.textContent = 'Unable to fetch'; + console.error('Error fetching IPv4:', error); + } + + try { + // Fetch IPv6 + const ipv6Response = await fetch('https://api64.ipify.org?format=json'); + const ipv6Data = await ipv6Response.json(); + ipv6Element.textContent = ipv6Data.ip; + } catch (error) { + ipv6Element.textContent = 'Not available'; + console.error('Error fetching IPv6:', error); + } +} + +// Initialize DNS lookup form +function initDNSForm() { + const form = document.getElementById('dns-form'); + const input = document.getElementById('domain-input'); + const results = document.getElementById('dns-results-container'); + const loader = document.getElementById('dns-loader'); + + if (!form || !input || !results || !loader) return; + + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + const domain = input.value.trim(); + if (!domain) return; + + // Show loader + loader.classList.remove('hidden'); + results.innerHTML = ''; + + try { + // DNS record types to query + const recordTypes = ['A', 'AAAA', 'MX', 'TXT', 'NS', 'CNAME', 'SOA', 'PTR', 'SRV']; + + // Create promises for all DNS queries + const queries = recordTypes.map(type => + fetch(`https://dns.google/resolve?name=${encodeURIComponent(domain)}&type=${type}`) + .then(response => response.json()) + .then(data => ({ type, data })) + .catch(error => ({ type, error })) + ); + + // Wait for all queries to complete + const responses = await Promise.all(queries); + + // Group results by record type + const groupedResults = {}; + + responses.forEach(({ type, data, error }) => { + if (error) { + console.error(`Error fetching ${type} records:`, error); + return; + } + + if (data.Answer && data.Answer.length > 0) { + groupedResults[type] = data.Answer.map(record => { + // Clean the record data + let cleanData = record.data; + if (typeof cleanData === 'string') { + cleanData = cleanData.replace(/^"(.*)"$/, '$1').replace(/\.$/, ''); + } + return { + ...record, + data: cleanData + }; + }); + } + }); + + // Display results + if (Object.keys(groupedResults).length === 0) { + results.innerHTML = ` +
+

No DNS records found

+

The domain "${domain}" does not have any DNS records or does not exist.

+
+ `; + } else { + let resultsHTML = '
'; + + Object.entries(groupedResults).forEach(([type, records]) => { + resultsHTML += ` +
+

${type} Records (${records.length})

+
    + `; + + records.forEach(record => { + resultsHTML += ` +
  • + ${record.data} + +
  • + `; + }); + + resultsHTML += '
'; + }); + + resultsHTML += '
'; + results.innerHTML = resultsHTML; + } + } catch (error) { + console.error('DNS lookup error:', error); + results.innerHTML = ` +
+

Error

+

Failed to perform DNS lookup. Please try again.

+
+ `; + } finally { + loader.classList.add('hidden'); + } + }); + + // Auto-submit on paste + input.addEventListener('paste', () => { + setTimeout(() => { + if (input.value.trim()) { + form.dispatchEvent(new Event('submit')); + } + }, 100); + }); +} + +// Initialize reverse DNS lookup form +function initReverseDNSForm() { + const form = document.getElementById('reverse-dns-form'); + const input = document.getElementById('ip-input'); + const results = document.getElementById('reverse-dns-results'); + const loader = document.getElementById('reverse-dns-loader'); + + if (!form || !input || !results || !loader) return; + + // IPv6 reverse DNS helper + function ipv6ToReverseDNS(ipv6) { + // Expand IPv6 to full format + let expanded = ipv6; + if (ipv6.includes('::')) { + const parts = ipv6.split('::'); + const left = parts[0] ? parts[0].split(':') : []; + const right = parts[1] ? parts[1].split(':') : []; + const middle = new Array(8 - left.length - right.length).fill('0000'); + expanded = left.concat(middle).concat(right).join(':'); + } + + // Remove colons and pad each segment to 4 characters + const fullHex = expanded.split(':').map(segment => + segment.padStart(4, '0') + ).join(''); + + // Reverse and add dots + return fullHex.split('').reverse().join('.') + '.ip6.arpa'; + } + + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + const ip = input.value.trim(); + if (!ip) return; + + // Show loader + loader.classList.remove('hidden'); + results.innerHTML = ''; + + try { + let reverseDomain; + + // Check if IPv4 or IPv6 + if (ip.includes(':')) { + // IPv6 + try { + reverseDomain = ipv6ToReverseDNS(ip); + } catch (error) { + throw new Error('Invalid IPv6 address format'); + } + } else { + // IPv4 + const parts = ip.split('.'); + if (parts.length !== 4 || parts.some(part => isNaN(part) || part < 0 || part > 255)) { + throw new Error('Invalid IPv4 address format'); + } + reverseDomain = parts.reverse().join('.') + '.in-addr.arpa'; + } + + // Perform reverse DNS lookup + const response = await fetch(`https://dns.google/resolve?name=${encodeURIComponent(reverseDomain)}&type=PTR`); + const data = await response.json(); + + if (data.Answer && data.Answer.length > 0) { + let resultsHTML = '
'; + data.Answer.forEach(record => { + const hostname = record.data.replace(/\.$/, ''); + resultsHTML += ` +
+
+
Hostname found:
+
${hostname}
+
+ +
+ `; + }); + resultsHTML += '
'; + results.innerHTML = resultsHTML; + } else { + results.innerHTML = ` +
+

No reverse DNS record found

+

The IP address "${ip}" does not have a reverse DNS (PTR) record.

+
+ `; + } + } catch (error) { + console.error('Reverse DNS lookup error:', error); + results.innerHTML = ` +
+

Error

+

${error.message || 'Failed to perform reverse DNS lookup. Please check the IP address format.'}

+
+ `; + } finally { + loader.classList.add('hidden'); + } + }); + + // Auto-submit on paste + input.addEventListener('paste', () => { + setTimeout(() => { + if (input.value.trim()) { + form.dispatchEvent(new Event('submit')); + } + }, 100); + }); +} diff --git a/assets/js/ip-tools.js b/assets/js/ip-tools.js new file mode 100644 index 0000000..7dffafc --- /dev/null +++ b/assets/js/ip-tools.js @@ -0,0 +1,437 @@ +// DNS Things - IP Tools Module + +// IP Tools utility functions +function isValidIPv4(ip) { + const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + return ipv4Regex.test(ip); +} + +function isValidIPv6(ip) { + const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::1$|^::$|^(?:[0-9a-fA-F]{1,4}:)*::(?:[0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4}$/; + return ipv6Regex.test(ip) || /^(?:[0-9a-fA-F]{0,4}:){0,7}[0-9a-fA-F]{0,4}$/.test(ip); +} + +function ipv4ToIPv6(ipv4) { + const parts = ipv4.split('.'); + const hex1 = (parseInt(parts[0]) * 256 + parseInt(parts[1])).toString(16).padStart(4, '0'); + const hex2 = (parseInt(parts[2]) * 256 + parseInt(parts[3])).toString(16).padStart(4, '0'); + return `::ffff:${hex1}:${hex2}`; +} + +function compressIPv6(ipv6) { + // Expand first if compressed + let expanded = expandIPv6(ipv6); + // Then compress by removing leading zeros and consecutive zero groups + let compressed = expanded.replace(/\b0+([0-9a-fA-F]+)/g, '$1'); + // Replace longest sequence of consecutive zero groups with :: + let parts = compressed.split(':'); + let maxZeroStart = -1, maxZeroLength = 0; + let currentZeroStart = -1, currentZeroLength = 0; + + for (let i = 0; i < parts.length; i++) { + if (parts[i] === '0' || parts[i] === '') { + if (currentZeroStart === -1) currentZeroStart = i; + currentZeroLength++; + } else { + if (currentZeroLength > maxZeroLength) { + maxZeroStart = currentZeroStart; + maxZeroLength = currentZeroLength; + } + currentZeroStart = -1; + currentZeroLength = 0; + } + } + + if (currentZeroLength > maxZeroLength) { + maxZeroStart = currentZeroStart; + maxZeroLength = currentZeroLength; + } + + if (maxZeroLength > 1) { + let before = parts.slice(0, maxZeroStart).join(':'); + let after = parts.slice(maxZeroStart + maxZeroLength).join(':'); + compressed = before + '::' + after; + compressed = compressed.replace(/^:/, '').replace(/:$/, ''); + if (compressed === '') compressed = '::'; + } + + return compressed; +} + +function expandIPv6(ipv6) { + if (ipv6.includes('::')) { + let parts = ipv6.split('::'); + let left = parts[0] ? parts[0].split(':') : []; + let right = parts[1] ? parts[1].split(':') : []; + let middle = new Array(8 - left.length - right.length).fill('0000'); + let expanded = left.concat(middle).concat(right); + return expanded.map(part => part.padStart(4, '0')).join(':'); + } + return ipv6.split(':').map(part => part.padStart(4, '0')).join(':'); +} + +function ipv4ToBinary(ipv4) { + return ipv4.split('.').map(octet => + parseInt(octet).toString(2).padStart(8, '0') + ).join('.'); +} + +function ipv4ToDecimal(ipv4) { + const parts = ipv4.split('.'); + return (parseInt(parts[0]) << 24) + (parseInt(parts[1]) << 16) + (parseInt(parts[2]) << 8) + parseInt(parts[3]); +} + +function calculateSubnet(cidr) { + const [ip, prefixLength] = cidr.split('/'); + const prefix = parseInt(prefixLength); + + if (!isValidIPv4(ip) || prefix < 0 || prefix > 32) { + throw new Error('Invalid CIDR notation'); + } + + const ipParts = ip.split('.').map(x => parseInt(x)); + const ipInt = (ipParts[0] << 24) + (ipParts[1] << 16) + (ipParts[2] << 8) + ipParts[3]; + + const subnetMask = (0xFFFFFFFF << (32 - prefix)) >>> 0; + const networkInt = (ipInt & subnetMask) >>> 0; + const broadcastInt = (networkInt | (0xFFFFFFFF >>> prefix)) >>> 0; + + const networkIP = [ + (networkInt >>> 24) & 0xFF, + (networkInt >>> 16) & 0xFF, + (networkInt >>> 8) & 0xFF, + networkInt & 0xFF + ].join('.'); + + const broadcastIP = [ + (broadcastInt >>> 24) & 0xFF, + (broadcastInt >>> 16) & 0xFF, + (broadcastInt >>> 8) & 0xFF, + broadcastInt & 0xFF + ].join('.'); + + const subnetMaskIP = [ + (subnetMask >>> 24) & 0xFF, + (subnetMask >>> 16) & 0xFF, + (subnetMask >>> 8) & 0xFF, + subnetMask & 0xFF + ].join('.'); + + const totalHosts = Math.pow(2, 32 - prefix); + const usableHosts = totalHosts > 2 ? totalHosts - 2 : totalHosts; + + return { + network: networkIP, + broadcast: broadcastIP, + subnetMask: subnetMaskIP, + totalHosts, + usableHosts, + prefix + }; +} + +// Initialize IP Tools +function initIPTools() { + // IP Validation + const ipValidateInput = document.getElementById('ip-validate-input'); + const ipValidateBtn = document.getElementById('ip-validate-btn'); + const ipValidateResult = document.getElementById('ip-validate-result'); + + const validateIP = () => { + const input = ipValidateInput.value.trim(); + if (!input) { + ipValidateResult.innerHTML = ''; + return; + } + + const isIPv4 = isValidIPv4(input); + const isIPv6 = isValidIPv6(input); + + if (isIPv4) { + ipValidateResult.innerHTML = ` +
+
+
+
✅ Valid IPv4 Address
+
+
Type: IPv4
+
Address: ${input}
+
Binary: ${ipv4ToBinary(input)}
+
Decimal: ${ipv4ToDecimal(input)}
+
+
+ +
+
+ `; + } else if (isIPv6) { + const compressed = compressIPv6(input); + const expanded = expandIPv6(input); + ipValidateResult.innerHTML = ` +
+
+
+
✅ Valid IPv6 Address
+
+
Type: IPv6
+
Compressed: ${compressed}
+
Expanded: ${expanded}
+
+
+ +
+
+ `; + } else { + ipValidateResult.innerHTML = ` +
+
❌ Invalid IP Address
+

Please enter a valid IPv4 or IPv6 address.

+
+ `; + } + }; + + if (ipValidateBtn && ipValidateInput) { + ipValidateBtn.addEventListener('click', validateIP); + ipValidateInput.addEventListener('input', () => { + clearTimeout(ipValidateInput.timeout); + ipValidateInput.timeout = setTimeout(validateIP, 500); + }); + } + + // IPv4 to IPv6 Mapping + const ipv4ToIPv6Input = document.getElementById('ipv4-to-ipv6-input'); + const ipv4ToIPv6Btn = document.getElementById('ipv4-to-ipv6-btn'); + const ipv4ToIPv6Result = document.getElementById('ipv4-to-ipv6-result'); + + const convertIPv4ToIPv6 = () => { + const input = ipv4ToIPv6Input.value.trim(); + if (!input) { + ipv4ToIPv6Result.innerHTML = ''; + return; + } + + if (isValidIPv4(input)) { + const ipv6 = ipv4ToIPv6(input); + // Escape the IPv6 address for safe HTML insertion + const escapedIPv6 = ipv6.replace(/'/g, '''); + ipv4ToIPv6Result.innerHTML = ` +
+
+
+
IPv6 Mapped Address:
+
${escapedIPv6}
+

✅ IPv4-mapped IPv6 address for ${input}

+
+

⚠️ Important:

+

This is NOT your actual IPv6 address! This is a special technical format that represents your IPv4 address (${input}) in IPv6 notation.

+

Your real IPv6 address is shown in the "Your IP Address" section above and is completely different.

+

Use case: IPv4-mapped IPv6 addresses are used for network programming and IPv4/IPv6 compatibility.

+
+
+ +
+
+ `; + } else { + ipv4ToIPv6Result.innerHTML = ` +
+
Error:
+

Please enter a valid IPv4 address.

+
+ `; + } + }; + + if (ipv4ToIPv6Btn && ipv4ToIPv6Input) { + ipv4ToIPv6Btn.addEventListener('click', convertIPv4ToIPv6); + ipv4ToIPv6Input.addEventListener('input', () => { + clearTimeout(ipv4ToIPv6Input.timeout); + ipv4ToIPv6Input.timeout = setTimeout(convertIPv4ToIPv6, 500); + }); + } + + // IPv6 Compression/Expansion + const ipv6CompressInput = document.getElementById('ipv6-compress-input'); + const ipv6CompressBtn = document.getElementById('ipv6-compress-btn'); + const ipv6CompressResult = document.getElementById('ipv6-compress-result'); + + const processIPv6 = () => { + const input = ipv6CompressInput.value.trim(); + if (!input) { + ipv6CompressResult.innerHTML = ''; + return; + } + + if (isValidIPv6(input)) { + const compressed = compressIPv6(input); + const expanded = expandIPv6(input); + ipv6CompressResult.innerHTML = ` +
+
+
+
Compressed Form:
+
+
${compressed}
+ +
+
+
+
Expanded Form:
+
+
${expanded}
+ +
+
+
+
+ `; + } else { + ipv6CompressResult.innerHTML = ` +
+
Error:
+

Please enter a valid IPv6 address.

+
+ `; + } + }; + + if (ipv6CompressBtn && ipv6CompressInput) { + ipv6CompressBtn.addEventListener('click', processIPv6); + ipv6CompressInput.addEventListener('input', () => { + clearTimeout(ipv6CompressInput.timeout); + ipv6CompressInput.timeout = setTimeout(processIPv6, 500); + }); + } + + // IP to Binary/Decimal + const ipBinaryInput = document.getElementById('ip-binary-input'); + const ipBinaryBtn = document.getElementById('ip-binary-btn'); + const ipBinaryResult = document.getElementById('ip-binary-result'); + + const convertIPToBinary = () => { + const input = ipBinaryInput.value.trim(); + if (!input) { + ipBinaryResult.innerHTML = ''; + return; + } + + if (isValidIPv4(input)) { + const binary = ipv4ToBinary(input); + const decimal = ipv4ToDecimal(input); + ipBinaryResult.innerHTML = ` +
+
+
+
Binary Representation:
+
+
${binary}
+ +
+
+
+
Decimal Representation:
+
+
${decimal}
+ +
+
+
+
+ `; + } else { + ipBinaryResult.innerHTML = ` +
+
Error:
+

Please enter a valid IPv4 address.

+
+ `; + } + }; + + if (ipBinaryBtn && ipBinaryInput) { + ipBinaryBtn.addEventListener('click', convertIPToBinary); + ipBinaryInput.addEventListener('input', () => { + clearTimeout(ipBinaryInput.timeout); + ipBinaryInput.timeout = setTimeout(convertIPToBinary, 500); + }); + } + + // Subnet Calculator + const subnetInput = document.getElementById('subnet-input'); + const subnetBtn = document.getElementById('subnet-btn'); + const subnetResult = document.getElementById('subnet-result'); + + const calculateSubnetInfo = () => { + const input = subnetInput.value.trim(); + if (!input) { + subnetResult.innerHTML = ''; + return; + } + + try { + const subnet = calculateSubnet(input); + subnetResult.innerHTML = ` +
+
Subnet Information:
+
+
+
Network Address: ${subnet.network}
+
Broadcast Address: ${subnet.broadcast}
+
Subnet Mask: ${subnet.subnetMask}
+
+
+
Prefix Length: /${subnet.prefix}
+
Total Hosts: ${subnet.totalHosts.toLocaleString()}
+
Usable Hosts: ${subnet.usableHosts.toLocaleString()}
+
+
+
+ `; + } catch (error) { + subnetResult.innerHTML = ` +
+
Error:
+

${error.message}

+
+ `; + } + }; + + if (subnetBtn && subnetInput) { + subnetBtn.addEventListener('click', calculateSubnetInfo); + subnetInput.addEventListener('input', () => { + clearTimeout(subnetInput.timeout); + subnetInput.timeout = setTimeout(calculateSubnetInfo, 500); + }); + } +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..9aabeec --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,33 @@ +// DNS Things - Main Application Initialization + +// Initialize everything when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + // Initialize core UI components + initTheme(); + initTabs(); + initCopyButtons(); + + // Initialize DNS tools + initIPDisplay(); + initDNSForm(); + initReverseDNSForm(); + + // Initialize additional tools + initWhoisForm(); + initPunycodeConverter(); + initIPTools(); + + // Set dynamic year in footer + initFooter(); + + console.log('DNS Things application initialized successfully'); +}); + +// Initialize footer with dynamic year +function initFooter() { + const yearElement = document.getElementById('current-year'); + if (yearElement) { + const currentYear = new Date().getFullYear(); + yearElement.textContent = currentYear; + } +} diff --git a/assets/js/punycode.js b/assets/js/punycode.js new file mode 100644 index 0000000..f708cf4 --- /dev/null +++ b/assets/js/punycode.js @@ -0,0 +1,176 @@ +// DNS Things - Punycode Module + +// Real Punycode conversion functions using punycode.js library +function toPunycode(domain) { + try { + // Check if punycode library is available + if (typeof punycode === 'undefined') { + throw new Error('Punycode library not loaded'); + } + + // Split domain into parts and convert each part + const parts = domain.split('.'); + const convertedParts = parts.map(part => { + // Check if part contains non-ASCII characters + if (/[^\x00-\x7F]/.test(part)) { + return punycode.toASCII(part); + } + return part; + }); + + return convertedParts.join('.'); + } catch (error) { + // Fallback to URL API if punycode library fails + try { + const url = new URL(`http://${domain}`); + return url.hostname; + } catch { + throw new Error('Invalid domain format'); + } + } +} + +function fromPunycode(domain) { + try { + // Check if domain contains punycode + if (!domain.includes('xn--')) { + return domain; // No punycode to convert + } + + // Check if punycode library is available + if (typeof punycode === 'undefined') { + throw new Error('Punycode library not loaded'); + } + + // Split domain into parts and convert each part + const parts = domain.split('.'); + const convertedParts = parts.map(part => { + if (part.startsWith('xn--')) { + try { + return punycode.toUnicode(part); + } catch { + return part; // Return original if conversion fails + } + } + return part; + }); + + return convertedParts.join('.'); + } catch (error) { + throw new Error('Invalid punycode format'); + } +} + +// Initialize IDN Punycode Converter +function initPunycodeConverter() { + const unicodeInput = document.getElementById('unicode-input'); + const punycodeInput = document.getElementById('punycode-input'); + const unicodeToPunycodeBtn = document.getElementById('unicode-to-punycode-btn'); + const punycodeToUnicodeBtn = document.getElementById('punycode-to-unicode-btn'); + const punycodeResult = document.getElementById('punycode-result'); + const unicodeResult = document.getElementById('unicode-result'); + + if (!unicodeInput || !punycodeInput) return; + + // Unicode to Punycode conversion + const convertUnicodeToPunycode = () => { + const input = unicodeInput.value.trim(); + if (!input) { + punycodeResult.innerHTML = ''; + return; + } + + try { + const converted = toPunycode(input); + const isConverted = converted !== input; + + punycodeResult.innerHTML = ` +
+
+
+
Punycode Result:
+
${converted}
+ ${isConverted ? '

✅ Conversion applied

' : '

ℹ️ No conversion needed (ASCII only)

'} +
+ +
+
+ `; + } catch (error) { + punycodeResult.innerHTML = ` +
+
Error:
+

${error.message}

+
+ `; + } + }; + + // Punycode to Unicode conversion + const convertPunycodeToUnicode = () => { + const input = punycodeInput.value.trim(); + if (!input) { + unicodeResult.innerHTML = ''; + return; + } + + try { + const converted = fromPunycode(input); + const isConverted = converted !== input; + + unicodeResult.innerHTML = ` +
+
+
+
Unicode Result:
+
${converted}
+ ${isConverted ? '

✅ Conversion applied

' : '

ℹ️ No conversion needed (no punycode found)

'} +
+ +
+
+ `; + } catch (error) { + unicodeResult.innerHTML = ` +
+
Error:
+

${error.message}

+
+ `; + } + }; + + // Event listeners + unicodeToPunycodeBtn.addEventListener('click', convertUnicodeToPunycode); + punycodeToUnicodeBtn.addEventListener('click', convertPunycodeToUnicode); + + // Auto-convert on input (with debounce) + let unicodeTimeout, punycodeTimeout; + + unicodeInput.addEventListener('input', () => { + clearTimeout(unicodeTimeout); + unicodeTimeout = setTimeout(convertUnicodeToPunycode, 500); + }); + + punycodeInput.addEventListener('input', () => { + clearTimeout(punycodeTimeout); + punycodeTimeout = setTimeout(convertPunycodeToUnicode, 500); + }); + + // Paste support + unicodeInput.addEventListener('paste', () => { + setTimeout(convertUnicodeToPunycode, 100); + }); + + punycodeInput.addEventListener('paste', () => { + setTimeout(convertPunycodeToUnicode, 100); + }); +} diff --git a/assets/js/theme.js b/assets/js/theme.js new file mode 100644 index 0000000..a8a7e8f --- /dev/null +++ b/assets/js/theme.js @@ -0,0 +1,197 @@ +// DNS Things - Theme and UI Utilities + +// Theme toggle functionality +function initTheme() { + const themeToggleBtn = document.getElementById('theme-toggle'); + const lightIcon = document.getElementById('theme-toggle-light-icon'); + const darkIcon = document.getElementById('theme-toggle-dark-icon'); + + if (!themeToggleBtn || !lightIcon || !darkIcon) return; + + // Check for saved theme preference or default to system preference + const savedTheme = localStorage.getItem('theme'); + const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + let currentTheme = savedTheme || (systemPrefersDark ? 'dark' : 'light'); + + // Apply initial theme + if (currentTheme === 'dark') { + document.documentElement.classList.add('dark'); + lightIcon.classList.add('hidden'); + darkIcon.classList.remove('hidden'); + } else { + document.documentElement.classList.remove('dark'); + lightIcon.classList.remove('hidden'); + darkIcon.classList.add('hidden'); + } + + // Toggle theme function + function toggleTheme() { + if (document.documentElement.classList.contains('dark')) { + document.documentElement.classList.remove('dark'); + lightIcon.classList.remove('hidden'); + darkIcon.classList.add('hidden'); + localStorage.setItem('theme', 'light'); + } else { + document.documentElement.classList.add('dark'); + lightIcon.classList.add('hidden'); + darkIcon.classList.remove('hidden'); + localStorage.setItem('theme', 'dark'); + } + } + + themeToggleBtn.addEventListener('click', toggleTheme); +} + +// Tab descriptions for dynamic updates +const tabDescriptions = { + 'dns-lookup-tab': 'Perform DNS lookups to resolve domain names and check DNS records', + 'reverse-dns-tab': 'Find domain names associated with IP addresses using reverse DNS', + 'whois-tab': 'Get detailed registration and ownership information for domains and IPs', + 'punycode-tab': 'Convert international domain names between Unicode and Punycode formats', + 'ip-tools-tab': 'Comprehensive IP address utilities including validation, conversion, and analysis' +}; + +// Tab switching functionality +function initTabs() { + const tabButtons = document.querySelectorAll('.tab-btn'); + const tabContents = document.querySelectorAll('.tab-content'); + const descriptionElement = document.querySelector('p.text-lg.text-gray-500.mt-2'); + + tabButtons.forEach(button => { + button.addEventListener('click', () => { + const targetTab = button.getAttribute('data-tab'); + + // Remove active class from all buttons and contents + tabButtons.forEach(btn => { + btn.classList.remove('active', 'text-indigo-600', 'dark:text-indigo-400', 'bg-white', 'dark:bg-gray-800', 'shadow'); + btn.classList.add('text-gray-600', 'dark:text-gray-300', 'hover:bg-white', 'hover:dark:bg-gray-800/50'); + }); + tabContents.forEach(content => { + content.classList.remove('active'); + content.classList.add('hidden'); + }); + + // Add active class to clicked button and show corresponding content + button.classList.remove('text-gray-600', 'dark:text-gray-300', 'hover:bg-white', 'hover:dark:bg-gray-800/50'); + button.classList.add('active', 'text-indigo-600', 'dark:text-indigo-400', 'bg-white', 'dark:bg-gray-800', 'shadow'); + + const targetContent = document.getElementById(targetTab); + if (targetContent) { + targetContent.classList.remove('hidden'); + targetContent.classList.add('active'); + } + + // Update description text + if (descriptionElement && tabDescriptions[targetTab]) { + descriptionElement.textContent = tabDescriptions[targetTab]; + } + }); + }); + + // Set initial description based on active tab + const activeTab = document.querySelector('.tab-btn.active'); + if (activeTab && descriptionElement) { + const activeTabId = activeTab.getAttribute('data-tab'); + if (tabDescriptions[activeTabId]) { + descriptionElement.textContent = tabDescriptions[activeTabId]; + } + } +} + +// Copy to clipboard functionality +function copyToClipboard(text, button) { + if (navigator.clipboard && window.isSecureContext) { + navigator.clipboard.writeText(text).then(() => { + showCopyFeedback(button); + }).catch(err => { + console.error('Failed to copy: ', err); + fallbackCopyTextToClipboard(text, button); + }); + } else { + fallbackCopyTextToClipboard(text, button); + } +} + +// Make copyToClipboard globally available +window.copyToClipboard = copyToClipboard; + +function fallbackCopyTextToClipboard(text, button) { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + textArea.style.top = '-999999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + showCopyFeedback(button); + } catch (err) { + console.error('Fallback: Oops, unable to copy', err); + } + + document.body.removeChild(textArea); +} + +function showCopyFeedback(button) { + const originalHTML = button.innerHTML; + button.innerHTML = ` + + + + `; + button.classList.add('bg-green-500'); + + setTimeout(() => { + button.innerHTML = originalHTML; + button.classList.remove('bg-green-500'); + }, 1000); +} + +// Initialize copy buttons for the original HTML structure +function initCopyButtons() { + document.querySelectorAll('.copy-btn').forEach(button => { + button.addEventListener('click', function(e) { + e.preventDefault(); + const targetId = this.getAttribute('data-copy-target'); + const targetElement = document.getElementById(targetId); + const copyIcon = this.querySelector('.copy-icon'); + const copyFeedback = this.querySelector('.copy-feedback'); + + if (targetElement) { + const textToCopy = targetElement.textContent.trim(); + + // Skip if text is loading or not available + if (!textToCopy || textToCopy === 'loading...' || textToCopy === 'Not available') { + return; + } + + // Try to use the modern clipboard API + if (navigator.clipboard && window.isSecureContext) { + navigator.clipboard.writeText(textToCopy).then(() => { + showCopyFeedback(copyIcon, copyFeedback); + }).catch(err => { + console.error('Failed to copy: ', err); + fallbackCopyTextToClipboard(textToCopy, copyIcon, copyFeedback); + }); + } else { + // Fallback for older browsers + fallbackCopyTextToClipboard(textToCopy, copyIcon, copyFeedback); + } + } + }); + }); +} + +function showCopyFeedback(copyIcon, copyFeedback) { + if (copyIcon) copyIcon.classList.add('hidden'); + if (copyFeedback) copyFeedback.classList.remove('hidden'); + + setTimeout(() => { + if (copyIcon) copyIcon.classList.remove('hidden'); + if (copyFeedback) copyFeedback.classList.add('hidden'); + }, 2000); +} diff --git a/assets/js/whois.js b/assets/js/whois.js new file mode 100644 index 0000000..efce606 --- /dev/null +++ b/assets/js/whois.js @@ -0,0 +1,196 @@ +// DNS Things - Whois Module + +// Initialize Whois lookup form +function initWhoisForm() { + const form = document.getElementById('whois-form'); + const input = document.getElementById('whois-input'); + const results = document.getElementById('whois-results'); + const loader = document.getElementById('whois-loader'); + + if (!form || !input || !results || !loader) return; + + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + const domain = input.value.trim(); + if (!domain) return; + + // Show loader + loader.classList.remove('hidden'); + results.innerHTML = ''; + + try { + // Use DNS-based domain information lookup as a free alternative + const recordTypes = ['A', 'AAAA', 'MX', 'TXT', 'NS', 'SOA']; + + const queries = recordTypes.map(type => + fetch(`https://dns.google/resolve?name=${encodeURIComponent(domain)}&type=${type}`) + .then(response => response.json()) + .then(data => ({ type, data })) + .catch(error => ({ type, error })) + ); + + const responses = await Promise.all(queries); + + // Process DNS data + const dnsData = {}; + const ipAddresses = { ipv4: [], ipv6: [] }; + + responses.forEach(({ type, data, error }) => { + if (!error && data.Answer && data.Answer.length > 0) { + dnsData[type] = data.Answer.map(record => record.data); + + if (type === 'A') { + ipAddresses.ipv4.push(...data.Answer.map(record => record.data)); + } else if (type === 'AAAA') { + ipAddresses.ipv6.push(...data.Answer.map(record => record.data)); + } + } + }); + + // Determine TLD registry + const tld = domain.split('.').pop().toLowerCase(); + const tldRegistries = { + 'com': 'Verisign', + 'net': 'Verisign', + 'org': 'Public Interest Registry (PIR)', + 'info': 'Afilias', + 'biz': 'NeuStar', + 'name': 'Verisign', + 'mobi': 'Afilias', + 'travel': 'Tralliance', + 'museum': 'MuseDoma', + 'coop': 'DotCooperation', + 'aero': 'SITA', + 'pro': 'RegistryPro', + 'edu': 'Educause', + 'gov': 'General Services Administration', + 'mil': 'DoD Network Information Center', + 'int': 'IANA' + }; + + // Build results + let resultsHTML = '
'; + + // Domain Information + resultsHTML += ` +
+

Domain Information

+
+
+
Domain: ${domain}
+
TLD Registry: ${tldRegistries[tld] || 'Unknown'}
+
Website: ${dnsData.A || dnsData.AAAA ? '✅ Available' : '❌ Not available'}
+
Email: ${dnsData.MX ? '✅ Supported' : '❌ Not supported'}
+
+
+

Note: This is a DNS-based lookup providing practical domain information. For detailed registration data, use official whois services.

+
+
+
+ `; + + // Name Servers + if (dnsData.NS) { + resultsHTML += ` +
+

Name Servers (${dnsData.NS.length})

+
    + `; + dnsData.NS.forEach(ns => { + const cleanNS = ns.replace(/\.$/, ''); + resultsHTML += ` +
  • + ${cleanNS} + +
  • + `; + }); + resultsHTML += '
'; + } + + // DNS Records Summary + resultsHTML += ` +
+

DNS Records Summary

+
+ `; + + recordTypes.forEach(type => { + const hasRecord = dnsData[type] && dnsData[type].length > 0; + resultsHTML += ` +
+
${type}
+
${hasRecord ? '✅' : '❌'}
+
+ `; + }); + + resultsHTML += '
'; + + // IP Addresses + if (ipAddresses.ipv4.length > 0 || ipAddresses.ipv6.length > 0) { + resultsHTML += ` +
+

IP Addresses

+
+ `; + + ipAddresses.ipv4.forEach(ip => { + resultsHTML += ` +
+ ${ip} + +
+ `; + }); + + ipAddresses.ipv6.forEach(ip => { + resultsHTML += ` +
+ ${ip} + +
+ `; + }); + + resultsHTML += '
'; + } + + resultsHTML += '
'; + results.innerHTML = resultsHTML; + + } catch (error) { + console.error('Whois lookup error:', error); + results.innerHTML = ` +
+

Error

+

Failed to lookup domain information. Please try again.

+
+ `; + } finally { + loader.classList.add('hidden'); + } + }); + + // Auto-submit on paste + input.addEventListener('paste', () => { + setTimeout(() => { + if (input.value.trim()) { + form.dispatchEvent(new Event('submit')); + } + }, 100); + }); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..82ddd7e --- /dev/null +++ b/index.html @@ -0,0 +1,292 @@ + + + + + + DNS Things + + + + + + + + + + + + +
+ +
+ +
+ +
+
+
+ +
+
+

Your IP Address

+

Your public IP addresses

+
+
+
+
+ + +
+
loading...
+
+
+
+ + +
+
loading...
+
+
+
+ +
+
+
+ + +
+
+
+

DNS Tools

+

Various DNS utilities to help you analyze domains and IPs

+
+ +
+ +
+
+ + + + + +
+
+ + +
+ +
+

DNS Lookup

+
+ + +
+
+ +
+ + + + + + + + + + + + +
+
+
+
+
+ + +
+

+ © 2025 Dewe Toolsites - DNS Things. +

+ + + + + + + + + +