code.gitea.io/gitea@v1.21.7/routers/web/repo/render.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"net/http"
    10  	"path"
    11  
    12  	"code.gitea.io/gitea/modules/charset"
    13  	"code.gitea.io/gitea/modules/context"
    14  	"code.gitea.io/gitea/modules/git"
    15  	"code.gitea.io/gitea/modules/markup"
    16  	"code.gitea.io/gitea/modules/typesniffer"
    17  	"code.gitea.io/gitea/modules/util"
    18  )
    19  
    20  // RenderFile renders a file by repos path
    21  func RenderFile(ctx *context.Context) {
    22  	blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
    23  	if err != nil {
    24  		if git.IsErrNotExist(err) {
    25  			ctx.NotFound("GetBlobByPath", err)
    26  		} else {
    27  			ctx.ServerError("GetBlobByPath", err)
    28  		}
    29  		return
    30  	}
    31  
    32  	dataRc, err := blob.DataAsync()
    33  	if err != nil {
    34  		ctx.ServerError("DataAsync", err)
    35  		return
    36  	}
    37  	defer dataRc.Close()
    38  
    39  	buf := make([]byte, 1024)
    40  	n, _ := util.ReadAtMost(dataRc, buf)
    41  	buf = buf[:n]
    42  
    43  	st := typesniffer.DetectContentType(buf)
    44  	isTextFile := st.IsText()
    45  
    46  	rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{})
    47  
    48  	if markupType := markup.Type(blob.Name()); markupType == "" {
    49  		if isTextFile {
    50  			_, err = io.Copy(ctx.Resp, rd)
    51  			if err != nil {
    52  				ctx.ServerError("Copy", err)
    53  			}
    54  			return
    55  		}
    56  		ctx.Error(http.StatusInternalServerError, "Unsupported file type render")
    57  		return
    58  	}
    59  
    60  	ctx.Resp.Header().Add("Content-Security-Policy", "frame-src 'self'; sandbox allow-scripts")
    61  	err = markup.Render(&markup.RenderContext{
    62  		Ctx:          ctx,
    63  		RelativePath: ctx.Repo.TreePath,
    64  		Links: markup.Links{
    65  			Base:       ctx.Repo.RepoLink,
    66  			BranchPath: ctx.Repo.BranchNameSubURL(),
    67  			TreePath:   path.Dir(ctx.Repo.TreePath),
    68  		},
    69  		Metas:            ctx.Repo.Repository.ComposeDocumentMetas(),
    70  		GitRepo:          ctx.Repo.GitRepo,
    71  		InStandalonePage: true,
    72  	}, rd, ctx.Resp)
    73  	if err != nil {
    74  		ctx.ServerError("Render", err)
    75  		return
    76  	}
    77  }