From 4318d9988a21b29702585fba5378fd2d5f2fab97 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 4 May 2019 16:04:41 -0700 Subject: [PATCH] Add support for renaming files/directories --- go.mod | 1 + go.sum | 2 ++ http.go | 37 +++++++++++++++++++++++++++++++++++-- server/filesystem.go | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 25a4bc1..b50a0d2 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Microsoft/go-winio v0.4.7 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/docker v0.0.0-20180422163414-57142e89befe diff --git a/go.sum b/go.sum index 4bb5c73..e61e2af 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/Microsoft/go-winio v0.4.7 h1:vOvDiY/F1avSWlCWiKJjdYKz2jVjTK3pWPHndeG4 github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= diff --git a/http.go b/http.go index b0061aa..4b1e998 100644 --- a/http.go +++ b/http.go @@ -2,8 +2,10 @@ package main import ( "bufio" + "bytes" "encoding/json" "fmt" + "github.com/buger/jsonparser" "github.com/gorilla/websocket" "github.com/julienschmidt/httprouter" "github.com/pterodactyl/wings/server" @@ -204,7 +206,7 @@ func (rt *Router) routeServerLogs(w http.ResponseWriter, r *http.Request, ps htt return } - json.NewEncoder(w).Encode(struct{Data []string `json:"data"`}{Data: out }) + json.NewEncoder(w).Encode(struct{ Data []string `json:"data"` }{Data: out}) } // Handle a request to get the contents of a file on the server. @@ -241,7 +243,7 @@ func (rt *Router) routeServerFileRead(w http.ResponseWriter, r *http.Request, ps // If a download parameter is included in the URL go ahead and attach the necessary headers // so that the file can be downloaded. if r.URL.Query().Get("download") != "" { - w.Header().Set("Content-Disposition", "attachment; filename=" + st.Name()) + w.Header().Set("Content-Disposition", "attachment; filename="+st.Name()) w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Length", strconv.Itoa(int(st.Size()))) } @@ -296,6 +298,36 @@ func (rt *Router) routeServerCreateDirectory(w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusNoContent) } +func (rt *Router) routeServerRenameFile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + s := rt.Servers.Get(ps.ByName("server")) + defer r.Body.Close() + + data := rt.ReaderToBytes(r.Body) + oldPath, _ := jsonparser.GetString(data, "rename_from") + newPath, _ := jsonparser.GetString(data, "rename_to") + + if oldPath == "" || newPath == "" { + http.Error(w, "invalid paths provided; did you forget to provide an old path and new path?", http.StatusUnprocessableEntity) + return + } + + if err := s.Filesystem.Rename(oldPath, newPath); err != nil { + zap.S().Errorw("failed to rename file on server", zap.String("server", s.Uuid), zap.Error(err)) + + http.Error(w, "an error occurred while renaming the file", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusNoContent) +} + +func (rt *Router) ReaderToBytes(r io.Reader) []byte { + buf := bytes.Buffer{} + buf.ReadFrom(r) + + return buf.Bytes() +} + // Configures the router and all of the associated routes. func (rt *Router) ConfigureRouter() *httprouter.Router { router := httprouter.New() @@ -306,6 +338,7 @@ func (rt *Router) ConfigureRouter() *httprouter.Router { router.GET("/api/servers/:server/logs", rt.AuthenticateToken("s:logs", rt.AuthenticateServer(rt.routeServerLogs))) router.GET("/api/servers/:server/files/read/*path", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerFileRead))) router.GET("/api/servers/:server/files/list/*path", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerFileList))) + router.PUT("/api/servers/:server/files/rename", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerRenameFile))) router.POST("/api/servers/:server/files/create-directory", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerCreateDirectory))) router.POST("/api/servers/:server/power", rt.AuthenticateToken("s:power", rt.AuthenticateServer(rt.routeServerPower))) diff --git a/server/filesystem.go b/server/filesystem.go index 1582122..3a653b3 100644 --- a/server/filesystem.go +++ b/server/filesystem.go @@ -272,6 +272,21 @@ func (fs *Filesystem) CreateDirectory(name string, p string) error { return os.MkdirAll(cleaned, 0755) } +// Moves (or renames) a file or directory. +func (fs *Filesystem) Rename(from string, to string) error { + cleanedFrom, err := fs.SafePath(from) + if err != nil { + return err + } + + cleanedTo, err := fs.SafePath(to) + if err != nil { + return err + } + + return os.Rename(cleanedFrom, cleanedTo) +} + // Lists the contents of a given directory and returns stat information about each // file and folder within it. func (fs *Filesystem) ListDirectory(p string) ([]*Stat, error) {