mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-11-26 22:20:18 +01:00
Multiple fixes
This commit is contained in:
commit
f38eb6fb77
16 changed files with 218 additions and 200 deletions
|
@ -6,7 +6,6 @@ bin
|
||||||
*.pyc
|
*.pyc
|
||||||
*.egg-info
|
*.egg-info
|
||||||
.vagrant
|
.vagrant
|
||||||
.git
|
|
||||||
.tmp
|
.tmp
|
||||||
bower_components
|
bower_components
|
||||||
node_modules
|
node_modules
|
||||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
run: |
|
run: |
|
||||||
go version
|
go version
|
||||||
go build -tags netgo -ldflags '-a -s -w -extldflags "-static"' -o ./artifacts/transfersh-${GITHUB_REF##*/}-${{ matrix.suffix }}
|
go build -tags netgo -ldflags "-X github.com/dutchcoders/transfer.sh/cmd.Version=${GITHUB_REF##*/} -a -s -w -extldflags '-static'" -o ./artifacts/transfersh-${GITHUB_REF##*/}-${{ matrix.suffix }}
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
name: Upload artifacts
|
name: Upload artifacts
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Default to Go 1.15
|
# Default to Go 1.16
|
||||||
ARG GO_VERSION=1.15
|
ARG GO_VERSION=1.16
|
||||||
FROM golang:${GO_VERSION}-alpine as build
|
FROM golang:${GO_VERSION}-alpine as build
|
||||||
|
|
||||||
# Necessary to run 'go get' and to compile the linked binary
|
# Necessary to run 'go get' and to compile the linked binary
|
||||||
|
@ -12,7 +12,7 @@ WORKDIR /go/src/github.com/dutchcoders/transfer.sh
|
||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
|
|
||||||
# build & install server
|
# build & install server
|
||||||
RUN go get -u ./... && CGO_ENABLED=0 go build -tags netgo -ldflags '-a -s -w -extldflags "-static"' -o /go/bin/transfersh github.com/dutchcoders/transfer.sh
|
RUN CGO_ENABLED=0 go build -tags netgo -ldflags "-X github.com/dutchcoders/transfer.sh/cmd.Version=$(git describe --tags) -a -s -w -extldflags '-static'" -o /go/bin/transfersh
|
||||||
|
|
||||||
FROM scratch AS final
|
FROM scratch AS final
|
||||||
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"
|
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,8 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2018 DutchCoders [https://github.com/dutchcoders/]
|
Copyright (c) 2014-2018 DutchCoders [https://github.com/dutchcoders/]
|
||||||
|
Copyright (c) 2018-2020 Andrea Spacca.
|
||||||
|
Copyright (c) 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -224,4 +224,7 @@ Contributions are welcome.
|
||||||
## Copyright and license
|
## Copyright and license
|
||||||
|
|
||||||
Code and documentation copyright 2011-2018 Remco Verhoef.
|
Code and documentation copyright 2011-2018 Remco Verhoef.
|
||||||
|
Code and documentation copyright 2018-2020 Andrea Spacca.
|
||||||
|
Code and documentation copyright 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
Code released under [the MIT license](LICENSE).
|
Code released under [the MIT license](LICENSE).
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Version = "1.2.4"
|
var Version = "0.0.0"
|
||||||
var helpTemplate = `NAME:
|
var helpTemplate = `NAME:
|
||||||
{{.Name}} - {{.Usage}}
|
{{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ var globalFlags = []cli.Flag{
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "CORS_DOMAINS",
|
EnvVar: "CORS_DOMAINS",
|
||||||
},
|
},
|
||||||
cli.Int64Flag{
|
cli.IntFlag{
|
||||||
Name: "random-token-length",
|
Name: "random-token-length",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Value: 6,
|
Value: 6,
|
||||||
|
@ -383,7 +383,7 @@ func New() *Cmd {
|
||||||
options = append(options, server.RateLimit(v))
|
options = append(options, server.RateLimit(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
v := c.Int64("random-token-length")
|
v := c.Int("random-token-length")
|
||||||
options = append(options, server.RandomTokenLength(v))
|
options = append(options, server.RandomTokenLength(v))
|
||||||
|
|
||||||
purgeDays := c.Int("purge-days")
|
purgeDays := c.Int("purge-days")
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -11,7 +11,7 @@ require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||||
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329
|
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329
|
||||||
github.com/dutchcoders/transfer.sh-web v0.0.0-20210212072623-ac7014a9c3a7
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723094506-f0946ebceb7a
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1
|
github.com/elazarl/go-bindata-assetfs v1.0.1
|
||||||
github.com/fatih/color v1.10.0
|
github.com/fatih/color v1.10.0
|
||||||
github.com/garyburd/redigo v1.6.2 // indirect
|
github.com/garyburd/redigo v1.6.2 // indirect
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -92,6 +92,14 @@ github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329 h1:ERqCk
|
||||||
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329/go.mod h1:G5qOfE5bQZ5scycLpB7fYWgN4y3xdfXo+pYWM8z2epY=
|
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329/go.mod h1:G5qOfE5bQZ5scycLpB7fYWgN4y3xdfXo+pYWM8z2epY=
|
||||||
github.com/dutchcoders/transfer.sh-web v0.0.0-20210212072623-ac7014a9c3a7 h1:zKJw+RxTDbypWVb0HfPs43bj/ee65Bl7rIDPO7HixrQ=
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210212072623-ac7014a9c3a7 h1:zKJw+RxTDbypWVb0HfPs43bj/ee65Bl7rIDPO7HixrQ=
|
||||||
github.com/dutchcoders/transfer.sh-web v0.0.0-20210212072623-ac7014a9c3a7/go.mod h1:jTzXZabwihvQgvmySgD4f4GNszimkXK3o8x1ucH1z5Q=
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210212072623-ac7014a9c3a7/go.mod h1:jTzXZabwihvQgvmySgD4f4GNszimkXK3o8x1ucH1z5Q=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210717081259-8b8af59a0fae h1:JalbO1PKAsbSYQBW6Q4aXbgj2w4bWofdrHxRRwqRgDc=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210717081259-8b8af59a0fae/go.mod h1:F6Q37CxDh2MHr5KXkcZmNB3tdkK7v+bgE+OpBY+9ilI=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723091746-c17d678a22f3 h1:CM9FGBPXLXhvKo0TuO4CKKdZLah6esP1SAfPzZDjEB0=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723091746-c17d678a22f3/go.mod h1:F6Q37CxDh2MHr5KXkcZmNB3tdkK7v+bgE+OpBY+9ilI=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723093538-596fe60a5dd5 h1:M6GI6DvsFgBGpp3+V+VB5okP1BGXISltz7acVYWWFOQ=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723093538-596fe60a5dd5/go.mod h1:F6Q37CxDh2MHr5KXkcZmNB3tdkK7v+bgE+OpBY+9ilI=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723094506-f0946ebceb7a h1:+N7J1NK7gxKZ+X4syY1HqafUudJiR8voJGcXWkxLgAw=
|
||||||
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20210723094506-f0946ebceb7a/go.mod h1:F6Q37CxDh2MHr5KXkcZmNB3tdkK7v+bgE+OpBY+9ilI=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
@ -249,6 +257,7 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/shuLhan/go-bindata v4.0.0+incompatible/go.mod h1:pkcPAATLBDD2+SpAPnX5vEM90F7fcwHCvvLCMXcmw3g=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
||||||
|
Copyright (c) 2018-2020 Andrea Spacca.
|
||||||
|
Copyright (c) 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -30,7 +32,6 @@ import (
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ func (s *Server) scanHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
abort := make(chan bool)
|
abort := make(chan bool)
|
||||||
response, err := c.ScanStream(reader, abort)
|
response, err := c.ScanStream(reader, abort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
https://github.com/fs111/kurz.go/blob/master/src/codec.go
|
|
||||||
|
|
||||||
Originally written and Copyright (c) 2011 André Kelpe
|
|
||||||
Modifications Copyright (c) 2015 John Ko
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"math/rand"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// characters used for short-urls
|
|
||||||
SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
|
|
||||||
// someone set us up the bomb !!
|
|
||||||
BASE = float64(len(SYMBOLS))
|
|
||||||
|
|
||||||
// init seed encode number
|
|
||||||
INIT_SEED = float64(-1)
|
|
||||||
)
|
|
||||||
|
|
||||||
// encodes a number into our *base* representation
|
|
||||||
// TODO can this be made better with some bitshifting?
|
|
||||||
func Encode(number float64, length int64) string {
|
|
||||||
if number == INIT_SEED {
|
|
||||||
seed := math.Pow(float64(BASE), float64(length))
|
|
||||||
number = seed + (rand.Float64() * seed) // start with seed to enforce desired length
|
|
||||||
}
|
|
||||||
|
|
||||||
rest := int64(math.Mod(number, BASE))
|
|
||||||
// strings are a bit weird in go...
|
|
||||||
result := string(SYMBOLS[rest])
|
|
||||||
if rest > 0 && number-float64(rest) != 0 {
|
|
||||||
newnumber := (number - float64(rest)) / BASE
|
|
||||||
result = Encode(newnumber, length) + result
|
|
||||||
} else {
|
|
||||||
// it would always be 1 because of starting with seed and we want to skip
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decodes a string given in our encoding and returns the decimal
|
|
||||||
// integer.
|
|
||||||
func Decode(input string) int64 {
|
|
||||||
const floatbase = float64(BASE)
|
|
||||||
l := len(input)
|
|
||||||
var sum int = 0
|
|
||||||
for index := l - 1; index > -1; index -= 1 {
|
|
||||||
current := string(input[index])
|
|
||||||
pos := strings.Index(SYMBOLS, current)
|
|
||||||
sum = sum + (pos * int(math.Pow(floatbase, float64((l-index-1)))))
|
|
||||||
}
|
|
||||||
return int64(sum)
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package server
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func BenchmarkEncodeConcat(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_ = Encode(INIT_SEED, 5) + Encode(INIT_SEED, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncodeLonger(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_ = Encode(INIT_SEED, 10)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,8 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
||||||
|
Copyright (c) 2018-2020 Andrea Spacca.
|
||||||
|
Copyright (c) 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -40,7 +42,6 @@ import (
|
||||||
html_template "html/template"
|
html_template "html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -125,7 +126,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
metadata, err := s.CheckMetadata(token, filename, false)
|
metadata, err := s.CheckMetadata(token, filename, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -237,16 +238,34 @@ func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
hostname := getURL(r, s.proxyPort).Host
|
hostname := getURL(r, s.proxyPort).Host
|
||||||
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
|
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
|
||||||
|
|
||||||
|
maxUploadSize := ""
|
||||||
|
if s.maxUploadSize > 0 {
|
||||||
|
maxUploadSize = formatSize(s.maxUploadSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
purgeTime := ""
|
||||||
|
if s.purgeDays > 0 {
|
||||||
|
purgeTime = s.purgeDays.String()
|
||||||
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
Hostname string
|
Hostname string
|
||||||
WebAddress string
|
WebAddress string
|
||||||
GAKey string
|
GAKey string
|
||||||
UserVoiceKey string
|
UserVoiceKey string
|
||||||
|
PurgeTime string
|
||||||
|
MaxUploadSize string
|
||||||
|
SampleToken string
|
||||||
|
SampleToken2 string
|
||||||
}{
|
}{
|
||||||
hostname,
|
hostname,
|
||||||
webAddress,
|
webAddress,
|
||||||
s.gaKey,
|
s.gaKey,
|
||||||
s.userVoiceKey,
|
s.userVoiceKey,
|
||||||
|
purgeTime,
|
||||||
|
maxUploadSize,
|
||||||
|
Token(s.randomTokenLength),
|
||||||
|
Token(s.randomTokenLength),
|
||||||
}
|
}
|
||||||
|
|
||||||
if acceptsHTML(r.Header) {
|
if acceptsHTML(r.Header) {
|
||||||
|
@ -272,12 +291,12 @@ func sanitize(fileName string) string {
|
||||||
|
|
||||||
func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := r.ParseMultipartForm(_24K); nil != err {
|
if err := r.ParseMultipartForm(_24K); nil != err {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Error occurred copying to output stream", 500)
|
http.Error(w, "Error occurred copying to output stream", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token := Encode(INIT_SEED, s.randomTokenLength)
|
token := Token(s.randomTokenLength)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
|
|
||||||
|
@ -290,7 +309,7 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if f, err = fheader.Open(); err != nil {
|
if f, err = fheader.Open(); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -299,7 +318,7 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
n, err := io.CopyN(&b, f, _24K+1)
|
n, err := io.CopyN(&b, f, _24K+1)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -310,14 +329,14 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if n > _24K {
|
if n > _24K {
|
||||||
file, err = ioutil.TempFile(s.tempPath, "transfer-")
|
file, err = ioutil.TempFile(s.tempPath, "transfer-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
s.logger.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = io.Copy(file, io.MultiReader(&b, f))
|
n, err = io.Copy(file, io.MultiReader(&b, f))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanTmpFile(file)
|
s.cleanTmpFile(file)
|
||||||
|
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -330,7 +349,7 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
contentLength := n
|
contentLength := n
|
||||||
|
|
||||||
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
||||||
log.Print("Entity too large")
|
s.logger.Print("Entity too large")
|
||||||
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -339,23 +358,23 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
buffer := &bytes.Buffer{}
|
buffer := &bytes.Buffer{}
|
||||||
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, errors.New("Could not encode metadata").Error(), 500)
|
http.Error(w, errors.New("Could not encode metadata").Error(), 500)
|
||||||
|
|
||||||
cleanTmpFile(file)
|
s.cleanTmpFile(file)
|
||||||
return
|
return
|
||||||
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, errors.New("Could not save metadata").Error(), 500)
|
http.Error(w, errors.New("Could not save metadata").Error(), 500)
|
||||||
|
|
||||||
cleanTmpFile(file)
|
s.cleanTmpFile(file)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
s.logger.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
||||||
|
|
||||||
if err = s.storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
if err = s.storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
||||||
log.Printf("Backend storage error: %s", err.Error())
|
s.logger.Printf("Backend storage error: %s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -365,21 +384,21 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
||||||
fmt.Fprintln(w, getURL(r, s.proxyPort).ResolveReference(relativeURL).String())
|
fmt.Fprintln(w, getURL(r, s.proxyPort).ResolveReference(relativeURL).String())
|
||||||
|
|
||||||
cleanTmpFile(file)
|
s.cleanTmpFile(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanTmpFile(f *os.File) {
|
func (s *Server) cleanTmpFile(f *os.File) {
|
||||||
if f != nil {
|
if f != nil {
|
||||||
err := f.Close()
|
err := f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error closing tmpfile: %s (%s)", err, f.Name())
|
s.logger.Printf("Error closing tmpfile: %s (%s)", err, f.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Remove(f.Name())
|
err = os.Remove(f.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error removing tmpfile: %s (%s)", err, f.Name())
|
s.logger.Printf("Error removing tmpfile: %s (%s)", err, f.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,13 +418,13 @@ type Metadata struct {
|
||||||
DeletionToken string
|
DeletionToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MetadataForRequest(contentType string, randomTokenLength int64, r *http.Request) Metadata {
|
func MetadataForRequest(contentType string, randomTokenLength int, r *http.Request) Metadata {
|
||||||
metadata := Metadata{
|
metadata := Metadata{
|
||||||
ContentType: strings.ToLower(contentType),
|
ContentType: strings.ToLower(contentType),
|
||||||
MaxDate: time.Time{},
|
MaxDate: time.Time{},
|
||||||
Downloads: 0,
|
Downloads: 0,
|
||||||
MaxDownloads: -1,
|
MaxDownloads: -1,
|
||||||
DeletionToken: Encode(INIT_SEED, randomTokenLength) + Encode(INIT_SEED, randomTokenLength),
|
DeletionToken: Token(randomTokenLength) + Token(randomTokenLength),
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := r.Header.Get("Max-Downloads"); v == "" {
|
if v := r.Header.Get("Max-Downloads"); v == "" {
|
||||||
|
@ -447,7 +466,7 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
n, err := io.CopyN(&b, f, _24K+1)
|
n, err := io.CopyN(&b, f, _24K+1)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
log.Printf("Error putting new file: %s", err.Error())
|
s.logger.Printf("Error putting new file: %s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -457,16 +476,16 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if n > _24K {
|
if n > _24K {
|
||||||
file, err = ioutil.TempFile(s.tempPath, "transfer-")
|
file, err = ioutil.TempFile(s.tempPath, "transfer-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cleanTmpFile(file)
|
defer s.cleanTmpFile(file)
|
||||||
|
|
||||||
n, err = io.Copy(file, io.MultiReader(&b, f))
|
n, err = io.Copy(file, io.MultiReader(&b, f))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -480,40 +499,40 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
||||||
log.Print("Entity too large")
|
s.logger.Print("Entity too large")
|
||||||
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if contentLength == 0 {
|
if contentLength == 0 {
|
||||||
log.Print("Empty content-length")
|
s.logger.Print("Empty content-length")
|
||||||
http.Error(w, errors.New("Could not upload empty file").Error(), 400)
|
http.Error(w, errors.New("Could not upload empty file").Error(), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contentType := mime.TypeByExtension(filepath.Ext(vars["filename"]))
|
contentType := mime.TypeByExtension(filepath.Ext(vars["filename"]))
|
||||||
|
|
||||||
token := Encode(INIT_SEED, s.randomTokenLength)
|
token := Token(s.randomTokenLength)
|
||||||
|
|
||||||
metadata := MetadataForRequest(contentType, s.randomTokenLength, r)
|
metadata := MetadataForRequest(contentType, s.randomTokenLength, r)
|
||||||
|
|
||||||
buffer := &bytes.Buffer{}
|
buffer := &bytes.Buffer{}
|
||||||
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, errors.New("Could not encode metadata").Error(), 500)
|
http.Error(w, errors.New("Could not encode metadata").Error(), 500)
|
||||||
return
|
return
|
||||||
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, errors.New("Could not save metadata").Error(), 500)
|
http.Error(w, errors.New("Could not save metadata").Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
s.logger.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if err = s.storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
if err = s.storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
||||||
log.Printf("Error putting new file: %s", err.Error())
|
s.logger.Printf("Error putting new file: %s", err.Error())
|
||||||
http.Error(w, errors.New("Could not save file").Error(), 500)
|
http.Error(w, errors.New("Could not save file").Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -637,23 +656,22 @@ func (metadata Metadata) remainingLimitHeaderValues() (remainingDownloads, remai
|
||||||
return remainingDownloads, remainingDays
|
return remainingDownloads, remainingDays
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Lock(token, filename string) error {
|
func (s *Server) Lock(token, filename string) {
|
||||||
key := path.Join(token, filename)
|
key := path.Join(token, filename)
|
||||||
|
|
||||||
if _, ok := s.locks[key]; !ok {
|
lock, _ := s.locks.LoadOrStore(key, &sync.Mutex{})
|
||||||
s.locks[key] = &sync.Mutex{}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.locks[key].Lock()
|
lock.(*sync.Mutex).Lock()
|
||||||
|
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Unlock(token, filename string) error {
|
func (s *Server) Unlock(token, filename string) {
|
||||||
key := path.Join(token, filename)
|
key := path.Join(token, filename)
|
||||||
s.locks[key].Unlock()
|
|
||||||
|
|
||||||
return nil
|
lock, _ := s.locks.LoadOrStore(key, &sync.Mutex{})
|
||||||
|
|
||||||
|
lock.(*sync.Mutex).Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CheckMetadata(token, filename string, increaseDownload bool) (Metadata, error) {
|
func (s *Server) CheckMetadata(token, filename string, increaseDownload bool) (Metadata, error) {
|
||||||
|
@ -723,7 +741,7 @@ func (s *Server) purgeHandler() {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
err := s.storage.Purge(s.purgeDays)
|
err := s.storage.Purge(s.purgeDays)
|
||||||
log.Printf("error cleaning up expired files: %v", err)
|
s.logger.Printf("error cleaning up expired files: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -737,7 +755,7 @@ func (s *Server) deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
deletionToken := vars["deletionToken"]
|
deletionToken := vars["deletionToken"]
|
||||||
|
|
||||||
if err := s.CheckDeletionToken(deletionToken, token, filename); err != nil {
|
if err := s.CheckDeletionToken(deletionToken, token, filename); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -747,7 +765,7 @@ func (s *Server) deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not delete file.", 500)
|
http.Error(w, "Could not delete file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -773,7 +791,7 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
filename := sanitize(strings.Split(key, "/")[1])
|
filename := sanitize(strings.Split(key, "/")[1])
|
||||||
|
|
||||||
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,7 +802,7 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not retrieve file.", 500)
|
http.Error(w, "Could not retrieve file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -802,20 +820,20 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
fw, err := zw.CreateHeader(header)
|
fw, err := zw.CreateHeader(header)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = io.Copy(fw, reader); err != nil {
|
if _, err = io.Copy(fw, reader); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := zw.Close(); err != nil {
|
if err := zw.Close(); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -845,7 +863,7 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
filename := sanitize(strings.Split(key, "/")[1])
|
filename := sanitize(strings.Split(key, "/")[1])
|
||||||
|
|
||||||
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,7 +873,7 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not retrieve file.", 500)
|
http.Error(w, "Could not retrieve file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -870,13 +888,13 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
err = zw.WriteHeader(header)
|
err = zw.WriteHeader(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = io.Copy(zw, reader); err != nil {
|
if _, err = io.Copy(zw, reader); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -904,7 +922,7 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
filename := strings.Split(key, "/")[1]
|
filename := strings.Split(key, "/")[1]
|
||||||
|
|
||||||
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +932,7 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not retrieve file.", 500)
|
http.Error(w, "Could not retrieve file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -929,13 +947,13 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
err = zw.WriteHeader(header)
|
err = zw.WriteHeader(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = io.Copy(zw, reader); err != nil {
|
if _, err = io.Copy(zw, reader); err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Internal server error.", 500)
|
http.Error(w, "Internal server error.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -951,7 +969,7 @@ func (s *Server) headHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
metadata, err := s.CheckMetadata(token, filename, false)
|
metadata, err := s.CheckMetadata(token, filename, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -962,7 +980,7 @@ func (s *Server) headHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not retrieve file.", 500)
|
http.Error(w, "Could not retrieve file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -986,7 +1004,7 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
metadata, err := s.CheckMetadata(token, filename, true)
|
metadata, err := s.CheckMetadata(token, filename, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
s.logger.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -997,7 +1015,7 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Printf("%s", err.Error())
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Could not retrieve file.", 500)
|
http.Error(w, "Could not retrieve file.", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1025,41 +1043,34 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
reader = ioutil.NopCloser(bluemonday.UGCPolicy().SanitizeReader(reader))
|
reader = ioutil.NopCloser(bluemonday.UGCPolicy().SanitizeReader(reader))
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.Header().Get("Range") == "" {
|
if w.Header().Get("Range") != "" || strings.HasPrefix(metadata.ContentType, "video") || strings.HasPrefix(metadata.ContentType, "audio") {
|
||||||
if _, err = io.Copy(w, reader); err != nil {
|
file, err := ioutil.TempFile(s.tempPath, "range-")
|
||||||
log.Printf("%s", err.Error())
|
if err != nil {
|
||||||
|
s.logger.Printf("%s", err.Error())
|
||||||
http.Error(w, "Error occurred copying to output stream", 500)
|
http.Error(w, "Error occurred copying to output stream", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer s.cleanTmpFile(file)
|
||||||
|
|
||||||
|
_, err = io.Copy(file, reader)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("%s", err.Error())
|
||||||
|
http.Error(w, "Error occurred copying to output stream", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.ServeContent(w, r, filename, time.Now(), file)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := ioutil.TempFile(s.tempPath, "range-")
|
if _, err = io.Copy(w, reader); err != nil {
|
||||||
if err != nil {
|
s.logger.Printf("%s", err.Error())
|
||||||
log.Printf("%s", err.Error())
|
|
||||||
http.Error(w, "Error occurred copying to output stream", 500)
|
http.Error(w, "Error occurred copying to output stream", 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cleanTmpFile(file)
|
return
|
||||||
|
|
||||||
tee := io.TeeReader(reader, file)
|
|
||||||
for {
|
|
||||||
b := make([]byte, _5M)
|
|
||||||
_, err = tee.Read(b)
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("%s", err.Error())
|
|
||||||
http.Error(w, "Error occurred copying to output stream", 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
http.ServeContent(w, r, filename, time.Now(), file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RedirectHandler(h http.Handler) http.HandlerFunc {
|
func (s *Server) RedirectHandler(h http.Handler) http.HandlerFunc {
|
||||||
|
|
|
@ -161,7 +161,7 @@ func LogFile(logger *log.Logger, s string) OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
f, err := os.OpenFile(s, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
f, err := os.OpenFile(s, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error opening file: %v", err)
|
logger.Fatalf("error opening file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.SetOutput(f)
|
logger.SetOutput(f)
|
||||||
|
@ -187,7 +187,7 @@ func RateLimit(requests int) OptionFn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandomTokenLength(length int64) OptionFn {
|
func RandomTokenLength(length int) OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
srvr.randomTokenLength = length
|
srvr.randomTokenLength = length
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ type Server struct {
|
||||||
|
|
||||||
profilerEnabled bool
|
profilerEnabled bool
|
||||||
|
|
||||||
locks map[string]*sync.Mutex
|
locks sync.Map
|
||||||
|
|
||||||
maxUploadSize int64
|
maxUploadSize int64
|
||||||
rateLimitRequests int
|
rateLimitRequests int
|
||||||
|
@ -300,7 +300,7 @@ type Server struct {
|
||||||
|
|
||||||
forceHTTPs bool
|
forceHTTPs bool
|
||||||
|
|
||||||
randomTokenLength int64
|
randomTokenLength int
|
||||||
|
|
||||||
ipFilterOptions *IPFilterOptions
|
ipFilterOptions *IPFilterOptions
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ type Server struct {
|
||||||
|
|
||||||
func New(options ...OptionFn) (*Server, error) {
|
func New(options ...OptionFn) (*Server, error) {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
locks: map[string]*sync.Mutex{},
|
locks: sync.Map{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, optionFn := range options {
|
for _, optionFn := range options {
|
||||||
|
|
45
server/token.go
Normal file
45
server/token.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// characters used for short-urls
|
||||||
|
SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
)
|
||||||
|
|
||||||
|
// generate a token
|
||||||
|
func Token(length int) string {
|
||||||
|
result := ""
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
x := rand.Intn(len(SYMBOLS) - 1)
|
||||||
|
result = string(SYMBOLS[x]) + result
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
15
server/token_test.go
Normal file
15
server/token_test.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func BenchmarkTokenConcat(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = Token(5) + Token(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTokenLonger(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = Token(10)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
Copyright (c) 2014-2017 DutchCoders [https://github.com/dutchcoders/]
|
||||||
|
Copyright (c) 2018-2020 Andrea Spacca.
|
||||||
|
Copyright (c) 2020- Andrea Spacca and Stefan Benten.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -25,6 +27,7 @@ THE SOFTWARE.
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
|
@ -47,7 +50,6 @@ func getAwsSession(accessKey, secretKey, region, endpoint string, forcePathStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatNumber(format string, s uint64) string {
|
func formatNumber(format string, s uint64) string {
|
||||||
|
|
||||||
return RenderFloat(format, float64(s))
|
return RenderFloat(format, float64(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,3 +255,27 @@ func acceptsHTML(hdr http.Header) bool {
|
||||||
|
|
||||||
return (false)
|
return (false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatSize(size int64) string {
|
||||||
|
sizeFloat := float64(size)
|
||||||
|
base := math.Log(sizeFloat) / math.Log(1024)
|
||||||
|
|
||||||
|
sizeOn := math.Pow(1024, base-math.Floor(base))
|
||||||
|
|
||||||
|
var round float64
|
||||||
|
pow := math.Pow(10, float64(2))
|
||||||
|
digit := pow * sizeOn
|
||||||
|
round = math.Floor(digit)
|
||||||
|
|
||||||
|
newVal := round / pow
|
||||||
|
|
||||||
|
var suffixes [5]string
|
||||||
|
suffixes[0] = "B"
|
||||||
|
suffixes[1] = "KB"
|
||||||
|
suffixes[2] = "MB"
|
||||||
|
suffixes[3] = "GB"
|
||||||
|
suffixes[4] = "TB"
|
||||||
|
|
||||||
|
getSuffix := suffixes[int(math.Floor(base))]
|
||||||
|
return fmt.Sprintf("%s %s", strconv.FormatFloat(newVal, 'f', -1, 64), getSuffix)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue