mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-05 18:32:41 +09:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30560b0f9b | ||
|
|
6076674d3a | ||
|
|
28cc3bd662 | ||
|
|
2631f7f64d | ||
|
|
af4626a270 | ||
|
|
21c70e1ed2 | ||
|
|
b45d58805a | ||
|
|
200b974e19 | ||
|
|
800271ee1f | ||
|
|
e6362f3d23 | ||
|
|
716c2918be | ||
|
|
60d7b614fe | ||
|
|
9cf9a54dca | ||
|
|
2b4f87da46 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -4,6 +4,26 @@ 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
|
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).
|
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||||
|
|
||||||
|
## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
|
||||||
|
* SECURITY
|
||||||
|
* Prevent DeleteFilePost doing arbitrary deletion (#5631)
|
||||||
|
* BUGFIX
|
||||||
|
* Fix wrong text getting saved on editing second comment on an issue (#5608)
|
||||||
|
|
||||||
|
## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
|
||||||
|
* SECURITY
|
||||||
|
* Sanitize uploaded file names (#5571) (#5573)
|
||||||
|
* HTMLEncode user added text (#5570) (#5575)
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix indexer reindex bug when gitea restart (#5563) (#5564)
|
||||||
|
* Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
|
||||||
|
* Fix bug when a read perm user to edit his issue (#5516) (#5534)
|
||||||
|
* Detect force push failure on deletion of protected branches (#5522) (#5531)
|
||||||
|
* Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
|
||||||
|
* Fix forgot deletion of notification when delete repository (#5506) (#5514)
|
||||||
|
* Fix undeleted content when deleting user (#5429) (#5509)
|
||||||
|
* Fix empty wiki (#5504) (#5508)
|
||||||
|
|
||||||
## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
|
## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
|
* Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
|
||||||
|
|||||||
24
cmd/hook.go
24
cmd/hook.go
@@ -112,10 +112,15 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||||
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if protectBranch != nil && protectBranch.IsProtected() {
|
if protectBranch != nil && protectBranch.IsProtected() {
|
||||||
|
// check and deletion
|
||||||
|
if newCommitID == git.EmptySHA {
|
||||||
|
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||||
|
}
|
||||||
|
|
||||||
// detect force push
|
// detect force push
|
||||||
if git.EmptySHA != oldCommitID {
|
if git.EmptySHA != oldCommitID {
|
||||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||||
@@ -126,17 +131,12 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check and deletion
|
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||||
if newCommitID == git.EmptySHA {
|
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
if err != nil {
|
||||||
} else {
|
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
} else if !canPush {
|
||||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||||
if err != nil {
|
|
||||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
|
||||||
} else if !canPush {
|
|
||||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
cmd/web.go
13
cmd/web.go
@@ -80,7 +80,13 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
|
|||||||
Cache: autocert.DirCache(directory),
|
Cache: autocert.DirCache(directory),
|
||||||
Email: email,
|
Email: email,
|
||||||
}
|
}
|
||||||
go http.ListenAndServe(listenAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validatio happens here)
|
go func() {
|
||||||
|
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||||
|
var err = http.ListenAndServe(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(4, "Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: listenAddr,
|
Addr: listenAddr,
|
||||||
Handler: m,
|
Handler: m,
|
||||||
@@ -96,7 +102,10 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target := setting.AppURL + r.URL.RequestURI()
|
// Remove the trailing slash at the end of setting.AppURL, the request
|
||||||
|
// URI always contains a leading slash, which would result in a double
|
||||||
|
// slash
|
||||||
|
target := strings.TrimRight(setting.AppURL, "/") + r.URL.RequestURI()
|
||||||
http.Redirect(w, r, target, http.StatusFound)
|
http.Redirect(w, r, target, http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1838,6 +1838,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
|||||||
&RepoRedirect{RedirectRepoID: repoID},
|
&RepoRedirect{RedirectRepoID: repoID},
|
||||||
&Webhook{RepoID: repoID},
|
&Webhook{RepoID: repoID},
|
||||||
&HookTask{RepoID: repoID},
|
&HookTask{RepoID: repoID},
|
||||||
|
&Notification{RepoID: repoID},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("deleteBeans: %v", err)
|
return fmt.Errorf("deleteBeans: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -535,6 +535,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
|||||||
if err = sess.Commit(); err != nil {
|
if err = sess.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
sess.Close()
|
||||||
|
|
||||||
return RewriteAllPublicKeys()
|
return RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
@@ -543,6 +544,10 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
|||||||
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
|
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
|
||||||
// outside any session scope independently.
|
// outside any session scope independently.
|
||||||
func RewriteAllPublicKeys() error {
|
func RewriteAllPublicKeys() error {
|
||||||
|
return rewriteAllPublicKeys(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteAllPublicKeys(e Engine) error {
|
||||||
//Don't rewrite key if internal server
|
//Don't rewrite key if internal server
|
||||||
if setting.SSH.StartBuiltinServer {
|
if setting.SSH.StartBuiltinServer {
|
||||||
return nil
|
return nil
|
||||||
@@ -569,7 +574,7 @@ func RewriteAllPublicKeys() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
err = e.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1038,25 +1038,26 @@ func deleteUser(e *xorm.Session, u *User) error {
|
|||||||
&EmailAddress{UID: u.ID},
|
&EmailAddress{UID: u.ID},
|
||||||
&UserOpenID{UID: u.ID},
|
&UserOpenID{UID: u.ID},
|
||||||
&Reaction{UserID: u.ID},
|
&Reaction{UserID: u.ID},
|
||||||
|
&TeamUser{UID: u.ID},
|
||||||
|
&Collaboration{UserID: u.ID},
|
||||||
|
&Stopwatch{UserID: u.ID},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("deleteBeans: %v", err)
|
return fmt.Errorf("deleteBeans: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***** START: PublicKey *****
|
// ***** START: PublicKey *****
|
||||||
keys := make([]*PublicKey, 0, 10)
|
if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil {
|
||||||
if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil {
|
|
||||||
return fmt.Errorf("get all public keys: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyIDs := make([]int64, len(keys))
|
|
||||||
for i := range keys {
|
|
||||||
keyIDs[i] = keys[i].ID
|
|
||||||
}
|
|
||||||
if err = deletePublicKeys(e, keyIDs...); err != nil {
|
|
||||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||||
}
|
}
|
||||||
|
rewriteAllPublicKeys(e)
|
||||||
// ***** END: PublicKey *****
|
// ***** END: PublicKey *****
|
||||||
|
|
||||||
|
// ***** START: GPGPublicKey *****
|
||||||
|
if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil {
|
||||||
|
return fmt.Errorf("deleteGPGKeys: %v", err)
|
||||||
|
}
|
||||||
|
// ***** END: GPGPublicKey *****
|
||||||
|
|
||||||
// Clear assignee.
|
// Clear assignee.
|
||||||
if err = clearAssigneeByUserID(e, u.ID); err != nil {
|
if err = clearAssigneeByUserID(e, u.ID); err != nil {
|
||||||
return fmt.Errorf("clear assignee: %v", err)
|
return fmt.Errorf("clear assignee: %v", err)
|
||||||
@@ -1110,6 +1111,7 @@ func DeleteUser(u *User) (err error) {
|
|||||||
if err = sess.Commit(); err != nil {
|
if err = sess.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
sess.Close()
|
||||||
|
|
||||||
return RewriteAllPublicKeys()
|
return RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = createIssueIndexer(); err != nil {
|
if err = createIssueIndexer(setting.Indexer.IssuePath, issueIndexerLatestVersion); err != nil {
|
||||||
log.Fatal(4, "InitIssuesIndexer: create index, %v", err)
|
log.Fatal(4, "InitIssuesIndexer: create index, %v", err)
|
||||||
}
|
}
|
||||||
if err = populateIndexer(); err != nil {
|
if err = populateIndexer(); err != nil {
|
||||||
@@ -69,7 +69,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createIssueIndexer create an issue indexer if one does not already exist
|
// createIssueIndexer create an issue indexer if one does not already exist
|
||||||
func createIssueIndexer() error {
|
func createIssueIndexer(path string, latestVersion int) error {
|
||||||
mapping := bleve.NewIndexMapping()
|
mapping := bleve.NewIndexMapping()
|
||||||
docMapping := bleve.NewDocumentMapping()
|
docMapping := bleve.NewDocumentMapping()
|
||||||
|
|
||||||
@@ -100,8 +100,14 @@ func createIssueIndexer() error {
|
|||||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
issueIndexer, err = bleve.New(setting.Indexer.IssuePath, mapping)
|
issueIndexer, err = bleve.New(path, mapping)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||||
|
Version: latestVersion,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// IssueIndexerBatch batch to add updates to
|
// IssueIndexerBatch batch to add updates to
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = createRepoIndexer(); err != nil {
|
if err = createRepoIndexer(setting.Indexer.RepoPath, repoIndexerLatestVersion); err != nil {
|
||||||
log.Fatal(4, "CreateRepoIndexer: %v", err)
|
log.Fatal(4, "CreateRepoIndexer: %v", err)
|
||||||
}
|
}
|
||||||
if err = populateIndexer(); err != nil {
|
if err = populateIndexer(); err != nil {
|
||||||
@@ -93,7 +93,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createRepoIndexer create a repo indexer if one does not already exist
|
// createRepoIndexer create a repo indexer if one does not already exist
|
||||||
func createRepoIndexer() error {
|
func createRepoIndexer(path string, latestVersion int) error {
|
||||||
var err error
|
var err error
|
||||||
docMapping := bleve.NewDocumentMapping()
|
docMapping := bleve.NewDocumentMapping()
|
||||||
numericFieldMapping := bleve.NewNumericFieldMapping()
|
numericFieldMapping := bleve.NewNumericFieldMapping()
|
||||||
@@ -119,8 +119,13 @@ func createRepoIndexer() error {
|
|||||||
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
||||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||||
|
|
||||||
repoIndexer, err = bleve.New(setting.Indexer.RepoPath, mapping)
|
repoIndexer, err = bleve.New(path, mapping)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||||
|
Version: latestVersion,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func filenameIndexerID(repoID int64, filename string) string {
|
func filenameIndexerID(repoID int64, filename string) string {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
function htmlEncode(text) {
|
||||||
|
return jQuery('<div />').text(text).html()
|
||||||
|
}
|
||||||
|
|
||||||
var csrf;
|
var csrf;
|
||||||
var suburl;
|
var suburl;
|
||||||
|
|
||||||
@@ -312,12 +316,12 @@ function initCommentForm() {
|
|||||||
switch (input_id) {
|
switch (input_id) {
|
||||||
case '#milestone_id':
|
case '#milestone_id':
|
||||||
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
||||||
$(this).text() + '</a>');
|
htmlEncode($(this).text()) + '</a>');
|
||||||
break;
|
break;
|
||||||
case '#assignee_id':
|
case '#assignee_id':
|
||||||
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
||||||
'<img class="ui avatar image" src=' + $(this).data('avatar') + '>' +
|
'<img class="ui avatar image" src=' + $(this).data('avatar') + '>' +
|
||||||
$(this).text() + '</a>');
|
htmlEncode($(this).text()) + '</a>');
|
||||||
}
|
}
|
||||||
$('.ui' + select_id + '.list .no-select').addClass('hide');
|
$('.ui' + select_id + '.list .no-select').addClass('hide');
|
||||||
$(input_id).val($(this).data('id'));
|
$(input_id).val($(this).data('id'));
|
||||||
@@ -604,7 +608,7 @@ function initRepository() {
|
|||||||
// Setup new form
|
// Setup new form
|
||||||
if ($editContentZone.html().length == 0) {
|
if ($editContentZone.html().length == 0) {
|
||||||
$editContentZone.html($('#edit-content-form').html());
|
$editContentZone.html($('#edit-content-form').html());
|
||||||
$textarea = $('#content');
|
$textarea = $editContentZone.find('textarea');
|
||||||
issuesTribute.attach($textarea.get());
|
issuesTribute.attach($textarea.get());
|
||||||
emojiTribute.attach($textarea.get());
|
emojiTribute.attach($textarea.get());
|
||||||
|
|
||||||
@@ -1456,7 +1460,7 @@ function searchUsers() {
|
|||||||
$.each(response.data, function (i, item) {
|
$.each(response.data, function (i, item) {
|
||||||
var title = item.login;
|
var title = item.login;
|
||||||
if (item.full_name && item.full_name.length > 0) {
|
if (item.full_name && item.full_name.length > 0) {
|
||||||
title += ' (' + item.full_name + ')';
|
title += ' (' + htmlEncode(item.full_name) + ')';
|
||||||
}
|
}
|
||||||
items.push({
|
items.push({
|
||||||
title: title,
|
title: title,
|
||||||
@@ -2510,7 +2514,7 @@ function initTopicbar() {
|
|||||||
if (res.topics) {
|
if (res.topics) {
|
||||||
formattedResponse.success = true;
|
formattedResponse.success = true;
|
||||||
for (var i=0;i < res.topics.length;i++) {
|
for (var i=0;i < res.topics.length;i++) {
|
||||||
formattedResponse.results.push({"description": res.topics[i].Name, "data-value":res.topics[i].Name})
|
formattedResponse.results.push({"description": res.topics[i].Name, "data-value": res.topics[i].Name})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2631,7 +2635,7 @@ function initIssueList() {
|
|||||||
// Parse the response from the api to work with our dropdown
|
// Parse the response from the api to work with our dropdown
|
||||||
$.each(response, function(index, issue) {
|
$.each(response, function(index, issue) {
|
||||||
filteredResponse.results.push({
|
filteredResponse.results.push({
|
||||||
'name' : '#' + issue.number + ' ' + issue.title,
|
'name' : '#' + issue.number + ' ' + htmlEncode(issue.title),
|
||||||
'value' : issue.id
|
'value' : issue.id
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -163,7 +163,11 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
|||||||
branchName = form.NewBranchName
|
branchName = form.NewBranchName
|
||||||
}
|
}
|
||||||
|
|
||||||
form.TreePath = strings.Trim(path.Clean("/"+form.TreePath), " /")
|
form.TreePath = cleanUploadFileName(form.TreePath)
|
||||||
|
if len(form.TreePath) == 0 {
|
||||||
|
ctx.Error(500, "Upload file name is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
||||||
|
|
||||||
ctx.Data["TreePath"] = form.TreePath
|
ctx.Data["TreePath"] = form.TreePath
|
||||||
@@ -373,6 +377,13 @@ func DeleteFile(ctx *context.Context) {
|
|||||||
func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||||
ctx.Data["PageIsDelete"] = true
|
ctx.Data["PageIsDelete"] = true
|
||||||
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
|
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
|
||||||
|
|
||||||
|
ctx.Repo.TreePath = cleanUploadFileName(ctx.Repo.TreePath)
|
||||||
|
if len(ctx.Repo.TreePath) == 0 {
|
||||||
|
ctx.Error(500, "Delete file name is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["TreePath"] = ctx.Repo.TreePath
|
ctx.Data["TreePath"] = ctx.Repo.TreePath
|
||||||
canCommit := renderCommitRights(ctx)
|
canCommit := renderCommitRights(ctx)
|
||||||
|
|
||||||
@@ -477,7 +488,12 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
|||||||
branchName = form.NewBranchName
|
branchName = form.NewBranchName
|
||||||
}
|
}
|
||||||
|
|
||||||
form.TreePath = strings.Trim(path.Clean("/"+form.TreePath), " /")
|
form.TreePath = cleanUploadFileName(form.TreePath)
|
||||||
|
if len(form.TreePath) == 0 {
|
||||||
|
ctx.Error(500, "Upload file name is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
||||||
if len(treeNames) == 0 {
|
if len(treeNames) == 0 {
|
||||||
// We must at least have one element for user to input.
|
// We must at least have one element for user to input.
|
||||||
@@ -559,6 +575,17 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
|||||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + branchName + "/" + form.TreePath)
|
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + branchName + "/" + form.TreePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cleanUploadFileName(name string) string {
|
||||||
|
name = strings.TrimLeft(name, "./\\")
|
||||||
|
name = strings.Replace(name, "../", "", -1)
|
||||||
|
name = strings.Replace(name, "..\\", "", -1)
|
||||||
|
name = strings.TrimPrefix(path.Clean(name), ".git/")
|
||||||
|
if name == ".git" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
// UploadFileToServer upload file to server file dir not git
|
// UploadFileToServer upload file to server file dir not git
|
||||||
func UploadFileToServer(ctx *context.Context) {
|
func UploadFileToServer(ctx *context.Context) {
|
||||||
file, header, err := ctx.Req.FormFile("file")
|
file, header, err := ctx.Req.FormFile("file")
|
||||||
@@ -591,7 +618,13 @@ func UploadFileToServer(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upload, err := models.NewUpload(header.Filename, buf, file)
|
name := cleanUploadFileName(header.Filename)
|
||||||
|
if len(name) == 0 {
|
||||||
|
ctx.Error(500, "Upload file name is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
upload, err := models.NewUpload(name, buf, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, fmt.Sprintf("NewUpload: %v", err))
|
ctx.Error(500, fmt.Sprintf("NewUpload: %v", err))
|
||||||
return
|
return
|
||||||
|
|||||||
30
routers/repo/editor_test.go
Normal file
30
routers/repo/editor_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCleanUploadName(t *testing.T) {
|
||||||
|
models.PrepareTestEnv(t)
|
||||||
|
|
||||||
|
var kases = map[string]string{
|
||||||
|
".git/refs/master": "git/refs/master",
|
||||||
|
"/root/abc": "root/abc",
|
||||||
|
"./../../abc": "abc",
|
||||||
|
"a/../.git": "a/.git",
|
||||||
|
"a/../../../abc": "a/abc",
|
||||||
|
"../../../acd": "acd",
|
||||||
|
"../../.git/abc": "git/abc",
|
||||||
|
"..\\..\\.git/abc": "git/abc",
|
||||||
|
}
|
||||||
|
for k, v := range kases {
|
||||||
|
assert.EqualValues(t, v, cleanUploadFileName(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,7 +73,6 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err
|
|||||||
|
|
||||||
commit, err := wikiRepo.GetBranchCommit("master")
|
commit, err := wikiRepo.GetBranchCommit("master")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranchCommit", err)
|
|
||||||
return wikiRepo, nil, err
|
return wikiRepo, nil, err
|
||||||
}
|
}
|
||||||
return wikiRepo, commit, nil
|
return wikiRepo, commit, nil
|
||||||
@@ -111,6 +110,9 @@ func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName strin
|
|||||||
func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *git.TreeEntry) {
|
func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *git.TreeEntry) {
|
||||||
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !git.IsErrNotExist(err) {
|
||||||
|
ctx.ServerError("GetBranchCommit", err)
|
||||||
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,6 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
{{if .RequireTribute}}
|
{{if .RequireTribute}}
|
||||||
<script src="{{AppSubUrl}}/vendor/plugins/tribute/tribute.min.js"></script>
|
<script src="{{AppSubUrl}}/vendor/plugins/tribute/tribute.min.js"></script>
|
||||||
|
|
||||||
{{if .Assignees}}
|
|
||||||
<script>
|
<script>
|
||||||
var issuesTribute = new Tribute({
|
var issuesTribute = new Tribute({
|
||||||
values: [
|
values: [
|
||||||
@@ -73,7 +71,6 @@
|
|||||||
})
|
})
|
||||||
issuesTribute.attach(document.getElementById('content'))
|
issuesTribute.attach(document.getElementById('content'))
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
|
||||||
<script>
|
<script>
|
||||||
var emojiTribute = new Tribute({
|
var emojiTribute = new Tribute({
|
||||||
collection: [{
|
collection: [{
|
||||||
|
|||||||
@@ -204,7 +204,7 @@
|
|||||||
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
|
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached active write tab segment">
|
<div class="ui bottom attached active write tab segment">
|
||||||
<textarea tabindex="1" id="content" name="content"></textarea>
|
<textarea tabindex="1" name="content"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached tab preview segment markdown">
|
<div class="ui bottom attached tab preview segment markdown">
|
||||||
{{$.i18n.Tr "loading"}}
|
{{$.i18n.Tr "loading"}}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
|
<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached active write tab segment">
|
<div class="ui bottom attached active write tab segment">
|
||||||
<textarea tabindex="1" id="content" name="content"></textarea>
|
<textarea tabindex="1" name="content"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached tab preview segment markdown">
|
<div class="ui bottom attached tab preview segment markdown">
|
||||||
{{$.i18n.Tr "loading"}}
|
{{$.i18n.Tr "loading"}}
|
||||||
|
|||||||
Reference in New Issue
Block a user