mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	Some old code use direct type-casting to get context, it causes problems. This PR fixes all legacy problems and use correct `ctx.Value` to get low-level contexts. Fix #33518
		
			
				
	
	
		
			120 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2024 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package markup
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"html/template"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"code.gitea.io/gitea/models/perm/access"
 | 
						|
	"code.gitea.io/gitea/models/repo"
 | 
						|
	"code.gitea.io/gitea/models/unit"
 | 
						|
	"code.gitea.io/gitea/modules/charset"
 | 
						|
	"code.gitea.io/gitea/modules/gitrepo"
 | 
						|
	"code.gitea.io/gitea/modules/indexer/code"
 | 
						|
	"code.gitea.io/gitea/modules/markup"
 | 
						|
	"code.gitea.io/gitea/modules/setting"
 | 
						|
	"code.gitea.io/gitea/modules/util"
 | 
						|
	gitea_context "code.gitea.io/gitea/services/context"
 | 
						|
	"code.gitea.io/gitea/services/repository/files"
 | 
						|
)
 | 
						|
 | 
						|
func renderRepoFileCodePreview(ctx context.Context, opts markup.RenderCodePreviewOptions) (template.HTML, error) {
 | 
						|
	opts.LineStop = max(opts.LineStop, opts.LineStart)
 | 
						|
	lineCount := opts.LineStop - opts.LineStart + 1
 | 
						|
	if lineCount <= 0 || lineCount > 140 /* GitHub at most show 140 lines */ {
 | 
						|
		lineCount = 10
 | 
						|
		opts.LineStop = opts.LineStart + lineCount
 | 
						|
	}
 | 
						|
 | 
						|
	dbRepo, err := repo.GetRepositoryByOwnerAndName(ctx, opts.OwnerName, opts.RepoName)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	webCtx := gitea_context.GetWebContext(ctx)
 | 
						|
	if webCtx == nil {
 | 
						|
		return "", fmt.Errorf("context is not a web context")
 | 
						|
	}
 | 
						|
	doer := webCtx.Doer
 | 
						|
 | 
						|
	perms, err := access.GetUserRepoPermission(ctx, dbRepo, doer)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	if !perms.CanRead(unit.TypeCode) {
 | 
						|
		return "", util.ErrPermissionDenied
 | 
						|
	}
 | 
						|
 | 
						|
	gitRepo, err := gitrepo.OpenRepository(ctx, dbRepo)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	defer gitRepo.Close()
 | 
						|
 | 
						|
	commit, err := gitRepo.GetCommit(opts.CommitID)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	language, _ := files.TryGetContentLanguage(gitRepo, opts.CommitID, opts.FilePath)
 | 
						|
	blob, err := commit.GetBlobByPath(opts.FilePath)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	if blob.Size() > setting.UI.MaxDisplayFileSize {
 | 
						|
		return "", fmt.Errorf("file is too large")
 | 
						|
	}
 | 
						|
 | 
						|
	dataRc, err := blob.DataAsync()
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	defer dataRc.Close()
 | 
						|
 | 
						|
	reader := bufio.NewReader(dataRc)
 | 
						|
	for i := 1; i < opts.LineStart; i++ {
 | 
						|
		if _, err = reader.ReadBytes('\n'); err != nil {
 | 
						|
			return "", err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	lineNums := make([]int, 0, lineCount)
 | 
						|
	lineCodes := make([]string, 0, lineCount)
 | 
						|
	for i := opts.LineStart; i <= opts.LineStop; i++ {
 | 
						|
		line, err := reader.ReadString('\n')
 | 
						|
		if err != nil && line == "" {
 | 
						|
			break
 | 
						|
		}
 | 
						|
 | 
						|
		lineNums = append(lineNums, i)
 | 
						|
		lineCodes = append(lineCodes, line)
 | 
						|
	}
 | 
						|
	realLineStop := max(opts.LineStart, opts.LineStart+len(lineNums)-1)
 | 
						|
	highlightLines := code.HighlightSearchResultCode(opts.FilePath, language, lineNums, strings.Join(lineCodes, ""))
 | 
						|
 | 
						|
	escapeStatus := &charset.EscapeStatus{}
 | 
						|
	lineEscapeStatus := make([]*charset.EscapeStatus, len(highlightLines))
 | 
						|
	for i, hl := range highlightLines {
 | 
						|
		lineEscapeStatus[i], hl.FormattedContent = charset.EscapeControlHTML(hl.FormattedContent, webCtx.Base.Locale, charset.RuneNBSP)
 | 
						|
		escapeStatus = escapeStatus.Or(lineEscapeStatus[i])
 | 
						|
	}
 | 
						|
 | 
						|
	return webCtx.RenderToHTML("base/markup_codepreview", map[string]any{
 | 
						|
		"FullURL":          opts.FullURL,
 | 
						|
		"FilePath":         opts.FilePath,
 | 
						|
		"LineStart":        opts.LineStart,
 | 
						|
		"LineStop":         realLineStop,
 | 
						|
		"RepoLink":         dbRepo.Link(),
 | 
						|
		"CommitID":         opts.CommitID,
 | 
						|
		"HighlightLines":   highlightLines,
 | 
						|
		"EscapeStatus":     escapeStatus,
 | 
						|
		"LineEscapeStatus": lineEscapeStatus,
 | 
						|
	})
 | 
						|
}
 |