'ttf', 'true' => 'ttf', 'OTTO' => 'otf', 'wOFF' => 'woff', 'wOF2' => 'woff2', ]; protected static function filePattern(): string { return '[a-f0-9]{64}\.(ttf|otf|woff|woff2)'; } /** * Stores the raw bytes of a typeface and returns its record. * * The format is read from the file's own signature, never from anything the client says. * `finfo` is not consulted the way it is for images: it reports fonts inconsistently across * libmagic versions (`font/sfnt`, `application/vnd.ms-opentype`, plain `application/octet-stream`), * so a second opinion from it would reject valid files rather than catch bad ones. * * `$originalName` is kept beside the file as a caption (see OriginalName): the hash says * nothing, and the name inside the font is deliberately never read (see `gm-font-` families). * * @return array{file:string,name:string,bytes:int} * @throws InvalidFontException when the bytes are not a supported font */ public function store(string $bytes, string $originalName, string $folder): array { $extension = self::SIGNATURES[substr($bytes, 0, 4)] ?? ''; if ($extension === '') { throw new InvalidFontException('Not a font file – use TTF, OTF, WOFF or WOFF2'); } // The shortest thing that can still be a font: a table directory and one entry. if (strlen($bytes) < 28) { throw new InvalidFontException('Font file is truncated'); } return $this->keep($bytes, $extension, $originalName, $folder); } } /** Thrown by FontStore::store when the uploaded bytes are not a usable font. */ final class InvalidFontException extends RuntimeException { }