@@ -10,8 +10,10 @@ import ( | |||
"encoding/base64" | |||
"fmt" | |||
"html/template" | |||
"io" | |||
"net/http" | |||
"net/url" | |||
"path/filepath" | |||
"strconv" | |||
"strings" | |||
"time" | |||
@@ -62,7 +64,7 @@ type Context struct { | |||
HTTPS string | |||
Git string | |||
} | |||
*models.Mirror | |||
Mirror *models.Mirror | |||
} | |||
} | |||
@@ -243,6 +245,41 @@ func (ctx *Context) CsrfTokenValid() bool { | |||
return true | |||
} | |||
func (ctx *Context) ServeFile(file string, names ...string) { | |||
var name string | |||
if len(names) > 0 { | |||
name = names[0] | |||
} else { | |||
name = filepath.Base(file) | |||
} | |||
ctx.Res.Header().Set("Content-Description", "File Transfer") | |||
ctx.Res.Header().Set("Content-Type", "application/octet-stream") | |||
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+name) | |||
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary") | |||
ctx.Res.Header().Set("Expires", "0") | |||
ctx.Res.Header().Set("Cache-Control", "must-revalidate") | |||
ctx.Res.Header().Set("Pragma", "public") | |||
http.ServeFile(ctx.Res, ctx.Req, file) | |||
} | |||
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) { | |||
modtime := time.Now() | |||
for _, p := range params { | |||
switch v := p.(type) { | |||
case time.Time: | |||
modtime = v | |||
} | |||
} | |||
ctx.Res.Header().Set("Content-Description", "File Transfer") | |||
ctx.Res.Header().Set("Content-Type", "application/octet-stream") | |||
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+name) | |||
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary") | |||
ctx.Res.Header().Set("Expires", "0") | |||
ctx.Res.Header().Set("Cache-Control", "must-revalidate") | |||
ctx.Res.Header().Set("Pragma", "public") | |||
http.ServeContent(ctx.Res, ctx.Req, name, modtime, r) | |||
} | |||
type Flash struct { | |||
url.Values | |||
ErrorMsg, SuccessMsg string |
@@ -0,0 +1,68 @@ | |||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package repo | |||
import ( | |||
"os" | |||
"path/filepath" | |||
"github.com/Unknwon/com" | |||
"github.com/go-martini/martini" | |||
"github.com/gogits/gogs/modules/base" | |||
"github.com/gogits/gogs/modules/middleware" | |||
) | |||
func SingleDownload(ctx *middleware.Context, params martini.Params) { | |||
// Get tree path | |||
treename := params["_1"] | |||
blob, err := ctx.Repo.Commit.GetBlobByPath(treename) | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err) | |||
return | |||
} | |||
data, err := blob.Data() | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(Data)", err) | |||
return | |||
} | |||
contentType, isTextFile := base.IsTextFile(data) | |||
_, isImageFile := base.IsImageFile(data) | |||
ctx.Res.Header().Set("Content-Type", contentType) | |||
if !isTextFile && !isImageFile { | |||
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename)) | |||
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary") | |||
} | |||
ctx.Res.Write(data) | |||
} | |||
func ZipDownload(ctx *middleware.Context, params martini.Params) { | |||
commitId := ctx.Repo.CommitId | |||
archivesPath := filepath.Join(ctx.Repo.GitRepo.Path, "archives") | |||
if !com.IsDir(archivesPath) { | |||
if err := os.Mkdir(archivesPath, 0755); err != nil { | |||
ctx.Handle(404, "ZipDownload -> os.Mkdir(archivesPath)", err) | |||
return | |||
} | |||
} | |||
zipPath := filepath.Join(archivesPath, commitId+".zip") | |||
if com.IsFile(zipPath) { | |||
ctx.ServeFile(zipPath, ctx.Repo.Repository.Name+".zip") | |||
return | |||
} | |||
err := ctx.Repo.Commit.CreateArchive(zipPath) | |||
if err != nil { | |||
ctx.Handle(404, "ZipDownload -> CreateArchive "+zipPath, err) | |||
return | |||
} | |||
ctx.ServeFile(zipPath, ctx.Repo.Repository.Name+".zip") | |||
} |
@@ -145,7 +145,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
return | |||
} | |||
if entry != nil && entry.IsFile() { | |||
if entry != nil && !entry.IsDir() { | |||
blob := entry.Blob() | |||
if data, err := blob.Data(); err != nil { | |||
@@ -154,7 +154,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
ctx.Data["FileSize"] = blob.Size() | |||
ctx.Data["IsFile"] = true | |||
ctx.Data["FileName"] = blob.Name | |||
ext := path.Ext(blob.Name) | |||
ext := path.Ext(blob.Name()) | |||
if len(ext) > 0 { | |||
ext = ext[1:] | |||
} | |||
@@ -168,7 +168,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
if isImageFile { | |||
ctx.Data["IsImageFile"] = true | |||
} else { | |||
readmeExist := base.IsMarkdownFile(blob.Name) || base.IsReadmeFile(blob.Name) | |||
readmeExist := base.IsMarkdownFile(blob.Name()) || base.IsReadmeFile(blob.Name()) | |||
ctx.Data["ReadmeExist"] = readmeExist | |||
if readmeExist { | |||
ctx.Data["FileContent"] = string(base.RenderMarkdown(data, "")) | |||
@@ -193,7 +193,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
files := make([][]interface{}, 0, len(entries)) | |||
for _, te := range entries { | |||
c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name)) | |||
c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name())) | |||
if err != nil { | |||
ctx.Handle(404, "repo.Single(SubTree)", err) | |||
return | |||
@@ -207,7 +207,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
var readmeFile *git.Blob | |||
for _, f := range entries { | |||
if !f.IsFile() || !base.IsReadmeFile(f.Name) { | |||
if f.IsDir() || !base.IsReadmeFile(f.Name()) { | |||
continue | |||
} else { | |||
readmeFile = f.Blob() | |||
@@ -260,32 +260,6 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
ctx.HTML(200, "repo/single") | |||
} | |||
func SingleDownload(ctx *middleware.Context, params martini.Params) { | |||
// Get tree path | |||
treename := params["_1"] | |||
blob, err := ctx.Repo.Commit.GetBlobByPath(treename) | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err) | |||
return | |||
} | |||
data, err := blob.Data() | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(Data)", err) | |||
return | |||
} | |||
contentType, isTextFile := base.IsTextFile(data) | |||
_, isImageFile := base.IsImageFile(data) | |||
ctx.Res.Header().Set("Content-Type", contentType) | |||
if !isTextFile && !isImageFile { | |||
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename)) | |||
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary") | |||
} | |||
ctx.Res.Write(data) | |||
} | |||
func basicEncode(username, password string) string { | |||
auth := username + ":" + password | |||
return base64.StdEncoding.EncodeToString([]byte(auth)) |
@@ -176,6 +176,7 @@ func runWeb(*cli.Context) { | |||
r.Get("/commit/:branchname", repo.Diff) | |||
r.Get("/commit/:branchname/**", repo.Diff) | |||
r.Get("/releases", repo.Releases) | |||
r.Get("/archive/:branchname/:reponame.zip", repo.ZipDownload) | |||
}, ignSignIn, middleware.RepoAssignment(true, true)) | |||
m.Group("/:username", func(r martini.Router) { |