upload expiry/barename respect, random fixes

This commit is contained in:
andreimarcu 2015-09-28 00:25:57 -04:00
parent 935db7c618
commit c32a698cbc
7 changed files with 93 additions and 73 deletions

View File

@ -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 {

View File

@ -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
}
} }

View File

@ -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
}

View File

@ -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()
} }

View File

@ -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)
} }

View File

@ -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>

View File

@ -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,8 +93,30 @@ func uploadPutHandler(c web.C, w http.ResponseWriter, r *http.Request) {
return return
} }
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) 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) {
// Determine the appropriate filename, then write to disk // Determine the appropriate filename, then write to disk
@ -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)
}
}
}