diff --git a/internal/entity/album.go b/internal/entity/album.go index 88584aadb..df605278e 100644 --- a/internal/entity/album.go +++ b/internal/entity/album.go @@ -143,7 +143,6 @@ func NewFolderAlbum(albumTitle, albumPath, albumFilter string) *Album { result := &Album{ AlbumOrder: SortOrderAdded, AlbumType: AlbumFolder, - AlbumTitle: txt.Clip(albumTitle, txt.ClipDefault), AlbumSlug: txt.Clip(albumSlug, txt.ClipSlug), AlbumPath: txt.Clip(albumPath, txt.ClipPath), AlbumFilter: albumFilter, @@ -151,6 +150,8 @@ func NewFolderAlbum(albumTitle, albumPath, albumFilter string) *Album { UpdatedAt: now, } + result.SetTitle(albumTitle) + return result } @@ -165,13 +166,14 @@ func NewMomentsAlbum(albumTitle, albumSlug, albumFilter string) *Album { result := &Album{ AlbumOrder: SortOrderOldest, AlbumType: AlbumMoment, - AlbumTitle: txt.Clip(albumTitle, txt.ClipDefault), AlbumSlug: txt.Clip(albumSlug, txt.ClipSlug), AlbumFilter: albumFilter, CreatedAt: now, UpdatedAt: now, } + result.SetTitle(albumTitle) + return result } @@ -189,13 +191,14 @@ func NewStateAlbum(albumTitle, albumSlug, albumFilter string) *Album { result := &Album{ AlbumOrder: SortOrderNewest, AlbumType: AlbumState, - AlbumTitle: txt.Clip(albumTitle, txt.ClipDefault), AlbumSlug: txt.Clip(albumSlug, txt.ClipSlug), AlbumFilter: albumFilter, CreatedAt: now, UpdatedAt: now, } + result.SetTitle(albumTitle) + return result } @@ -219,7 +222,6 @@ func NewMonthAlbum(albumTitle, albumSlug string, year, month int) *Album { result := &Album{ AlbumOrder: SortOrderOldest, AlbumType: AlbumMonth, - AlbumTitle: albumTitle, AlbumSlug: albumSlug, AlbumFilter: f.Serialize(), AlbumYear: year, @@ -228,6 +230,8 @@ func NewMonthAlbum(albumTitle, albumSlug string, year, month int) *Album { UpdatedAt: now, } + result.SetTitle(albumTitle) + return result } @@ -367,13 +371,15 @@ func (m *Album) IsDefault() bool { // SetTitle changes the album name. func (m *Album) SetTitle(title string) { - title = strings.TrimSpace(title) + title = strings.Trim(title, "_&|{}<>: \n\r\t\\") + title = strings.ReplaceAll(title, "\"", "'") + title = txt.Shorten(title, txt.ClipDefault, txt.Ellipsis) if title == "" { title = m.CreatedAt.Format("January 2006") } - m.AlbumTitle = txt.Clip(title, txt.ClipDefault) + m.AlbumTitle = title if m.AlbumType == AlbumDefault || m.AlbumSlug == "" { if len(m.AlbumTitle) < txt.ClipSlug { @@ -408,7 +414,9 @@ func (m *Album) UpdateSlug(title, slug string) error { return nil } - m.AlbumTitle = title + if title != "" { + m.SetTitle(title) + } return m.Updates(Values{"album_title": m.AlbumTitle, "album_slug": m.AlbumSlug}) } @@ -449,7 +457,9 @@ func (m *Album) UpdateState(title, slug, stateName, countryCode string) error { return nil } - m.AlbumTitle = title + if title != "" { + m.SetTitle(title) + } return m.Updates(Values{"album_title": m.AlbumTitle, "album_slug": m.AlbumSlug, "album_location": m.AlbumLocation, "album_country": m.AlbumCountry, "album_state": m.AlbumState}) } diff --git a/internal/entity/album_test.go b/internal/entity/album_test.go index 6e5cb7d56..08434bd28 100644 --- a/internal/entity/album_test.go +++ b/internal/entity/album_test.go @@ -60,7 +60,7 @@ the further from the equator you get. The precision of the latitude part does no more strictly however, a meridian arc length per 1 second depends on the latitude at the point in question. The discrepancy of 1 second meridian arc length between equator and pole is about 0.3 metres because the earth is an oblate spheroid.` - expected := txt.Clip(longName, txt.ClipDefault) + expected := txt.Shorten(longName, txt.ClipDefault, txt.Ellipsis) slugExpected := txt.Clip(longName, txt.ClipSlug) album := NewAlbum(longName, AlbumDefault) assert.Equal(t, expected, album.AlbumTitle) diff --git a/internal/entity/photo_title.go b/internal/entity/photo_title.go index 476dfb7a8..f433f5be6 100644 --- a/internal/entity/photo_title.go +++ b/internal/entity/photo_title.go @@ -26,6 +26,8 @@ func (m *Photo) NoTitle() bool { // SetTitle changes the photo title and clips it to 300 characters. func (m *Photo) SetTitle(title, source string) { + title = strings.Trim(title, "_&|{}<>: \n\r\t\\") + title = strings.ReplaceAll(title, "\"", "'") title = txt.Shorten(title, txt.ClipTitle, txt.Ellipsis) if title == "" { diff --git a/internal/search/photos.go b/internal/search/photos.go index afdf2c9bf..e8fd9e8b7 100644 --- a/internal/search/photos.go +++ b/internal/search/photos.go @@ -306,7 +306,7 @@ func Photos(f form.SearchPhotos) (results PhotoResults, count int, err error) { s = s.Where("photos.camera_id = ?", txt.UInt(f.Camera)) } else if txt.NotEmpty(f.Camera) { v := strings.Trim(f.Camera, "*%") + "%" - s = s.Where("cameras.camera_make LIKE ? OR cameras.camera_model LIKE ? OR cameras.camera_slug LIKE ?", v, v, v) + s = s.Where("cameras.camera_name LIKE ? OR cameras.camera_model LIKE ? OR cameras.camera_slug LIKE ?", v, v, v) } // Filter by lens id or name? @@ -314,7 +314,7 @@ func Photos(f form.SearchPhotos) (results PhotoResults, count int, err error) { s = s.Where("photos.lens_id = ?", txt.UInt(f.Lens)) } else if txt.NotEmpty(f.Lens) { v := strings.Trim(f.Lens, "*%") + "%" - s = s.Where("lenses.lens_make LIKE ? OR lenses.lens_model LIKE ? OR lenses.lens_slug LIKE ?", v, v, v) + s = s.Where("lenses.lens_name LIKE ? OR lenses.lens_model LIKE ? OR lenses.lens_slug LIKE ?", v, v, v) } // Filter by year? diff --git a/pkg/sanitize/search.go b/pkg/sanitize/search.go index d779a03ed..6a5eb9447 100644 --- a/pkg/sanitize/search.go +++ b/pkg/sanitize/search.go @@ -27,7 +27,7 @@ func SearchString(s string) string { s = strings.ReplaceAll(s, "**", "*") // Trim. - return strings.Trim(s, "&|\\<>\n\r\t") + return strings.Trim(s, "|\\<>\n\r\t") } // SearchQuery replaces search operator with default symbols. @@ -49,5 +49,5 @@ func SearchQuery(s string) string { s = strings.ReplaceAll(s, "**", "*") // Trim. - return strings.Trim(s, "+&|-=$^(){}\\<>,;: \n\r\t") + return strings.Trim(s, "|${}\\<>: \n\r\t") } diff --git a/pkg/sanitize/search_test.go b/pkg/sanitize/search_test.go index 45379ae7d..c8e83d9ed 100644 --- a/pkg/sanitize/search_test.go +++ b/pkg/sanitize/search_test.go @@ -28,7 +28,7 @@ func TestSearchQuery(t *testing.T) { }) t.Run("AndOr", func(t *testing.T) { q := SearchQuery("Jens AND Mander and me Or Kitty AND ") - assert.Equal(t, "Jens&Mander&me|Kitty", q) + assert.Equal(t, "Jens&Mander&me|Kitty&", q) }) t.Run("FlowersInThePark", func(t *testing.T) { q := SearchQuery(" Flowers in the Park ") diff --git a/pkg/sanitize/sql.go b/pkg/sanitize/sql.go index 232d75bd9..944fce02b 100644 --- a/pkg/sanitize/sql.go +++ b/pkg/sanitize/sql.go @@ -5,7 +5,8 @@ import ( ) // sqlSpecialBytes contains special bytes to escape in SQL search queries. -var sqlSpecialBytes = []byte{34, 39, 92, 95} +// see https://mariadb.com/kb/en/string-literals/ +var sqlSpecialBytes = []byte{34, 39, 92, 95} // ", ', \, _ // SqlString escapes a string for use in an SQL query. func SqlString(s string) string {