Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2181,8 +2181,11 @@ PATH =
;RENDER_COMMAND = "asciidoc --out-file=- -"
;; Don't pass the file on STDIN, pass the filename as argument instead.
;IS_INPUT_FILE = false
; Don't filter html tags and attributes if true
;; Don't filter html tags and attributes if true
;DISABLE_SANITIZER = false
;; Display the HTML with an embed iframe instead of rendering inside the page. When a renderer uses iframe
;; it suppresses DISABLE_SANITIZER option and there will be no sanitizer.
;USE_IFRAME=false

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
2 changes: 1 addition & 1 deletion docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ IS_INPUT_FILE = false
- RENDER\_COMMAND: External command to render all matching extensions.
- IS\_INPUT\_FILE: **false** Input is not a standard input but a file param followed `RENDER_COMMAND`.
- DISABLE_SANITIZER: **false** Don't filter html tags and attributes if true. This is insecure. Don't change this to true except you know what that means.
- USE_IFRAME: **false** Display the HTML with an embed iframe but not directly renderer.
- USE_IFRAME: **false** Display the HTML with an embed iframe instead of rendering inside the page. When a renderer uses iframe, it suppresses DISABLE_SANITIZER option and there will be no sanitizer.

Two special environment variables are passed to the render command:
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
Expand Down
4 changes: 1 addition & 3 deletions modules/markup/console/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ func init() {
}

// Renderer implements markup.Renderer
type Renderer struct {
markup.BaseRenderer
}
type Renderer struct{}

// Name implements markup.Renderer
func (Renderer) Name() string {
Expand Down
4 changes: 1 addition & 3 deletions modules/markup/csv/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ func init() {
}

// Renderer implements markup.Renderer for csv files
type Renderer struct {
markup.BaseRenderer
}
type Renderer struct{}

// Name implements markup.Renderer
func (Renderer) Name() string {
Expand Down
3 changes: 3 additions & 0 deletions modules/markup/external/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Renderer struct {
*setting.MarkupRenderer
}

var _ markup.PostProcessRenderer = (*Renderer)(nil)
var _ markup.ExternalRenderer = (*Renderer)(nil)

// Name returns the external tool name
func (p *Renderer) Name() string {
return p.MarkupName
Expand Down
8 changes: 4 additions & 4 deletions modules/markup/markdown/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,16 @@ func init() {
}

// Renderer implements markup.Renderer
type Renderer struct {
markup.BaseRenderer
}
type Renderer struct{}

var _ markup.PostProcessRenderer = (*Renderer)(nil)

// Name implements markup.Renderer
func (Renderer) Name() string {
return MarkupName
}

// NeedPostProcess implements markup.Renderer
// NeedPostProcess implements markup.PostProcessRenderer
func (Renderer) NeedPostProcess() bool { return true }

// Extensions implements markup.Renderer
Expand Down
8 changes: 4 additions & 4 deletions modules/markup/orgmode/orgmode.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ func init() {
}

// Renderer implements markup.Renderer for orgmode
type Renderer struct {
markup.BaseRenderer
}
type Renderer struct{}

var _ markup.PostProcessRenderer = (*Renderer)(nil)

// Name implements markup.Renderer
func (Renderer) Name() string {
return "orgmode"
}

// NeedPostProcess implements markup.Renderer
// NeedPostProcess implements markup.PostProcessRenderer
func (Renderer) NeedPostProcess() bool { return true }

// Extensions implements markup.Renderer
Expand Down
75 changes: 44 additions & 31 deletions modules/markup/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ type Header struct {

// RenderContext represents a render context
type RenderContext struct {
Ctx context.Context
RelativePath string // relative path from tree root of the branch
Type string
IsWiki bool
URLPrefix string
Metas map[string]string
DefaultLink string
GitRepo *git.Repository
ShaExistCache map[string]bool
cancelFn func()
TableOfContents []Header
AllowIFrame bool
Ctx context.Context
RelativePath string // relative path from tree root of the branch
Type string
IsWiki bool
URLPrefix string
Metas map[string]string
DefaultLink string
GitRepo *git.Repository
ShaExistCache map[string]bool
cancelFn func()
TableOfContents []Header
InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
}

// Cancel runs any cleanup functions that have been registered for this Ctx
Expand Down Expand Up @@ -90,23 +90,23 @@ func (ctx *RenderContext) AddCancel(fn func()) {
type Renderer interface {
Name() string // markup format name
Extensions() []string
NeedPostProcess() bool
SanitizerRules() []setting.MarkupSanitizerRule
SanitizerDisabled() bool
DisplayInIFrame() bool
Render(ctx *RenderContext, input io.Reader, output io.Writer) error
}

type BaseRenderer struct{}

// NeedPostProcess implements markup.Renderer
func (BaseRenderer) NeedPostProcess() bool { return false }
// PostProcessRenderer defines an interface for renderers who need post process
type PostProcessRenderer interface {
NeedPostProcess() bool
}

// SanitizerDisabled disabled sanitize if return true
func (BaseRenderer) SanitizerDisabled() bool { return false }
// PostProcessRenderer defines an interface for external renderers
type ExternalRenderer interface {
// SanitizerDisabled disabled sanitize if return true
SanitizerDisabled() bool

// DisplayInIFrame represents whether render the content with an iframe
func (BaseRenderer) DisplayInIFrame() bool { return false }
// DisplayInIFrame represents whether render the content with an iframe
DisplayInIFrame() bool
}

// RendererContentDetector detects if the content can be rendered
// by specified renderer
Expand Down Expand Up @@ -177,10 +177,14 @@ type nopCloser struct {

func (nopCloser) Close() error { return nil }

func renderIFrame(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Writer) error {
_, err := io.WriteString(output, fmt.Sprintf(`<iframe src="%s%s/%s/render/%s/%s" name="ifd"
onload="this.height=ifd.document.body.scrollHeight" width="100%%" scrolling="no" frameborder="0" style="overflow: hidden"
sandbox="allow-same-origin allow-scripts"></iframe>`,
func renderIFrame(ctx *RenderContext, output io.Writer) error {
_, err := io.WriteString(output, fmt.Sprintf(`
<iframe src="%s%s/%s/render/%s/%s"
name="giteaExternalRender"
onload="this.height=giteaExternalRender.document.body.scrollHeight"
width="100%%" scrolling="no" frameborder="0" style="overflow: hidden"
sandbox="allow-same-origin allow-scripts"
></iframe>`,
setting.AppSubURL,
url.PathEscape(ctx.Metas["user"]),
url.PathEscape(ctx.Metas["repo"]),
Expand All @@ -202,7 +206,12 @@ func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Wr
var pr2 io.ReadCloser
var pw2 io.WriteCloser

if !renderer.SanitizerDisabled() {
var sanitizerDisabled bool
if r, ok := renderer.(ExternalRenderer); ok {
sanitizerDisabled = r.SanitizerDisabled()
}

if !sanitizerDisabled {
pr2, pw2 = io.Pipe()
defer func() {
_ = pr2.Close()
Expand All @@ -221,7 +230,7 @@ func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Wr

wg.Add(1)
go func() {
if renderer.NeedPostProcess() {
if r, ok := renderer.(PostProcessRenderer); ok && r.NeedPostProcess() {
err = PostProcess(ctx, pr, pw2)
} else {
_, err = io.Copy(pw2, pr)
Expand Down Expand Up @@ -268,8 +277,12 @@ func (err ErrUnsupportedRenderExtension) Error() string {
func renderFile(ctx *RenderContext, input io.Reader, output io.Writer) error {
extension := strings.ToLower(filepath.Ext(ctx.RelativePath))
if renderer, ok := extRenderers[extension]; ok {
if renderer.DisplayInIFrame() && ctx.AllowIFrame {
return renderIFrame(ctx, renderer, input, output)
if r, ok := renderer.(ExternalRenderer); ok && r.DisplayInIFrame() {
if !ctx.InStandalonePage {
// for an external render, it could only output its content in a standalone page
// otherwise, a <iframe> should be outputted to embed the external rendered page
return renderIFrame(ctx, output)
}
}
return render(ctx, renderer, input, output)
}
Expand Down
11 changes: 6 additions & 5 deletions routers/web/repo/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ func RenderFile(ctx *context.Context) {
}

err = markup.Render(&markup.RenderContext{
Ctx: ctx,
RelativePath: ctx.Repo.TreePath,
URLPrefix: path.Dir(treeLink),
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
GitRepo: ctx.Repo.GitRepo,
Ctx: ctx,
RelativePath: ctx.Repo.TreePath,
URLPrefix: path.Dir(treeLink),
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
GitRepo: ctx.Repo.GitRepo,
InStandalonePage: true,
}, rd, ctx.Resp)
if err != nil {
ctx.ServerError("Render", err)
Expand Down
1 change: 0 additions & 1 deletion routers/web/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
URLPrefix: path.Dir(treeLink),
Metas: metas,
GitRepo: ctx.Repo.GitRepo,
AllowIFrame: true, // allow possible iframe from UI
}, rd, &result)
if err != nil {
ctx.ServerError("Render", err)
Expand Down