From bb308b1a87ca090d639fb3745b3ef139820a82d7 Mon Sep 17 00:00:00 2001 From: Michel Engelen <32863416+michelengelen@users.noreply.github.com> Date: Wed, 27 Apr 2022 18:27:06 +0200 Subject: [PATCH] [MM-43393]: replace .Decoder() method with .Token() (#19988) Automatic Merge --- app/imaging/svg.go | 86 +++++++++++++++++++++++++++-------------- app/imaging/svg_test.go | 10 +++++ 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/app/imaging/svg.go b/app/imaging/svg.go index c45c134a5a..04defeaa81 100644 --- a/app/imaging/svg.go +++ b/app/imaging/svg.go @@ -5,9 +5,9 @@ package imaging import ( "encoding/xml" + "fmt" "io" - "regexp" - "strconv" + "strings" "github.com/pkg/errors" ) @@ -20,39 +20,67 @@ type SVGInfo struct { // ParseSVG returns information for the given SVG input data. func ParseSVG(svgReader io.Reader) (SVGInfo, error) { - var parsedSVG struct { - Width string `xml:"width,attr,omitempty"` - Height string `xml:"height,attr,omitempty"` - ViewBox string `xml:"viewBox,attr,omitempty"` - } svgInfo := SVGInfo{ Width: 0, Height: 0, } - viewBoxPattern := regexp.MustCompile("^([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)[, ]+([0-9]+)$") - dimensionPattern := regexp.MustCompile("(?i)^([0-9]+)(?:px)?$") - // decode provided SVG - if err := xml.NewDecoder(svgReader).Decode(&parsedSVG); err != nil { - return svgInfo, err - } + decoder := xml.NewDecoder(svgReader) - // prefer viewbox for SVG dimensions over width/height - if viewBoxMatches := viewBoxPattern.FindStringSubmatch(parsedSVG.ViewBox); len(viewBoxMatches) == 5 { - svgInfo.Width, _ = strconv.Atoi(viewBoxMatches[3]) - svgInfo.Height, _ = strconv.Atoi(viewBoxMatches[4]) - } else if parsedSVG.Width != "" && parsedSVG.Height != "" { - widthMatches := dimensionPattern.FindStringSubmatch(parsedSVG.Width) - heightMatches := dimensionPattern.FindStringSubmatch(parsedSVG.Height) - if len(widthMatches) == 2 && len(heightMatches) == 2 { - svgInfo.Width, _ = strconv.Atoi(widthMatches[1]) - svgInfo.Height, _ = strconv.Atoi(heightMatches[1]) + for { + token, err := decoder.Token() + if err != nil { + return svgInfo, err + } + switch t := token.(type) { + case xml.StartElement: + for _, attr := range t.Attr { + if attr.Name.Local == "viewBox" { + values := strings.Fields(attr.Value) + if len(values) == 4 { + width := 0 + _, widthErr := fmt.Sscan(values[2], &width) + + height := 0 + _, heightErr := fmt.Sscan(values[3], &height) + + if widthErr != nil || heightErr != nil { + return svgInfo, err + } + + svgInfo.Width = width + svgInfo.Height = height + + return svgInfo, nil + } + } + if attr.Name.Local == "width" { + width := 0 + _, err := fmt.Sscan(attr.Value, &width) + + if err != nil { + return svgInfo, err + } + + svgInfo.Width = width + } + if attr.Name.Local == "height" { + height := 0 + _, err := fmt.Sscan(attr.Value, &height) + + if err != nil { + return svgInfo, err + } + + svgInfo.Height = height + } + } + + if svgInfo.Width == 0 || svgInfo.Height == 0 { + return svgInfo, errors.New("unable to extract SVG dimensions") + } + + return svgInfo, nil } } - - // if width and/or height are still zero, create new error - if svgInfo.Width == 0 || svgInfo.Height == 0 { - return svgInfo, errors.New("unable to extract SVG dimensions") - } - return svgInfo, nil } diff --git a/app/imaging/svg_test.go b/app/imaging/svg_test.go index c9e5bbdc5e..63c5c3bd9f 100644 --- a/app/imaging/svg_test.go +++ b/app/imaging/svg_test.go @@ -8,6 +8,8 @@ import ( "io" "strings" "testing" + + "github.com/stretchr/testify/require" ) //nolint:unparam @@ -74,3 +76,11 @@ func TestParseInvalidSVGData(t *testing.T) { } } } + +func TestParseProcInstOnlySVGData(t *testing.T) { + svg := strings.NewReader("") + svgInfo, err := ParseSVG(svg) + require.Error(t, err) + require.Equal(t, 0, svgInfo.Width) + require.Equal(t, 0, svgInfo.Height) +}