diff --git a/go.mod b/go.mod index e8cb554782..cf3d71fa51 100644 --- a/go.mod +++ b/go.mod @@ -88,6 +88,7 @@ require ( github.com/unrolled/render v1.5.0 github.com/urfave/cli v1.22.10 github.com/xanzy/go-gitlab v0.73.1 + github.com/xeipuuv/gojsonschema v1.2.0 github.com/yohcop/openid-go v1.0.0 github.com/yuin/goldmark v1.5.2 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87 @@ -266,6 +267,8 @@ require ( github.com/valyala/fastjson v1.6.3 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.2 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.6 // indirect diff --git a/go.sum b/go.sum index 7a1787b863..4ef817eaa2 100644 --- a/go.sum +++ b/go.sum @@ -1468,6 +1468,12 @@ github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+ github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= diff --git a/modules/charset/escape.go b/modules/charset/escape.go index ce2eb1446d..3b1c206977 100644 --- a/modules/charset/escape.go +++ b/modules/charset/escape.go @@ -8,6 +8,7 @@ package charset import ( + "bufio" "io" "strings" @@ -31,7 +32,7 @@ func EscapeControlHTML(text string, locale translation.Locale, allowed ...rune) return streamer.escaped, sb.String() } -// EscapeControlReaders escapes the unicode control sequences in a provider reader and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte +// EscapeControlReaders escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) { outputStream := &HTMLStreamerWriter{Writer: writer} streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer) @@ -43,6 +44,35 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation. return streamer.escaped, err } +// EscapeControlStringReader escapes the unicode control sequences in a provided reader of string content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte +func EscapeControlStringReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) { + bufRd := bufio.NewReader(reader) + outputStream := &HTMLStreamerWriter{Writer: writer} + streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer) + + for { + line, rdErr := bufRd.ReadString('\n') + if len(line) > 0 { + if err := streamer.Text(line); err != nil { + streamer.escaped.HasError = true + log.Error("Error whilst escaping: %v", err) + return streamer.escaped, err + } + } + if rdErr != nil { + if rdErr != io.EOF { + err = rdErr + } + break + } + if err := streamer.SelfClosingTag("br"); err != nil { + streamer.escaped.HasError = true + return streamer.escaped, err + } + } + return streamer.escaped, err +} + // EscapeControlString escapes the unicode control sequences in a provided string and returns the findings as an EscapeStatus and the escaped string func EscapeControlString(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) { sb := &strings.Builder{} diff --git a/modules/storage/local.go b/modules/storage/local.go index a439a24592..ca51d26c9a 100644 --- a/modules/storage/local.go +++ b/modules/storage/local.go @@ -102,7 +102,8 @@ func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error) return 0, err } // Golang's tmp file (os.CreateTemp) always have 0o600 mode, so we need to change the file to follow the umask (as what Create/MkDir does) - if err := util.ApplyUmask(p, os.ModePerm); err != nil { + // but we don't want to make these files executable - so ensure that we mask out the executable bits + if err := util.ApplyUmask(p, os.ModePerm&0o666); err != nil { return 0, err } diff --git a/options/license/LOOP b/options/license/LOOP new file mode 100644 index 0000000000..434d2c45e2 --- /dev/null +++ b/options/license/LOOP @@ -0,0 +1,44 @@ +Portions of LOOP are Copyright (c) 1986 by the Massachusetts Institute of Technology. +All Rights Reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the M.I.T. copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. The names "M.I.T." and "Massachusetts +Institute of Technology" may not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. Notice must be given in supporting documentation that +copying distribution is by permission of M.I.T. M.I.T. makes no +representations about the suitability of this software for any purpose. +It is provided "as is" without express or implied warranty. + +Massachusetts Institute of Technology +77 Massachusetts Avenue +Cambridge, Massachusetts 02139 +United States of America ++1-617-253-1000 + +Portions of LOOP are Copyright (c) 1989, 1990, 1991, 1992 by Symbolics, Inc. +All Rights Reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the Symbolics copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation. The name "Symbolics" may not be used in +advertising or publicity pertaining to distribution of the software +without specific, written prior permission. Notice must be given in +supporting documentation that copying distribution is by permission of +Symbolics. Symbolics makes no representations about the suitability of +this software for any purpose. It is provided "as is" without express +or implied warranty. + +Symbolics, CLOE Runtime, and Minima are trademarks, and CLOE, Genera, +and Zetalisp are registered trademarks of Symbolics, Inc. + +Symbolics, Inc. +8 New England Executive Park, East +Burlington, Massachusetts 01803 +United States of America ++1-617-221-1000 diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index f139a971fc..3e3a4efc31 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -9,7 +9,6 @@ import ( gocontext "context" "encoding/base64" "fmt" - gotemplate "html/template" "io" "net/http" "net/url" @@ -350,15 +349,13 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin if err != nil { log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.name, ctx.Repo.Repository, err) buf := &bytes.Buffer{} - ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf, ctx.Locale) - ctx.Data["FileContent"] = strings.ReplaceAll( - gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, - ) + ctx.Data["EscapeStatus"], _ = charset.EscapeControlStringReader(rd, buf, ctx.Locale) + ctx.Data["FileContent"] = buf.String() } } else { - ctx.Data["IsRenderedHTML"] = true + ctx.Data["IsPlainText"] = true buf := &bytes.Buffer{} - ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, &charset.BreakWriter{Writer: buf}, ctx.Locale, charset.RuneNBSP) + ctx.Data["EscapeStatus"], err = charset.EscapeControlStringReader(rd, buf, ctx.Locale) if err != nil { log.Error("Read failed: %v", err) } @@ -492,15 +489,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } // to prevent iframe load third-party url ctx.Resp.Header().Add("Content-Security-Policy", "frame-src 'self'") - } else if readmeExist && !shouldRenderSource { - buf := &bytes.Buffer{} - ctx.Data["IsRenderedHTML"] = true - - ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf, ctx.Locale) - - ctx.Data["FileContent"] = strings.ReplaceAll( - gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, - ) } else { buf, _ := io.ReadAll(rd) diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl index ce3c39eac2..6d20aaddef 100644 --- a/templates/repo/settings/lfs_file.tmpl +++ b/templates/repo/settings/lfs_file.tmpl @@ -17,11 +17,11 @@
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}} -
+
{{if .IsMarkup}} {{if .FileContent}}{{.FileContent | Safe}}{{end}} - {{else if .IsRenderedHTML}} -
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
+ {{else if .IsPlainText}} +
{{if .FileContent}}{{.FileContent | Safe}}{{end}}
{{else if not .IsTextFile}}
{{if .IsImageFile}} diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index 9d82cc018c..711a37461e 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -61,11 +61,11 @@ {{if not (or .IsMarkup .IsRenderedHTML)}} {{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}} {{end}} -
+
{{if .IsMarkup}} {{if .FileContent}}{{.FileContent | Safe}}{{end}} - {{else if .IsRenderedHTML}} -
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
+ {{else if .IsPlainText}} +
{{if .FileContent}}{{.FileContent | Safe}}{{end}}
{{else if not .IsTextSource}}
{{if .IsImageFile}} diff --git a/templates/user/dashboard/repolist.tmpl b/templates/user/dashboard/repolist.tmpl index 620cc322f0..9d0ea01ec5 100644 --- a/templates/user/dashboard/repolist.tmpl +++ b/templates/user/dashboard/repolist.tmpl @@ -128,9 +128,9 @@