mcard-js
Version:
MCard - Content-addressable storage with cryptographic hashing, handle resolution, and vector search for Node.js and browsers
84 lines • 3.36 kB
JavaScript
export class BinarySignatureDetector {
// Dictionary of binary signatures mapped to MIME types
// Note: In TS, we use numbers or number arrays for bytes
static SIGNATURES = {
// Images
'89504e470d0a1a0a': 'image/png', // \x89PNG\r\n\x1a\n
'ffd8ff': 'image/jpeg',
'474946383761': 'image/gif', // GIF87a
'474946383961': 'image/gif', // GIF89a
'424d': 'image/bmp', // BM
'00000100': 'image/x-icon',
'00000200': 'image/x-icon',
// MP4
'00000018667479706d703432': 'video/mp4', // ...ftypmp42
'000000186674797069736f6d': 'video/mp4', // ...ftypisom
// ... (simplified for key common ones)
// Documents
'25504446': 'application/pdf', // %PDF
// Archives
'504b0304': 'application/zip', // PK\x03\x04
'1f8b08': 'application/gzip',
'526172211a0700': 'application/x-rar-compressed', // Rar!
'377abcaf271c': 'application/x-7z-compressed', // 7z...
// Database
'53514c69746520666f726d6174203300': 'application/x-sqlite3', // SQLite format 3\0
};
static OLE_SIGNATURE = 'd0cf11e0a1b11ae1';
/**
* Helper to convert hex string to Uint8Array for easy comparison if needed,
* but we will convert input bytes to hex for lookup.
*/
detect(content) {
return this.detectFromBytes(content);
}
detectFromBytes(content) {
// Handle RIFF (WAV, WebP)
if (this.startsWithAscii(content, 'RIFF')) {
return this.detectRiffFormat(content);
}
// Convert start of content to hex string for signature matching
// Max signature length is roughly 16 bytes for what we have
const hexHeader = this.toHex(content.slice(0, 32));
for (const [signature, mimeType] of Object.entries(BinarySignatureDetector.SIGNATURES)) {
if (hexHeader.startsWith(signature)) {
if (signature === BinarySignatureDetector.OLE_SIGNATURE) {
return 'application/oleobject';
}
if (signature === '504b0304') { // PK\x03\x04
// Check logic for OpenXML could go here, but omitted for parity with basic Python logic shown
return 'application/zip';
}
return mimeType;
}
}
return 'application/octet-stream';
}
detectRiffFormat(content) {
if (content.length < 12)
return 'application/octet-stream';
// Check format type at offset 8
const formatType = this.toAscii(content.slice(8, 12));
if (formatType === 'WAVE')
return 'audio/wav';
if (formatType === 'WEBP')
return 'image/webp';
return 'application/octet-stream';
}
startsWithAscii(content, str) {
if (content.length < str.length)
return false;
for (let i = 0; i < str.length; i++) {
if (content[i] !== str.charCodeAt(i))
return false;
}
return true;
}
toAscii(content) {
return Array.from(content).map(b => String.fromCharCode(b)).join('');
}
toHex(content) {
return Array.from(content).map(b => b.toString(16).padStart(2, '0')).join('');
}
}
//# sourceMappingURL=BinarySignatureDetector.js.map