diff options
author | Jonathan Tran <jonnytran@gmail.com> | 2021-01-12 22:45:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-12 22:45:19 -0500 |
commit | 81467e6f35f343b911c09f746deca869a48da4c8 (patch) | |
tree | 1b759007789bc0dbeeb543d54739ccf8b8dfb434 /routers/repo | |
parent | 9465e60504284699078e620f7c892a9685d91458 (diff) | |
download | gitea-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.go | 5 | ||||
-rw-r--r-- | routers/repo/editor.go | 6 | ||||
-rw-r--r-- | routers/repo/lfs.go | 11 | ||||
-rw-r--r-- | routers/repo/view.go | 24 |
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 |