@@ -44,18 +44,17 @@ type Header struct {
4444
4545// RenderContext represents a render context
4646type RenderContext struct {
47- Ctx context.Context
48- RelativePath string // relative path from tree root of the branch
49- Type string
50- IsWiki bool
51- URLPrefix string
52- Metas map [string ]string
53- DefaultLink string
54- GitRepo * git.Repository
55- ShaExistCache map [string ]bool
56- cancelFn func ()
57- TableOfContents []Header
58- InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
47+ Ctx context.Context
48+ RelativePath string // relative path from tree root of the branch
49+ Type string
50+ IsWiki bool
51+ URLPrefix string
52+ Metas map [string ]string
53+ DefaultLink string
54+ GitRepo * git.Repository
55+ ShaExistCache map [string ]bool
56+ cancelFn func ()
57+ TableOfContents []Header
5958}
6059
6160// Cancel runs any cleanup functions that have been registered for this Ctx
@@ -106,6 +105,9 @@ type ExternalRenderer interface {
106105
107106 // DisplayInIFrame represents whether render the content with an iframe
108107 DisplayInIFrame () bool
108+
109+ // AllowSameOrigin represents whether render allow same origin
110+ AllowSameOrigin () bool
109111}
110112
111113// RendererContentDetector detects if the content can be rendered
@@ -152,14 +154,39 @@ func DetectRendererType(filename string, input io.Reader) string {
152154 return ""
153155}
154156
157+ // GetRenderer returned the renderer according type or relativepath
158+ func GetRenderer (tp , relativePath string ) (Renderer , error ) {
159+ if tp != "" {
160+ if renderer , ok := renderers [tp ]; ok {
161+ return renderer , nil
162+ }
163+ return nil , ErrUnsupportedRenderType {tp }
164+ }
165+
166+ if relativePath != "" {
167+ extension := strings .ToLower (filepath .Ext (relativePath ))
168+ if renderer , ok := extRenderers [extension ]; ok {
169+ return renderer , nil
170+ }
171+ return nil , ErrUnsupportedRenderExtension {extension }
172+ }
173+ return nil , errors .New ("Render options both filename and type missing" )
174+ }
175+
155176// Render renders markup file to HTML with all specific handling stuff.
156177func Render (ctx * RenderContext , input io.Reader , output io.Writer ) error {
157- if ctx .Type != "" {
158- return renderByType (ctx , input , output )
159- } else if ctx .RelativePath != "" {
160- return renderFile (ctx , input , output )
178+ renderer , err := GetRenderer (ctx .Type , ctx .RelativePath )
179+ if err != nil {
180+ return err
181+ }
182+
183+ if r , ok := renderer .(ExternalRenderer ); ok && (r .DisplayInIFrame () || r .AllowSameOrigin ()) {
184+ // for an external render, it could only output its content in a standalone page
185+ // otherwise, a <iframe> should be outputted to embed the external rendered page
186+ return renderIFrame (ctx , output , r .AllowSameOrigin ())
161187 }
162- return errors .New ("Render options both filename and type missing" )
188+
189+ return RenderDirect (ctx , renderer , input , output )
163190}
164191
165192// RenderString renders Markup string to HTML with all specific handling stuff and return string
@@ -177,7 +204,11 @@ type nopCloser struct {
177204
178205func (nopCloser ) Close () error { return nil }
179206
180- func renderIFrame (ctx * RenderContext , output io.Writer ) error {
207+ func renderIFrame (ctx * RenderContext , output io.Writer , allowSameOrigin bool ) error {
208+ var allowSameOriginStr string
209+ if allowSameOrigin {
210+ allowSameOriginStr = " allow-same-origin"
211+ }
181212 // set height="0" ahead, otherwise the scrollHeight would be max(150, realHeight)
182213 // at the moment, only "allow-scripts" is allowed for sandbox mode.
183214 // "allow-same-origin" should never be used, it leads to XSS attack, and it makes the JS in iframe can access parent window's config and CSRF token
@@ -187,18 +218,20 @@ func renderIFrame(ctx *RenderContext, output io.Writer) error {
187218name="giteaExternalRender"
188219onload="this.height=giteaExternalRender.document.documentElement.scrollHeight"
189220width="100%%" height="0" scrolling="no" frameborder="0" style="overflow: hidden"
190- sandbox="allow-scripts"
221+ sandbox="allow-scripts%s "
191222></iframe>` ,
192223 setting .AppSubURL ,
193224 url .PathEscape (ctx .Metas ["user" ]),
194225 url .PathEscape (ctx .Metas ["repo" ]),
195226 ctx .Metas ["BranchNameSubURL" ],
196227 url .PathEscape (ctx .RelativePath ),
228+ allowSameOriginStr ,
197229 ))
198230 return err
199231}
200232
201- func render (ctx * RenderContext , renderer Renderer , input io.Reader , output io.Writer ) error {
233+ // RenderDirect renders markup file to HTML with all specific handling stuff.
234+ func RenderDirect (ctx * RenderContext , renderer Renderer , input io.Reader , output io.Writer ) error {
202235 var wg sync.WaitGroup
203236 var err error
204237 pr , pw := io .Pipe ()
@@ -262,13 +295,6 @@ func (err ErrUnsupportedRenderType) Error() string {
262295 return fmt .Sprintf ("Unsupported render type: %s" , err .Type )
263296}
264297
265- func renderByType (ctx * RenderContext , input io.Reader , output io.Writer ) error {
266- if renderer , ok := renderers [ctx .Type ]; ok {
267- return render (ctx , renderer , input , output )
268- }
269- return ErrUnsupportedRenderType {ctx .Type }
270- }
271-
272298// ErrUnsupportedRenderExtension represents the error when extension doesn't supported to render
273299type ErrUnsupportedRenderExtension struct {
274300 Extension string
@@ -278,21 +304,6 @@ func (err ErrUnsupportedRenderExtension) Error() string {
278304 return fmt .Sprintf ("Unsupported render extension: %s" , err .Extension )
279305}
280306
281- func renderFile (ctx * RenderContext , input io.Reader , output io.Writer ) error {
282- extension := strings .ToLower (filepath .Ext (ctx .RelativePath ))
283- if renderer , ok := extRenderers [extension ]; ok {
284- if r , ok := renderer .(ExternalRenderer ); ok && r .DisplayInIFrame () {
285- if ! ctx .InStandalonePage {
286- // for an external render, it could only output its content in a standalone page
287- // otherwise, a <iframe> should be outputted to embed the external rendered page
288- return renderIFrame (ctx , output )
289- }
290- }
291- return render (ctx , renderer , input , output )
292- }
293- return ErrUnsupportedRenderExtension {extension }
294- }
295-
296307// Type returns if markup format via the filename
297308func Type (filename string ) string {
298309 if parser := GetRendererByFileName (filename ); parser != nil {
0 commit comments