1
0
mirror of https://github.com/dutchcoders/transfer.sh.git synced 2020-11-18 19:53:40 -08:00

Compare commits

..

No commits in common. "master" and "v1.1.5" have entirely different histories.

9 changed files with 74 additions and 249 deletions

View File

@ -1,89 +0,0 @@
name: Deploy multi-architecture Docker images for transfer.sh with buildx
on:
schedule:
- cron: '0 0 * * *' # everyday at midnight UTC
pull_request:
branches: master
push:
branches: master
tags:
- v*
jobs:
buildx:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Prepare
id: prepare
run: |
DOCKER_IMAGE=dutchcoders/transfer.sh
DOCKER_PLATFORMS=linux/amd64,linux/arm/v7,linux/arm64,linux/386
VERSION=edge
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
fi
if [ "${{ github.event_name }}" = "schedule" ]; then
VERSION=nightly
fi
TAGS="--tag ${DOCKER_IMAGE}:${VERSION}"
if [ $VERSION = edge -o $VERSION = nightly ]; then
TAGS="$TAGS --tag ${DOCKER_IMAGE}:latest"
fi
echo ::set-output name=docker_image::${DOCKER_IMAGE}
echo ::set-output name=version::${VERSION}
echo ::set-output name=buildx_args::--platform ${DOCKER_PLATFORMS} \
--build-arg VERSION=${VERSION} \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=${GITHUB_SHA::8} \
${TAGS} .
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
with:
platforms: all
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
version: latest
-
name: Available platforms
run: echo ${{ steps.buildx.outputs.platforms }}
-
name: Docker Buildx (build)
run: |
docker buildx build --no-cache --pull --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args }}
-
name: Docker Login
if: success() && github.event_name != 'pull_request'
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin
-
name: Docker Buildx (push)
if: success() && github.event_name != 'pull_request'
run: |
docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args }}
-
name: Docker Check Manifest
if: always() && github.event_name != 'pull_request'
run: |
docker run --rm mplatform/mquery ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}
-
name: Clear
if: always() && github.event_name != 'pull_request'
run: |
rm -f ${HOME}/.docker/config.json

View File

@ -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 -ldflags -a -tags netgo -ldflags '-w -extldflags "-static"' -o /go/bin/transfersh github.com/dutchcoders/transfer.sh RUN go get -u ./... && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags -a -tags netgo -ldflags '-w -extldflags "-static"' -o /go/bin/transfersh github.com/dutchcoders/transfer.sh
FROM scratch AS final FROM scratch AS final
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>" LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"

View File

@ -76,44 +76,40 @@ https://transfer.sh/1lDau/test.txt --> https://transfer.sh/inline/1lDau/test.txt
Parameter | Description | Value | Env Parameter | Description | Value | Env
--- | --- | --- | --- --- | --- | --- | ---
listener | port to use for http (:80) | | LISTENER | listener | port to use for http (:80) | |
profile-listener | port to use for profiler (:6060) | | PROFILE_LISTENER | profile-listener | port to use for profiler (:6060)| |
force-https | redirect to https | false | FORCE_HTTPS force-https | redirect to https | false |
tls-listener | port to use for https (:443) | | TLS_LISTENER | tls-listener | port to use for https (:443) | |
tls-listener-only | flag to enable tls listener only | | TLS_LISTENER_ONLY | tls-listener-only | flag to enable tls listener only | |
tls-cert-file | path to tls certificate | | TLS_CERT_FILE | tls-cert-file | path to tls certificate | |
tls-private-key | path to tls private key | | TLS_PRIVATE_KEY | tls-private-key | path to tls private key | |
http-auth-user | user for basic http auth on upload | | HTTP_AUTH_USER | http-auth-user | user for basic http auth on upload | |
http-auth-pass | pass for basic http auth on upload | | HTTP_AUTH_PASS | http-auth-pass | pass for basic http auth on upload | |
ip-whitelist | comma separated list of ips allowed to connect to the service | | IP_WHITELIST | ip-whitelist | comma separated list of ips allowed to connect to the service | |
ip-blacklist | comma separated list of ips not allowed to connect to the service | | IP_BLACKLIST | ip-blacklist | comma separated list of ips not allowed to connect to the service | |
temp-path | path to temp folder | system temp | TEMP_PATH | temp-path | path to temp folder | system temp |
web-path | path to static web files (for development or custom front end) | | WEB_PATH | web-path | path to static web files (for development or custom front end) | |
proxy-path | path prefix when service is run behind a proxy | | PROXY_PATH | proxy-path | path prefix when service is run behind a proxy | |
proxy-port | port of the proxy when the service is run behind a proxy | | PROXY_PORT | ga-key | google analytics key for the front end | |
ga-key | google analytics key for the front end | | GA_KEY | uservoice-key | user voice key for the front end | |
uservoice-key | user voice key for the front end | | USERVOICE_KEY | provider | which storage provider to use | (s3, gdrive or local) |
provider | which storage provider to use | (s3, gdrive or local) | PROVIDER | aws-access-key | aws access key | | AWS_ACCESS_KEY
aws-access-key | aws access key | | AWS_ACCESS_KEY | aws-secret-key | aws access key | | AWS_SECRET_KEY
aws-secret-key | aws access key | | AWS_SECRET_KEY | bucket | aws bucket | | BUCKET
bucket | aws bucket | | BUCKET | s3-endpoint | Custom S3 endpoint. | |
s3-endpoint | Custom S3 endpoint. | | S3_ENDPOINT | s3-region | region of the s3 bucket | eu-west-1 | S3_REGION
s3-region | region of the s3 bucket | eu-west-1 | S3_REGION | s3-no-multipart | disables s3 multipart upload | false | |
s3-no-multipart | disables s3 multipart upload | false | S3_NO_MULTIPART | s3-path-style | Forces path style URLs, required for Minio. | false | |
s3-path-style | Forces path style URLs, required for Minio. | false | S3_PATH_STYLE | basedir | path storage for local/gdrive provider| |
basedir | path storage for local/gdrive provider | | BASEDIR | gdrive-client-json-filepath | path to oauth client json config for gdrive provider| |
gdrive-client-json-filepath | path to oauth client json config for gdrive provider | | GDRIVE_CLIENT_JSON_FILEPATH | gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| |
gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| | GDRIVE_LOCAL_CONFIG_PATH | gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | |
gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | | GDRIVE_CHUNK_SIZE | lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | |
lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | | HOSTS | log | path to log file| |
log | path to log file| | LOG |
cors-domains | comma separated list of domains for CORS, setting it enable CORS | | CORS_DOMAINS |
clamav-host | host for clamav feature | | CLAMAV_HOST |
rate-limit | request per minute | | RATE_LIMIT |
If you want to use TLS using lets encrypt certificates, set lets-encrypt-hosts to your domain, set tls-listener to :443 and enable force-https. If you want to use TLS using lets encrypt certificates, set lets-encrypt-hosts to your domain, set tls-listener to :443 and enable force-https.
If you want to use TLS using your own certificates, set tls-listener to :443, force-https, tls-cert-file and tls-private-key. If you want to use TLS using your own certificates, set tls-listener to :443, force-https, tls-cert=file and tls-private-key.
## Development ## Development

View File

@ -12,7 +12,7 @@ import (
"google.golang.org/api/googleapi" "google.golang.org/api/googleapi"
) )
var Version = "1.1.7" var Version = "1.1.4"
var helpTemplate = `NAME: var helpTemplate = `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}
@ -37,7 +37,6 @@ var globalFlags = []cli.Flag{
Name: "listener", Name: "listener",
Usage: "127.0.0.1:8080", Usage: "127.0.0.1:8080",
Value: "127.0.0.1:8080", Value: "127.0.0.1:8080",
EnvVar: "LISTENER",
}, },
// redirect to https? // redirect to https?
// hostnames // hostnames
@ -45,75 +44,57 @@ var globalFlags = []cli.Flag{
Name: "profile-listener", Name: "profile-listener",
Usage: "127.0.0.1:6060", Usage: "127.0.0.1:6060",
Value: "", Value: "",
EnvVar: "PROFILE_LISTENER",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "force-https", Name: "force-https",
Usage: "", Usage: "",
EnvVar: "FORCE_HTTPS",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "tls-listener", Name: "tls-listener",
Usage: "127.0.0.1:8443", Usage: "127.0.0.1:8443",
Value: "", Value: "",
EnvVar: "TLS_LISTENER",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "tls-listener-only", Name: "tls-listener-only",
Usage: "", Usage: "",
EnvVar: "TLS_LISTENER_ONLY",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "tls-cert-file", Name: "tls-cert-file",
Value: "", Value: "",
EnvVar: "TLS_CERT_FILE",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "tls-private-key", Name: "tls-private-key",
Value: "", Value: "",
EnvVar: "TLS_PRIVATE_KEY",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "temp-path", Name: "temp-path",
Usage: "path to temp files", Usage: "path to temp files",
Value: os.TempDir(), Value: os.TempDir(),
EnvVar: "TEMP_PATH",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "web-path", Name: "web-path",
Usage: "path to static web files", Usage: "path to static web files",
Value: "", Value: "",
EnvVar: "WEB_PATH",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "proxy-path", Name: "proxy-path",
Usage: "path prefix when service is run behind a proxy", Usage: "path prefix when service is run behind a proxy",
Value: "", Value: "",
EnvVar: "PROXY_PATH",
},
cli.StringFlag{
Name: "proxy-port",
Usage: "port of the proxy when the service is run behind a proxy",
Value: "",
EnvVar: "PROXY_PORT",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "ga-key", Name: "ga-key",
Usage: "key for google analytics (front end)", Usage: "key for google analytics (front end)",
Value: "", Value: "",
EnvVar: "GA_KEY",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "uservoice-key", Name: "uservoice-key",
Usage: "key for user voice (front end)", Usage: "key for user voice (front end)",
Value: "", Value: "",
EnvVar: "USERVOICE_KEY",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "provider", Name: "provider",
Usage: "s3|gdrive|local", Usage: "s3|gdrive|local",
Value: "", Value: "",
EnvVar: "PROVIDER",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "s3-endpoint", Name: "s3-endpoint",
@ -148,36 +129,31 @@ var globalFlags = []cli.Flag{
cli.BoolFlag{ cli.BoolFlag{
Name: "s3-no-multipart", Name: "s3-no-multipart",
Usage: "Disables S3 Multipart Puts", Usage: "Disables S3 Multipart Puts",
EnvVar: "S3_NO_MULTIPART",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "s3-path-style", Name: "s3-path-style",
Usage: "Forces path style URLs, required for Minio.", Usage: "Forces path style URLs, required for Minio.",
EnvVar: "S3_PATH_STYLE",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "gdrive-client-json-filepath", Name: "gdrive-client-json-filepath",
Usage: "", Usage: "",
Value: "", Value: "",
EnvVar: "GDRIVE_CLIENT_JSON_FILEPATH",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "gdrive-local-config-path", Name: "gdrive-local-config-path",
Usage: "", Usage: "",
Value: "", Value: "",
EnvVar: "GDRIVE_LOCAL_CONFIG_PATH",
}, },
cli.IntFlag{ cli.IntFlag{
Name: "gdrive-chunk-size", Name: "gdrive-chunk-size",
Usage: "", Usage: "",
Value: googleapi.DefaultUploadChunkSize / 1024 / 1024, Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
EnvVar: "GDRIVE_CHUNK_SIZE",
}, },
cli.IntFlag{ cli.IntFlag{
Name: "rate-limit", Name: "rate-limit",
Usage: "requests per minute", Usage: "requests per minute",
Value: 0, Value: 0,
EnvVar: "RATE_LIMIT", EnvVar: "",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "lets-encrypt-hosts", Name: "lets-encrypt-hosts",
@ -189,13 +165,11 @@ var globalFlags = []cli.Flag{
Name: "log", Name: "log",
Usage: "/var/log/transfersh.log", Usage: "/var/log/transfersh.log",
Value: "", Value: "",
EnvVar: "LOG",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "basedir", Name: "basedir",
Usage: "path to storage", Usage: "path to storage",
Value: "", Value: "",
EnvVar: "BASEDIR",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "clamav-host", Name: "clamav-host",
@ -212,37 +186,26 @@ var globalFlags = []cli.Flag{
cli.BoolFlag{ cli.BoolFlag{
Name: "profiler", Name: "profiler",
Usage: "enable profiling", Usage: "enable profiling",
EnvVar: "PROFILER",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "http-auth-user", Name: "http-auth-user",
Usage: "user for http basic auth", Usage: "user for http basic auth",
Value: "", Value: "",
EnvVar: "HTTP_AUTH_USER",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "http-auth-pass", Name: "http-auth-pass",
Usage: "pass for http basic auth", Usage: "pass for http basic auth",
Value: "", Value: "",
EnvVar: "HTTP_AUTH_PASS",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "ip-whitelist", Name: "ip-whitelist",
Usage: "comma separated list of ips allowed to connect to the service", Usage: "comma separated list of ips allowed to connect to the service",
Value: "", Value: "",
EnvVar: "IP_WHITELIST",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "ip-blacklist", Name: "ip-blacklist",
Usage: "comma separated list of ips not allowed to connect to the service", Usage: "comma separated list of ips not allowed to connect to the service",
Value: "", Value: "",
EnvVar: "IP_BLACKLIST",
},
cli.StringFlag{
Name: "cors-domains",
Usage: "comma separated list of domains allowed for CORS requests",
Value: "",
EnvVar: "CORS_DOMAINS",
}, },
} }
@ -251,7 +214,7 @@ type Cmd struct {
} }
func VersionAction(c *cli.Context) { func VersionAction(c *cli.Context) {
fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh %s: Easy file sharing from the command line", Version))) fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh: Easy file sharing from the command line")))
} }
func New() *Cmd { func New() *Cmd {
@ -282,10 +245,6 @@ func New() *Cmd {
options = append(options, server.Listener(v)) options = append(options, server.Listener(v))
} }
if v := c.String("cors-domains"); v != "" {
options = append(options, server.CorsDomains(v))
}
if v := c.String("tls-listener"); v == "" { if v := c.String("tls-listener"); v == "" {
} else if c.Bool("tls-listener-only") { } else if c.Bool("tls-listener-only") {
options = append(options, server.TLSListener(v, true)) options = append(options, server.TLSListener(v, true))
@ -305,10 +264,6 @@ func New() *Cmd {
options = append(options, server.ProxyPath(v)) options = append(options, server.ProxyPath(v))
} }
if v := c.String("proxy-port"); v != "" {
options = append(options, server.ProxyPort(v))
}
if v := c.String("ga-key"); v != "" { if v := c.String("ga-key"); v != "" {
options = append(options, server.GoogleAnalytics(v)) options = append(options, server.GoogleAnalytics(v))
} }

1
go.mod
View File

@ -16,7 +16,6 @@ require (
github.com/garyburd/redigo v1.6.0 // indirect github.com/garyburd/redigo v1.6.0 // indirect
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273 github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273
github.com/golang/protobuf v1.3.5 // indirect github.com/golang/protobuf v1.3.5 // indirect
github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/securecookie v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.3 // indirect github.com/hashicorp/golang-lru v0.5.3 // indirect

2
go.sum
View File

@ -127,8 +127,6 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=

View File

@ -158,9 +158,9 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
} }
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename)) relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
resolvedURL := resolveURL(r, relativeURL, s.proxyPort) resolvedURL := resolveURL(r, relativeURL)
relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename)) relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename))
resolvedURLGet := resolveURL(r, relativeURLGet, s.proxyPort) resolvedURLGet := resolveURL(r, relativeURLGet)
var png []byte var png []byte
png, err = qrcode.Encode(resolvedURL, qrcode.High, 150) png, err = qrcode.Encode(resolvedURL, qrcode.High, 150)
if err != nil { if err != nil {
@ -170,8 +170,8 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
qrCode := base64.StdEncoding.EncodeToString(png) qrCode := base64.StdEncoding.EncodeToString(png)
hostname := getURL(r, s.proxyPort).Host hostname := getURL(r).Host
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort) webAddress := resolveWebAddress(r, s.proxyPath)
data := struct { data := struct {
ContentType string ContentType string
@ -212,8 +212,8 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) { func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) {
// vars := mux.Vars(r) // vars := mux.Vars(r)
hostname := getURL(r, s.proxyPort).Host hostname := getURL(r).Host
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort) webAddress := resolveWebAddress(r, s.proxyPath)
data := struct { data := struct {
Hostname string Hostname string
@ -339,7 +339,7 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
filename = url.PathEscape(filename) filename = url.PathEscape(filename)
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).ResolveReference(relativeURL).String())
cleanTmpFile(file) cleanTmpFile(file)
} }
@ -500,15 +500,15 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename)) relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
deleteURL, _ := url.Parse(path.Join(s.proxyPath, token, filename, metadata.DeletionToken)) deleteURL, _ := url.Parse(path.Join(s.proxyPath, token, filename, metadata.DeletionToken))
w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL, s.proxyPort)) w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL))
fmt.Fprint(w, resolveURL(r, relativeURL, s.proxyPort)) fmt.Fprint(w, resolveURL(r, relativeURL))
} }
func resolveURL(r *http.Request, u *url.URL, proxyPort string) string { func resolveURL(r *http.Request, u *url.URL) string {
r.URL.Path = "" r.URL.Path = ""
return getURL(r, proxyPort).ResolveReference(u).String() return getURL(r).ResolveReference(u).String()
} }
func resolveKey(key, proxyPath string) string { func resolveKey(key, proxyPath string) string {
@ -525,8 +525,8 @@ func resolveKey(key, proxyPath string) string {
return key return key
} }
func resolveWebAddress(r *http.Request, proxyPath string, proxyPort string) string { func resolveWebAddress(r *http.Request, proxyPath string) string {
url := getURL(r, proxyPort) url := getURL(r)
var webAddress string var webAddress string
@ -544,7 +544,7 @@ func resolveWebAddress(r *http.Request, proxyPath string, proxyPort string) stri
return webAddress return webAddress
} }
func getURL(r *http.Request, proxyPort string) *url.URL { func getURL(r *http.Request) *url.URL {
u, _ := url.Parse(r.URL.String()) u, _ := url.Parse(r.URL.String())
if r.TLS != nil { if r.TLS != nil {
@ -555,25 +555,16 @@ func getURL(r *http.Request, proxyPort string) *url.URL {
u.Scheme = "http" u.Scheme = "http"
} }
if u.Host == "" { if u.Host != "" {
host, port, err := net.SplitHostPort(r.Host) } else if host, port, err := net.SplitHostPort(r.Host); err != nil {
if err != nil { u.Host = r.Host
host = r.Host } else {
port = "" if port == "80" && u.Scheme == "http" {
} u.Host = host
if len(proxyPort) != 0 { } else if port == "443" && u.Scheme == "https" {
port = proxyPort
}
if len(port) == 0 {
u.Host = host u.Host = host
} else { } else {
if port == "80" && u.Scheme == "http" { u.Host = net.JoinHostPort(host, port)
u.Host = host
} else if port == "443" && u.Scheme == "https" {
u.Host = host
} else {
u.Host = net.JoinHostPort(host, port)
}
} }
} }
@ -623,7 +614,9 @@ func (s *Server) CheckMetadata(token, filename string, increaseDownload bool) (M
var metadata Metadata var metadata Metadata
r, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename)) r, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename))
if err != nil { if s.storage.IsNotExist(err) {
return metadata, nil
} else if err != nil {
return metadata, err return metadata, err
} }
@ -1018,7 +1011,7 @@ func (s *Server) RedirectHandler(h http.Handler) http.HandlerFunc {
} else if r.Header.Get("X-Forwarded-Proto") == "https" { } else if r.Header.Get("X-Forwarded-Proto") == "https" {
} else if r.URL.Scheme == "https" { } else if r.URL.Scheme == "https" {
} else { } else {
u := getURL(r, s.proxyPort) u := getURL(r)
u.Scheme = "https" u.Scheme = "https"
http.Redirect(w, r, u.String(), http.StatusPermanentRedirect) http.Redirect(w, r, u.String(), http.StatusPermanentRedirect)

View File

@ -26,10 +26,7 @@ package server
import ( import (
"errors" "errors"
gorillaHandlers "github.com/gorilla/handlers"
"log" "log"
crypto_rand "crypto/rand"
"encoding/binary"
"math/rand" "math/rand"
"mime" "mime"
"net/http" "net/http"
@ -88,13 +85,6 @@ func Listener(s string) OptionFn {
} }
func CorsDomains(s string) OptionFn {
return func(srvr *Server) {
srvr.CorsDomains = s
}
}
func GoogleAnalytics(gaKey string) OptionFn { func GoogleAnalytics(gaKey string) OptionFn {
return func(srvr *Server) { return func(srvr *Server) {
srvr.gaKey = gaKey srvr.gaKey = gaKey
@ -141,12 +131,6 @@ func ProxyPath(s string) OptionFn {
} }
} }
func ProxyPort(s string) OptionFn {
return func(srvr *Server) {
srvr.proxyPort = s
}
}
func TempPath(s string) OptionFn { func TempPath(s string) OptionFn {
return func(srvr *Server) { return func(srvr *Server) {
if s[len(s)-1:] != "/" { if s[len(s)-1:] != "/" {
@ -286,13 +270,11 @@ type Server struct {
webPath string webPath string
proxyPath string proxyPath string
proxyPort string
gaKey string gaKey string
userVoiceKey string userVoiceKey string
TLSListenerOnly bool TLSListenerOnly bool
CorsDomains string
ListenerString string ListenerString string
TLSListenerString string TLSListenerString string
ProfileListenerString string ProfileListenerString string
@ -315,11 +297,7 @@ func New(options ...OptionFn) (*Server, error) {
} }
func init() { func init() {
var seedBytes [8]byte rand.Seed(time.Now().UTC().UnixNano())
if _, err := crypto_rand.Read(seedBytes[:]); err != nil {
panic("cannot obtain cryptographically secure seed")
}
rand.Seed(int64(binary.LittleEndian.Uint64(seedBytes[:])))
} }
func (s *Server) Run() { func (s *Server) Run() {
@ -435,24 +413,11 @@ func (s *Server) Run() {
s.logger.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type()) s.logger.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type())
var cors func(http.Handler) http.Handler
if len(s.CorsDomains) > 0 {
cors = gorillaHandlers.CORS(
gorillaHandlers.AllowedHeaders([]string{"*"}),
gorillaHandlers.AllowedOrigins(strings.Split(s.CorsDomains, ",")),
gorillaHandlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"}),
)
} else {
cors = func(h http.Handler) http.Handler {
return h
}
}
h := handlers.PanicHandler( h := handlers.PanicHandler(
IPFilterHandler( IPFilterHandler(
handlers.LogHandler( handlers.LogHandler(
LoveHandler( LoveHandler(
s.RedirectHandler(cors(r))), s.RedirectHandler(r)),
handlers.NewLogOptions(s.logger.Printf, "_default_"), handlers.NewLogOptions(s.logger.Printf, "_default_"),
), ),
s.ipFilterOptions, s.ipFilterOptions,

View File

@ -32,20 +32,28 @@ func FuzzLocalStorage(fuzz []byte) int {
panic("unable to save file") panic("unable to save file")
} }
contentLength, err := storage.Head(token, filename) contentType, contentLength, err := storage.Head(token, filename)
if err != nil { if err != nil {
panic("not visible through head") panic("not visible through head")
} }
if contentType != applicationOctetStream {
panic("incorrect content type")
}
if contentLength != fuzzLength { if contentLength != fuzzLength {
panic("incorrect content length") panic("incorrect content length")
} }
output, contentLength, err := storage.Get(token, filename) output, contentType, contentLength, err := storage.Get(token, filename)
if err != nil { if err != nil {
panic("not visible through get") panic("not visible through get")
} }
if contentType != applicationOctetStream {
panic("incorrect content type")
}
if contentLength != fuzzLength { if contentLength != fuzzLength {
panic("incorrect content length") panic("incorrect content length")
} }
@ -73,7 +81,7 @@ func FuzzLocalStorage(fuzz []byte) int {
panic("unable to delete file") panic("unable to delete file")
} }
_, err = storage.Head(token, filename) _, _, err = storage.Head(token, filename)
if !storage.IsNotExist(err) { if !storage.IsNotExist(err) {
panic("file not deleted") panic("file not deleted")
} }