mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
Backend: Ignore image unique IDs that are not standard UUIDs
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
@@ -3,6 +3,8 @@ package meta
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
)
|
||||
|
||||
// Data represents image meta data.
|
||||
@@ -83,12 +85,12 @@ func (data Data) Megapixels() int {
|
||||
|
||||
// HasDocumentID returns true if a DocumentID exists.
|
||||
func (data Data) HasDocumentID() bool {
|
||||
return len(data.DocumentID) >= 15
|
||||
return rnd.IsUUID(data.DocumentID)
|
||||
}
|
||||
|
||||
// HasInstanceID returns true if an InstanceID exists.
|
||||
func (data Data) HasInstanceID() bool {
|
||||
return len(data.InstanceID) >= 15
|
||||
return rnd.IsUUID(data.InstanceID)
|
||||
}
|
||||
|
||||
// HasTimeAndPlace if data contains a time and gps position.
|
||||
|
||||
@@ -80,15 +80,23 @@ func TestData_Megapixels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestData_HasDocumentID(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
t.Run("6ba7b810-9dad-11d1-80b4-00c04fd430c8", func(t *testing.T) {
|
||||
data := Data{
|
||||
DocumentID: "asdfg12345hjyt6",
|
||||
DocumentID: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
||||
}
|
||||
|
||||
assert.Equal(t, true, data.HasDocumentID())
|
||||
})
|
||||
|
||||
t.Run("false", func(t *testing.T) {
|
||||
t.Run("asdfg12345hjyt6", func(t *testing.T) {
|
||||
data := Data{
|
||||
DocumentID: "asdfg12345hjyt6",
|
||||
}
|
||||
|
||||
assert.Equal(t, false, data.HasDocumentID())
|
||||
})
|
||||
|
||||
t.Run("asdfg12345hj", func(t *testing.T) {
|
||||
data := Data{
|
||||
DocumentID: "asdfg12345hj",
|
||||
}
|
||||
@@ -100,7 +108,7 @@ func TestData_HasDocumentID(t *testing.T) {
|
||||
func TestData_HasInstanceID(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
data := Data{
|
||||
InstanceID: "asdfg12345hjyt6",
|
||||
InstanceID: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
||||
}
|
||||
|
||||
assert.Equal(t, true, data.HasInstanceID())
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/dsoprea/go-png-image-structure"
|
||||
"github.com/dsoprea/go-tiff-image-structure"
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
"gopkg.in/ugjka/go-tz.v2/tz"
|
||||
)
|
||||
@@ -280,7 +281,9 @@ func (data *Data) Exif(fileName string, fileType fs.FileType) (err error) {
|
||||
}
|
||||
|
||||
if value, ok := tags["ImageUniqueID"]; ok {
|
||||
data.DocumentID = SanitizeUID(value)
|
||||
if id := rnd.SanitizeUUID(value); id != "" {
|
||||
data.DocumentID = id
|
||||
}
|
||||
}
|
||||
|
||||
if value, ok := tags["PixelXDimension"]; ok {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/rnd"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
"github.com/tidwall/gjson"
|
||||
"gopkg.in/ugjka/go-tz.v2/tz"
|
||||
@@ -165,13 +166,13 @@ func (data *Data) Exiftool(jsonData []byte, originalName string) (err error) {
|
||||
}
|
||||
|
||||
// Validate and normalize optional DocumentID.
|
||||
if len(data.DocumentID) > 0 {
|
||||
data.DocumentID = SanitizeUID(data.DocumentID)
|
||||
if data.DocumentID != "" {
|
||||
data.DocumentID = rnd.SanitizeUUID(data.DocumentID)
|
||||
}
|
||||
|
||||
// Validate and normalize optional InstanceID.
|
||||
if len(data.InstanceID) > 0 {
|
||||
data.InstanceID = SanitizeUID(data.InstanceID)
|
||||
if data.InstanceID != "" {
|
||||
data.InstanceID = rnd.SanitizeUUID(data.InstanceID)
|
||||
}
|
||||
|
||||
if data.Projection == "equirectangular" {
|
||||
|
||||
@@ -275,7 +275,7 @@ func TestJSON(t *testing.T) {
|
||||
|
||||
// t.Logf("DATA: %+v", data)
|
||||
|
||||
assert.Equal(t, "4b1fef2d1cf4a5be38b263e0637edead", data.DocumentID)
|
||||
assert.Equal(t, "", data.DocumentID)
|
||||
assert.Equal(t, "dafbfeb8-a129-4e7c-9cf0-e7996a701cdb", data.InstanceID)
|
||||
assert.Equal(t, CodecJpeg, data.Codec)
|
||||
assert.Equal(t, "0s", data.Duration.String())
|
||||
|
||||
@@ -15,11 +15,10 @@ func TestDirs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Len(t, result, 7)
|
||||
assert.Contains(t, result, "/directory")
|
||||
assert.Contains(t, result, "/directory/subdirectory")
|
||||
assert.Contains(t, result, "/linked")
|
||||
assert.Contains(t, result, "/linked/photoprism")
|
||||
assert.Contains(t, result, "/linked/photoprism/sub")
|
||||
})
|
||||
|
||||
t.Run("recursive no-symlinks", func(t *testing.T) {
|
||||
|
||||
@@ -29,20 +29,6 @@ func BenchmarkRandomPassword(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUUID(t *testing.T) {
|
||||
for n := 0; n < 5; n++ {
|
||||
uuid := UUID()
|
||||
t.Logf("token: %s", uuid)
|
||||
assert.Equal(t, 36, len(uuid))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUUID(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
UUID()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRandomToken4(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
Token(4)
|
||||
|
||||
@@ -58,11 +58,6 @@ func IsLowerAlnum(s string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Returns true if the string looks like a standard UUID.
|
||||
func IsUUID(s string) bool {
|
||||
return len(s) == 36 && IsHex(s)
|
||||
}
|
||||
|
||||
// IsUID returns true if string is a seemingly unique id.
|
||||
func IsUID(s string, prefix byte) bool {
|
||||
// Regular UUID.
|
||||
|
||||
@@ -45,14 +45,6 @@ func TestIsHex(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestIsUUID(t *testing.T) {
|
||||
assert.True(t, IsUUID("dafbfeb8-a129-4e7c-9cf0-e7996a701cdb"))
|
||||
assert.True(t, IsUUID("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
||||
assert.False(t, IsUUID("55785BAC-9H4B-4747-B090-EE123FFEE437"))
|
||||
assert.True(t, IsUUID("550e8400-e29b-11d4-a716-446655440000"))
|
||||
assert.False(t, IsUUID("4B1FEF2D1CF4A5BE38B263E0637EDEAD"))
|
||||
}
|
||||
|
||||
func TestIsUID(t *testing.T) {
|
||||
assert.True(t, IsUID("lt9k3pw1wowuy3c2", 'l'))
|
||||
assert.True(t, IsUID("dafbfeb8-a129-4e7c-9cf0-e7996a701cdb", 'l'))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package rnd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
@@ -8,3 +10,27 @@ import (
|
||||
func UUID() string {
|
||||
return uuid.NewV4().String()
|
||||
}
|
||||
|
||||
// Returns true if the string looks like a standard UUID.
|
||||
func IsUUID(s string) bool {
|
||||
return len(s) == 36 && IsHex(s)
|
||||
}
|
||||
|
||||
// SanitizeUUID normalizes UUIDs found in XMP or Exif metadata.
|
||||
func SanitizeUUID(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
s = strings.Replace(strings.TrimSpace(s), "\"", "", -1)
|
||||
|
||||
if start := strings.LastIndex(s, ":"); start != -1 {
|
||||
s = s[start+1:]
|
||||
}
|
||||
|
||||
if !IsUUID(s) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.ToLower(s)
|
||||
}
|
||||
|
||||
39
pkg/rnd/uuid_test.go
Normal file
39
pkg/rnd/uuid_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package rnd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUUID(t *testing.T) {
|
||||
for n := 0; n < 5; n++ {
|
||||
uuid := UUID()
|
||||
t.Logf("token: %s", uuid)
|
||||
assert.Equal(t, 36, len(uuid))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUUID(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
UUID()
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsUUID(t *testing.T) {
|
||||
assert.True(t, IsUUID("dafbfeb8-a129-4e7c-9cf0-e7996a701cdb"))
|
||||
assert.True(t, IsUUID("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
||||
assert.False(t, IsUUID("55785BAC-9H4B-4747-B090-EE123FFEE437"))
|
||||
assert.True(t, IsUUID("550e8400-e29b-11d4-a716-446655440000"))
|
||||
assert.False(t, IsUUID("4B1FEF2D1CF4A5BE38B263E0637EDEAD"))
|
||||
}
|
||||
|
||||
func TestSanitizeUUID(t *testing.T) {
|
||||
assert.Equal(t, "dafbfeb8-a129-4e7c-9cf0-e7996a701cdb", SanitizeUUID(" \"dafbfeb8-a129-4e7c-9cf0-e7996a701cdb\" "))
|
||||
assert.Equal(t, "dafbfeb8-a129-4e7c-9cf0-e7996a701cdb", SanitizeUUID(" xmp:dafbfeb8-a129-4e7c-9cf0-e7996a701cdb "))
|
||||
assert.Equal(t, "dafbfeb8-a129-4e7c-9cf0-e7996a701cdb", SanitizeUUID("dafbfeb8-a129-4e7c-9cf0-e7996a701cdb"))
|
||||
assert.Equal(t, "6ba7b810-9dad-11d1-80b4-00c04fd430c8", SanitizeUUID("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
||||
assert.Equal(t, "", SanitizeUUID("55785BAC-9H4B-4747-B090-EE123FFEE437"))
|
||||
assert.Equal(t, "550e8400-e29b-11d4-a716-446655440000", SanitizeUUID("550e8400-e29b-11d4-a716-446655440000"))
|
||||
assert.Equal(t, "", SanitizeUUID("4B1FEF2D1CF4A5BE38B263E0637EDEAD"))
|
||||
}
|
||||
Reference in New Issue
Block a user