code revamp, missing dir/db fault tolerance, frontend changes, misc cleanup

This commit is contained in:
delorean 2023-12-12 13:42:00 -06:00
parent 979c7e34d4
commit f15f9de04a
5 changed files with 70 additions and 46 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
files/
*.db

View File

@ -4,4 +4,4 @@ vhost = "hardfiles.org"
dbfile = "dbfile.db"
filelen = 6
folder = "files"
fileexpiry = 86400
ttl_seconds = 86400

82
main.go
View File

@ -29,7 +29,7 @@ type Config struct {
DBFile string `toml:"dbfile"`
FileLen int `toml:"filelen"`
FileFolder string `toml:"folder"`
FileExpirySeconds int `toml:"fileexpiry"`
TTLSeconds int `toml:"ttl_seconds"`
}
func LoadConf() {
@ -44,18 +44,15 @@ func Shred(path string) error {
return err
}
size := fileinfo.Size()
err = Scramble(path, size)
if err != nil {
if err = Scramble(path, size); err != nil {
return err
}
err = Zeros(path, size)
if err != nil {
if err = Zeros(path, size); err != nil {
return err
}
err = os.Remove(path)
if err != nil {
if err = os.Remove(path); err != nil {
return err
}
@ -100,7 +97,7 @@ func Zeros(path string, size int64) error {
}
func NameGen() string {
const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789"
const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789"
ll := len(chars)
b := make([]byte, conf.FileLen)
rand.Read(b) // generates len(b) random bytes
@ -110,6 +107,24 @@ func NameGen() string {
return string(b)
}
func CheckFolder(path string) {
if _, err := os.Stat(path); os.IsNotExist(err) {
err := os.Mkdir(path, 0755)
if err != nil {
log.Fatal().Err(err).Msg("unable to create folder")
}
}
}
func CheckDB(path string) {
if _, err := os.Stat(path); os.IsNotExist(err) {
_, err := os.Create(path)
if err != nil {
log.Fatal().Err(err).Msg("unable to create database file")
}
}
}
func CheckFile(name string) bool { // false if doesn't exist, true if exists
tfd, err := os.Open(conf.FileFolder + "/" + name)
if err != nil {
@ -120,8 +135,8 @@ func CheckFile(name string) bool { // false if doesn't exist, true if exists
}
func UploadHandler(w http.ResponseWriter, r *http.Request) {
// expiry sanitize
twentyfour := int64(conf.FileExpirySeconds)
// expiry time
ttl := int64(conf.TTLSeconds)
file, _, err := r.FormFile("file")
if err != nil {
@ -149,31 +164,33 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
err = db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("expiry"))
err := b.Put([]byte(name), []byte(strconv.FormatInt(time.Now().Unix()+twentyfour, 10)))
err := b.Put([]byte(name), []byte(strconv.FormatInt(time.Now().Unix()+ttl, 10)))
return err
})
if err != nil {
log.Error().Err(err).Msg("Failed to put expiry")
log.Error().Err(err).Msg("failed to put expiry")
}
log.Info().Int64("expiry", twentyfour).Msg("Writing new file")
f, err := os.OpenFile(conf.FileFolder+"/"+name, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Error().Err(err).Msg("Error opening a file for write")
log.Error().Err(err).Msg("error opening a file for write")
w.WriteHeader(http.StatusInternalServerError) // change to json
return
}
defer f.Close()
io.Copy(f, file)
log.Info().Str("name", name).Int64("ttl", ttl).Msg("wrote new file")
w.Write([]byte("https://" + conf.VHost + "/uploads/" + name))
hostedurl := "https://" + conf.VHost + "/uploads/" + name
w.Header().Set("Location", hostedurl)
w.WriteHeader(http.StatusSeeOther)
w.Write([]byte(hostedurl))
}
func Cull() {
for {
removed := 0
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("expiry"))
c := b.Cursor()
@ -187,16 +204,13 @@ func Cull() {
if err := Shred(conf.FileFolder + "/" + string(k)); err != nil {
log.Error().Err(err).Msg("shredding failed")
} else {
removed += 1
log.Info().Str("name", string(k)).Msg("shredded file")
}
c.Delete()
}
}
return nil
})
if removed >= 1 {
log.Info().Int("amount", removed).Msg("shredded")
}
time.Sleep(5 * time.Second)
}
}
@ -205,6 +219,9 @@ func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
LoadConf()
CheckFolder(conf.FileFolder)
CheckDB(conf.DBFile)
err := landlock.V2.BestEffort().RestrictPaths(
landlock.RWDirs(conf.FileFolder),
landlock.RWDirs(conf.Webroot),
@ -217,9 +234,9 @@ func main() {
_, err = os.Open("/etc/passwd")
if err == nil {
log.Warn().Msg("landlock failed, could open /etc/passwd")
log.Warn().Msg("landlock failed, could open /etc/passwd, are you on a 5.13+ kernel?")
} else {
log.Info().Err(err).Msg("Landlocked")
log.Info().Err(err).Msg("landlocked")
}
db, err = bolt.Open(conf.DBFile, 0600, nil)
@ -241,21 +258,21 @@ func main() {
vars := mux.Vars(r)
if !CheckFile(vars["name"]) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("file not found"))
} else {
http.ServeFile(w, r, conf.FileFolder+"/"+vars["name"])
}
}).Methods("GET")
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, conf.Webroot+"/index.html")
}).Methods("GET")
r.HandleFunc("/index.html", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, conf.Webroot+"/index.html")
}).Methods("GET")
r.HandleFunc("/fist.ico", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, conf.Webroot+"/fist.ico")
}).Methods("GET")
r.HandleFunc("/header.png", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, conf.Webroot+"/header.png")
})
r.HandleFunc("/{file}", func(w http.ResponseWriter, r *http.Request) {
file := mux.Vars(r)["file"]
if _, err := os.Stat(conf.Webroot + "/" + file); os.IsNotExist(err) {
http.Redirect(w, r, "/", http.StatusSeeOther)
} else {
http.ServeFile(w, r, conf.Webroot+"/"+file)
}
}).Methods("GET")
http.Handle("/", r)
@ -268,6 +285,7 @@ func main() {
IdleTimeout: 20 * time.Second,
}
log.Warn().Msg("shredding is only effective on HDD volumes")
log.Info().Err(err).Msg("listening on port " + conf.LPort + "...")
if err := serv.ListenAndServe(); err != nil {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -1,12 +1,9 @@
<!DOCTYPE html>
<html>
<html style="overflow: hidden;">
<head>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="fist.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Black+Ops+One&display=swap" rel="stylesheet">
<title>HARDFILES</title>
<style>
body {
@ -16,6 +13,7 @@
}
@media (prefers-color-scheme: dark) {
body {
overflow: hidden;
background: black;
background-image: url('https://media.tenor.com/fYnd0R6F-0UAAAAC/gun-revolver.gif');
background-size: cover;
@ -122,7 +120,6 @@
<body>
<div class="container">
<img src="header.png" width="50%" alt="supernets" style="margin-top: 10rem;">
<!-- <h1 class="hf" style=" color: #660000; font-weight: 800; font-family: 'Black Ops One', cursive; margin-bottom: 0 !important; margin-top: 5rem !important;">HARDFILES</h1> -->
<h2 style="font-size: 1em; color: #ffffff; font-weight: 200;">curl -F file=@example.png https://hardfiles.org/</h1>
<form method="POST" class="subform" enctype="multipart/form-data">
<div class="file-upload" style="display: flex; justify-content: center; width: 25rem;">
@ -135,6 +132,14 @@
</div>
</form>
<p style="color: white; font-weight: 300;">⚠️ Uploads are erased after 24 hours</p>
</div>
<div style="position: relative;">
<a href="https://supernets.org/" target="_blank" style="position: absolute; bottom: 10px; right:10px; display: flex; align-items: center; text-decoration: none;">
<p style="font-weight:200; color:#ffffff">A SUPERNETS</p>
<img src="https://git.supernets.org/assets/img/logo.png" width="30px" style="margin: 0 5px;">
<p style="font-weight:200; color: #ffffff">SERVICE</p>
</a>
</div>
</body>
</html>