Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
439b6bdee9 | |||
17a2b97d18 | |||
8e65053cc1 |
0
.dockerignore
Executable file → Normal file
3
.gitignore
vendored
Executable file → Normal file
@ -1,4 +1,3 @@
|
|||||||
files/
|
files/
|
||||||
*.db
|
*.db
|
||||||
hardfiles
|
hardfiles
|
||||||
todo
|
|
12
Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM golang:1.21-alpine as builder
|
||||||
|
WORKDIR /build
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
COPY *.go ./
|
||||||
|
RUN go build -o hardfiles main.go
|
||||||
|
|
||||||
|
FROM golang:1.21-alpine as app
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /build/hardfiles .
|
||||||
|
RUN mkdir files
|
||||||
|
CMD ["./hardfiles"]
|
0
config.toml
Executable file → Normal file
11
docker-compose.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
services:
|
||||||
|
hardfiles:
|
||||||
|
container_name: hardfiles
|
||||||
|
image: git.supernets.org/supernets/hardfiles:latest
|
||||||
|
build: .
|
||||||
|
volumes:
|
||||||
|
- "$PWD/files:/app/files"
|
||||||
|
- "$PWD/www:/app/www"
|
||||||
|
- "$PWD/config.toml:/app/config.toml"
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
2
go.mod
Executable file → Normal file
@ -12,8 +12,6 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/chroma/v2 v2.13.0 // indirect
|
|
||||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
|
4
go.sum
Executable file → Normal file
@ -1,12 +1,8 @@
|
|||||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
|
|
||||||
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
|
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
|
||||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
108
main.go
Executable file → Normal file
@ -6,8 +6,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
"compress/gzip"
|
||||||
|
"strings"
|
||||||
|
"bytes"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
@ -110,29 +112,76 @@ func Exists(path string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
func isValidGzipHeader(data []byte) bool {
|
||||||
var ttl int64 = 0 //expiration
|
return len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b
|
||||||
|
}
|
||||||
|
|
||||||
file, _, err := r.FormFile("file")
|
func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// expiry time
|
||||||
|
var ttl int64
|
||||||
|
|
||||||
|
ttl = 0
|
||||||
|
|
||||||
|
var file, header, err = r.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("empty file form field")
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
mtype, err := mimetype.DetectReader(file)
|
var buffer bytes.Buffer
|
||||||
if err != nil {
|
_, err = io.Copy(&buffer, file)
|
||||||
w.Write([]byte("error detecting the mime type of your file\n"))
|
if err != nil {
|
||||||
return
|
log.Error().Err(err).Msg("error reading file data")
|
||||||
}
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
file.Seek(0, 0)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var data bytes.Buffer
|
||||||
|
var name = header.Filename
|
||||||
|
println("file: " + name)
|
||||||
|
if strings.HasSuffix(name, ".5000") {
|
||||||
|
buffer.WriteTo(&data)
|
||||||
|
if isValidGzipHeader(data.Bytes()[:2]) {
|
||||||
|
gz, err := gzip.NewReader(&data)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error creating gzip reader")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer gz.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(&buffer, gz)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error decompressing gzip file")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name = strings.TrimSuffix(name, ".5000")
|
||||||
|
data.Write(buffer.Bytes())
|
||||||
|
} else {
|
||||||
|
log.Error().Msg("Invalid gzip file")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.Write(buffer.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
mtype, err := mimetype.DetectReader(&data)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error detecting MIME type")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if expiry time is present and length is too long
|
// Check if expiry time is present and length is too long
|
||||||
if r.PostFormValue("expiry") != "" {
|
if r.PostFormValue("expiry") != "" {
|
||||||
ttl, err = strconv.ParseInt(r.PostFormValue("expiry"), 10, 64)
|
ttl, err = strconv.ParseInt(r.PostFormValue("expiry"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("expiry could not be parsed")
|
log.Error().Err(err).Msg("expiry could not be parsed")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
} else {
|
} else {
|
||||||
// Get maximum ttl length from config and kill upload if specified ttl is too long, this can probably be handled better in the future
|
// Get maximum ttl length from config and kill upload if specified ttl is too long, this can probably be handled better in the future
|
||||||
if ttl < 1 || ttl > int64(conf.MaxTTL) {
|
if ttl < 1 || ttl > int64(conf.MaxTTL) {
|
||||||
@ -142,13 +191,12 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to conf if not present
|
// Default to conf if not present
|
||||||
if ttl == 0 {
|
if ttl == 0 {
|
||||||
ttl = int64(conf.DefaultTTL)
|
ttl = int64(conf.DefaultTTL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate + check name
|
// generate + check name
|
||||||
var name string
|
|
||||||
for {
|
for {
|
||||||
id := NameGen()
|
id := NameGen()
|
||||||
name = id + mtype.Extension()
|
name = id + mtype.Extension()
|
||||||
@ -166,24 +214,29 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Error().Err(err).Msg("failed to put expiry")
|
log.Error().Err(err).Msg("failed to put expiry")
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(conf.FileFolder+"/"+name, os.O_WRONLY|os.O_CREATE, 0644)
|
f, err := os.OpenFile(conf.FileFolder+"/"+name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
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
|
w.WriteHeader(http.StatusInternalServerError) // change to json
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
io.Copy(f, file)
|
io.Copy(f, &buffer)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error copying file")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
|
data.Reset()
|
||||||
log.Info().Str("name", name).Int64("ttl", ttl).Msg("wrote new file")
|
log.Info().Str("name", name).Int64("ttl", ttl).Msg("wrote new file")
|
||||||
|
|
||||||
hostedurl := "https://" + conf.VHost + "/uploads/" + name
|
hostedurl := "https://" + conf.VHost + "/uploads/" + name
|
||||||
|
|
||||||
if strings.Contains(name, "jpeg") || strings.Contains(name, "png") || strings.Contains(name, "jpg") || strings.Contains(name, "txt") || strings.Contains(name, "csv") || strings.Contains(name, "pdf") {
|
w.Header().Set("Location", hostedurl)
|
||||||
w.Header().Set("Location", hostedurl)
|
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusSeeOther)
|
w.WriteHeader(http.StatusSeeOther)
|
||||||
w.Write([]byte(hostedurl + "\n"))
|
w.Write([]byte(hostedurl))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Cull() {
|
func Cull() {
|
||||||
@ -230,13 +283,12 @@ func main() {
|
|||||||
if err = landlock.V2.BestEffort().RestrictPaths(
|
if err = landlock.V2.BestEffort().RestrictPaths(
|
||||||
landlock.RWDirs(conf.FileFolder),
|
landlock.RWDirs(conf.FileFolder),
|
||||||
landlock.RWDirs(conf.Webroot),
|
landlock.RWDirs(conf.Webroot),
|
||||||
// landlock.RWDirs("/tmp"),
|
|
||||||
landlock.RWFiles(conf.DBFile),
|
landlock.RWFiles(conf.DBFile),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Warn().Err(err).Msg("could not landlock")
|
log.Warn().Err(err).Msg("could not landlock")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = os.Open("/etc/passwd"); err == nil {
|
if _, err = os.Open("/etc/passwd"); err != nil {
|
||||||
log.Warn().Msg("landlock failed, could open /etc/passwd, are you on a 5.13+ kernel?")
|
log.Warn().Msg("landlock failed, could open /etc/passwd, are you on a 5.13+ kernel?")
|
||||||
} else {
|
} else {
|
||||||
log.Info().Err(err).Msg("landlocked")
|
log.Info().Err(err).Msg("landlocked")
|
||||||
@ -281,12 +333,10 @@ func main() {
|
|||||||
go Cull()
|
go Cull()
|
||||||
|
|
||||||
serv := &http.Server{
|
serv := &http.Server{
|
||||||
Addr: ":" + conf.LPort,
|
Addr: ":" + conf.LPort,
|
||||||
Handler: r,
|
Handler: r,
|
||||||
ErrorLog: nil,
|
ErrorLog: nil,
|
||||||
IdleTimeout: 60 * time.Second,
|
IdleTimeout: 20 * time.Second,
|
||||||
ReadTimeout: 600 * time.Second,
|
|
||||||
WriteTimeout: 600 * time.Second,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warn().Msg("shredding is only effective on HDD volumes")
|
log.Warn().Msg("shredding is only effective on HDD volumes")
|
||||||
|
Before Width: | Height: | Size: 290 KiB |
0
www/fist.ico
Executable file → Normal file
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
0
www/header.png
Executable file → Normal file
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
326
www/index.html
Executable file → Normal file
@ -1,109 +1,29 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html style="overflow: hidden;">
|
<html style="overflow: hidden;">
|
||||||
<head>
|
<head>
|
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.4/pako_deflate.min.js"></script>
|
||||||
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
|
<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">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="The Hardest file hosting solution, creating by the Hardest people online."/>
|
|
||||||
<link rel="icon" href="fist.ico">
|
<link rel="icon" href="fist.ico">
|
||||||
<title>HARDFILES</title>
|
<title>HARDFILES</title>
|
||||||
|
|
||||||
<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=Rajdhani:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@keyframes rainbowbtn {
|
body {
|
||||||
0%{background-color: lime;}
|
font-family: sans-serif;
|
||||||
10%{background-color: red;}
|
background-image: url('https://media.tenor.com/fYnd0R6F-0UAAAAC/gun-revolver.gif');
|
||||||
20%{background-color: purple;}
|
background-size: cover;
|
||||||
30%{background-color: hotpink;}
|
background-position: center;
|
||||||
40%{background-color: orange;}
|
|
||||||
50%{background-color: yellow;}
|
|
||||||
60%{background-color: turquoise;}
|
|
||||||
70%{background-color: aqua;}
|
|
||||||
80%{background-color: cyan;}
|
|
||||||
90%{background-color: blue;}
|
|
||||||
100%{background-color: lime;}
|
|
||||||
}
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
@keyframes rainbowbox {
|
|
||||||
0%{color: lime; border: 1px dashed lime;}
|
|
||||||
10%{color: red; border: 1px dashed red;}
|
|
||||||
20%{color: purple; border: 1px dashed purple;}
|
|
||||||
30%{color: hotpink; border: 1px dashed hotpink;}
|
|
||||||
40%{color: orange; border: 1px dashed orange;}
|
|
||||||
50%{color: yellow; border: 1px dashed yellow;}
|
|
||||||
60%{color: turquoise; border: 1px dashed turquoise;}
|
|
||||||
70%{color: aqua; border: 1px dashed aqua;}
|
|
||||||
80%{color: cyan; border: 1px dashed cyan;}
|
|
||||||
90%{color: blue; border: 1px dashed blue;}
|
|
||||||
100%{color: lime; border: 1px dashed lime;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: black;
|
background: black;
|
||||||
background-image: url('revolver.gif');
|
background-image: url('https://media.tenor.com/fYnd0R6F-0UAAAAC/gun-revolver.gif');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.container {
|
||||||
@media (min-width: 768px) {
|
|
||||||
body {
|
|
||||||
background-image: url('delirious.gif') !important;
|
|
||||||
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
width: 750px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hf {
|
|
||||||
font-size: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hflogo {
|
|
||||||
width: 50% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#fupload {
|
|
||||||
width: 20rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subform {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.container {
|
|
||||||
width: 970px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
.container {
|
|
||||||
width: 1170px;
|
|
||||||
}
|
|
||||||
.hf {
|
|
||||||
font-size: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#curl {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
background-image: url('pentagram.gif');
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
@ -114,14 +34,142 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
.subform {
|
.container {
|
||||||
|
width: 750px;
|
||||||
|
}
|
||||||
|
.hf {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hflogo {
|
||||||
|
width: 50% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.container {
|
||||||
|
width: 970px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.container {
|
||||||
|
width: 1170px;
|
||||||
|
}
|
||||||
|
.hf {
|
||||||
|
font-size: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input,select {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.file-upload{
|
||||||
|
display:block;
|
||||||
|
text-align:center;
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.file-upload .file-select{
|
||||||
|
display:block;
|
||||||
|
border: 2px solid #dce4ec;
|
||||||
|
color: black;
|
||||||
|
cursor:pointer;
|
||||||
|
height:40px;
|
||||||
|
line-height:40px;
|
||||||
|
text-align:left;
|
||||||
|
background:#FFFFFF;
|
||||||
|
overflow:hidden;
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
.file-upload .file-select .file-select-button{
|
||||||
|
background:#dce4ec;
|
||||||
|
padding:0 10px;
|
||||||
|
display:inline-block;
|
||||||
|
height:40px;
|
||||||
|
line-height:40px;
|
||||||
|
}
|
||||||
|
.file-upload .file-select .file-select-name{
|
||||||
|
line-height:40px;
|
||||||
|
display:inline-block;
|
||||||
|
padding:0 10px;
|
||||||
|
}
|
||||||
|
.file-upload .file-select:hover{
|
||||||
|
border-color:red;
|
||||||
|
transition:all .2s ease-in-out;
|
||||||
|
-moz-transition:all .2s ease-in-out;
|
||||||
|
-webkit-transition:all .2s ease-in-out;
|
||||||
|
-o-transition:all .2s ease-in-out;
|
||||||
|
}
|
||||||
|
.file-upload .file-select:hover .file-select-button{
|
||||||
|
background:red;
|
||||||
|
color:#FFFFFF;
|
||||||
|
transition:all .2s ease-in-out;
|
||||||
|
-moz-transition:all .2s ease-in-out;
|
||||||
|
-webkit-transition:all .2s ease-in-out;
|
||||||
|
-o-transition:all .2s ease-in-out;
|
||||||
|
}
|
||||||
|
.file-upload.active .file-select{
|
||||||
|
border-color:red;
|
||||||
|
transition:all .2s ease-in-out;
|
||||||
|
-moz-transition:all .2s ease-in-out;
|
||||||
|
-webkit-transition:all .2s ease-in-out;
|
||||||
|
-o-transition:all .2s ease-in-out;
|
||||||
|
}
|
||||||
|
.file-upload.active .file-select .file-select-button{
|
||||||
|
background:red;
|
||||||
|
color:#FFFFFF;
|
||||||
|
transition:all .2s ease-in-out;
|
||||||
|
-moz-transition:all .2s ease-in-out;
|
||||||
|
-webkit-transition:all .2s ease-in-out;
|
||||||
|
-o-transition:all .2s ease-in-out;
|
||||||
|
}
|
||||||
|
.file-upload .file-select input[type=file]{
|
||||||
|
z-index:100;
|
||||||
|
cursor:pointer;
|
||||||
|
position:absolute;
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
top:0;
|
||||||
|
left:0;
|
||||||
|
opacity:0;
|
||||||
|
filter:alpha(opacity=0);
|
||||||
|
}
|
||||||
|
.file-upload .file-select.file-select-disabled{
|
||||||
|
opacity:0.65;
|
||||||
|
}
|
||||||
|
.file-upload .file-select.file-select-disabled:hover{
|
||||||
|
cursor:default;
|
||||||
|
display:block;
|
||||||
|
border: 2px solid #dce4ec;
|
||||||
|
color: red;
|
||||||
|
cursor:pointer;
|
||||||
|
height:40px;
|
||||||
|
line-height:40px;
|
||||||
|
margin-top:5px;
|
||||||
|
text-align:left;
|
||||||
|
background:#FFFFFF;
|
||||||
|
overflow:hidden;
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
.file-upload .file-select.file-select-disabled:hover .file-select-button{
|
||||||
|
background:#dce4ec;
|
||||||
|
color:#666666;
|
||||||
|
padding:0 10px;
|
||||||
|
display:inline-block;
|
||||||
|
height:40px;
|
||||||
|
line-height:40px;
|
||||||
|
}
|
||||||
|
.file-upload .file-select.file-select-disabled:hover .file-select-name{
|
||||||
|
line-height:40px;
|
||||||
|
display:inline-block;
|
||||||
|
padding:0 10px;
|
||||||
|
}
|
||||||
|
.subform {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
button {
|
||||||
button {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 0;
|
border: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
@ -146,49 +194,83 @@
|
|||||||
-webkit-text-size-adjust:none;
|
-webkit-text-size-adjust:none;
|
||||||
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
||||||
}
|
}
|
||||||
|
button:hover {
|
||||||
button:hover {
|
background: #c93c1d;
|
||||||
animation: rainbowbtn 0.2s infinite;
|
-webkit-transition:all .25s ease-in-out;
|
||||||
color:black !important;
|
-moz-transition:all .25s ease-in-out;
|
||||||
|
-o-transition:all .25s ease-in-out;
|
||||||
|
transition:all .25s ease-in-out;
|
||||||
}
|
}
|
||||||
|
button:active {
|
||||||
button.light {
|
background: #ae3318;
|
||||||
|
}
|
||||||
|
button.light {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #555759;
|
color: #555759;
|
||||||
}
|
}
|
||||||
|
button.light:hover {
|
||||||
.hflogo {
|
background: red;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.hflogo {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
|
||||||
animation: rainbowbox 6s infinite;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.litfont {
|
|
||||||
font-family: "Source Code Pro", monospace;
|
|
||||||
font-optical-sizing: auto;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img src="header.png" class="hflogo" alt="hardfiles" style="margin-top: 3rem;">
|
<img src="header.png" class="hflogo" alt="supernets" style="margin-top: 10rem;">
|
||||||
<h2 id="curl" class="litfont" style="display: none; font-size: 1rem; color: #ffffff; text-align: center; font-weight: lighter;">curl -F file=@example.png https://hardfiles.org/</h1>
|
<h2 style="font-size: 1rem; color: #ffffff; font-weight: 200;">curl -F file=@example.png https://hardfiles.org/</h1>
|
||||||
<form method="POST" class="subform" enctype="multipart/form-data" style="margin-top: 0.5rem;">
|
<form method="POST" class="subform" enctype="multipart/form-data">
|
||||||
<div style="display: flex; align-items: center; justify-content: center;">
|
<div class="file-upload" style="display: flex; justify-content: center; width: 25rem;">
|
||||||
<input type="file" id="fupload" name="file" style="background-color: black; padding: 12px; border-radius: 5px; color: white;" />
|
<div class="file-select" style="width: 100%;">
|
||||||
|
<div class="file-select-button" id="fileName">Browse</div>
|
||||||
|
<div class="file-select-name" id="noFile" style="cursor: pointer;">No file chosen...</div>
|
||||||
|
<input type="file" name="file" id="chooseFile">
|
||||||
|
</div>
|
||||||
<button class="light" type="submit" style="margin-left: 0.7rem;">up</button>
|
<button class="light" type="submit" style="margin-left: 0.7rem;">up</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<p style="color: white; font-weight: bold; font-size:0.8rem;" class="litfont">⚠️ Uploads are destroyed after 24 hours</p>
|
<p style="color: white; font-weight: 300;">⚠️ Uploads are erased after 24 hours</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="callingcard" style="position: relative;">
|
<div style="position: relative;">
|
||||||
<a href="https://supernets.org/" target="_blank" style="position: absolute; bottom: 20px; right:1px; display: flex; align-items: center; text-decoration: none;">
|
<a href="https://supernets.org/" target="_blank" style="position: absolute; bottom: 10px; right:10px; display: flex; align-items: center; text-decoration: none;">
|
||||||
<img src="supernets_logo.png" width="40px;">
|
<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>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#chooseFile').bind('change', function (e) {
|
||||||
|
var file = e.target.files[0];
|
||||||
|
if (!file) {
|
||||||
|
$(".file-upload").removeClass('active');
|
||||||
|
$("#noFile").text("No file chosen...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".file-upload").addClass('active');
|
||||||
|
$("#noFile").text(file.name.replace("C:\\fakepath\\", ""));
|
||||||
|
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(event) {
|
||||||
|
var binaryData = event.target.result;
|
||||||
|
// Compress the file data
|
||||||
|
var compressed = pako.gzip(new Uint8Array(binaryData), { level:1});
|
||||||
|
var compressedFile = new Blob([compressed], { type: "application/gzip" });
|
||||||
|
updateFileInput(compressedFile, file.name);
|
||||||
|
};
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateFileInput(compressedFile, fileName) {
|
||||||
|
var dataTransfer = new DataTransfer();
|
||||||
|
dataTransfer.items.add(new File([compressedFile], fileName + '.5000'));
|
||||||
|
$('#chooseFile')[0].files = dataTransfer.files;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
Before Width: | Height: | Size: 962 KiB |
BIN
www/revolver.gif
Before Width: | Height: | Size: 542 KiB |
Before Width: | Height: | Size: 17 KiB |