initial commit

This commit is contained in:
overcuriousity 2025-09-27 22:09:31 +02:00
parent 56e6b7483e
commit 51a3aacb38

809
index.html Normal file
View File

@ -0,0 +1,809 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Filesystem Calculator</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Consolas', 'Courier New', monospace;
background-color: #1a1a1a;
color: #e0e0e0;
line-height: 1.6;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* Header */
.header {
background-color: #2a2a2a;
border-bottom: 2px solid #3a3a3a;
padding: 15px 0;
}
.header-content {
max-width: 1400px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.logo {
font-size: 1.5em;
font-weight: bold;
color: #ffffff;
}
.nav {
display: flex;
gap: 20px;
}
.nav a {
color: #cccccc;
text-decoration: none;
transition: color 0.2s;
}
.nav a:hover {
color: #ffffff;
}
/* Main Content */
.main-content {
flex: 1;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
h1 {
text-align: center;
margin-bottom: 30px;
color: #ffffff;
font-size: 2.2em;
font-weight: normal;
}
/* Tabs */
.tabs {
display: flex;
background-color: #2a2a2a;
border-radius: 6px 6px 0 0;
border: 1px solid #3a3a3a;
border-bottom: none;
overflow-x: auto;
}
.tab {
padding: 15px 25px;
cursor: pointer;
background-color: #2a2a2a;
border-right: 1px solid #3a3a3a;
color: #cccccc;
transition: all 0.2s;
white-space: nowrap;
min-width: 120px;
text-align: center;
}
.tab:last-child {
border-right: none;
}
.tab:hover {
background-color: #353535;
}
.tab.active {
background-color: #3a3a3a;
color: #ffffff;
border-bottom: 2px solid #666666;
}
.tab-content {
display: none;
background-color: #2a2a2a;
border: 1px solid #3a3a3a;
border-radius: 0 0 6px 6px;
padding: 20px;
}
.tab-content.active {
display: block;
}
/* Sections */
.section {
background-color: #252525;
border-radius: 6px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #3a3a3a;
}
.section h2 {
color: #cccccc;
margin-bottom: 15px;
border-bottom: 1px solid #3a3a3a;
padding-bottom: 8px;
font-weight: normal;
font-size: 1.3em;
}
.constants {
background-color: #202020;
}
.results {
background-color: #202020;
}
.formulas {
background-color: #1a1a1a;
}
.formula-box {
background-color: #151515;
border: 1px solid #404040;
border-radius: 4px;
padding: 15px;
margin: 10px 0;
font-family: 'Consolas', monospace;
font-size: 0.9em;
}
.formula {
margin: 8px 0;
color: #d0d0d0;
word-wrap: break-word;
}
.calculated {
color: #ffffff;
font-weight: bold;
}
.input-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 15px;
margin: 20px 0;
}
@media (max-width: 768px) {
.input-grid {
grid-template-columns: 1fr;
gap: 12px;
}
}
.input-group {
display: flex;
flex-direction: column;
}
.input-group label {
margin-bottom: 6px;
color: #cccccc;
font-weight: normal;
font-size: 0.95em;
}
.input-group input {
padding: 12px;
background-color: #333333;
border: 1px solid #4a4a4a;
border-radius: 4px;
color: #ffffff;
font-family: 'Consolas', monospace;
font-size: 14px;
transition: border-color 0.2s;
}
.input-group input:focus {
outline: none;
border-color: #666666;
background-color: #383838;
}
.result-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #3a3a3a;
}
.result-item:last-child {
border-bottom: none;
}
.result-label {
color: #cccccc;
font-weight: normal;
flex: 1;
}
.result-value {
color: #ffffff;
font-family: 'Consolas', monospace;
text-align: right;
font-weight: bold;
min-width: 120px;
}
@media (max-width: 600px) {
.result-item {
flex-direction: column;
align-items: flex-start;
gap: 5px;
}
.result-value {
text-align: left;
min-width: auto;
}
}
@media (max-width: 600px) {
.header-content {
flex-direction: column;
gap: 10px;
}
.nav {
justify-content: center;
}
}
.error {
color: #ff8888;
font-style: italic;
}
/* Footer */
.footer {
background-color: #2a2a2a;
border-top: 1px solid #3a3a3a;
padding: 20px 0;
margin-top: 40px;
}
.footer-content {
max-width: 1400px;
margin: 0 auto;
padding: 0 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 30px;
}
.footer-section h3 {
color: #ffffff;
margin-bottom: 10px;
font-size: 1.1em;
}
.footer-section p,
.footer-section a {
color: #cccccc;
font-size: 0.9em;
text-decoration: none;
margin-bottom: 5px;
display: block;
}
.footer-section a:hover {
color: #ffffff;
}
.footer-bottom {
text-align: center;
padding-top: 20px;
margin-top: 20px;
border-top: 1px solid #3a3a3a;
color: #888888;
font-size: 0.85em;
}
@media (max-width: 768px) {
.main-content {
padding: 15px;
}
h1 {
font-size: 1.8em;
margin-bottom: 20px;
}
.section {
padding: 15px;
}
.formula-box {
padding: 12px;
font-size: 0.85em;
}
.tab {
padding: 12px 15px;
min-width: 100px;
}
}
@media (min-width: 1200px) {
.input-grid {
grid-template-columns: repeat(3, 1fr);
}
}
</style>
</head>
<body>
<header class="header">
<div class="header-content">
<div class="logo">Filesystem Calculator</div>
<nav class="nav">
<a href="#home">Home</a>
<a href="#contact">Contact</a>
</nav>
</div>
</header>
<main class="main-content">
<div class="container">
<h1>Filesystem Structure Calculator</h1>
<div class="tabs">
<div class="tab active" onclick="switchTab('fat1216')">FAT12/16</div>
<div class="tab" onclick="switchTab('fat32')">FAT32</div>
</div>
<!-- FAT12/16 Tab -->
<div class="tab-content active" id="fat1216">
<div class="section constants">
<h2>Konstanten</h2>
<div class="input-grid">
<div class="input-group">
<label for="baseOffset1216">Base Offset (Partition Start):</label>
<input type="text" id="baseOffset1216" value="0x0" placeholder="0x0">
</div>
<div class="input-group">
<label for="sectorSize1216">Größe eines Sektors (Bytes):</label>
<input type="text" id="sectorSize1216" value="0x200" placeholder="0x200">
</div>
</div>
</div>
<div class="section">
<h2>Eingabeparameter</h2>
<div class="input-grid">
<div class="input-group">
<label for="reservedSectors1216">Anzahl reservierter Sektoren:</label>
<input type="text" id="reservedSectors1216" placeholder="0x1">
</div>
<div class="input-group">
<label for="numFATs1216">Anzahl FATs:</label>
<input type="text" id="numFATs1216" placeholder="0x2">
</div>
<div class="input-group">
<label for="fatSizeBytes1216">Größe einer FAT (Bytes):</label>
<input type="text" id="fatSizeBytes1216" placeholder="0x1000">
</div>
<div class="input-group">
<label for="maxRootEntries1216">Anzahl max. Wurzelverzeichnis-Einträge:</label>
<input type="text" id="maxRootEntries1216" placeholder="0x200">
</div>
<div class="input-group">
<label for="partitionSize1216">Größe Partition (Bytes):</label>
<input type="text" id="partitionSize1216" placeholder="0x100000">
</div>
<div class="input-group">
<label for="clusterSizeSectors1216">Größe eines Clusters (Sektoren):</label>
<input type="text" id="clusterSizeSectors1216" placeholder="0x1">
</div>
<div class="input-group">
<label for="clusterNumber1216">Cluster Nummer (für Position):</label>
<input type="text" id="clusterNumber1216" placeholder="0x2">
</div>
</div>
</div>
<div class="section results">
<h2>Berechnete Werte</h2>
<div id="results1216">
<div class="result-item">
<span class="result-label">Beginn FAT-Bereich:</span>
<span class="result-value" id="fatStart1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe FAT-Bereich:</span>
<span class="result-value" id="fatSize1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Ende FAT-Bereich:</span>
<span class="result-value" id="fatEnd1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe Wurzelverzeichnis:</span>
<span class="result-value" id="rootDirSize1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Beginn Daten-Bereich:</span>
<span class="result-value" id="dataStart1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe Daten-Bereich:</span>
<span class="result-value" id="dataSize1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe eines Clusters:</span>
<span class="result-value" id="clusterSize1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Anzahl Cluster:</span>
<span class="result-value" id="numClusters1216">-</span>
</div>
<div class="result-item">
<span class="result-label">Beginn Cluster:</span>
<span class="result-value" id="clusterStart1216">-</span>
</div>
</div>
</div>
<div class="section formulas">
<h2>Berechnungsformeln FAT12/16</h2>
<div class="formula-box">
<div class="formula"><span class="calculated">Beginn FAT-Bereich</span> = Anzahl reservierter Sektoren × Größe eines Sektors + Base Offset</div>
<div class="formula"><span class="calculated">Größe FAT-Bereich</span> = Anzahl FATs × Größe einer FAT</div>
<div class="formula"><span class="calculated">Ende FAT-Bereich</span> = Beginn FAT-Bereich + Größe FAT-Bereich</div>
<div class="formula"><span class="calculated">Größe Wurzelverzeichnis</span> = Anzahl max. Wurzelverzeichnis-Einträge × 0x20</div>
<div class="formula"><span class="calculated">Beginn Daten-Bereich</span> = Ende FAT-Bereich + Größe Wurzelverzeichnis</div>
<div class="formula"><span class="calculated">Größe Daten-Bereich</span> = Größe Partition - (Beginn Daten-Bereich - Base Offset)</div>
<div class="formula"><span class="calculated">Größe eines Clusters</span> = Größe eines Sektors × Größe eines Clusters in Sektoren</div>
<div class="formula"><span class="calculated">Anzahl Cluster</span> = Größe Daten-Bereich ÷ Größe eines Clusters</div>
<div class="formula"><span class="calculated">Beginn Cluster</span> = Beginn Daten-Bereich + (Cluster - 0x2) × Größe eines Clusters</div>
</div>
</div>
</div>
<!-- FAT32 Tab -->
<div class="tab-content" id="fat32">
<div class="section constants">
<h2>Konstanten</h2>
<div class="input-grid">
<div class="input-group">
<label for="baseOffset32">Base Offset (Partition Start):</label>
<input type="text" id="baseOffset32" value="0x0" placeholder="0x0">
</div>
<div class="input-group">
<label for="sectorSize32">Größe eines Sektors (Bytes):</label>
<input type="text" id="sectorSize32" value="0x200" placeholder="0x200">
</div>
</div>
</div>
<div class="section">
<h2>Eingabeparameter</h2>
<div class="input-grid">
<div class="input-group">
<label for="reservedSectors32">Anzahl reservierter Sektoren:</label>
<input type="text" id="reservedSectors32" placeholder="0x20">
</div>
<div class="input-group">
<label for="numFATs32">Anzahl FATs:</label>
<input type="text" id="numFATs32" placeholder="0x2">
</div>
<div class="input-group">
<label for="fatSizeBytes32">Größe einer FAT (Bytes):</label>
<input type="text" id="fatSizeBytes32" placeholder="0x10000">
</div>
<div class="input-group">
<label for="rootDirCluster32">Root Directory Cluster:</label>
<input type="text" id="rootDirCluster32" placeholder="0x2">
</div>
<div class="input-group">
<label for="partitionSize32">Größe Partition (Bytes):</label>
<input type="text" id="partitionSize32" placeholder="0x10000000">
</div>
<div class="input-group">
<label for="clusterSizeSectors32">Größe eines Clusters (Sektoren):</label>
<input type="text" id="clusterSizeSectors32" placeholder="0x8">
</div>
<div class="input-group">
<label for="clusterNumber32">Cluster Nummer (für Position):</label>
<input type="text" id="clusterNumber32" placeholder="0x2">
</div>
</div>
</div>
<div class="section results">
<h2>Berechnete Werte</h2>
<div id="results32">
<div class="result-item">
<span class="result-label">Beginn FAT-Bereich:</span>
<span class="result-value" id="fatStart32">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe FAT-Bereich:</span>
<span class="result-value" id="fatSize32">-</span>
</div>
<div class="result-item">
<span class="result-label">Ende FAT-Bereich:</span>
<span class="result-value" id="fatEnd32">-</span>
</div>
<div class="result-item">
<span class="result-label">Beginn Daten-Bereich:</span>
<span class="result-value" id="dataStart32">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe Daten-Bereich:</span>
<span class="result-value" id="dataSize32">-</span>
</div>
<div class="result-item">
<span class="result-label">Größe eines Clusters:</span>
<span class="result-value" id="clusterSize32">-</span>
</div>
<div class="result-item">
<span class="result-label">Anzahl Cluster:</span>
<span class="result-value" id="numClusters32">-</span>
</div>
<div class="result-item">
<span class="result-label">Beginn Cluster:</span>
<span class="result-value" id="clusterStart32">-</span>
</div>
<div class="result-item">
<span class="result-label">Root Directory Position:</span>
<span class="result-value" id="rootDirPos32">-</span>
</div>
</div>
</div>
<div class="section formulas">
<h2>Berechnungsformeln FAT32</h2>
<div class="formula-box">
<div class="formula"><span class="calculated">Beginn FAT-Bereich</span> = Anzahl reservierter Sektoren × Größe eines Sektors + Base Offset</div>
<div class="formula"><span class="calculated">Größe FAT-Bereich</span> = Anzahl FATs × Größe einer FAT</div>
<div class="formula"><span class="calculated">Ende FAT-Bereich</span> = Beginn FAT-Bereich + Größe FAT-Bereich</div>
<div class="formula"><span class="calculated">Beginn Daten-Bereich</span> = Ende FAT-Bereich (kein festes Root Directory)</div>
<div class="formula"><span class="calculated">Größe Daten-Bereich</span> = Größe Partition - (Beginn Daten-Bereich - Base Offset)</div>
<div class="formula"><span class="calculated">Größe eines Clusters</span> = Größe eines Sektors × Größe eines Clusters in Sektoren</div>
<div class="formula"><span class="calculated">Anzahl Cluster</span> = Größe Daten-Bereich ÷ Größe eines Clusters</div>
<div class="formula"><span class="calculated">Beginn Cluster</span> = Beginn Daten-Bereich + (Cluster - 0x2) × Größe eines Clusters</div>
<div class="formula"><span class="calculated">Root Directory Position</span> = Beginn Daten-Bereich + (Root Directory Cluster - 0x2) × Größe eines Clusters</div>
</div>
</div>
</div>
</div>
</main>
<footer class="footer">
<div class="footer-content">
<div class="footer-section">
<h3>About</h3>
<p>Filesystem calculator for educational and forensic purposes.</p>
<p>Version 0.1.0</p>
</div>
<div class="footer-section">
<h3>Support</h3>
<a href="#contact">Contact Support</a>
<a href="#bug-report">Report Bug</a>
</div>
<div class="footer-section">
<h3>Legal</h3>
<a href="#privacy">Privacy Policy</a>
<a href="#terms">Terms of Service</a>
<a href="#license">License</a>
</div>
<div class="footer-section">
<h3>Connect</h3>
<a href="#github">Gitea Repository</a>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 Filesystem Calculator. All rights reserved. | Built with ❤️ for computer science education.</p>
</div>
</footer>
<script>
// Filesystem calculation implementations
const filesystems = {
fat1216: {
requiredFields: ['reservedSectors1216', 'numFATs1216', 'fatSizeBytes1216', 'maxRootEntries1216', 'partitionSize1216', 'clusterSizeSectors1216'],
calculate: function() {
const baseOffset = parseHex(document.getElementById('baseOffset1216').value);
const sectorSize = parseHex(document.getElementById('sectorSize1216').value);
const reservedSectors = parseHex(document.getElementById('reservedSectors1216').value);
const numFATs = parseHex(document.getElementById('numFATs1216').value);
const fatSizeBytes = parseHex(document.getElementById('fatSizeBytes1216').value);
const maxRootEntries = parseHex(document.getElementById('maxRootEntries1216').value);
const partitionSize = parseHex(document.getElementById('partitionSize1216').value);
const clusterSizeSectors = parseHex(document.getElementById('clusterSizeSectors1216').value);
const clusterNumber = parseHex(document.getElementById('clusterNumber1216').value);
const fatStart = reservedSectors * sectorSize + baseOffset;
const fatSize = numFATs * fatSizeBytes;
const fatEnd = fatStart + fatSize;
const rootDirSize = maxRootEntries * 0x20;
const dataStart = fatEnd + rootDirSize;
const dataSize = partitionSize - (dataStart - baseOffset);
const clusterSize = sectorSize * clusterSizeSectors;
const numClusters = clusterSize > 0 ? Math.floor(dataSize / clusterSize) : 0;
const clusterStart = dataStart + (clusterNumber - 0x2) * clusterSize;
return {
fatStart, fatSize, fatEnd, rootDirSize, dataStart, dataSize,
clusterSize, numClusters, clusterStart
};
}
},
fat32: {
requiredFields: ['reservedSectors32', 'numFATs32', 'fatSizeBytes32', 'rootDirCluster32', 'partitionSize32', 'clusterSizeSectors32'],
calculate: function() {
const baseOffset = parseHex(document.getElementById('baseOffset32').value);
const sectorSize = parseHex(document.getElementById('sectorSize32').value);
const reservedSectors = parseHex(document.getElementById('reservedSectors32').value);
const numFATs = parseHex(document.getElementById('numFATs32').value);
const fatSizeBytes = parseHex(document.getElementById('fatSizeBytes32').value);
const rootDirCluster = parseHex(document.getElementById('rootDirCluster32').value);
const partitionSize = parseHex(document.getElementById('partitionSize32').value);
const clusterSizeSectors = parseHex(document.getElementById('clusterSizeSectors32').value);
const clusterNumber = parseHex(document.getElementById('clusterNumber32').value);
const fatStart = reservedSectors * sectorSize + baseOffset;
const fatSize = numFATs * fatSizeBytes;
const fatEnd = fatStart + fatSize;
const dataStart = fatEnd; // No fixed root directory in FAT32
const dataSize = partitionSize - (dataStart - baseOffset);
const clusterSize = sectorSize * clusterSizeSectors;
const numClusters = clusterSize > 0 ? Math.floor(dataSize / clusterSize) : 0;
const clusterStart = dataStart + (clusterNumber - 0x2) * clusterSize;
const rootDirPos = dataStart + (rootDirCluster - 0x2) * clusterSize;
return {
fatStart, fatSize, fatEnd, dataStart, dataSize,
clusterSize, numClusters, clusterStart, rootDirPos
};
}
}
};
function parseHex(value) {
if (!value) return 0;
let cleanValue = value.toString().trim();
if (cleanValue.startsWith('0x') || cleanValue.startsWith('0X')) {
cleanValue = cleanValue.substring(2);
}
const parsed = parseInt(cleanValue, 16);
return isNaN(parsed) ? 0 : parsed;
}
function formatHex(value) {
if (isNaN(value) || value < 0) {
return '<span class="error">Fehler</span>';
}
return '0x' + value.toString(16).toUpperCase();
}
function switchTab(tabId) {
// Hide all tab contents
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
// Remove active class from all tabs
document.querySelectorAll('.tab').forEach(tab => {
tab.classList.remove('active');
});
// Show selected tab content
document.getElementById(tabId).classList.add('active');
// Add active class to clicked tab
event.target.classList.add('active');
}
function calculate(fsType) {
try {
const fs = filesystems[fsType];
if (!fs) {
alert('Unknown filesystem type: ' + fsType);
return;
}
const results = fs.calculate();
// Update results based on filesystem type
if (fsType === 'fat1216') {
document.getElementById('fatStart1216').innerHTML = formatHex(results.fatStart);
document.getElementById('fatSize1216').innerHTML = formatHex(results.fatSize);
document.getElementById('fatEnd1216').innerHTML = formatHex(results.fatEnd);
document.getElementById('rootDirSize1216').innerHTML = formatHex(results.rootDirSize);
document.getElementById('dataStart1216').innerHTML = formatHex(results.dataStart);
document.getElementById('dataSize1216').innerHTML = formatHex(results.dataSize);
document.getElementById('clusterSize1216').innerHTML = formatHex(results.clusterSize);
document.getElementById('numClusters1216').innerHTML = formatHex(results.numClusters);
document.getElementById('clusterStart1216').innerHTML = formatHex(results.clusterStart);
} else if (fsType === 'fat32') {
document.getElementById('fatStart32').innerHTML = formatHex(results.fatStart);
document.getElementById('fatSize32').innerHTML = formatHex(results.fatSize);
document.getElementById('fatEnd32').innerHTML = formatHex(results.fatEnd);
document.getElementById('dataStart32').innerHTML = formatHex(results.dataStart);
document.getElementById('dataSize32').innerHTML = formatHex(results.dataSize);
document.getElementById('clusterSize32').innerHTML = formatHex(results.clusterSize);
document.getElementById('numClusters32').innerHTML = formatHex(results.numClusters);
document.getElementById('clusterStart32').innerHTML = formatHex(results.clusterStart);
document.getElementById('rootDirPos32').innerHTML = formatHex(results.rootDirPos);
}
} catch (error) {
alert('Fehler bei der Berechnung: ' + error.message);
console.error('Calculation error:', error);
}
}
function clearAll(fsType) {
const fs = filesystems[fsType];
if (!fs) return;
// Clear input fields
fs.requiredFields.forEach(fieldId => {
const element = document.getElementById(fieldId);
if (element) element.value = '';
});
// Clear cluster number field
const clusterField = document.getElementById(`clusterNumber${fsType === 'fat1216' ? '1216' : '32'}`);
if (clusterField) clusterField.value = '';
// Reset results
if (fsType === 'fat1216') {
const resultElements = ['fatStart1216', 'fatSize1216', 'fatEnd1216', 'rootDirSize1216', 'dataStart1216', 'dataSize1216', 'clusterSize1216', 'numClusters1216', 'clusterStart1216'];
resultElements.forEach(id => {
document.getElementById(id).innerHTML = '-';
});
} else if (fsType === 'fat32') {
const resultElements = ['fatStart32', 'fatSize32', 'fatEnd32', 'dataStart32', 'dataSize32', 'clusterSize32', 'numClusters32', 'clusterStart32', 'rootDirPos32'];
resultElements.forEach(id => {
document.getElementById(id).innerHTML = '-';
});
}
}
// Add event listeners for real-time calculation
document.addEventListener('DOMContentLoaded', function() {
Object.keys(filesystems).forEach(fsType => {
const fs = filesystems[fsType];
fs.requiredFields.forEach(fieldId => {
const input = document.getElementById(fieldId);
if (input) {
input.addEventListener('input', function() {
const allFilled = fs.requiredFields.every(id =>
document.getElementById(id).value.trim() !== ''
);
if (allFilled) {
calculate(fsType);
}
});
}
});
});
});
</script>
</body>
</html>
87.123.43.152