Initial commit

This commit is contained in:
hgc 2022-09-17 17:02:40 +09:30
commit d66cf13471
6 changed files with 180 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
filehole
data/

14
filehole.service Normal file
View File

@ -0,0 +1,14 @@
[Unit]
Description=Filehole
After=network.target
[Service]
ExecStart=/usr/local/bin/filehole
WorkingDirectory=/home/filehole
User=filehole
Group=filehole
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.target

16
go.mod Normal file
View File

@ -0,0 +1,16 @@
module git.tcp.direct/hgc/filehole
go 1.19
require (
github.com/gabriel-vasile/mimetype v1.4.1
github.com/gorilla/mux v1.8.0
github.com/rs/zerolog v1.28.0
)
require (
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
)

24
go.sum Normal file
View File

@ -0,0 +1,24 @@
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=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

29
index.html Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Filehole</title>
</head>
<body>
<h1>Filehole</h1>
<form method="POST" enctype="multipart/form-data">
<label for="url_len">URL Length (5-69)</label>
<input type="number" name="url_len" id="url_len" min=5 max=69 value=24></input><br>
<label for="expiry">Expiry (slider is 1d-5d)</label>
<input type="range" name="expiry" id="expiry" min=86400 max=432000 step=86400 value=86400></input><br>
<br>
<input type="file" name="file"></input>
<input type="submit"></input>
</form>
<br>
<hr>
<h2>curl</h2>
<p>
<pre>curl -X POST -F 'file=@filehole.png' https://filehole.org</pre>
</p>
<p>
<pre>curl -X POST -F 'file=@filehole.png' -F "url_len=5" -F "expiry=86400" https://filehole.org</pre>
</p>
<h2>Firefox</h2>
<a href="https://addons.mozilla.org/en-US/firefox/addon/post-image/">POST Image by rj1</a>
</body>
</html>

95
main.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
"crypto/rand"
"io"
"net/http"
"os"
"strconv"
"github.com/gabriel-vasile/mimetype"
"github.com/gorilla/mux"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func shortID(length int64) string {
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
ll := len(chars)
b := make([]byte, length)
rand.Read(b) // generates len(b) random bytes
for i := int64(0); i < length; i++ {
b[i] = chars[int(b[i])%ll]
}
return string(b)
}
func UploadHandler(w http.ResponseWriter, r *http.Request) {
// url_len sanitize
inpUrlLen := r.FormValue("url_len")
sanUrlLen, err := strconv.ParseInt(inpUrlLen, 10, 64)
if err != nil {
sanUrlLen = 24
}
if sanUrlLen < 5 || sanUrlLen > 64 {
w.Write([]byte("url_len needs to be between 5 and 64\n"))
return
}
// expiry sanitize
inpExpiry := r.FormValue("expiry")
sanExpiry, err := strconv.ParseInt(inpExpiry, 10, 64)
if err != nil {
sanExpiry = 86400
}
if sanExpiry < 5 || sanExpiry > 432000 {
w.Write([]byte("expiry needs to be between 5 and 432000\n"))
return
}
// mimetype check
file, _, err := r.FormFile("file")
if err != nil {
w.Write([]byte("error reading your file parameter\n"))
return
}
defer file.Close()
mtype, err := mimetype.DetectReader(file)
if err != nil {
w.Write([]byte("error detecting the mime type of your file\n"))
return
}
file.Seek(0, 0)
// ready for upload
name := shortID(sanUrlLen) + mtype.Extension()
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)
if err != nil {
log.Error().Err(err).Msg("Error opening a file for write")
w.Write([]byte("internal error\n"))
return
}
defer f.Close()
io.Copy(f, file)
w.Write([]byte("https://u.filehole.org/" + name + "\n"))
}
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
r := mux.NewRouter()
r.HandleFunc("/", UploadHandler).Methods("POST")
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
}).Methods("GET")
http.Handle("/", r)
http.ListenAndServe("127.0.0.1:8000", r)
}