mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Refactor markup render system (#32533)
Remove unmaintainable sanitizer rules. No need to add special "class" regexp rules anymore, use RenderInternal.SafeAttr instead, more details (and examples) are in the tests
This commit is contained in:
		| @@ -9,14 +9,15 @@ import ( | ||||
| 	"io" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/git" | ||||
| 	"code.gitea.io/gitea/modules/gitrepo" | ||||
| 	"code.gitea.io/gitea/modules/markup/internal" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"github.com/yuin/goldmark/ast" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| ) | ||||
|  | ||||
| type RenderMetaMode string | ||||
| @@ -65,6 +66,8 @@ type RenderContext struct { | ||||
| 	SidebarTocNode   ast.Node | ||||
| 	RenderMetaAs     RenderMetaMode | ||||
| 	InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page | ||||
|  | ||||
| 	RenderInternal internal.RenderInternal | ||||
| } | ||||
|  | ||||
| // Cancel runs any cleanup functions that have been registered for this Ctx | ||||
| @@ -156,59 +159,53 @@ sandbox="allow-scripts" | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Writer) error { | ||||
| 	var wg sync.WaitGroup | ||||
| 	var err error | ||||
| func pipes() (io.ReadCloser, io.WriteCloser, func()) { | ||||
| 	pr, pw := io.Pipe() | ||||
| 	defer func() { | ||||
| 	return pr, pw, func() { | ||||
| 		_ = pr.Close() | ||||
| 		_ = pw.Close() | ||||
| 	}() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 	var pr2 io.ReadCloser | ||||
| 	var pw2 io.WriteCloser | ||||
| func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Writer) error { | ||||
| 	finalProcessor := ctx.RenderInternal.Init(output) | ||||
| 	defer finalProcessor.Close() | ||||
|  | ||||
| 	var sanitizerDisabled bool | ||||
| 	if r, ok := renderer.(ExternalRenderer); ok { | ||||
| 		sanitizerDisabled = r.SanitizerDisabled() | ||||
| 	// input -> (pw1=pr1) -> renderer -> (pw2=pr2) -> SanitizeReader -> finalProcessor -> output | ||||
| 	// no sanitizer: input -> (pw1=pr1) -> renderer -> pw2(finalProcessor) -> output | ||||
| 	pr1, pw1, close1 := pipes() | ||||
| 	defer close1() | ||||
|  | ||||
| 	eg, _ := errgroup.WithContext(ctx.Ctx) | ||||
| 	var pw2 io.WriteCloser = util.NopCloser{Writer: finalProcessor} | ||||
|  | ||||
| 	if r, ok := renderer.(ExternalRenderer); !ok || !r.SanitizerDisabled() { | ||||
| 		var pr2 io.ReadCloser | ||||
| 		var close2 func() | ||||
| 		pr2, pw2, close2 = pipes() | ||||
| 		defer close2() | ||||
| 		eg.Go(func() error { | ||||
| 			defer pr2.Close() | ||||
| 			return SanitizeReader(pr2, renderer.Name(), finalProcessor) | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	if !sanitizerDisabled { | ||||
| 		pr2, pw2 = io.Pipe() | ||||
| 		defer func() { | ||||
| 			_ = pr2.Close() | ||||
| 			_ = pw2.Close() | ||||
| 		}() | ||||
|  | ||||
| 		wg.Add(1) | ||||
| 		go func() { | ||||
| 			err = SanitizeReader(pr2, renderer.Name(), output) | ||||
| 			_ = pr2.Close() | ||||
| 			wg.Done() | ||||
| 		}() | ||||
| 	} else { | ||||
| 		pw2 = util.NopCloser{Writer: output} | ||||
| 	} | ||||
|  | ||||
| 	wg.Add(1) | ||||
| 	go func() { | ||||
| 	eg.Go(func() (err error) { | ||||
| 		if r, ok := renderer.(PostProcessRenderer); ok && r.NeedPostProcess() { | ||||
| 			err = PostProcess(ctx, pr, pw2) | ||||
| 			err = PostProcess(ctx, pr1, pw2) | ||||
| 		} else { | ||||
| 			_, err = io.Copy(pw2, pr) | ||||
| 			_, err = io.Copy(pw2, pr1) | ||||
| 		} | ||||
| 		_ = pr.Close() | ||||
| 		_ = pw2.Close() | ||||
| 		wg.Done() | ||||
| 	}() | ||||
| 		_, _ = pr1.Close(), pw2.Close() | ||||
| 		return err | ||||
| 	}) | ||||
|  | ||||
| 	if err1 := renderer.Render(ctx, input, pw); err1 != nil { | ||||
| 		return err1 | ||||
| 	if err := renderer.Render(ctx, input, pw1); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_ = pw.Close() | ||||
| 	_ = pw1.Close() | ||||
|  | ||||
| 	wg.Wait() | ||||
| 	return err | ||||
| 	return eg.Wait() | ||||
| } | ||||
|  | ||||
| // Init initializes the render global variables | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 wxiaoguang
					wxiaoguang