aboutsummaryrefslogtreecommitdiff
path: root/src/helpers.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/helpers.go')
-rw-r--r--src/helpers.go292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/helpers.go b/src/helpers.go
new file mode 100644
index 0000000..c544d71
--- /dev/null
+++ b/src/helpers.go
@@ -0,0 +1,292 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "os"
+ "os/user"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+type ServerError struct {
+ Err error
+ Message string
+ Status int
+}
+
+func (e *ServerError) Error() string { return e.Err.Error() }
+func (e *ServerError) Unwrap() error { return e.Err }
+
+
+func getFileNode(URL string) (*FileNode, *ServerError) {
+ path, err := url.PathUnescape(URL)
+ if err != nil {
+ return nil, &ServerError{err, "", 500}
+ }
+ p := strings.Split(path, "/")
+ fileURI := strings.Trim(strings.Join(p[2:], "/"), "/")
+ filePath := filepath.Join(homeDir, fileURI)
+
+ fileInfo, err := os.Lstat(filePath)
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ return nil, &ServerError{err, fileURI+" not found", 404}
+ }
+ return nil, &ServerError{err, "", 500}
+ }
+
+ return &FileNode{
+ Path: filePath,
+ URI: fileURI,
+ IsDir: fileInfo.IsDir(),
+ Info: fileInfo,
+ }, nil
+}
+
+
+var filePattern = regexp.MustCompile(`^-file-entry--(.+)$`)
+
+func getSelectedNodes(r *http.Request) (*FileNode, []*FileNode, *ServerError) {
+ fileNode, e := getFileNode(r.URL.Path)
+ if e != nil {
+ return nil, nil, e
+ }
+ r.ParseMultipartForm(65536)
+ fmt.Println(r.Form)
+ var fileNames []string
+ for key := range r.Form {
+ if match := filePattern.FindStringSubmatch(key); len(match) > 1 {
+ fileNames = append(fileNames, match[1])
+ }
+ }
+ fmt.Printf("FileNames: %s\n", fileNames)
+ if len(fileNames) == 0 {
+ return fileNode, []*FileNode{fileNode}, nil
+ }
+
+ files := make([]*FileNode, len(fileNames))
+ for i, fileName := range fileNames {
+ fileNode, e := getFileNode(filepath.Join(r.URL.Path, fileName))
+ if e != nil {
+ return fileNode, nil, e
+ }
+ files[i] = fileNode
+ }
+ return fileNode, files, nil
+}
+
+
+func sendFile(w http.ResponseWriter, r *http.Request, info ...string) {
+ fmt.Printf("info: %s\n", info[:])
+ if len(info) < 2 {
+ info = append(info, filepath.Base(info[0]))
+ }
+ w.Header().Set("Content-Disposition", "attachment; filename=" + info[1])
+ http.ServeFile(w, r, info[0])
+}
+
+
+func addSelectionToBuffer(w http.ResponseWriter, r *http.Request, bufferPath string) *ServerError {
+ _, files, e := getSelectedNodes(r)
+ if e != nil {
+ return e
+ }
+ buffer, err := readBuffer(bufferPath)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ buff, err := os.OpenFile(bufferPath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ var fileURI string
+
+ writeToBuffer:
+ for _, file := range files {
+ fileURI = strings.Trim(file.URI, "/")
+ for _, line := range buffer {
+ if strings.Trim(line, "/") == fileURI {
+ continue writeToBuffer
+ }
+ }
+ if file.IsDir {
+ fileURI += "/"
+ }
+ buff.WriteString("/" + fileURI + "\r\n")
+ }
+
+ http.Redirect(w, r, r.URL.Path, 303)
+ return nil
+}
+
+
+func deleteBuffer(w http.ResponseWriter, r *http.Request, bufferPath string) *ServerError {
+ err := os.Remove(bufferPath)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ http.Redirect(w, r, r.URL.Path, 303)
+ return nil
+}
+
+
+func moveFilesFromBuffer(w http.ResponseWriter, r *http.Request, bufferPath string) *ServerError {
+ fileNode, serr := getFileNode(r.URL.Path)
+ if serr != nil {
+ return serr
+ }
+ if !fileNode.IsDir {
+ return &ServerError{nil, "Cannot move file, destination is not a directory", 400}
+ }
+ buffer, err := readBuffer(bufferPath)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ for _, line := range buffer {
+ err := copyTo(filepath.Join(homeDir, line), fileNode.Path)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ }
+ deleteBuffer(w, r, bufferPath)
+ return nil
+}
+
+
+func pasteFilesFromBuffer(w http.ResponseWriter, r *http.Request, bufferPath string) *ServerError {
+ fileNode, serr := getFileNode(r.URL.Path)
+ if serr != nil {
+ return serr
+ }
+ if !fileNode.IsDir {
+ return &ServerError{nil, "Cannot copy files, destination is not a directory", 400}
+ }
+ buffer, err := readBuffer(bufferPath)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ fmt.Printf("Buffer content: %s\n", buffer)
+ for _, line := range buffer {
+ err := copyTo(filepath.Join(homeDir, line), fileNode.Path)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ }
+ deleteBuffer(w, r, bufferPath)
+ return nil
+}
+
+
+func createNewDirectory(w http.ResponseWriter, r *http.Request) *ServerError {
+ fileNode, serr := getFileNode(r.URL.Path)
+ if serr != nil {
+ return serr
+ }
+ dirname := strings.TrimSpace(r.FormValue("newdir"))
+ msg := "Requested to create directory '"+dirname+"' in "+fileNode.URI+"\n"
+ if dirname == "" {
+ msg = "Directory name cannot be empty.\n" + msg
+ return &ServerError{nil, msg, 400}
+ }
+ if !fileNode.IsDir {
+ msg = "Cannot create directory, the given destination is a file.\n" + msg
+ return &ServerError{nil, msg, 400}
+ }
+ path := filepath.Join(fileNode.Path, dirname)
+ isExist, err := fileExists(path)
+ if isExist {
+ msg = "Cannot create directory, a file with given name already exists.\n" + msg
+ return &ServerError{nil, msg, 400}
+ }
+ err = os.Mkdir(path, 0755)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ http.Redirect(w, r, r.URL.Path, 303)
+ return nil
+}
+
+
+func blockAction(w http.ResponseWriter, r *http.Request, action string) *ServerError {
+ msg := ""
+ _, files, serr := getSelectedNodes(r)
+ if serr != nil {
+ return serr
+ }
+ msg += "The " + action + " operation is currently disabled for testing and security reasons.\n"
+ msg += "You requested to " + action + " following files :-\n\n"
+ for _, file := range files {
+ msg += file.Path + "\n"
+ }
+ fmt.Fprintf(w, msg)
+ return nil
+}
+
+
+func deleteSelectedFiles(w http.ResponseWriter, r *http.Request) *ServerError {
+ // return blockAction(w, r, "delete")
+ fileNode, files, serr := getSelectedNodes(r)
+ if serr != nil {
+ return serr
+ }
+ for _, file := range files {
+ if file.Path == homeDir {
+ return &ServerError{nil, "Cannot delete root directory.", 400}
+ }
+ fmt.Printf("Deleting: %s\n", file.Path)
+ err := os.RemoveAll(file.Path)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ fmt.Println("Deleted.")
+ }
+ isExist, err := fileExists(fileNode.Path)
+ if err != nil {
+ return &ServerError{err, "", 500}
+ }
+ if !isExist {
+ http.Redirect(w, r, "/view/" + filepath.Dir(fileNode.URI), 303)
+ } else {
+ http.Redirect(w, r, "/view/" + fileNode.URI, 303)
+ }
+ return nil
+}
+
+
+var (
+ homeDir = "/media/"
+ tempDir = "/tmp/cloud/"
+ cutBuffer = filepath.Join(tempDir, "cut_buffer")
+ copyBuffer = filepath.Join(tempDir, "copy_buffer")
+)
+
+
+func init() {
+ err := os.MkdirAll(tempDir, 0755);
+ if err != nil {
+ panic(err)
+ }
+ mountpoint := os.Getenv("CLOUD_MAKER_HOME")
+ if mountpoint != "" {
+ isExist, err := fileExists(mountpoint)
+ if err != nil {
+ panic(err)
+ }
+ if isExist {
+ homeDir = mountpoint
+ }
+ return
+ }
+
+ u, err := user.Current()
+ if err != nil {
+ panic(err)
+ }
+ homeDir += u.Username
+}
+
+