first commit
This commit is contained in:
137
filesystem/filesystem.go
Normal file
137
filesystem/filesystem.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.0x0001f346.de/andreas/ablage/config"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
err := prepareDataFolder()
|
||||
if err != nil {
|
||||
fmt.Println("err")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = prepareUploadDir()
|
||||
if err != nil {
|
||||
fmt.Println("err")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func GetHumanReadableSize(bytes int64) string {
|
||||
const unit int64 = 1024
|
||||
|
||||
if bytes < unit {
|
||||
return fmt.Sprintf("%d Bytes", bytes)
|
||||
}
|
||||
|
||||
div, exp := int64(unit), 0
|
||||
|
||||
for n := bytes / unit; n >= unit; n /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
|
||||
}
|
||||
|
||||
func SanitizeFilename(dirtyFilename string) string {
|
||||
if dirtyFilename == "" {
|
||||
return "upload.bin"
|
||||
}
|
||||
|
||||
filenameWithoutPath := filepath.Base(dirtyFilename)
|
||||
|
||||
extension := filepath.Ext(filenameWithoutPath)
|
||||
filenameWithoutPathAndExtension := filenameWithoutPath[:len(filenameWithoutPath)-len(extension)]
|
||||
|
||||
cleanedFilename := strings.ReplaceAll(filenameWithoutPathAndExtension, " ", "_")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "Ä", "Ae")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "ä", "äe")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "Ö", "Oe")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "ö", "oe")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "Ü", "Ue")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "ü", "ue")
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "ß", "ss")
|
||||
|
||||
var safeNameRegex = regexp.MustCompile(`[^a-zA-Z0-9._-]+`)
|
||||
cleanedFilename = safeNameRegex.ReplaceAllString(cleanedFilename, "_")
|
||||
|
||||
for strings.Contains(cleanedFilename, "__") {
|
||||
cleanedFilename = strings.ReplaceAll(cleanedFilename, "__", "_")
|
||||
}
|
||||
|
||||
cleanedFilename = strings.Trim(cleanedFilename, "_")
|
||||
|
||||
const maxLenFilename int = 128
|
||||
if len(cleanedFilename) > maxLenFilename {
|
||||
cleanedFilename = cleanedFilename[:maxLenFilename]
|
||||
}
|
||||
|
||||
return cleanedFilename + extension
|
||||
}
|
||||
|
||||
func prepareDataFolder() error {
|
||||
info, err := os.Stat(config.GetPathDataFolder())
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.Mkdir(config.GetPathDataFolder(), 0755); err != nil {
|
||||
return fmt.Errorf("Error: Could not create folder '%s': %v", config.GetPathDataFolder(), err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("Error: Could not access '%s': %v", config.GetPathDataFolder(), err)
|
||||
} else if !info.IsDir() {
|
||||
return fmt.Errorf("Error: '%s' exists but is not a directory", config.GetPathDataFolder())
|
||||
}
|
||||
|
||||
pathTestFile := filepath.Join(config.GetPathDataFolder(), ".write_test")
|
||||
err = os.WriteFile(pathTestFile, []byte("test"), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: Could not create test file '%s': %v", pathTestFile, err)
|
||||
}
|
||||
|
||||
err = os.Remove(pathTestFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: Could not delete test file '%s': %v", pathTestFile, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareUploadDir() error {
|
||||
info, err := os.Stat(config.GetPathUploadFolder())
|
||||
if err == nil {
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("%s exists, but is not a folder", config.GetPathUploadFolder())
|
||||
}
|
||||
|
||||
err = os.RemoveAll(config.GetPathUploadFolder())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: Could not delete upload folder '%s': %v", config.GetPathUploadFolder(), err)
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("Error: '%s' exists but is somewhat broken", config.GetPathUploadFolder())
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(config.GetPathUploadFolder(), 0755); err != nil {
|
||||
return fmt.Errorf("Error: Could not create upload folder '%s': %v", config.GetPathUploadFolder(), err)
|
||||
}
|
||||
|
||||
pathTestFile := filepath.Join(config.GetPathUploadFolder(), ".write_test")
|
||||
err = os.WriteFile(pathTestFile, []byte("test"), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: Could not create test file '%s': %v", pathTestFile, err)
|
||||
}
|
||||
|
||||
err = os.Remove(pathTestFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: Could not delete test file '%s': %v", pathTestFile, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
113
filesystem/filesystem_test.go
Normal file
113
filesystem/filesystem_test.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_sanitizeFilename(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "1",
|
||||
input: "test.png",
|
||||
want: "test.png",
|
||||
},
|
||||
{
|
||||
name: "2",
|
||||
input: "/tmp/test.png",
|
||||
want: "test.png",
|
||||
},
|
||||
{
|
||||
name: "3",
|
||||
input: "../../etc/passwd",
|
||||
want: "passwd",
|
||||
},
|
||||
{
|
||||
name: "4",
|
||||
input: "",
|
||||
want: "upload.bin",
|
||||
},
|
||||
{
|
||||
name: "5",
|
||||
input: "übergrößé.png",
|
||||
want: "uebergroess.png",
|
||||
},
|
||||
{
|
||||
name: "6",
|
||||
input: "my cool file!!.txt",
|
||||
want: "my_cool_file.txt",
|
||||
},
|
||||
{
|
||||
name: "7",
|
||||
input: "so many spaces.txt",
|
||||
want: "so_many_spaces.txt",
|
||||
},
|
||||
{
|
||||
name: "8",
|
||||
input: "/tmp/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.txt",
|
||||
want: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx.txt",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := SanitizeFilename(tt.input); got != tt.want {
|
||||
t.Errorf("\nsanitizeFilename()\nname: %v\nwant: %v\ngot: %v", tt.name, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getHumanReadableSize(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input int64
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "1",
|
||||
input: 7,
|
||||
want: "7 Bytes",
|
||||
},
|
||||
{
|
||||
name: "2",
|
||||
input: 7 * int64(math.Pow(10, 3)),
|
||||
want: "6.8 KB",
|
||||
},
|
||||
{
|
||||
name: "3",
|
||||
input: 7 * int64(math.Pow(10, 6)),
|
||||
want: "6.7 MB",
|
||||
},
|
||||
{
|
||||
name: "4",
|
||||
input: 7 * int64(math.Pow(10, 9)),
|
||||
want: "6.5 GB",
|
||||
},
|
||||
{
|
||||
name: "5",
|
||||
input: 7 * int64(math.Pow(10, 12)),
|
||||
want: "6.4 TB",
|
||||
},
|
||||
{
|
||||
name: "6",
|
||||
input: 7 * int64(math.Pow(10, 15)),
|
||||
want: "6.2 PB",
|
||||
},
|
||||
{
|
||||
name: "7",
|
||||
input: 7 * int64(math.Pow(10, 18)),
|
||||
want: "6.1 EB",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GetHumanReadableSize(tt.input); got != tt.want {
|
||||
t.Errorf("\ngetHumanReadableSize()\nname: %v\nwant: %v\ngot: %v", tt.name, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user