feat: update style

This commit is contained in:
2026-01-02 17:45:41 +01:00
parent fdc753b32f
commit a7d189d89d
9 changed files with 1336 additions and 493 deletions

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,66 +9,199 @@
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles --> <!-- Eigene Styles -->
<style> <style>
/* Einfacher Lade-Spinner */ /* Einfacher Lade-Spinner (Tailwind animiert) */
.loader { .loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */ border: 4px solid rgba(168, 85, 247, 0.1);
border-left-color: #a855f7; /* Lila */ /* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%; border-radius: 50%;
width: 24px; width: 24px;
height: 24px; height: 24px;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to {
transform: rotate(360deg);
}
} }
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */ /* Ergebnis-Pre-Formatierung */
.result-pre { .result-pre {
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-all; word-break: break-all;
font-family: monospace; font-family: 'Courier New', Courier, monospace;
background-color: #1f2937; /* Dunkelgrau */ background-color: rgba(0, 0, 0, 0.3);
color: #d1d5db; /* Hellgrau */ color: #e5e7eb;
padding: 1rem; padding: 1rem;
border-radius: 0.375rem; /* rounded-md */ border-radius: 0.375rem;
max-height: 400px; max-height: 400px;
overflow-y: auto; overflow-y: auto;
font-size: 0.875rem; /* text-sm */ font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
} }
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */ /* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } nav ul {
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; } list-style: none;
nav a:hover { color: #a78bfa; text-decoration: underline; } padding: 0;
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } margin: 0;
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } } display: flex;
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; } flex-wrap: wrap;
.hidden { display: none; } gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style> </style>
</head> </head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header> <body
<h1>uTools Network Suite</h1> class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav> <nav>
<ul> <ul>
<li><a href="index.html">IP Info & Tools</a></li> <li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li> <li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li> <li><a href="dns-lookup.html" class="active-link">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li> <li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li> <li><a href="mac-lookup.html">MAC Lookup</a></li>
</ul> </ul>
</nav> </nav>
</header> </header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6"> <div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">DNS Lookup</h1> <h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">DNS Lookup</h1>
<!-- Bereich für DNS Lookup --> <!-- Bereich für DNS Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded"> <div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-2 mb-4"> <div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="dns-domain-input" placeholder="Enter domain name (e.g., google.com)" <input type="text" id="dns-domain-input" placeholder="Enter domain name (e.g., google.com)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<select id="dns-type-select" class="px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"> <select id="dns-type-select"
class="px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent cursor-pointer">
<option value="ANY">ANY</option> <option value="ANY">ANY</option>
<option value="A">A</option> <option value="A">A</option>
<option value="AAAA">AAAA</option> <option value="AAAA">AAAA</option>
@@ -80,30 +214,38 @@
<option value="PTR">PTR (Reverse)</option> <option value="PTR">PTR (Reverse)</option>
</select> </select>
<button id="dns-lookup-button" <button id="dns-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"> class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup DNS Lookup DNS
</button> </button>
</div> </div>
<div id="dns-lookup-error" class="text-red-400 mb-4 hidden"></div> <div id="dns-lookup-error"
<div id="dns-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4"> class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<h3 class="text-lg font-semibold text-purple-300 mb-2">DNS Results for: <span id="dns-lookup-query" class="font-mono text-purple-400"></span></h3> <div id="dns-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<div id="dns-lookup-loader" class="loader hidden mb-2"></div> <h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center gap-2">
<pre id="dns-lookup-output" class="result-pre"></pre> <!-- Ergebnisbereich --> <div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
DNS Results for: <span id="dns-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="dns-lookup-loader" class="loader hidden mb-4"></div>
<pre id="dns-lookup-output" class="result-pre custom-scrollbar"></pre> <!-- Ergebnisbereich -->
</div> </div>
</div> </div>
<!-- Globaler Fehlerbereich --> <!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div> <div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version --> <!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500"> <footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p> <p>&copy; 2025 <a href="https://mrunk.de"
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
</footer> <p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div> </div>
<!-- Eigene JS-Logik für diese Seite --> <!-- Eigene JS-Logik für diese Seite -->
<script src="dns-lookup.js"></script> <script src="dns-lookup.js"></script>
</body> </body>
</html> </html>

View File

@@ -44,6 +44,11 @@ document.addEventListener('DOMContentLoaded', () => {
* @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement. * @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement.
*/ */
async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) { async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) {
// Reset animation
resultsSection.classList.remove('fade-in');
void resultsSection.offsetWidth; // Trigger reflow
resultsSection.classList.add('fade-in');
resultsSection.classList.remove('hidden'); resultsSection.classList.remove('hidden');
loaderElement.classList.remove('hidden'); loaderElement.classList.remove('hidden');
errorElement.classList.add('hidden'); errorElement.classList.add('hidden');

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,87 +9,299 @@
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<!-- Leaflet CSS --> <!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
crossorigin=""/>
<!-- Eigene Styles --> <!-- Eigene Styles -->
<style> <style>
/* Container für Karten müssen eine Höhe haben */ /* Container für Karten müssen eine Höhe haben */
#map { height: 300px; } #map {
#lookup-map { height: 250px; } /* Höhe für Lookup-Karte */ height: 300px;
}
#lookup-map {
height: 250px;
}
/* Höhe für Lookup-Karte */
/* Einfacher Lade-Spinner (Tailwind animiert) */ /* Einfacher Lade-Spinner (Tailwind animiert) */
.loader { .loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */ border: 4px solid rgba(168, 85, 247, 0.1);
border-left-color: #a855f7; /* Lila */ /* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%; border-radius: 50%;
width: 24px; width: 24px;
height: 24px; height: 24px;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
/* gray-900 mit Opacity */
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
/* gray-800 mit Opacity */
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
} }
/* Basis für Glitch-Effekt (Beispiel: Text-Schatten) */ /* Basis für Glitch-Effekt (Beispiel: Text-Schatten) */
.glitch-text:hover { .glitch-text:hover {
text-shadow: text-shadow:
1px 1px 0px rgba(168, 85, 247, 0.7), /* Lila */ 2px 2px 0px rgba(168, 85, 247, 0.4),
-1px -1px 0px rgba(76, 29, 149, 0.7); /* Dunkleres Lila */ -2px -2px 0px rgba(236, 72, 153, 0.4);
} }
/* Klickbarer IP-Cursor und Link-Styling */ /* Klickbarer IP-Cursor und Link-Styling */
#ip-address-link { #ip-address-link {
cursor: pointer; cursor: pointer;
text-decoration: none; /* Standard-Link-Unterstreichung entfernen */ text-decoration: none;
position: relative;
display: inline-block;
transition: color 0.3s ease;
} }
#ip-address-link:hover {
text-decoration: underline; /* Unterstreichung beim Hover */ #ip-address-link::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 2px;
bottom: 0;
left: 0;
background-color: #d8b4fe;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
#ip-address-link:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
} }
/* Traceroute Output Formatierung */ /* Traceroute Output Formatierung */
#traceroute-output pre, .result-pre { /* Gemeinsamer Stil für <pre> */ #traceroute-output pre,
white-space: pre-wrap; /* Zeilenumbruch */ .result-pre {
word-break: break-all; /* Lange Zeilen umbrechen */ white-space: pre-wrap;
font-family: monospace; word-break: break-all;
background-color: #1f2937; /* Dunkelgrau */ font-family: 'Courier New', Courier, monospace;
color: #d1d5db; /* Hellgrau */ /* Mehr Terminal-Feeling */
background-color: rgba(0, 0, 0, 0.3);
/* Transparenter */
color: #e5e7eb;
padding: 1rem; padding: 1rem;
border-radius: 0.375rem; /* rounded-md */ border-radius: 0.375rem;
max-height: 400px; max-height: 400px;
overflow-y: auto; overflow-y: auto;
font-size: 0.875rem; /* text-sm */ font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
#traceroute-output .hop-line {
margin-bottom: 0.25rem;
padding-left: 0.5rem;
border-left: 2px solid transparent;
transition: border-left-color 0.3s;
}
#traceroute-output .hop-line:hover {
border-left-color: #a855f7;
background: rgba(255, 255, 255, 0.02);
}
#traceroute-output .hop-number {
display: inline-block;
width: 30px;
text-align: right;
margin-right: 15px;
color: #6b7280;
font-weight: bold;
}
#traceroute-output .hop-ip {
color: #60a5fa;
font-weight: 500;
}
#traceroute-output .hop-hostname {
color: #c084fc;
}
/* Helleres Lila */
#traceroute-output .hop-rtt {
color: #34d399;
margin-left: 8px;
font-size: 0.85em;
}
#traceroute-output .hop-timeout {
color: #f87171;
}
#traceroute-output .info-line {
color: #fbbf24;
font-style: italic;
}
#traceroute-output .error-line {
color: #f87171;
font-weight: bold;
border-left: 3px solid #f87171;
padding-left: 10px;
}
#traceroute-output .end-line {
color: #d8b4fe;
font-weight: bold;
margin-top: 15px;
text-transform: uppercase;
letter-spacing: 0.05em;
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 10px;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
} }
#traceroute-output .hop-line { margin-bottom: 0.25rem; }
#traceroute-output .hop-number { display: inline-block; width: 30px; text-align: right; margin-right: 10px; color: #9ca3af; } /* Grau */
#traceroute-output .hop-ip { color: #60a5fa; } /* Blau */
#traceroute-output .hop-hostname { color: #a78bfa; } /* Lila */
#traceroute-output .hop-rtt { color: #34d399; margin-left: 5px;} /* Grün */
#traceroute-output .hop-timeout { color: #f87171; } /* Rot */
#traceroute-output .info-line { color: #fbbf24; font-style: italic;} /* Gelb */
#traceroute-output .error-line { color: #f87171; font-weight: bold;} /* Rot */
#traceroute-output .end-line { color: #a78bfa; font-weight: bold; margin-top: 10px;} /* Lila */
/* Navigations-Styling */ /* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } /* flex-wrap hinzugefügt */ nav ul {
nav a { color: #c4b5fd; /* purple-300 */ text-decoration: none; white-space: nowrap; } /* nowrap hinzugefügt */ list-style: none;
nav a:hover { color: #a78bfa; /* purple-400 */ text-decoration: underline; } padding: 0;
header { background-color: #374151; /* gray-700 */ padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; /* rounded-lg */ display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } /* Flex direction geändert */ margin: 0;
@media (min-width: 768px) { /* md breakpoint */ display: flex;
header { flex-direction: row; justify-content: space-between; } flex-wrap: wrap;
gap: 0.5rem;
} }
header h1 { font-size: 1.5rem; /* text-2xl */ font-weight: bold; color: #e5e7eb; /* gray-200 */ }
/* Hilfsklasse zum Verstecken */ nav a {
.hidden { display: none; } color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
/* Purple tint */
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
/* Optional active state */
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
/* Sehr transparent */
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
/* Standard property for compatibility */
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style> </style>
</head> </head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header> <body
<h1>uTools Network Suite</h1> <!-- Name angepasst --> class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav> <nav>
<ul> <ul>
<li><a href="index.html">IP Info & Tools</a></li> <li><a href="index.html" class="active-link">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li> <li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li> <li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li> <li><a href="whois-lookup.html">WHOIS Lookup</a></li>
@@ -97,166 +310,260 @@
</nav> </nav>
</header> </header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6"> <div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 glitch-text text-center">IP Information</h1> <!-- Titel angepasst --> <h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">Your Digital Footprint</h1>
<!-- Bereich für EIGENE IP-Infos --> <!-- Bereich für EIGENE IP-Infos -->
<div id="info-section" class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> <div id="info-section" class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
<!-- Linke Spalte: Eigene IP, Geo, ASN, rDNS --> <!-- Linke Spalte: Eigene IP, Geo, ASN, rDNS -->
<div class="space-y-4 p-4 bg-gray-700 rounded"> <div class="space-y-6 fade-in" style="animation-delay: 0.1s;">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Your Public IP</h2> <!-- IP Card -->
<div id="ip-info" class="min-h-[50px]"> <div class="glass-card rounded-lg p-5 relative overflow-hidden group">
<div id="ip-loader" class="loader"></div> <div class="absolute top-0 right-0 p-2 opacity-10 group-hover:opacity-20 transition-opacity">
<!-- Geändert zu <a> Tag --> <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-purple-500" fill="none"
<a id="ip-address-link" href="#" class="text-2xl font-mono font-bold text-purple-400 break-all hidden" title="Go to WHOIS Lookup for this IP"> viewBox="0 0 24 24" stroke="currentColor">
<span id="ip-address"></span> <!-- Span für den eigentlichen Text --> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
</a> d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</div> </svg>
</div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Geolocation</h2> <h2 class="text-xs font-bold text-purple-400 uppercase tracking-widest mb-2">Your Public IP</h2>
<div id="geo-info" class="min-h-[100px] space-y-1 text-sm"> <div id="ip-info" class="min-h-[40px] flex items-center">
<div id="geo-loader" class="loader"></div> <div id="ip-loader" class="loader"></div>
<div class="hidden"> <!-- Hide data until loaded --> <a id="ip-address-link" href="#"
<p><strong>Country:</strong> <span id="country">-</span></p> class="text-3xl font-mono font-bold text-white tracking-tight break-all hidden hover:text-purple-300 transition-colors"
<p><strong>Region:</strong> <span id="region">-</span></p> title="Click for WHOIS Lookup">
<p><strong>City:</strong> <span id="city">-</span></p> <span id="ip-address"></span>
<p><strong>Postal Code:</strong> <span id="postal">-</span></p> </a>
<p><strong>Coordinates:</strong> <span id="coords">-</span></p>
<p><strong>Timezone:</strong> <span id="timezone">-</span></p>
<p id="geo-error" class="text-red-400"></p>
</div> </div>
</div> </div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">ASN</h2> <!-- Geo/ASN Combo Card -->
<div id="asn-info" class="min-h-[50px] space-y-1 text-sm"> <div class="glass-card rounded-lg p-5 space-y-4">
<div id="asn-loader" class="loader"></div> <div>
<div class="hidden"> <!-- Hide data until loaded --> <h2
<p><strong>Number:</strong> <span id="asn-number">-</span></p> class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
<p><strong>Organization:</strong> <span id="asn-org">-</span></p> Location Details</h2>
<p id="asn-error" class="text-red-400"></p> <div id="geo-info" class="min-h-[80px] space-y-1 text-sm text-gray-300">
</div> <div id="geo-loader" class="loader"></div>
<div class="hidden grid grid-cols-2 gap-x-2 gap-y-1">
<p><span class="text-gray-500">Country:</span> <span id="country"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">Region:</span> <span id="region"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">City:</span> <span id="city"
class="text-gray-200 font-medium">-</span></p>
<p><span class="text-gray-500">Zip:</span> <span id="postal"
class="text-gray-200 font-medium">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Coords:</span> <span id="coords"
class="font-mono text-xs text-purple-300">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Time:</span> <span id="timezone"
class="text-gray-200 font-medium">-</span></p>
<p id="geo-error" class="text-red-400 col-span-2 text-xs"></p>
</div>
</div>
</div>
<div>
<h2
class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
Network (ASN)</h2>
<div id="asn-info" class="min-h-[40px] space-y-1 text-sm text-gray-300">
<div id="asn-loader" class="loader"></div>
<div class="hidden">
<p><span class="text-gray-500">AS Number:</span> <span id="asn-number"
class="font-mono text-purple-300">-</span></p>
<p><span class="text-gray-500">Org:</span> <span id="asn-org"
class="font-medium text-white">-</span></p>
<p id="asn-error" class="text-red-400 text-xs"></p>
</div>
</div>
</div>
</div> </div>
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Reverse DNS (rDNS)</h2> <!-- rDNS Card -->
<div id="rdns-info" class="min-h-[50px] space-y-1 text-sm"> <div class="glass-card rounded-lg p-5">
<div id="rdns-loader" class="loader"></div> <h2
<div class="hidden"> <!-- Hide data until loaded --> class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 border-b border-gray-700 pb-1">
<ul id="rdns-list" class="list-disc list-inside"><li>-</li></ul> Hostname (rDNS)</h2>
<p id="rdns-error" class="text-red-400"></p> <div id="rdns-info" class="min-h-[30px] text-sm text-gray-300">
</div> <div id="rdns-loader" class="loader"></div>
<div class="hidden">
<ul id="rdns-list" class="list-none space-y-1 font-mono text-xs text-green-400">
<li>-</li>
</ul>
<p id="rdns-error" class="text-red-400 text-xs"></p>
</div>
</div>
</div> </div>
</div> </div>
<!-- Rechte Spalte: Eigene Karte --> <!-- Rechte Spalte: Eigene Karte -->
<div class="space-y-4 p-4 bg-gray-700 rounded"> <div class="space-y-4 fade-in" style="animation-delay: 0.2s;">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1">Your Location Map</h2> <h2 class="text-lg font-semibold text-gray-200 flex items-center gap-2">
<div id="map-container" class="bg-gray-600 rounded min-h-[300px] flex items-center justify-center relative"> <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-purple-400" viewBox="0 0 20 20"
<div id="map-loader" class="loader absolute"></div> fill="currentColor">
<div id="map" class="w-full rounded hidden"></div> <path fill-rule="evenodd"
<p id="map-message" class="text-gray-400 hidden absolute">Could not load map.</p> d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"
</div> clip-rule="evenodd" />
</svg>
Location Visualization
</h2>
<div id="map-container"
class="bg-gray-800/50 rounded-lg min-h-[400px] h-full flex items-center justify-center relative border border-gray-700/50 shadow-inner overflow-hidden">
<div id="map-loader" class="loader absolute z-10"></div>
<div id="map"
class="w-full h-full rounded-lg hidden z-0 opacity-80 hover:opacity-100 transition-opacity duration-700">
</div>
<p id="map-message" class="text-gray-400 hidden absolute text-sm">Could not load map.</p>
<div class="absolute inset-0 pointer-events-none rounded-lg ring-1 ring-inset ring-white/10"></div>
</div>
</div> </div>
</div> </div>
<!-- Bereich für IP Lookup --> <!-- Bereich für IP Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded"> <div class="mt-8 p-6 glass-card rounded-xl">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">IP Address Lookup</h2> <h2
<div class="flex flex-col sm:flex-row gap-2 mb-4"> class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-purple-400 to-pink-500 mb-4 flex items-center gap-2">
<input type="text" id="lookup-ip-input" placeholder="Enter IP address (e.g., 8.8.8.8)" <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-pink-500" fill="none" viewBox="0 0 24 24"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
IP Address / Domain Lookup
</h2>
<div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="lookup-ip-input" placeholder="Enter IP or Domain (e.g., 8.8.8.8 or google.com)"
class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="lookup-button" <button id="lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"> class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup IP Lookup
</button> </button>
</div> </div>
<div id="lookup-error" class="text-red-400 mb-4 hidden"></div> <div id="lookup-error" class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded">
</div>
<!-- Ergebnisse des Lookups (initial versteckt) --> <!-- Ergebnisse des Lookups (initial versteckt) -->
<div id="lookup-results-section" class="hidden grid grid-cols-1 md:grid-cols-2 gap-6 mt-4 border-t border-gray-600 pt-4"> <div id="lookup-results-section"
<!-- Linke Spalte: IP, Geo, ASN, rDNS --> class="hidden grid grid-cols-1 md:grid-cols-2 gap-8 mt-6 border-t border-gray-700/50 pt-6 fade-in">
<div class="space-y-4"> <!-- Linke Spalte: IP, Geo, ASN, rDNS -->
<h3 class="text-lg font-semibold text-purple-300">Lookup Result for: <span id="lookup-ip-address" class="font-mono text-purple-400"></span></h3> <div class="space-y-6">
<div id="lookup-result-loader" class="loader hidden"></div> <!-- Loader für den gesamten Block --> <h3 class="text-lg font-semibold text-gray-200">Result for: <span id="lookup-ip-address"
class="font-mono text-purple-400 bg-purple-500/10 px-2 py-0.5 rounded"></span></h3>
<div id="lookup-result-loader" class="loader hidden"></div>
<div id="lookup-geo-info" class="space-y-1 text-sm"> <div id="lookup-geo-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-semibold text-purple-300">Geolocation</h4> <h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2">Geolocation</h4>
<p><strong>Country:</strong> <span id="lookup-country">-</span></p> <div class="grid grid-cols-2 gap-x-2 gap-y-1">
<p><strong>Region:</strong> <span id="lookup-region">-</span></p> <p><span class="text-gray-500">Country:</span> <span id="lookup-country"
<p><strong>City:</strong> <span id="lookup-city">-</span></p> class="text-white">-</span></p>
<p><strong>Postal Code:</strong> <span id="lookup-postal">-</span></p> <p><span class="text-gray-500">Region:</span> <span id="lookup-region"
<p><strong>Coordinates:</strong> <span id="lookup-coords">-</span></p> class="text-white">-</span></p>
<p><strong>Timezone:</strong> <span id="lookup-timezone">-</span></p> <p><span class="text-gray-500">City:</span> <span id="lookup-city"
<p id="lookup-geo-error" class="text-red-400"></p> class="text-white">-</span></p>
<p><span class="text-gray-500">Zip:</span> <span id="lookup-postal"
class="text-white">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Coords:</span> <span id="lookup-coords"
class="font-mono text-purple-300">-</span></p>
<p class="col-span-2"><span class="text-gray-500">Time:</span> <span id="lookup-timezone"
class="text-white">-</span></p>
<p id="lookup-geo-error" class="text-red-400 col-span-2"></p>
</div>
</div> </div>
<div id="lookup-asn-info" class="space-y-1 text-sm"> <div id="lookup-asn-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-semibold text-purple-300">ASN</h4> <h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2 mt-4">ASN</h4>
<p><strong>Number:</strong> <span id="lookup-asn-number">-</span></p> <p><span class="text-gray-500">Number:</span> <span id="lookup-asn-number"
<p><strong>Organization:</strong> <span id="lookup-asn-org">-</span></p> class="text-white font-mono">-</span></p>
<p><span class="text-gray-500">Org:</span> <span id="lookup-asn-org" class="text-white">-</span>
</p>
<p id="lookup-asn-error" class="text-red-400"></p> <p id="lookup-asn-error" class="text-red-400"></p>
</div> </div>
<div id="lookup-rdns-info" class="space-y-1 text-sm"> <div id="lookup-rdns-info" class="space-y-1 text-sm text-gray-300">
<h4 class="font-semibold text-purple-300">Reverse DNS (rDNS)</h4> <h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2 mt-4">Reverse DNS</h4>
<ul id="lookup-rdns-list" class="list-disc list-inside"><li>-</li></ul> <ul id="lookup-rdns-list" class="list-none space-y-1 font-mono text-xs text-green-400">
<li>-</li>
</ul>
<p id="lookup-rdns-error" class="text-red-400"></p> <p id="lookup-rdns-error" class="text-red-400"></p>
</div> </div>
</div> </div>
<!-- Rechte Spalte: Karte & Aktionen --> <!-- Rechte Spalte: Karte & Aktionen -->
<div class="space-y-4"> <div class="space-y-6">
<h4 class="font-semibold text-purple-300">Location Map</h4> <h4 class="font-bold text-gray-500 uppercase text-xs tracking-wider mb-2">Location Map</h4>
<div id="lookup-map-container" class="bg-gray-600 rounded min-h-[250px] flex items-center justify-center relative"> <div id="lookup-map-container"
<div id="lookup-map-loader" class="loader hidden absolute"></div> class="glass-panel rounded-lg min-h-[250px] flex items-center justify-center relative overflow-hidden">
<div id="lookup-map" class="w-full rounded hidden"></div> <!-- Höhe via CSS --> <div id="lookup-map-loader" class="loader hidden absolute z-10"></div>
<p id="lookup-map-message" class="text-gray-400 hidden absolute">Could not load map.</p> <div id="lookup-map" class="w-full rounded hidden opacity-90"></div>
</div> <p id="lookup-map-message" class="text-gray-400 hidden absolute">Could not load map.</p>
<!-- Optional: Buttons für Ping/Trace für diese IP --> <div class="absolute inset-0 pointer-events-none ring-1 ring-inset ring-white/10 rounded-lg">
<div class="mt-4 space-x-2"> </div>
<button id="lookup-ping-button" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Ping this IP</button> </div>
<button id="lookup-trace-button" class="bg-teal-600 hover:bg-teal-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Trace this IP</button>
<button id="lookup-scan-button" class="bg-red-600 hover:bg-red-700 text-white font-bold py-1 px-3 rounded text-sm transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" disabled>Scan Ports</button> <!-- Action Buttons -->
</div> <div class="flex flex-wrap gap-2 pt-2">
<!-- Bereich für Ping-Ergebnisse (Lookup) --> <button id="lookup-ping-button"
<div id="lookup-ping-results" class="mt-2 text-sm hidden"> class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
<h4 class="font-semibold text-purple-300">Ping Results</h4> disabled>Ping</button>
<div id="lookup-ping-loader" class="loader hidden"></div> <button id="lookup-trace-button"
<pre id="lookup-ping-output" class="mt-1 whitespace-pre-wrap break-all font-mono bg-gray-900 text-gray-300 p-2 rounded text-xs"></pre> class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
<p id="lookup-ping-error" class="text-red-400"></p> disabled>Trace</button>
</div> <button id="lookup-scan-button"
</div> class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed border border-gray-600 hover:border-gray-500 shadow-md"
disabled>Port Scan</button>
</div>
<!-- Bereich für Ping-Ergebnisse (Lookup) -->
<div id="lookup-ping-results" class="mt-4 text-sm hidden fade-in">
<h4 class="font-bold text-purple-400 mb-2 flex items-center gap-2">
<div class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div> Ping Results
</h4>
<div id="lookup-ping-loader" class="loader hidden"></div>
<pre id="lookup-ping-output" class="result-pre mt-1"></pre>
<p id="lookup-ping-error" class="text-red-400 mt-2"></p>
</div>
</div>
</div> </div>
</div> </div>
<!-- Bereich für Traceroute --> <!-- Bereich für Traceroute -->
<div id="traceroute-section" class="mt-8 p-4 bg-gray-700 rounded hidden"> <div id="traceroute-section" class="mt-8 p-6 glass-card rounded-xl hidden fade-in">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">Traceroute Results</h2> <h2 class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4">Traceroute Results
<div id="traceroute-status" class="flex items-center mb-2"> </h2>
<div id="traceroute-loader" class="loader mr-2 hidden"></div> <div id="traceroute-status" class="flex items-center mb-4 text-sm">
<span id="traceroute-message" class="text-gray-400"></span> <div id="traceroute-loader" class="loader mr-3 hidden"></div>
</div> <span id="traceroute-message" class="text-gray-300"></span>
<div id="traceroute-output"><pre></pre></div> </div>
<div id="traceroute-output" class="rounded-lg overflow-hidden custom-scrollbar">
<pre class="m-0"></pre>
</div>
</div> </div>
<!-- Bereich für Port Scan --> <!-- Bereich für Port Scan -->
<div id="port-scan-section" class="mt-8 p-4 bg-gray-700 rounded hidden"> <div id="port-scan-section" class="mt-8 p-6 glass-card rounded-xl hidden fade-in">
<h2 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-1 mb-4">Port Scan Results</h2> <h2 class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4">Port Scan Results</h2>
<div id="port-scan-status" class="flex items-center mb-2"> <div id="port-scan-status" class="flex items-center mb-4 text-sm">
<div id="port-scan-loader" class="loader mr-2 hidden"></div> <div id="port-scan-loader" class="loader mr-3 hidden"></div>
<span id="port-scan-message" class="text-gray-400"></span> <span id="port-scan-message" class="text-gray-300"></span>
</div> </div>
<div id="port-scan-output" class="text-sm font-mono"></div> <div id="port-scan-output"
class="text-sm font-mono bg-gray-900/50 p-4 rounded-lg border border-gray-700/50 max-h-[300px] overflow-y-auto">
</div>
</div> </div>
<!-- Globaler Fehlerbereich --> <!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div> <div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version --> <!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500"> <footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p> <p>&copy; 2025 <a href="https://mrunk.de"
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer> </footer>
@@ -264,9 +571,9 @@
<!-- Leaflet JS --> <!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
crossorigin=""></script>
<!-- Eigene JS-Logik --> <!-- Eigene JS-Logik -->
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,82 +9,227 @@
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles --> <!-- Eigene Styles -->
<style> <style>
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader { .loader {
border: 4px solid rgba(168, 85, 247, 0.3); border: 4px solid rgba(168, 85, 247, 0.1);
border-left-color: #a855f7; /* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%; border-radius: 50%;
width: 24px; width: 24px;
height: 24px; height: 24px;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */
.result-pre { .result-pre {
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-all; word-break: break-all;
font-family: monospace; font-family: 'Courier New', Courier, monospace;
background-color: #1f2937; background-color: rgba(0, 0, 0, 0.3);
color: #d1d5db; color: #e5e7eb;
padding: 1rem; padding: 1rem;
border-radius: 0.375rem; border-radius: 0.375rem;
max-height: 400px; max-height: 400px;
overflow-y: auto; overflow-y: auto;
font-size: 1.25rem; /* Larger font for the result */ font-size: 1.25rem;
text-align: center; text-align: center;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
} }
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; }
nav a:hover { color: #a78bfa; text-decoration: underline; }
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; }
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } }
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; }
.hidden { display: none; }
</style> </style>
</head> </head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header> <body
<h1>uTools Network Suite</h1> class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav> <nav>
<ul> <ul>
<li><a href="index.html">IP Info & Tools</a></li> <li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li> <li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li> <li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li> <li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li> <li><a href="mac-lookup.html" class="active-link">MAC Lookup</a></li>
</ul> </ul>
</nav> </nav>
</header> </header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6"> <div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">MAC Address Vendor Lookup</h1> <h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">MAC Address Vendor Lookup</h1>
<div class="mt-8 p-4 bg-gray-700 rounded"> <div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-2 mb-4"> <div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="mac-input" placeholder="Enter MAC address (e.g., 00:1A:2B:3C:4D:5E)" <input type="text" id="mac-input" placeholder="Enter MAC address (e.g., 00:1A:2B:3C:4D:5E)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="mac-lookup-button" <button id="mac-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"> class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Find Vendor Find Vendor
</button> </button>
</div> </div>
<div id="mac-lookup-error" class="text-red-400 mb-4 hidden"></div> <div id="mac-lookup-error"
<div id="mac-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4"> class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<h3 class="text-lg font-semibold text-purple-300 mb-2">Vendor for: <span id="mac-lookup-query" class="font-mono text-purple-400"></span></h3> <div id="mac-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<div id="mac-lookup-loader" class="loader hidden mb-2 mx-auto"></div> <h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center justify-center gap-2">
<pre id="mac-lookup-output" class="result-pre"></pre> <div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
Vendor for: <span id="mac-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="mac-lookup-loader" class="loader hidden mb-4 mx-auto"></div>
<pre id="mac-lookup-output" class="result-pre custom-scrollbar"></pre>
</div> </div>
</div> </div>
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div> <div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500"> <footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p> <p>&copy; 2025 <a href="https://mrunk.de"
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
</footer> <p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div> </div>
<script src="mac-lookup.js"></script> <script src="mac-lookup.js"></script>
</body> </body>
</html> </html>

View File

@@ -43,6 +43,11 @@ document.addEventListener('DOMContentLoaded', () => {
return; return;
} }
// Reset animation
macLookupResultsSection.classList.remove('fade-in');
void macLookupResultsSection.offsetWidth; // Trigger reflow
macLookupResultsSection.classList.add('fade-in');
macLookupResultsSection.classList.remove('hidden'); macLookupResultsSection.classList.remove('hidden');
macLookupLoader.classList.remove('hidden'); macLookupLoader.classList.remove('hidden');
macLookupErrorEl.classList.add('hidden'); macLookupErrorEl.classList.add('hidden');

View File

@@ -149,33 +149,33 @@ document.addEventListener('DOMContentLoaded', () => {
} }
} }
/** /**
* Aktualisiert die rDNS Liste generisch. * Aktualisiert die rDNS Liste generisch.
* @param {HTMLElement} listElement - Das UL Element. * @param {HTMLElement} listElement - Das UL Element.
* @param {Array|object} rdnsData - Die rDNS Daten oder ein Fehlerobjekt. * @param {Array|object} rdnsData - Die rDNS Daten oder ein Fehlerobjekt.
* @param {HTMLElement} [loaderElement] - Das zu versteckende Loader-Element. * @param {HTMLElement} [loaderElement] - Das zu versteckende Loader-Element.
* @param {HTMLElement} [errorElement] - Das Element zur Anzeige von Fehlern. * @param {HTMLElement} [errorElement] - Das Element zur Anzeige von Fehlern.
*/ */
function updateRdns(listElement, rdnsData, loaderElement = null, errorElement = null) { function updateRdns(listElement, rdnsData, loaderElement = null, errorElement = null) {
if (loaderElement) loaderElement.classList.add('hidden'); if (loaderElement) loaderElement.classList.add('hidden');
if (listElement) listElement.innerHTML = ''; // Clear previous entries if (listElement) listElement.innerHTML = ''; // Clear previous entries
if (errorElement) errorElement.textContent = ''; if (errorElement) errorElement.textContent = '';
// Zeige das Elternelement des listElements, falls es vorher versteckt war // Zeige das Elternelement des listElements, falls es vorher versteckt war
const dataContainer = listElement?.closest('div:not(.loader)'); const dataContainer = listElement?.closest('div:not(.loader)');
if (dataContainer?.classList.contains('hidden')) { if (dataContainer?.classList.contains('hidden')) {
dataContainer.classList.remove('hidden'); dataContainer.classList.remove('hidden');
} }
if (rdnsData && Array.isArray(rdnsData)) { if (rdnsData && Array.isArray(rdnsData)) {
if (rdnsData.length > 0) { if (rdnsData.length > 0) {
rdnsData.forEach(hostname => { rdnsData.forEach(hostname => {
const li = document.createElement('li'); const li = document.createElement('li');
li.textContent = hostname; li.textContent = hostname;
if (listElement) listElement.appendChild(li); if (listElement) listElement.appendChild(li);
}); });
} else { } else {
if (listElement) listElement.innerHTML = '<li>No rDNS records found.</li>'; // Klarere Meldung if (listElement) listElement.innerHTML = '<li>No rDNS records found.</li>'; // Klarere Meldung
} }
} else if (rdnsData && rdnsData.error) { } else if (rdnsData && rdnsData.error) {
if (listElement) listElement.innerHTML = '<li>-</li>'; if (listElement) listElement.innerHTML = '<li>-</li>';
@@ -241,10 +241,10 @@ document.addEventListener('DOMContentLoaded', () => {
messageElement.classList.remove('hidden'); messageElement.classList.remove('hidden');
messageElement.textContent = 'Map could not be loaded (missing or invalid coordinates).'; messageElement.textContent = 'Map could not be loaded (missing or invalid coordinates).';
// If map existed, remove it to clean up resources // If map existed, remove it to clean up resources
if(mapInstance) { if (mapInstance) {
mapInstance.remove(); mapInstance.remove();
window[mapId + '_instance'] = null; window[mapId + '_instance'] = null;
} }
return null; return null;
} }
} }
@@ -357,8 +357,8 @@ document.addEventListener('DOMContentLoaded', () => {
} }
/** Setzt den Lookup-Ergebnisbereich zurück */ /** Setzt den Lookup-Ergebnisbereich zurück */
function resetLookupResults() { function resetLookupResults() {
if (!lookupResultsSection) return; if (!lookupResultsSection) return;
lookupResultsSection.classList.add('hidden'); lookupResultsSection.classList.add('hidden');
if (lookupResultLoader) lookupResultLoader.classList.add('hidden'); if (lookupResultLoader) lookupResultLoader.classList.add('hidden');
@@ -396,7 +396,7 @@ document.addEventListener('DOMContentLoaded', () => {
portScanEventSource.close(); portScanEventSource.close();
portScanEventSource = null; portScanEventSource = null;
} }
} }
/** Ruft Informationen für eine spezifische IP ab */ /** Ruft Informationen für eine spezifische IP ab */
async function fetchLookupInfo(ipToLookup) { async function fetchLookupInfo(ipToLookup) {
@@ -452,8 +452,8 @@ document.addEventListener('DOMContentLoaded', () => {
resetLookupResults(); // Hide the section again on error resetLookupResults(); // Hide the section again on error
} finally { } finally {
if (lookupResultLoader) lookupResultLoader.classList.add('hidden'); // Hide main loader if (lookupResultLoader) lookupResultLoader.classList.add('hidden'); // Hide main loader
// Map loader is handled by initOrUpdateMap // Map loader is handled by initOrUpdateMap
} }
} }
@@ -522,10 +522,10 @@ document.addEventListener('DOMContentLoaded', () => {
if (data.stats.rtt) { if (data.stats.rtt) {
outputText += `Round Trip Time (ms): min=${data.stats.rtt.min}, avg=${data.stats.rtt.avg}, max=${data.stats.rtt.max}, mdev=${data.stats.rtt.mdev}\n`; outputText += `Round Trip Time (ms): min=${data.stats.rtt.min}, avg=${data.stats.rtt.avg}, max=${data.stats.rtt.max}, mdev=${data.stats.rtt.mdev}\n`;
} else if (data.stats.packets.received === 0) { } else if (data.stats.packets.received === 0) {
outputText += `Status: Host unreachable or request timed out.\n`; outputText += `Status: Host unreachable or request timed out.\n`;
} }
} else { } else {
outputText += `Could not parse statistics.\n`; outputText += `Could not parse statistics.\n`;
} }
outputText += `\n--- Raw Output ---\n${data.rawOutput || 'No raw output available.'}`; outputText += `\n--- Raw Output ---\n${data.rawOutput || 'No raw output available.'}`;
lookupPingOutputEl.textContent = outputText; lookupPingOutputEl.textContent = outputText;
@@ -571,7 +571,7 @@ document.addEventListener('DOMContentLoaded', () => {
console.error('EventSource failed:', event); console.error('EventSource failed:', event);
let errorMsg = 'Connection error during traceroute.'; let errorMsg = 'Connection error during traceroute.';
if (eventSource.readyState === EventSource.CLOSED) { if (eventSource.readyState === EventSource.CLOSED) {
errorMsg = 'Connection closed. Server might have stopped or a network issue occurred.'; errorMsg = 'Connection closed. Server might have stopped or a network issue occurred.';
} }
tracerouteMessage.textContent = errorMsg; tracerouteMessage.textContent = errorMsg;
tracerouteLoader.classList.add('hidden'); tracerouteLoader.classList.add('hidden');
@@ -587,14 +587,14 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
eventSource.addEventListener('info', (event) => { eventSource.addEventListener('info', (event) => {
try { try {
const infoData = JSON.parse(event.data); const infoData = JSON.parse(event.data);
displayTracerouteLine(infoData.message, 'info-line'); displayTracerouteLine(infoData.message, 'info-line');
} catch (e) { displayTracerouteLine(`[Error parsing info data: ${event.data}]`, 'error-line'); } } catch (e) { displayTracerouteLine(`[Error parsing info data: ${event.data}]`, 'error-line'); }
}); });
eventSource.addEventListener('error', (event) => { // Backend error event eventSource.addEventListener('error', (event) => { // Backend error event
try { try {
const errorData = JSON.parse(event.data); const errorData = JSON.parse(event.data);
displayTracerouteLine(errorData.error, 'error-line'); displayTracerouteLine(errorData.error, 'error-line');
tracerouteMessage.textContent = `Error during traceroute: ${errorData.error}`; tracerouteMessage.textContent = `Error during traceroute: ${errorData.error}`;
@@ -603,7 +603,7 @@ document.addEventListener('DOMContentLoaded', () => {
eventSource.addEventListener('end', (event) => { eventSource.addEventListener('end', (event) => {
console.log('SSE connection closed by server (end event).'); console.log('SSE connection closed by server (end event).');
try { try {
const endData = JSON.parse(event.data); const endData = JSON.parse(event.data);
const endMessage = `Traceroute finished ${endData.exitCode === 0 ? 'successfully' : `with exit code ${endData.exitCode}`}.`; const endMessage = `Traceroute finished ${endData.exitCode === 0 ? 'successfully' : `with exit code ${endData.exitCode}`}.`;
displayTracerouteLine(endMessage, 'end-line'); displayTracerouteLine(endMessage, 'end-line');
@@ -615,18 +615,19 @@ document.addEventListener('DOMContentLoaded', () => {
} }
function displayTracerouteLine(text, className = '') { function displayTracerouteLine(text, className = '') {
if (!tracerouteOutputEl) return; if (!tracerouteOutputEl) return;
const lineDiv = document.createElement('div'); const lineDiv = document.createElement('div');
if (className) lineDiv.classList.add(className); if (className) lineDiv.classList.add(className);
lineDiv.textContent = text; lineDiv.classList.add('fade-in'); // Animation hinzufügen
tracerouteOutputEl.appendChild(lineDiv); lineDiv.textContent = text;
tracerouteOutputEl.scrollTop = tracerouteOutputEl.scrollHeight; tracerouteOutputEl.appendChild(lineDiv);
tracerouteOutputEl.scrollTop = tracerouteOutputEl.scrollHeight;
} }
function displayTracerouteHop(hopData) { function displayTracerouteHop(hopData) {
if (!tracerouteOutputEl) return; if (!tracerouteOutputEl) return;
const lineDiv = document.createElement('div'); const lineDiv = document.createElement('div');
lineDiv.classList.add('hop-line'); lineDiv.classList.add('hop-line', 'fade-in'); // Animation hinzufügen
const hopNumSpan = document.createElement('span'); const hopNumSpan = document.createElement('span');
hopNumSpan.classList.add('hop-number'); hopNumSpan.classList.add('hop-number');
@@ -645,12 +646,12 @@ document.addEventListener('DOMContentLoaded', () => {
lineDiv.appendChild(hostSpan); lineDiv.appendChild(hostSpan);
} }
} else if (hopData.rtt && hopData.rtt.every(r => r === '*')) { } else if (hopData.rtt && hopData.rtt.every(r => r === '*')) {
const timeoutSpan = document.createElement('span'); const timeoutSpan = document.createElement('span');
timeoutSpan.classList.add('hop-timeout'); timeoutSpan.classList.add('hop-timeout');
timeoutSpan.textContent = '* * *'; timeoutSpan.textContent = '* * *';
lineDiv.appendChild(timeoutSpan); lineDiv.appendChild(timeoutSpan);
} else { } else {
lineDiv.appendChild(document.createTextNode(hopData.rawLine || 'Unknown hop format')); lineDiv.appendChild(document.createTextNode(hopData.rawLine || 'Unknown hop format'));
} }
if (hopData.rtt && Array.isArray(hopData.rtt)) { if (hopData.rtt && Array.isArray(hopData.rtt)) {
@@ -729,7 +730,7 @@ document.addEventListener('DOMContentLoaded', () => {
function displayPortScanResult(data) { function displayPortScanResult(data) {
if (!portScanOutputEl) return; if (!portScanOutputEl) return;
const lineDiv = document.createElement('div'); const lineDiv = document.createElement('div');
lineDiv.classList.add('mb-1'); lineDiv.classList.add('mb-1', 'fade-in'); // Animation hinzufügen
let statusColor = 'text-gray-400'; let statusColor = 'text-gray-400';
let statusText = data.status.toUpperCase(); let statusText = data.status.toUpperCase();
@@ -794,38 +795,38 @@ document.addEventListener('DOMContentLoaded', () => {
// lookupIpInput.value = resolvedIp; // lookupIpInput.value = resolvedIp;
fetchLookupInfo(resolvedIp); // Fetch info for the resolved IP fetchLookupInfo(resolvedIp); // Fetch info for the resolved IP
} else { } else {
// Should be caught by the error in resolveDomainToIp, but as a fallback: // Should be caught by the error in resolveDomainToIp, but as a fallback:
showLookupError(`Could not resolve domain ${query} to an IP address.`); showLookupError(`Could not resolve domain ${query} to an IP address.`);
} }
} catch (error) { } catch (error) {
showLookupError(error.message); // Display resolution error showLookupError(error.message); // Display resolution error
} finally { } finally {
hideLookupStatus(); // Hide status message regardless of outcome hideLookupStatus(); // Hide status message regardless of outcome
} }
} }
} }
function handleLookupPingClick() { function handleLookupPingClick() {
if (currentLookupIp) { if (currentLookupIp) {
console.log(`Starting ping for looked-up IP: ${currentLookupIp}`); console.log(`Starting ping for looked-up IP: ${currentLookupIp}`);
runLookupPing(currentLookupIp); // Call the new ping function runLookupPing(currentLookupIp); // Call the new ping function
} }
} }
function handleLookupTraceClick() { function handleLookupTraceClick() {
if (currentLookupIp) { if (currentLookupIp) {
console.log(`Starting traceroute for looked-up IP: ${currentLookupIp}`); console.log(`Starting traceroute for looked-up IP: ${currentLookupIp}`);
startTraceroute(currentLookupIp); startTraceroute(currentLookupIp);
} }
} }
function handleLookupScanClick() { function handleLookupScanClick() {
if (currentLookupIp) { if (currentLookupIp) {
console.log(`Starting port scan for looked-up IP: ${currentLookupIp}`); console.log(`Starting port scan for looked-up IP: ${currentLookupIp}`);
startPortScan(currentLookupIp); startPortScan(currentLookupIp);
} }
} }
// --- Initial Load & Event Listeners --- // --- Initial Load & Event Listeners ---
fetchIpInfo(); // Lade Infos zur eigenen IP fetchIpInfo(); // Lade Infos zur eigenen IP

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,116 +9,164 @@
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles (für Navigation etc., wie in index.html) --> <!-- Eigene Styles (für Navigation etc., wie in index.html) -->
<style> <style>
/* Einfacher Lade-Spinner (Tailwind animiert) */
.loader {
border: 4px solid rgba(168, 85, 247, 0.1);
/* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Navigations-Styling */ /* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } /* flex-wrap hinzugefügt */ nav ul {
nav a { color: #c4b5fd; /* purple-300 */ text-decoration: none; white-space: nowrap; } /* nowrap hinzugefügt */ list-style: none;
nav a:hover { color: #a78bfa; /* purple-400 */ text-decoration: underline; } padding: 0;
header { background-color: #374151; /* gray-700 */ padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; /* rounded-lg */ display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } /* Flex direction geändert */ margin: 0;
@media (min-width: 768px) { /* md breakpoint */ display: flex;
header { flex-direction: row; justify-content: space-between; } flex-wrap: wrap;
gap: 0.5rem;
} }
header h1 { font-size: 1.5rem; /* text-2xl */ font-weight: bold; color: #e5e7eb; /* gray-200 */ }
/* Styling für Formular und Ergebnisse */ nav a {
label { display: block; margin-bottom: 0.5rem; font-weight: 600; color: #d1d5db; /* gray-300 */ } color: #d1d5db;
input[type="text"] { text-decoration: none;
width: 100%; padding: 0.5rem 1rem;
padding: 0.75rem; border-radius: 0.5rem;
margin-bottom: 1rem; transition: all 0.2s ease;
background-color: #4b5563; /* gray-600 */ position: relative;
border: 1px solid #6b7280; /* gray-500 */ overflow: hidden;
border-radius: 0.375rem; /* rounded-md */ background: rgba(255, 255, 255, 0.03);
color: #e5e7eb; /* gray-200 */ border: 1px solid rgba(255, 255, 255, 0.05);
font-family: monospace;
} }
input[type="text"]:focus {
outline: none; nav a:hover {
border-color: #a78bfa; /* purple-400 */ color: #fff;
box-shadow: 0 0 0 2px rgba(167, 139, 250, 0.5); background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
} }
button[type="submit"] {
background-color: #8b5cf6; /* purple-500 */ nav a.active-link {
color: white; background: rgba(168, 85, 247, 0.3);
padding: 0.75rem 1.5rem; color: #fff;
border: none; border-color: #a855f7;
border-radius: 0.375rem; /* rounded-md */
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
} }
button[type="submit"]:hover {
background-color: #7c3aed; /* purple-600 */ header {
} background: rgba(31, 41, 55, 0.4);
#results, #examples { backdrop-filter: blur(10px);
margin-top: 2rem;
padding: 1.5rem; padding: 1.5rem;
background-color: #374151; /* gray-700 */ margin-bottom: 2rem;
border-radius: 0.5rem; /* rounded-lg */ border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
} }
#results h3, #examples h3 {
font-size: 1.25rem; /* text-xl */
font-weight: 600;
color: #c4b5fd; /* purple-300 */
margin-bottom: 1rem;
border-bottom: 1px solid #6b7280; /* gray-500 */
padding-bottom: 0.5rem;
}
#results p {
margin-bottom: 0.75rem;
color: #d1d5db; /* gray-300 */
}
#results p strong {
color: #e5e7eb; /* gray-200 */
min-width: 150px; /* Für bessere Ausrichtung */
display: inline-block;
}
#results span {
font-family: monospace;
color: #a78bfa; /* purple-400 */
}
/* Styling für Beispiel-Tabelle */
#examples table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
}
#examples th, #examples td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #4b5563; /* gray-600 */
color: #d1d5db; /* gray-300 */
}
#examples th {
color: #e5e7eb; /* gray-200 */
font-weight: 600;
}
#examples td code {
font-family: monospace;
background-color: #4b5563; /* gray-600 */
padding: 0.2rem 0.4rem;
border-radius: 0.25rem;
color: #c4b5fd; /* purple-300 */
}
#examples .example-link {
color: #a78bfa; /* purple-400 */
cursor: pointer;
text-decoration: underline;
}
#examples .example-link:hover {
color: #c4b5fd; /* purple-300 */
}
.hidden { display: none; }
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
</style> </style>
</head> </head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header> <body
<h1>uTools Network Suite</h1> <!-- Titel angepasst --> class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav> <nav>
<ul> <ul>
<li><a href="index.html">IP Info & Tools</a></li> <li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li> <li><a href="subnet-calculator.html" class="active-link">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li> <li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li> <li><a href="whois-lookup.html">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li> <li><a href="mac-lookup.html">MAC Lookup</a></li>
@@ -125,92 +174,133 @@
</nav> </nav>
</header> </header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6"> <div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h2 class="text-2xl font-bold mb-6 text-purple-400 text-center">IP Subnetz Rechner</h2> <h2 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">IP Subnetz Rechner</h2>
<form id="subnet-form" class="mb-6"> <form id="subnet-form" class="mb-8 glass-card p-6 rounded-xl">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div> <div>
<label for="ip-address">IP Adresse:</label> <label for="ip-address"
class="block text-gray-400 text-sm font-bold mb-2 uppercase tracking-wide">IP Adresse:</label>
<input type="text" id="ip-address" name="ip-address" placeholder="z.B. 192.168.1.1" required <input type="text" id="ip-address" name="ip-address" placeholder="z.B. 192.168.1.1" required
class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> class="w-full px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all">
</div> </div>
<div> <div>
<label for="cidr">CIDR / Subnetzmaske:</label> <label for="cidr" class="block text-gray-400 text-sm font-bold mb-2 uppercase tracking-wide">CIDR /
Maske:</label>
<input type="text" id="cidr" name="cidr" placeholder="z.B. 24 oder 255.255.255.0" required <input type="text" id="cidr" name="cidr" placeholder="z.B. 24 oder 255.255.255.0" required
class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> class="w-full px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all">
</div> </div>
</div> </div>
<button type="submit" <button type="submit"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"> class="w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Berechnen Berechnen
</button> </button>
</form> </form>
<div id="results" class="bg-gray-700 rounded p-6 hidden"> <!-- Ergebnisse initial verstecken --> <div id="results" class="glass-card rounded-xl p-6 hidden fade-in"> <!-- Ergebnisse initial verstecken -->
<h3 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-2 mb-4">Ergebnisse:</h3> <h3
<div class="space-y-2 text-sm"> class="text-xl font-bold text-purple-300 border-b border-purple-500/30 pb-2 mb-4 flex items-center gap-2">
<p><strong>Netzwerkadresse:</strong> <span id="network-address" class="font-mono text-purple-400">-</span></p> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
<p><strong>Broadcast-Adresse:</strong> <span id="broadcast-address" class="font-mono text-purple-400">-</span></p> stroke="currentColor">
<p><strong>Subnetzmaske:</strong> <span id="subnet-mask" class="font-mono text-purple-400">-</span></p> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
<p><strong>Anzahl der Hosts:</strong> <span id="host-count" class="font-mono text-purple-400">-</span></p> d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
<p><strong>Erste Host-Adresse:</strong> <span id="first-host" class="font-mono text-purple-400">-</span></p> </svg>
<p><strong>Letzte Host-Adresse:</strong> <span id="last-host" class="font-mono text-purple-400">-</span></p> Ergebnisse:
</h3>
<div class="space-y-3 text-sm">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Netzwerkadresse:</span>
<span id="network-address" class="font-mono text-white font-semibold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Broadcast-Adresse:</span>
<span id="broadcast-address" class="font-mono text-purple-400 font-semibold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Subnetzmaske:</span>
<span id="subnet-mask" class="font-mono text-gray-300">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Anzahl der Hosts:</span>
<span id="host-count" class="font-mono text-green-400 font-bold">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 border-b border-gray-700/50 pb-2">
<span class="text-gray-400">Erste Host-Adresse:</span>
<span id="first-host" class="font-mono text-blue-300">-</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
<span class="text-gray-400">Letzte Host-Adresse:</span>
<span id="last-host" class="font-mono text-blue-300">-</span>
</div>
</div> </div>
</div> </div>
<!-- Beispiel-Subnetze --> <!-- Beispiel-Subnetze -->
<div id="examples" class="bg-gray-700 rounded p-6 mt-8"> <div id="examples" class="glass-card rounded-xl p-6 mt-8">
<h3 class="text-xl font-semibold text-purple-300 border-b border-purple-500 pb-2 mb-4">Beispiel-Subnetze (Private Adressbereiche)</h3> <h3 class="text-lg font-bold text-gray-400 uppercase tracking-wider border-b border-gray-700/50 pb-2 mb-4">
<div class="overflow-x-auto"> Beispiel-Subnetze (Private Adressbereiche)</h3>
<table class="min-w-full text-sm"> <div class="overflow-x-auto">
<thead> <table class="min-w-full text-sm text-left text-gray-400">
<tr> <thead class="text-xs uppercase bg-gray-800/50 text-gray-200">
<th>Bereich</th> <tr>
<th>CIDR</th> <th scope="col" class="px-6 py-3">Bereich</th>
<th>Subnetzmaske</th> <th scope="col" class="px-6 py-3">CIDR</th>
<th>Beschreibung</th> <th scope="col" class="px-6 py-3">Subnetzmaske</th>
<th>Aktion</th> <th scope="col" class="px-6 py-3">Beschreibung</th>
</tr> <th scope="col" class="px-6 py-3">Aktion</th>
</thead> </tr>
<tbody class="divide-y divide-gray-600"> </thead>
<tr> <tbody class="divide-y divide-gray-700/50">
<td><code>192.168.0.0 - 192.168.255.255</code></td> <tr class="hover:bg-gray-700/30 transition-colors">
<td><code>/16</code> (Gesamt)</td> <td class="px-6 py-4 font-mono text-white">192.168.0.0 - 192.168.255.255</td>
<td><code>255.255.0.0</code></td> <td class="px-6 py-4 font-mono">/16 (Gesamt)</td>
<td>Klasse C (oft als /24 genutzt)</td> <td class="px-6 py-4 font-mono">255.255.0.0</td>
<td><span class="example-link" data-ip="192.168.1.1" data-cidr="24">Beispiel /24</span></td> <td class="px-6 py-4">Klasse C (oft als /24 genutzt)</td>
</tr> <td class="px-6 py-4"><span
<tr> class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
<td><code>172.16.0.0 - 172.31.255.255</code></td> data-ip="192.168.1.1" data-cidr="24">Beispiel /24</span></td>
<td><code>/12</code> (Gesamt)</td> </tr>
<td><code>255.240.0.0</code></td> <tr class="hover:bg-gray-700/30 transition-colors">
<td>Klasse B</td> <td class="px-6 py-4 font-mono text-white">172.16.0.0 - 172.31.255.255</td>
<td><span class="example-link" data-ip="172.16.10.5" data-cidr="16">Beispiel /16</span></td> <td class="px-6 py-4 font-mono">/12 (Gesamt)</td>
</tr> <td class="px-6 py-4 font-mono">255.240.0.0</td>
<tr> <td class="px-6 py-4">Klasse B</td>
<td><code>10.0.0.0 - 10.255.255.255</code></td> <td class="px-6 py-4"><span
<td><code>/8</code> (Gesamt)</td> class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
<td><code>255.0.0.0</code></td> data-ip="172.16.10.5" data-cidr="16">Beispiel /16</span></td>
<td>Klasse A</td> </tr>
<td><span class="example-link" data-ip="10.0.50.100" data-cidr="8">Beispiel /8</span></td> <tr class="hover:bg-gray-700/30 transition-colors">
</tr> <td class="px-6 py-4 font-mono text-white">10.0.0.0 - 10.255.255.255</td>
</tbody> <td class="px-6 py-4 font-mono">/8 (Gesamt)</td>
</table> <td class="px-6 py-4 font-mono">255.0.0.0</td>
</div> <td class="px-6 py-4">Klasse A</td>
<p class="mt-4 text-xs text-gray-400">Klicken Sie auf "Beispiel", um die Felder oben auszufüllen und die Berechnung zu starten.</p> <td class="px-6 py-4"><span
class="example-link text-purple-400 hover:text-purple-300 cursor-pointer underline"
data-ip="10.0.50.100" data-cidr="8">Beispiel /8</span></td>
</tr>
</tbody>
</table>
</div>
<p class="mt-4 text-xs text-gray-500 italic">Klicken Sie auf "Beispiel", um die Felder oben auszufüllen und
die Berechnung zu starten.</p>
</div> </div>
<!-- Globaler Fehlerbereich --> <!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div> <div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
</div> </div>
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500"> <footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p> <p>&copy; 2025 <a href="https://mrunk.de"
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> <!-- Footer mit Version hinzugefügt --> class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
<p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
<!-- Footer mit Version hinzugefügt -->
</footer> </footer>
<!-- Nur das Skript für den Rechner laden --> <!-- Nur das Skript für den Rechner laden -->
@@ -248,8 +338,8 @@
console.error('Failed to fetch version info:', error); console.error('Failed to fetch version info:', error);
if (commitShaEl) commitShaEl.textContent = 'error'; if (commitShaEl) commitShaEl.textContent = 'error';
if (globalErrorEl) { // Zeige Fehler global an, wenn Element existiert if (globalErrorEl) { // Zeige Fehler global an, wenn Element existiert
globalErrorEl.textContent = `Error loading version: ${error.message}`; globalErrorEl.textContent = `Error loading version: ${error.message}`;
globalErrorEl.classList.remove('hidden'); globalErrorEl.classList.remove('hidden');
} }
} }
} }
@@ -257,4 +347,5 @@
}); });
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -8,90 +9,230 @@
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<!-- Eigene Styles --> <!-- Eigene Styles -->
<style> <style>
/* Einfacher Lade-Spinner */ /* Einfacher Lade-Spinner (Tailwind animiert) */
.loader { .loader {
border: 4px solid rgba(168, 85, 247, 0.3); /* Lila transparent */ border: 4px solid rgba(168, 85, 247, 0.1);
border-left-color: #a855f7; /* Lila */ /* Lila sehr transparent */
border-left-color: #d8b4fe;
/* Helleres Lila */
border-radius: 50%; border-radius: 50%;
width: 24px; width: 24px;
height: 24px; height: 24px;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to {
transform: rotate(360deg);
}
} }
/* Glassmorphism Utilities */
.glass-panel {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05);
}
.glass-card {
background: rgba(31, 41, 55, 0.6);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.5s ease-out forwards;
}
/* Ergebnis-Pre-Formatierung */ /* Ergebnis-Pre-Formatierung */
.result-pre { .result-pre {
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-all; word-break: break-all;
font-family: monospace; font-family: 'Courier New', Courier, monospace;
background-color: #1f2937; /* Dunkelgrau */ background-color: rgba(0, 0, 0, 0.3);
color: #d1d5db; /* Hellgrau */ color: #e5e7eb;
padding: 1rem; padding: 1rem;
border-radius: 0.375rem; /* rounded-md */ border-radius: 0.375rem;
max-height: 600px; /* Mehr Höhe für WHOIS */ max-height: 600px;
overflow-y: auto; overflow-y: auto;
font-size: 0.875rem; /* text-sm */ font-size: 0.875rem;
border: 1px solid rgba(255, 255, 255, 0.05);
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
} }
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
/* Navigations-Styling */ /* Navigations-Styling */
nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1rem; } nav ul {
nav a { color: #c4b5fd; text-decoration: none; white-space: nowrap; } list-style: none;
nav a:hover { color: #a78bfa; text-decoration: underline; } padding: 0;
header { background-color: #374151; padding: 1rem; margin-bottom: 1.5rem; border-radius: 0.5rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } margin: 0;
@media (min-width: 768px) { header { flex-direction: row; justify-content: space-between; } } display: flex;
header h1 { font-size: 1.5rem; font-weight: bold; color: #e5e7eb; } flex-wrap: wrap;
.hidden { display: none; } gap: 0.5rem;
}
nav a {
color: #d1d5db;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.05);
}
nav a:hover {
color: #fff;
background: rgba(168, 85, 247, 0.2);
border-color: rgba(168, 85, 247, 0.4);
box-shadow: 0 0 15px rgba(168, 85, 247, 0.1);
}
nav a.active-link {
background: rgba(168, 85, 247, 0.3);
color: #fff;
border-color: #a855f7;
}
header {
background: rgba(31, 41, 55, 0.4);
backdrop-filter: blur(10px);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
header {
flex-direction: row;
justify-content: space-between;
}
}
header h1 {
background-clip: text;
}
.text-gradient {
background: linear-gradient(to right, #c084fc, #e879f9);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.hidden {
display: none !important;
}
</style> </style>
</head> </head>
<body class="bg-gray-900 text-gray-200 font-sans p-4 md:p-8">
<header> <body
<h1>uTools Network Suite</h1> class="bg-gray-950 text-gray-100 font-sans p-4 md:p-8 min-h-screen bg-[url('https://tailwindcss.com/_next/static/media/hero-dark.939eb757.png')] bg-cover bg-center bg-fixed selection:bg-purple-500 selection:text-white">
<header class="glass-panel">
<h1>uTools <span class="text-sm font-normal text-gray-400 opacity-75 tracking-wider uppercase ml-2">Network
Suite</span></h1>
<nav> <nav>
<ul> <ul>
<li><a href="index.html">IP Info & Tools</a></li> <li><a href="index.html">IP Info & Tools</a></li>
<li><a href="subnet-calculator.html">Subnetz Rechner</a></li> <li><a href="subnet-calculator.html">Subnetz Rechner</a></li>
<li><a href="dns-lookup.html">DNS Lookup</a></li> <li><a href="dns-lookup.html">DNS Lookup</a></li>
<li><a href="whois-lookup.html">WHOIS Lookup</a></li> <li><a href="whois-lookup.html" class="active-link">WHOIS Lookup</a></li>
<li><a href="mac-lookup.html">MAC Lookup</a></li> <li><a href="mac-lookup.html">MAC Lookup</a></li>
</ul> </ul>
</nav> </nav>
</header> </header>
<div class="container mx-auto max-w-4xl bg-gray-800 rounded-lg shadow-xl p-6"> <div
class="container mx-auto max-w-5xl glass-panel rounded-xl shadow-2xl p-6 md:p-8 backdrop-blur-xl border border-gray-800/50">
<h1 class="text-3xl font-bold mb-6 text-purple-400 text-center">WHOIS Lookup</h1> <h1 class="text-3xl font-bold mb-8 text-center text-gradient glitch-text">WHOIS Lookup</h1>
<!-- Bereich für WHOIS Lookup --> <!-- Bereich für WHOIS Lookup -->
<div class="mt-8 p-4 bg-gray-700 rounded"> <div class="mt-8 p-6 glass-card rounded-xl">
<div class="flex flex-col sm:flex-row gap-2 mb-4"> <div class="flex flex-col sm:flex-row gap-3 mb-6">
<input type="text" id="whois-query-input" placeholder="Enter domain or IP (e.g., google.com or 8.8.8.8)" <input type="text" id="whois-query-input" placeholder="Enter domain or IP (e.g., google.com or 8.8.8.8)"
class="flex-grow px-3 py-2 bg-gray-800 border border-gray-600 rounded text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono"> class="flex-grow px-4 py-3 bg-gray-900/50 border border-gray-700/50 rounded-lg text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent font-mono transition-all placeholder-gray-600">
<button id="whois-lookup-button" <button id="whois-lookup-button"
class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"> class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white font-bold py-3 px-6 rounded-lg shadow-lg hover:shadow-purple-500/25 transition-all duration-200 ease-in-out transform hover:-translate-y-0.5">
Lookup WHOIS Lookup WHOIS
</button> </button>
</div> </div>
<div id="whois-lookup-error" class="text-red-400 mb-4 hidden"></div> <div id="whois-lookup-error"
<div id="whois-lookup-results-section" class="hidden mt-4 border-t border-gray-600 pt-4"> class="text-red-400 mb-4 hidden p-3 bg-red-900/20 border border-red-500/30 rounded"></div>
<h3 class="text-lg font-semibold text-purple-300 mb-2">WHOIS Results for: <span id="whois-lookup-query" class="font-mono text-purple-400"></span></h3> <div id="whois-lookup-results-section" class="hidden mt-6 border-t border-gray-700/50 pt-6 fade-in">
<div id="whois-lookup-loader" class="loader hidden mb-2"></div> <h3 class="text-lg font-semibold text-purple-300 mb-4 flex items-center gap-2">
<pre id="whois-lookup-output" class="result-pre"></pre> <!-- Ergebnisbereich --> <div class="w-1.5 h-6 bg-purple-500 rounded-full"></div>
WHOIS Results for: <span id="whois-lookup-query" class="font-mono text-purple-400 ml-1"></span>
</h3>
<div id="whois-lookup-loader" class="loader hidden mb-4"></div>
<pre id="whois-lookup-output" class="result-pre custom-scrollbar"></pre> <!-- Ergebnisbereich -->
</div> </div>
</div> </div>
<!-- Globaler Fehlerbereich --> <!-- Globaler Fehlerbereich -->
<div id="global-error" class="mt-6 p-4 bg-red-800 text-red-100 rounded hidden"></div> <div id="global-error"
class="mt-6 p-4 bg-red-900/50 border border-red-500/50 text-red-100 rounded-lg hidden backdrop-blur shadow-lg">
</div>
<!-- Footer für Version --> <!-- Footer für Version -->
<footer class="mt-8 pt-4 border-t border-gray-600 text-center text-xs text-gray-500"> <footer class="mt-12 pt-6 border-t border-gray-700/30 text-center text-xs text-gray-500">
<p>&copy; 2025 <a href="https://mrunk.de" class="text-purple-400 hover:underline">MrUnknownDE</a></p> <p>&copy; 2025 <a href="https://mrunk.de"
<p>Version: <span id="commit-sha" class="font-mono">loading...</span></p> class="text-purple-400 hover:text-purple-300 transition-colors">MrUnknownDE</a></p>
</footer> <p class="mt-1">Version: <span id="commit-sha" class="font-mono text-gray-400">loading...</span></p>
</footer>
</div> </div>
<!-- Eigene JS-Logik für diese Seite --> <!-- Eigene JS-Logik für diese Seite -->
<script src="whois-lookup.js"></script> <script src="whois-lookup.js"></script>
</body> </body>
</html> </html>

View File

@@ -43,6 +43,11 @@ document.addEventListener('DOMContentLoaded', () => {
* @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement. * @param {function} displayFn - Funktion zur Formatierung und Anzeige der Daten im outputElement.
*/ */
async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) { async function fetchAndDisplay(endpoint, params, resultsSection, loaderElement, errorElement, queryElement, outputElement, displayFn) {
// Reset animation
resultsSection.classList.remove('fade-in');
void resultsSection.offsetWidth; // Trigger reflow
resultsSection.classList.add('fade-in');
resultsSection.classList.remove('hidden'); resultsSection.classList.remove('hidden');
loaderElement.classList.remove('hidden'); loaderElement.classList.remove('hidden');
errorElement.classList.add('hidden'); errorElement.classList.add('hidden');
@@ -94,10 +99,10 @@ document.addEventListener('DOMContentLoaded', () => {
function displayWhoisResults(data, outputEl) { function displayWhoisResults(data, outputEl) {
// WHOIS data can be large and unstructured, display as raw text // WHOIS data can be large and unstructured, display as raw text
if (typeof data.result === 'string') { if (typeof data.result === 'string') {
outputEl.textContent = data.result; // Display raw text outputEl.textContent = data.result; // Display raw text
} else { } else {
// Fallback if the result is not a string (shouldn't happen with current backend) // Fallback if the result is not a string (shouldn't happen with current backend)
outputEl.textContent = JSON.stringify(data.result, null, 2); outputEl.textContent = JSON.stringify(data.result, null, 2);
} }
} }