diff --git a/README.md b/README.md index c1ce53a..b2518e2 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,16 @@ go run transfersh-server/*.go -provider=local --port 8080 --temp=/tmp/ --basedir go build -o transfersh-server *.go ``` +## Docker + +For easy deployment we've enabled Docker deployment. + +``` +cd ./transfer-server/ +docker build -t transfersh . +docker run --publish 8080:8080 --rm transfersh --provider local --basedir /tmp/ +``` + ## Contributions Contributions are welcome. diff --git a/transfersh-server/.ebextensions/01config_nginx.config b/transfersh-server/.ebextensions/01config_nginx.config new file mode 100644 index 0000000..5b2b9cf --- /dev/null +++ b/transfersh-server/.ebextensions/01config_nginx.config @@ -0,0 +1,6 @@ +files: + "/etc/nginx/conf.d/client_max_body_size.conf": + mode: "000644" + owner: root + group: root + content: "client_max_body_size 0;" diff --git a/transfersh-server/handlers.go b/transfersh-server/handlers.go index a21297b..d1aad70 100644 --- a/transfersh-server/handlers.go +++ b/transfersh-server/handlers.go @@ -76,9 +76,9 @@ func previewHandler(w http.ResponseWriter, r *http.Request) { switch { case strings.HasPrefix(contentType, "image/"): - templatePath = "static/download.image.html" + templatePath = "download.image.html" case strings.HasPrefix(contentType, "text/"): - templatePath = "static/download.md.html" + templatePath = "download.md.html" var reader io.ReadCloser if reader, _, _, err = storage.Get(token, filename); err != nil { @@ -100,12 +100,12 @@ func previewHandler(w http.ResponseWriter, r *http.Request) { content = html_template.HTML(data) } - templatePath = "static/download.md.html" + templatePath = "download.md.html" default: - templatePath = "static/download.html" + templatePath = "download.html" } - tmpl, err := html_template.ParseFiles(templatePath) + tmpl, err := html_template.New(templatePath).Funcs(html_template.FuncMap{"format": formatNumber}).ParseFiles("static/" + templatePath) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -126,7 +126,7 @@ func previewHandler(w http.ResponseWriter, r *http.Request) { contentLength, } - if err := tmpl.Execute(w, data); err != nil { + if err := tmpl.ExecuteTemplate(w, templatePath, data); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/transfersh-server/main.go b/transfersh-server/main.go index 936c7cb..7186fba 100644 --- a/transfersh-server/main.go +++ b/transfersh-server/main.go @@ -88,27 +88,26 @@ func main() { r.HandleFunc("/({files:.*}).tar.gz", tarGzHandler).Methods("GET") r.HandleFunc("/download/{token}/{filename}", getHandler).Methods("GET") - r.HandleFunc("/{token}/{filename}", previewHandler).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool { + r.HandleFunc("/{token}/{filename}", previewHandler).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) (match bool) { + match = false + // The file will show a preview page when opening the link in browser directly or - // from external link. Otherwise it will download the file immediatly. + // from external link. If the referer url path and current path are the same it will be + // downloaded. if !acceptsHtml(r.Header) { return false } - match := (r.Referer() == "") + match = (r.Referer() == "") u, err := url.Parse(r.Referer()) if err != nil { log.Fatal(err) - return match + return } - match = match || (u.Host == "transfersh.elasticbeanstalk.com") - match = match || (u.Host == "jxm5d6emw5rknovg.onion") - match = match || (u.Host == "transfer.sh") - match = match || (u.Host == "127.0.0.1") - - return match + match = match || (u.Path != r.URL.Path) + return }).Methods("GET") r.HandleFunc("/{token}/{filename}", getHandler).Methods("GET") diff --git a/transfersh-server/static/download.html b/transfersh-server/static/download.html index 71d8fbe..d0df7a4 100644 --- a/transfersh-server/static/download.html +++ b/transfersh-server/static/download.html @@ -57,12 +57,9 @@

-

- {{.Filename}}

-

- Type: {{.ContentType}}

-

- Length: {{.ContentLength}} bytes

+

{{.Filename}}

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes

copy link    download diff --git a/transfersh-server/static/download.image.html b/transfersh-server/static/download.image.html index aa8cd46..8c74902 100644 --- a/transfersh-server/static/download.image.html +++ b/transfersh-server/static/download.image.html @@ -56,10 +56,9 @@

-

- {{.Filename}}

- - +

{{.Filename}}

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes

diff --git a/transfersh-server/static/download.md.html b/transfersh-server/static/download.md.html index 2f41183..bc35e4b 100644 --- a/transfersh-server/static/download.md.html +++ b/transfersh-server/static/download.md.html @@ -55,9 +55,10 @@
+

{{.Filename}}

-

Type: {{.ContentType}}

-

Length: {{.ContentLength}} bytes

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes

diff --git a/transfersh-server/utils.go b/transfersh-server/utils.go index 3426886..c5afb37 100644 --- a/transfersh-server/utils.go +++ b/transfersh-server/utils.go @@ -28,8 +28,10 @@ import ( "github.com/goamz/goamz/aws" "github.com/goamz/goamz/s3" "github.com/golang/gddo/httputil/header" + "math" "net/http" "net/mail" + "strconv" "strings" "time" ) @@ -45,6 +47,163 @@ func getBucket() (*s3.Bucket, error) { return b, nil } +func formatNumber(format string, s uint64) string { + + return RenderFloat(format, float64(s)) +} + +var renderFloatPrecisionMultipliers = [10]float64{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, +} + +var renderFloatPrecisionRounders = [10]float64{ + 0.5, + 0.05, + 0.005, + 0.0005, + 0.00005, + 0.000005, + 0.0000005, + 0.00000005, + 0.000000005, + 0.0000000005, +} + +func RenderFloat(format string, n float64) string { + // Special cases: + // NaN = "NaN" + // +Inf = "+Infinity" + // -Inf = "-Infinity" + if math.IsNaN(n) { + return "NaN" + } + if n > math.MaxFloat64 { + return "Infinity" + } + if n < -math.MaxFloat64 { + return "-Infinity" + } + + // default format + precision := 2 + decimalStr := "." + thousandStr := "," + positiveStr := "" + negativeStr := "-" + + if len(format) > 0 { + // If there is an explicit format directive, + // then default values are these: + precision = 9 + thousandStr = "" + + // collect indices of meaningful formatting directives + formatDirectiveChars := []rune(format) + formatDirectiveIndices := make([]int, 0) + for i, char := range formatDirectiveChars { + if char != '#' && char != '0' { + formatDirectiveIndices = append(formatDirectiveIndices, i) + } + } + + if len(formatDirectiveIndices) > 0 { + // Directive at index 0: + // Must be a '+' + // Raise an error if not the case + // index: 0123456789 + // +0.000,000 + // +000,000.0 + // +0000.00 + // +0000 + if formatDirectiveIndices[0] == 0 { + if formatDirectiveChars[formatDirectiveIndices[0]] != '+' { + panic("RenderFloat(): invalid positive sign directive") + } + positiveStr = "+" + formatDirectiveIndices = formatDirectiveIndices[1:] + } + + // Two directives: + // First is thousands separator + // Raise an error if not followed by 3-digit + // 0123456789 + // 0.000,000 + // 000,000.00 + if len(formatDirectiveIndices) == 2 { + if (formatDirectiveIndices[1] - formatDirectiveIndices[0]) != 4 { + panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers") + } + thousandStr = string(formatDirectiveChars[formatDirectiveIndices[0]]) + formatDirectiveIndices = formatDirectiveIndices[1:] + } + + // One directive: + // Directive is decimal separator + // The number of digit-specifier following the separator indicates wanted precision + // 0123456789 + // 0.00 + // 000,0000 + if len(formatDirectiveIndices) == 1 { + decimalStr = string(formatDirectiveChars[formatDirectiveIndices[0]]) + precision = len(formatDirectiveChars) - formatDirectiveIndices[0] - 1 + } + } + } + + // generate sign part + var signStr string + if n >= 0.000000001 { + signStr = positiveStr + } else if n <= -0.000000001 { + signStr = negativeStr + n = -n + } else { + signStr = "" + n = 0.0 + } + + // split number into integer and fractional parts + intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision]) + + // generate integer part string + intStr := strconv.Itoa(int(intf)) + + // add thousand separator if required + if len(thousandStr) > 0 { + for i := len(intStr); i > 3; { + i -= 3 + intStr = intStr[:i] + thousandStr + intStr[i:] + } + } + + // no fractional part, we can leave now + if precision == 0 { + return signStr + intStr + } + + // generate fractional part + fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision])) + // may need padding + if len(fracStr) < precision { + fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr + } + + return signStr + intStr + decimalStr + fracStr +} + +func RenderInteger(format string, n int) string { + return RenderFloat(format, float64(n)) +} + // Request.RemoteAddress contains port, which we want to remove i.e.: // "[::1]:58292" => "[::1]" func ipAddrFromRemoteAddr(s string) string { diff --git a/transfersh-web/download.html b/transfersh-web/download.html index b2feefd..18d7ea7 100644 --- a/transfersh-web/download.html +++ b/transfersh-web/download.html @@ -31,12 +31,9 @@ include "includes/head.html"

-

- {{.Filename}}

-

- Type: {{.ContentType}}

-

- Length: {{.ContentLength}} bytes

+

{{.Filename}}

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes

copy link    download diff --git a/transfersh-web/download.image.html b/transfersh-web/download.image.html index 3999e3e..f4b9666 100644 --- a/transfersh-web/download.image.html +++ b/transfersh-web/download.image.html @@ -30,10 +30,9 @@ include "includes/head.html"

-

- {{.Filename}}

- - +

{{.Filename}}

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes

diff --git a/transfersh-web/download.md.html b/transfersh-web/download.md.html index 7b34453..c2c1655 100644 --- a/transfersh-web/download.md.html +++ b/transfersh-web/download.md.html @@ -29,9 +29,10 @@ include "includes/head.html"
+

{{.Filename}}

-

Type: {{.ContentType}}

-

Length: {{.ContentLength}} bytes

+

type: {{.ContentType}}

+

size: {{.ContentLength | format "#,###."}} bytes