Backend now stores AVIF, WebP, JPEG, and optional JXL variants for both full-size and thumbnail images. Database schema extended with 7 new columns. Image validation supports AVIF and JXL magic bytes. Comprehensive test coverage for all format URL fields and magic byte detection. Legacy single-URL images remain backward-compatible. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
40 lines
1.0 KiB
Go
40 lines
1.0 KiB
Go
package images
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
)
|
|
|
|
var allowedImageMagic = []struct {
|
|
magic []byte
|
|
ext string
|
|
}{
|
|
{[]byte{0xff, 0xd8, 0xff}, ".jpg"},
|
|
{[]byte{0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}, ".png"},
|
|
{[]byte{'G', 'I', 'F', '8', '7', 'a'}, ".gif"},
|
|
{[]byte{'G', 'I', 'F', '8', '9', 'a'}, ".gif"},
|
|
}
|
|
|
|
func ValidateImageBytes(data []byte) (string, error) {
|
|
if len(data) < 12 {
|
|
return "", fmt.Errorf("file too small to be a valid image")
|
|
}
|
|
for _, m := range allowedImageMagic {
|
|
if bytes.HasPrefix(data, m.magic) {
|
|
return m.ext, nil
|
|
}
|
|
}
|
|
if len(data) >= 12 && bytes.Equal(data[0:4], []byte("RIFF")) && bytes.Equal(data[8:12], []byte("WEBP")) {
|
|
return ".webp", nil
|
|
}
|
|
if len(data) >= 12 && bytes.Equal(data[4:8], []byte("ftyp")) {
|
|
if bytes.Equal(data[8:12], []byte("avif")) || bytes.Equal(data[8:12], []byte("avis")) {
|
|
return ".avif", nil
|
|
}
|
|
if bytes.Equal(data[8:12], []byte("jxl ")) {
|
|
return ".jxl", nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("file is not a supported image type (jpeg, png, webp, gif, avif, jxl)")
|
|
}
|