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 @@
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
+ {{else if .IsPlainText}}
+ {{if .FileContent}}{{.FileContent | Safe}}{{end}}
{{else if not .IsTextFile}}