Compare commits

...

4 Commits

Author SHA1 Message Date
Stefan Benten
92324798d5 server: adding no-store header (#476)
In order to prevent viewing content, which max-download rate has been reached,
we need to ensure the data is not stored locally in a browser cache.
To achieve this, we set the Cache-Control Setting to "no-store" according to:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

fixes #470
2022-04-10 12:13:06 +02:00
Ramon Fischer
b30b296ac8 correct typo (#480) 2022-04-06 01:33:40 +02:00
jeanluc
bb0891cd7d Docker: Allow selection of (unprivileged) UID/GID at build time (#418)
* Docker: use custom non-root UID/GID (build-arg)
2022-04-03 14:55:15 +02:00
Andrea Spacca
9c31ceb2c5 Update README.md 2022-04-03 06:17:51 +02:00
6 changed files with 99 additions and 20 deletions

View File

@@ -34,9 +34,11 @@ jobs:
fi
TAGS="--tag ${DOCKER_IMAGE}:${VERSION}"
TAGS_NOROOT="--tag ${DOCKER_IMAGE}:${VERSION}-noroot"
if [ $VERSION = edge -o $VERSION = nightly ]; then
TAGS="$TAGS --tag ${DOCKER_IMAGE}:latest"
TAGS_NOROOT="$TAGS_NOROOT --tag ${DOCKER_IMAGE}:latest-noroot"
fi
echo ::set-output name=docker_image::${DOCKER_IMAGE}
@@ -46,6 +48,12 @@ jobs:
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=${GITHUB_SHA::8} \
${TAGS} .
echo ::set-output name=buildx_args_noroot::--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} \
--build-arg RUNAS=noroot \
${TAGS_NOROOT} .
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
@@ -64,6 +72,7 @@ jobs:
name: Docker Buildx (build)
run: |
docker buildx build --no-cache --pull --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args }}
docker buildx build --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args_noroot }}
-
name: Docker Login
if: success() && github.event_name != 'pull_request'
@@ -77,11 +86,13 @@ jobs:
if: success() && github.event_name != 'pull_request'
run: |
docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args }}
docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args_noroot }}
-
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 }}
docker run --rm mplatform/mquery ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}-noroot
-
name: Clear
if: always() && github.event_name != 'pull_request'

View File

@@ -14,12 +14,27 @@ ENV GO111MODULE=on
# build & install server
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
ARG PUID=5000 \
PGID=5000 \
RUNAS
RUN mkdir -p /tmp/useradd && \
if [ ! -z "$RUNAS" ]; then \
echo "${RUNAS}:x:${PUID}:${PGID}::/nonexistent:/sbin/nologin" >> /tmp/useradd/passwd && \
echo "${RUNAS}:!:::::::" >> /tmp/useradd/shadow && \
echo "${RUNAS}:x:${PGID}:" >> /tmp/useradd/group && \
echo "${RUNAS}:!::" >> /tmp/useradd/groupshadow; else touch /tmp/useradd/unused; fi
FROM scratch AS final
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"
ARG RUNAS
COPY --from=build /go/bin/transfersh /go/bin/transfersh
COPY --from=build /tmp/useradd/* /etc/
COPY --from=build --chown=${RUNAS} /go/bin/transfersh /go/bin/transfersh
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
USER ${RUNAS}
ENTRYPOINT ["/go/bin/transfersh", "--listener", ":8080"]
EXPOSE 8080

View File

@@ -140,12 +140,31 @@ $ go build -o transfersh main.go
## Docker
For easy deployment, we've created a Docker container.
For easy deployment, we've created an official Docker container. There are two variants, differing only by which user runs the process.
The default one will run as `root`:
```bash
docker run --publish 8080:8080 dutchcoders/transfer.sh:latest --provider local --basedir /tmp/
```
The one tagged with the suffix `-noroot` will use `5000` as both UID and GID:
```bash
docker run --publish 8080:8080 dutchcoders/transfer.sh:latest-noroot --provider local --basedir /tmp/
```
### Building the Container
You can also build the container yourself. This allows you to choose which UID/GID will be used, e.g. when using NFS mounts:
```bash
# Build arguments:
# * RUNAS: If empty, the container will run as root.
# Set this to anything to enable UID/GID selection.
# * PUID: UID of the process. Needs RUNAS != "". Defaults to 5000.
# * PGID: GID of the process. Needs RUNAS != "". Defaults to 5000.
docker build -t transfer.sh-noroot --build-arg RUNAS=doesntmatter --build-arg PUID=1337 --build-arg PGID=1338 .
```
## S3 Usage
For the usage with a AWS S3 Bucket, you just need to specify the following options:
@@ -204,6 +223,41 @@ You need to create an OAuth Client id from console.cloud.google.com, download th
```go run main.go --provider gdrive --basedir /tmp/ --gdrive-client-json-filepath /[credential_dir] --gdrive-local-config-path [directory_to_save_config] ```
## Shell functions
### Bash and zsh (multiple files uploaded as zip archive)
##### Add this to .bashrc or .zshrc or its equivalent
```bash
transfer(){ if [ $# -eq 0 ];then echo "No arguments specified.\nUsage:\n transfer <file|directory>\n ... | transfer <file_name>">&2;return 1;fi;if tty -s;then file="$1";file_name=$(basename "$file");if [ ! -e "$file" ];then echo "$file: No such file or directory">&2;return 1;fi;if [ -d "$file" ];then file_name="$file_name.zip" ,;(cd "$file"&&zip -r -q - .)|curl --progress-bar --upload-file "-" "https://transfer.sh/$file_name"|tee /dev/null,;else cat "$file"|curl --progress-bar --upload-file "-" "https://transfer.sh/$file_name"|tee /dev/null;fi;else file_name=$1;curl --progress-bar --upload-file "-" "https://transfer.sh/$file_name"|tee /dev/null;fi;}
```
#### Now you can use transfer function
```
$ transfer hello.txt
```
### Zsh (with delete url outpu)
##### Add this to .zshrc or its equivalent
```bash
transfer()
{
local file="${1}"
local filename="${file##*/}"
# show delete link from the response header after upload. the command "sed" is necessary to clean up the output, "gsub()" in "awk" does not work.
curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/${filename}" | sed "s/#//g" | awk '/x-url-delete/ { print "Delete command: curl --request DELETE " $2 } END{ print "Download link: " $1 }'
}
```
#### Sample ouput
```bash
$ transfer image.img
######################################################################################################################################################################################################################################## 100.0%
Delete command: curl --request DELETE https://transfer.sh/Ge9cuW/image.img/<some_delete_token>
Download link: https://transfer.sh/Ge9cuW/image.img
```
## Contributions
Contributions are welcome.

View File

@@ -781,8 +781,7 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
zipfilename := fmt.Sprintf("transfersh-%d.zip", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", zipfilename))
w.Header().Set("Connection", "close")
commonHeader(w, zipfilename)
zw := zip.NewWriter(w)
@@ -848,8 +847,7 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
tarfilename := fmt.Sprintf("transfersh-%d.tar.gz", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/x-gzip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", tarfilename))
w.Header().Set("Connection", "close")
commonHeader(w, tarfilename)
gw := gzip.NewWriter(w)
defer CloseCheck(gw.Close)
@@ -910,8 +908,7 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
tarfilename := fmt.Sprintf("transfersh-%d.tar", uint16(time.Now().UnixNano()))
w.Header().Set("Content-Type", "application/x-tar")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", tarfilename))
w.Header().Set("Connection", "close")
commonHeader(w, tarfilename)
zw := tar.NewWriter(w)
defer CloseCheck(zw.Close)
@@ -1037,6 +1034,7 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
w.Header().Set("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"", disposition, filename))
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Cache-Control", "no-store")
w.Header().Set("X-Remaining-Downloads", remainingDownloads)
w.Header().Set("X-Remaining-Days", remainingDays)
@@ -1072,6 +1070,12 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
}
}
func commonHeader(w http.ResponseWriter, filename string) {
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
w.Header().Set("Connection", "close")
w.Header().Set("Cache-Control", "no-store")
}
// RedirectHandler handles redirect
func (s *Server) RedirectHandler(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {

View File

@@ -25,39 +25,34 @@ THE SOFTWARE.
package server
import (
"context"
crypto_rand "crypto/rand"
"crypto/tls"
"encoding/binary"
"errors"
gorillaHandlers "github.com/gorilla/handlers"
"log"
"math/rand"
"mime"
"net/http"
_ "net/http/pprof"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"sync"
"syscall"
"time"
context "golang.org/x/net/context"
"github.com/PuerkitoBio/ghost/handlers"
"github.com/VojtechVitek/ratelimit"
"github.com/VojtechVitek/ratelimit/memory"
gorillaHandlers "github.com/gorilla/handlers"
"github.com/gorilla/mux"
// import pprof
_ "net/http/pprof"
"crypto/tls"
"golang.org/x/crypto/acme/autocert"
web "github.com/dutchcoders/transfer.sh-web"
assetfs "github.com/elazarl/go-bindata-assetfs"
autocert "golang.org/x/crypto/acme/autocert"
"path/filepath"
)
// parse request with maximum memory of _24Kilobits