Fix int types in OpenSubsonic responses.

Refer to https://support.symfonium.app/t/symfonium-sync-crashes-when-tpos-is-not-an-int/4204
This commit is contained in:
Deluan 2024-05-01 13:57:11 -04:00
parent 7ab7b5df5e
commit 2c06a4234e
4 changed files with 39 additions and 14 deletions

View File

@ -7,7 +7,6 @@ import (
"mime"
"net/http"
"sort"
"strconv"
"strings"
"github.com/navidrome/navidrome/consts"
@ -15,6 +14,7 @@ import (
"github.com/navidrome/navidrome/model/request"
"github.com/navidrome/navidrome/server/public"
"github.com/navidrome/navidrome/server/subsonic/responses"
"github.com/navidrome/navidrome/utils/number"
)
func newResponse() *responses.Subsonic {
@ -254,12 +254,12 @@ func toItemDate(date string) responses.ItemDate {
}
parts := strings.Split(date, "-")
if len(parts) > 2 {
itemDate.Day, _ = strconv.Atoi(parts[2])
itemDate.Day = number.ParseInt[int32](parts[2])
}
if len(parts) > 1 {
itemDate.Month, _ = strconv.Atoi(parts[1])
itemDate.Month = number.ParseInt[int32](parts[1])
}
itemDate.Year, _ = strconv.Atoi(parts[0])
itemDate.Year = number.ParseInt[int32](parts[0])
return itemDate
}
@ -278,7 +278,7 @@ func buildDiscSubtitles(_ context.Context, a model.Album) responses.DiscTitles {
}
discTitles := responses.DiscTitles{}
for num, title := range a.Discs {
discTitles = append(discTitles, responses.DiscTitle{Disc: num, Title: title})
discTitles = append(discTitles, responses.DiscTitle{Disc: int32(num), Title: title})
}
sort.Slice(discTitles, func(i, j int) bool {
return discTitles[i].Disc < discTitles[j].Disc

View File

@ -502,7 +502,7 @@ type ReplayGain struct {
}
type DiscTitle struct {
Disc int `xml:"disc,attr" json:"disc"`
Disc int32 `xml:"disc,attr" json:"disc"`
Title string `xml:"title,attr" json:"title"`
}
@ -523,7 +523,7 @@ func marshalJSONArray[T any](v []T) ([]byte, error) {
}
type ItemDate struct {
Year int `xml:"year,attr,omitempty" json:"year,omitempty"`
Month int `xml:"month,attr,omitempty" json:"month,omitempty"`
Day int `xml:"day,attr,omitempty" json:"day,omitempty"`
Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
Month int32 `xml:"month,attr,omitempty" json:"month,omitempty"`
Day int32 `xml:"day,attr,omitempty" json:"day,omitempty"`
}

View File

@ -3,9 +3,17 @@ package number
import (
"crypto/rand"
"math/big"
"strconv"
"golang.org/x/exp/constraints"
)
func RandomInt64(max int64) int64 {
rnd, _ := rand.Int(rand.Reader, big.NewInt(max))
return rnd.Int64()
}
func ParseInt[T constraints.Integer](s string) T {
r, _ := strconv.ParseInt(s, 10, 64)
return T(r)
}

View File

@ -13,10 +13,27 @@ func TestNumber(t *testing.T) {
RunSpecs(t, "Number Suite")
}
var _ = Describe("RandomInt64", func() {
It("should return a random int64", func() {
for i := 0; i < 10000; i++ {
Expect(number.RandomInt64(100)).To(BeNumerically("<", 100))
}
var _ = Describe("number package", func() {
Describe("RandomInt64", func() {
It("should return a random int64", func() {
for i := 0; i < 10000; i++ {
Expect(number.RandomInt64(100)).To(BeNumerically("<", 100))
}
})
})
Describe("ParseInt", func() {
It("should parse a string into an int", func() {
Expect(number.ParseInt[int64]("123")).To(Equal(int64(123)))
})
It("should parse a string into an int32", func() {
Expect(number.ParseInt[int32]("123")).To(Equal(int32(123)))
})
It("should parse a string into an int64", func() {
Expect(number.ParseInt[int]("123")).To(Equal(123))
})
It("should parse a string into an uint", func() {
Expect(number.ParseInt[uint]("123")).To(Equal(uint(123)))
})
})
})