@@ -19,6 +19,9 @@ import (
19
19
"code.gitea.io/gitea/modules/log"
20
20
)
21
21
22
+ var javascriptTypes = []string {"application/ecmascript" , "application/javascript" , "text/ecmascript" , "text/javascript" ,
23
+ "text/jscript" , "text/livescript" }
24
+
22
25
// ServeData download file from io.Reader
23
26
func ServeData (ctx * context.Context , name string , size int64 , reader io.Reader ) error {
24
27
buf := make ([]byte , 1024 )
@@ -41,26 +44,44 @@ func ServeData(ctx *context.Context, name string, size int64, reader io.Reader)
41
44
// Google Chrome dislike commas in filenames, so let's change it to a space
42
45
name = strings .ReplaceAll (name , "," , " " )
43
46
44
- if base .IsTextFile (buf ) || ctx .QueryBool ("render" ) {
45
- cs , err := charset .DetectEncoding (buf )
46
- if err != nil {
47
- log .Error ("Detect raw file %s charset failed: %v, using by default utf-8" , name , err )
48
- cs = "utf-8"
47
+ ct := base .DetectContentType (buf )
48
+ matches := func (mimes []string ) bool {
49
+ for _ , mime := range mimes {
50
+ if strings .Contains (ct , mime ) {
51
+ return true
52
+ }
49
53
}
50
- ctx .Resp .Header ().Set ("Content-Type" , "text/plain; charset=" + strings .ToLower (cs ))
51
- } else if base .IsImageFile (buf ) || base .IsPDFFile (buf ) {
54
+ return false
55
+ }
56
+ if ct == "" {
57
+ log .Error ("Detect raw file %s content type failed: %v, using by default text/plain" , name , err )
58
+ ct = "text/plain"
59
+ } else if matches (javascriptTypes ) {
60
+ // Serve JavaScript files as plain text to prevent XSS attacks
61
+ ct = "text/plain"
62
+ }
63
+
64
+ if matches ([]string {"text/" }) || ctx .QueryBool ("render" ) {
65
+ if ! strings .Contains (ct , "charset=" ) {
66
+ cs , err := charset .DetectEncoding (buf )
67
+ if err != nil {
68
+ log .Error ("Detect raw file %s charset failed: %v, using by default utf-8" , name , err )
69
+ cs = "utf-8"
70
+ }
71
+ ct += "; charset=" + cs
72
+ }
73
+ } else if matches ([]string {"image/" , "application/pdf" }) {
52
74
ctx .Resp .Header ().Set ("Content-Disposition" , fmt .Sprintf (`inline; filename="%s"` , name ))
53
75
ctx .Resp .Header ().Set ("Access-Control-Expose-Headers" , "Content-Disposition" )
54
- if base .IsSVGImageFile (buf ) {
55
- ctx .Resp .Header ().Set ("Content-Security-Policy" , "default-src 'none'; style-src 'unsafe-inline'; sandbox" )
56
- ctx .Resp .Header ().Set ("X-Content-Type-Options" , "nosniff" )
57
- ctx .Resp .Header ().Set ("Content-Type" , base .SVGMimeType )
58
- }
59
76
} else {
60
77
ctx .Resp .Header ().Set ("Content-Disposition" , fmt .Sprintf (`attachment; filename="%s"` , name ))
61
78
ctx .Resp .Header ().Set ("Access-Control-Expose-Headers" , "Content-Disposition" )
62
79
}
63
80
81
+ ctx .Resp .Header ().Set ("Content-Type" , strings .ToLower (ct ))
82
+ ctx .Resp .Header ().Set ("X-Content-Type-Options" , "nosniff" )
83
+ ctx .Resp .Header ().Set ("Content-Security-Policy" , "default-src 'none'; style-src 'unsafe-inline'; sandbox" )
84
+
64
85
_ , err = ctx .Resp .Write (buf )
65
86
if err != nil {
66
87
return err
0 commit comments