diff --git a/index.html b/index.html
index d276a17..c56d590 100644
--- a/index.html
+++ b/index.html
@@ -77,9 +77,20 @@
.drop-zone:hover { background: #f0f8ff; }
/* TABLE */
- .table-header { background-color: #e9ecef; color: #333; font-weight: 700; border-bottom: 2px solid #ccc; }
- .hash-font { font-family: 'Courier New', monospace; font-size: 0.8rem; color: #004085; }
- .search-input { border-radius: 4px; padding: 8px 15px; border: 1px solid #ddd; background: white; }
+ .table-header { background-color: #e9ecef; color: #333; font-weight: 700; border-bottom: 2px solid #ccc; }
+ .hash-font { font-family: 'Courier New', monospace; font-size: 0.8rem; color: #004085; }
+ .search-input { border-radius: 4px; padding: 8px 15px; border: 1px solid #ddd; background: white; }
+ .system-console {
+ background: #0b1623;
+ color: #d7e6f5;
+ border-radius: 8px;
+ max-height: 150px;
+ overflow-y: auto;
+ font-family: 'Courier New', monospace;
+ font-size: 0.78rem;
+ }
+ .system-console-entry { border-bottom: 1px solid rgba(255,255,255,0.08); padding: 6px 10px; }
+ .system-console-entry:last-child { border-bottom: none; }
/* BLOG CARDS */
.news-section { background: #fff; padding: 60px 0; }
@@ -237,14 +248,19 @@
@@ -494,15 +521,17 @@
Yahoo/Outlook:
${file.name}
${isEml ? 'EMAIL' : ''}
- |
-
Calculating... |
-
Calculating... |
-
- `);
- fileQueue.push({ file, rowId });
- });
- if (!isProcessing) processQueue();
- }
+
+
Calculating... |
+
Calculating... |
+
Calculating... |
+
+ `);
+ fileQueue.push({ file, rowId });
+ logSystem(`Queued ${file.name} for MD5, SHA-256, and SHA-3-256 hashing.`);
+ });
+ if (!isProcessing) processQueue();
+ }
// PROCESS QUEUE
async function processQueue() {
@@ -516,12 +545,14 @@
Yahoo/Outlook:
reader.onload = function(e) {
const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
setTimeout(() => {
- if (row) {
- row.querySelector('.md5').innerText = CryptoJS.MD5(wordArray).toString();
- row.querySelector('.sha256').innerText = CryptoJS.SHA256(wordArray).toString();
- }
- processQueue();
- }, 50);
+ if (row) {
+ row.querySelector('.md5').innerText = CryptoJS.MD5(wordArray).toString();
+ row.querySelector('.sha256').innerText = CryptoJS.SHA256(wordArray).toString();
+ row.querySelector('.sha3').innerText = CryptoJS.SHA3(wordArray, { outputLength: 256 }).toString();
+ logSystem(`SHA-3-256 calculated for ${file.name}.`);
+ }
+ processQueue();
+ }, 50);
};
reader.readAsArrayBuffer(file);
}
@@ -610,9 +641,10 @@
Yahoo/Outlook:
for (let i = 0; i < files.length; i++) {
doc.addPage();
- const text = await readFile(files[i]);
- const emailData = parseEml(text);
- const sha256 = await calculateSHA256(files[i]);
+ const text = await readFile(files[i]);
+ const emailData = parseEml(text);
+ const sha256 = await calculateSHA256(files[i]);
+ const sha3 = await calculateSHA3(files[i]);
// HEADER WITH WRAPPED FILENAME
doc.setFillColor(0, 51, 102);
@@ -644,10 +676,11 @@
Yahoo/Outlook:
['To', emailData.to],
['Date', emailData.date],
['Message-ID', emailData.messageId],
- ['Originating IP', emailData.serverIP],
- ['DKIM Status', emailData.dkim],
- ['SHA-256 Hash', sha256]
- ],
+ ['Originating IP', emailData.serverIP],
+ ['DKIM Status', emailData.dkim],
+ ['SHA-256 Hash', sha256],
+ ['SHA-3-256 Hash', sha3]
+ ],
theme: 'grid',
headStyles: {
fillColor: [0, 51, 102],
@@ -713,12 +746,13 @@
Yahoo/Outlook:
if (tr.querySelector('input').checked) {
const cells = tr.querySelectorAll('td');
rows.push([
- cells[1].innerText,
- cells[2].innerText,
- cells[4].innerText
- ]);
- }
- });
+ cells[1].innerText,
+ cells[2].innerText,
+ cells[4].innerText,
+ cells[5].innerText
+ ]);
+ }
+ });
if (rows.length === 0) {
alert("Please select files to include in report.");
@@ -727,24 +761,25 @@
Yahoo/Outlook:
doc.autoTable({
startY: 70,
- head: [['#', 'Filename', 'SHA-256']],
- body: rows,
- theme: 'grid',
+ head: [['#', 'Filename', 'SHA-256', 'SHA-3-256']],
+ body: rows,
+ theme: 'grid',
headStyles: {
fillColor: [0, 51, 102],
fontSize: 11,
fontStyle: 'bold'
- },
- bodyStyles: {
- fontSize: 9,
- font: 'courier'
- },
- columnStyles: {
- 0: { cellWidth: 40 },
- 1: { cellWidth: 300 },
- 2: { cellWidth: 450, font: 'courier' }
- }
- });
+ },
+ bodyStyles: {
+ fontSize: 8,
+ font: 'courier'
+ },
+ columnStyles: {
+ 0: { cellWidth: 40 },
+ 1: { cellWidth: 240 },
+ 2: { cellWidth: 270, font: 'courier' },
+ 3: { cellWidth: 270, font: 'courier' }
+ }
+ });
doc.save("Hash_Report.pdf", { compress: true });
}
@@ -776,28 +811,38 @@
Yahoo/Outlook:
})],
shading: { fill: "003366" }
}),
- new TableCell({
- children: [new Paragraph({
- children: [new TextRun({ text: "SHA-256", bold: true, color: "FFFFFF" })],
- alignment: AlignmentType.CENTER
- })],
- shading: { fill: "003366" }
- })
- ]
- }));
+ new TableCell({
+ children: [new Paragraph({
+ children: [new TextRun({ text: "SHA-256", bold: true, color: "FFFFFF" })],
+ alignment: AlignmentType.CENTER
+ })],
+ shading: { fill: "003366" }
+ }),
+ new TableCell({
+ children: [new Paragraph({
+ children: [new TextRun({ text: "SHA-3-256", bold: true, color: "FFFFFF" })],
+ alignment: AlignmentType.CENTER
+ })],
+ shading: { fill: "003366" }
+ })
+ ]
+ }));
document.querySelectorAll("#hashTableBody tr").forEach(tr => {
if (tr.querySelector('input').checked) {
const cells = tr.querySelectorAll('td');
rows.push(new TableRow({
children: [
- new TableCell({ children: [new Paragraph(cells[1].innerText)] }),
- new TableCell({ children: [new Paragraph(cells[2].innerText)] }),
- new TableCell({ children: [new Paragraph({
- children: [new TextRun({ text: cells[4].innerText, font: "Courier New", size: 18 })]
- })] })
- ]
- }));
+ new TableCell({ children: [new Paragraph(cells[1].innerText)] }),
+ new TableCell({ children: [new Paragraph(cells[2].innerText)] }),
+ new TableCell({ children: [new Paragraph({
+ children: [new TextRun({ text: cells[4].innerText, font: "Courier New", size: 18 })]
+ })] }),
+ new TableCell({ children: [new Paragraph({
+ children: [new TextRun({ text: cells[5].innerText, font: "Courier New", size: 18 })]
+ })] })
+ ]
+ }));
}
});
@@ -835,34 +880,87 @@
Yahoo/Outlook:
});
}
- // ===== DOWNLOAD CSV =====
- function downloadSelectedCSV() {
- let csv = "#,Subject,From,To,Date,Originating IP,DKIM,SHA-256\n";
-
- let counter = 1;
- const promises = [];
-
- document.querySelectorAll("#hashTableBody tr").forEach(tr => {
- if (tr.querySelector('input').checked && tr.fileData && tr.fileData.name.toLowerCase().endsWith('.eml')) {
- const cells = tr.querySelectorAll('td');
- promises.push(
- readFile(tr.fileData).then(text => {
- const eml = parseEml(text);
- return `${counter++},"${eml.subject}","${eml.from}","${eml.to}","${eml.date}","${eml.serverIP}","${eml.dkim}","${cells[4].innerText}"\n`;
- })
- );
- }
- });
-
- Promise.all(promises).then(rows => {
- csv += rows.join('');
+ // ===== DOWNLOAD CSV =====
+ function downloadSelectedCSV() {
+ let csv = "#,Filename,MD5,SHA-256,SHA-3-256,Subject,From,To,Date,Originating IP,DKIM\n";
+
+ let counter = 1;
+ const promises = [];
+
+ document.querySelectorAll("#hashTableBody tr").forEach(tr => {
+ if (tr.querySelector('input').checked && tr.fileData) {
+ const cells = tr.querySelectorAll('td');
+ const baseCells = [
+ counter++,
+ cells[2].innerText,
+ cells[3].innerText,
+ cells[4].innerText,
+ cells[5].innerText
+ ];
+
+ if (tr.fileData.name.toLowerCase().endsWith('.eml')) {
+ promises.push(readFile(tr.fileData).then(text => {
+ const eml = parseEml(text);
+ return [...baseCells, eml.subject, eml.from, eml.to, eml.date, eml.serverIP, eml.dkim]
+ .map(csvEscape)
+ .join(",") + "\n";
+ }));
+ } else {
+ promises.push(Promise.resolve([...baseCells, "", "", "", "", "", ""].map(csvEscape).join(",") + "\n"));
+ }
+ }
+ });
+
+ if (promises.length === 0) {
+ alert("Please select files to include in CSV report.");
+ return;
+ }
+
+ Promise.all(promises).then(rows => {
+ csv += rows.join('');
const blob = new Blob([csv], { type: 'text/csv' });
const a = document.createElement('a');
- a.href = URL.createObjectURL(blob);
- a.download = "Email_Report.csv";
- a.click();
- });
- }
+ a.href = URL.createObjectURL(blob);
+ a.download = "Hash_Report.csv";
+ a.click();
+ });
+ }
+
+ // ===== DOWNLOAD EXCEL-COMPATIBLE REPORT =====
+ function downloadSelectedExcel() {
+ const rows = [];
+ document.querySelectorAll("#hashTableBody tr").forEach(tr => {
+ if (tr.querySelector('input').checked) {
+ const cells = tr.querySelectorAll('td');
+ rows.push([cells[1].innerText, cells[2].innerText, cells[3].innerText, cells[4].innerText, cells[5].innerText]);
+ }
+ });
+
+ if (rows.length === 0) {
+ alert("Please select files to include in Excel report.");
+ return;
+ }
+
+ const tableRows = rows.map(row => (
+ "
" + row.map(value => `| ${htmlEscape(value)} | `).join("") + "
"
+ )).join("");
+ const workbook = `
+
+
+
+
+ | # | Filename | MD5 | SHA-256 | SHA-3-256 |
+ ${tableRows}
+
+
+
+ `;
+ const blob = new Blob([workbook], { type: "application/vnd.ms-excel" });
+ const a = document.createElement("a");
+ a.href = URL.createObjectURL(blob);
+ a.download = "Hash_Report.xls";
+ a.click();
+ }
// ===== UTILITY FUNCTIONS =====
function getSelectedEmlFiles() {
@@ -883,16 +981,51 @@
Yahoo/Outlook:
});
}
- async function calculateSHA256(file) {
- return new Promise(resolve => {
- const reader = new FileReader();
- reader.onload = e => {
+ async function calculateSHA256(file) {
+ return new Promise(resolve => {
+ const reader = new FileReader();
+ reader.onload = e => {
const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
resolve(CryptoJS.SHA256(wordArray).toString());
};
- reader.readAsArrayBuffer(file);
- });
- }
+ reader.readAsArrayBuffer(file);
+ });
+ }
+
+ async function calculateSHA3(file) {
+ return new Promise(resolve => {
+ const reader = new FileReader();
+ reader.onload = e => {
+ const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
+ resolve(CryptoJS.SHA3(wordArray, { outputLength: 256 }).toString());
+ };
+ reader.readAsArrayBuffer(file);
+ });
+ }
+
+ function csvEscape(value) {
+ return `"${String(value).replace(/"/g, '""')}"`;
+ }
+
+ function htmlEscape(value) {
+ return String(value)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
+
+ function logSystem(message) {
+ const consolePanel = document.getElementById('systemConsole');
+ if (!consolePanel) return;
+ const entry = document.createElement('div');
+ entry.className = 'system-console-entry';
+ entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
+ consolePanel.appendChild(entry);
+ consolePanel.scrollTop = consolePanel.scrollHeight;
+ window.console.info(`[System Console] ${message}`);
+ }
function toggleAll(checkbox) {
document.querySelectorAll('input[name="fileSelect"]').forEach(c => c.checked = checkbox.checked);