Compare commits

...

5 Commits

Author SHA1 Message Date
John Olheiser
9f33aa61bd Proposed changelog for 1.7.4 (#6316)
* Proposed changelog for 1.7.4

Signed-off-by: jolheiser <john.olheiser@gmail.com>

* Updated security fix description with @zeripath suggestion.

* Added 6292

* Update CHANGELOG.md

* Update CHANGELOG.md
2019-03-13 09:02:58 +08:00
Lunny Xiao
d0bbfd835f update git vendor to fix wrong release commit id and add migrations (#6224) (#6300) 2019-03-12 13:39:20 -04:00
techknowlogick
c7bbfd8f5e backport 6306 (#6308) 2019-03-12 18:58:49 +08:00
Muhammed TİFTİKÇİ
59a64c0e1d Fix #5580 : Make organization dropdown scrollable when using mouse wh… (#6246)
* Fix #5580 : Make organization dropdown scrollable when using mouse wheel.

* build less file with old makefile
2019-03-05 13:27:50 -05:00
Lunny Xiao
6a86a82368 fix display dashboard even if require to change password (#6214) (#6215)
* fix display dashboard even if require to change password

* fix comments
2019-02-28 19:36:57 +08:00
18 changed files with 235 additions and 86 deletions

View File

@@ -4,6 +4,15 @@ 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.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
* SECURITY
* Fix potential XSS vulnerability in repository description. (#6306) (#6308)
* BUGFIXES
* Fix wrong release commit id (#6224) (#6300)
* Fix panic on empty signed commits (#6292) (#6300)
* Fix organization dropdown not being scrollable when using mouse wheel (#5988) (#6246)
* Fix displaying dashboard even if required to change password (#6214) (#6215)
## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
* BUGFIXES
* Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)

5
Gopkg.lock generated
View File

@@ -3,11 +3,11 @@
[[projects]]
branch = "master"
digest = "1:ab875622908a804a327a95a1701002b150806a3c5406df51ec231eac16d3a1ca"
digest = "1:e1fa64238b0a2dbf1edf98c4af8d1b8cb65179e286d7f28006b50fa9f508ee9d"
name = "code.gitea.io/git"
packages = ["."]
pruneopts = "NUT"
revision = "389d3c803e12a30dffcbb54a15c2242521bc4333"
revision = "74d7c14dd4a3ed9c5def0dc3c1aeede399ddc5c5"
[[projects]]
branch = "master"
@@ -1173,7 +1173,6 @@
"github.com/keybase/go-crypto/openpgp",
"github.com/keybase/go-crypto/openpgp/armor",
"github.com/keybase/go-crypto/openpgp/packet",
"github.com/klauspost/compress/gzip",
"github.com/lafriks/xormstore",
"github.com/lib/pq",
"github.com/lunny/dingtalk_webhook",

View File

@@ -719,10 +719,12 @@ var (
// DescriptionHTML does special handles to description and return HTML string.
func (repo *Repository) DescriptionHTML() template.HTML {
sanitize := func(s string) string {
return fmt.Sprintf(`<a href="%[1]s" target="_blank" rel="noopener noreferrer">%[1]s</a>`, s)
desc, err := markup.RenderDescriptionHTML([]byte(repo.Description), repo.HTMLURL(), repo.ComposeMetas())
if err != nil {
log.Error(4, "Failed to render description for %s (ID: %d): %v", repo.Name, repo.ID, err)
return template.HTML(markup.Sanitize(repo.Description))
}
return template.HTML(descPattern.ReplaceAllStringFunc(markup.Sanitize(repo.Description), sanitize))
return template.HTML(markup.Sanitize(string(desc)))
}
// LocalCopyPath returns the local repository copy path.

View File

@@ -70,10 +70,6 @@ func (repo *Repository) CheckBranchName(name string) error {
return err
}
if _, err := gitRepo.GetTag(name); err == nil {
return ErrTagAlreadyExists{name}
}
branches, err := repo.GetBranches()
if err != nil {
return err
@@ -87,6 +83,11 @@ func (repo *Repository) CheckBranchName(name string) error {
return ErrBranchNameConflict{branch.Name}
}
}
if _, err := gitRepo.GetTag(name); err == nil {
return ErrTagAlreadyExists{name}
}
return nil
}

View File

@@ -44,21 +44,17 @@ func Toggle(options *ToggleOptions) macaron.Handler {
return
}
// prevent infinite redirection
// also make sure that the form cannot be accessed by
// users who don't need this
if ctx.Req.URL.Path == "/user/settings/change_password" {
if !ctx.User.MustChangePassword {
ctx.Redirect(setting.AppSubURL + "/")
}
return
}
if ctx.User.MustChangePassword {
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
if ctx.Req.URL.Path != "/user/settings/change_password" {
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
return
}
} else if ctx.Req.URL.Path == "/user/settings/change_password" {
// make sure that the form cannot be accessed by users who don't need this
ctx.Redirect(setting.AppSubURL + "/")
return
}
}

View File

@@ -234,6 +234,23 @@ func RenderCommitMessage(
return ctx.postProcess(rawHTML)
}
// RenderDescriptionHTML will use similar logic as PostProcess, but will
// use a single special linkProcessor.
func RenderDescriptionHTML(
rawHTML []byte,
urlPrefix string,
metas map[string]string,
) ([]byte, error) {
ctx := &postProcessCtx{
metas: metas,
urlPrefix: urlPrefix,
procs: []processor{
descriptionLinkProcessor,
},
}
return ctx.postProcess(rawHTML)
}
var byteBodyTag = []byte("<body>")
var byteBodyTagClosing = []byte("</body>")
@@ -668,3 +685,34 @@ func genDefaultLinkProcessor(defaultLink string) processor {
node.FirstChild, node.LastChild = ch, ch
}
}
// descriptionLinkProcessor creates links for DescriptionHTML
func descriptionLinkProcessor(ctx *postProcessCtx, node *html.Node) {
m := linkRegex.FindStringIndex(node.Data)
if m == nil {
return
}
uri := node.Data[m[0]:m[1]]
replaceContent(node, m[0], m[1], createDescriptionLink(uri, uri))
}
func createDescriptionLink(href, content string) *html.Node {
textNode := &html.Node{
Type: html.TextNode,
Data: content,
}
linkNode := &html.Node{
FirstChild: textNode,
LastChild: textNode,
Type: html.ElementNode,
Data: "a",
DataAtom: atom.A,
Attr: []html.Attribute{
{Key: "href", Val: href},
{Key: "target", Val: "_blank"},
{Key: "rel", Val: "noopener noreferrer"},
},
}
textNode.Parent = linkNode
return linkNode
}

File diff suppressed because one or more lines are too long

View File

@@ -384,33 +384,12 @@ pre, code {
}
.overflow.menu {
.items {
max-height: 300px;
overflow-y: auto;
.item {
position: relative;
cursor: pointer;
display: block;
border: none;
height: auto;
border-top: none;
line-height: 1em;
color: rgba(0,0,0,.8);
padding: .71428571em 1.14285714em !important;
font-size: 1rem;
text-transform: none;
font-weight: 400;
box-shadow: none;
-webkit-touch-callout: none;
&.active {
font-weight: 700;
}
&:hover {
background: rgba(0,0,0,.05);
color: rgba(0,0,0,.8);
z-index: 13;
}
.ui.floating.dropdown {
.overflow.menu {
.scrolling.menu.items {
border-radius: 0px !important;
box-shadow: none !important;
border-bottom: 1px solid rgba(34, 36, 38, 0.15);
}
}
}

View File

@@ -6,6 +6,7 @@ package routers
import (
"bytes"
"net/url"
"strings"
"code.gitea.io/gitea/models"
@@ -43,6 +44,11 @@ func Home(ctx *context.Context) {
log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(200, "user/auth/prohibit_login")
} else if ctx.User.MustChangePassword {
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
} else {
user.Dashboard(ctx)
}

View File

@@ -50,7 +50,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
}
entries.CustomSort(base.NaturalSortLess)
ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath)
ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath, nil)
if err != nil {
ctx.ServerError("GetCommitsInfo", err)
return

View File

@@ -11,7 +11,7 @@
<div class="ui header">
{{.i18n.Tr "home.switch_dashboard_context"}}
</div>
<div class="items">
<div class="scrolling menu items">
<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{end}}">
<img class="ui avatar image" src="{{.SignedUser.RelAvatarLink}}">
{{.SignedUser.Name}}

11
vendor/code.gitea.io/git/cache.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
// Copyright 2019 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 git
// LastCommitCache cache
type LastCommitCache interface {
Get(repoPath, ref, entryPath string) (*Commit, error)
Put(repoPath, ref, entryPath string, commit *Commit) error
}

53
vendor/code.gitea.io/git/commit.go generated vendored
View File

@@ -1,4 +1,5 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2018 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.
@@ -9,6 +10,7 @@ import (
"bytes"
"container/list"
"fmt"
"io"
"net/http"
"strconv"
"strings"
@@ -16,6 +18,7 @@ import (
// Commit represents a git commit.
type Commit struct {
Branch string // Branch this commit belongs to
Tree
ID SHA1 // The ID of this commit object
Author *Signature
@@ -279,6 +282,56 @@ func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
return nil, nil
}
// CommitFileStatus represents status of files in a commit.
type CommitFileStatus struct {
Added []string
Removed []string
Modified []string
}
// NewCommitFileStatus creates a CommitFileStatus
func NewCommitFileStatus() *CommitFileStatus {
return &CommitFileStatus{
[]string{}, []string{}, []string{},
}
}
// GetCommitFileStatus returns file status of commit in given repository.
func GetCommitFileStatus(repoPath, commitID string) (*CommitFileStatus, error) {
stdout, w := io.Pipe()
done := make(chan struct{})
fileStatus := NewCommitFileStatus()
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
if len(fields) < 2 {
continue
}
switch fields[0][0] {
case 'A':
fileStatus.Added = append(fileStatus.Added, fields[1])
case 'D':
fileStatus.Removed = append(fileStatus.Removed, fields[1])
case 'M':
fileStatus.Modified = append(fileStatus.Modified, fields[1])
}
}
done <- struct{}{}
}()
stderr := new(bytes.Buffer)
err := NewCommand("show", "--name-status", "--pretty=format:''", commitID).RunInDirPipeline(repoPath, w, stderr)
w.Close() // Close writer to exit parsing goroutine
if err != nil {
return nil, concatenateError(err, stderr.String())
}
<-done
return fileStatus, nil
}
// GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository.
func GetFullCommitID(repoPath, shortID string) (string, error) {
if len(shortID) >= 40 {

View File

@@ -72,13 +72,20 @@ func (state *getCommitsInfoState) getTargetedEntryPath() string {
}
// repeatedly perform targeted searches for unpopulated entries
func targetedSearch(state *getCommitsInfoState, done chan error) {
func targetedSearch(state *getCommitsInfoState, done chan error, cache LastCommitCache) {
for {
entryPath := state.getTargetedEntryPath()
if len(entryPath) == 0 {
done <- nil
return
}
if cache != nil {
commit, err := cache.Get(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath)
if err == nil && commit != nil {
state.update(entryPath, commit)
continue
}
}
command := NewCommand("rev-list", "-1", state.headCommit.ID.String(), "--", entryPath)
output, err := command.RunInDir(state.headCommit.repo.Path)
if err != nil {
@@ -96,6 +103,9 @@ func targetedSearch(state *getCommitsInfoState, done chan error) {
return
}
state.update(entryPath, commit)
if cache != nil {
cache.Put(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath, commit)
}
}
}
@@ -118,9 +128,9 @@ func initGetCommitInfoState(entries Entries, headCommit *Commit, treePath string
}
// GetCommitsInfo gets information of all commits that are corresponding to these entries
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCommitCache) ([][]interface{}, error) {
state := initGetCommitInfoState(tes, commit, treePath)
if err := getCommitsInfo(state); err != nil {
if err := getCommitsInfo(state, cache); err != nil {
return nil, err
}
if len(state.commits) < len(state.entryPaths) {
@@ -188,7 +198,7 @@ func (state *getCommitsInfoState) update(entryPath string, commit *Commit) bool
const getCommitsInfoPretty = "--pretty=format:%H %ct %s"
func getCommitsInfo(state *getCommitsInfoState) error {
func getCommitsInfo(state *getCommitsInfoState, cache LastCommitCache) error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
@@ -215,7 +225,7 @@ func getCommitsInfo(state *getCommitsInfoState) error {
numThreads := runtime.NumCPU()
done := make(chan error, numThreads)
for i := 0; i < numThreads; i++ {
go targetedSearch(state, done)
go targetedSearch(state, done, cache)
}
scanner := bufio.NewScanner(readCloser)

View File

@@ -10,7 +10,7 @@ import (
"strconv"
"strings"
"github.com/mcuadros/go-version"
version "github.com/mcuadros/go-version"
)
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
@@ -32,7 +32,14 @@ func (repo *Repository) GetBranchCommitID(name string) (string, error) {
// GetTagCommitID returns last commit ID string of given tag.
func (repo *Repository) GetTagCommitID(name string) (string, error) {
return repo.GetRefCommitID(TagPrefix + name)
stdout, err := NewCommand("rev-list", "-n", "1", name).RunInDir(repo.Path)
if err != nil {
if strings.Contains(err.Error(), "unknown revision or path") {
return "", ErrNotExist{name, ""}
}
return "", err
}
return strings.TrimSpace(stdout), nil
}
// parseCommitData parses commit information from the (uncompressed) raw
@@ -94,7 +101,11 @@ l:
sig, err := newGPGSignatureFromCommitline(data, (nextline+1)+sigindex, true)
if err == nil && sig != nil {
// remove signature from commit message
cm = cm[:sigindex-1]
if sigindex == 0 {
cm = ""
} else {
cm = cm[:sigindex-1]
}
commit.Signature = sig
}
}
@@ -130,6 +141,14 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
commit.repo = repo
commit.ID = id
data, err = NewCommand("name-rev", id.String()).RunInDirBytes(repo.Path)
if err != nil {
return nil, err
}
// name-rev commitID ouput will be "COMMIT_ID master" or "COMMIT_ID master~12"
commit.Branch = strings.Split(strings.Split(string(data), " ")[1], "~")[0]
repo.commitCache.Set(id.String(), commit)
return commit, nil
}
@@ -138,10 +157,14 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
if len(commitID) != 40 {
var err error
commitID, err = NewCommand("rev-parse", commitID).RunInDir(repo.Path)
actualCommitID, err := NewCommand("rev-parse", commitID).RunInDir(repo.Path)
if err != nil {
if strings.Contains(err.Error(), "unknown revision or path") {
return nil, ErrNotExist{commitID, ""}
}
return nil, err
}
commitID = actualCommitID
}
id, err := NewIDFromString(commitID)
if err != nil {

20
vendor/code.gitea.io/git/repo_tag.go generated vendored
View File

@@ -76,12 +76,12 @@ func (repo *Repository) getTag(id SHA1) (*Tag, error) {
// GetTag returns a Git tag by given name.
func (repo *Repository) GetTag(name string) (*Tag, error) {
stdout, err := NewCommand("show-ref", "--tags", name).RunInDir(repo.Path)
idStr, err := repo.GetTagCommitID(name)
if err != nil {
return nil, err
}
id, err := NewIDFromString(strings.Split(stdout, " ")[0])
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}
@@ -103,26 +103,18 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) {
}
tagNames := strings.Split(stdout, "\n")
var tags []*Tag
var tags = make([]*Tag, 0, len(tagNames))
for _, tagName := range tagNames {
tagName = strings.TrimSpace(tagName)
if len(tagName) == 0 {
continue
}
commitID, err := NewCommand("rev-parse", tagName).RunInDir(repo.Path)
tag, err := repo.GetTag(tagName)
if err != nil {
return nil, err
}
commit, err := repo.GetCommit(commitID)
if err != nil {
return nil, err
}
tags = append(tags, &Tag{
Name: tagName,
Message: commit.Message(),
Object: commit.ID,
Tagger: commit.Author,
})
tags = append(tags, tag)
}
sortTagsByTime(tags)
return tags, nil

View File

@@ -29,13 +29,12 @@ func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile {
}
}
// RefURL guesses and returns reference URL.
func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
if sf.refURL == "" {
func getRefURL(refURL, urlPrefix, parentPath string) string {
if refURL == "" {
return ""
}
url := strings.TrimSuffix(sf.refURL, ".git")
url := strings.TrimSuffix(refURL, ".git")
// git://xxx/user/repo
if strings.HasPrefix(url, "git://") {
@@ -67,12 +66,21 @@ func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
if strings.Contains(urlPrefix, url[i+1:j]) {
return urlPrefix + url[j+1:]
}
if strings.HasPrefix(url, "ssh://") || strings.HasPrefix(url, "git+ssh://") {
k := strings.Index(url[j+1:], "/")
return "http://" + url[i+1:j] + "/" + url[j+1:][k+1:]
}
return "http://" + url[i+1:j] + "/" + url[j+1:]
}
return url
}
// RefURL guesses and returns reference URL.
func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
return getRefURL(sf.refURL, urlPrefix, parentPath)
}
// RefID returns reference ID.
func (sf *SubModuleFile) RefID() string {
return sf.refID

22
vendor/code.gitea.io/git/tree.go generated vendored
View File

@@ -18,6 +18,9 @@ type Tree struct {
entries Entries
entriesParsed bool
entriesRecursive Entries
entriesRecursiveParsed bool
}
// NewTree create a new tree according the repository and commit id
@@ -67,20 +70,29 @@ func (t *Tree) ListEntries() (Entries, error) {
if err != nil {
return nil, err
}
t.entries, err = parseTreeEntries(stdout, t)
if err == nil {
t.entriesParsed = true
}
return t.entries, err
}
// ListEntriesRecursive returns all entries of current tree recursively including all subtrees
func (t *Tree) ListEntriesRecursive() (Entries, error) {
if t.entriesParsed {
return t.entries, nil
if t.entriesRecursiveParsed {
return t.entriesRecursive, nil
}
stdout, err := NewCommand("ls-tree", "-t", "-r", t.ID.String()).RunInDirBytes(t.repo.Path)
if err != nil {
return nil, err
}
t.entries, err = parseTreeEntries(stdout, t)
return t.entries, err
t.entriesRecursive, err = parseTreeEntries(stdout, t)
if err == nil {
t.entriesRecursiveParsed = true
}
return t.entriesRecursive, err
}