Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-10-08 15:21:05 +03:00
parent e8a375796d
commit 4909845c61

30
main.go
View File

@@ -12,6 +12,7 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -34,6 +35,7 @@ var assetsFS embed.FS
type meta struct { type meta struct {
Expiry time.Time `json:"expiry"` Expiry time.Time `json:"expiry"`
ExpireOnView bool `json:"expire_on_view"` ExpireOnView bool `json:"expire_on_view"`
FileName string `json:"file_name,omitempty"`
} }
func init() { func init() {
@@ -144,8 +146,8 @@ Upload from stdin and expire on first view:
<input type="submit" value="Upload file"> <input type="submit" value="Upload file">
</div> </div>
</form> </form>
<h2 style="margin-top:1.5rem">Quick text</h2> <h2 style="margin-top:1.5rem">No file? Type your text in here!</h2>
<p class="small">Type or paste text and upload as a .txt (no file chooser needed).</p> <p class="small">Type or paste text and upload as a .txt.</p>
<textarea id="textArea" placeholder="Type or paste here..."></textarea> <textarea id="textArea" placeholder="Type or paste here..."></textarea>
<div class="controls" style="margin-top:.5rem"> <div class="controls" style="margin-top:.5rem">
<button id="uploadTextBtn" type="button">Upload text</button> <button id="uploadTextBtn" type="button">Upload text</button>
@@ -285,6 +287,7 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
var reader io.Reader var reader io.Reader
var ext string var ext string
var fileName string
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")
if strings.HasPrefix(contentType, "multipart/form-data") { if strings.HasPrefix(contentType, "multipart/form-data") {
@@ -293,6 +296,7 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
defer file.Close() defer file.Close()
reader = file reader = file
ext = filepath.Ext(header.Filename) ext = filepath.Ext(header.Filename)
fileName = filepath.Base(header.Filename)
} }
} }
} }
@@ -345,7 +349,10 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
m.Expiry = time.Now().Add(d) m.Expiry = time.Now().Add(d)
} }
} }
if !m.Expiry.IsZero() || m.ExpireOnView { if fileName != "" {
m.FileName = fileName
}
if !m.Expiry.IsZero() || m.ExpireOnView || m.FileName != "" {
metaBytes, _ := json.Marshal(m) metaBytes, _ := json.Marshal(m)
_ = os.WriteFile(path+".json", metaBytes, 0644) _ = os.WriteFile(path+".json", metaBytes, 0644)
} }
@@ -357,6 +364,20 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s://%s/%s\n", scheme, domain, filename) fmt.Fprintf(w, "%s://%s/%s\n", scheme, domain, filename)
} }
func contentDispositionInlineFilename(name string) string {
q := strconv.QuoteToASCII(name)
var b strings.Builder
for i := 0; i < len(name); i++ {
c := name[i]
if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.' || c == '-' || c == '_' {
b.WriteByte(c)
} else {
fmt.Fprintf(&b, "%%%02X", c)
}
}
return fmt.Sprintf(`inline; filename=%s; filename*=UTF-8''%s`, q, b.String())
}
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/") id := strings.TrimPrefix(r.URL.Path, "/")
if id == "" { if id == "" {
@@ -379,6 +400,9 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
defer os.Remove(path) defer os.Remove(path)
defer os.Remove(metaPath) defer os.Remove(metaPath)
} }
if m.FileName != "" {
w.Header().Set("Content-Disposition", contentDispositionInlineFilename(m.FileName))
}
} }
} }