Display remaining time until removal
This commit is contained in:
49
lts.go
49
lts.go
@ -16,6 +16,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
)
|
)
|
||||||
@ -30,22 +32,23 @@ var tmpls embed.FS
|
|||||||
//go:embed etc/*
|
//go:embed etc/*
|
||||||
var etc embed.FS
|
var etc embed.FS
|
||||||
|
|
||||||
func createFile(storePath, name string) (*os.File, error) {
|
func createFile(storePath, name string) (*os.File, string, error) {
|
||||||
if _, err := os.Stat(storePath); os.IsNotExist(err) {
|
if _, err := os.Stat(storePath); os.IsNotExist(err) {
|
||||||
os.Mkdir(storePath, 0755)
|
os.Mkdir(storePath, 0755)
|
||||||
}
|
}
|
||||||
|
|
||||||
uuidBytes, err := NewV4()
|
uuidBytes, err := NewV4()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
uuid := uuidBytes.String()
|
uuid := uuidBytes.String()
|
||||||
|
|
||||||
dst, err := os.Create(filepath.Join(storePath, fmt.Sprintf("%s-%s", uuid, name)))
|
bare_name := fmt.Sprintf("%s-%s", uuid, name)
|
||||||
|
dst, err := os.Create(filepath.Join(storePath, bare_name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, bare_name, err
|
||||||
}
|
}
|
||||||
return dst, nil
|
return dst, bare_name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllowedUser struct {
|
type AllowedUser struct {
|
||||||
@ -107,6 +110,19 @@ func byteCountSI(b int64) string {
|
|||||||
float64(b)/float64(div), "kMGTPE"[exp])
|
float64(b)/float64(div), "kMGTPE"[exp])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Timeout struct {
|
||||||
|
H int64
|
||||||
|
M int64
|
||||||
|
S int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cleaner struct {
|
||||||
|
Timeout Timeout
|
||||||
|
SpawnTime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var cleaners map[string]Cleaner = map[string]Cleaner{}
|
||||||
|
|
||||||
func handleUpload(w http.ResponseWriter, r *http.Request) {
|
func handleUpload(w http.ResponseWriter, r *http.Request) {
|
||||||
limit := int64(10737418240) // 10GiB
|
limit := int64(10737418240) // 10GiB
|
||||||
r.ParseMultipartForm(limit)
|
r.ParseMultipartForm(limit)
|
||||||
@ -147,7 +163,7 @@ func handleUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
dst, err := createFile(storePath, handler.Filename)
|
dst, bare_name, err := createFile(storePath, handler.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Could not save file", http.StatusInternalServerError)
|
http.Error(w, "Could not save file", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@ -161,17 +177,20 @@ func handleUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintf(w, "Uploaded file: %s\n", handler.Filename)
|
fmt.Fprintf(w, "Uploaded file: %s\n", handler.Filename)
|
||||||
fmt.Fprintf(w, "File size: %s\n", byteCountSI(handler.Size))
|
fmt.Fprintf(w, "File size: %s\n", byteCountSI(handler.Size))
|
||||||
fmt.Fprintf(w, "Lifetime: %02d:%02d:%02d total %d\n", hours, mins, secs, total);
|
fmt.Fprintf(w, "Lifetime: %02d:%02d:%02d total %d\n", hours, mins, secs, total);
|
||||||
fmt.Fprintf(w, "Link: %s", fmt.Sprintf("%s/%s", listener.Addr().String(), dst.Name()))
|
fmt.Fprintf(w, "Link: %s", fmt.Sprintf("%s/store/%s", listener.Addr().String(), bare_name))
|
||||||
|
|
||||||
cmd := exec.Command("./ltscleanerd", dst.Name(), strconv.FormatInt(total, 10))
|
cmd := exec.Command("./ltscleanerd", dst.Name(), strconv.FormatInt(total, 10))
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setsid: true,
|
||||||
|
}
|
||||||
log.Println("Started ", cmd.String())
|
log.Println("Started ", cmd.String())
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Could not start cleaner daemon: ", err)
|
log.Println("Could not start cleaner daemon: ", err)
|
||||||
}
|
}
|
||||||
err = cmd.Process.Release()
|
cleaners[bare_name] = Cleaner{
|
||||||
if err != nil {
|
Timeout: Timeout{ H: hours, M: mins, S: secs },
|
||||||
log.Fatal("Could not detach from cleaner daemon: ", err)
|
SpawnTime: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +207,7 @@ type BrowseRecord struct {
|
|||||||
ReadableName string
|
ReadableName string
|
||||||
Perm string
|
Perm string
|
||||||
Modtime string
|
Modtime string
|
||||||
|
TimeLeft string
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleBrowse(w http.ResponseWriter, r *http.Request) {
|
func handleBrowse(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -211,12 +231,21 @@ func handleBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
info.ModTime().Day(), info.ModTime().Month().String(), info.ModTime().Year(),
|
info.ModTime().Day(), info.ModTime().Month().String(), info.ModTime().Year(),
|
||||||
info.ModTime().Hour(), info.ModTime().Minute(), info.ModTime().Second(),
|
info.ModTime().Hour(), info.ModTime().Minute(), info.ModTime().Second(),
|
||||||
)
|
)
|
||||||
|
cleaner, _ := cleaners[e.Name()]
|
||||||
|
total := cleaner.Timeout.S + cleaner.Timeout.M*60 + cleaner.Timeout.H*60*60
|
||||||
|
now := time.Now().Unix()
|
||||||
|
fmt.Println(cleaner.SpawnTime + total - now)
|
||||||
|
timeleft_unix := time.Unix(cleaner.SpawnTime + total - now, 0)
|
||||||
|
timeleft := fmt.Sprintf("time left %02d:%02d:%02d",
|
||||||
|
timeleft_unix.Hour() - 1, timeleft_unix.Minute(), timeleft_unix.Second(),
|
||||||
|
)
|
||||||
|
|
||||||
records = append(records, BrowseRecord{
|
records = append(records, BrowseRecord{
|
||||||
FileName: filename,
|
FileName: filename,
|
||||||
ReadableName: readable_name,
|
ReadableName: readable_name,
|
||||||
Perm: info.Mode().Perm().String(),
|
Perm: info.Mode().Perm().String(),
|
||||||
Modtime: modtime,
|
Modtime: modtime,
|
||||||
|
TimeLeft: timeleft,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<td><a href="/store/{{.FileName}}">{{.ReadableName}}</a></td>
|
<td><a href="/store/{{.FileName}}">{{.ReadableName}}</a></td>
|
||||||
<td><span>{{.Perm}}</span></td>
|
<td><span>{{.Perm}}</span></td>
|
||||||
<td><span>{{.Modtime}}</span></td>
|
<td><span>{{.Modtime}}</span></td>
|
||||||
|
<td><span>{{.TimeLeft}}</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</table>
|
</table>
|
||||||
|
@ -11,19 +11,24 @@
|
|||||||
<p>
|
<p>
|
||||||
Welcome to The Lair's temporary storage service. Use this service to transport files via
|
Welcome to The Lair's temporary storage service. Use this service to transport files via
|
||||||
a temporary remote storage. <br />
|
a temporary remote storage. <br />
|
||||||
ONLY WHITELISTED USERS can upload! For access, reach out to <a href="mailto:kamkow256@gmail.com">me</a>.<br />
|
ONLY WHITELISTED USERS can upload! For access, reach out to <a href="mailto:kamkow256@gmail.com">me</a>.
|
||||||
Only 30PLN / 12MON.
|
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Upload</h2>
|
<h2>Upload</h2>
|
||||||
<p>
|
<p>
|
||||||
<form id="upload-form" method="POST" enctype="multipart/form-data">
|
<form id="upload-form" method="POST" enctype="multipart/form-data">
|
||||||
|
<label for="myfile">File:</label>
|
||||||
<input type="file" name="myfile" id="myfile" required />
|
<input type="file" name="myfile" id="myfile" required />
|
||||||
|
<label for="user">User:</label>
|
||||||
<input type="text" name="user" id="user" required />
|
<input type="text" name="user" id="user" required />
|
||||||
|
<label for="pass">Password:</label>
|
||||||
<input type="password" name="pass", id="pass" required />
|
<input type="password" name="pass", id="pass" required />
|
||||||
|
<label for="hours">Hours:</label>
|
||||||
<input type="number" name="hours" id="hours" min="0" max="24" step="1" value="0" required />
|
<input type="number" name="hours" id="hours" min="0" max="24" step="1" value="0" required />
|
||||||
|
<label for="mins">Minutes:</label>
|
||||||
<input type="number" name="mins" id="mins" min="0" max="60" step="1" value="0" required />
|
<input type="number" name="mins" id="mins" min="0" max="60" step="1" value="0" required />
|
||||||
|
<label for="secs">Seconds:</label>
|
||||||
<input type="number" name="secs" id="secs" min="0" max="60" step="1" value="0" required />
|
<input type="number" name="secs" id="secs" min="0" max="60" step="1" value="0" required />
|
||||||
<input type="submit" value="Upload" />
|
<input type="submit" value="Upload" />
|
||||||
</form>
|
</form>
|
||||||
|
Reference in New Issue
Block a user