mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +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
 | 
			
		||||
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
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * 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)
 | 
			
		||||
		protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
 | 
			
		||||
		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() {
 | 
			
		||||
			// check and deletion
 | 
			
		||||
			if newCommitID == git.EmptySHA {
 | 
			
		||||
				fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// detect force push
 | 
			
		||||
			if git.EmptySHA != oldCommitID {
 | 
			
		||||
				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
 | 
			
		||||
			if newCommitID == git.EmptySHA {
 | 
			
		||||
				fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
 | 
			
		||||
			} else {
 | 
			
		||||
				userID, _ := strconv.ParseInt(userIDStr, 10, 64)
 | 
			
		||||
				canPush, err := private.CanUserPush(protectBranch.ID, userID)
 | 
			
		||||
				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), "")
 | 
			
		||||
				}
 | 
			
		||||
			userID, _ := strconv.ParseInt(userIDStr, 10, 64)
 | 
			
		||||
			canPush, err := private.CanUserPush(protectBranch.ID, userID)
 | 
			
		||||
			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),
 | 
			
		||||
		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{
 | 
			
		||||
		Addr:    listenAddr,
 | 
			
		||||
		Handler: m,
 | 
			
		||||
@@ -96,7 +102,10 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		http.Error(w, "Use HTTPS", http.StatusBadRequest)
 | 
			
		||||
		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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1838,6 +1838,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 | 
			
		||||
		&RepoRedirect{RedirectRepoID: repoID},
 | 
			
		||||
		&Webhook{RepoID: repoID},
 | 
			
		||||
		&HookTask{RepoID: repoID},
 | 
			
		||||
		&Notification{RepoID: repoID},
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return fmt.Errorf("deleteBeans: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -535,6 +535,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
 | 
			
		||||
	if err = sess.Commit(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	sess.Close()
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
// outside any session scope independently.
 | 
			
		||||
func RewriteAllPublicKeys() error {
 | 
			
		||||
	return rewriteAllPublicKeys(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rewriteAllPublicKeys(e Engine) error {
 | 
			
		||||
	//Don't rewrite key if internal server
 | 
			
		||||
	if setting.SSH.StartBuiltinServer {
 | 
			
		||||
		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())
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
 
 | 
			
		||||
@@ -1038,25 +1038,26 @@ func deleteUser(e *xorm.Session, u *User) error {
 | 
			
		||||
		&EmailAddress{UID: u.ID},
 | 
			
		||||
		&UserOpenID{UID: u.ID},
 | 
			
		||||
		&Reaction{UserID: u.ID},
 | 
			
		||||
		&TeamUser{UID: u.ID},
 | 
			
		||||
		&Collaboration{UserID: u.ID},
 | 
			
		||||
		&Stopwatch{UserID: u.ID},
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return fmt.Errorf("deleteBeans: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ***** START: PublicKey *****
 | 
			
		||||
	keys := make([]*PublicKey, 0, 10)
 | 
			
		||||
	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 {
 | 
			
		||||
	if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil {
 | 
			
		||||
		return fmt.Errorf("deletePublicKeys: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	rewriteAllPublicKeys(e)
 | 
			
		||||
	// ***** END: PublicKey *****
 | 
			
		||||
 | 
			
		||||
	// ***** START: GPGPublicKey *****
 | 
			
		||||
	if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil {
 | 
			
		||||
		return fmt.Errorf("deleteGPGKeys: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// ***** END: GPGPublicKey *****
 | 
			
		||||
 | 
			
		||||
	// Clear assignee.
 | 
			
		||||
	if err = clearAssigneeByUserID(e, u.ID); err != nil {
 | 
			
		||||
		return fmt.Errorf("clear assignee: %v", err)
 | 
			
		||||
@@ -1110,6 +1111,7 @@ func DeleteUser(u *User) (err error) {
 | 
			
		||||
	if err = sess.Commit(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	sess.Close()
 | 
			
		||||
 | 
			
		||||
	return RewriteAllPublicKeys()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ func InitIssueIndexer(populateIndexer func() error) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = createIssueIndexer(); err != nil {
 | 
			
		||||
	if err = createIssueIndexer(setting.Indexer.IssuePath, issueIndexerLatestVersion); err != nil {
 | 
			
		||||
		log.Fatal(4, "InitIssuesIndexer: create index, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
func createIssueIndexer() error {
 | 
			
		||||
func createIssueIndexer(path string, latestVersion int) error {
 | 
			
		||||
	mapping := bleve.NewIndexMapping()
 | 
			
		||||
	docMapping := bleve.NewDocumentMapping()
 | 
			
		||||
 | 
			
		||||
@@ -100,8 +100,14 @@ func createIssueIndexer() error {
 | 
			
		||||
	mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	issueIndexer, err = bleve.New(setting.Indexer.IssuePath, mapping)
 | 
			
		||||
	return err
 | 
			
		||||
	issueIndexer, err = bleve.New(path, mapping)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
 | 
			
		||||
		Version: latestVersion,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IssueIndexerBatch batch to add updates to
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ func InitRepoIndexer(populateIndexer func() error) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = createRepoIndexer(); err != nil {
 | 
			
		||||
	if err = createRepoIndexer(setting.Indexer.RepoPath, repoIndexerLatestVersion); err != nil {
 | 
			
		||||
		log.Fatal(4, "CreateRepoIndexer: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
func createRepoIndexer() error {
 | 
			
		||||
func createRepoIndexer(path string, latestVersion int) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	docMapping := bleve.NewDocumentMapping()
 | 
			
		||||
	numericFieldMapping := bleve.NewNumericFieldMapping()
 | 
			
		||||
@@ -119,8 +119,13 @@ func createRepoIndexer() error {
 | 
			
		||||
	mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
 | 
			
		||||
	mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
 | 
			
		||||
 | 
			
		||||
	repoIndexer, err = bleve.New(setting.Indexer.RepoPath, mapping)
 | 
			
		||||
	return err
 | 
			
		||||
	repoIndexer, err = bleve.New(path, mapping)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
 | 
			
		||||
		Version: latestVersion,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func filenameIndexerID(repoID int64, filename string) string {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
function htmlEncode(text) {
 | 
			
		||||
   return jQuery('<div />').text(text).html()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var csrf;
 | 
			
		||||
var suburl;
 | 
			
		||||
 | 
			
		||||
@@ -312,12 +316,12 @@ function initCommentForm() {
 | 
			
		||||
            switch (input_id) {
 | 
			
		||||
                case '#milestone_id':
 | 
			
		||||
                    $list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
 | 
			
		||||
                        $(this).text() + '</a>');
 | 
			
		||||
                        htmlEncode($(this).text()) + '</a>');
 | 
			
		||||
                    break;
 | 
			
		||||
                case '#assignee_id':
 | 
			
		||||
                    $list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
 | 
			
		||||
                        '<img class="ui avatar image" src=' + $(this).data('avatar') + '>' +
 | 
			
		||||
                        $(this).text() + '</a>');
 | 
			
		||||
                        htmlEncode($(this).text()) + '</a>');
 | 
			
		||||
            }
 | 
			
		||||
            $('.ui' + select_id + '.list .no-select').addClass('hide');
 | 
			
		||||
            $(input_id).val($(this).data('id'));
 | 
			
		||||
@@ -604,7 +608,7 @@ function initRepository() {
 | 
			
		||||
            // Setup new form
 | 
			
		||||
            if ($editContentZone.html().length == 0) {
 | 
			
		||||
                $editContentZone.html($('#edit-content-form').html());
 | 
			
		||||
                $textarea = $('#content');
 | 
			
		||||
                $textarea = $editContentZone.find('textarea');
 | 
			
		||||
                issuesTribute.attach($textarea.get());
 | 
			
		||||
                emojiTribute.attach($textarea.get());
 | 
			
		||||
 | 
			
		||||
@@ -1456,7 +1460,7 @@ function searchUsers() {
 | 
			
		||||
                $.each(response.data, function (i, item) {
 | 
			
		||||
                    var title = item.login;
 | 
			
		||||
                    if (item.full_name && item.full_name.length > 0) {
 | 
			
		||||
                        title += ' (' + item.full_name + ')';
 | 
			
		||||
                        title += ' (' + htmlEncode(item.full_name) + ')';
 | 
			
		||||
                    }
 | 
			
		||||
                    items.push({
 | 
			
		||||
                        title: title,
 | 
			
		||||
@@ -2510,7 +2514,7 @@ function initTopicbar() {
 | 
			
		||||
                if (res.topics) {
 | 
			
		||||
                    formattedResponse.success = true;
 | 
			
		||||
                    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
 | 
			
		||||
                    $.each(response, function(index, issue) {
 | 
			
		||||
                        filteredResponse.results.push({
 | 
			
		||||
                            'name'  : '#' + issue.number + ' ' + issue.title,
 | 
			
		||||
                            'name'  : '#' + issue.number + ' ' + htmlEncode(issue.title),
 | 
			
		||||
                            'value' : issue.id
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
 
 | 
			
		||||
@@ -163,7 +163,11 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
 | 
			
		||||
		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)
 | 
			
		||||
 | 
			
		||||
	ctx.Data["TreePath"] = form.TreePath
 | 
			
		||||
@@ -373,6 +377,13 @@ func DeleteFile(ctx *context.Context) {
 | 
			
		||||
func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
 | 
			
		||||
	ctx.Data["PageIsDelete"] = true
 | 
			
		||||
	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
 | 
			
		||||
	canCommit := renderCommitRights(ctx)
 | 
			
		||||
 | 
			
		||||
@@ -477,7 +488,12 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
 | 
			
		||||
		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)
 | 
			
		||||
	if len(treeNames) == 0 {
 | 
			
		||||
		// 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
func UploadFileToServer(ctx *context.Context) {
 | 
			
		||||
	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 {
 | 
			
		||||
		ctx.Error(500, fmt.Sprintf("NewUpload: %v", err))
 | 
			
		||||
		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")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetBranchCommit", err)
 | 
			
		||||
		return wikiRepo, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	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) {
 | 
			
		||||
	wikiRepo, commit, err := findWikiRepoCommit(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if !git.IsErrNotExist(err) {
 | 
			
		||||
			ctx.ServerError("GetBranchCommit", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,6 @@
 | 
			
		||||
{{end}}
 | 
			
		||||
{{if .RequireTribute}}
 | 
			
		||||
	<script src="{{AppSubUrl}}/vendor/plugins/tribute/tribute.min.js"></script>
 | 
			
		||||
 | 
			
		||||
	{{if .Assignees}}
 | 
			
		||||
	<script>
 | 
			
		||||
		var issuesTribute = new Tribute({
 | 
			
		||||
			values: [
 | 
			
		||||
@@ -73,7 +71,6 @@
 | 
			
		||||
		})
 | 
			
		||||
		issuesTribute.attach(document.getElementById('content'))
 | 
			
		||||
	</script>
 | 
			
		||||
	{{end}}
 | 
			
		||||
	<script>
 | 
			
		||||
		var emojiTribute = new Tribute({
 | 
			
		||||
			collection: [{
 | 
			
		||||
 
 | 
			
		||||
@@ -204,7 +204,7 @@
 | 
			
		||||
				<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
 | 
			
		||||
			</div>
 | 
			
		||||
			<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 class="ui bottom attached tab preview segment markdown">
 | 
			
		||||
			{{$.i18n.Tr "loading"}}
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@
 | 
			
		||||
			<a class="preview item" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a>
 | 
			
		||||
		</div>
 | 
			
		||||
		<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 class="ui bottom attached tab preview segment markdown">
 | 
			
		||||
			{{$.i18n.Tr "loading"}}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user