make icons
This commit is contained in:
@@ -146,10 +146,26 @@
|
||||
box-shadow: 0 8px 15px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.tool-card.method {
|
||||
border-left: 4px solid #9b59b6;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #f4f1ff 100%);
|
||||
}
|
||||
|
||||
.tool-card.software {
|
||||
border-left: 4px solid #3498db;
|
||||
}
|
||||
|
||||
.tool-card h3 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.3em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tool-icon {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.tool-card p {
|
||||
@@ -169,6 +185,12 @@
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.tag.method-tag {
|
||||
background: #e8e4ff;
|
||||
color: #9b59b6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tag.domain-agnostic {
|
||||
background: #e8f5e8;
|
||||
color: #27ae60;
|
||||
@@ -426,6 +448,42 @@
|
||||
margin: 10px 0;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.type-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.type-software {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.type-method {
|
||||
background: #9b59b6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.conditional-fields {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.conditional-fields.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.icon-input {
|
||||
font-size: 1.5em;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
width: 80px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -458,6 +516,14 @@
|
||||
<div class="stat-number" id="totalTools">0</div>
|
||||
<div class="stat-label">Total Tools</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number" id="softwareCount">0</div>
|
||||
<div class="stat-label">Software</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number" id="methodCount">0</div>
|
||||
<div class="stat-label">Methods</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number" id="totalDomains">0</div>
|
||||
<div class="stat-label">Domains</div>
|
||||
@@ -496,7 +562,7 @@
|
||||
|
||||
<!-- Tools Tab -->
|
||||
<div id="tools" class="tab-content">
|
||||
<input type="text" class="search-bar" id="searchBar" placeholder="🔍 Search tools by name, description, tags, domains, phases, or domain-agnostic categories..." onkeyup="filterTools()" />
|
||||
<input type="text" class="search-bar" id="searchBar" placeholder="🔍 Search tools by name, description, tags, domains, phases, or type..." onkeyup="filterTools()" />
|
||||
<div class="tools-grid" id="toolsGrid"></div>
|
||||
</div>
|
||||
|
||||
@@ -506,11 +572,31 @@
|
||||
<h3 id="editorTitle">Add New Tool</h3>
|
||||
<div id="messageArea"></div>
|
||||
<form id="toolForm">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr 100px; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="toolName">Tool Name *</label>
|
||||
<input type="text" id="toolName" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="toolType">Type *</label>
|
||||
<select id="toolType" required onchange="handleTypeChange()">
|
||||
<option value="">Select Type</option>
|
||||
<option value="software">Software</option>
|
||||
<option value="method">Method</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="toolIcon">Icon <small style="color: #7f8c8d; cursor: pointer;" onclick="showIconSuggestions()" title="Click for suggestions">💡 suggestions</small></label>
|
||||
<input type="text" id="toolIcon" class="icon-input" placeholder="🔧" maxlength="2" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description *</label>
|
||||
<textarea id="description" rows="3" required></textarea>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="skillLevel">Skill Level *</label>
|
||||
<select id="skillLevel" required>
|
||||
@@ -522,74 +608,75 @@
|
||||
<option value="expert">Expert</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description *</label>
|
||||
<textarea id="description" rows="3" required></textarea>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="url">URL</label>
|
||||
<input type="url" id="url" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="projectUrl">Project URL</label>
|
||||
<input type="url" id="projectUrl" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="license">License</label>
|
||||
<input type="text" id="license" />
|
||||
<!-- Software-specific fields -->
|
||||
<div id="softwareFields" class="conditional-fields">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="projectUrl">Project URL</label>
|
||||
<input type="url" id="projectUrl" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="license">License</label>
|
||||
<input type="text" id="license" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="accessType">Access Type</label>
|
||||
<select id="accessType">
|
||||
<option value="">Select Type</option>
|
||||
<option value="download">Download</option>
|
||||
<option value="server-based">CC24-Server</option>
|
||||
<option value="commercial">Commercial</option>
|
||||
<option value="built-in">Built-in</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="accessType">Access Type</label>
|
||||
<select id="accessType">
|
||||
<option value="">Select Type</option>
|
||||
<option value="download">Download</option>
|
||||
<option value="server-based">CC24-Server</option>
|
||||
<option value="commercial">Commercial</option>
|
||||
<option value="OS">Operating System</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="statusUrl">Status URL</label>
|
||||
<input type="url" id="statusUrl" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="knowledgebase" />
|
||||
<label for="knowledgebase">📚 Knowledgebase Tool</label>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||
<div class="form-group">
|
||||
<label for="statusUrl">Status URL</label>
|
||||
<input type="url" id="statusUrl" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="knowledgebase" />
|
||||
<label for="knowledgebase">📚 Knowledgebase Tool</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Platforms</label>
|
||||
<div class="checkbox-group" id="platformsCheckbox">
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-windows" value="Windows">
|
||||
<label for="platform-windows">Windows</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-linux" value="Linux">
|
||||
<label for="platform-linux">Linux</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-macos" value="macOS">
|
||||
<label for="platform-macos">macOS</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-web" value="Web">
|
||||
<label for="platform-web">Web</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-os" value="OS">
|
||||
<label for="platform-os">Operating System</label>
|
||||
<div class="form-group">
|
||||
<label>Platforms</label>
|
||||
<div class="checkbox-group" id="platformsCheckbox">
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-windows" value="Windows">
|
||||
<label for="platform-windows">Windows</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-linux" value="Linux">
|
||||
<label for="platform-linux">Linux</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-macos" value="macOS">
|
||||
<label for="platform-macos">macOS</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-web" value="Web">
|
||||
<label for="platform-web">Web</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-os" value="OS">
|
||||
<label for="platform-os">Operating System</label>
|
||||
</div>
|
||||
<div class="checkbox-item">
|
||||
<input type="checkbox" id="platform-hardware" value="Hardware">
|
||||
<label for="platform-hardware">Hardware</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -633,6 +720,8 @@
|
||||
|
||||
<div style="margin: 20px 0;">
|
||||
<button class="btn" onclick="selectAllTools()">Select All</button>
|
||||
<button class="btn" onclick="selectByType('software')">Select Software</button>
|
||||
<button class="btn" onclick="selectByType('method')">Select Methods</button>
|
||||
<button class="btn" onclick="clearSelection()">Clear Selection</button>
|
||||
<span id="selectionCount" style="margin-left: 20px; font-weight: bold;">0 selected</span>
|
||||
</div>
|
||||
@@ -643,11 +732,14 @@
|
||||
<button class="btn btn-warning" onclick="bulkUpdatePhases()">Update Phases</button>
|
||||
<button class="btn btn-warning" onclick="bulkUpdateDomainAgnostic()">Update Domain-Agnostic</button>
|
||||
<button class="btn btn-warning" onclick="bulkUpdateTags()">Update Tags</button>
|
||||
<button class="btn btn-warning" onclick="bulkUpdateType()">Update Type</button>
|
||||
<button class="btn btn-warning" onclick="bulkUpdateIcons()">🎨 Update Icons</button>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 15px;">
|
||||
<button class="btn" onclick="bulkSetKnowledgebase(true)">📚 Set as Knowledgebase</button>
|
||||
<button class="btn" onclick="bulkSetKnowledgebase(false)">📖 Remove Knowledgebase</button>
|
||||
<button class="btn" onclick="bulkClearField('icon')">🗑️ Clear Icons</button>
|
||||
<button class="btn" onclick="bulkClearField('tags')">🗑️ Clear All Tags</button>
|
||||
<button class="btn" onclick="bulkClearField('domains')">🗑️ Clear All Domains</button>
|
||||
</div>
|
||||
@@ -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 => `<span class="tag">${tag}</span>`).join('');
|
||||
const knowledgebaseIndicator = tool.knowledgebase ? '<span class="tag" style="background: #e8f5e8; color: #27ae60; font-weight: bold;">📚 Knowledgebase</span>' : '';
|
||||
const typeIndicator = `<span class="type-badge type-${tool.type || 'software'}">${tool.type || 'software'}</span>`;
|
||||
|
||||
// Add domain-agnostic indicators
|
||||
const domainAgnosticTags = (tool['domain-agnostic-software'] || []).map(cat => {
|
||||
@@ -986,7 +1136,11 @@
|
||||
}).join('');
|
||||
|
||||
card.innerHTML = `
|
||||
<h3>${tool.name}</h3>
|
||||
<h3>
|
||||
${tool.icon ? `<span class="tool-icon">${tool.icon}</span>` : ''}
|
||||
${tool.name}
|
||||
${typeIndicator}
|
||||
</h3>
|
||||
<div style="margin: 5px 0;">
|
||||
<div class="skill-badge ${skillClass}">${tool.skillLevel || 'intermediate'}</div>
|
||||
${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 ? '<span class="tag" style="background: #e8f5e8; color: #27ae60; font-weight: bold; margin-left: 10px;">📚 KB</span>' : '';
|
||||
const typeIndicator = `<span class="type-badge type-${tool.type || 'software'}" style="margin-left: 10px;">${tool.type || 'software'}</span>`;
|
||||
|
||||
card.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
|
||||
<input type="checkbox" ${isSelected ? 'checked' : ''} onchange="toggleToolSelection(${index})" />
|
||||
<h3 style="margin: 0;">${tool.name}</h3>
|
||||
<h3 style="margin: 0; display: flex; align-items: center; gap: 8px;">
|
||||
${tool.icon ? `<span class="tool-icon">${tool.icon}</span>` : ''}
|
||||
${tool.name}
|
||||
</h3>
|
||||
${typeIndicator}
|
||||
${knowledgebaseIndicator}
|
||||
</div>
|
||||
<div class="skill-badge ${skillClass}">${tool.skillLevel || 'intermediate'}</div>
|
||||
@@ -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`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user