diff --git a/server/common/log.go b/server/common/log.go index b625cb5b..5b2c4901 100644 --- a/server/common/log.go +++ b/server/common/log.go @@ -1,10 +1,14 @@ package common import ( - "fmt" - "io" - "io/ioutil" "time" + "log" +) + +const ( + LOG_INFO = "INFO" + LOG_WARNING = "WARNING" + LOG_ERROR = "ERROR" ) type LogEntry struct { @@ -23,7 +27,34 @@ type LogEntry struct { Backend string `json:"backend"` } -func Debug_reader(r io.Reader) { - a, _ := ioutil.ReadAll(r) - fmt.Println("> DEBUG:", string(a)) +func Log(ctx *App, str string, level string){ + if ctx.Config.Log.Enable == false { + return + } + + shouldDisplay := func(r string, l string) bool { + levels := []string{"DEBUG", "INFO", "WARNING", "ERROR"} + + configLevel := -1 + currentLevel := 0 + + for i:=0; i <= len(levels); i++ { + if levels[i] == l { + currentLevel = i + } + if levels[i] == r { + configLevel = i + break + } + } + + if currentLevel <= configLevel { + return true + } + return false + }(ctx.Config.Log.Level, level) + + if shouldDisplay { + log.Printf("%s %s\n", level, str) + } } diff --git a/server/ctrl/static.go b/server/ctrl/static.go new file mode 100644 index 00000000..c1574cae --- /dev/null +++ b/server/ctrl/static.go @@ -0,0 +1,60 @@ +package ctrl + +import ( + . "github.com/mickael-kerjean/nuage/server/common" + "mime" + "net/http" + "os" + "path" + "path/filepath" + "strings" +) + +func StaticHandler(_path string, ctx App) http.Handler { + return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + header := res.Header() + header.Set("Content-Type", mime.TypeByExtension(filepath.Ext(req.URL.Path))) + header.Set("Cache-Control", "max-age=2592000") + SecureHeader(&header) + + if strings.HasSuffix(req.URL.Path, "/") { + http.NotFound(res, req) + return + } + + absPath := ctx.Helpers.AbsolutePath(_path) + fsrv := http.FileServer(http.Dir(absPath)) + _, err := os.Open(path.Join(absPath, req.URL.Path+".gz")) + if err == nil && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + res.Header().Set("Content-Encoding", "gzip") + req.URL.Path += ".gz" + } + fsrv.ServeHTTP(res, req) + }) +} + +func DefaultHandler(_path string, ctx App) http.Handler { + return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.Method != "GET" { + http.Error(res, "Invalid request method.", 405) + return + } + + header := res.Header() + header.Set("Content-Type", "text/html") + SecureHeader(&header) + + p := _path + if _, err := os.Open(path.Join(ctx.Config.Runtime.Dirname, p+".gz")); err == nil && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + res.Header().Set("Content-Encoding", "gzip") + p += ".gz" + } + http.ServeFile(res, req, ctx.Helpers.AbsolutePath(p)) + }) +} + +func SecureHeader(header *http.Header) { + header.Set("X-XSS-Protection", "1; mode=block") + header.Set("X-Content-Type-Options", "nosniff") + header.Set("X-Frame-Options", "DENY") +} diff --git a/server/ctrl/webdav.go b/server/ctrl/webdav.go new file mode 100644 index 00000000..8d1910ec --- /dev/null +++ b/server/ctrl/webdav.go @@ -0,0 +1,36 @@ +package ctrl + +import ( + "net/http" + "log" + . "github.com/mickael-kerjean/nuage/server/common" + "github.com/mickael-kerjean/nuage/server/model" + "golang.org/x/net/webdav" + "github.com/mickael-kerjean/mux" + "strings" +) + +func WebdavHandler(ctx App, res http.ResponseWriter, req *http.Request) { + accept := req.Header.Get("Accept") + if strings.HasPrefix(accept, "text/html") { + DefaultHandler("./data/public/index.html", ctx).ServeHTTP(res, req) + return + } + if ctx.Backend == nil { + http.NotFound(res, req) + return + } + + s := model.Share{ Id: mux.Vars(req)["id"] } + log.Println("> webdav: "+ s.Id) + + h := &webdav.Handler{ + Prefix: "/s/",// + s.Id, + FileSystem: model.NewWebdavFs(ctx.Backend), + LockSystem: webdav.NewMemLS(), + Logger: func(r *http.Request, err error) { + Log(&ctx, "Webdav", "INFO") + }, + } + h.ServeHTTP(res, req) +} diff --git a/server/model/webdav.go b/server/model/webdav.go new file mode 100644 index 00000000..91d90718 --- /dev/null +++ b/server/model/webdav.go @@ -0,0 +1,50 @@ +package model + +import ( + "os" + "context" + . "github.com/mickael-kerjean/nuage/server/common" + "golang.org/x/net/webdav" + //"log" +) + +type WebdavFs struct { + backend IBackend +} + +func NewWebdavFs(b IBackend) WebdavFs { + return WebdavFs{backend: b} +} + +func (w WebdavFs) Mkdir(ctx context.Context, name string, perm os.FileMode) error { + return w.backend.Mkdir(name) +} + +func (w WebdavFs) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { + f, err := os.OpenFile(name, flag, perm) + if err != nil { + return nil, err + } + return f, nil +} + +func (w WebdavFs) RemoveAll(ctx context.Context, name string) error { + return w.backend.Rm(name) +} + +func (w WebdavFs) Rename(ctx context.Context, oldName, newName string) error { + return w.backend.Mv(oldName, newName) +} + +func (w WebdavFs) Stat(ctx context.Context, name string) (os.FileInfo, error) { + files, err := w.backend.Ls(name) + if err != nil { + return nil, err + } + for i:=0; i < len(files); i++ { + if files[i].Name() == "test" { + return files[i], nil + } + } + return nil, os.ErrNotExist +} diff --git a/server/router/index.go b/server/router/index.go index fb1a942f..968677b2 100644 --- a/server/router/index.go +++ b/server/router/index.go @@ -34,11 +34,14 @@ func Init(a *App) *http.Server { share.HandleFunc("/{id}", APIHandler(ShareUpsert, *a)).Methods("POST") share.HandleFunc("/{id}", APIHandler(ShareDelete, *a)).Methods("DELETE") share.HandleFunc("/{id}/proof", APIHandler(ShareVerifyProof, *a)).Methods("POST") + + // WEBDAV + r.PathPrefix("/s/{id}").Handler(APIHandler(WebdavHandler, *a)) // APP r.HandleFunc("/api/config", CtxInjector(ConfigHandler, *a)).Methods("GET") r.PathPrefix("/assets").Handler(StaticHandler("./data/public/", *a)).Methods("GET") - r.NotFoundHandler = DefaultHandler("./data/public/index.html", *a) + r.PathPrefix("/").Handler(DefaultHandler("./data/public/index.html", *a)).Methods("GET") srv := &http.Server{ Addr: ":" + strconv.Itoa(a.Config.General.Port), diff --git a/server/router/static.go b/server/router/static.go index 3d0aa0a0..0e6d0cd5 100644 --- a/server/router/static.go +++ b/server/router/static.go @@ -35,11 +35,6 @@ func StaticHandler(_path string, ctx App) http.Handler { func DefaultHandler(_path string, ctx App) http.Handler { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.Method != "GET" { - http.Error(res, "Invalid request method.", 405) - return - } - header := res.Header() header.Set("Content-Type", "text/html") SecureHeader(&header) diff --git a/server/services/webdav.go b/server/services/webdav.go new file mode 100644 index 00000000..176752e6 --- /dev/null +++ b/server/services/webdav.go @@ -0,0 +1,28 @@ +package services + +// type Webdav struct { +// } + +// func NewWebdav() Webdav { +// return Webdav{} +// } + +// func (w Webdav) Mkdir(ctx context.Context, name string, perm os.FileMode) error { +// return nil +// } + +// func (w Webdav) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) { +// return File{}, nil +// } + +// func (w Webdav) RemoveAll(ctx context.Context, name string) error { +// return nil +// } + +// func (w Webdav) Rename(ctx context.Context, oldName, newName string) error { +// return nil +// } + +// func (w Webdav) Stat(ctx context.Context, name string) (os.FileInfo, error) { +// return nil, nil +// }