From 68e1b6ae40c24ba3cec8e281ffdff9341f8a5800 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 5 Mar 2023 22:42:12 +0800 Subject: [PATCH 1/6] fix --- modules/typesniffer/typesniffer.go | 22 ++++++++++++++++------ modules/typesniffer/typesniffer_test.go | 20 ++++++++++++++++++++ web_src/js/features/imagediff.js | 13 +++++-------- web_src/less/features/imagediff.less | 5 +++-- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go index c9fef953ce70..5955c03d6bdf 100644 --- a/modules/typesniffer/typesniffer.go +++ b/modules/typesniffer/typesniffer.go @@ -24,8 +24,9 @@ const ( ) var ( - svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(||>))\s*)*\/]`) - svgTagInXMLRegex = regexp.MustCompile(`(?si)\A<\?xml\b.*?\?>\s*(?:(||>))\s*)*\/]`) + svgComment = regexp.MustCompile(`(?s)`) + svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(|>))\s*)*/]`) + svgTagInXMLRegex = regexp.MustCompile(`(?si)\A<\?xml\b.*?\?>\s*(?:(|>))\s*)*/]`) ) // SniffedType contains information about a blobs type. @@ -91,10 +92,19 @@ func DetectContentType(data []byte) SniffedType { data = data[:sniffLen] } - if (strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html")) && svgTagRegex.Match(data) || - strings.Contains(ct, "text/xml") && svgTagInXMLRegex.Match(data) { - // SVG is unsupported. https://github.com/golang/go/issues/15888 - ct = SvgMimeType + // SVG is unsupported by http.DetectContentType, https://github.com/golang/go/issues/15888 + + if strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html") { + dataNoComment := svgComment.ReplaceAll(data, nil) + if svgTagRegex.Match(dataNoComment) { + ct = SvgMimeType + } + } + if strings.Contains(ct, "text/xml") { + dataNoComment := svgComment.ReplaceAll(data, nil) + if svgTagInXMLRegex.Match(dataNoComment) { + ct = SvgMimeType + } } return SniffedType{ct} diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index dbce94fc3bdd..aab4f92b5c53 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -68,6 +68,26 @@ func TestIsSvgImage(t *testing.T) { assert.False(t, DetectContentType([]byte(` `)).IsSvgImage()) + + assert.False(t, DetectContentType([]byte(` + +
+ + +
+`)).IsSvgImage()) + + assert.False(t, DetectContentType([]byte(` + +
+ + +
+`)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) } func TestIsPDF(t *testing.T) { diff --git a/web_src/js/features/imagediff.js b/web_src/js/features/imagediff.js index 7a285f1f8dbc..5f20be456238 100644 --- a/web_src/js/features/imagediff.js +++ b/web_src/js/features/imagediff.js @@ -129,8 +129,8 @@ export function initImageDiff() { initOverlay(createContext($imageAfter[2], $imageBefore[2])); } - hideElem($container.find('> .loader')); $container.find('> .gt-hidden').removeClass('gt-hidden'); + hideElem($container.find('.ui.loader')); } function initSideBySide(sizes) { @@ -155,7 +155,7 @@ export function initImageDiff() { height: sizes.size1.height * factor }); sizes.image1.parent().css({ - margin: `${sizes.ratio[1] * factor + 15}px ${sizes.ratio[0] * factor}px ${sizes.ratio[1] * factor}px`, + margin: `10px auto`, width: sizes.size1.width * factor + 2, height: sizes.size1.height * factor + 2 }); @@ -164,7 +164,7 @@ export function initImageDiff() { height: sizes.size2.height * factor }); sizes.image2.parent().css({ - margin: `${sizes.ratio[3] * factor}px ${sizes.ratio[2] * factor}px`, + margin: `10px auto`, width: sizes.size2.width * factor + 2, height: sizes.size2.height * factor + 2 }); @@ -255,13 +255,10 @@ export function initImageDiff() { width: sizes.size2.width * factor + 2, height: sizes.size2.height * factor + 2 }); + sizes.image2.parent().parent().css({ width: sizes.max.width * factor + 2, - height: sizes.max.height * factor + 2 - }); - $container.find('.onion-skin').css({ - width: sizes.max.width * factor + 2, - height: sizes.max.height * factor + 4 + height: sizes.max.height * factor + 2 + 20, }); const $range = $container.find("input[type='range']"); diff --git a/web_src/less/features/imagediff.less b/web_src/less/features/imagediff.less index a9ba7f8c8f36..07763c15e126 100644 --- a/web_src/less/features/imagediff.less +++ b/web_src/less/features/imagediff.less @@ -1,6 +1,6 @@ .image-diff-container { text-align: center; - padding: 30px 0; + padding: 1em 0; img { border: 1px solid var(--color-primary-light-7); @@ -22,6 +22,7 @@ display: inline-block; line-height: 0; vertical-align: top; + margin: 0 1em; .side-header { font-weight: bold; @@ -98,7 +99,7 @@ } input { - width: 300px; + max-width: 300px; } } } From be77cb87c526cca882ce401570716984f761cc7c Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 5 Mar 2023 23:24:04 +0800 Subject: [PATCH 2/6] add more SVG checks, remove unnecessary `` test case --- modules/typesniffer/typesniffer.go | 27 ++++++++++++++----------- modules/typesniffer/typesniffer_test.go | 1 - 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go index 5955c03d6bdf..c2b4ffd664a5 100644 --- a/modules/typesniffer/typesniffer.go +++ b/modules/typesniffer/typesniffer.go @@ -4,6 +4,7 @@ package typesniffer import ( + "bytes" "fmt" "io" "net/http" @@ -25,8 +26,8 @@ const ( var ( svgComment = regexp.MustCompile(`(?s)`) - svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(|>))\s*)*/]`) - svgTagInXMLRegex = regexp.MustCompile(`(?si)\A<\?xml\b.*?\?>\s*(?:(|>))\s*)*/]`) + svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(|>))\s*)*\s*(?:(|>))\s*)*") + // DetectContentType extends http.DetectContentType with more content types. Defaults to text/unknown if input is empty. func DetectContentType(data []byte) SniffedType { if len(data) == 0 { @@ -94,16 +97,16 @@ func DetectContentType(data []byte) SniffedType { // SVG is unsupported by http.DetectContentType, https://github.com/golang/go/issues/15888 - if strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html") { - dataNoComment := svgComment.ReplaceAll(data, nil) - if svgTagRegex.Match(dataNoComment) { - ct = SvgMimeType - } - } - if strings.Contains(ct, "text/xml") { - dataNoComment := svgComment.ReplaceAll(data, nil) - if svgTagInXMLRegex.Match(dataNoComment) { - ct = SvgMimeType + detectByHTML := strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html") + detectByXML := strings.Contains(ct, "text/xml") + if detectByHTML || detectByXML { + dataProcessed := svgComment.ReplaceAll(data, nil) + dataProcessed = bytes.TrimSpace(dataProcessed) + if bytes.HasSuffix(dataProcessed, svgCloseTag) { + if detectByHTML && svgTagRegex.Match(dataProcessed) || + detectByXML && svgTagInXMLRegex.Match(dataProcessed) { + ct = SvgMimeType + } } } diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index aab4f92b5c53..92590f5dbbf8 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -28,7 +28,6 @@ func TestIsSvgImage(t *testing.T) { assert.True(t, DetectContentType([]byte("")).IsSvgImage()) assert.True(t, DetectContentType([]byte(" ")).IsSvgImage()) assert.True(t, DetectContentType([]byte(``)).IsSvgImage()) - assert.True(t, DetectContentType([]byte("")).IsSvgImage()) assert.True(t, DetectContentType([]byte(``)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` `)).IsSvgImage()) From b185941ff831f01161d7160abc1a165421a99ff6 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 5 Mar 2023 23:27:53 +0800 Subject: [PATCH 3/6] add tests --- modules/typesniffer/typesniffer_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index 92590f5dbbf8..84042e98b91d 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -68,6 +68,9 @@ func TestIsSvgImage(t *testing.T) { `)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(`text`)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(`
From ef6be0d12d905564883efdcb3bda07396b143ffe Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 7 Mar 2023 10:52:20 +0800 Subject: [PATCH 4/6] add comments --- web_src/js/features/imagediff.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web_src/js/features/imagediff.js b/web_src/js/features/imagediff.js index 5f20be456238..a26b927c33de 100644 --- a/web_src/js/features/imagediff.js +++ b/web_src/js/features/imagediff.js @@ -256,9 +256,11 @@ export function initImageDiff() { height: sizes.size2.height * factor + 2 }); + // some inner elements are `position: absolute`, so the container's height must be large enough + // the "css(width, height)" is somewhat hacky and not easy to understand, it could be improved in the future sizes.image2.parent().parent().css({ width: sizes.max.width * factor + 2, - height: sizes.max.height * factor + 2 + 20, + height: sizes.max.height * factor + 2 + 20 /* extra height for inner "position: absolute" elements */, }); const $range = $container.find("input[type='range']"); From 409ad49e250ad5b076721423ceba7f50ed4ccf9a Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 7 Mar 2023 10:55:08 +0800 Subject: [PATCH 5/6] remove the close tag check --- modules/typesniffer/typesniffer.go | 10 +++------- modules/typesniffer/typesniffer_test.go | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go index c2b4ffd664a5..5b215496b80c 100644 --- a/modules/typesniffer/typesniffer.go +++ b/modules/typesniffer/typesniffer.go @@ -81,8 +81,6 @@ func (ct SniffedType) GetMimeType() string { return strings.SplitN(ct.contentType, ";", 2)[0] } -var svgCloseTag = []byte("") - // DetectContentType extends http.DetectContentType with more content types. Defaults to text/unknown if input is empty. func DetectContentType(data []byte) SniffedType { if len(data) == 0 { @@ -102,11 +100,9 @@ func DetectContentType(data []byte) SniffedType { if detectByHTML || detectByXML { dataProcessed := svgComment.ReplaceAll(data, nil) dataProcessed = bytes.TrimSpace(dataProcessed) - if bytes.HasSuffix(dataProcessed, svgCloseTag) { - if detectByHTML && svgTagRegex.Match(dataProcessed) || - detectByXML && svgTagInXMLRegex.Match(dataProcessed) { - ct = SvgMimeType - } + if detectByHTML && svgTagRegex.Match(dataProcessed) || + detectByXML && svgTagInXMLRegex.Match(dataProcessed) { + ct = SvgMimeType } } diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index 84042e98b91d..92590f5dbbf8 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -68,9 +68,6 @@ func TestIsSvgImage(t *testing.T) { `)).IsSvgImage()) - assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) - assert.False(t, DetectContentType([]byte(`text`)).IsSvgImage()) - assert.False(t, DetectContentType([]byte(`
From 7871171aabec83c05b8b0ff78eb5761175aaa078 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 7 Mar 2023 18:06:14 +0800 Subject: [PATCH 6/6] add one more test --- modules/typesniffer/typesniffer_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index 92590f5dbbf8..2bafdffd141c 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -56,6 +56,10 @@ func TestIsSvgImage(t *testing.T) { `)).IsSvgImage()) + + // the DetectContentType should work for incomplete data, because only beginning bytes are used for detection + assert.True(t, DetectContentType([]byte(`....`)).IsSvgImage()) + assert.False(t, DetectContentType([]byte{}).IsSvgImage()) assert.False(t, DetectContentType([]byte("svg")).IsSvgImage()) assert.False(t, DetectContentType([]byte("")).IsSvgImage())