adjust dual urls
This commit is contained in:
parent
b8183ec961
commit
b842df040c
@ -9,6 +9,7 @@ export interface Props {
|
|||||||
skillLevel: string;
|
skillLevel: string;
|
||||||
accessType: string;
|
accessType: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
projectUrl?: string;
|
||||||
license: string;
|
license: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
isHosted: boolean;
|
isHosted: boolean;
|
||||||
@ -20,6 +21,12 @@ const { tool } = Astro.props;
|
|||||||
|
|
||||||
// Determine card styling
|
// Determine card styling
|
||||||
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
||||||
|
|
||||||
|
// Check if tool has a valid project URL for hosted services
|
||||||
|
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||||
|
tool.projectUrl !== null &&
|
||||||
|
tool.projectUrl !== "" &&
|
||||||
|
tool.projectUrl.trim() !== "";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class={cardClass}>
|
<div class={cardClass}>
|
||||||
@ -74,7 +81,26 @@ const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Propri
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
<!-- Button section - different layouts for hosted vs non-hosted -->
|
||||||
{tool.isHosted ? 'Access Service' : 'Visit Website'}
|
{tool.isHosted && hasValidProjectUrl ? (
|
||||||
|
<!-- Two buttons for self-hosted tools with both URLs -->
|
||||||
|
<div style="display: flex; gap: 0.5rem;">
|
||||||
|
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
|
||||||
|
Project Page
|
||||||
</a>
|
</a>
|
||||||
|
<a href={tool.projectUrl} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
|
||||||
|
Access Service
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
) : tool.isHosted ? (
|
||||||
|
<!-- Single button for self-hosted tools with only project URL -->
|
||||||
|
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Project Page
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<!-- Single button for non-hosted tools -->
|
||||||
|
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Visit Website
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
@ -12,12 +12,21 @@ const domains = data.domains;
|
|||||||
const phases = data.phases;
|
const phases = data.phases;
|
||||||
const tools = data.tools;
|
const tools = data.tools;
|
||||||
|
|
||||||
// Create matrix structure
|
// Separate collaboration tools from domain-specific tools
|
||||||
|
const collaborationTools = tools.filter((tool: any) =>
|
||||||
|
tool.phases.includes('collaboration')
|
||||||
|
);
|
||||||
|
|
||||||
|
const domainTools = tools.filter((tool: any) =>
|
||||||
|
!tool.phases.includes('collaboration')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create matrix structure for domain-specific tools only
|
||||||
const matrix: Record<string, Record<string, any[]>> = {};
|
const matrix: Record<string, Record<string, any[]>> = {};
|
||||||
domains.forEach((domain: any) => {
|
domains.forEach((domain: any) => {
|
||||||
matrix[domain.id] = {};
|
matrix[domain.id] = {};
|
||||||
phases.forEach((phase: any) => {
|
phases.filter((phase: any) => phase.id !== 'collaboration').forEach((phase: any) => {
|
||||||
matrix[domain.id][phase.id] = tools.filter((tool: any) =>
|
matrix[domain.id][phase.id] = domainTools.filter((tool: any) =>
|
||||||
tool.domains.includes(domain.id) && tool.phases.includes(phase.id)
|
tool.domains.includes(domain.id) && tool.phases.includes(phase.id)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -25,11 +34,41 @@ domains.forEach((domain: any) => {
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div id="matrix-container" class="matrix-wrapper" style="display: none;">
|
<div id="matrix-container" class="matrix-wrapper" style="display: none;">
|
||||||
|
<!-- Collaboration Tools Section (compact horizontal layout for matrix view) -->
|
||||||
|
<div id="collaboration-tools-section" style="margin-bottom: 1.5rem;">
|
||||||
|
<h3 style="margin-bottom: 0.75rem; color: var(--color-text); font-size: 1.125rem;">General Tools for Collaboration</h3>
|
||||||
|
<div class="collaboration-tools-compact" id="collaboration-tools-container">
|
||||||
|
{collaborationTools.map((tool: any) => (
|
||||||
|
<div class={`collaboration-tool-compact ${tool.isHosted ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`}
|
||||||
|
onclick={`window.showToolDetails('${tool.name}')`}>
|
||||||
|
<div class="tool-compact-header">
|
||||||
|
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;">{tool.name}</h4>
|
||||||
|
<div style="display: flex; gap: 0.25rem;">
|
||||||
|
{tool.isHosted && <span class="badge-mini badge-primary">Self-Hosted</span>}
|
||||||
|
{tool.license !== 'Proprietary' && <span class="badge-mini badge-success">OSS</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p style="font-size: 0.75rem; color: var(--color-text-secondary); margin: 0.25rem 0; line-height: 1.3;">
|
||||||
|
{tool.description}
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; gap: 0.75rem; font-size: 0.6875rem; color: var(--color-text-secondary);">
|
||||||
|
<span>{tool.platforms.join(', ')}</span>
|
||||||
|
<span>•</span>
|
||||||
|
<span>{tool.skillLevel}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DFIR Tools Matrix -->
|
||||||
|
<div id="dfir-matrix-section">
|
||||||
|
<h2 style="margin-bottom: 1rem; color: var(--color-text);">DFIR Tools Matrix</h2>
|
||||||
<table class="matrix-table">
|
<table class="matrix-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 200px;">Domain / Phase</th>
|
<th style="width: 200px;">Domain / Phase</th>
|
||||||
{phases.map((phase: any) => (
|
{phases.filter((phase: any) => phase.id !== 'collaboration').map((phase: any) => (
|
||||||
<th>{phase.name}</th>
|
<th>{phase.name}</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
@ -38,7 +77,7 @@ domains.forEach((domain: any) => {
|
|||||||
{domains.map((domain: any) => (
|
{domains.map((domain: any) => (
|
||||||
<tr>
|
<tr>
|
||||||
<th>{domain.name}</th>
|
<th>{domain.name}</th>
|
||||||
{phases.map((phase: any) => (
|
{phases.filter((phase: any) => phase.id !== 'collaboration').map((phase: any) => (
|
||||||
<td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}>
|
<td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}>
|
||||||
{matrix[domain.id][phase.id].map((tool: any) => (
|
{matrix[domain.id][phase.id].map((tool: any) => (
|
||||||
<span
|
<span
|
||||||
@ -55,6 +94,7 @@ domains.forEach((domain: any) => {
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tool Details Modal -->
|
<!-- Tool Details Modal -->
|
||||||
@ -78,12 +118,11 @@ domains.forEach((domain: any) => {
|
|||||||
|
|
||||||
<div id="tool-tags" style="margin-bottom: 1rem;"></div>
|
<div id="tool-tags" style="margin-bottom: 1rem;"></div>
|
||||||
|
|
||||||
<a id="tool-link" href="#" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
<!-- Updated button container for dual buttons -->
|
||||||
Visit Website
|
<div id="tool-links" style="display: flex; gap: 0.5rem;"></div>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script define:vars={{ toolsData: tools }}>
|
<script define:vars={{ toolsData: tools, collaborationTools, domainTools }}>
|
||||||
// Tool details functions
|
// Tool details functions
|
||||||
window.showToolDetails = function(toolName) {
|
window.showToolDetails = function(toolName) {
|
||||||
const tool = toolsData.find(t => t.name === toolName);
|
const tool = toolsData.find(t => t.name === toolName);
|
||||||
@ -105,14 +144,16 @@ domains.forEach((domain: any) => {
|
|||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
const metadataContainer = document.getElementById('tool-metadata');
|
const metadataContainer = document.getElementById('tool-metadata');
|
||||||
|
const domainsText = tool.domains.length > 0 ? tool.domains.join(', ') : 'Domain-agnostic';
|
||||||
|
const phasesText = tool.phases.join(', ');
|
||||||
metadataContainer.innerHTML = `
|
metadataContainer.innerHTML = `
|
||||||
<div style="display: grid; gap: 0.5rem;">
|
<div style="display: grid; gap: 0.5rem;">
|
||||||
<div><strong>Platforms:</strong> ${tool.platforms.join(', ')}</div>
|
<div><strong>Platforms:</strong> ${tool.platforms.join(', ')}</div>
|
||||||
<div><strong>Skill Level:</strong> ${tool.skillLevel}</div>
|
<div><strong>Skill Level:</strong> ${tool.skillLevel}</div>
|
||||||
<div><strong>License:</strong> ${tool.license}</div>
|
<div><strong>License:</strong> ${tool.license}</div>
|
||||||
<div><strong>Access Type:</strong> ${tool.accessType}</div>
|
<div><strong>Access Type:</strong> ${tool.accessType}</div>
|
||||||
<div><strong>Domains:</strong> ${tool.domains.join(', ')}</div>
|
<div><strong>Domains:</strong> ${domainsText}</div>
|
||||||
<div><strong>Phases:</strong> ${tool.phases.join(', ')}</div>
|
<div><strong>Phases:</strong> ${phasesText}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -124,10 +165,38 @@ domains.forEach((domain: any) => {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Link
|
// Links - Updated to handle dual buttons for self-hosted tools
|
||||||
const linkElement = document.getElementById('tool-link');
|
const linksContainer = document.getElementById('tool-links');
|
||||||
linkElement.href = tool.url;
|
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||||
linkElement.textContent = tool.isHosted ? 'Access Service' : 'Visit Website';
|
tool.projectUrl !== null &&
|
||||||
|
tool.projectUrl !== "" &&
|
||||||
|
tool.projectUrl.trim() !== "";
|
||||||
|
|
||||||
|
if (tool.isHosted && hasValidProjectUrl) {
|
||||||
|
// Two buttons for self-hosted tools with both URLs
|
||||||
|
linksContainer.innerHTML = `
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
|
||||||
|
Project Page
|
||||||
|
</a>
|
||||||
|
<a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
|
||||||
|
Access Service
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
} else if (tool.isHosted) {
|
||||||
|
// Single button for self-hosted tools with only project URL
|
||||||
|
linksContainer.innerHTML = `
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Project Page
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Single button for non-hosted tools
|
||||||
|
linksContainer.innerHTML = `
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Visit Website
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
// Show modal
|
// Show modal
|
||||||
document.getElementById('modal-overlay').classList.add('active');
|
document.getElementById('modal-overlay').classList.add('active');
|
||||||
@ -145,15 +214,58 @@ domains.forEach((domain: any) => {
|
|||||||
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
|
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
|
||||||
|
|
||||||
if (currentView === 'matrix') {
|
if (currentView === 'matrix') {
|
||||||
// Update matrix cells
|
const selectedPhase = document.getElementById('phase-select')?.value;
|
||||||
|
|
||||||
|
// Handle collaboration tools section
|
||||||
|
const collaborationSection = document.getElementById('collaboration-tools-section');
|
||||||
|
const dfirMatrixSection = document.getElementById('dfir-matrix-section');
|
||||||
|
const collaborationContainer = document.getElementById('collaboration-tools-container');
|
||||||
|
|
||||||
|
if (selectedPhase === 'collaboration') {
|
||||||
|
// Show only collaboration tools, hide matrix
|
||||||
|
collaborationSection.style.display = 'block';
|
||||||
|
dfirMatrixSection.style.display = 'none';
|
||||||
|
|
||||||
|
// Filter collaboration tools
|
||||||
|
const filteredCollaboration = filtered.filter(tool => tool.phases.includes('collaboration'));
|
||||||
|
collaborationContainer.innerHTML = '';
|
||||||
|
|
||||||
|
filteredCollaboration.forEach(tool => {
|
||||||
|
const toolCard = createCollaborationToolCardCompact(tool);
|
||||||
|
collaborationContainer.appendChild(toolCard);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Show matrix, handle collaboration tools visibility
|
||||||
|
dfirMatrixSection.style.display = 'block';
|
||||||
|
|
||||||
|
if (selectedPhase === '' || selectedPhase === null) {
|
||||||
|
// Show collaboration tools when no specific phase is selected
|
||||||
|
collaborationSection.style.display = 'block';
|
||||||
|
|
||||||
|
// Show all collaboration tools that pass general filters
|
||||||
|
const filteredCollaboration = filtered.filter(tool => tool.phases.includes('collaboration'));
|
||||||
|
collaborationContainer.innerHTML = '';
|
||||||
|
|
||||||
|
filteredCollaboration.forEach(tool => {
|
||||||
|
const toolCard = createCollaborationToolCardCompact(tool);
|
||||||
|
collaborationContainer.appendChild(toolCard);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Hide collaboration tools when specific DFIR phase is selected
|
||||||
|
collaborationSection.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear and update matrix cells with DFIR tools only
|
||||||
document.querySelectorAll('.matrix-cell').forEach(cell => {
|
document.querySelectorAll('.matrix-cell').forEach(cell => {
|
||||||
cell.innerHTML = '';
|
cell.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Re-populate with filtered tools
|
// Re-populate with filtered DFIR tools
|
||||||
filtered.forEach(tool => {
|
const filteredDfirTools = filtered.filter(tool => !tool.phases.includes('collaboration'));
|
||||||
|
filteredDfirTools.forEach(tool => {
|
||||||
tool.domains.forEach(domain => {
|
tool.domains.forEach(domain => {
|
||||||
tool.phases.forEach(phase => {
|
tool.phases.forEach(phase => {
|
||||||
|
if (phase !== 'collaboration') {
|
||||||
const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`);
|
const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`);
|
||||||
if (cell) {
|
if (cell) {
|
||||||
const chip = document.createElement('span');
|
const chip = document.createElement('span');
|
||||||
@ -162,9 +274,39 @@ domains.forEach((domain: any) => {
|
|||||||
chip.onclick = () => window.showToolDetails(tool.name);
|
chip.onclick = () => window.showToolDetails(tool.name);
|
||||||
cell.appendChild(chip);
|
cell.appendChild(chip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Helper function to create compact collaboration tool cards for matrix view
|
||||||
|
function createCollaborationToolCardCompact(tool) {
|
||||||
|
const cardDiv = document.createElement('div');
|
||||||
|
const cardClass = `collaboration-tool-compact ${tool.isHosted ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`;
|
||||||
|
cardDiv.className = cardClass;
|
||||||
|
cardDiv.onclick = () => window.showToolDetails(tool.name);
|
||||||
|
|
||||||
|
cardDiv.innerHTML = `
|
||||||
|
<div class="tool-compact-header">
|
||||||
|
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;">${tool.name}</h4>
|
||||||
|
<div style="display: flex; gap: 0.25rem;">
|
||||||
|
${tool.isHosted ? '<span class="badge-mini badge-primary">Self-Hosted</span>' : ''}
|
||||||
|
${tool.license !== 'Proprietary' ? '<span class="badge-mini badge-success">OSS</span>' : ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p style="font-size: 0.75rem; color: var(--color-text-secondary); margin: 0.25rem 0; line-height: 1.3;">
|
||||||
|
${tool.description}
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; gap: 0.75rem; font-size: 0.6875rem; color: var(--color-text-secondary);">
|
||||||
|
<span>${tool.platforms.join(', ')}</span>
|
||||||
|
<span>•</span>
|
||||||
|
<span>${tool.skillLevel}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return cardDiv;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@ -15,6 +15,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.autopsy.com/"
|
url: "https://www.autopsy.com/"
|
||||||
|
projectUrl: ""
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["disk-forensics", "file-recovery", "timeline-analysis"]
|
tags: ["disk-forensics", "file-recovery", "timeline-analysis"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -30,6 +31,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.volatilityfoundation.org/"
|
url: "https://www.volatilityfoundation.org/"
|
||||||
|
projectUrl: ""
|
||||||
license: "VSL"
|
license: "VSL"
|
||||||
tags: ["memory-forensics", "malware-analysis", "incident-response"]
|
tags: ["memory-forensics", "malware-analysis", "incident-response"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -48,7 +50,8 @@ tools:
|
|||||||
platforms: ["Web"]
|
platforms: ["Web"]
|
||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://thehive.example.lab"
|
url: "https://strangebee.com/"
|
||||||
|
projectUrl: ""
|
||||||
license: "AGPL-3.0"
|
license: "AGPL-3.0"
|
||||||
tags: ["incident-response", "case-management", "collaboration"]
|
tags: ["incident-response", "case-management", "collaboration"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -66,7 +69,8 @@ tools:
|
|||||||
platforms: ["Web"]
|
platforms: ["Web"]
|
||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://misp.example.lab"
|
url: "https://misp-project.org/"
|
||||||
|
projectUrl: "https://misp.cc24.dev"
|
||||||
license: "AGPL-3.0"
|
license: "AGPL-3.0"
|
||||||
tags: ["threat-intelligence", "ioc-sharing", "collaboration"]
|
tags: ["threat-intelligence", "ioc-sharing", "collaboration"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -83,7 +87,8 @@ tools:
|
|||||||
platforms: ["Web"]
|
platforms: ["Web"]
|
||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://timesketch.example.lab"
|
url: "https://timesketch.org/"
|
||||||
|
projectUrl: "https://timesketch.cc24.dev"
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["timeline-analysis", "collaboration", "visualization"]
|
tags: ["timeline-analysis", "collaboration", "visualization"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -101,6 +106,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.wireshark.org/"
|
url: "https://www.wireshark.org/"
|
||||||
|
projectUrl: ""
|
||||||
license: "GPL-2.0"
|
license: "GPL-2.0"
|
||||||
tags: ["network-analysis", "pcap", "protocol-analysis"]
|
tags: ["network-analysis", "pcap", "protocol-analysis"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -119,6 +125,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "commercial"
|
accessType: "commercial"
|
||||||
url: "https://www.opentext.com/products/encase-forensic"
|
url: "https://www.opentext.com/products/encase-forensic"
|
||||||
|
projectUrl: ""
|
||||||
license: "Proprietary"
|
license: "Proprietary"
|
||||||
tags: ["commercial", "enterprise", "court-approved"]
|
tags: ["commercial", "enterprise", "court-approved"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -135,6 +142,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://cuckoosandbox.org/"
|
url: "https://cuckoosandbox.org/"
|
||||||
|
projectUrl: ""
|
||||||
license: "GPL-3.0"
|
license: "GPL-3.0"
|
||||||
tags: ["malware-analysis", "sandbox", "dynamic-analysis"]
|
tags: ["malware-analysis", "sandbox", "dynamic-analysis"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -151,6 +159,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://exterro.com/ftk-imager"
|
url: "https://exterro.com/ftk-imager"
|
||||||
|
projectUrl: ""
|
||||||
license: "Proprietary"
|
license: "Proprietary"
|
||||||
tags: ["disk-imaging", "preview", "data-acquisition"]
|
tags: ["disk-imaging", "preview", "data-acquisition"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -167,6 +176,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://github.com/google/grr"
|
url: "https://github.com/google/grr"
|
||||||
|
projectUrl: ""
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["live-forensics", "remote-response", "dfir"]
|
tags: ["live-forensics", "remote-response", "dfir"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -183,6 +193,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://plaso.readthedocs.io/"
|
url: "https://plaso.readthedocs.io/"
|
||||||
|
projectUrl: ""
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["timeline-analysis", "log-parsing", "dfir"]
|
tags: ["timeline-analysis", "log-parsing", "dfir"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -198,6 +209,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.netresec.com/?page=NetworkMiner"
|
url: "https://www.netresec.com/?page=NetworkMiner"
|
||||||
|
projectUrl: ""
|
||||||
license: "Freeware/Commercial"
|
license: "Freeware/Commercial"
|
||||||
tags: ["pcap-analysis", "passive-sniffing", "credential-recovery"]
|
tags: ["pcap-analysis", "passive-sniffing", "credential-recovery"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -214,6 +226,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.mandiant.com/resources/download/redline"
|
url: "https://www.mandiant.com/resources/download/redline"
|
||||||
|
projectUrl: ""
|
||||||
license: "Proprietary"
|
license: "Proprietary"
|
||||||
tags: ["memory-analysis", "ioc-scan", "host-analysis"]
|
tags: ["memory-analysis", "ioc-scan", "host-analysis"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -230,6 +243,7 @@ tools:
|
|||||||
skillLevel: "intermediate"
|
skillLevel: "intermediate"
|
||||||
accessType: "download"
|
accessType: "download"
|
||||||
url: "https://www.kroll.com/en/services/cyber-risk/incident-response-litigation-support/kroll-artifact-parser-extractor-kape"
|
url: "https://www.kroll.com/en/services/cyber-risk/incident-response-litigation-support/kroll-artifact-parser-extractor-kape"
|
||||||
|
projectUrl: ""
|
||||||
license: "Freeware"
|
license: "Freeware"
|
||||||
tags: ["triage", "artifact-collection", "parsing"]
|
tags: ["triage", "artifact-collection", "parsing"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
@ -246,6 +260,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://www.velociraptor.app/"
|
url: "https://www.velociraptor.app/"
|
||||||
|
projectUrl: ""
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["dfir", "hunting", "endpoint-monitoring"]
|
tags: ["dfir", "hunting", "endpoint-monitoring"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -262,6 +277,7 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "self-hosted"
|
accessType: "self-hosted"
|
||||||
url: "https://arkime.com/"
|
url: "https://arkime.com/"
|
||||||
|
projectUrl: ""
|
||||||
license: "Apache 2.0"
|
license: "Apache 2.0"
|
||||||
tags: ["packet-capture", "full-packet-analysis", "network-forensics"]
|
tags: ["packet-capture", "full-packet-analysis", "network-forensics"]
|
||||||
isHosted: true
|
isHosted: true
|
||||||
@ -279,10 +295,43 @@ tools:
|
|||||||
skillLevel: "advanced"
|
skillLevel: "advanced"
|
||||||
accessType: "commercial"
|
accessType: "commercial"
|
||||||
url: "https://www.x-ways.net/forensics/"
|
url: "https://www.x-ways.net/forensics/"
|
||||||
|
projectUrl: ""
|
||||||
license: "Proprietary"
|
license: "Proprietary"
|
||||||
tags: ["disk-forensics", "file-recovery", "commercial"]
|
tags: ["disk-forensics", "file-recovery", "commercial"]
|
||||||
isHosted: false
|
isHosted: false
|
||||||
|
|
||||||
|
# Collaboration Tools - Domain-agnostic
|
||||||
|
- name: "Nextcloud"
|
||||||
|
description: "Self-hosted file sharing and collaboration platform for secure data exchange"
|
||||||
|
domains: [] # Domain-agnostic
|
||||||
|
phases:
|
||||||
|
- "collaboration"
|
||||||
|
platforms: ["Web"]
|
||||||
|
skillLevel: "beginner"
|
||||||
|
accessType: "self-hosted"
|
||||||
|
url: "https://nextcloud.com/de/"
|
||||||
|
projectUrl: "https://cloud.cc24.dev"
|
||||||
|
license: "AGPL-3.0"
|
||||||
|
tags: ["file-sharing", "collaboration", "document-management", "secure-storage"]
|
||||||
|
isHosted: true
|
||||||
|
statusUrl: "https://uptime.example.lab/api/badge/10/status"
|
||||||
|
|
||||||
|
- name: "Gitea"
|
||||||
|
description: "Lightweight self-hosted Git service for code collaboration and version control"
|
||||||
|
domains: [] # Domain-agnostic
|
||||||
|
phases:
|
||||||
|
- "collaboration"
|
||||||
|
platforms: ["Web"]
|
||||||
|
skillLevel: "intermediate"
|
||||||
|
accessType: "self-hosted"
|
||||||
|
url: "https://git.example.lab"
|
||||||
|
projectUrl: ""
|
||||||
|
license: "MIT"
|
||||||
|
tags: ["version-control", "git", "code-collaboration", "documentation"]
|
||||||
|
isHosted: true
|
||||||
|
statusUrl: "https://uptime.example.lab/api/badge/11/status"
|
||||||
|
|
||||||
|
|
||||||
# Domain definitions for reference
|
# Domain definitions for reference
|
||||||
domains:
|
domains:
|
||||||
- id: "storage-file-system"
|
- id: "storage-file-system"
|
||||||
@ -310,3 +359,5 @@ phases:
|
|||||||
name: "Analysis"
|
name: "Analysis"
|
||||||
- id: "reporting"
|
- id: "reporting"
|
||||||
name: "Reporting"
|
name: "Reporting"
|
||||||
|
- id: "collaboration"
|
||||||
|
name: "General Tools for Collaboration"
|
@ -104,12 +104,53 @@ const tools = data.tools;
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create tool card element
|
// This replaces the createToolCard function in index.astro script section
|
||||||
function createToolCard(tool: any): HTMLElement {
|
|
||||||
|
// This replaces the createToolCard function in index.astro script section
|
||||||
|
|
||||||
|
// This replaces the createToolCard function in index.astro script section
|
||||||
|
|
||||||
|
// Create tool card element
|
||||||
|
function createToolCard(tool) {
|
||||||
const cardDiv = document.createElement('div');
|
const cardDiv = document.createElement('div');
|
||||||
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
||||||
cardDiv.className = cardClass;
|
cardDiv.className = cardClass;
|
||||||
|
|
||||||
|
// Create button HTML based on hosting status
|
||||||
|
const hasValidProjectUrl = tool.projectUrl !== undefined &&
|
||||||
|
tool.projectUrl !== null &&
|
||||||
|
tool.projectUrl !== "" &&
|
||||||
|
tool.projectUrl.trim() !== "";
|
||||||
|
|
||||||
|
let buttonHTML;
|
||||||
|
if (tool.isHosted && hasValidProjectUrl) {
|
||||||
|
// Two buttons for self-hosted tools with both URLs
|
||||||
|
buttonHTML = `
|
||||||
|
<div style="display: flex; gap: 0.5rem;">
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
|
||||||
|
Project Page
|
||||||
|
</a>
|
||||||
|
<a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
|
||||||
|
Access Service
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (tool.isHosted) {
|
||||||
|
// Single button for self-hosted tools with only project URL
|
||||||
|
buttonHTML = `
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Project Page
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Single button for non-hosted tools
|
||||||
|
buttonHTML = `
|
||||||
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||||
|
Visit Website
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
cardDiv.innerHTML = `
|
cardDiv.innerHTML = `
|
||||||
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
|
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
|
||||||
<h3 style="margin: 0;">${tool.name}</h3>
|
<h3 style="margin: 0;">${tool.name}</h3>
|
||||||
@ -157,15 +198,13 @@ const tools = data.tools;
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem;">
|
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem;">
|
||||||
${tool.tags.map((tag: string) => `<span class="tag">${tag}</span>`).join('')}
|
${tool.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
${buttonHTML}
|
||||||
${tool.isHosted ? 'Access Service' : 'Visit Website'}
|
|
||||||
</a>
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return cardDiv;
|
return cardDiv;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
@ -472,6 +472,15 @@ footer {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
/* Add this inside the existing @media (max-width: 768px) block */
|
||||||
|
.collaboration-tools-compact {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collaboration-tool-compact {
|
||||||
|
min-width: auto;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
@ -483,3 +492,63 @@ footer {
|
|||||||
.fade-in {
|
.fade-in {
|
||||||
animation: fadeIn 0.3s ease-in;
|
animation: fadeIn 0.3s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compact Collaboration Tools for Matrix View */
|
||||||
|
.collaboration-tools-compact {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collaboration-tool-compact {
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
flex: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collaboration-tool-compact:hover {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collaboration-tool-compact.hosted {
|
||||||
|
background-color: var(--color-hosted-bg);
|
||||||
|
border-color: var(--color-hosted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collaboration-tool-compact.oss {
|
||||||
|
background-color: var(--color-oss-bg);
|
||||||
|
border-color: var(--color-oss);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-compact-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: start;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-mini {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.0625rem 0.375rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-mini.badge-primary {
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-mini.badge-success {
|
||||||
|
background-color: var(--color-accent);
|
||||||
|
color: white;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user