summaryrefslogtreecommitdiffstats
path: root/routers/repo
diff options
context:
space:
mode:
authorJonathan Tran <jonnytran@gmail.com>2021-01-12 22:45:19 -0500
committerGitHub <noreply@github.com>2021-01-12 22:45:19 -0500
commit81467e6f35f343b911c09f746deca869a48da4c8 (patch)
tree1b759007789bc0dbeeb543d54739ccf8b8dfb434 /routers/repo
parent9465e60504284699078e620f7c892a9685d91458 (diff)
downloadgitea-81467e6f35f343b911c09f746deca869a48da4c8.tar.gz
gitea-81467e6f35f343b911c09f746deca869a48da4c8.zip
Display SVG files as images instead of text (#14101)
* Change to display SVG files as images * Remove unsafe styles from SVG CSP * Add integration test to test SVG headers * Add config setting to disable SVG rendering * Add test for img tag when loading SVG image * Remove the Raw view button for svg files since we don't fully support this * Fix copyright year * Rename and move config setting * Add setting to cheat sheet in docs * Fix so that comment matches cheat sheet * Add allowing styles in CSP based on pull request feedback * Re-enable raw button since we show SVG styles now * Change so that SVG files are editable * Add UI to toggle between source and rendered image for SVGs * Change to show blame button for SVG images * Fix to update ctx data * Add test for DetectContentType when file is longer than sniffLen Co-authored-by: Jonathan Tran <jon@allspice.io> Co-authored-by: Kyle D <kdumontnu@gmail.com>
Diffstat (limited to 'routers/repo')
-rw-r--r--routers/repo/download.go5
-rw-r--r--routers/repo/editor.go6
-rw-r--r--routers/repo/lfs.go11
-rw-r--r--routers/repo/view.go24
4 files changed, 38 insertions, 8 deletions
diff --git a/routers/repo/download.go b/routers/repo/download.go
index 2f1f2d3c47..f04dac6aa5 100644
--- a/routers/repo/download.go
+++ b/routers/repo/download.go
@@ -46,6 +46,11 @@ func ServeData(ctx *context.Context, name string, reader io.Reader) error {
} else if base.IsImageFile(buf) || base.IsPDFFile(buf) {
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
+ if base.IsSVGImageFile(buf) {
+ ctx.Resp.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
+ ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff")
+ ctx.Resp.Header().Set("Content-Type", base.SVGMimeType)
+ }
} else {
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
diff --git a/routers/repo/editor.go b/routers/repo/editor.go
index 1ee557a4fd..7538c4cdaa 100644
--- a/routers/repo/editor.go
+++ b/routers/repo/editor.go
@@ -114,9 +114,9 @@ func editFile(ctx *context.Context, isNewFile bool) {
n, _ := dataRc.Read(buf)
buf = buf[:n]
- // Only text file are editable online.
- if !base.IsTextFile(buf) {
- ctx.NotFound("base.IsTextFile", nil)
+ // Only some file types are editable online as text.
+ if !base.IsRepresentableAsText(buf) {
+ ctx.NotFound("base.IsRepresentableAsText", nil)
return
}
diff --git a/routers/repo/lfs.go b/routers/repo/lfs.go
index 01bbd192bc..fb0e3b10ea 100644
--- a/routers/repo/lfs.go
+++ b/routers/repo/lfs.go
@@ -279,14 +279,19 @@ func LFSFileGet(ctx *context.Context) {
}
buf = buf[:n]
- isTextFile := base.IsTextFile(buf)
- ctx.Data["IsTextFile"] = isTextFile
+ ctx.Data["IsTextFile"] = base.IsTextFile(buf)
+ isRepresentableAsText := base.IsRepresentableAsText(buf)
fileSize := meta.Size
ctx.Data["FileSize"] = meta.Size
ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s.git/info/lfs/objects/%s/%s", setting.AppURL, ctx.Repo.Repository.FullName(), meta.Oid, "direct")
switch {
- case isTextFile:
+ case isRepresentableAsText:
+ // This will be true for SVGs.
+ if base.IsImageFile(buf) {
+ ctx.Data["IsImageFile"] = true
+ }
+
if fileSize >= setting.UI.MaxDisplayFileSize {
ctx.Data["IsFileTooLarge"] = true
break
diff --git a/routers/repo/view.go b/routers/repo/view.go
index 8f010490c3..fdb8d5f136 100644
--- a/routers/repo/view.go
+++ b/routers/repo/view.go
@@ -396,6 +396,20 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
isLFSFile := false
ctx.Data["IsTextFile"] = isTextFile
+ isDisplayingSource := ctx.Query("display") == "source"
+ isDisplayingRendered := !isDisplayingSource
+ isRepresentableAsText := base.IsRepresentableAsText(buf)
+ ctx.Data["IsRepresentableAsText"] = isRepresentableAsText
+ if !isRepresentableAsText {
+ // If we can't show plain text, always try to render.
+ isDisplayingSource = false
+ isDisplayingRendered = true
+ }
+ ctx.Data["IsDisplayingSource"] = isDisplayingSource
+ ctx.Data["IsDisplayingRendered"] = isDisplayingRendered
+
+ ctx.Data["IsTextSource"] = isTextFile || isDisplayingSource
+
//Check for LFS meta file
if isTextFile && setting.LFS.StartServer {
meta := lfs.IsPointerFile(&buf)
@@ -451,12 +465,18 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
// Assume file is not editable first.
if isLFSFile {
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
- } else if !isTextFile {
+ } else if !isRepresentableAsText {
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
}
switch {
- case isTextFile:
+ case isRepresentableAsText:
+ // This will be true for SVGs.
+ if base.IsImageFile(buf) {
+ ctx.Data["IsImageFile"] = true
+ ctx.Data["HasSourceRenderedToggle"] = true
+ }
+
if fileSize >= setting.UI.MaxDisplayFileSize {
ctx.Data["IsFileTooLarge"] = true
break