43 lines
1.2 KiB
Elixir
43 lines
1.2 KiB
Elixir
|
defmodule FileSniffer do
|
||
|
@signatures [
|
||
|
{<<0x7F, 0x45, 0x4C, 0x46>>, "application/octet-stream"},
|
||
|
{<<0x42, 0x4D>>, "image/bmp"},
|
||
|
{<<0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A>>, "image/png"},
|
||
|
{<<0xFF, 0xD8, 0xFF>>, "image/jpg"},
|
||
|
{<<0x47, 0x49, 0x46>>, "image/gif"}
|
||
|
]
|
||
|
|
||
|
@file_types %{
|
||
|
"exe" => "application/octet-stream",
|
||
|
"bmp" => "image/bmp",
|
||
|
"png" => "image/png",
|
||
|
"jpg" => "image/jpg",
|
||
|
"gif" => "image/gif"
|
||
|
}
|
||
|
|
||
|
def type_from_extension(extension), do: @file_types[extension]
|
||
|
|
||
|
def type_from_binary(file_binary) do
|
||
|
Enum.find_value(@signatures, fn {signature, type} ->
|
||
|
with signature_size <- byte_size(signature),
|
||
|
<<file_signature::binary-size(signature_size), _rest::binary>> <- file_binary,
|
||
|
true <- file_signature == signature do
|
||
|
type
|
||
|
else
|
||
|
_ -> nil
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
def verify(file_binary, extension) do
|
||
|
ext_type = type_from_extension(extension)
|
||
|
bin_type = type_from_binary(file_binary)
|
||
|
case ext_type == bin_type do
|
||
|
true when ext_type != nil and bin_type != nil ->
|
||
|
{:ok, ext_type}
|
||
|
_ ->
|
||
|
{:error, "Warning, file format and file extension do not match."}
|
||
|
end
|
||
|
end
|
||
|
end
|