-
-
+
@@ -724,6 +816,25 @@
}
}
+ function handleTypeChange() {
+ const type = document.getElementById('toolType').value;
+ const softwareFields = document.getElementById('softwareFields');
+
+ if (type === 'method') {
+ softwareFields.classList.add('disabled');
+ // Clear software-specific fields for methods
+ document.getElementById('projectUrl').value = '';
+ document.getElementById('license').value = '';
+ document.getElementById('accessType').value = '';
+ document.getElementById('statusUrl').value = '';
+ document.getElementById('knowledgebase').checked = false;
+ // Clear platform checkboxes
+ document.querySelectorAll('#platformsCheckbox input').forEach(cb => cb.checked = false);
+ } else {
+ softwareFields.classList.remove('disabled');
+ }
+ }
+
function showMessage(message, type = 'success') {
const messageArea = document.getElementById('messageArea');
const className = type === 'error' ? 'error-message' : 'success-message';
@@ -757,24 +868,56 @@
}
function loadSampleData() {
- // This would load from your existing YAML data
- // For brevity, I'll just show the structure
try {
const sampleData = {
- tools: [], // Your existing tools
- domains: [], // Your existing domains
- phases: [], // Your existing phases
- "domain-agnostic-software": [
+ tools: [
{
- id: "collaboration-general",
- name: "Übergreifend & Kollaboration",
- description: "Cross-cutting tools and collaboration platforms"
+ name: "Autopsy",
+ icon: "📱",
+ type: "software",
+ description: "The leading open-source digital forensics platform.",
+ domains: ["incident-response", "law-enforcement"],
+ phases: ["examination", "analysis"],
+ platforms: ["Windows", "Linux"],
+ skillLevel: "intermediate",
+ accessType: "download",
+ url: "https://www.autopsy.com/",
+ projectUrl: "",
+ license: "Apache 2.0",
+ knowledgebase: false,
+ tags: ["gui", "filesystem", "timeline-analysis", "carving"]
},
{
- id: "specific-os",
- name: "Betriebssysteme",
- description: "Operating Systems which focus on forensics"
+ name: "Live Memory Acquisition Procedure",
+ icon: "🧠",
+ type: "method",
+ description: "Standardized procedure for forensically sound memory acquisition.",
+ domains: ["incident-response", "law-enforcement"],
+ phases: ["data-collection"],
+ platforms: [],
+ skillLevel: "advanced",
+ accessType: null,
+ url: "https://www.nist.gov/publications/guide-integrating-forensic-techniques-incident-response",
+ projectUrl: null,
+ license: null,
+ knowledgebase: false,
+ tags: ["memory-acquisition", "volatile-evidence", "procedure"]
}
+ ],
+ domains: [
+ { id: "incident-response", name: "Incident Response & Breach Investigation" },
+ { id: "law-enforcement", name: "Law Enforcement & Criminal Investigation" },
+ { id: "malware-analysis", name: "Malware Analysis & Reverse Engineering" }
+ ],
+ phases: [
+ { id: "data-collection", name: "Data Collection", description: "Imaging, Acquisition, Remote Collection Tools" },
+ { id: "examination", name: "Examination", description: "Parsing, Extraction, Initial Analysis Tools" },
+ { id: "analysis", name: "Analysis", description: "Deep Analysis, Correlation, Visualization Tools" },
+ { id: "reporting", name: "Reporting", description: "Documentation, Visualization, Presentation Tools" }
+ ],
+ "domain-agnostic-software": [
+ { id: "collaboration-general", name: "Collaboration & General", description: "Cross-cutting tools and collaboration platforms" },
+ { id: "specific-os", name: "Operating Systems", description: "Operating Systems which focus on forensics" }
]
};
yamlData = sampleData;
@@ -808,6 +951,12 @@
const tools = yamlData.tools;
document.getElementById('totalTools').textContent = tools.length;
+
+ const softwareCount = tools.filter(tool => tool.type === 'software').length;
+ const methodCount = tools.filter(tool => tool.type === 'method').length;
+ document.getElementById('softwareCount').textContent = softwareCount;
+ document.getElementById('methodCount').textContent = methodCount;
+
document.getElementById('totalDomains').textContent = yamlData.domains ? yamlData.domains.length : 0;
document.getElementById('totalPhases').textContent = yamlData.phases ? yamlData.phases.length : 0;
document.getElementById('totalDomainAgnostic').textContent = yamlData['domain-agnostic-software'] ? yamlData['domain-agnostic-software'].length : 0;
@@ -973,11 +1122,12 @@
function createToolCard(tool, index) {
const card = document.createElement('div');
- card.className = 'tool-card';
+ card.className = `tool-card ${tool.type || 'software'}`;
const skillClass = `skill-${tool.skillLevel || 'intermediate'}`;
const tags = (tool.tags || []).map(tag => `
${tag}`).join('');
const knowledgebaseIndicator = tool.knowledgebase ? '
📚 Knowledgebase' : '';
+ const typeIndicator = `
${tool.type || 'software'}`;
// Add domain-agnostic indicators
const domainAgnosticTags = (tool['domain-agnostic-software'] || []).map(cat => {
@@ -986,7 +1136,11 @@
}).join('');
card.innerHTML = `
-
${tool.name}
+
+ ${tool.icon ? `${tool.icon}` : ''}
+ ${tool.name}
+ ${typeIndicator}
+
${tool.skillLevel || 'intermediate'}
${knowledgebaseIndicator}
@@ -1004,16 +1158,21 @@
function createBulkToolCard(tool, index) {
const card = document.createElement('div');
- card.className = 'tool-card';
+ card.className = `tool-card ${tool.type || 'software'}`;
const skillClass = `skill-${tool.skillLevel || 'intermediate'}`;
const isSelected = selectedTools.has(index);
const knowledgebaseIndicator = tool.knowledgebase ? '
📚 KB' : '';
+ const typeIndicator = `
${tool.type || 'software'}`;
card.innerHTML = `
-
${tool.name}
+
+ ${tool.icon ? `${tool.icon}` : ''}
+ ${tool.name}
+
+ ${typeIndicator}
${knowledgebaseIndicator}
${tool.skillLevel || 'intermediate'}
@@ -1046,6 +1205,7 @@
const searchableText = [
tool.name || '',
tool.description || '',
+ tool.type || '',
...(tool.tags || []),
...(tool.domains || []),
...(tool.phases || []),
@@ -1077,6 +1237,8 @@
// Populate form fields
document.getElementById('toolName').value = tool.name || '';
+ document.getElementById('toolType').value = tool.type || 'software';
+ document.getElementById('toolIcon').value = tool.icon || '';
document.getElementById('description').value = tool.description || '';
document.getElementById('skillLevel').value = tool.skillLevel || '';
document.getElementById('url').value = tool.url || '';
@@ -1086,6 +1248,9 @@
document.getElementById('statusUrl').value = tool.statusUrl || '';
document.getElementById('knowledgebase').checked = tool.knowledgebase || false;
+ // Handle conditional fields
+ handleTypeChange();
+
// Set checkboxes
setCheckboxValues('#platformsCheckbox input', tool.platforms || []);
setCheckboxValues('#domainsCheckbox input', tool.domains || []);
@@ -1149,36 +1314,70 @@
yamlData.tools = [];
}
+ const toolType = document.getElementById('toolType').value;
const tool = {
name: document.getElementById('toolName').value,
+ type: toolType,
description: document.getElementById('description').value,
domains: getCheckedValues('#domainsCheckbox input:checked'),
phases: getCheckedValues('#phasesCheckbox input:checked'),
- platforms: getCheckedValues('#platformsCheckbox input:checked'),
- 'domain-agnostic-software': getCheckedValues('#domainAgnosticCheckbox input:checked'),
skillLevel: document.getElementById('skillLevel').value,
- accessType: document.getElementById('accessType').value,
url: document.getElementById('url').value,
- projectUrl: document.getElementById('projectUrl').value,
- license: document.getElementById('license').value,
- knowledgebase: document.getElementById('knowledgebase').checked,
tags: getTags()
};
+ // Add icon if provided
+ const icon = document.getElementById('toolIcon').value.trim();
+ if (icon) {
+ tool.icon = icon;
+ }
+
+ // Add software-specific fields
+ if (toolType === 'software') {
+ tool.platforms = getCheckedValues('#platformsCheckbox input:checked');
+ tool.accessType = document.getElementById('accessType').value;
+ tool.projectUrl = document.getElementById('projectUrl').value;
+ tool.license = document.getElementById('license').value;
+ tool.knowledgebase = document.getElementById('knowledgebase').checked;
+
+ const statusUrl = document.getElementById('statusUrl').value;
+ if (statusUrl) {
+ tool.statusUrl = statusUrl;
+ }
+ } else {
+ // For methods, set appropriate defaults
+ tool.platforms = [];
+ tool.accessType = null;
+ tool.projectUrl = null;
+ tool.license = null;
+ tool.knowledgebase = false;
+ }
+
+ // Add domain-agnostic software if selected
+ const domainAgnostic = getCheckedValues('#domainAgnosticCheckbox input:checked');
+ if (domainAgnostic.length > 0) {
+ tool['domain-agnostic-software'] = domainAgnostic;
+ } else {
+ tool['domain-agnostic-software'] = null;
+ }
+
// Clean up empty arrays and null values
Object.keys(tool).forEach(key => {
if (Array.isArray(tool[key]) && tool[key].length === 0) {
- delete tool[key];
+ if (key === 'platforms' && toolType === 'method') {
+ tool[key] = []; // Keep empty array for methods
+ } else {
+ delete tool[key];
+ }
} else if (tool[key] === '' || tool[key] === null) {
- delete tool[key];
+ if ((key === 'accessType' || key === 'projectUrl' || key === 'license') && toolType === 'method') {
+ tool[key] = null; // Keep null for methods
+ } else {
+ delete tool[key];
+ }
}
});
- const statusUrl = document.getElementById('statusUrl').value;
- if (statusUrl) {
- tool.statusUrl = statusUrl;
- }
-
if (currentEditingIndex >= 0) {
yamlData.tools[currentEditingIndex] = tool;
showMessage('Tool updated successfully!');
@@ -1213,6 +1412,7 @@
document.getElementById('tagContainer').querySelectorAll('.removable-tag').forEach(tag => tag.remove());
document.getElementById('editorTitle').textContent = 'Add New Tool';
document.getElementById('deleteBtn').style.display = 'none';
+ document.getElementById('softwareFields').classList.remove('disabled');
currentEditingIndex = -1;
}
@@ -1251,6 +1451,18 @@
}
}
+ function selectByType(type) {
+ if (yamlData && yamlData.tools) {
+ yamlData.tools.forEach((tool, index) => {
+ if (tool.type === type) {
+ selectedTools.add(index);
+ }
+ });
+ updateSelectionCount();
+ renderBulkGrid();
+ }
+ }
+
function clearSelection() {
selectedTools.clear();
updateSelectionCount();
@@ -1261,6 +1473,111 @@
document.getElementById('selectionCount').textContent = `${selectedTools.size} selected`;
}
+ function showIconSuggestions() {
+ const suggestions = `DFIR Tool Icons by Operational Mode:
+
+📦 Downloaded/Installed 🌐 Web Application ☁️ Cloud Service
+🖥️ Operating System ⌨️ Command Line 📡 Server/Self-hosted
+🔧 Hardware Tool 💰 Commercial ⚙️ Built-in/System
+📱 Mobile Application 🔗 API/Library 📋 Method/Procedure
+
+🖲️ Remote Access 💻 Desktop GUI 🛠️ Utility/Helper
+🏢 Enterprise Platform 🔓 Open Source 🎯 Specialized Tool
+📊 Analysis Platform 🗄️ Database/Storage 🔄 Processing Engine
+
+Most common combinations:
+📦 + 🔓 = Open Source Desktop Software
+🌐 + ☁️ = Cloud Web Application
+🖥️ + 🔓 = Forensic Live OS
+⌨️ + 🔧 = Command Line Utility
+📋 + 🎯 = Specialized Method
+
+Click any emoji to copy it, then paste into the icon field.`;
+
+ alert(suggestions);
+ }
+
+ function bulkUpdateIcons() {
+ if (selectedTools.size === 0) {
+ showMessage('No tools selected', 'error');
+ return;
+ }
+
+ // Show operational mode-focused icon suggestions
+ const suggestedIcons = `
+DFIR Tool Icons by Operational Mode:
+
+📦 Downloaded/Installed 🌐 Web Application ☁️ Cloud Service
+🖥️ Operating System ⌨️ Command Line 📡 Server/Self-hosted
+🔧 Hardware Tool 💰 Commercial ⚙️ Built-in/System
+📱 Mobile Application 🔗 API/Library 📋 Method/Procedure
+
+🖲️ Remote Access 💻 Desktop GUI 🛠️ Utility/Helper
+🏢 Enterprise Platform 🔓 Open Source 🎯 Specialized Tool
+📊 Analysis Platform 🗄️ Database/Storage 🔄 Processing Engine
+
+Quick suggestions by access type:
+• Downloaded Software: 📦
+• Web Applications: 🌐
+• Cloud Services: ☁️
+• Operating Systems: 🖥️
+• Command Line: ⌨️
+• Hardware: 🔧
+• Methods/Procedures: 📋`;
+
+ const icon = prompt(`Enter emoji icon (single character) or leave empty to remove:\n\n${suggestedIcons}`);
+
+ if (icon !== null) { // Allow empty string to remove icons
+ const trimmedIcon = icon.trim();
+ if (trimmedIcon.length > 2) {
+ showMessage('Icon should be a single emoji character', 'error');
+ return;
+ }
+
+ selectedTools.forEach(index => {
+ if (trimmedIcon === '') {
+ delete yamlData.tools[index].icon; // Remove icon field entirely
+ } else {
+ yamlData.tools[index].icon = trimmedIcon;
+ }
+ });
+
+ const action = trimmedIcon === '' ? 'removed icons from' : 'updated icons for';
+ showMessage(`Successfully ${action} ${selectedTools.size} tools`);
+ renderBulkGrid();
+ renderToolsGrid(); // Update tools view if visible
+ }
+ }
+
+ function bulkUpdateType() {
+ if (selectedTools.size === 0) {
+ showMessage('No tools selected', 'error');
+ return;
+ }
+
+ const type = prompt('Enter type (software/method):');
+ if (type && ['software', 'method'].includes(type)) {
+ selectedTools.forEach(index => {
+ yamlData.tools[index].type = type;
+
+ // Handle method-specific cleanup
+ if (type === 'method') {
+ yamlData.tools[index].platforms = [];
+ yamlData.tools[index].accessType = null;
+ yamlData.tools[index].projectUrl = null;
+ yamlData.tools[index].license = null;
+ yamlData.tools[index].knowledgebase = false;
+ if (yamlData.tools[index].statusUrl) {
+ delete yamlData.tools[index].statusUrl;
+ }
+ }
+ });
+ showMessage(`Updated type for ${selectedTools.size} tools`);
+ updateStats();
+ renderBulkGrid();
+ }
+ }
+
function bulkUpdateSkillLevel() {
if (selectedTools.size === 0) {
showMessage('No tools selected', 'error');
@@ -1352,19 +1669,29 @@
return;
}
- const action = value ? 'set as knowledgebase' : 'remove knowledgebase flag from';
- if (!confirm(`Are you sure you want to ${action} ${selectedTools.size} selected tools?`)) {
+ // Only apply to software tools
+ const softwareTools = Array.from(selectedTools).filter(index =>
+ yamlData.tools[index].type === 'software'
+ );
+
+ if (softwareTools.length === 0) {
+ showMessage('No software tools selected (knowledgebase only applies to software)', 'error');
return;
}
- selectedTools.forEach(index => {
+ const action = value ? 'set as knowledgebase' : 'remove knowledgebase flag from';
+ if (!confirm(`Are you sure you want to ${action} ${softwareTools.length} selected software tools?`)) {
+ return;
+ }
+
+ softwareTools.forEach(index => {
if (yamlData.tools[index]) {
yamlData.tools[index].knowledgebase = value;
}
});
const actionCompleted = value ? 'marked as knowledgebase' : 'removed knowledgebase flag from';
- showMessage(`Successfully ${actionCompleted} ${selectedTools.size} tools`);
+ showMessage(`Successfully ${actionCompleted} ${softwareTools.length} software tools`);
updateStats();
renderBulkGrid();
@@ -1383,11 +1710,23 @@
selectedTools.forEach(index => {
if (yamlData.tools[index]) {
+ const tool = yamlData.tools[index];
const arrayFields = ['tags', 'domains', 'phases', 'platforms', 'domain-agnostic-software'];
+
if (arrayFields.includes(fieldName)) {
- yamlData.tools[index][fieldName] = [];
+ if (fieldName === 'platforms' && tool.type === 'method') {
+ tool[fieldName] = []; // Keep empty array for methods
+ } else {
+ tool[fieldName] = [];
+ }
+ } else if (fieldName === 'icon') {
+ delete tool.icon; // Remove icon field entirely
} else {
- yamlData.tools[index][fieldName] = '';
+ if ((fieldName === 'projectUrl' || fieldName === 'accessType' || fieldName === 'license') && tool.type === 'method') {
+ tool[fieldName] = null; // Keep null for methods
+ } else {
+ tool[fieldName] = '';
+ }
}
}
});
@@ -1399,6 +1738,9 @@
}
renderBulkGrid();
+ if (fieldName === 'icon') {
+ renderToolsGrid(); // Update tools view to reflect icon changes
+ }
}
function bulkDelete() {
@@ -1438,6 +1780,25 @@
if (!tool.name) validationResults.push(`❌ Tool ${index + 1}: Missing name`);
if (!tool.description) validationResults.push(`❌ Tool ${index + 1}: Missing description`);
if (!tool.skillLevel) validationResults.push(`❌ Tool ${index + 1}: Missing skillLevel`);
+ if (!tool.type) validationResults.push(`❌ Tool ${index + 1}: Missing type`);
+ if (tool.type && !['software', 'method'].includes(tool.type)) {
+ validationResults.push(`❌ Tool ${index + 1}: Invalid type (must be 'software' or 'method')`);
+ }
+
+ // Software-specific validation
+ if (tool.type === 'software') {
+ if (!tool.platforms || tool.platforms.length === 0) {
+ validationResults.push(`❌ Tool ${index + 1}: Software must have platforms`);
+ }
+ if (!tool.license) validationResults.push(`❌ Tool ${index + 1}: Software should have license`);
+ }
+
+ // Method-specific validation
+ if (tool.type === 'method') {
+ if (tool.platforms && tool.platforms.length > 0) {
+ validationResults.push(`⚠️ Tool ${index + 1}: Methods should not have platforms`);
+ }
+ }
});
}
diff --git a/public/fingerprint_scope_logo.svg b/public/fingerprint_scope_logo.svg
deleted file mode 100644
index 35a8af9..0000000
--- a/public/fingerprint_scope_logo.svg
+++ /dev/null
@@ -1,60 +0,0 @@
-
\ No newline at end of file
diff --git a/src/components/AIQueryInterface.astro b/src/components/AIQueryInterface.astro
index d2e8f8f..fdab0f2 100644
--- a/src/components/AIQueryInterface.astro
+++ b/src/components/AIQueryInterface.astro
@@ -461,7 +461,10 @@ document.addEventListener('DOMContentLoaded', () => {