Skip to content

Commit 282b8a3

Browse files
authored
Merge branch 'main' into fix-15932-close-earlier
2 parents 3759a6b + effad26 commit 282b8a3

File tree

15 files changed

+164
-180
lines changed

15 files changed

+164
-180
lines changed

integrations/links_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ func TestLinksNoLogin(t *testing.T) {
3535
"/user2/repo1",
3636
"/user2/repo1/projects",
3737
"/user2/repo1/projects/1",
38+
"/assets/img/404.png",
39+
"/assets/img/500.png",
3840
}
3941

4042
for _, link := range links {

modules/notification/mail/mail.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ func (m *mailNotifier) NotifyNewIssue(issue *models.Issue, mentions []*models.Us
5454

5555
func (m *mailNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, actionComment *models.Comment, isClosed bool) {
5656
var actionType models.ActionType
57-
issue.Content = ""
5857
if issue.IsPull {
5958
if isClosed {
6059
actionType = models.ActionClosePullRequest
@@ -124,7 +123,6 @@ func (m *mailNotifier) NotifyMergePullRequest(pr *models.PullRequest, doer *mode
124123
log.Error("pr.LoadIssue: %v", err)
125124
return
126125
}
127-
pr.Issue.Content = ""
128126
if err := mailer.MailParticipants(pr.Issue, doer, models.ActionMergePullRequest, nil); err != nil {
129127
log.Error("MailParticipants: %v", err)
130128
}
@@ -151,8 +149,6 @@ func (m *mailNotifier) NotifyPullRequestPushCommits(doer *models.User, pr *model
151149
if err := comment.LoadPushCommits(); err != nil {
152150
log.Error("comment.LoadPushCommits: %v", err)
153151
}
154-
comment.Content = ""
155-
156152
m.NotifyCreateIssueComment(doer, comment.Issue.Repo, comment.Issue, comment, nil)
157153
}
158154

modules/public/dynamic.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ import (
1313
"time"
1414
)
1515

16-
// Static implements the static handler for serving assets.
17-
func Static(opts *Options) func(next http.Handler) http.Handler {
18-
return opts.staticHandler(opts.Directory)
16+
func fileSystem(dir string) http.FileSystem {
17+
return http.Dir(dir)
1918
}
2019

21-
// ServeContent serve http content
22-
func ServeContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
20+
// serveContent serve http content
21+
func serveContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
2322
http.ServeContent(w, req, fi.Name(), modtime, content)
2423
}

modules/public/public.go

Lines changed: 67 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,85 +5,82 @@
55
package public
66

77
import (
8-
"log"
98
"net/http"
9+
"os"
1010
"path"
1111
"path/filepath"
1212
"strings"
1313

1414
"code.gitea.io/gitea/modules/httpcache"
15+
"code.gitea.io/gitea/modules/log"
1516
"code.gitea.io/gitea/modules/setting"
1617
)
1718

1819
// Options represents the available options to configure the handler.
1920
type Options struct {
2021
Directory string
21-
IndexFile string
22-
SkipLogging bool
23-
FileSystem http.FileSystem
2422
Prefix string
23+
CorsHandler func(http.Handler) http.Handler
2524
}
2625

27-
// KnownPublicEntries list all direct children in the `public` directory
28-
var KnownPublicEntries = []string{
29-
"css",
30-
"fonts",
31-
"img",
32-
"js",
33-
"serviceworker.js",
34-
"vendor",
35-
}
36-
37-
// Custom implements the static handler for serving custom assets.
38-
func Custom(opts *Options) func(next http.Handler) http.Handler {
39-
return opts.staticHandler(path.Join(setting.CustomPath, "public"))
40-
}
41-
42-
// staticFileSystem implements http.FileSystem interface.
43-
type staticFileSystem struct {
44-
dir *http.Dir
45-
}
46-
47-
func newStaticFileSystem(directory string) staticFileSystem {
48-
if !filepath.IsAbs(directory) {
49-
directory = filepath.Join(setting.AppWorkPath, directory)
26+
// AssetsHandler implements the static handler for serving custom or original assets.
27+
func AssetsHandler(opts *Options) func(next http.Handler) http.Handler {
28+
var custPath = filepath.Join(setting.CustomPath, "public")
29+
if !filepath.IsAbs(custPath) {
30+
custPath = filepath.Join(setting.AppWorkPath, custPath)
31+
}
32+
if !filepath.IsAbs(opts.Directory) {
33+
opts.Directory = filepath.Join(setting.AppWorkPath, opts.Directory)
34+
}
35+
if !strings.HasSuffix(opts.Prefix, "/") {
36+
opts.Prefix += "/"
5037
}
51-
dir := http.Dir(directory)
52-
return staticFileSystem{&dir}
53-
}
5438

55-
func (fs staticFileSystem) Open(name string) (http.File, error) {
56-
return fs.dir.Open(name)
57-
}
39+
return func(next http.Handler) http.Handler {
40+
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
41+
if !strings.HasPrefix(req.URL.Path, opts.Prefix) {
42+
next.ServeHTTP(resp, req)
43+
return
44+
}
45+
if req.Method != "GET" && req.Method != "HEAD" {
46+
resp.WriteHeader(http.StatusNotFound)
47+
return
48+
}
5849

59-
// StaticHandler sets up a new middleware for serving static files in the
60-
func StaticHandler(dir string, opts *Options) func(next http.Handler) http.Handler {
61-
return opts.staticHandler(dir)
62-
}
50+
file := req.URL.Path
51+
file = file[len(opts.Prefix):]
52+
if len(file) == 0 {
53+
resp.WriteHeader(http.StatusNotFound)
54+
return
55+
}
56+
if strings.Contains(file, "\\") {
57+
resp.WriteHeader(http.StatusBadRequest)
58+
return
59+
}
60+
file = "/" + file
61+
62+
var written bool
63+
if opts.CorsHandler != nil {
64+
written = true
65+
opts.CorsHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
66+
written = false
67+
})).ServeHTTP(resp, req)
68+
}
69+
if written {
70+
return
71+
}
6372

64-
func (opts *Options) staticHandler(dir string) func(next http.Handler) http.Handler {
65-
return func(next http.Handler) http.Handler {
66-
// Defaults
67-
if len(opts.IndexFile) == 0 {
68-
opts.IndexFile = "index.html"
69-
}
70-
// Normalize the prefix if provided
71-
if opts.Prefix != "" {
72-
// Ensure we have a leading '/'
73-
if opts.Prefix[0] != '/' {
74-
opts.Prefix = "/" + opts.Prefix
73+
// custom files
74+
if opts.handle(resp, req, http.Dir(custPath), file) {
75+
return
7576
}
76-
// Remove any trailing '/'
77-
opts.Prefix = strings.TrimRight(opts.Prefix, "/")
78-
}
79-
if opts.FileSystem == nil {
80-
opts.FileSystem = newStaticFileSystem(dir)
81-
}
8277

83-
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
84-
if !opts.handle(w, req, opts) {
85-
next.ServeHTTP(w, req)
78+
// internal files
79+
if opts.handle(resp, req, fileSystem(opts.Directory), file) {
80+
return
8681
}
82+
83+
resp.WriteHeader(http.StatusNotFound)
8784
})
8885
}
8986
}
@@ -98,76 +95,36 @@ func parseAcceptEncoding(val string) map[string]bool {
9895
return types
9996
}
10097

101-
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, opt *Options) bool {
102-
if req.Method != "GET" && req.Method != "HEAD" {
103-
return false
104-
}
105-
106-
file := req.URL.Path
107-
// if we have a prefix, filter requests by stripping the prefix
108-
if opt.Prefix != "" {
109-
if !strings.HasPrefix(file, opt.Prefix) {
110-
return false
111-
}
112-
file = file[len(opt.Prefix):]
113-
if file != "" && file[0] != '/' {
114-
return false
115-
}
116-
}
117-
118-
f, err := opt.FileSystem.Open(file)
98+
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.FileSystem, file string) bool {
99+
// use clean to keep the file is a valid path with no . or ..
100+
f, err := fs.Open(path.Clean(file))
119101
if err != nil {
120-
// 404 requests to any known entries in `public`
121-
if path.Base(opts.Directory) == "public" {
122-
parts := strings.Split(file, "/")
123-
if len(parts) < 2 {
124-
return false
125-
}
126-
for _, entry := range KnownPublicEntries {
127-
if entry == parts[1] {
128-
w.WriteHeader(404)
129-
return true
130-
}
131-
}
102+
if os.IsNotExist(err) {
103+
return false
132104
}
133-
return false
105+
w.WriteHeader(http.StatusInternalServerError)
106+
log.Error("[Static] Open %q failed: %v", file, err)
107+
return true
134108
}
135109
defer f.Close()
136110

137111
fi, err := f.Stat()
138112
if err != nil {
139-
log.Printf("[Static] %q exists, but fails to open: %v", file, err)
113+
w.WriteHeader(http.StatusInternalServerError)
114+
log.Error("[Static] %q exists, but fails to open: %v", file, err)
140115
return true
141116
}
142117

143118
// Try to serve index file
144119
if fi.IsDir() {
145-
// Redirect if missing trailing slash.
146-
if !strings.HasSuffix(req.URL.Path, "/") {
147-
http.Redirect(w, req, path.Clean(req.URL.Path+"/"), http.StatusFound)
148-
return true
149-
}
150-
151-
f, err = opt.FileSystem.Open(file)
152-
if err != nil {
153-
return false // Discard error.
154-
}
155-
defer f.Close()
156-
157-
fi, err = f.Stat()
158-
if err != nil || fi.IsDir() {
159-
return false
160-
}
161-
}
162-
163-
if !opt.SkipLogging {
164-
log.Println("[Static] Serving " + file)
120+
w.WriteHeader(http.StatusNotFound)
121+
return true
165122
}
166123

167124
if httpcache.HandleFileETagCache(req, w, fi) {
168125
return true
169126
}
170127

171-
ServeContent(w, req, fi, fi.ModTime(), f)
128+
serveContent(w, req, fi, fi.ModTime(), f)
172129
return true
173130
}

modules/public/static.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@ import (
2020
"code.gitea.io/gitea/modules/log"
2121
)
2222

23-
// Static implements the static handler for serving assets.
24-
func Static(opts *Options) func(next http.Handler) http.Handler {
25-
opts.FileSystem = Assets
26-
// we don't need to pass the directory, because the directory var is only
27-
// used when in the options there is no FileSystem.
28-
return opts.staticHandler("")
23+
func fileSystem(dir string) http.FileSystem {
24+
return Assets
2925
}
3026

3127
func Asset(name string) ([]byte, error) {
@@ -59,8 +55,8 @@ func AssetIsDir(name string) (bool, error) {
5955
}
6056
}
6157

62-
// ServeContent serve http content
63-
func ServeContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
58+
// serveContent serve http content
59+
func serveContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
6460
encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding"))
6561
if encodings["gzip"] {
6662
if cf, ok := fi.(*vfsgen۰CompressedFileInfo); ok {
@@ -76,7 +72,7 @@ func ServeContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modt
7672
_, err := rd.Seek(0, io.SeekStart) // rewind to output whole file
7773
if err != nil {
7874
log.Error("rd.Seek error: %v", err)
79-
http.Error(w, http.StatusText(500), 500)
75+
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
8076
return
8177
}
8278
}

options/gitignore/Gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,3 @@ gradle-app.setting
1010

1111
# Cache of project
1212
.gradletasknamecache
13-
14-
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
15-
# gradle/wrapper/gradle-wrapper.properties

options/gitignore/Gretl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# gitignore template for Gretl
2+
# website: http://gretl.sourceforge.net/
3+
4+
# Auto-generated log file is overwritten whenever you start a new session
5+
session.inp
6+
7+
# Auto-generated temporary string code table
8+
string_table.txt

options/gitignore/Node

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ npm-debug.log*
55
yarn-debug.log*
66
yarn-error.log*
77
lerna-debug.log*
8+
.pnpm-debug.log*
89

910
# Diagnostic reports (https://nodejs.org/api/report.html)
1011
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
@@ -71,6 +72,7 @@ web_modules/
7172
# dotenv environment variables file
7273
.env
7374
.env.test
75+
.env.production
7476

7577
# parcel-bundler cache (https://parceljs.org/)
7678
.cache

options/gitignore/SPFx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#SharePoint Framework (SPFx)
2+
# Logs
3+
logs
4+
*.log
5+
npm-debug.log*
6+
7+
# Dependency directories
8+
node_modules
9+
10+
# Build generated files
11+
dist
12+
lib
13+
solution
14+
temp
15+
*.sppkg
16+
17+
# Coverage directory used by tools like istanbul
18+
coverage
19+
20+
# OSX
21+
.DS_Store
22+
23+
# Visual Studio files
24+
.ntvs_analysis.dat
25+
.vs
26+
bin
27+
obj
28+
29+
# Resx Generated Code
30+
*.resx.ts
31+
32+
# Styles Generated Code
33+
*.scss.ts

options/gitignore/Umbraco

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
**/App_Data/umbraco.config
1616

1717
## this [Uu]mbraco/ folder should be created by cmd like `Install-Package UmbracoCms -Version 8.5.3`
18-
## you can find your umbraco version at your Web.config. (i.e. <add key="Umbraco.Core.ConfigurationStatus" value="8.5.3" />)
18+
## you can find your Umbraco version in your Web.config. (i.e. <add key="Umbraco.Core.ConfigurationStatus" value="8.5.3" />)
1919
## Uncomment this line if you think it fits the way you work on your project.
2020
## **/[Uu]mbraco/
2121

@@ -29,4 +29,4 @@
2929
**/App_Data/cache/
3030

3131
# Ignore the Models Builder models out of date flag
32-
**/App_Data/Models/ood.flag
32+
**/ood.flag

0 commit comments

Comments
 (0)