specify-expiry-and-urllen #2
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
files/
|
files/
|
||||||
|
dbfile.db
|
||||||
|
hardfile
|
||||||
|
25
README.md
25
README.md
@ -34,7 +34,6 @@ Start by adjusting the necessary configuration variables in `config.toml`.
|
|||||||
Execute the following commands to build and initiate HardFiles:
|
Execute the following commands to build and initiate HardFiles:
|
||||||
```
|
```
|
||||||
go build -o hardfiles main.go
|
go build -o hardfiles main.go
|
||||||
mkdir files
|
|
||||||
./hardfiles
|
./hardfiles
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -46,7 +45,8 @@ docker compose up -d
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 3. Default Port:
|
#### 3. Default Port:
|
||||||
By default, HardFiles listens on port `5000`. For production environments, it's recommended to use a robust web server like Nginx or Apache to proxy traffic to this port.
|
|
||||||
|
By default, HardFiles listens on port `5000`. For production environments, it's recommended to use a robust web server like Nginx or Caddy to proxy traffic to this port. Just don't use Apache ever.
|
||||||
|
|
||||||
###### Using Nginx as a Reverse Proxy:
|
###### Using Nginx as a Reverse Proxy:
|
||||||
|
|
||||||
@ -62,9 +62,11 @@ server {
|
|||||||
location / {
|
location / {
|
||||||
proxy_pass http://localhost:5000;
|
proxy_pass http://localhost:5000;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
access_log /dev/null;
|
||||||
|
error_log /dev/null;
|
||||||
|
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
|
||||||
@ -77,21 +79,38 @@ For obtaining the Let's Encrypt certificates, you can use tools like `certbot` t
|
|||||||
|
|
||||||
Remember, by using a reverse proxy, you can run HardFiles without needing root privileges and maintain a more secure environment.
|
Remember, by using a reverse proxy, you can run HardFiles without needing root privileges and maintain a more secure environment.
|
||||||
|
|
||||||
|
###### Using Caddy as a Reverse Proxy:
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
your_domain.com {
|
||||||
|
reverse_proxy localhost:5000
|
||||||
|
|
||||||
|
tls /etc/letsencrypt/live/your_domain.com/fullchain.pem /etc/letsencrypt/live/your_domain.com/privkey.pem
|
||||||
|
|
||||||
|
log {
|
||||||
|
output discard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## cURL Uploads & Bash Alias
|
## cURL Uploads & Bash Alias
|
||||||
|
|
||||||
If you frequently upload files to HardFiles via the command line, you can streamline the process by setting up a bash alias. This allows you to use a simple command, like `upload`, to push your files to HardFiles using `curl`.
|
If you frequently upload files to HardFiles via the command line, you can streamline the process by setting up a bash alias. This allows you to use a simple command, like `upload`, to push your files to HardFiles using `curl`.
|
||||||
|
|
||||||
#### Setting Up:
|
#### Setting Up:
|
||||||
|
|
||||||
1. **Edit your `.bashrc` file:** Open your `~/.bashrc` file in a text editor. You can use `nano` or `vim` for this purpose:
|
1. **Edit your `.bashrc` file:** Open your `~/.bashrc` file in a text editor. You can use `nano` or `vim` for this purpose:
|
||||||
```shell
|
```shell
|
||||||
nano ~/.bashrc
|
nano ~/.bashrc
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Add the `upload` function:** At the end of the `.bashrc` file, append the following function (replace the domain if you are running your own instance):
|
2. **Add the `upload` function:** At the end of the `.bashrc` file, append the following function (replace the domain if you are running your own instance):
|
||||||
```shell
|
```shell
|
||||||
upload() {
|
upload() {
|
||||||
curl -F file=@$1 https://hardfiles.org/
|
curl -F file=@$1 https://hardfiles.org/
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Reload your .bashrc file: To make the new function available in your current session, reload your .bashrc:
|
3. Reload your .bashrc file: To make the new function available in your current session, reload your .bashrc:
|
||||||
```shell
|
```shell
|
||||||
source ~/.bashrc
|
source ~/.bashrc
|
||||||
|
57
main.go
57
main.go
@ -99,12 +99,12 @@ func Zeros(path string, size int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NameGen() string {
|
func NameGen(fileNameLength int) string {
|
||||||
const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789"
|
const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ1234567890-_"
|
||||||
ll := len(chars)
|
ll := len(chars)
|
||||||
b := make([]byte, conf.FileLen)
|
b := make([]byte, fileNameLength)
|
||||||
rand.Read(b) // generates len(b) random bytes
|
rand.Read(b) // generates len(b) random bytes
|
||||||
for i := int64(0); i < int64(conf.FileLen); i++ {
|
for i := int64(0); i < int64(fileNameLength); i++ {
|
||||||
b[i] = chars[int(b[i])%ll]
|
b[i] = chars[int(b[i])%ll]
|
||||||
}
|
}
|
||||||
return string(b)
|
return string(b)
|
||||||
@ -120,8 +120,9 @@ func CheckFile(name string) bool { // false if doesn't exist, true if exists
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// expiry sanitize
|
var name string
|
||||||
twentyfour := int64(conf.FileExpirySeconds)
|
var expiryTime int64
|
||||||
|
var fileNameLength int
|
||||||
|
|
||||||
file, _, err := r.FormFile("file")
|
file, _, err := r.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -137,10 +138,41 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
file.Seek(0, 0)
|
file.Seek(0, 0)
|
||||||
|
|
||||||
|
// Check if expiry time is present and length is too long
|
||||||
|
if r.PostFormValue("expiry") != "" {
|
||||||
|
expiryTime, err = strconv.ParseInt(r.PostFormValue("expiry"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("expiry could not be parsed")
|
||||||
|
} else {
|
||||||
|
// 5 days max
|
||||||
|
if expiryTime < 1 || expiryTime > 432000 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expiryTime = int64(conf.FileExpirySeconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the file length parameter exists and also if it's too long
|
||||||
|
if r.PostFormValue("url_len") != "" {
|
||||||
|
fileNameLength, err = strconv.Atoi(r.PostFormValue("url_len"))
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("url_len could not be parsed")
|
||||||
|
} else {
|
||||||
|
// if the length is < 3 and > 128 return error
|
||||||
|
if fileNameLength < 3 || fileNameLength > 128 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileNameLength = conf.FileLen
|
||||||
|
}
|
||||||
|
|
||||||
// generate + check name
|
// generate + check name
|
||||||
var name string
|
|
||||||
for {
|
for {
|
||||||
id := NameGen()
|
id := NameGen(fileNameLength)
|
||||||
name = id + mtype.Extension()
|
name = id + mtype.Extension()
|
||||||
if !CheckFile(name) {
|
if !CheckFile(name) {
|
||||||
break
|
break
|
||||||
@ -149,14 +181,14 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err = db.Update(func(tx *bolt.Tx) error {
|
err = db.Update(func(tx *bolt.Tx) error {
|
||||||
b := tx.Bucket([]byte("expiry"))
|
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()+expiryTime, 10)))
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
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")
|
log.Info().Int64("expiry", expiryTime).Msg("Writing new file")
|
||||||
|
|
||||||
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_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -235,6 +267,11 @@ func main() {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Create the files directory if it doesn't already exist
|
||||||
|
if _, err := os.Stat(conf.FileFolder); os.IsNotExist(err) {
|
||||||
|
os.Mkdir(conf.FileFolder, 0755)
|
||||||
|
}
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/", UploadHandler).Methods("POST")
|
r.HandleFunc("/", UploadHandler).Methods("POST")
|
||||||
r.HandleFunc("/uploads/{name}", func(w http.ResponseWriter, r *http.Request) {
|
r.HandleFunc("/uploads/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Loading…
Reference in New Issue
Block a user