Compare commits

...

9 Commits

Author SHA1 Message Date
zeripath
c7d8181a70 Changelog 1.15.6 (#17457)
* Changelog 1.15.6

Unforunately #17435 is a somewhat critical bug and therefore we should
really release 1.15.6 as soon as possible.

 ## [1.15.6](https://github.com/go-gitea/gitea/releases/tag/v1.15.6) - 2021-10-27

* BUGFIXES
  * Prevent panic in serv.go with Deploy Keys (#17434) (#17435)
  * Fix CSV render error (#17406) (#17431)
  * Read expected buffer size (#17409) (#17430)

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Add 17456 and its backport

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Add 17464

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Add final pr

* Update date

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2021-10-28 16:11:23 +08:00
wxiaoguang
548ae3eb98 Make commit-statuses popup show correctly (#17447) (#17466)
Backport #17447

Close #17443
2021-10-28 08:42:31 +01:00
zeripath
2c383d812d Add integration tests for private.NoServCommand and private.ServCommand (#17456) (#17463)
Backport #17456

modules/private/serv.go has two major functions that are missing testcases to ensure
that Deploy and normal SSH keys work correctly.

This PR adds some basic integration tests for these.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: 6543 <6543@obermui.de>
2021-10-28 14:07:29 +08:00
zeripath
ef12b8de80 Ensure that restricted users can access repos for which they are members (#17460) (#17464)
Backport #17460

There is a small bug in the way that repo access is checked in
repoAssignment: Accessibility is checked by checking if the user has a
marked access to the repository instead of checking if the user has any
team granted access.

This PR changes this permissions check to use HasAccess() which does the
correct test. There is also a fix in the release api ListReleases where
it should return draft releases if the user is a member of a team with
write access to the releases.

The PR also adds a testcase.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-10-28 11:33:18 +08:00
zeripath
dd1ba34ee5 Prevent panic in serv.go with Deploy Keys (#17434) (#17435)
Backport #17434

Unfortunately there was a regression in #17373 which missed that the user is not
for deploy keys. This leads to a panic when pushing with deploy keys.

Fix #17412

Signed-off-by: Andrew Thornton <art27@cantab.net>
2021-10-26 01:24:29 +02:00
KN4CK3R
1fbdf96c34 Fix CSV render error (#17406) (#17431)
Backport #17406.

Closes #17378 

Both errors from #17378 were caused by  #15175.

Problem 1 (error with added file):
`ToUTF8WithFallbackReader` creates a `MultiReader` from a `byte[2048]` and the remaining reader. `CreateReaderAndGuessDelimiter` tries to read 10000 bytes from this reader but only gets 2048 because that's the first reader in the `MultiReader`. Then the `if size < 1e4` thinks the input is at EOF and just returns that.

Problem 2 (error with changed file):
The blob reader gets defer closed. That was fine because the old version reads the whole file into memory. Now with the streaming version the close needs to defer after the method.

Co-authored-by: zeripath <art27@cantab.net>
2021-10-25 18:31:15 +01:00
KN4CK3R
5159055278 Read expected buffer size (#17409) (#17430)
Backport of #17409

* Read expected buffer size.

* Changed name.
2021-10-25 17:46:56 +01:00
wxiaoguang
06da10b9a1 Fix markdown checkbox rendering (#17427)
We allow to render empty check list item - [ ], while GitHub doesn't allow.

To make the rendering correct, we need tune the UI (the last PR #17413 uses absolute layout, which makes the empty checkbox item can not be displayed correctly)
2021-10-25 17:02:39 +08:00
wxiaoguang
175ebc6f88 Fix issue markdown bugs (#17413)
* Bug fix: render Markdown `http://AppURL/org/repo/issues/4?a=1&b=2#comment-123 test` to HTML correctly, close #17394
* Bug fix: fix the positions of checkboxes in rendered HTML, close #17395

# Conflicts:
#	modules/markup/html.go
2021-10-23 23:30:46 +08:00
24 changed files with 339 additions and 61 deletions

View File

@@ -4,6 +4,17 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.15.6](https://github.com/go-gitea/gitea/releases/tag/v1.15.6) - 2021-10-28
* BUGFIXES
* Prevent panic in serv.go with Deploy Keys (#17434) (#17435)
* Fix CSV render error (#17406) (#17431)
* Read expected buffer size (#17409) (#17430)
* Ensure that restricted users can access repos for which they are members (#17460) (#17464)
* Make commit-statuses popup show correctly (#17447) (#17466)
* TESTING
* Add integration tests for private.NoServCommand and private.ServCommand (#17456) (#17463)
## [1.15.5](https://github.com/go-gitea/gitea/releases/tag/v1.15.5) - 2021-10-21
* SECURITY

View File

@@ -0,0 +1,154 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package integrations
import (
"context"
"net/url"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/private"
"github.com/stretchr/testify/assert"
)
func TestAPIPrivateNoServ(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
key, user, err := private.ServNoCommand(ctx, 1)
assert.NoError(t, err)
assert.Equal(t, int64(2), user.ID)
assert.Equal(t, "user2", user.Name)
assert.Equal(t, int64(1), key.ID)
assert.Equal(t, "user2@localhost", key.Name)
deployKey, err := models.AddDeployKey(1, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
assert.NoError(t, err)
key, user, err = private.ServNoCommand(ctx, deployKey.KeyID)
assert.NoError(t, err)
assert.Empty(t, user)
assert.Equal(t, deployKey.KeyID, key.ID)
assert.Equal(t, "test-deploy", key.Name)
})
}
func TestAPIPrivateServ(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Can push to a repo we own
results, err := private.ServCommand(ctx, 1, "user2", "repo1", models.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
assert.Equal(t, int64(1), results.KeyID)
assert.Equal(t, "user2@localhost", results.KeyName)
assert.Equal(t, "user2", results.UserName)
assert.Equal(t, int64(2), results.UserID)
assert.Equal(t, "user2", results.OwnerName)
assert.Equal(t, "repo1", results.RepoName)
assert.Equal(t, int64(1), results.RepoID)
// Cannot push to a private repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Cannot pull from a private repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", models.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Can pull from a public repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", models.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
assert.Equal(t, int64(1), results.KeyID)
assert.Equal(t, "user2@localhost", results.KeyName)
assert.Equal(t, "user2", results.UserName)
assert.Equal(t, int64(2), results.UserID)
assert.Equal(t, "user15", results.OwnerName)
assert.Equal(t, "big_test_public_1", results.RepoName)
assert.Equal(t, int64(17), results.RepoID)
// Cannot push to a public repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", models.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Add reading deploy key
deployKey, err := models.AddDeployKey(19, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", true)
assert.NoError(t, err)
// Can pull from repo we're a deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)
assert.Equal(t, int64(15), results.UserID)
assert.Equal(t, "user15", results.OwnerName)
assert.Equal(t, "big_test_private_1", results.RepoName)
assert.Equal(t, int64(19), results.RepoID)
// Cannot push to a private repo with reading key
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Cannot pull from a private repo we're not associated with
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_private_2", models.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Cannot pull from a public repo we're not associated with
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_public_1", models.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Add writing deploy key
deployKey, err = models.AddDeployKey(20, "test-deploy", "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment", false)
assert.NoError(t, err)
// Cannot push to a private repo with reading key
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)
// Can pull from repo we're a writing deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", models.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)
assert.Equal(t, int64(15), results.UserID)
assert.Equal(t, "user15", results.OwnerName)
assert.Equal(t, "big_test_private_2", results.RepoName)
assert.Equal(t, int64(20), results.RepoID)
// Can push to repo we're a writing deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", models.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)
assert.Equal(t, int64(15), results.UserID)
assert.Equal(t, "user15", results.OwnerName)
assert.Equal(t, "big_test_private_2", results.RepoName)
assert.Equal(t, int64(20), results.RepoID)
})
}

View File

@@ -5,10 +5,12 @@
package integrations
import (
"fmt"
"net/http"
"strings"
"testing"
api "code.gitea.io/gitea/modules/structs"
"github.com/stretchr/testify/assert"
)
@@ -110,3 +112,64 @@ func TestPrivateOrg(t *testing.T) {
req = NewRequest(t, "GET", "/privated_org/private_repo_on_private_org")
session.MakeRequest(t, req, http.StatusOK)
}
func TestOrgRestrictedUser(t *testing.T) {
defer prepareTestEnv(t)()
// privated_org is a private org who has id 23
orgName := "privated_org"
// public_repo_on_private_org is a public repo on privated_org
repoName := "public_repo_on_private_org"
// user29 is a restricted user who is not a member of the organization
restrictedUser := "user29"
// #17003 reports a bug whereby adding a restricted user to a read-only team doesn't work
// assert restrictedUser cannot see the org or the public repo
restrictedSession := loginUser(t, restrictedUser)
req := NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
restrictedSession.MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
restrictedSession.MakeRequest(t, req, http.StatusNotFound)
// Therefore create a read-only team
adminSession := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, adminSession)
teamToCreate := &api.CreateTeamOption{
Name: "codereader",
Description: "Code Reader",
IncludesAllRepositories: true,
Permission: "read",
Units: []string{"repo.code"},
}
req = NewRequestWithJSON(t, "POST",
fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", orgName, token), teamToCreate)
var apiTeam api.Team
resp := adminSession.MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &apiTeam)
checkTeamResponse(t, &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
teamToCreate.Permission, teamToCreate.Units)
checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
teamToCreate.Permission, teamToCreate.Units)
//teamID := apiTeam.ID
// Now we need to add the restricted user to the team
req = NewRequest(t, "PUT",
fmt.Sprintf("/api/v1/teams/%d/members/%s?token=%s", apiTeam.ID, restrictedUser, token))
_ = adminSession.MakeRequest(t, req, http.StatusNoContent)
// Now we need to check if the restrictedUser can access the repo
req = NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
restrictedSession.MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
restrictedSession.MakeRequest(t, req, http.StatusOK)
}

View File

@@ -568,7 +568,7 @@
-
id: 40
owner_id: 23
owner_name: limited_org
owner_name: privated_org
lower_name: public_repo_on_private_org
name: public_repo_on_private_org
is_private: false
@@ -581,7 +581,7 @@
-
id: 41
owner_id: 23
owner_name: limited_org
owner_name: privated_org
lower_name: private_repo_on_private_org
name: private_repo_on_private_org
is_private: true

View File

@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/gogs/chardet"
"golang.org/x/net/html/charset"
@@ -26,9 +27,9 @@ var UTF8BOM = []byte{'\xef', '\xbb', '\xbf'}
// ToUTF8WithFallbackReader detects the encoding of content and coverts to UTF-8 reader if possible
func ToUTF8WithFallbackReader(rd io.Reader) io.Reader {
var buf = make([]byte, 2048)
n, err := rd.Read(buf)
n, err := util.ReadAtMost(rd, buf)
if err != nil {
return rd
return io.MultiReader(bytes.NewReader(RemoveBOMIfPresent(buf[:n])), rd)
}
charsetLabel, err := DetectEncoding(buf[:n])

View File

@@ -345,7 +345,7 @@ func repoAssignment(ctx *Context, repo *models.Repository) {
}
// Check access.
if ctx.Repo.Permission.AccessMode == models.AccessModeNone {
if !ctx.Repo.Permission.HasAccess() {
if ctx.Query("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
return

View File

@@ -28,35 +28,24 @@ func CreateReader(input io.Reader, delimiter rune) *stdcsv.Reader {
}
// CreateReaderAndGuessDelimiter tries to guess the field delimiter from the content and creates a csv.Reader.
// Reads at most 10k bytes.
func CreateReaderAndGuessDelimiter(rd io.Reader) (*stdcsv.Reader, error) {
var data = make([]byte, 1e4)
size, err := rd.Read(data)
size, err := util.ReadAtMost(rd, data)
if err != nil {
if err == io.EOF {
return CreateReader(bytes.NewReader([]byte{}), rune(',')), nil
}
return nil, err
}
delimiter := guessDelimiter(data[:size])
var newInput io.Reader
if size < 1e4 {
newInput = bytes.NewReader(data[:size])
} else {
newInput = io.MultiReader(bytes.NewReader(data), rd)
}
return CreateReader(newInput, delimiter), nil
return CreateReader(
io.MultiReader(bytes.NewReader(data[:size]), rd),
guessDelimiter(data[:size]),
), nil
}
// guessDelimiter scores the input CSV data against delimiters, and returns the best match.
// Reads at most 10k bytes & 10 lines.
func guessDelimiter(data []byte) rune {
maxLines := 10
maxBytes := util.Min(len(data), 1e4)
text := string(data[:maxBytes])
text = quoteRegexp.ReplaceAllLiteralString(text, "")
text := quoteRegexp.ReplaceAllLiteralString(string(data), "")
lines := strings.SplitN(text, "\n", maxLines+1)
lines = lines[:util.Min(maxLines, len(lines))]

View File

@@ -12,6 +12,7 @@ import (
"io/ioutil"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
)
// This file contains common functions between the gogit and !gogit variants for git Blobs
@@ -29,7 +30,7 @@ func (b *Blob) GetBlobContent() (string, error) {
}
defer dataRc.Close()
buf := make([]byte, 1024)
n, _ := dataRc.Read(buf)
n, _ := util.ReadAtMost(dataRc, buf)
buf = buf[:n]
return string(buf), nil
}

View File

@@ -92,7 +92,7 @@ func isLinkStr(link string) bool {
func getIssueFullPattern() *regexp.Regexp {
if issueFullPattern == nil {
issueFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) +
`\w+/\w+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#]\S+.(\S+)?)?\b`)
`\w+/\w+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`)
}
return issueFullPattern
}

View File

@@ -265,6 +265,10 @@ func TestRender_FullIssueURLs(t *testing.T) {
`<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4</a>`)
test("http://localhost:3000/gogits/gogs/issues/4",
`<a href="http://localhost:3000/gogits/gogs/issues/4" class="ref-issue">#4</a>`)
test("http://localhost:3000/gogits/gogs/issues/4 test",
`<a href="http://localhost:3000/gogits/gogs/issues/4" class="ref-issue">#4</a> test`)
test("http://localhost:3000/gogits/gogs/issues/4?a=1&b=2#comment-123 test",
`<a href="http://localhost:3000/gogits/gogs/issues/4?a=1&amp;b=2#comment-123" class="ref-issue">#4</a> test`)
}
func TestRegExp_sha1CurrentPattern(t *testing.T) {

View File

@@ -19,6 +19,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
stdcharset "golang.org/x/net/html/charset"
"golang.org/x/text/transform"
@@ -61,7 +62,7 @@ func detectEncodingAndBOM(entry *git.TreeEntry, repo *models.Repository) (string
}
defer reader.Close()
buf := make([]byte, 1024)
n, err := reader.Read(buf)
n, err := util.ReadAtMost(reader, buf)
if err != nil {
// return default
return "UTF-8", false
@@ -84,7 +85,7 @@ func detectEncodingAndBOM(entry *git.TreeEntry, repo *models.Repository) (string
}
defer dataRc.Close()
buf = make([]byte, 1024)
n, err = dataRc.Read(buf)
n, err = util.ReadAtMost(dataRc, buf)
if err != nil {
// return default
return "UTF-8", false

View File

@@ -10,6 +10,8 @@ import (
"net/http"
"regexp"
"strings"
"code.gitea.io/gitea/modules/util"
)
// Use at most this many bytes to determine Content Type.
@@ -86,8 +88,8 @@ func DetectContentType(data []byte) SniffedType {
// DetectContentTypeFromReader guesses the content type contained in the reader.
func DetectContentTypeFromReader(r io.Reader) (SniffedType, error) {
buf := make([]byte, sniffLen)
n, err := r.Read(buf)
if err != nil && err != io.EOF {
n, err := util.ReadAtMost(r, buf)
if err != nil {
return SniffedType{}, fmt.Errorf("DetectContentTypeFromReader io error: %w", err)
}
buf = buf[:n]

20
modules/util/io.go Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package util
import (
"io"
)
// ReadAtMost reads at most len(buf) bytes from r into buf.
// It returns the number of bytes copied. n is only less then len(buf) if r provides fewer bytes.
// If EOF occurs while reading, err will be nil.
func ReadAtMost(r io.Reader, buf []byte) (n int, err error) {
n, err = io.ReadFull(r, buf)
if err == io.EOF || err == io.ErrUnexpectedEOF {
err = nil
}
return
}

View File

@@ -115,7 +115,7 @@ func ListReleases(ctx *context.APIContext) {
opts := models.FindReleasesOptions{
ListOptions: listOptions,
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite,
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite || ctx.Repo.UnitAccessMode(models.UnitTypeReleases) >= models.AccessModeWrite,
IncludeTags: false,
IsDraft: ctx.QueryOptionalBool("draft"),
IsPreRelease: ctx.QueryOptionalBool("pre-release"),

View File

@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
)
// ServeBlob download a git.Blob
@@ -42,8 +43,8 @@ func ServeBlob(ctx *context.Context, blob *git.Blob) error {
// ServeData download file from io.Reader
func ServeData(ctx *context.Context, name string, size int64, reader io.Reader) error {
buf := make([]byte, 1024)
n, err := reader.Read(buf)
if err != nil && err != io.EOF {
n, err := util.ReadAtMost(reader, buf)
if err != nil {
return err
}
if n >= 0 {

View File

@@ -282,7 +282,7 @@ func ServCommand(ctx *context.PrivateContext) {
(mode > models.AccessModeRead ||
repo.IsPrivate ||
owner.Visibility.IsPrivate() ||
user.IsRestricted ||
(user != nil && user.IsRestricted) || // user will be nil if the key is a deploykey
setting.Service.RequireSignInView) {
if key.Type == models.KeyTypeDeploy {
if deployKey.Mode < mode {

View File

@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/common"
)
@@ -43,10 +44,8 @@ func uploadAttachment(ctx *context.Context, allowedTypes string) {
defer file.Close()
buf := make([]byte, 1024)
n, _ := file.Read(buf)
if n > 0 {
buf = buf[:n]
}
n, _ := util.ReadAtMost(file, buf)
buf = buf[:n]
err = upload.Verify(buf, header.Filename, allowedTypes)
if err != nil {

View File

@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"html"
"io"
"net/http"
"path"
"path/filepath"
@@ -104,30 +105,36 @@ func setCsvCompareContext(ctx *context.Context) {
errTooLarge := errors.New(ctx.Locale.Tr("repo.error.csv.too_large"))
csvReaderFromCommit := func(c *git.Commit) (*csv.Reader, error) {
csvReaderFromCommit := func(c *git.Commit) (*csv.Reader, io.Closer, error) {
blob, err := c.GetBlobByPath(diffFile.Name)
if err != nil {
return nil, err
return nil, nil, err
}
if setting.UI.CSV.MaxFileSize != 0 && setting.UI.CSV.MaxFileSize < blob.Size() {
return nil, errTooLarge
return nil, nil, errTooLarge
}
reader, err := blob.DataAsync()
if err != nil {
return nil, err
return nil, nil, err
}
defer reader.Close()
return csv_module.CreateReaderAndGuessDelimiter(charset.ToUTF8WithFallbackReader(reader))
csvReader, err := csv_module.CreateReaderAndGuessDelimiter(charset.ToUTF8WithFallbackReader(reader))
return csvReader, reader, err
}
baseReader, err := csvReaderFromCommit(baseCommit)
baseReader, baseBlobCloser, err := csvReaderFromCommit(baseCommit)
if baseBlobCloser != nil {
defer baseBlobCloser.Close()
}
if err == errTooLarge {
return CsvDiffResult{nil, err.Error()}
}
headReader, err := csvReaderFromCommit(headCommit)
headReader, headBlobCloser, err := csvReaderFromCommit(headCommit)
if headBlobCloser != nil {
defer headBlobCloser.Close()
}
if err == errTooLarge {
return CsvDiffResult{nil, err.Error()}
}

View File

@@ -114,7 +114,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
ctx.Data["FileName"] = blob.Name()
buf := make([]byte, 1024)
n, _ := dataRc.Read(buf)
n, _ := util.ReadAtMost(dataRc, buf)
buf = buf[:n]
// Only some file types are editable online as text.
@@ -747,7 +747,7 @@ func UploadFileToServer(ctx *context.Context) {
defer file.Close()
buf := make([]byte, 1024)
n, _ := file.Read(buf)
n, _ := util.ReadAtMost(file, buf)
if n > 0 {
buf = buf[:n]
}

View File

@@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
)
const (
@@ -272,7 +273,7 @@ func LFSFileGet(ctx *context.Context) {
}
defer dataRc.Close()
buf := make([]byte, 1024)
n, err := dataRc.Read(buf)
n, err := util.ReadAtMost(dataRc, buf)
if err != nil {
ctx.ServerError("Data", err)
return
@@ -297,10 +298,10 @@ func LFSFileGet(ctx *context.Context) {
break
}
buf := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc))
rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc))
// Building code view blocks with line number on server side.
fileContent, _ := ioutil.ReadAll(buf)
fileContent, _ := ioutil.ReadAll(rd)
var output bytes.Buffer
lines := strings.Split(string(fileContent), "\n")

View File

@@ -31,6 +31,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
)
const (
@@ -264,7 +265,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
defer dataRc.Close()
buf := make([]byte, 1024)
n, _ := dataRc.Read(buf)
n, _ := util.ReadAtMost(dataRc, buf)
buf = buf[:n]
st := typesniffer.DetectContentType(buf)
@@ -299,7 +300,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
defer dataRc.Close()
buf = make([]byte, 1024)
n, err = dataRc.Read(buf)
n, err = util.ReadAtMost(dataRc, buf)
if err != nil {
ctx.ServerError("Data", err)
return
@@ -413,7 +414,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
ctx.Data["RawFileLink"] = rawLink + "/" + ctx.Repo.TreePath
buf := make([]byte, 1024)
n, _ := dataRc.Read(buf)
n, _ := util.ReadAtMost(dataRc, buf)
buf = buf[:n]
st := typesniffer.DetectContentType(buf)
@@ -445,10 +446,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
defer dataRc.Close()
buf = make([]byte, 1024)
n, err = dataRc.Read(buf)
// Error EOF don't mean there is an error, it just means we read to
// the end
if err != nil && err != io.EOF {
n, err = util.ReadAtMost(dataRc, buf)
if err != nil {
ctx.ServerError("Data", err)
return
}

View File

@@ -788,10 +788,13 @@ async function initRepository() {
// Commit statuses
$('.commit-statuses-trigger').each(function () {
const positionRight = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0;
const popupPosition = positionRight ? 'right center' : 'left center';
$(this)
.popup({
on: 'click',
position: ($('.repository.file.list').length > 0 ? 'right center' : 'left center'),
lastResort: popupPosition, // prevent error message "Popup does not fit within the boundaries of the viewport"
position: popupPosition,
});
});

View File

@@ -1,6 +1,19 @@
.repository {
.commit-statuses .list > .item {
line-height: 2;
.popup.commit-statuses {
// we had better limit the max size of the popup, and add scroll bars if the content size is too large.
// otherwise some part of the popup will be hidden by viewport boundary
max-height: 45vh;
max-width: 60vw;
overflow: auto;
padding: 0;
.list {
padding: .8em; // to make the scrollbar align to the border, we move the padding from outer `.popup` to this inside `.list`
> .item {
line-height: 2;
}
}
}
.repo-header {

View File

@@ -158,9 +158,18 @@
.task-list-item {
list-style-type: none;
position: relative;
line-height: 1.5rem;
min-height: 1.5rem; // to render a checkbox list without content `- [ ]`, we need this min-height to make sure the <li> can be visible
input[type="checkbox"] {
margin: 0 6px .25em -1.6em;
position: absolute;
top: .25em;
left: -1.6em;
}
p {
line-height: 1.5rem;
}
}