MishkaCmsCore.Runtime.FileSignature (Mishka CMS Core v0.0.1)

Copy Markdown View Source

What a file is, read from its first bytes instead of from the name or the type its sender gave it.

A file name and a MIME type are claims made by whoever uploaded the file. The first bytes are what the file is, so every upload that a site serves back from its own origin is checked here before it is stored: MishkaCmsCore.Runtime.Media for the media library and MishkaCmsCore.Runtime.PageUpload for a visitor's files.

Kinds

A kind is a family of formats that share a signature:

KindExtensionsFirst bytes
:pngpngthe PNG signature
:jpegjpg, jpegFF D8 FF
:gifgifGIF87a or GIF89a
:webpwebpRIFF, four bytes, WEBP
:pdfpdf%PDF-
:iso_mediamp4, mova box size under 16 MB, then an ISO base media box name (ftyp, moov, mdat, ...)
:matroskawebmthe EBML header 1A 45 DF A3
:ole2doc, xls, pptthe OLE2 compound file header
:zipdocx, xlsx, pptx, odt, ods, zipPK and a local file header
:texttxt, csvvalid UTF-8 with no NUL byte and no control character but tab and line breaks

An extension that is not in the table has no kind, so nothing matches it: html, htm, svg, xml and js are never a kind, and the bytes of a script do not become a picture by being named .png.

Summary

Functions

The kind an extension belongs to, with or without its dot and in any case, or nil for one that is not in the table.

Whether the file at path is what extension says: the extension has a kind and the first bytes of the file are that kind.

The kind of the file at path, read from its first bytes. :error when the file cannot be read or is none of the kinds in the table.

Types

kind()

@type kind() ::
  :png
  | :jpeg
  | :gif
  | :webp
  | :pdf
  | :iso_media
  | :matroska
  | :ole2
  | :zip
  | :text

Functions

kind(extension)

@spec kind(String.t()) :: kind() | nil

The kind an extension belongs to, with or without its dot and in any case, or nil for one that is not in the table.

matches?(path, extension)

@spec matches?(Path.t(), String.t()) :: boolean()

Whether the file at path is what extension says: the extension has a kind and the first bytes of the file are that kind.

sniff(path)

@spec sniff(Path.t()) :: {:ok, kind()} | :error

The kind of the file at path, read from its first bytes. :error when the file cannot be read or is none of the kinds in the table.