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

Compare commits

...

28 Commits

Author SHA1 Message Date
Andrea Spacca
ae00f8ceaa
Merge pull request #331 from zuh0/official-docker-buildx-ghaction
ci: switch to official docker buildx GitHub action
2020-10-26 09:08:38 +01:00
Gabriel Duque
ec9db7a42e
ci: switch to official docker buildx GitHub action
Signed-off-by: Gabriel Duque <gabriel@zuh0.com>
2020-10-21 00:30:52 +02:00
Andrea Spacca
bcf40c15a2
Merge pull request #330 from stillwondering/show-version-in-version-command
Include version string in version command output
2020-10-12 19:33:08 +02:00
stillwondering
fe1cde6614
Include version string in version command output
The command `transfer.sh version` does not include the application's
version string in its output. Fix this.
2020-10-12 13:25:29 +02:00
Andrea Spacca
ffb2cf0011
Merge pull request #317 from zuh0/multi-architecture-docker-images
ci: deploy multi-architecture Docker images using buildx
2020-06-21 20:41:17 +02:00
Gabriel Duque
085e9f8414
ci: deploy multi-architecture Docker images using buildx
Signed-off-by: Gabriel Duque <gabriel@zuh0.com>
2020-06-14 21:57:48 +02:00
Andrea Spacca
a4bf102d29
Merge pull request #315 from dutchcoders/revert-314-ISSUE-313-BUILDX
Revert "ISSUE-313-BUILDX"
2020-06-14 20:01:51 +02:00
Andrea Spacca
c8497fb27d
Revert "ISSUE-313-BUILDX" 2020-06-14 20:01:38 +02:00
Andrea Spacca
68212d100e
Merge pull request #314 from dutchcoders/ISSUE-313-BUILDX
ISSUE-313-BUILDX
2020-06-14 19:56:02 +02:00
Andrea Spacca
18f4b42cf1 ISSUE-313-BUILDX 2020-06-14 19:53:36 +02:00
Andrea Spacca
92055f1b3c
Merge pull request #274 from eksoverzero/os_and_arch
Remove explicit OS and Arch builds
2020-05-17 20:12:38 +02:00
Andrea Spacca
9430e53689
Merge pull request #307 from cheeseandcereal/add_proxy_port
add proxy-port for port override when running behind a proxy
2020-05-17 19:28:21 +02:00
Andrea Spacca
a26b32dd86
Merge pull request #311 from cheeseandcereal/crypto_seed
use cryptographically secure rng seed
2020-05-17 19:10:56 +02:00
Adam Crowder
0a6b5817a9
use cryptographically secure rng seed
Signed-off-by: Adam Crowder <adam@adamcrowder.net>
2020-05-11 18:57:04 -07:00
Andrea Spacca
5e7e3a1b39 v1.1.7 2020-05-09 12:00:53 +02:00
Andrea Spacca
42adceb4c6
Merge pull request #309 from cheeseandcereal/fix_arbitrary_reading
fix missing metadata security vuln
2020-05-09 11:59:37 +02:00
Adam Crowder
f909ad3ce2
fix missing metadata security vuln 2020-05-08 16:23:32 -07:00
Adam Crowder
d830bf1afc
revert println
Signed-off-by: Adam Crowder <adam@adamcrowder.net>
2020-05-08 11:49:21 -07:00
Adam Crowder
f366e8217e
add proxy-port for port override when running behind a proxy
Signed-off-by: Adam Crowder <adam@adamcrowder.net>
2020-05-03 13:26:49 -07:00
Andrea Spacca
8a5c737140 UPDATE README.md 2020-05-03 15:28:59 +02:00
Andrea Spacca
b920eb842a
Merge pull request #304 from tofuSCHNITZEL/master
Added EnvVar to all flags
2020-05-03 13:28:21 +02:00
Tobias Perschon
45e0967a37
Update cmd.go
added EnvVar to all flags
2020-04-24 10:32:31 +02:00
Andrea Spacca
28614c991d
Merge pull request #297 from dutchcoders/ISSUE-296
ISSUE-296 add CORS
2020-04-07 15:31:41 +02:00
Andrea Spacca
ef28bcb28f ISSUE-296 add CORS 2020-04-04 14:29:33 +02:00
Andrea Spacca
2dd23bff3c
Merge pull request #291 from dutchcoders/ISSUE-278
ISSUE 278
2020-03-24 08:34:02 +01:00
Andrea Spacca
663c59e754 ISSUE 278 2020-03-23 09:22:58 +01:00
Andrea Spacca
38d643e12b fix fuzzy 2020-03-15 20:09:12 +01:00
Steven Eksteen
9297c253aa Remove explicit OS and Arch builds
This could allow multi-arch supporting using `docker buildx`
2019-11-13 21:19:04 +02:00
9 changed files with 249 additions and 74 deletions

View File

@ -0,0 +1,89 @@
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 GOOS=linux GOARCH=amd64 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 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,40 +76,44 @@ 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 | port to use for http (:80) | | LISTENER |
profile-listener | port to use for profiler (:6060)| | profile-listener | port to use for profiler (:6060) | | PROFILE_LISTENER |
force-https | redirect to https | false | force-https | redirect to https | false | FORCE_HTTPS
tls-listener | port to use for https (:443) | | tls-listener | port to use for https (:443) | | TLS_LISTENER |
tls-listener-only | flag to enable tls listener only | | tls-listener-only | flag to enable tls listener only | | TLS_LISTENER_ONLY |
tls-cert-file | path to tls certificate | | tls-cert-file | path to tls certificate | | TLS_CERT_FILE |
tls-private-key | path to tls private key | | tls-private-key | path to tls private key | | TLS_PRIVATE_KEY |
http-auth-user | user for basic http auth on upload | | http-auth-user | user for basic http auth on upload | | HTTP_AUTH_USER |
http-auth-pass | pass for basic http auth on upload | | http-auth-pass | pass for basic http auth on upload | | HTTP_AUTH_PASS |
ip-whitelist | comma separated list of ips allowed to connect to the service | | ip-whitelist | comma separated list of ips allowed to connect to the service | | IP_WHITELIST |
ip-blacklist | comma separated list of ips not allowed to connect to the service | | ip-blacklist | comma separated list of ips not allowed to connect to the service | | IP_BLACKLIST |
temp-path | path to temp folder | system temp | temp-path | path to temp folder | system temp | TEMP_PATH |
web-path | path to static web files (for development or custom front end) | | web-path | path to static web files (for development or custom front end) | | WEB_PATH |
proxy-path | path prefix when service is run behind a proxy | | proxy-path | path prefix when service is run behind a proxy | | PROXY_PATH |
ga-key | google analytics key for the front end | | proxy-port | port of the proxy when the service is run behind a proxy | | PROXY_PORT |
uservoice-key | user voice key for the front end | | ga-key | google analytics key for the front end | | GA_KEY |
provider | which storage provider to use | (s3, gdrive or local) | uservoice-key | user voice key for the front end | | USERVOICE_KEY |
aws-access-key | aws access key | | AWS_ACCESS_KEY provider | which storage provider to use | (s3, gdrive or local) | PROVIDER |
aws-secret-key | aws access key | | AWS_SECRET_KEY aws-access-key | aws access key | | AWS_ACCESS_KEY |
bucket | aws bucket | | BUCKET aws-secret-key | aws access key | | AWS_SECRET_KEY |
s3-endpoint | Custom S3 endpoint. | | bucket | aws bucket | | BUCKET |
s3-region | region of the s3 bucket | eu-west-1 | S3_REGION s3-endpoint | Custom S3 endpoint. | | S3_ENDPOINT |
s3-no-multipart | disables s3 multipart upload | false | | s3-region | region of the s3 bucket | eu-west-1 | S3_REGION |
s3-path-style | Forces path style URLs, required for Minio. | false | | s3-no-multipart | disables s3 multipart upload | false | S3_NO_MULTIPART |
basedir | path storage for local/gdrive provider| | s3-path-style | Forces path style URLs, required for Minio. | false | S3_PATH_STYLE |
gdrive-client-json-filepath | path to oauth client json config for gdrive provider| | basedir | path storage for local/gdrive provider | | BASEDIR |
gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| | gdrive-client-json-filepath | path to oauth client json config for gdrive provider | | GDRIVE_CLIENT_JSON_FILEPATH |
gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | | gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| | GDRIVE_LOCAL_CONFIG_PATH |
lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | | gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | | GDRIVE_CHUNK_SIZE |
log | path to log file| | lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | | HOSTS |
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.4" var Version = "1.1.7"
var helpTemplate = `NAME: var helpTemplate = `NAME:
{{.Name}} - {{.Usage}} {{.Name}} - {{.Usage}}
@ -37,6 +37,7 @@ 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
@ -44,57 +45,75 @@ 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",
@ -129,31 +148,36 @@ 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: "", EnvVar: "RATE_LIMIT",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "lets-encrypt-hosts", Name: "lets-encrypt-hosts",
@ -165,11 +189,13 @@ 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",
@ -186,26 +212,37 @@ 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",
}, },
} }
@ -214,7 +251,7 @@ type Cmd struct {
} }
func VersionAction(c *cli.Context) { func VersionAction(c *cli.Context) {
fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh: Easy file sharing from the command line"))) fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh %s: Easy file sharing from the command line", Version)))
} }
func New() *Cmd { func New() *Cmd {
@ -245,6 +282,10 @@ 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))
@ -264,6 +305,10 @@ 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,6 +16,7 @@ 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,6 +127,8 @@ 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) resolvedURL := resolveURL(r, relativeURL, s.proxyPort)
relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename)) relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename))
resolvedURLGet := resolveURL(r, relativeURLGet) resolvedURLGet := resolveURL(r, relativeURLGet, s.proxyPort)
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).Host hostname := getURL(r, s.proxyPort).Host
webAddress := resolveWebAddress(r, s.proxyPath) webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
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).Host hostname := getURL(r, s.proxyPort).Host
webAddress := resolveWebAddress(r, s.proxyPath) webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
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).ResolveReference(relativeURL).String()) fmt.Fprintln(w, getURL(r, s.proxyPort).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)) w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL, s.proxyPort))
fmt.Fprint(w, resolveURL(r, relativeURL)) fmt.Fprint(w, resolveURL(r, relativeURL, s.proxyPort))
} }
func resolveURL(r *http.Request, u *url.URL) string { func resolveURL(r *http.Request, u *url.URL, proxyPort string) string {
r.URL.Path = "" r.URL.Path = ""
return getURL(r).ResolveReference(u).String() return getURL(r, proxyPort).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) string { func resolveWebAddress(r *http.Request, proxyPath string, proxyPort string) string {
url := getURL(r) url := getURL(r, proxyPort)
var webAddress string var webAddress string
@ -544,7 +544,7 @@ func resolveWebAddress(r *http.Request, proxyPath string) string {
return webAddress return webAddress
} }
func getURL(r *http.Request) *url.URL { func getURL(r *http.Request, proxyPort string) *url.URL {
u, _ := url.Parse(r.URL.String()) u, _ := url.Parse(r.URL.String())
if r.TLS != nil { if r.TLS != nil {
@ -555,16 +555,25 @@ func getURL(r *http.Request) *url.URL {
u.Scheme = "http" u.Scheme = "http"
} }
if u.Host != "" { if u.Host == "" {
} else if host, port, err := net.SplitHostPort(r.Host); err != nil { host, port, err := net.SplitHostPort(r.Host)
u.Host = r.Host if err != nil {
} else { host = r.Host
if port == "80" && u.Scheme == "http" { port = ""
u.Host = host }
} else if port == "443" && u.Scheme == "https" { if len(proxyPort) != 0 {
port = proxyPort
}
if len(port) == 0 {
u.Host = host u.Host = host
} else { } else {
u.Host = net.JoinHostPort(host, port) if port == "80" && u.Scheme == "http" {
u.Host = host
} else if port == "443" && u.Scheme == "https" {
u.Host = host
} else {
u.Host = net.JoinHostPort(host, port)
}
} }
} }
@ -614,9 +623,7 @@ 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 s.storage.IsNotExist(err) { if err != nil {
return metadata, nil
} else if err != nil {
return metadata, err return metadata, err
} }
@ -1011,7 +1018,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) u := getURL(r, s.proxyPort)
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,7 +26,10 @@ 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"
@ -85,6 +88,13 @@ 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
@ -131,6 +141,12 @@ 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:] != "/" {
@ -270,11 +286,13 @@ 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
@ -297,7 +315,11 @@ func New(options ...OptionFn) (*Server, error) {
} }
func init() { func init() {
rand.Seed(time.Now().UTC().UnixNano()) var seedBytes [8]byte
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() {
@ -413,11 +435,24 @@ 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(r)), s.RedirectHandler(cors(r))),
handlers.NewLogOptions(s.logger.Printf, "_default_"), handlers.NewLogOptions(s.logger.Printf, "_default_"),
), ),
s.ipFilterOptions, s.ipFilterOptions,

View File

@ -32,28 +32,20 @@ func FuzzLocalStorage(fuzz []byte) int {
panic("unable to save file") panic("unable to save file")
} }
contentType, contentLength, err := storage.Head(token, filename) 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, contentType, contentLength, err := storage.Get(token, filename) output, 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")
} }
@ -81,7 +73,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")
} }