hardfiles

- Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.acid.vegas/-c.git
Log | Files | Refs | Archive | README | LICENSE

commit f15f9de04a60ffa895529edb2d0b4ff0cb3bac59
parent 979c7e34d45132c143534451a5df3b419a746ef3
Author: delorean <jackdelmar@protonmail.com>
Date: Tue, 12 Dec 2023 13:42:00 -0600

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

Diffstat:
M.gitignore | 5+++--
Mconfig.toml | 4++--
Mmain.go | 94+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mwww/header.png | 0
Mwww/index.html | 17+++++++++++------

5 files changed, 72 insertions(+), 48 deletions(-)

diff --git a/.gitignore b/.gitignore
@@ -1 +1,2 @@
-files/
-\ No newline at end of file
+files/
+*.db
+\ No newline at end of file
diff --git a/config.toml b/config.toml
@@ -4,4 +4,4 @@ vhost = "hardfiles.org"
 dbfile = "dbfile.db"
 filelen = 6
 folder = "files"
-fileexpiry = 86400
-\ No newline at end of file
+ttl_seconds = 86400
+\ No newline at end of file
diff --git a/main.go b/main.go
@@ -23,13 +23,13 @@ var (
 )
 
 type Config struct {
-	Webroot           string `toml:"webroot"`
-	LPort             string `toml:"lport"`
-	VHost             string `toml:"vhost"`
-	DBFile            string `toml:"dbfile"`
-	FileLen           int    `toml:"filelen"`
-	FileFolder        string `toml:"folder"`
-	FileExpirySeconds int    `toml:"fileexpiry"`
+	Webroot    string `toml:"webroot"`
+	LPort      string `toml:"lport"`
+	VHost      string `toml:"vhost"`
+	DBFile     string `toml:"dbfile"`
+	FileLen    int    `toml:"filelen"`
+	FileFolder string `toml:"folder"`
+	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")
+
+	hostedurl := "https://" + conf.VHost + "/uploads/" + name
 
-	w.Write([]byte("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 {
diff --git a/www/header.png b/www/header.png
Binary files differ.
diff --git a/www/index.html b/www/index.html
@@ -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"> 
+        <link rel="icon" href="fist.ico"> 
         <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>