mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-11-04 05:27:04 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			288 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package ctrl
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	. "github.com/mickael-kerjean/filestash/server/common"
 | 
						|
	"github.com/mickael-kerjean/filestash/server/model"
 | 
						|
	"io"
 | 
						|
	"net/http"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
type FileInfo struct {
 | 
						|
	Name string `json:"name"`
 | 
						|
	Type string `json:"type"`
 | 
						|
	Size int64  `json:"size"`
 | 
						|
	Time int64  `json:"time"`
 | 
						|
}
 | 
						|
 | 
						|
func FileLs(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	var files []FileInfo = make([]FileInfo, 0)
 | 
						|
	if model.CanRead(&ctx) == false {
 | 
						|
		if model.CanUpload(&ctx) == false {
 | 
						|
			SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
			return
 | 
						|
		}
 | 
						|
		SendSuccessResults(res, files)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	entries, err := ctx.Backend.Ls(path)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	for _, entry := range entries {
 | 
						|
		f := FileInfo{
 | 
						|
			Name: entry.Name(),
 | 
						|
			Size: entry.Size(),
 | 
						|
			Time: func(t time.Time) int64 {
 | 
						|
				return t.UnixNano() / int64(time.Millisecond)
 | 
						|
			}(entry.ModTime()),
 | 
						|
			Type: func(isDir bool) string {
 | 
						|
				if isDir == true {
 | 
						|
					return "directory"
 | 
						|
				}
 | 
						|
				return "file"
 | 
						|
			}(entry.IsDir()),
 | 
						|
		}
 | 
						|
		files = append(files, f)
 | 
						|
	}
 | 
						|
 | 
						|
	var perms Metadata = Metadata{}
 | 
						|
	if obj, ok := ctx.Backend.(interface{ Meta(path string) Metadata }); ok {
 | 
						|
		perms = obj.Meta(path)
 | 
						|
	}
 | 
						|
 | 
						|
	if model.CanEdit(&ctx) == false {
 | 
						|
		perms.CanCreateFile = NewBool(false)
 | 
						|
		perms.CanCreateDirectory = NewBool(false)
 | 
						|
		perms.CanRename = NewBool(false)
 | 
						|
		perms.CanMove = NewBool(false)
 | 
						|
		perms.CanDelete = NewBool(false)
 | 
						|
	}
 | 
						|
	if model.CanUpload(&ctx) == false {
 | 
						|
		perms.CanCreateDirectory = NewBool(false)
 | 
						|
		perms.CanRename = NewBool(false)
 | 
						|
		perms.CanMove = NewBool(false)
 | 
						|
		perms.CanDelete = NewBool(false)
 | 
						|
	}
 | 
						|
	if model.CanShare(&ctx) == false {
 | 
						|
		perms.CanShare = NewBool(false)
 | 
						|
	}
 | 
						|
 | 
						|
	etag := func() string {
 | 
						|
		tmp := struct {
 | 
						|
			Tmp0 interface{}
 | 
						|
			Tmp1 interface{}
 | 
						|
		}{ files, perms }
 | 
						|
		if j, err := json.Marshal(tmp); err == nil {
 | 
						|
			return Hash(string(j))
 | 
						|
		}
 | 
						|
		return ""
 | 
						|
	}()
 | 
						|
	if etag != "" && req.Header.Get("If-None-Match") == etag {
 | 
						|
		res.WriteHeader(http.StatusNotModified)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	res.Header().Set("Etag", etag)
 | 
						|
 | 
						|
	SendSuccessResultsWithMetadata(res, files, perms)
 | 
						|
}
 | 
						|
 | 
						|
func FileCat(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	http.SetCookie(res, &http.Cookie{
 | 
						|
		Name:   "download",
 | 
						|
		Value:  "",
 | 
						|
		MaxAge: -1,
 | 
						|
		Path:   "/",
 | 
						|
	})
 | 
						|
	if model.CanRead(&ctx) == false {
 | 
						|
		SendErrorResult(res, ErrPermissionDenied)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	file, err := ctx.Backend.Cat(path)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if obj, ok := file.(interface{ Close() error }); ok {
 | 
						|
		defer obj.Close()
 | 
						|
	}
 | 
						|
 | 
						|
	mType := GetMimeType(req.URL.Query().Get("path"))
 | 
						|
	res.Header().Set("Content-Type", mType)
 | 
						|
 | 
						|
	for _, obj := range Hooks.Get.ProcessFileContentBeforeSend() {
 | 
						|
		if file, err = obj(file, &ctx, &res, req); err != nil {
 | 
						|
			SendErrorResult(res, err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	io.Copy(res, file)
 | 
						|
}
 | 
						|
 | 
						|
func FileAccess(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	allowed := []string{}
 | 
						|
	if model.CanRead(&ctx){
 | 
						|
		allowed = append(allowed, "GET")
 | 
						|
	}
 | 
						|
	if model.CanEdit(&ctx){
 | 
						|
		allowed = append(allowed, "PUT")
 | 
						|
	}
 | 
						|
	if model.CanUpload(&ctx){
 | 
						|
		allowed = append(allowed, "POST")
 | 
						|
	}
 | 
						|
	res.Header().Set("Allow", strings.Join(allowed, ", "))
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func FileSave(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	if model.CanEdit(&ctx) == false {
 | 
						|
		SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	file, _, err := req.FormFile("file")
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	defer file.Close()
 | 
						|
 | 
						|
	err = ctx.Backend.Save(path, file)
 | 
						|
	if obj, ok := file.(interface{ Close() error }); ok {
 | 
						|
		obj.Close()
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, NewError(err.Error(), 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func FileMv(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	if model.CanEdit(&ctx) == false {
 | 
						|
		SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	from, err := pathBuilder(ctx, req.URL.Query().Get("from"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	to, err := pathBuilder(ctx, req.URL.Query().Get("to"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if from == "" || to == "" {
 | 
						|
		SendErrorResult(res, NewError("missing path parameter", 400))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err = ctx.Backend.Mv(from, to)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func FileRm(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	if model.CanEdit(&ctx) == false {
 | 
						|
		SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	err = ctx.Backend.Rm(path)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func FileMkdir(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	if model.CanUpload(&ctx) == false {
 | 
						|
		SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err = ctx.Backend.Mkdir(path)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func FileTouch(ctx App, res http.ResponseWriter, req *http.Request) {
 | 
						|
	if model.CanUpload(&ctx) == false {
 | 
						|
		SendErrorResult(res, NewError("Permission denied", 403))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err = ctx.Backend.Touch(path)
 | 
						|
	if err != nil {
 | 
						|
		SendErrorResult(res, err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	SendSuccessResult(res, nil)
 | 
						|
}
 | 
						|
 | 
						|
func pathBuilder(ctx App, path string) (string, error) {
 | 
						|
	if path == "" {
 | 
						|
		return "", NewError("No path available", 400)
 | 
						|
	}
 | 
						|
	basePath := ctx.Session["path"]
 | 
						|
	basePath = filepath.Join(basePath, path)
 | 
						|
	if string(path[len(path)-1]) == "/" && basePath != "/" {
 | 
						|
		basePath += "/"
 | 
						|
	}
 | 
						|
	if strings.HasPrefix(basePath, ctx.Session["path"]) == false {
 | 
						|
		return "", NewError("There's nothing here", 403)
 | 
						|
	}
 | 
						|
	return basePath, nil
 | 
						|
}
 |