diff --git a/delete.go b/delete.go new file mode 100644 index 0000000..63e71a9 --- /dev/null +++ b/delete.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "net/http" + "os" +) + +func Delete(c echo.Context) error { + file := c.Param("file") + filePath := "files/" + file + + if _, err := os.Stat(filePath); err != nil { + return c.String(http.StatusOK, "That file doesn't exist on the server\n") + } + + err := os.Remove(filePath) + if err != nil { + return c.String(http.StatusOK, "Error while deleting "+file+"\n") + } + return c.String(http.StatusOK, "Deleted file from server: "+file+"\n") +} diff --git a/files.go b/files.go new file mode 100644 index 0000000..0aa41cd --- /dev/null +++ b/files.go @@ -0,0 +1,93 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "log" + "net/http" + "os" + "regexp" +) + +type File struct { + Name string + FileType string + Content string +} + +type FilesData struct { + Files []File +} + +func Files(c echo.Context) error { + var files FilesData + + filelist, err := os.ReadDir("./files/") + if err != nil { + log.Fatal(err) + } + + UserAgent := c.Request().UserAgent() + + log.Print(UserAgent) + + match, err := regexp.MatchString("^curl/.*", UserAgent) + if err != nil { + log.Fatal(err) + } + + if match { + out := "" + for _, f := range filelist { + out += f.Name() + "\n" + } + return c.String(http.StatusOK, out) + } + + var Type string + var Content string + + ImageMatch := regexp.MustCompile("^image/.*") + VideoMatch := regexp.MustCompile("^video/.*") + JsonMatch := regexp.MustCompile("application/json") + TextMatch := regexp.MustCompile("^text/.*") + + for _, f := range filelist { + filePath := "files/" + f.Name() + file, err := os.Open(filePath) + if err != nil { + panic(err) + } + + defer file.Close() + + contentType, err := GetFileContentType(file) + + switch { + case ImageMatch.MatchString(contentType): + Type = "image" + Content = "" + case VideoMatch.MatchString(contentType): + Type = "video" + Content = "" + case JsonMatch.MatchString(contentType): + Type = "text" + b, _ := os.ReadFile(filePath) + Content = string(b) + case TextMatch.MatchString(contentType): + Type = "text" + b, _ := os.ReadFile(filePath) + Content = string(b) + default: + Type = "else" + Content = "" + } + + log.Print(contentType) + files.Files = append( + files.Files, + File{Name: f.Name(), FileType: Type, Content: Content}, + ) + } + + return c.Render(http.StatusOK, "files", files) +} diff --git a/index.go b/index.go new file mode 100644 index 0000000..cb4a853 --- /dev/null +++ b/index.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "net/http" +) + +type IndexData struct { + Host string +} + +func Index(c echo.Context) error { + data := IndexData{ + Host: domain, + } + return c.Render(http.StatusOK, "index", data) +} diff --git a/main.go b/main.go index f506920..7b6fb33 100644 --- a/main.go +++ b/main.go @@ -1,247 +1,5 @@ package main -import ( - "embed" - "errors" - "flag" - "html/template" - "io" - "log" - "net/http" - "os" - "regexp" - "strconv" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" -) - -//go:embed all:public/views/*.html -var templates embed.FS - -//go:embed all:static/* -var static embed.FS - -var domain string - func main() { - t := &Template{ - templates: template.Must(template.ParseFS(templates, "public/views/*.html")), - } - - p := flag.Int("p", 1323, "upfast port to listen on.") - a := flag.String("a", "127.0.0.1", "upfast ip to listen to") - d := flag.String("d", "127.0.0.1", "upfast domain") - flag.Parse() - - host := *a + ":" + strconv.Itoa(*p) - - domain = *d - - e := echo.New() - - e.Renderer = t - e.Use(middleware.Logger()) - - e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ - Root: "static", - Browse: false, - HTML5: true, - Filesystem: http.FS(static), - })) - - files := "files" - - if _, err := os.Stat(files); errors.Is(err, os.ErrNotExist) { - err := os.Mkdir(files, os.ModePerm) - if err != nil { - log.Println(err) - } - } - - e.Static("/files", files) - - e.GET("/", Index) - - e.POST("/", Upload) - - e.GET("/files/", Files) - - e.DELETE("/files/:file", Delete) - - e.Logger.Fatal(e.Start(host)) -} - -type Template struct { - templates *template.Template -} - -type File struct { - Name string - FileType string - Content string -} - -type FilesData struct { - Files []File -} - -type IndexData struct { - Host string -} - -func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { - return t.templates.ExecuteTemplate(w, name, data) -} - -func Index(c echo.Context) error { - data := IndexData{ - Host: domain, - } - return c.Render(http.StatusOK, "index", data) -} - -func GetFileContentType(ouput *os.File) (string, error) { - buf := make([]byte, 512) - - _, err := ouput.Read(buf) - if err != nil { - return "", err - } - - contentType := http.DetectContentType(buf) - - return contentType, nil -} - -func Files(c echo.Context) error { - var files FilesData - - filelist, err := os.ReadDir("./files/") - if err != nil { - log.Fatal(err) - } - - UserAgent := c.Request().UserAgent() - - log.Print(UserAgent) - - match, err := regexp.MatchString("^curl/.*", UserAgent) - if err != nil { - log.Fatal(err) - } - - if match { - out := "" - for _, f := range filelist { - out += f.Name() + "\n" - } - return c.String(http.StatusOK, out) - } - - var Type string - var Content string - - ImageMatch := regexp.MustCompile("^image/.*") - VideoMatch := regexp.MustCompile("^video/.*") - JsonMatch := regexp.MustCompile("application/json") - TextMatch := regexp.MustCompile("^text/.*") - - for _, f := range filelist { - filePath := "files/" + f.Name() - file, err := os.Open(filePath) - if err != nil { - panic(err) - } - - defer file.Close() - - contentType, err := GetFileContentType(file) - - switch { - case ImageMatch.MatchString(contentType): - Type = "image" - Content = "" - case VideoMatch.MatchString(contentType): - Type = "video" - Content = "" - case JsonMatch.MatchString(contentType): - Type = "text" - b, _ := os.ReadFile(filePath) - Content = string(b) - case TextMatch.MatchString(contentType): - Type = "text" - b, _ := os.ReadFile(filePath) - Content = string(b) - default: - Type = "else" - Content = "" - } - - log.Print(contentType) - files.Files = append( - files.Files, - File{Name: f.Name(), FileType: Type, Content: Content}, - ) - } - - return c.Render(http.StatusOK, "files", files) -} - -func Upload(c echo.Context) error { - file, err := c.FormFile("file") - if err != nil { - return err - } - - if _, err := os.Stat("files/" + file.Filename); err == nil { - return c.String(http.StatusOK, "A file with the same name already exist's on the server.\n") - } - - src, err := file.Open() - if err != nil { - return err - } - - dst, err := os.Create("files/" + file.Filename) - if err != nil { - return err - } - defer dst.Close() - - if _, err = io.Copy(dst, src); err != nil { - return err - } - - fileUrl := domain + "/files/" + file.Filename + "\n" - - UserAgent := c.Request().UserAgent() - - log.Print(UserAgent) - - match, err := regexp.MatchString("^curl/.*", UserAgent) - if err != nil { - log.Fatal(err) - } - - if match { - return c.String(http.StatusOK, fileUrl) - } - - return c.HTML(http.StatusOK, "File uploaded at url: "+fileUrl+"") -} - -func Delete(c echo.Context) error { - file := c.Param("file") - filePath := "files/" + file - - if _, err := os.Stat(filePath); err != nil { - return c.String(http.StatusOK, "That file doesn't exist on the server\n") - } - - err := os.Remove(filePath) - if err != nil { - return c.String(http.StatusOK, "Error while deleting "+file+"\n") - } - return c.String(http.StatusOK, "Deleted file from server\n") + StartServer() } diff --git a/misc.go b/misc.go new file mode 100644 index 0000000..da0df69 --- /dev/null +++ b/misc.go @@ -0,0 +1,34 @@ +package main + +import ( + "errors" + "log" + "net/http" + "os" +) + +// Miscelaneous functions + +// Create directory if it doesn't exist +func CreateDirIfNotExisting(d string) { + if _, err := os.Stat(d); errors.Is(err, os.ErrNotExist) { + err := os.Mkdir(d, os.ModePerm) + if err != nil { + log.Println(err) + } + } +} + +// Get the file content type +func GetFileContentType(ouput *os.File) (string, error) { + buf := make([]byte, 512) + + _, err := ouput.Read(buf) + if err != nil { + return "", err + } + + contentType := http.DetectContentType(buf) + + return contentType, nil +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..ff43ba9 --- /dev/null +++ b/server.go @@ -0,0 +1,73 @@ +package main + +import ( + "embed" + "flag" + "html/template" + "io" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +type Template struct { + templates *template.Template +} + +func (t *Template) Render(w io.Writer, name string, data any, c echo.Context) error { + return t.templates.ExecuteTemplate(w, name, data) +} + +//go:embed all:public/views/*.html +var templates embed.FS + +//go:embed all:static/* +var static embed.FS + +// domain of the website +var domain string + +func StartServer() { + t := &Template{ + templates: template.Must(template.ParseFS(templates, "public/views/*.html")), + } + + p := flag.Int("p", 1323, "upfast port to listen on.") + a := flag.String("a", "127.0.0.1", "upfast ip to listen to") + d := flag.String("d", "127.0.0.1", "upfast domain") + flag.Parse() + + host := *a + ":" + strconv.Itoa(*p) + + domain = *d + + e := echo.New() + + e.Renderer = t + e.Use(middleware.Logger()) + + e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ + Root: "static", + Browse: false, + HTML5: true, + Filesystem: http.FS(static), + })) + + files := "files" + + CreateDirIfNotExisting(files) + + e.Static("/files", files) + + e.GET("/", Index) + + e.POST("/", Upload) + + e.GET("/files/", Files) + + e.DELETE("/files/:file", Delete) + + e.Logger.Fatal(e.Start(host)) +} diff --git a/upload.go b/upload.go new file mode 100644 index 0000000..96df539 --- /dev/null +++ b/upload.go @@ -0,0 +1,53 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "io" + "log" + "net/http" + "os" + "regexp" +) + +func Upload(c echo.Context) error { + file, err := c.FormFile("file") + if err != nil { + return err + } + + if _, err := os.Stat("files/" + file.Filename); err == nil { + return c.String(http.StatusOK, "A file with the same name already exist's on the server.\n") + } + + src, err := file.Open() + if err != nil { + return err + } + + dst, err := os.Create("files/" + file.Filename) + if err != nil { + return err + } + defer dst.Close() + + if _, err = io.Copy(dst, src); err != nil { + return err + } + + fileUrl := domain + "/files/" + file.Filename + "\n" + + UserAgent := c.Request().UserAgent() + + log.Print(UserAgent) + + match, err := regexp.MatchString("^curl/.*", UserAgent) + if err != nil { + log.Fatal(err) + } + + if match { + return c.String(http.StatusOK, fileUrl) + } + + return c.HTML(http.StatusOK, "File uploaded at url: "+fileUrl+"") +}