From de29fceba21bf0b146b172101ce314e9b7adee1d Mon Sep 17 00:00:00 2001 From: hgc Date: Fri, 30 Sep 2022 19:58:29 +0930 Subject: [PATCH] add expiry mechanism --- go.mod | 1 + go.sum | 2 ++ index.html | 87 +++++++++++++++++++++++++++++++++++++++++------------- main.go | 64 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 130 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 91317e6..8cabda9 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.tcp.direct/hgc/filehole go 1.19 require ( + github.com/boltdb/bolt v1.3.1 github.com/gabriel-vasile/mimetype v1.4.1 github.com/gorilla/mux v1.8.0 github.com/rs/zerolog v1.28.0 diff --git a/go.sum b/go.sum index c875fa1..6f809d5 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q= github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M= diff --git a/index.html b/index.html index ec2c8e7..d04ff7b 100644 --- a/index.html +++ b/index.html @@ -1,29 +1,74 @@ + Filehole + -

Filehole

-
- -
- -
-
- - -
-
-
-

curl

-

-

curl -X POST -F 'file=@filehole.png' https://filehole.org
-

-

-

curl -X POST -F 'file=@filehole.png' -F "url_len=5" -F "expiry=86400" https://filehole.org
-

-

Firefox

- POST Image by rj1 +
+

Filehole

+
+ +
+ +
+ + +
+
+

How to put your files in the hole

+

curl

+

curl -X POST -F 'file=@filehole.png' https://filehole.org

+

curl -X POST -F 'file=@filehole.png' -F "url_len=5" -F "expiry=86400" https://filehole.org

+

Firefox

+ POST Image by rj1 +

Mac OS

+ Filehole.org-Mac by AndroidKitKat* +

*not actually tested or endorsed because I will never own a Mac

+
diff --git a/main.go b/main.go index 34b0cff..2a4ac03 100644 --- a/main.go +++ b/main.go @@ -6,16 +6,19 @@ import ( "net/http" "os" "strconv" + "time" "github.com/gabriel-vasile/mimetype" "github.com/gorilla/mux" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + + "github.com/boltdb/bolt" ) func shortID(length int64) string { - const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789" ll := len(chars) b := make([]byte, length) rand.Read(b) // generates len(b) random bytes @@ -25,6 +28,8 @@ func shortID(length int64) string { return string(b) } +var db *bolt.DB + func UploadHandler(w http.ResponseWriter, r *http.Request) { // url_len sanitize inpUrlLen := r.FormValue("url_len") @@ -32,8 +37,8 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) { if err != nil { sanUrlLen = 24 } - if sanUrlLen < 5 || sanUrlLen > 64 { - w.Write([]byte("url_len needs to be between 5 and 64\n")) + if sanUrlLen < 5 || sanUrlLen > 169 { + w.Write([]byte("url_len needs to be between 5 and 169\n")) return } @@ -66,6 +71,15 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) { // ready for upload name := shortID(sanUrlLen) + mtype.Extension() + err = db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("expiry")) + err := b.Put([]byte(name), []byte(strconv.FormatInt(time.Now().Unix()+sanExpiry, 10))) + return err + }) + if err != nil { + log.Error().Err(err).Msg("Failed to put expiry") + } + log.Info().Str("mtype", mtype.String()).Str("ext", mtype.Extension()).Int64("expiry", sanExpiry).Int64("url_len", sanUrlLen).Msg("Writing new file") f, err := os.OpenFile("data/"+name, os.O_WRONLY|os.O_CREATE, 0644) @@ -81,9 +95,50 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("https://u.filehole.org/" + name + "\n")) } +func ExpiryDoer() { + for { + removed := 0 + db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("expiry")) + c := b.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + expiryTime, err := strconv.ParseInt(string(v), 10, 64) + if err != nil { + log.Error().Err(err).Bytes("k", k).Bytes("v", v).Msg("Expiry time could not be parsed") + continue + } + if time.Now().After(time.Unix(expiryTime, 0)) { + os.Remove("data/" + string(k)) + removed += 1 + c.Delete() + } + } + return nil + }) + if removed >= 1 { + log.Info().Int("amt", removed).Msg("Purged based on expiry") + } + time.Sleep(5 * time.Second) + } +} + func main() { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + var err error + db, err = bolt.Open("filehole.db", 0600, nil) + if err != nil { + log.Fatal().Err(err).Msg("dangerous database activity") + } + db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucketIfNotExists([]byte("expiry")) + if err != nil { + log.Fatal().Err(err).Msg("Error creating expiry bucket") + return err + } + return nil + }) + r := mux.NewRouter() r.HandleFunc("/", UploadHandler).Methods("POST") r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { @@ -91,5 +146,8 @@ func main() { }).Methods("GET") http.Handle("/", r) + go ExpiryDoer() http.ListenAndServe("127.0.0.1:8000", r) + + db.Close() }