Persist file categories on the index and classify archives and unknown types during idle maintenance.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
84
src/Explorer.Domain/FileSignatureClassifier.cs
Normal file
84
src/Explorer.Domain/FileSignatureClassifier.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
namespace Explorer.Domain;
|
||||
|
||||
/// <summary>Light magic-byte hints for files with no useful extension category.</summary>
|
||||
public static class FileSignatureClassifier
|
||||
{
|
||||
public static FileClassification? TryClassify(ReadOnlySpan<byte> header)
|
||||
{
|
||||
if (header.Length < 4)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF)
|
||||
{
|
||||
return new FileClassification(FileCategory.Photos, "JPEG signature.");
|
||||
}
|
||||
|
||||
if (header.Length >= 8
|
||||
&& header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47)
|
||||
{
|
||||
return new FileClassification(FileCategory.Photos, "PNG signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x47 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x38)
|
||||
{
|
||||
return new FileClassification(FileCategory.Photos, "GIF signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x25 && header[1] == 0x50 && header[2] == 0x44 && header[3] == 0x46)
|
||||
{
|
||||
return new FileClassification(FileCategory.Documents, "PDF signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x50 && header[1] == 0x4B && (header[2] == 0x03 || header[2] == 0x05 || header[2] == 0x07))
|
||||
{
|
||||
return new FileClassification(FileCategory.Archive, "ZIP-family signature.");
|
||||
}
|
||||
|
||||
if (header.Length >= 12
|
||||
&& header[0] == 0x52 && header[1] == 0x49 && header[2] == 0x46 && header[3] == 0x46)
|
||||
{
|
||||
var form = System.Text.Encoding.ASCII.GetString(header.Slice(8, 4));
|
||||
if (form is "WAVE" or "AVI ")
|
||||
{
|
||||
return new FileClassification(
|
||||
form == "WAVE" ? FileCategory.Audio : FileCategory.Video,
|
||||
"RIFF " + form.Trim() + " signature.");
|
||||
}
|
||||
}
|
||||
|
||||
if (header.Length >= 12
|
||||
&& header[4] == 0x66 && header[5] == 0x74 && header[6] == 0x79 && header[7] == 0x70)
|
||||
{
|
||||
return new FileClassification(FileCategory.Video, "ISO BMFF (ftyp) signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x49 && header[1] == 0x44 && header[2] == 0x33)
|
||||
{
|
||||
return new FileClassification(FileCategory.Audio, "ID3 signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x7F && header[1] == 0x45 && header[2] == 0x4C && header[3] == 0x46)
|
||||
{
|
||||
return new FileClassification(FileCategory.Installer, "ELF binary signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x4D && header[1] == 0x5A)
|
||||
{
|
||||
return new FileClassification(FileCategory.Installer, "PE/MZ signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x37 && header[1] == 0x7A && header[2] == 0xBC && header[3] == 0xAF)
|
||||
{
|
||||
return new FileClassification(FileCategory.Archive, "7z signature.");
|
||||
}
|
||||
|
||||
if (header[0] == 0x52 && header[1] == 0x61 && header[2] == 0x72 && header[3] == 0x21)
|
||||
{
|
||||
return new FileClassification(FileCategory.Archive, "RAR signature.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user