mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-09-28 20:43:54 +02:00
Add svg package tests
This commit is contained in:
@@ -324,29 +324,6 @@ func (s *ProcessingHandlerTestSuite) TestSkipProcessingSVG() {
|
|||||||
require.True(s.T(), bytes.Equal(expected.Data, actual))
|
require.True(s.T(), bytes.Equal(expected.Data, actual))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ProcessingHandlerTestSuite) TestPreserveOriginSVGHeaders() {
|
|
||||||
rw := s.send("/unsafe/rs:fill:4:4/plain/local:///test1.svg")
|
|
||||||
res := rw.Result()
|
|
||||||
|
|
||||||
require.Equal(s.T(), 200, res.StatusCode)
|
|
||||||
|
|
||||||
actual := s.readBody(res)
|
|
||||||
originHeaders := map[string]string{
|
|
||||||
"Content-Type": "image/svg+xml",
|
|
||||||
"Cache-Control": "public, max-age=12345",
|
|
||||||
}
|
|
||||||
|
|
||||||
expected, err := svg.Sanitize(&imagedata.ImageData{
|
|
||||||
Data: s.readTestFile("test1.svg"),
|
|
||||||
Headers: originHeaders,
|
|
||||||
})
|
|
||||||
|
|
||||||
require.Nil(s.T(), err)
|
|
||||||
|
|
||||||
require.True(s.T(), bytes.Equal(expected.Data, actual))
|
|
||||||
require.Equal(s.T(), originHeaders, expected.Headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ProcessingHandlerTestSuite) TestNotSkipProcessingSVGToJPG() {
|
func (s *ProcessingHandlerTestSuite) TestNotSkipProcessingSVGToJPG() {
|
||||||
rw := s.send("/unsafe/rs:fill:4:4/plain/local:///test1.svg@jpg")
|
rw := s.send("/unsafe/rs:fill:4:4/plain/local:///test1.svg@jpg")
|
||||||
res := rw.Result()
|
res := rw.Result()
|
||||||
|
22
svg/svg.go
22
svg/svg.go
@@ -15,17 +15,17 @@ import (
|
|||||||
|
|
||||||
var feDropShadowName = []byte("feDropShadow")
|
var feDropShadowName = []byte("feDropShadow")
|
||||||
|
|
||||||
const feDropShadowTemplate = `
|
var feDropShadowTemplate = strings.TrimSpace(`
|
||||||
<feMerge result="dsin-%[1]s"><feMergeNode %[3]s /></feMerge>
|
<feMerge result="dsin-%[1]s"><feMergeNode %[3]s /></feMerge>
|
||||||
<feGaussianBlur %[4]s />
|
<feGaussianBlur %[4]s />
|
||||||
<feOffset %[5]s result="dsof-%[2]s" />
|
<feOffset %[5]s result="dsof-%[2]s" />
|
||||||
<feFlood %[6]s />
|
<feFlood %[6]s />
|
||||||
<feComposite in2="dsof-%[2]s" operator="in" />
|
<feComposite in2="dsof-%[2]s" operator="in" />
|
||||||
<feMerge %[7]s>
|
<feMerge %[7]s>
|
||||||
<feMergeNode />
|
<feMergeNode />
|
||||||
<feMergeNode in="dsin-%[1]s" />
|
<feMergeNode in="dsin-%[1]s" />
|
||||||
</feMerge>
|
</feMerge>
|
||||||
`
|
`)
|
||||||
|
|
||||||
func Sanitize(data *imagedata.ImageData) (*imagedata.ImageData, error) {
|
func Sanitize(data *imagedata.ImageData) (*imagedata.ImageData, error) {
|
||||||
r := bytes.NewReader(data.Data)
|
r := bytes.NewReader(data.Data)
|
||||||
|
83
svg/svg_test.go
Normal file
83
svg/svg_test.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package svg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/imgproxy/imgproxy/v3/config"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/imagedata"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/imagetype"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SvgTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SvgTestSuite) SetupSuite() {
|
||||||
|
config.Reset()
|
||||||
|
|
||||||
|
err := imagedata.Init()
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SvgTestSuite) readTestFile(name string) *imagedata.ImageData {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
|
||||||
|
data, err := os.ReadFile(filepath.Join(wd, "..", "testdata", name))
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
|
||||||
|
return &imagedata.ImageData{
|
||||||
|
Type: imagetype.SVG,
|
||||||
|
Data: data,
|
||||||
|
Headers: map[string]string{
|
||||||
|
"Content-Type": "image/svg+xml",
|
||||||
|
"Cache-Control": "public, max-age=12345",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SvgTestSuite) TestSanitize() {
|
||||||
|
origin := s.readTestFile("test1.svg")
|
||||||
|
expected := s.readTestFile("test1.sanitized.svg")
|
||||||
|
|
||||||
|
actual, err := Sanitize(origin)
|
||||||
|
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
require.Equal(s.T(), string(expected.Data), string(actual.Data))
|
||||||
|
require.Equal(s.T(), origin.Headers, actual.Headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SvgTestSuite) TestFixUnsupportedDropShadow() {
|
||||||
|
origin := s.readTestFile("test1.drop-shadow.svg")
|
||||||
|
expected := s.readTestFile("test1.drop-shadow.fixed.svg")
|
||||||
|
|
||||||
|
actual, changed, err := FixUnsupported(origin)
|
||||||
|
|
||||||
|
// `FixUnsupported` generates random IDs, we need to replace them for the test
|
||||||
|
re := regexp.MustCompile(`"ds(in|of)-.+?"`)
|
||||||
|
actualData := re.ReplaceAllString(string(actual.Data), `"ds$1-test"`)
|
||||||
|
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
require.True(s.T(), changed)
|
||||||
|
require.Equal(s.T(), string(expected.Data), actualData)
|
||||||
|
require.Equal(s.T(), origin.Headers, actual.Headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SvgTestSuite) TestFixUnsupportedNothingChanged() {
|
||||||
|
origin := s.readTestFile("test1.svg")
|
||||||
|
|
||||||
|
actual, changed, err := FixUnsupported(origin)
|
||||||
|
|
||||||
|
require.Nil(s.T(), err)
|
||||||
|
require.False(s.T(), changed)
|
||||||
|
require.Equal(s.T(), origin, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSvg(t *testing.T) {
|
||||||
|
suite.Run(t, new(SvgTestSuite))
|
||||||
|
}
|
17
testdata/test1.drop-shadow.fixed.svg
vendored
Normal file
17
testdata/test1.drop-shadow.fixed.svg
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<svg width="200" height="100">
|
||||||
|
<defs>
|
||||||
|
<filter id="dropShadow">
|
||||||
|
<feMerge result="dsin-test"><feMergeNode in="SourceGraphic" /></feMerge>
|
||||||
|
<feGaussianBlur stdDeviation="3" />
|
||||||
|
<feOffset dx="2" dy="1" result="dsof-test" />
|
||||||
|
<feFlood flood-opacity="0.8" flood-color="#0f0" />
|
||||||
|
<feComposite in2="dsof-test" operator="in" />
|
||||||
|
<feMerge width="200%" height="200%">
|
||||||
|
<feMergeNode />
|
||||||
|
<feMergeNode in="dsin-test" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="200" height="100" fill="#fff"/>
|
||||||
|
<rect x="50" y="25" width="100" height="50" fill="#f00" filter="url(#dropShadow)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 611 B |
9
testdata/test1.drop-shadow.svg
vendored
Normal file
9
testdata/test1.drop-shadow.svg
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="200" height="100">
|
||||||
|
<defs>
|
||||||
|
<filter id="dropShadow">
|
||||||
|
<feDropShadow in="SourceGraphic" dx="2" dy="1" stdDeviation="3" flood-opacity="0.8" flood-color="#0f0" width="200%" height="200%"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="200" height="100" fill="#fff" />
|
||||||
|
<rect x="50" y="25" width="100" height="50" fill="#f00" filter="url(#dropShadow)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 373 B |
4
testdata/test1.sanitized.svg
vendored
Normal file
4
testdata/test1.sanitized.svg
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect width="190" height="90" style="fill:rgb(0,0,0);stroke-width:5;stroke:rgb(255,255,255)"/>
|
||||||
|
<use/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 222 B |
9
testdata/test1.svg
vendored
9
testdata/test1.svg
vendored
@@ -1,3 +1,8 @@
|
|||||||
<svg width="200" height="100">
|
<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="alert(3)">
|
||||||
<rect width="190" height="90" style="fill:rgb(0,0,0);stroke-width:5;stroke:rgb(255,255,255)" />
|
<rect onclick="alert(4)" width="190" height="90" style="fill:rgb(0,0,0);stroke-width:5;stroke:rgb(255,255,255)" />
|
||||||
|
<script>
|
||||||
|
// <![CDATA[
|
||||||
|
alert(2);
|
||||||
|
// ]]>
|
||||||
|
</script><use xlink:href="data:application/xml;base64,PHN2ZyBpZD0ndGVzdCcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluaycgd2lkdGg9JzEwMCcgaGVpZ2h0PScxMDAnPgo8aW1hZ2UgaHJlZj0iMSIgb25lcnJvcj0iYWxlcnQoMSkiIC8+Cjwvc3ZnPg==#test"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 589 B |
Reference in New Issue
Block a user