dir) && !mkdir($this->dir, 0775, true) && !is_dir($this->dir)) { throw new RuntimeException("Cannot create pixel directory {$this->dir}"); } } public static function isValidName(string $name): bool { return (bool) preg_match('/^[a-f0-9]{64}\.px$/', $name); } /** * @return array{file:string,bytes:int} * @throws InvalidPixelsException when the bytes are not a cel */ public function store(string $bytes): array { $length = strlen($bytes); if ($length < self::HEADER_BYTES || substr($bytes, 0, 4) !== self::MAGIC || ord($bytes[4]) !== self::VERSION) { throw new InvalidPixelsException('Not a pixel cel'); } $width = ord($bytes[6]) | (ord($bytes[7]) << 8); $height = ord($bytes[8]) | (ord($bytes[9]) << 8); if ($width < 1 || $height < 1 || $width > self::MAX_SIDE || $height > self::MAX_SIDE) { throw new InvalidPixelsException('A cel is 1 to ' . self::MAX_SIDE . ' pixels per side'); } if ($length !== self::HEADER_BYTES + $width * $height) { throw new InvalidPixelsException('The cel does not hold ' . $width . ' x ' . $height . ' pixels'); } $file = hash('sha256', $bytes) . '.px'; $path = $this->dir . '/' . $file; if (!is_file($path)) { $tmp = $path . '.' . bin2hex(random_bytes(4)) . '.tmp'; if (file_put_contents($tmp, $bytes, LOCK_EX) === false || !rename($tmp, $path)) { if (is_file($tmp)) { unlink($tmp); } throw new RuntimeException('Cannot write pixel file'); } chmod($path, 0664); } return ['file' => $file, 'bytes' => $length]; } } /** Thrown by PixelStore::store when the uploaded bytes are not a cel. */ final class InvalidPixelsException extends RuntimeException { }