leech/route/route.go

135 lines
3.5 KiB
Go

package route
import (
"errors"
"leech/config"
"leech/html"
"leech/thumbnail"
"net/url"
"os"
"path"
"sort"
"strings"
"github.com/gofiber/fiber/v2"
)
func RecursivelyGetSize(completePath string) (int64, error) {
files, err := os.ReadDir(completePath)
if err != nil {
return -1, err
}
var sum int64
for _, f := range files {
dirEntryInfo, err := f.Info()
if err != nil {
return -1, err
}
dirEntrySize := dirEntryInfo.Size()
if f.IsDir() {
dirEntrySize, err = RecursivelyGetSize(path.Join(completePath, f.Name()))
if err != nil {
return -1, err
}
}
sum += dirEntrySize
}
return sum, nil
}
func HandleList(c *fiber.Ctx) error {
encodedReq := c.Path()[1:]
req, err := url.QueryUnescape(encodedReq)
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
if req == "" {
keys := make([]string, 0, len(config.Config.ServeDirs))
for k := range config.Config.ServeDirs {
keys = append(keys, k)
}
sort.Strings(keys)
entries := make([]html.Entry, 0, len(config.Config.ServeDirs))
for _, key := range keys {
dirEntrySize, err := RecursivelyGetSize(config.Config.ServeDirs[key])
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
entries = append(entries, html.Entry{
Name: key,
Size: dirEntrySize,
IsDir: true,
})
}
return c.SendString(html.FileListPage(req, entries))
} else {
pathSlice := strings.Split(req, "/")
pathBase, ok := config.Config.ServeDirs[pathSlice[0]]
if ok {
pathSlice[0] = pathBase
completePath := path.Join(pathSlice...)
files, err := os.ReadDir(completePath)
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
entries := []html.Entry{}
for _, f := range files {
dirEntryInfo, err := f.Info()
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString("Internal server error!")
}
dirEntrySize := dirEntryInfo.Size()
if f.IsDir() {
dirEntrySize, err = RecursivelyGetSize(path.Join(completePath, f.Name()))
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
}
entries = append(entries, html.Entry{
Name: f.Name(),
Size: dirEntrySize,
IsDir: f.IsDir(),
})
}
return c.SendString(html.FileListPage(req, entries))
} else {
return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
}
}
}
func HandleThumb(c *fiber.Ctx) error {
encodedReq := c.Path()[1:]
req, err := url.QueryUnescape(encodedReq)
if err != nil {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
}
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
pathSlice := strings.Split(req, "/")
pathSlice = pathSlice[1:]
pathBase, ok := config.Config.ServeDirs[pathSlice[0]]
if ok {
pathSlice[0] = pathBase
completePath := path.Join(pathSlice...)
if file_info, err := os.Stat(completePath); err == nil {
if file_info.IsDir() {
return c.Status(fiber.StatusUnauthorized).SendString("Sorry that's a directory!")
}
thumbnail.GetThumbnail(c, completePath)
} else if errors.Is(err, os.ErrNotExist) {
return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
} /* else {
// Schrodinger: file may or may not exist. See err for details.
// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
} */
} else {
return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
}
return nil
}