upload expiry/barename respect, random fixes
This commit is contained in:
parent
935db7c618
commit
c32a698cbc
|
@ -22,13 +22,11 @@ func fileDisplayHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
filePath := path.Join(Config.filesDir, fileName)
|
filePath := path.Join(Config.filesDir, fileName)
|
||||||
fileInfo, err := os.Stat(filePath)
|
fileInfo, err := os.Stat(filePath)
|
||||||
|
|
||||||
if os.IsNotExist(err) {
|
if !fileExistsAndNotExpired(fileName) {
|
||||||
notFoundHandler(c, w, r)
|
notFoundHandler(c, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// file expiry checking
|
|
||||||
|
|
||||||
if err := magicmime.Open(magicmime.MAGIC_MIME_TYPE |
|
if err := magicmime.Open(magicmime.MAGIC_MIME_TYPE |
|
||||||
magicmime.MAGIC_SYMLINK |
|
magicmime.MAGIC_SYMLINK |
|
||||||
magicmime.MAGIC_ERROR); err != nil {
|
magicmime.MAGIC_ERROR); err != nil {
|
||||||
|
|
10
expiry.go
10
expiry.go
|
@ -33,12 +33,8 @@ func isTsExpired(ts int32) (expired bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if the given filename is expired
|
// Determine if the given filename is expired
|
||||||
func isFileExpired(filename string) (bool, error) {
|
func isFileExpired(filename string) bool {
|
||||||
exp, err := metadataGetExpiry(filename)
|
exp, _ := metadataGetExpiry(filename)
|
||||||
|
|
||||||
if err != nil {
|
return isTsExpired(exp)
|
||||||
return true, err
|
|
||||||
} else {
|
|
||||||
return isTsExpired(exp), err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
32
fileserve.go
32
fileserve.go
|
@ -11,24 +11,28 @@ import (
|
||||||
func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
fileName := c.URLParams["name"]
|
fileName := c.URLParams["name"]
|
||||||
filePath := path.Join(Config.filesDir, fileName)
|
filePath := path.Join(Config.filesDir, fileName)
|
||||||
_, err := os.Stat(filePath)
|
|
||||||
|
|
||||||
if os.IsNotExist(err) {
|
if isFileExpired(fileName) {
|
||||||
notFoundHandler(c, w, r)
|
notFoundHandler(c, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expired, expErr := isFileExpired(fileName)
|
|
||||||
|
|
||||||
if expErr != nil {
|
|
||||||
// Error reading metadata, pretend it's expired
|
|
||||||
notFoundHandler(c, w, r)
|
|
||||||
// TODO log error internally
|
|
||||||
return
|
|
||||||
} else if expired {
|
|
||||||
notFoundHandler(c, w, r)
|
|
||||||
// TODO delete the file
|
|
||||||
}
|
|
||||||
|
|
||||||
http.ServeFile(w, r, filePath)
|
http.ServeFile(w, r, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fileExistsAndNotExpired(filename string) bool {
|
||||||
|
filePath := path.Join(Config.filesDir, filename)
|
||||||
|
|
||||||
|
_, err := os.Stat(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isFileExpired(filename) {
|
||||||
|
os.Remove(path.Join(Config.filesDir, filename))
|
||||||
|
os.Remove(path.Join(Config.metaDir, filename))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
1
meta.go
1
meta.go
|
@ -24,7 +24,6 @@ func metadataWrite(filename string, upload *Upload) error {
|
||||||
|
|
||||||
fmt.Fprintln(w, upload.Expiry)
|
fmt.Fprintln(w, upload.Expiry)
|
||||||
fmt.Fprintln(w, upload.DeleteKey)
|
fmt.Fprintln(w, upload.DeleteKey)
|
||||||
fmt.Fprintln(w, upload.DebugInfo)
|
|
||||||
|
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,13 @@ func main() {
|
||||||
|
|
||||||
err = os.MkdirAll(Config.filesDir, 0755)
|
err = os.MkdirAll(Config.filesDir, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error: could not create files directory\n")
|
fmt.Println("Error: could not create files directory")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.MkdirAll(Config.metaDir, 0700)
|
err = os.MkdirAll(Config.metaDir, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error: could not create metadata directory\n")
|
fmt.Println("Error: could not create metadata directory")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,20 @@
|
||||||
<div id="choices">
|
<div id="choices">
|
||||||
<div id="expiry">
|
<div id="expiry">
|
||||||
<label>File expiry:
|
<label>File expiry:
|
||||||
<select name="expires" id="expires">
|
<select name="expires" id="expires" onchange="uploader.setParams({expires: $('#expires').val(), randomize: $('#randomize').is(':checked')})">
|
||||||
</label>
|
</label>
|
||||||
<option value="never">never</option>
|
<option value="0">never</option>
|
||||||
<option value="a minute">a minute</option>
|
<option value="60">a minute</option>
|
||||||
<option value="5 minutes">5 minutes</option>
|
<option value="300">5 minutes</option>
|
||||||
<option value="an hour">an hour</option>
|
<option value="3600">an hour</option>
|
||||||
<option value="a day">a day</option>
|
<option value="86400">a day</option>
|
||||||
<option value="a week">a week</option>
|
<option value="604800">a week</option>
|
||||||
<option value="a month">a month</option>
|
<option value="2419200">a month</option>
|
||||||
<option value="a year">a year</option>
|
<option value="29030400">a year</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label><input name="randomize" id="randomize" type="checkbox" checked /> Randomize filename</label>
|
<label><input name="randomize" id="randomize" type="checkbox" checked onclick="uploader.setParams({expires: $('#expires').val(), randomize: $('#randomize').is(':checked')})" /> Randomize filename</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
95
upload.go
95
upload.go
|
@ -30,35 +30,6 @@ type Upload struct {
|
||||||
Size int64
|
Size int64
|
||||||
Expiry int32 // Unix timestamp of expiry, 0=never
|
Expiry int32 // Unix timestamp of expiry, 0=never
|
||||||
DeleteKey string // Deletion key, one generated if not provided
|
DeleteKey string // Deletion key, one generated if not provided
|
||||||
DebugInfo string // Optional field to store whatever
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadHeaderProcess(r *http.Request, upReq *UploadRequest) {
|
|
||||||
// For legacy reasons
|
|
||||||
upReq.randomBarename = false
|
|
||||||
if r.Header.Get("X-Randomized-Filename") == "yes" {
|
|
||||||
upReq.randomBarename = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.Header.Get("X-Randomized-Barename") == "yes" {
|
|
||||||
upReq.randomBarename = true
|
|
||||||
}
|
|
||||||
|
|
||||||
upReq.deletionKey = r.Header.Get("X-Delete-Key")
|
|
||||||
|
|
||||||
// Get seconds until expiry. Non-integer responses never expire.
|
|
||||||
expStr := r.Header.Get("X-File-Expiry")
|
|
||||||
if expStr == "" {
|
|
||||||
upReq.expiry = 0
|
|
||||||
} else {
|
|
||||||
expiry, err := strconv.ParseInt(expStr, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
upReq.expiry = 0
|
|
||||||
} else {
|
|
||||||
upReq.expiry = int32(expiry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -66,6 +37,11 @@ func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
uploadHeaderProcess(r, &upReq)
|
uploadHeaderProcess(r, &upReq)
|
||||||
|
|
||||||
if r.Header.Get("Content-Type") == "application/octet-stream" {
|
if r.Header.Get("Content-Type") == "application/octet-stream" {
|
||||||
|
if r.URL.Query().Get("randomize") == "true" {
|
||||||
|
upReq.randomBarename = true
|
||||||
|
}
|
||||||
|
upReq.expiry = parseExpiry(r.URL.Query().Get("expires"))
|
||||||
|
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
upReq.src = r.Body
|
upReq.src = r.Body
|
||||||
upReq.filename = r.URL.Query().Get("qqfile")
|
upReq.filename = r.URL.Query().Get("qqfile")
|
||||||
|
@ -78,6 +54,11 @@ func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
r.ParseForm()
|
||||||
|
if r.Form.Get("randomize") == "true" {
|
||||||
|
upReq.randomBarename = true
|
||||||
|
}
|
||||||
|
upReq.expiry = parseExpiry(r.Form.Get("expires"))
|
||||||
upReq.src = file
|
upReq.src = file
|
||||||
upReq.filename = headers.Filename
|
upReq.filename = headers.Filename
|
||||||
}
|
}
|
||||||
|
@ -89,14 +70,9 @@ func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.EqualFold("application/json", r.Header.Get("Accept")) {
|
if strings.EqualFold("application/json", r.Header.Get("Accept")) {
|
||||||
js, _ := json.Marshal(map[string]string{
|
js := generateJSONresponse(upload)
|
||||||
"filename": upload.Filename,
|
|
||||||
"url": Config.siteURL + upload.Filename,
|
|
||||||
})
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
w.Write(js)
|
w.Write(js)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
http.Redirect(w, r, "/"+upload.Filename, 301)
|
http.Redirect(w, r, "/"+upload.Filename, 301)
|
||||||
}
|
}
|
||||||
|
@ -117,7 +93,29 @@ func uploadPutHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, Config.siteURL+upload.Filename)
|
if strings.EqualFold("application/json", r.Header.Get("Accept")) {
|
||||||
|
js := generateJSONresponse(upload)
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
|
w.Write(js)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, Config.siteURL+upload.Filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadHeaderProcess(r *http.Request, upReq *UploadRequest) {
|
||||||
|
// For legacy reasons
|
||||||
|
if r.Header.Get("X-Randomized-Filename") == "yes" {
|
||||||
|
upReq.randomBarename = true
|
||||||
|
} else if r.Header.Get("X-Randomized-Barename") == "yes" {
|
||||||
|
upReq.randomBarename = true
|
||||||
|
}
|
||||||
|
|
||||||
|
upReq.deletionKey = r.Header.Get("X-Delete-Key")
|
||||||
|
|
||||||
|
// Get seconds until expiry. Non-integer responses never expire.
|
||||||
|
expStr := r.Header.Get("X-File-Expiry")
|
||||||
|
upReq.expiry = parseExpiry(expStr)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func processUpload(upReq UploadRequest) (upload Upload, err error) {
|
func processUpload(upReq UploadRequest) (upload Upload, err error) {
|
||||||
|
@ -183,6 +181,18 @@ func generateBarename() string {
|
||||||
return uuid.New()[:8]
|
return uuid.New()[:8]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateJSONresponse(upload Upload) []byte {
|
||||||
|
js, _ := json.Marshal(map[string]string{
|
||||||
|
"url": Config.siteURL + upload.Filename,
|
||||||
|
"filename": upload.Filename,
|
||||||
|
"delete_key": upload.DeleteKey,
|
||||||
|
"expiry": strconv.FormatInt(int64(upload.Expiry), 10),
|
||||||
|
"size": strconv.FormatInt(upload.Size, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
return js
|
||||||
|
}
|
||||||
|
|
||||||
var barePlusRe = regexp.MustCompile(`[^A-Za-z0-9\-]`)
|
var barePlusRe = regexp.MustCompile(`[^A-Za-z0-9\-]`)
|
||||||
|
|
||||||
func barePlusExt(filename string) (barename, extension string) {
|
func barePlusExt(filename string) (barename, extension string) {
|
||||||
|
@ -198,3 +208,16 @@ func barePlusExt(filename string) (barename, extension string) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseExpiry(expStr string) int32 {
|
||||||
|
if expStr == "" {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
expiry, err := strconv.ParseInt(expStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return int32(expiry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue