diff --git a/cmd/version.go b/cmd/version.go index 2c68d32..8fc183c 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -10,7 +10,7 @@ import ( "github.com/spf13/cobra" ) -var Version = "0.0.1" +var Version = "0.1.0" func init() { rootCmd.AddCommand(versionCmd) diff --git a/cmd/web.go b/cmd/web.go index 564d063..a7b306f 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -5,6 +5,7 @@ Copyright © 2022 Seednode package cmd import ( + "errors" "fmt" "io" "log" @@ -12,75 +13,124 @@ import ( "net/url" "os" "strconv" + "strings" ) -func generateHeader(fileName string) string { - htmlHeader := ` - - - ` - htmlHeader += fileName - htmlHeader += ` - - -` - - return htmlHeader -} - -func generateFooter() string { - htmlFooter := ` -` - - return htmlFooter -} - -func generatePageHtml(w http.ResponseWriter, paths []string, output []string) { +func generatePageHtml(w http.ResponseWriter, paths []string) error { fileList, err := getFileList(paths) if err != nil { - panic(err) + return err } fileName, filePath := pickFile(fileList) w.Header().Add("Content-Type", "text/html") - _, err = io.WriteString(w, generateHeader(fileName)) - if err != nil { - fmt.Println(err) - } - - htmlBody := ` + + + ` + htmlBody += fileName + htmlBody += ` + + + ` _, err = io.WriteString(w, htmlBody) - - _, err = io.WriteString(w, generateFooter()) if err != nil { - fmt.Println(err) + return err } + + return nil +} + +func statusNotFound(w http.ResponseWriter, filePath string) error { + fmt.Println("Client requested non-existent file " + filePath + ".") + + w.WriteHeader(http.StatusNotFound) + w.Header().Set("Content-Type", "txt/plain") + htmlBody := "File not found." + _, err := io.WriteString(w, htmlBody) + if err != nil { + return err + } + + return nil +} + +func statusForbidden(w http.ResponseWriter, filePath string) error { + fmt.Println("Client requested forbidden file " + filePath + ".") + + w.WriteHeader(http.StatusForbidden) + w.Header().Set("Content-Type", "txt/plain") + htmlBody := "Access denied." + _, err := io.WriteString(w, htmlBody) + if err != nil { + return err + } + + return nil +} + +func serveStaticFile(w http.ResponseWriter, request string, paths []string) error { + filePath, err := url.QueryUnescape(request) + if err != nil { + return err + } + + var matchesPrefix = false + + for i := 0; i < len(paths); i++ { + if strings.HasPrefix(filePath, paths[i]) { + matchesPrefix = true + } + } + + if matchesPrefix == false { + err := statusNotFound(w, filePath) + if err != nil { + return err + } + + return nil + } + + _, err = os.Stat(filePath) + if errors.Is(err, os.ErrNotExist) { + err := statusNotFound(w, filePath) + if err != nil { + return err + } + + return nil + } else if !errors.Is(err, os.ErrNotExist) && err != nil { + return err + } + + buf, err := os.ReadFile(filePath) + if err != nil { + return err + } + + w.Write(buf) + + return nil } func servePageHandler(paths []string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var output []string - - request := r.RequestURI - if r.RequestURI == "/" { - generatePageHtml(w, paths, output) - } else { - f, err := url.QueryUnescape(request) + err := generatePageHtml(w, paths) if err != nil { log.Fatal(err) - return } - buf, err := os.ReadFile(f) + } else { + err := serveStaticFile(w, r.RequestURI, paths) if err != nil { - panic(err) + log.Fatal(err) } - w.Write(buf) } } }