From 9e4b2bfdfef8b95d65e9ce5be88986012b3f5033 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sat, 8 Sep 2012 19:44:44 +0200 Subject: Implement all files and dirs APIs except file reading and directory listing. Implement the cloud status API. --- src/ninjacloud.go | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ninjacloud.go b/src/ninjacloud.go index 57e939a..9ec2962 100644 --- a/src/ninjacloud.go +++ b/src/ninjacloud.go @@ -2,14 +2,12 @@ package main import ( "encoding/json" - //"errors" "flag" + "io" "io/ioutil" "log" "net/http" "os" - //"path" - "io" "path/filepath" ) @@ -29,7 +27,8 @@ const statusPath = "/cloudstatus" const filePathLen = len(filePath) const dirPathLen = len(dirPath) const webPathLen = len(webPath) -const statusPathLen = len(statusPath) + +//const statusPathLen = len(statusPath) //////// FILESYSTEM @@ -41,6 +40,10 @@ func exist(path string) bool { return false } +func isInRoot(path string) bool { + return filepath.HasPrefix(path, rootFlag) +} + //// Files func writeFile(path string, content []byte, overwrite bool) (err error) { @@ -49,6 +52,11 @@ func writeFile(path string, content []byte, overwrite bool) (err error) { err = os.ErrExist return } + } else { + if !exist(path) { + err = os.ErrNotExist + return + } } err = ioutil.WriteFile(path, content, 0600) return @@ -157,22 +165,113 @@ func copyDir(source string, dest string) (err error) { func fileHandler(w http.ResponseWriter, r *http.Request) { p := r.URL.Path[filePathLen:] filepath.Clean(p) + if !isInRoot(p) { + w.WriteHeader(http.StatusForbidden) + return + } switch r.Method { case "POST": // Create a new file + content, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + err = writeFile(p, *&content, false) + if err == os.ErrExist { + w.WriteHeader(http.StatusBadRequest) + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusCreated) + return case "PUT": - if r.Header.Get("sourceURI") == "" { + source := r.Header.Get("sourceURI") + if source == "" { // Update an existing file (save over existing file) + content, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + err = writeFile(p, *&content, true) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusNoContent) + return } else { // Copy, Move of an existing file + if r.Header.Get("overwrite-destination") == "true" { + err := removeFile(p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } + if r.Header.Get("delete-source") == "true" { + err := moveFile(source, p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } else { + err := copyFile(source, p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } + w.WriteHeader(http.StatusNoContent) + return } case "DELETE": // Delete an existing file + err := removeFile(p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusNoContent) + return case "GET": // Read an existing file + modifiedSince := r.Header.Get("If-modified-since") + if modifiedSince != "" { + // TODO + var test os.FileInfo + test.ModTime() + } else if r.Header.Get("check-existence-only") == "true" { + if exist(p) { + w.WriteHeader(http.StatusNoContent) + return + } else { + w.WriteHeader(http.StatusNotFound) + return + } + } else if r.Header.Get("get-file-info") != "" { + // TODO + } else { + // TODO + } } - } //// Directory APIs @@ -180,18 +279,69 @@ func fileHandler(w http.ResponseWriter, r *http.Request) { func dirHandler(w http.ResponseWriter, r *http.Request) { p := r.URL.Path[dirPathLen:] filepath.Clean(p) + if !isInRoot(p) { + w.WriteHeader(http.StatusForbidden) + return + } switch r.Method { case "POST": // Create a new directory + err := createDir(p) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + w.WriteHeader(http.StatusCreated) + return case "DELETE": // Delete an existing directory + err := removeDir(p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusNoContent) + return case "GET": // List the contents of an existing directory + // TODO case "PUT": // Copy, Move of an existing directory + source := r.Header.Get("sourceURI") + if exist(p) { + w.WriteHeader(http.StatusBadRequest) + return + } + operation := r.Header.Get("operation") + if operation == "move" { + err := moveDir(source, p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } else if operation == "copy" { + err := copyDir(source, p) + if err == os.ErrNotExist { + w.WriteHeader(http.StatusNotFound) + return + } else if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + } else { + w.WriteHeader(http.StatusBadRequest) + return + } + w.WriteHeader(http.StatusNoContent) + return } - } //// Web API -- cgit v1.2.3