@ -22,6 +22,7 @@ import (
"gopkg.in/h2non/filetype.v1"
)
var FileTooLargeError = errors . New ( "File too large." )
var fileBlacklist = map [ string ] bool {
"favicon.ico" : true ,
"index.htm" : true ,
@ -34,10 +35,11 @@ var fileBlacklist = map[string]bool{
// Describes metadata directly from the user request
type UploadRequest struct {
src io . Reader
size int64
filename string
expiry time . Duration // Seconds until expiry, 0 = never
deleteKey string // Empty string if not defined
randomBarename bool
deletionKey string // Empty string if not defined
}
// Metadata associated with a file as it would actually be stored
@ -48,7 +50,7 @@ type Upload struct {
func uploadPostHandler ( c web . C , w http . ResponseWriter , r * http . Request ) {
if ! strictReferrerCheck ( r , getSiteURL ( r ) , [ ] string { "Linx-Delete-Key" , "Linx-Expiry" , "Linx-Randomize" , "X-Requested-With" } ) {
badRequestHandler ( c , w , r )
badRequestHandler ( c , w , r , RespAUTO , "" )
return
}
@ -65,38 +67,39 @@ func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
}
defer file . Close ( )
r . ParseForm ( )
if r . Form . Get ( "randomize" ) == "true" {
upReq . randomBarename = true
}
upReq . expiry = parseExpiry ( r . Form . Get ( "expires" ) )
upReq . src = http . MaxBytesReader ( w , file , Config . maxSize )
upReq . src = file
upReq . size = headers . Size
upReq . filename = headers . Filename
} else {
if r . FormValue ( "content" ) == "" {
oops Handler( c , w , r , RespHTML , "Empty file" )
if r . PostFormValue ( "content" ) == "" {
badRequestHandler ( c , w , r , RespAUTO , "Empty file" )
return
}
extension := r . FormValue ( "extension" )
extension := r . Post FormValue( "extension" )
if extension == "" {
extension = "txt"
}
content := r . FormValue ( "content" )
if int64 ( len ( content ) ) > Config . maxSize {
oopsHandler ( c , w , r , RespJSON , "Content length exceeds max size" )
return
}
content := r . PostFormValue ( "content" )
upReq . src = strings . NewReader ( content )
upReq . expiry = parseExpiry ( r . FormValue ( "expires" ) )
upReq . filename = r . FormValue ( "filename" ) + "." + extension
upReq . size = int64 ( len ( content ) )
upReq . filename = r . PostFormValue ( "filename" ) + "." + extension
}
upReq . expiry = parseExpiry ( r . PostFormValue ( "expires" ) )
if r . PostFormValue ( "randomize" ) == "true" {
upReq . randomBarename = true
}
upload , err := processUpload ( upReq )
if strings . EqualFold ( "application/json" , r . Header . Get ( "Accept" ) ) {
if err != nil {
if err == FileTooLargeError || err == backends . FileEmptyError {
badRequestHandler ( c , w , r , RespJSON , err . Error ( ) )
return
} else if err != nil {
oopsHandler ( c , w , r , RespJSON , "Could not upload file: " + err . Error ( ) )
return
}
@ -105,14 +108,16 @@ func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
w . Header ( ) . Set ( "Content-Type" , "application/json; charset=UTF-8" )
w . Write ( js )
} else {
if err != nil {
if err == FileTooLargeError || err == backends . FileEmptyError {
badRequestHandler ( c , w , r , RespHTML , err . Error ( ) )
return
} else if err != nil {
oopsHandler ( c , w , r , RespHTML , "Could not upload file: " + err . Error ( ) )
return
}
http . Redirect ( w , r , Config . sitePath + upload . Filename , 303 )
}
}
func uploadPutHandler ( c web . C , w http . ResponseWriter , r * http . Request ) {
@ -126,7 +131,10 @@ func uploadPutHandler(c web.C, w http.ResponseWriter, r *http.Request) {
upload , err := processUpload ( upReq )
if strings . EqualFold ( "application/json" , r . Header . Get ( "Accept" ) ) {
if err != nil {
if err == FileTooLargeError || err == backends . FileEmptyError {
badRequestHandler ( c , w , r , RespJSON , err . Error ( ) )
return
} else if err != nil {
oopsHandler ( c , w , r , RespJSON , "Could not upload file: " + err . Error ( ) )
return
}
@ -135,7 +143,10 @@ func uploadPutHandler(c web.C, w http.ResponseWriter, r *http.Request) {
w . Header ( ) . Set ( "Content-Type" , "application/json; charset=UTF-8" )
w . Write ( js )
} else {
if err != nil {
if err == FileTooLargeError || err == backends . FileEmptyError {
badRequestHandler ( c , w , r , RespPLAIN , err . Error ( ) )
return
} else if err != nil {
oopsHandler ( c , w , r , RespPLAIN , "Could not upload file: " + err . Error ( ) )
return
}
@ -169,7 +180,7 @@ func uploadRemote(c web.C, w http.ResponseWriter, r *http.Request) {
upReq . filename = filepath . Base ( grabUrl . Path )
upReq . src = http . MaxBytesReader ( w , resp . Body , Config . maxSize )
upReq . deletion Key = r . FormValue ( "deletekey" )
upReq . delete Key = r . FormValue ( "deletekey" )
upReq . randomBarename = r . FormValue ( "randomize" ) == "yes"
upReq . expiry = parseExpiry ( r . FormValue ( "expiry" ) )
@ -199,15 +210,18 @@ func uploadHeaderProcess(r *http.Request, upReq *UploadRequest) {
upReq . randomBarename = true
}
upReq . deletion Key = r . Header . Get ( "Linx-Delete-Key" )
upReq . delete Key = r . Header . Get ( "Linx-Delete-Key" )
// Get seconds until expiry. Non-integer responses never expire.
expStr := r . Header . Get ( "Linx-Expiry" )
upReq . expiry = parseExpiry ( expStr )
}
func processUpload ( upReq UploadRequest ) ( upload Upload , err error ) {
if upReq . size > Config . maxSize {
return upload , FileTooLargeError
}
// Determine the appropriate filename, then write to disk
barename , extension := barePlusExt ( upReq . filename )
@ -221,7 +235,7 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) {
header = make ( [ ] byte , 512 )
n , _ := upReq . src . Read ( header )
if n == 0 {
return upload , errors . New ( "Empty file" )
return upload , backends . FileEmptyError
}
header = header [ : n ]
@ -243,7 +257,7 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) {
if fileexists {
metad , merr := storageBackend . Head ( upload . Filename )
if merr == nil {
if upReq . deletion Key == metad . DeleteKey {
if upReq . delete Key == metad . DeleteKey {
fileexists = false
}
}
@ -273,11 +287,11 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) {
fileExpiry = time . Now ( ) . Add ( upReq . expiry )
}
if upReq . deletion Key == "" {
upReq . deletion Key = uniuri . NewLen ( 30 )
if upReq . delete Key == "" {
upReq . delete Key = uniuri . NewLen ( 30 )
}
upload . Metadata , err = storageBackend . Put ( upload . Filename , io . MultiReader ( bytes . NewReader ( header ) , upReq . src ) , fileExpiry , upReq . deletion Key )
upload . Metadata , err = storageBackend . Put ( upload . Filename , io . MultiReader ( bytes . NewReader ( header ) , upReq . src ) , fileExpiry , upReq . delete Key )
if err != nil {
return upload , err
}