mirror of
https://github.com/go-gitea/gitea
synced 2024-08-07 06:22:07 +02:00
Merge branch 'main' into fix-any-hash-parse
This commit is contained in:
commit
067853f5b2
@ -17,11 +17,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
charsetModule "code.gitea.io/gitea/modules/charset"
|
charsetModule "code.gitea.io/gitea/modules/charset"
|
||||||
|
"code.gitea.io/gitea/modules/container"
|
||||||
"code.gitea.io/gitea/modules/httpcache"
|
"code.gitea.io/gitea/modules/httpcache"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/typesniffer"
|
"code.gitea.io/gitea/modules/typesniffer"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"github.com/klauspost/compress/gzhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServeHeaderOptions struct {
|
type ServeHeaderOptions struct {
|
||||||
@ -38,6 +41,11 @@ type ServeHeaderOptions struct {
|
|||||||
func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
|
func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
|
||||||
header := w.Header()
|
header := w.Header()
|
||||||
|
|
||||||
|
skipCompressionExts := container.SetOf(".gz", ".bz2", ".zip", ".xz", ".zst", ".deb", ".apk", ".jar", ".png", ".jpg", ".webp")
|
||||||
|
if skipCompressionExts.Contains(strings.ToLower(path.Ext(opts.Filename))) {
|
||||||
|
w.Header().Add(gzhttp.HeaderNoCompression, "1")
|
||||||
|
}
|
||||||
|
|
||||||
contentType := typesniffer.ApplicationOctetStream
|
contentType := typesniffer.ApplicationOctetStream
|
||||||
if opts.ContentType != "" {
|
if opts.ContentType != "" {
|
||||||
if opts.ContentTypeCharset != "" {
|
if opts.ContentTypeCharset != "" {
|
||||||
|
@ -592,17 +592,16 @@ func replaceContentList(node *html.Node, i, j int, newNodes []*html.Node) {
|
|||||||
|
|
||||||
func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
||||||
start := 0
|
start := 0
|
||||||
next := node.NextSibling
|
for node != nil {
|
||||||
for node != nil && node != next && start < len(node.Data) {
|
found, loc := references.FindFirstMentionBytes(util.UnsafeStringToBytes(node.Data[start:]))
|
||||||
// We replace only the first mention; other mentions will be addressed later
|
|
||||||
found, loc := references.FindFirstMentionBytes([]byte(node.Data[start:]))
|
|
||||||
if !found {
|
if !found {
|
||||||
return
|
node = node.NextSibling
|
||||||
|
start = 0
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
loc.Start += start
|
loc.Start += start
|
||||||
loc.End += start
|
loc.End += start
|
||||||
mention := node.Data[loc.Start:loc.End]
|
mention := node.Data[loc.Start:loc.End]
|
||||||
var teams string
|
|
||||||
teams, ok := ctx.Metas["teams"]
|
teams, ok := ctx.Metas["teams"]
|
||||||
// FIXME: util.URLJoin may not be necessary here:
|
// FIXME: util.URLJoin may not be necessary here:
|
||||||
// - setting.AppURL is defined to have a terminal '/' so unless mention[1:]
|
// - setting.AppURL is defined to have a terminal '/' so unless mention[1:]
|
||||||
@ -624,10 +623,10 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
|||||||
if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) {
|
if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) {
|
||||||
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "mention"))
|
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "mention"))
|
||||||
node = node.NextSibling.NextSibling
|
node = node.NextSibling.NextSibling
|
||||||
} else {
|
|
||||||
node = node.NextSibling
|
|
||||||
}
|
|
||||||
start = 0
|
start = 0
|
||||||
|
} else {
|
||||||
|
start = loc.End
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
// TODO: fix invalid linking issue
|
// TODO: fix invalid linking issue
|
||||||
|
|
||||||
// mentionPattern matches all mentions in the form of "@user" or "@org/team"
|
// mentionPattern matches all mentions in the form of "@user" or "@org/team"
|
||||||
mentionPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(@[0-9a-zA-Z-_]+|@[0-9a-zA-Z-_]+\/?[0-9a-zA-Z-_]+|@[0-9a-zA-Z-_][0-9a-zA-Z-_.]+\/?[0-9a-zA-Z-_.]+[0-9a-zA-Z-_])(?:\s|[:,;.?!]\s|[:,;.?!]?$|\)|\])`)
|
mentionPattern = regexp.MustCompile(`(?:\s|^|\(|\[)(@[-\w][-.\w]*?|@[-\w][-.\w]*?/[-\w][-.\w]*?)(?:\s|$|[:,;.?!](\s|$)|'|\)|\])`)
|
||||||
// issueNumericPattern matches string that references to a numeric issue, e.g. #1287
|
// issueNumericPattern matches string that references to a numeric issue, e.g. #1287
|
||||||
issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\'|\")([#!][0-9]+)(?:\s|$|\)|\]|\'|\"|[:;,.?!]\s|[:;,.?!]$)`)
|
issueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[|\'|\")([#!][0-9]+)(?:\s|$|\)|\]|\'|\"|[:;,.?!]\s|[:;,.?!]$)`)
|
||||||
// issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234
|
// issueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234
|
||||||
|
@ -392,6 +392,7 @@ func TestRegExp_mentionPattern(t *testing.T) {
|
|||||||
{"@gitea,", "@gitea"},
|
{"@gitea,", "@gitea"},
|
||||||
{"@gitea;", "@gitea"},
|
{"@gitea;", "@gitea"},
|
||||||
{"@gitea/team1;", "@gitea/team1"},
|
{"@gitea/team1;", "@gitea/team1"},
|
||||||
|
{"@user's idea", "@user"},
|
||||||
}
|
}
|
||||||
falseTestCases := []string{
|
falseTestCases := []string{
|
||||||
"@ 0",
|
"@ 0",
|
||||||
@ -412,7 +413,6 @@ func TestRegExp_mentionPattern(t *testing.T) {
|
|||||||
|
|
||||||
for _, testCase := range trueTestCases {
|
for _, testCase := range trueTestCases {
|
||||||
found := mentionPattern.FindStringSubmatch(testCase.pat)
|
found := mentionPattern.FindStringSubmatch(testCase.pat)
|
||||||
assert.Len(t, found, 2)
|
|
||||||
assert.Equal(t, testCase.exp, found[1])
|
assert.Equal(t, testCase.exp, found[1])
|
||||||
}
|
}
|
||||||
for _, testCase := range falseTestCases {
|
for _, testCase := range falseTestCases {
|
||||||
|
@ -207,3 +207,8 @@ func TestRenderLabels(t *testing.T) {
|
|||||||
expected = `/owner/repo/pulls?labels=123`
|
expected = `/owner/repo/pulls?labels=123`
|
||||||
assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected)
|
assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserMention(t *testing.T) {
|
||||||
|
rendered := RenderMarkdownToHtml(context.Background(), "@no-such-user @mention-user @mention-user")
|
||||||
|
assert.EqualValues(t, `<p>@no-such-user <a href="/mention-user" rel="nofollow">@mention-user</a> <a href="/mention-user" rel="nofollow">@mention-user</a></p>`, strings.TrimSpace(string(rendered)))
|
||||||
|
}
|
||||||
|
@ -54,7 +54,7 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const GzipMinSize = 1400 // min size to compress for the body size of response
|
var GzipMinSize = 1400 // min size to compress for the body size of response
|
||||||
|
|
||||||
// optionsCorsHandler return a http handler which sets CORS options if enabled by config, it blocks non-CORS OPTIONS requests.
|
// optionsCorsHandler return a http handler which sets CORS options if enabled by config, it blocks non-CORS OPTIONS requests.
|
||||||
func optionsCorsHandler() func(next http.Handler) http.Handler {
|
func optionsCorsHandler() func(next http.Handler) http.Handler {
|
||||||
|
33
tests/integration/repo_archive_test.go
Normal file
33
tests/integration/repo_archive_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
"code.gitea.io/gitea/routers"
|
||||||
|
"code.gitea.io/gitea/routers/web"
|
||||||
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRepoDownloadArchive(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
defer test.MockVariableValue(&setting.EnableGzip, true)()
|
||||||
|
defer test.MockVariableValue(&web.GzipMinSize, 10)()
|
||||||
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", "/user2/repo1/archive/master.zip")
|
||||||
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
bs, err := io.ReadAll(resp.Body)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, resp.Header().Get("Content-Encoding"))
|
||||||
|
assert.Equal(t, 320, len(bs))
|
||||||
|
}
|
@ -152,6 +152,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ui.attached.segment:has(+ .ui[class*="top attached"].header),
|
.ui.attached.segment:has(+ .ui[class*="top attached"].header),
|
||||||
|
.ui.attached.segment:has(+ .page.buttons),
|
||||||
.ui.attached.segment:last-child,
|
.ui.attached.segment:last-child,
|
||||||
.ui.segment:has(+ .ui.segment:not(.attached)),
|
.ui.segment:has(+ .ui.segment:not(.attached)),
|
||||||
.ui.attached.segment:has(+ .ui.modal) {
|
.ui.attached.segment:has(+ .ui.modal) {
|
||||||
|
Loading…
Reference in New Issue
Block a user