defmodule FileSniffer do
@exe_media_type "application/octet-stream"
@bmp_media_type "image/bmp"
@png_media_type "image/png"
@jpg_media_type "image/jpg"
@gif_media_type "image/gif"
@spec type_from_extension(String.t()) :: String.t()
def type_from_extension("exe"), do: @exe_media_type
def type_from_extension("bmp"), do: @bmp_media_type
def type_from_extension("png"), do: @png_media_type
def type_from_extension("jpg"), do: @jpg_media_type
def type_from_extension("gif"), do: @gif_media_type
@exe_signature <<0x7F, 0x45, 0x4C, 0x46>>
@bmp_signature <<0x42, 0x4D>>
@png_signature <<0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A>>
@jpg_signature <<0xFF, 0xD8, 0xFF>>
@gif_signature <<0x47, 0x49, 0x46>>
@spec type_from_binary(binary()) :: String.t()
def type_from_binary(<<@exe_signature, _::binary>>), do: @exe_media_type
def type_from_binary(<<@bmp_signature, _::binary>>), do: @bmp_media_type
def type_from_binary(<<@png_signature, _::binary>>), do: @png_media_type
def type_from_binary(<<@jpg_signature, _::binary>>), do: @jpg_media_type
def type_from_binary(<<@gif_signature, _::binary>>), do: @gif_media_type
@spec verify(binary(), String.t()) :: {:ok | :error, String.t()}
def verify(file_binary, extension) do
media_type = type_from_extension(extension)
cond do
type_from_binary(file_binary) == media_type ->
{:ok, media_type}
true ->
{:error, "Warning, file format and file extension do not match."}
end
end
end