Bladeren bron

[GINR] file view and raw download with captcha

cgars 8 jaren geleden
bovenliggende
commit
0879535176

+ 1 - 1
cmd/web.go

@@ -320,7 +320,7 @@ func runWeb(c *cli.Context) error {
 			c.Header().Set("Cache-Control", "public,max-age=86400")
 			fmt.Println("attach.Name:", attach.Name)
 			c.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
-			if err = repo.ServeData(c, attach.Name, fr); err != nil {
+			if err = repo.ServeData(c, attach.Name, fr, nil); err != nil {
 				c.Handle(500, "ServeData", err)
 				return
 			}

+ 5 - 0
conf/app.ini

@@ -98,6 +98,11 @@ ENABLE_LOCAL_PATH_MIGRATION = false
 COMMITS_FETCH_CONCURRENCY = 0
 ; Enable render mode for raw file
 ENABLE_RAW_FILE_RENDER_MODE = false
+; File size from which on raw view is protected by captures
+RAW_CAPTCHA_MIN_FILE_SIZE = 50
+; File size from which on repo file view is protected by captures
+CAPTCHA_MIN_FILE_SIZE = 5
+
 
 [repository.editor]
 ; List of file extensions that should have line wraps in the CodeMirror editor.

+ 2 - 0
conf/locale/locale_en-GB.ini

@@ -466,8 +466,10 @@ commits=Commits
 git_branches=Branches
 releases=Releases
 file_raw=Raw
+file_dl=Download
 file_history=History
 file_view_raw=View Raw
+file_view_dl= Download
 file_permalink=Permalink
 file_too_large=This file is too large to be shown
 video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.

+ 2 - 0
conf/locale/locale_en-US.ini

@@ -466,8 +466,10 @@ commits = Commits
 git_branches = Branches
 releases = Releases
 file_raw = Raw
+file_dl=Download
 file_history = History
 file_view_raw = View Raw
+file_view_dl = Download
 file_permalink = Permalink
 file_too_large = This file is too large to be shown
 video_not_supported_in_browser = Your browser doesn't support HTML5 video tag.

+ 2 - 0
pkg/setting/setting.go

@@ -125,6 +125,8 @@ var (
 		EnableLocalPathMigration bool
 		CommitsFetchConcurrency  int
 		EnableRawFileRenderMode  bool
+		RawCaptchaMinFileSize    int64
+		CaptchaMinFileSize       int64
 
 		// Repository editor settings
 		Editor struct {

+ 1 - 13
routes/api/v1/repo/file.go

@@ -23,19 +23,7 @@ func GetRawFile(c *context.APIContext) {
 		c.Status(404)
 		return
 	}
-
-	blob, err := c.Repo.Commit.GetBlobByPath(c.Repo.TreePath)
-	if err != nil {
-		if git.IsErrNotExist(err) {
-			c.Status(404)
-		} else {
-			c.Error(500, "GetBlobByPath", err)
-		}
-		return
-	}
-	if err = repo.ServeBlob(c.Context, blob); err != nil {
-		c.Error(500, "ServeBlob", err)
-	}
+	return
 }
 
 // https://github.com/gogits/go-gogs-client/wiki/Repositories-Contents#download-archive

+ 18 - 5
routes/repo/download.go

@@ -16,9 +16,10 @@ import (
 	"github.com/G-Node/gogs/pkg/setting"
 	"github.com/G-Node/gogs/pkg/tool"
 	"os"
+	"github.com/go-macaron/captcha"
 )
 
-func ServeData(c *context.Context, name string, reader io.Reader) error {
+func ServeData(c *context.Context, name string, reader io.Reader, cpt *captcha.Captcha) error {
 	buf := make([]byte, 1024)
 	n, _ := reader.Read(buf)
 	if n >= 0 {
@@ -31,8 +32,14 @@ func ServeData(c *context.Context, name string, reader io.Reader) error {
 		af, err := gannex.NewAFile(c.Repo.Repository.RepoPath(), "annex", name, buf)
 		if err != nil {
 
+		}
+		if af.Info.Size() > gannex.MEGABYTE*setting.Repository.RawCaptchaMinFileSize && !cpt.VerifyReq(c.Req) {
+			c.Data["EnableCaptcha"] = true
+			c.HTML(200, "repo/download")
+			return nil
 		}
 		afp, err = af.Open()
+		defer afp.Close()
 		if err != nil {
 
 		}
@@ -57,16 +64,22 @@ func ServeData(c *context.Context, name string, reader io.Reader) error {
 	return err
 }
 
-func ServeBlob(c *context.Context, blob *git.Blob) error {
+func ServeBlob(c *context.Context, blob *git.Blob, cpt *captcha.Captcha) error {
 	r, w := io.Pipe()
 	defer r.Close()
 	defer w.Close()
 	go blob.DataPipeline(w, w)
-	return ServeData(c, path.Base(c.Repo.TreePath), io.LimitReader(r, blob.Size()))
+	return ServeData(c, path.Base(c.Repo.TreePath), io.LimitReader(r, blob.Size()), cpt)
 }
 
-func SingleDownload(c *context.Context) {
+func SingleDownload(c *context.Context, cpt *captcha.Captcha) {
 	blob, err := c.Repo.Commit.GetBlobByPath(c.Repo.TreePath)
+	if blob.Size() > gannex.MEGABYTE*setting.Repository.RawCaptchaMinFileSize && setting.Service.EnableCaptcha &&
+		!cpt.VerifyReq(c.Req) {
+		c.Data["EnableCaptcha"] = true
+		c.HTML(200, "repo/download")
+		return
+	}
 	if err != nil {
 		if git.IsErrNotExist(err) {
 			c.Handle(404, "GetBlobByPath", nil)
@@ -75,7 +88,7 @@ func SingleDownload(c *context.Context) {
 		}
 		return
 	}
-	if err = ServeBlob(c, blob); err != nil {
+	if err = ServeBlob(c, blob, cpt); err != nil {
 		c.Handle(500, "ServeBlob", err)
 	}
 }

+ 20 - 11
routes/repo/view.go

@@ -28,6 +28,7 @@ import (
 	"github.com/G-Node/gogs/pkg/tool"
 	"io"
 	"os"
+	"github.com/go-macaron/captcha"
 )
 
 const (
@@ -129,18 +130,20 @@ func renderDirectory(c *context.Context, treeLink string) {
 	}
 }
 
-func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink string) {
+func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink string, cpt *captcha.Captcha) {
 	c.Data["IsViewFile"] = true
 	blob := entry.Blob()
 	log.Trace("Blob size is %s", blob.Size())
+	if blob.Size() > gannex.MEGABYTE*10 && setting.Service.EnableCaptcha && !cpt.VerifyReq(c.Req) {
+		c.Data["EnableCaptcha"] = true
+		c.HTML(200, "repo/download")
+		return
+	}
 	c.Data["FileSize"] = blob.Size()
 	c.Data["FileName"] = blob.Name()
 	c.Data["HighlightClass"] = highlight.FileNameToHighlightClass(blob.Name())
 	c.Data["RawFileLink"] = rawLink + "/" + c.Repo.TreePath
-	if blob.Size() > 1024*1024*100 {
-		c.Data["IsFileTooLarge"] = true
-		return
-	}
+
 	r, w := io.Pipe()
 	defer r.Close()
 	defer w.Close()
@@ -162,6 +165,12 @@ func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink stri
 			log.Trace("Could not get annex file: %v", err)
 			return
 		}
+		if af.Info.Size() > gannex.MEGABYTE*setting.Repository.CaptchaMinFileSize && setting.Service.EnableCaptcha &&
+			!cpt.VerifyReq(c.Req) {
+			c.Data["EnableCaptcha"] = true
+			c.HTML(200, "repo/download")
+			return
+		}
 		afp, err = af.Open()
 		defer afp.Close()
 		if err != nil {
@@ -252,13 +261,13 @@ func renderFile(c *context.Context, entry *git.TreeEntry, treeLink, rawLink stri
 			c.Data["EditFileTooltip"] = c.Tr("repo.editor.fork_before_edit")
 		}
 
-	case tool.IsPDFFile(buf):
+	case tool.IsPDFFile(buf) && (c.Data["FileSize"].(int64) < setting.Repository.RawCaptchaMinFileSize*gannex.MEGABYTE):
 		c.Data["IsPDFFile"] = true
-	case tool.IsVideoFile(buf):
+	case tool.IsVideoFile(buf) && (c.Data["FileSize"].(int64) < setting.Repository.RawCaptchaMinFileSize*gannex.MEGABYTE):
 		c.Data["IsVideoFile"] = true
-	case tool.IsImageFile(buf):
+	case tool.IsImageFile(buf) && (c.Data["FileSize"].(int64) < setting.Repository.RawCaptchaMinFileSize*gannex.MEGABYTE):
 		c.Data["IsImageFile"] = true
-	case tool.IsAnnexedFile(buf):
+	case tool.IsAnnexedFile(buf) && (c.Data["FileSize"].(int64) < setting.Repository.RawCaptchaMinFileSize*gannex.MEGABYTE):
 		c.Data["IsAnnexedFile"] = true
 	}
 
@@ -285,7 +294,7 @@ func setEditorconfigIfExists(c *context.Context) {
 	c.Data["Editorconfig"] = ec
 }
 
-func Home(c *context.Context) {
+func Home(c *context.Context, cpt *captcha.Captcha) {
 	c.Data["PageIsViewFiles"] = true
 
 	if c.Repo.Repository.IsBare {
@@ -334,7 +343,7 @@ func Home(c *context.Context) {
 	if entry.IsDir() {
 		renderDirectory(c, treeLink)
 	} else {
-		renderFile(c, entry, treeLink, rawLink)
+		renderFile(c, entry, treeLink, rawLink, cpt)
 	}
 	if c.Written() {
 		return

+ 31 - 0
templates/repo/download.tmpl

@@ -0,0 +1,31 @@
+{{template "base/head" .}}
+<div class="user signup">
+	<div class="ui middle very relaxed page grid">
+		<div class="column">
+			<form class="ui form" action="{{.Link}}" method="get">
+				{{.CSRFTokenHTML}}
+				<h3 class="ui top attached header">
+					Solve captcha to proceed
+				</h3>
+				<div class="ui attached segment">
+					{{template "base/alert" .}}
+					{{if .EnableCaptcha}}
+					<div class="inline field">
+						<label></label>
+						{{.Captcha.CreateHtml}}
+					</div>
+					<div class="required inline field {{if .Err_Captcha}}error{{end}}">
+						<label for="captcha">{{.i18n.Tr "captcha"}}</label>
+						<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
+					</div>
+					{{end}}
+					<div class="inline field">
+						<label></label>
+						<button class="ui button">Proceed</button>
+					</div>
+				</div>
+			</form>
+		</div>
+	</div>
+</div>
+	{{template "base/footer" .}}

+ 2 - 2
templates/repo/view_file.tmpl

@@ -18,7 +18,7 @@
 						<a class="ui button" href="{{.RepoLink}}/src/{{.CommitID}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_permalink"}}</a>
 					{{end}}
 					<a class="ui button" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_history"}}</a>
-					<a class="ui button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
+					<a class="ui button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_dl"}}</a>
 				</div>
 				{{if .Repository.CanEnableEditor}}
 					{{if .CanEditFile}}
@@ -100,7 +100,7 @@ git annex get {{.TreePath}}
 					{{else if .IsPDFFile}}
 						<iframe width="100%" height="600px" src="{{AppSubURL}}/plugins/pdfjs-1.4.20/web/viewer.html?file={{EscapePound $.RawFileLink}}"></iframe>
 					{{else}}
-						<a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
+						<a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_dl"}}</a>
 					{{end}}
 				</div>
 			{{else if .FileSize}}