Compare commits
133 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7cf688e86e | ||
|
1abc7cfb0e | ||
|
be6dea2546 | ||
|
d554eb8e2d | ||
|
fe9e699255 | ||
|
d3b6fd5e90 | ||
|
322310d47f | ||
|
76fd83b599 | ||
|
d3381a2293 | ||
|
6ac6c8fa99 | ||
|
2721ece759 | ||
|
e53d599e09 | ||
|
bfb34634de | ||
|
614a7fd23d | ||
|
fb8f0e781b | ||
|
06d87eac8e | ||
|
580cd8d978 | ||
|
111f1794fb | ||
|
b372dc97b5 | ||
|
ae00f8ceaa | ||
|
ec9db7a42e | ||
|
bcf40c15a2 | ||
|
fe1cde6614 | ||
|
e182376100 | ||
|
4a2fce4344 | ||
|
ffb2cf0011 | ||
|
085e9f8414 | ||
|
a4bf102d29 | ||
|
c8497fb27d | ||
|
68212d100e | ||
|
18f4b42cf1 | ||
|
92055f1b3c | ||
|
9430e53689 | ||
|
a26b32dd86 | ||
|
0a6b5817a9 | ||
|
5e7e3a1b39 | ||
|
42adceb4c6 | ||
|
f909ad3ce2 | ||
|
d830bf1afc | ||
|
f366e8217e | ||
|
8a5c737140 | ||
|
b920eb842a | ||
|
45e0967a37 | ||
|
28614c991d | ||
|
ef28bcb28f | ||
|
2dd23bff3c | ||
|
663c59e754 | ||
|
c89b7f56c2 | ||
|
8bb5094ccc | ||
|
b7deec505b | ||
|
c62e5757ef | ||
|
38d643e12b | ||
|
0411db0443 | ||
|
3b1b5b890a | ||
|
fb3d410004 | ||
|
924275e45b | ||
|
fdca501681 | ||
|
38996c9c7f | ||
|
9f9e1b66b2 | ||
|
b3f2319cba | ||
|
867471aa9c | ||
|
96fb3cbe61 | ||
|
800dd6658e | ||
|
2e33f7c716 | ||
|
5fab83bde8 | ||
|
dcaf572f3d | ||
|
ce4e015641 | ||
|
9c15248adc | ||
|
d8e1248949 | ||
|
7dc3982c77 | ||
|
82617a25c1 | ||
|
fcbddcee17 | ||
|
8b92f5bac4 | ||
|
8aa835f21f | ||
|
9297c253aa | ||
|
b22a410a78 | ||
|
229482fa3d | ||
|
f22bfbf804 | ||
|
8ecc94ed7c | ||
|
0ee2dfd7e1 | ||
|
b90bd685e7 | ||
|
73e2bca999 | ||
|
d09f4fdd81 | ||
|
356412c838 | ||
|
6b249d21c4 | ||
|
c0d5d99e5d | ||
|
9e27485bbb | ||
|
b8ca25fb9b | ||
|
bef766f605 | ||
|
c2a152c622 | ||
|
c403f9a2f1 | ||
|
8d196039ba | ||
|
11ad244584 | ||
|
060dbdf152 | ||
|
2127b4f1e4 | ||
|
8c5ef8f2e1 | ||
|
b40e9d1fb8 | ||
|
071ecb491c | ||
|
806006a0b8 | ||
|
76f00c5d04 | ||
|
6b148d3574 | ||
|
6eabb248da | ||
|
5bb0e84fa5 | ||
|
1e815d382c | ||
|
cf00af36f2 | ||
|
79c5130066 | ||
|
c1691c58dc | ||
|
d5e07fe2f4 | ||
|
874268d80e | ||
|
59014f2110 | ||
|
6c54ddccef | ||
|
a2ab63c7b8 | ||
|
11dffa22b4 | ||
|
758cd881ce | ||
|
f00209973e | ||
|
0b27adba9d | ||
|
8463d4169b | ||
|
e340ad9e45 | ||
|
4e288cc4e4 | ||
|
ee7011d55b | ||
|
6c73f13fd0 | ||
|
e5b5ee7140 | ||
|
6a956a445f | ||
|
ce7e008bb3 | ||
|
b9a03ac180 | ||
|
cccbaac6d7 | ||
|
a09bcf3bf0 | ||
|
0b23354473 | ||
|
372ff5f368 | ||
|
ce043efca0 | ||
|
6cb2de3cff | ||
|
58edf68fd7 | ||
|
2e41852860 |
89
.github/workflows/build-docker-images.yml
vendored
Normal file
89
.github/workflows/build-docker-images.yml
vendored
Normal 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
|
41
.travis.yml
41
.travis.yml
@@ -4,18 +4,45 @@ sudo: false
|
|||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.9.x
|
- 1.13.x
|
||||||
- 1.10.x
|
- 1.14.x
|
||||||
- 1.11.x
|
- 1.15.x
|
||||||
- 1.12.x
|
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
install:
|
env:
|
||||||
- echo "This is an override of the default install deps step in travis."
|
global:
|
||||||
|
- GO111MODULE=on
|
||||||
|
|
||||||
script:
|
install:
|
||||||
- go get -t -u -v ./...
|
- go get -t -u -v ./...
|
||||||
- go build -v .
|
- go build -v .
|
||||||
- go vet ./...
|
- go vet ./...
|
||||||
|
|
||||||
|
script:
|
||||||
- go test ./...
|
- go test ./...
|
||||||
|
|
||||||
|
before_deploy:
|
||||||
|
- mkdir -p release
|
||||||
|
- "GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags -a -tags netgo -ldflags '-s -w -extldflags -static' -o release/transfersh-$TRAVIS_TAG-linux-amd64"
|
||||||
|
- "GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 go build -ldflags -a -tags netgo -ldflags '-s -w -extldflags -static' -o release/transfersh-$TRAVIS_TAG-linux-armv7"
|
||||||
|
- "GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags -a -tags netgo -ldflags '-s -w -extldflags -static' -o release/transfersh-$TRAVIS_TAG-darwin-amd64"
|
||||||
|
- "GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags -a -tags netgo -ldflags '-s -w -extldflags -static' -o release/transfersh-$TRAVIS_TAG-win-amd64.exe"
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: releases
|
||||||
|
api_key:
|
||||||
|
secure: cOuMGyvrl/9GX3TZFL+Vq++2Bv5Hlb3VfXSYONfeAj+1AXI3Y+tPruy/XnWpa1MUxkvFuIhea3sUAiKfwhHip9csCmMUhDJtaTU9apsxRkyF/OFrWb7/FlbnqYuAwnp91ImvtSlnubg2VHTjhBA6ycNQF7WZcJEMVMsAtC/nSY4=
|
||||||
|
file:
|
||||||
|
- "release/transfersh-$TRAVIS_TAG-linux-amd64"
|
||||||
|
- "release/transfersh-$TRAVIS_TAG-linux-armv7"
|
||||||
|
- "release/transfersh-$TRAVIS_TAG-darwin-amd64"
|
||||||
|
- "release/transfersh-$TRAVIS_TAG-win-amd64.exe"
|
||||||
|
skip_cleanup: true
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
go: 1.15.x
|
||||||
|
overwrite: true
|
@@ -1,5 +1,5 @@
|
|||||||
# Default to Go 1.12
|
# Default to Go 1.13
|
||||||
ARG GO_VERSION=1.12
|
ARG GO_VERSION=1.13
|
||||||
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 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>"
|
||||||
|
200
README.md
200
README.md
@@ -1,4 +1,4 @@
|
|||||||
# transfer.sh [](https://gitter.im/dutchcoders/transfer.sh?utm_source=badge&utm_medium=badge&utm_campaign=&utm_campaign=pr-badge&utm_content=badge) [](https://goreportcard.com/report/github.com/dutchcoders/transfer.sh) [](https://hub.docker.com/r/dutchcoders/transfer.sh/) [](https://travis-ci.org/dutchcoders/transfer.sh)
|
# transfer.sh [](https://gitter.im/dutchcoders/transfer.sh?utm_source=badge&utm_medium=badge&utm_campaign=&utm_campaign=pr-badge&utm_content=badge) [](https://goreportcard.com/report/github.com/dutchcoders/transfer.sh) [](https://hub.docker.com/r/dutchcoders/transfer.sh/) [](https://travis-ci.com/dutchcoders/transfer.sh)
|
||||||
|
|
||||||
Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance.
|
Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance.
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ Transfer.sh currently supports the s3 (Amazon S3), gdrive (Google Drive) provide
|
|||||||
This project repository has no relation with the service at https://transfer.sh that's managed by https://storj.io.
|
This project repository has no relation with the service at https://transfer.sh that's managed by https://storj.io.
|
||||||
So far we cannot address any issue related to the service at https://transfer.sh.
|
So far we cannot address any issue related to the service at https://transfer.sh.
|
||||||
|
|
||||||
|
The service at https://transfersh.com is of unknown origin and reported as cloud malware.
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -58,76 +60,9 @@ curl -sD - --upload-file ./hello https://transfer.sh/hello.txt | grep 'X-Url-Del
|
|||||||
X-Url-Delete: https://transfer.sh/hello.txt/BAYh0/hello.txt/PDw0NHPcqU
|
X-Url-Delete: https://transfer.sh/hello.txt/BAYh0/hello.txt/PDw0NHPcqU
|
||||||
```
|
```
|
||||||
|
|
||||||
## Add alias to .bashrc or .zshrc
|
## Examples
|
||||||
|
|
||||||
### Using curl
|
See good usage examples on [examples.md](examples.md)
|
||||||
```bash
|
|
||||||
transfer() {
|
|
||||||
curl --progress-bar --upload-file "$1" https://transfer.sh/$(basename "$1") | tee /dev/null;
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
alias transfer=transfer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using wget
|
|
||||||
```bash
|
|
||||||
transfer() {
|
|
||||||
wget -t 1 -qO - --method=PUT --body-file="$1" --header="Content-Type: $(file -b --mime-type "$1")" https://transfer.sh/$(basename "$1");
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
alias transfer=transfer
|
|
||||||
```
|
|
||||||
|
|
||||||
## Add alias for fish-shell
|
|
||||||
|
|
||||||
### Using curl
|
|
||||||
```fish
|
|
||||||
function transfer --description 'Upload a file to transfer.sh'
|
|
||||||
if [ $argv[1] ]
|
|
||||||
# write to output to tmpfile because of progress bar
|
|
||||||
set -l tmpfile ( mktemp -t transferXXX )
|
|
||||||
curl --progress-bar --upload-file "$argv[1]" https://transfer.sh/(basename $argv[1]) >> $tmpfile
|
|
||||||
cat $tmpfile
|
|
||||||
command rm -f $tmpfile
|
|
||||||
else
|
|
||||||
echo 'usage: transfer FILE_TO_TRANSFER'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
funcsave transfer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using wget
|
|
||||||
```fish
|
|
||||||
function transfer --description 'Upload a file to transfer.sh'
|
|
||||||
if [ $argv[1] ]
|
|
||||||
wget -t 1 -qO - --method=PUT --body-file="$argv[1]" --header="Content-Type: (file -b --mime-type $argv[1])" https://transfer.sh/(basename $argv[1])
|
|
||||||
else
|
|
||||||
echo 'usage: transfer FILE_TO_TRANSFER'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
funcsave transfer
|
|
||||||
```
|
|
||||||
|
|
||||||
Now run it like this:
|
|
||||||
```bash
|
|
||||||
$ transfer test.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Add alias on Windows
|
|
||||||
|
|
||||||
Put a file called `transfer.cmd` somewhere in your PATH with this inside it:
|
|
||||||
```cmd
|
|
||||||
@echo off
|
|
||||||
setlocal
|
|
||||||
:: use env vars to pass names to PS, to avoid escaping issues
|
|
||||||
set FN=%~nx1
|
|
||||||
set FULL=%1
|
|
||||||
powershell -noprofile -command "$(Invoke-Webrequest -Method put -Infile $Env:FULL https://transfer.sh/$Env:FN).Content"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Link aliases
|
## Link aliases
|
||||||
|
|
||||||
@@ -143,38 +78,49 @@ 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, grdrive or local) |
|
provider | which storage provider to use | (s3, storj, gdrive or local) |
|
||||||
aws-access-key | aws access key | | AWS_ACCESS_KEY
|
uservoice-key | user voice key for the front end | | USERVOICE_KEY |
|
||||||
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-region | region of the s3 bucket | eu-west-1 | S3_REGION
|
bucket | aws bucket | | BUCKET |
|
||||||
s3-no-multipart | disables s3 multipart upload | false | |
|
s3-endpoint | Custom S3 endpoint. | | S3_ENDPOINT |
|
||||||
basedir | path storage for local/gdrive provider| |
|
s3-region | region of the s3 bucket | eu-west-1 | S3_REGION |
|
||||||
gdrive-client-json-filepath | path to oauth client json config for gdrive provider| |
|
s3-no-multipart | disables s3 multipart upload | false | S3_NO_MULTIPART |
|
||||||
gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| |
|
s3-path-style | Forces path style URLs, required for Minio. | false | S3_PATH_STYLE |
|
||||||
gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | |
|
storj-access | Access for the project | | STORJ_ACCESS |
|
||||||
lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | |
|
storj-bucket | Bucket to use within the project | | STORJ_BUCKET |
|
||||||
log | path to log file| |
|
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 |
|
||||||
|
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 |
|
||||||
|
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 |
|
||||||
|
max-upload-size | max upload size in kilobytes | | MAX_UPLOAD_SIZE |
|
||||||
|
purge-days | number of days after the uploads are purged automatically | | PURGE_DAYS |
|
||||||
|
purge-interval | interval in hours to run the automatic purge for (not applicable to S3 and Storj) | | PURGE_INTERVAL |
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -186,13 +132,10 @@ go run main.go --provider=local --listener :8080 --temp-path=/tmp/ --basedir=/tm
|
|||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
If on go < 1.11
|
|
||||||
```bash
|
```bash
|
||||||
go get -u -v ./...
|
$ git clone git@github.com:dutchcoders/transfer.sh.git
|
||||||
```
|
$ cd transfer.sh
|
||||||
|
$ go build -o transfersh main.go
|
||||||
```bash
|
|
||||||
go build -o transfersh main.go
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
@@ -216,7 +159,52 @@ If you specify the s3-region, you don't need to set the endpoint URL since the c
|
|||||||
|
|
||||||
### Custom S3 providers
|
### Custom S3 providers
|
||||||
|
|
||||||
To use a custom non-AWS S3 provider, you need to specify the endpoint as definied from your cloud provider.
|
To use a custom non-AWS S3 provider, you need to specify the endpoint as defined from your cloud provider.
|
||||||
|
|
||||||
|
## Storj Network Provider
|
||||||
|
|
||||||
|
To use the Storj Network as storage provider you need to specify the following flags:
|
||||||
|
- provider `--provider storj`
|
||||||
|
- storj-access _(either via flag or environment variable STORJ_ACCESS)_
|
||||||
|
- storj-bucket _(either via flag or environment variable STORJ_BUCKET)_
|
||||||
|
|
||||||
|
### Creating Bucket and Scope
|
||||||
|
|
||||||
|
In preparation you need to create a scope (or copy it from the uplink configuration) and a bucket.
|
||||||
|
|
||||||
|
To get started, download the latest uplink from the release page: https://github.com/storj/storj/releases
|
||||||
|
|
||||||
|
After extracting, execute `uplink setup`. The Wizard asks for Satellite to use, the API Key
|
||||||
|
(which you can retrieve via the Satellite UI), as well as an Encryption Key.
|
||||||
|
Once the uplink is setup create the bucket using the following schema:
|
||||||
|
`uplink mb sj://<BUCKET>` where <BUCKET> is your desired name.
|
||||||
|
|
||||||
|
Afterwards you can copy the SCOPE out of the configuration file of the uplink and then start the startup of the
|
||||||
|
transfer.sh endpoint. For enhanced security its recommended to provide both the scope and the bucket name as ENV Variables.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
export STORJ_BUCKET=transfersh
|
||||||
|
export STORJ_ACCESS=<SCOPE>
|
||||||
|
transfer.sh --provider storj
|
||||||
|
```
|
||||||
|
|
||||||
|
## Google Drive Usage
|
||||||
|
|
||||||
|
For the usage with Google drive, you need to specify the following options:
|
||||||
|
- provider
|
||||||
|
- gdrive-client-json-filepath
|
||||||
|
- gdrive-local-config-path
|
||||||
|
- basedir
|
||||||
|
|
||||||
|
### Creating Gdrive Client Json
|
||||||
|
|
||||||
|
You need to create a Oauth Client id from console.cloud.google.com
|
||||||
|
download the file and place into a safe directory
|
||||||
|
|
||||||
|
### Usage example
|
||||||
|
|
||||||
|
```go run main.go --provider gdrive --basedir /tmp/ --gdrive-client-json-filepath /[credential_dir] --gdrive-local-config-path [directory_to_save_config] ```
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
|
241
cmd/cmd.go
241
cmd/cmd.go
@@ -8,11 +8,11 @@ import (
|
|||||||
|
|
||||||
"github.com/dutchcoders/transfer.sh/server"
|
"github.com/dutchcoders/transfer.sh/server"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/minio/cli"
|
"github.com/urfave/cli"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Version = "1.1.0"
|
var Version = "1.2.1"
|
||||||
var helpTemplate = `NAME:
|
var helpTemplate = `NAME:
|
||||||
{{.Name}} - {{.Usage}}
|
{{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
@@ -34,67 +34,86 @@ VERSION:
|
|||||||
|
|
||||||
var globalFlags = []cli.Flag{
|
var globalFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
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
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
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{
|
cli.StringFlag{
|
||||||
Name: "ga-key",
|
Name: "proxy-port",
|
||||||
Usage: "key for google analytics (front end)",
|
Usage: "port of the proxy when the service is run behind a proxy",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
EnvVar: "PROXY_PORT",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "uservoice-key",
|
Name: "ga-key",
|
||||||
Usage: "key for user voice (front end)",
|
Usage: "key for google analytics (front end)",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
EnvVar: "GA_KEY",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "provider",
|
Name: "uservoice-key",
|
||||||
Usage: "s3|gdrive|local",
|
Usage: "key for user voice (front end)",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
EnvVar: "USERVOICE_KEY",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "provider",
|
||||||
|
Usage: "s3|gdrive|local",
|
||||||
|
Value: "",
|
||||||
|
EnvVar: "PROVIDER",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "s3-endpoint",
|
Name: "s3-endpoint",
|
||||||
@@ -127,29 +146,68 @@ var globalFlags = []cli.Flag{
|
|||||||
EnvVar: "BUCKET",
|
EnvVar: "BUCKET",
|
||||||
},
|
},
|
||||||
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{
|
||||||
|
Name: "s3-path-style",
|
||||||
|
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.StringFlag{
|
||||||
|
Name: "storj-access",
|
||||||
|
Usage: "Access for the project",
|
||||||
|
Value: "",
|
||||||
|
EnvVar: "STORJ_ACCESS",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "storj-bucket",
|
||||||
|
Usage: "Bucket to use within the project",
|
||||||
|
Value: "",
|
||||||
|
EnvVar: "STORJ_BUCKET",
|
||||||
},
|
},
|
||||||
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.IntFlag{
|
||||||
|
Name: "purge-days",
|
||||||
|
Usage: "number of days after uploads are purged automatically",
|
||||||
|
Value: 0,
|
||||||
|
EnvVar: "PURGE_DAYS",
|
||||||
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "purge-interval",
|
||||||
|
Usage: "interval in hours to run the automatic purge for",
|
||||||
|
Value: 0,
|
||||||
|
EnvVar: "PURGE_INTERVAL",
|
||||||
|
},
|
||||||
|
cli.Int64Flag{
|
||||||
|
Name: "max-upload-size",
|
||||||
|
Usage: "max limit for upload, in kilobytes",
|
||||||
|
Value: 0,
|
||||||
|
EnvVar: "MAX_UPLOAD_SIZE",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "lets-encrypt-hosts",
|
Name: "lets-encrypt-hosts",
|
||||||
@@ -158,14 +216,16 @@ var globalFlags = []cli.Flag{
|
|||||||
EnvVar: "HOSTS",
|
EnvVar: "HOSTS",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
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",
|
||||||
@@ -180,28 +240,39 @@ var globalFlags = []cli.Flag{
|
|||||||
EnvVar: "VIRUSTOTAL_KEY",
|
EnvVar: "VIRUSTOTAL_KEY",
|
||||||
},
|
},
|
||||||
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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +281,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 {
|
||||||
@@ -241,6 +312,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))
|
||||||
@@ -260,6 +335,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))
|
||||||
}
|
}
|
||||||
@@ -290,10 +369,20 @@ func New() *Cmd {
|
|||||||
options = append(options, server.ClamavHost(v))
|
options = append(options, server.ClamavHost(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v := c.Int64("max-upload-size"); v > 0 {
|
||||||
|
options = append(options, server.MaxUploadSize(v))
|
||||||
|
}
|
||||||
|
|
||||||
if v := c.Int("rate-limit"); v > 0 {
|
if v := c.Int("rate-limit"); v > 0 {
|
||||||
options = append(options, server.RateLimit(v))
|
options = append(options, server.RateLimit(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purgeDays := c.Int("purge-days")
|
||||||
|
purgeInterval := c.Int("purge-interval")
|
||||||
|
if purgeDays > 0 && purgeInterval > 0 {
|
||||||
|
options = append(options, server.Purge(purgeDays, purgeInterval))
|
||||||
|
}
|
||||||
|
|
||||||
if cert := c.String("tls-cert-file"); cert == "" {
|
if cert := c.String("tls-cert-file"); cert == "" {
|
||||||
} else if pk := c.String("tls-private-key"); pk == "" {
|
} else if pk := c.String("tls-private-key"); pk == "" {
|
||||||
} else {
|
} else {
|
||||||
@@ -339,7 +428,7 @@ func New() *Cmd {
|
|||||||
panic("secret-key not set.")
|
panic("secret-key not set.")
|
||||||
} else if bucket := c.String("bucket"); bucket == "" {
|
} else if bucket := c.String("bucket"); bucket == "" {
|
||||||
panic("bucket not set.")
|
panic("bucket not set.")
|
||||||
} else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, c.String("s3-region"), c.String("s3-endpoint"), logger, c.Bool("s3-no-multipart")); err != nil {
|
} else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, purgeDays, c.String("s3-region"), c.String("s3-endpoint"), c.Bool("s3-no-multipart"), c.Bool("s3-path-style"), logger); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else {
|
} else {
|
||||||
options = append(options, server.UseStorage(storage))
|
options = append(options, server.UseStorage(storage))
|
||||||
@@ -358,6 +447,16 @@ func New() *Cmd {
|
|||||||
} else {
|
} else {
|
||||||
options = append(options, server.UseStorage(storage))
|
options = append(options, server.UseStorage(storage))
|
||||||
}
|
}
|
||||||
|
case "storj":
|
||||||
|
if access := c.String("storj-access"); access == "" {
|
||||||
|
panic("storj-access not set.")
|
||||||
|
} else if bucket := c.String("storj-bucket"); bucket == "" {
|
||||||
|
panic("storj-bucket not set.")
|
||||||
|
} else if storage, err := server.NewStorjStorage(access, bucket, purgeDays, logger); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
options = append(options, server.UseStorage(storage))
|
||||||
|
}
|
||||||
case "local":
|
case "local":
|
||||||
if v := c.String("basedir"); v == "" {
|
if v := c.String("basedir"); v == "" {
|
||||||
panic("basedir not set.")
|
panic("basedir not set.")
|
||||||
|
176
examples.md
Normal file
176
examples.md
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
# Table of Contents
|
||||||
|
|
||||||
|
* [Aliases](#aliases)
|
||||||
|
* [Uploading and downloading](#uploading-and-downloading)
|
||||||
|
* [Archiving and backups](#archiving-and-backups)
|
||||||
|
* [Encrypting and decrypting](#encrypting-and-decrypting)
|
||||||
|
* [Scanning for viruses](#scanning-for-viruses)
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
<a name="aliases"/>
|
||||||
|
|
||||||
|
## Add alias to .bashrc or .zshrc
|
||||||
|
|
||||||
|
### Using curl
|
||||||
|
```bash
|
||||||
|
transfer() {
|
||||||
|
curl --progress-bar --upload-file "$1" https://transfer.sh/$(basename "$1") | tee /dev/null;
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
alias transfer=transfer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using wget
|
||||||
|
```bash
|
||||||
|
transfer() {
|
||||||
|
wget -t 1 -qO - --method=PUT --body-file="$1" --header="Content-Type: $(file -b --mime-type "$1")" https://transfer.sh/$(basename "$1");
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
alias transfer=transfer
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add alias for fish-shell
|
||||||
|
|
||||||
|
### Using curl
|
||||||
|
```fish
|
||||||
|
function transfer --description 'Upload a file to transfer.sh'
|
||||||
|
if [ $argv[1] ]
|
||||||
|
# write to output to tmpfile because of progress bar
|
||||||
|
set -l tmpfile ( mktemp -t transferXXXXXX )
|
||||||
|
curl --progress-bar --upload-file "$argv[1]" https://transfer.sh/(basename $argv[1]) >> $tmpfile
|
||||||
|
cat $tmpfile
|
||||||
|
command rm -f $tmpfile
|
||||||
|
else
|
||||||
|
echo 'usage: transfer FILE_TO_TRANSFER'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
funcsave transfer
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using wget
|
||||||
|
```fish
|
||||||
|
function transfer --description 'Upload a file to transfer.sh'
|
||||||
|
if [ $argv[1] ]
|
||||||
|
wget -t 1 -qO - --method=PUT --body-file="$argv[1]" --header="Content-Type: (file -b --mime-type $argv[1])" https://transfer.sh/(basename $argv[1])
|
||||||
|
else
|
||||||
|
echo 'usage: transfer FILE_TO_TRANSFER'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
funcsave transfer
|
||||||
|
```
|
||||||
|
|
||||||
|
Now run it like this:
|
||||||
|
```bash
|
||||||
|
$ transfer test.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add alias on Windows
|
||||||
|
|
||||||
|
Put a file called `transfer.cmd` somewhere in your PATH with this inside it:
|
||||||
|
```cmd
|
||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
:: use env vars to pass names to PS, to avoid escaping issues
|
||||||
|
set FN=%~nx1
|
||||||
|
set FULL=%1
|
||||||
|
powershell -noprofile -command "$(Invoke-Webrequest -Method put -Infile $Env:FULL https://transfer.sh/$Env:FN).Content"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uploading and Downloading
|
||||||
|
<a name="uploading-and-downloading"/>
|
||||||
|
|
||||||
|
### Uploading with wget
|
||||||
|
```bash
|
||||||
|
$ wget --method PUT --body-file=/tmp/file.tar https://transfer.sh/file.tar -O - -nv
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uploading with PowerShell
|
||||||
|
```posh
|
||||||
|
PS H:\> invoke-webrequest -method put -infile .\file.txt https://transfer.sh/file.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload using HTTPie
|
||||||
|
```bash
|
||||||
|
$ http https://transfer.sh/ -vv < /tmp/test.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uploading a filtered text file
|
||||||
|
```bash
|
||||||
|
$ grep 'pound' /var/log/syslog | curl --upload-file - https://transfer.sh/pound.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Downloading with curl
|
||||||
|
```bash
|
||||||
|
$ curl https://transfer.sh/1lDau/test.txt -o test.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Downloading with wget
|
||||||
|
```bash
|
||||||
|
$ wget https://transfer.sh/1lDau/test.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Archiving and backups
|
||||||
|
<a name="archiving-and-backups"/>
|
||||||
|
|
||||||
|
### Backup, encrypt and transfer a MySQL dump
|
||||||
|
```bash
|
||||||
|
$ mysqldump --all-databases | gzip | gpg -ac -o- | curl -X PUT --upload-file "-" https://transfer.sh/test.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Archive and upload directory
|
||||||
|
```bash
|
||||||
|
$ tar -czf - /var/log/journal | curl --upload-file - https://transfer.sh/journal.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uploading multiple files at once
|
||||||
|
```bash
|
||||||
|
$ curl -i -F filedata=@/tmp/hello.txt -F filedata=@/tmp/hello2.txt https://transfer.sh/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combining downloads as zip or tar.gz archive
|
||||||
|
```bash
|
||||||
|
$ curl https://transfer.sh/(15HKz/hello.txt,15HKz/hello.txt).tar.gz
|
||||||
|
$ curl https://transfer.sh/(15HKz/hello.txt,15HKz/hello.txt).zip
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transfer and send email with link (using an alias)
|
||||||
|
```bash
|
||||||
|
$ transfer /tmp/hello.txt | mail -s "Hello World" user@yourmaildomain.com
|
||||||
|
```
|
||||||
|
## Encrypting and decrypting
|
||||||
|
<a name="encrypting-and-decrypting"/>
|
||||||
|
|
||||||
|
### Encrypting files with password using gpg
|
||||||
|
```bash
|
||||||
|
$ cat /tmp/hello.txt | gpg -ac -o- | curl -X PUT --upload-file "-" https://transfer.sh/test.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Downloading and decrypting
|
||||||
|
```bash
|
||||||
|
$ curl https://transfer.sh/1lDau/test.txt | gpg -o- > /tmp/hello.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import keys from [keybase](https://keybase.io/)
|
||||||
|
```bash
|
||||||
|
$ keybase track [them] # Encrypt for recipient(s)
|
||||||
|
$ cat somebackupfile.tar.gz | keybase encrypt [them] | curl --upload-file '-' https://transfer.sh/test.txt # Decrypt
|
||||||
|
$ curl https://transfer.sh/sqUFi/test.md | keybase decrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scanning for viruses
|
||||||
|
<a name="scanning-for-viruses"/>
|
||||||
|
|
||||||
|
### Scan for malware or viruses using Clamav
|
||||||
|
```bash
|
||||||
|
$ wget http://www.eicar.org/download/eicar.com
|
||||||
|
$ curl -X PUT --upload-file ./eicar.com https://transfer.sh/eicar.com/scan
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload malware to VirusTotal, get a permalink in return
|
||||||
|
```bash
|
||||||
|
$ curl -X PUT --upload-file nhgbhhj https://transfer.sh/test.txt/virustotal
|
||||||
|
```
|
42
go.mod
42
go.mod
@@ -3,34 +3,36 @@ module github.com/dutchcoders/transfer.sh
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go v0.54.0 // indirect
|
||||||
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14
|
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14
|
||||||
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2
|
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2
|
||||||
github.com/aws/aws-sdk-go v1.20.6
|
github.com/aws/aws-sdk-go v1.29.24
|
||||||
|
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-20190520063132-37110d436c89
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20190716184912-96e06a2276ba
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0
|
github.com/elazarl/go-bindata-assetfs v1.0.0
|
||||||
github.com/fatih/color v1.7.0
|
github.com/fatih/color v1.9.0
|
||||||
github.com/garyburd/redigo v1.6.0 // indirect
|
github.com/garyburd/redigo v1.6.0 // indirect
|
||||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
|
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273
|
||||||
github.com/gorilla/mux v1.7.1
|
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/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/jmespath/go-jmespath v0.3.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
|
||||||
github.com/microcosm-cc/bluemonday v1.0.2
|
github.com/microcosm-cc/bluemonday v1.0.2
|
||||||
github.com/minio/cli v1.3.0
|
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
github.com/russross/blackfriday/v2 v2.0.1
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
|
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
|
||||||
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
|
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529
|
github.com/urfave/cli v1.22.3
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
|
||||||
google.golang.org/api v0.5.0
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
|
google.golang.org/api v0.20.0
|
||||||
gopkg.in/russross/blackfriday.v2 v2.0.1
|
google.golang.org/grpc v1.28.0 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
|
||||||
|
storj.io/common v0.0.0-20201207172416-78f4e59925c3
|
||||||
|
storj.io/uplink v1.4.2
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gopkg.in/russross/blackfriday.v2 v2.0.1 => github.com/russross/blackfriday/v2 v2.0.1
|
|
||||||
|
431
go.sum
431
go.sum
@@ -1,121 +1,478 @@
|
|||||||
|
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0=
|
||||||
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14 h1:3zOOc7WdrATDXof+h/rBgMsg0sAmZIEVHft1UbWHh94=
|
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14 h1:3zOOc7WdrATDXof+h/rBgMsg0sAmZIEVHft1UbWHh94=
|
||||||
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14/go.mod h1:+VFiaivV54Sa94ijzA/ZHQLoHuoUIS9hIqCK6f/76Zw=
|
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14/go.mod h1:+VFiaivV54Sa94ijzA/ZHQLoHuoUIS9hIqCK6f/76Zw=
|
||||||
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2 h1:sIvihcW4qpN5qGSjmrsDDAbLpEq5tuHjJJfWY0Hud5Y=
|
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2 h1:sIvihcW4qpN5qGSjmrsDDAbLpEq5tuHjJJfWY0Hud5Y=
|
||||||
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2/go.mod h1:3YwJE8rEisS9eraee0hygGG4G3gqX8H8Nyu+nPTUnGU=
|
github.com/VojtechVitek/ratelimit v0.0.0-20160722140851-dc172bc0f6d2/go.mod h1:3YwJE8rEisS9eraee0hygGG4G3gqX8H8Nyu+nPTUnGU=
|
||||||
github.com/aws/aws-sdk-go v1.20.6 h1:kmy4Gvdlyez1fV4kw5RYxZzWKVyuHZHgPWeU/YvRsV4=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.29.24 h1:KOnds/LwADMDBaALL4UB98ZR+TUR1A1mYmAYbdLixLA=
|
||||||
|
github.com/aws/aws-sdk-go v1.29.24/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
||||||
|
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||||
|
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||||
|
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||||
|
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||||
|
github.com/btcsuite/btcutil v1.0.3-0.20201124182144-4031bdc69ded h1:WcPFZzCIqGt/TdFJHsOiX5dIlB/MUzrftltMhpjzfA8=
|
||||||
|
github.com/btcsuite/btcutil v1.0.3-0.20201124182144-4031bdc69ded/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=
|
||||||
|
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||||
|
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||||
|
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||||
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||||
|
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||||
|
github.com/calebcase/tmpfile v1.0.2-0.20200602150926-3af473ef8439 h1:fqGdSbbWVbQqNCQXd/dyZ7Bl+u8R2X7QCiNzwgyUa/M=
|
||||||
|
github.com/calebcase/tmpfile v1.0.2-0.20200602150926-3af473ef8439/go.mod h1:iErLeG/iqJr8LaQ/gYRv4GXdqssi3jg4iSzvrA06/lw=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e h1:rcHHSQqzCgvlwP0I/fQ8rQMn/MpHE5gWSLdtpxtP6KQ=
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e h1:rcHHSQqzCgvlwP0I/fQ8rQMn/MpHE5gWSLdtpxtP6KQ=
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e/go.mod h1:Byz7q8MSzSPkouskHJhX0er2mZY/m0Vj5bMeMCkkyY4=
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e/go.mod h1:Byz7q8MSzSPkouskHJhX0er2mZY/m0Vj5bMeMCkkyY4=
|
||||||
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329 h1:ERqCkG/uSyT74P1m/j9yR+so+7ynY4fbTvLY/Mr1ZMg=
|
github.com/dutchcoders/go-virustotal v0.0.0-20140923143438-24cc8e6fa329 h1:ERqCkG/uSyT74P1m/j9yR+so+7ynY4fbTvLY/Mr1ZMg=
|
||||||
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-20190520063132-37110d436c89 h1:FJc5t2SEtRmLXDWxHFQG4QB98Vqr7/60cIiUT2F5yAA=
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20190716184912-96e06a2276ba h1:474BcGUqYKnxg49p7O7i3m9EuFfOag+OtPw5b/nmGVk=
|
||||||
github.com/dutchcoders/transfer.sh-web v0.0.0-20190520063132-37110d436c89/go.mod h1:UjR1zlrq/R2Sef7e4q3TeJm4HcbLh4vRzlCEGJP+wLg=
|
github.com/dutchcoders/transfer.sh-web v0.0.0-20190716184912-96e06a2276ba/go.mod h1:UjR1zlrq/R2Sef7e4q3TeJm4HcbLh4vRzlCEGJP+wLg=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||||
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
|
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
|
||||||
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
|
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273 h1:fHbEOLXdSMRJrzJwQkKixEg3Uq2RIcNQF0Y7iiQ+gRk=
|
||||||
|
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273/go.mod h1:sam69Hju0uq+5uvLJUMDlsKlQ21Vrs1Kd/1YFPNYdOU=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
||||||
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
|
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/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.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||||
|
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||||
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||||
|
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||||
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||||
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
|
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||||
github.com/minio/cli v1.3.0 h1:vB0iUpmyaH54+1jJJj62Aa0qFF3xO3i0J3IcKiM6bHM=
|
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/minio/cli v1.3.0/go.mod h1:hLsWNQy2wIf3FKFnMlH69f4RdEyn8nbRA2shaulTjGY=
|
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
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/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-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 h1:RYiqpb2ii2Z6J4x0wxK46kvPBbFuZcdhS+CIztmYgZs=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||||
|
github.com/spacemonkeygo/monkit/v3 v3.0.4 h1:Ay+PZirv+qfd4sqcT+X/U3BnC7AcIaqp/IXh0oV36k8=
|
||||||
|
github.com/spacemonkeygo/monkit/v3 v3.0.4/go.mod h1:JcK1pCbReQsOsMKF/POFSZCq7drXFybgGmbc27tuwes=
|
||||||
|
github.com/spacemonkeygo/monkit/v3 v3.0.7 h1:LsGdIXl8mccqJrYEh4Uf4sLVGu/g0tjhNqQzdn9MzVk=
|
||||||
|
github.com/spacemonkeygo/monkit/v3 v3.0.7/go.mod h1:kj1ViJhlyADa7DiA4xVnTuPA46lFKbM7mxQTrXCuJP4=
|
||||||
|
github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a h1:8+cCjxhToanKmxLIbuyBNe2EnpgwhiivsIaRJstDRFA=
|
||||||
|
github.com/spacemonkeygo/monotime v0.0.0-20180824235756-e3f48a95f98a/go.mod h1:ul4bvvnCOPZgq8w0nTkSmWVg/hauVpFS97Am1YM1XXo=
|
||||||
|
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||||
|
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
|
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
|
||||||
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
|
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
|
||||||
|
github.com/urfave/cli v1.22.3 h1:FpNT6zq26xNpHZy08emi755QwzLPs6Pukqjlc7RfOMU=
|
||||||
|
github.com/urfave/cli v1.22.3/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3 h1:zMsHhfK9+Wdl1F7sIKLyx3wrOFofpb3rWFbA4HgcK5k=
|
||||||
|
github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3/go.mod h1:R0Gbuw7ElaGSLOZUSwBm/GgVwMd30jWxBDdAyMOeTuc=
|
||||||
|
github.com/zeebo/admission/v3 v3.0.2/go.mod h1:BP3isIv9qa2A7ugEratNq1dnl2oZRXaQUGdU7WXKtbw=
|
||||||
|
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
|
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||||
|
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
|
||||||
|
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
||||||
|
github.com/zeebo/float16 v0.1.0 h1:kRqxv5og6z1emEyz5FpW0/BVHe5VfxEAw6b1ljCZlUc=
|
||||||
|
github.com/zeebo/float16 v0.1.0/go.mod h1:fssGvvXu+XS8MH57cKmyrLB/cqioYeYX/2mXCN3a5wo=
|
||||||
|
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54 h1:+cwNE5KJ3pika4HuzmDHkDlK5myo0G9Sv+eO7WWxnUQ=
|
||||||
|
github.com/zeebo/incenc v0.0.0-20180505221441-0d92902eec54/go.mod h1:EI8LcOBDlSL3POyqwC1eJhOYlMBMidES+613EtmmT5w=
|
||||||
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||||
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
|
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||||
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||||
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38=
|
||||||
|
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
google.golang.org/api v0.5.0 h1:lj9SyhMzyoa38fgFF0oO2T6pjs5IzkLPKfVtxpyCRMM=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171 h1:xes2Q2k+d/+YNXVw0FpZkIDJiaux4OVrRKXRAzH6A0U=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
storj.io/common v0.0.0-20201207172416-78f4e59925c3 h1:D+rAQBzjl0Mw3VQ+1Sjv5/53I7JaIymMrkDW5DYBgRE=
|
||||||
|
storj.io/common v0.0.0-20201207172416-78f4e59925c3/go.mod h1:6sepaQTRLuygvA+GNPzdgRPOB1+wFfjde76KBWofbMY=
|
||||||
|
storj.io/drpc v0.0.16 h1:9sxypc5lKi/0D69cR21BR0S21+IvXfON8L5nXMVNTwQ=
|
||||||
|
storj.io/drpc v0.0.16/go.mod h1:zdmQ93nx4Z35u11pQ+GAnBy4DGOK3HJCSOfeh2RryTo=
|
||||||
|
storj.io/uplink v1.4.2 h1:Kj4ubuSQfoLRC0n1cJXt1Tgns0WF1DRNMs8Luh6+rY8=
|
||||||
|
storj.io/uplink v1.4.2/go.mod h1:VoxYTP5AzJ+gnzsqptuB5Ra8Old+fVVbwLCmi4jr5y4=
|
||||||
|
203
lock.json
203
lock.json
@@ -1,203 +0,0 @@
|
|||||||
{
|
|
||||||
"memo": "5b27aecb0272e40f3b8b8f9a5deeb7c9f5dbf06c53b1134de2b84eac466d27e0",
|
|
||||||
"projects": [
|
|
||||||
{
|
|
||||||
"name": "github.com/PuerkitoBio/ghost",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "206e6e460e14a42d1d811c970b30248db058e9b2",
|
|
||||||
"packages": [
|
|
||||||
".",
|
|
||||||
"handlers"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/VojtechVitek/ratelimit",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "dc172bc0f6d241e980010dbc63957ef1a2c8ca33",
|
|
||||||
"packages": [
|
|
||||||
".",
|
|
||||||
"memory"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/dutchcoders/go-clamd",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "a9a81beaffff0392094052913ec45fa140eb8511",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/dutchcoders/go-virustotal",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "24cc8e6fa329f020c70a3b32330b5743f1ba7971",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/dutchcoders/transfer.sh-web",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "cdb97c4b64a33dd1eec7e94b2c200cd9b06296a1",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/elazarl/go-bindata-assetfs",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/fatih/color",
|
|
||||||
"version": "v1.4.1",
|
|
||||||
"revision": "9131ab34cf20d2f6d83fdc67168a5430d1c7dc23",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/garyburd/redigo",
|
|
||||||
"version": "v1.0.0",
|
|
||||||
"revision": "8873b2f1995f59d4bcdd2b0dc9858e2cb9bf0c13",
|
|
||||||
"packages": [
|
|
||||||
"internal",
|
|
||||||
"redis"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/goamz/goamz",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "c35091c30f44b7f151ec9028b895465a191d1ea7",
|
|
||||||
"packages": [
|
|
||||||
"aws",
|
|
||||||
"s3"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/golang/gddo",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "72302b972abba39585150723aea3cf343e99437c",
|
|
||||||
"packages": [
|
|
||||||
"httputil/header"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/gorilla/context",
|
|
||||||
"version": "v1.1",
|
|
||||||
"revision": "1ea25387ff6f684839d82767c1733ff4d4d15d0a",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/gorilla/mux",
|
|
||||||
"version": "v1.3.0",
|
|
||||||
"revision": "392c28fe23e1c45ddba891b0320b3b5df220beea",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/gorilla/securecookie",
|
|
||||||
"version": "v1.1",
|
|
||||||
"revision": "667fe4e3466a040b780561fe9b51a83a3753eefc",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/mattn/go-colorable",
|
|
||||||
"version": "v0.0.7",
|
|
||||||
"revision": "d228849504861217f796da67fae4f6e347643f15",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/mattn/go-isatty",
|
|
||||||
"version": "v0.0.1",
|
|
||||||
"revision": "3a115632dcd687f9c8cd01679c83a06a0e21c1f3",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/minio/cli",
|
|
||||||
"version": "v1.3.0",
|
|
||||||
"revision": "8683fa7fef37cc8cb092f47bdb6b403e0049f9ee",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/nu7hatch/gouuid",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "179d4d0c4d8d407a32af483c2354df1d2c91e6c3",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/russross/blackfriday",
|
|
||||||
"version": "v1.4",
|
|
||||||
"revision": "0b647d0506a698cca42caca173e55559b12a69f2",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/shurcooL/sanitized_anchor_name",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "1dba4b3954bc059efc3991ec364f9f9a35f597d2",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "github.com/vaughan0/go-ini",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "golang.org/x/crypto",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "459e26527287adbc2adcc5d0d49abff9a5f315a7",
|
|
||||||
"packages": [
|
|
||||||
"acme",
|
|
||||||
"acme/autocert"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "golang.org/x/net",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "a6577fac2d73be281a500b310739095313165611",
|
|
||||||
"packages": [
|
|
||||||
"context",
|
|
||||||
"context/ctxhttp"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "golang.org/x/sys",
|
|
||||||
"branch": "master",
|
|
||||||
"revision": "99f16d856c9836c42d24e7ab64ea72916925fa97",
|
|
||||||
"packages": [
|
|
||||||
"unix"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gopkg.in/check.v1",
|
|
||||||
"branch": "v1",
|
|
||||||
"revision": "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
|
|
||||||
"packages": [
|
|
||||||
"."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -35,7 +35,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
blackfriday "gopkg.in/russross/blackfriday.v2"
|
blackfriday "github.com/russross/blackfriday/v2"
|
||||||
"html"
|
"html"
|
||||||
html_template "html/template"
|
html_template "html/template"
|
||||||
"io"
|
"io"
|
||||||
@@ -102,7 +102,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
token := vars["token"]
|
token := vars["token"]
|
||||||
filename := vars["filename"]
|
filename := vars["filename"]
|
||||||
|
|
||||||
_, 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())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
@@ -110,7 +110,8 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contentType, contentLength, err := s.storage.Head(token, filename)
|
contentType := metadata.ContentType
|
||||||
|
contentLength, err := s.storage.Head(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(404), 404)
|
http.Error(w, http.StatusText(404), 404)
|
||||||
return
|
return
|
||||||
@@ -130,7 +131,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
templatePath = "download.markdown.html"
|
templatePath = "download.markdown.html"
|
||||||
|
|
||||||
var reader io.ReadCloser
|
var reader io.ReadCloser
|
||||||
if reader, _, _, err = s.storage.Get(token, filename); err != nil {
|
if reader, _, err = s.storage.Get(token, filename); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -157,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, getURL(r).ResolveReference(relativeURL), true)
|
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, getURL(r).ResolveReference(relativeURLGet), true)
|
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 {
|
||||||
@@ -169,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
|
||||||
@@ -211,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
|
||||||
@@ -310,6 +311,12 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
contentLength := n
|
contentLength := n
|
||||||
|
|
||||||
|
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
||||||
|
log.Print("Entity too large")
|
||||||
|
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
metadata := MetadataForRequest(contentType, r)
|
metadata := MetadataForRequest(contentType, r)
|
||||||
|
|
||||||
buffer := &bytes.Buffer{}
|
buffer := &bytes.Buffer{}
|
||||||
@@ -338,7 +345,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)
|
||||||
}
|
}
|
||||||
@@ -454,6 +461,12 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
contentLength = n
|
contentLength = n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.maxUploadSize > 0 && contentLength > s.maxUploadSize {
|
||||||
|
log.Print("Entity too large")
|
||||||
|
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if contentLength == 0 {
|
if contentLength == 0 {
|
||||||
log.Print("Empty content-length")
|
log.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)
|
||||||
@@ -499,17 +512,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, true))
|
w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL, s.proxyPort))
|
||||||
|
|
||||||
fmt.Fprint(w, resolveURL(r, relativeURL, false))
|
fmt.Fprint(w, resolveURL(r, relativeURL, s.proxyPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveURL(r *http.Request, u *url.URL, absolutePath bool) string {
|
func resolveURL(r *http.Request, u *url.URL, proxyPort string) string {
|
||||||
if absolutePath {
|
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 {
|
||||||
@@ -526,8 +537,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
|
||||||
|
|
||||||
@@ -545,8 +556,22 @@ func resolveWebAddress(r *http.Request, proxyPath string) string {
|
|||||||
return webAddress
|
return webAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func getURL(r *http.Request) *url.URL {
|
// Similar to the logic found here:
|
||||||
u, _ := url.Parse(r.URL.String())
|
// https://github.com/golang/go/blob/release-branch.go1.14/src/net/http/clone.go#L22-L33
|
||||||
|
func cloneURL(u *url.URL) *url.URL {
|
||||||
|
c := &url.URL{}
|
||||||
|
*c = *u
|
||||||
|
|
||||||
|
if u.User != nil {
|
||||||
|
c.User = &url.Userinfo{}
|
||||||
|
*c.User = *u.User
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func getURL(r *http.Request, proxyPort string) *url.URL {
|
||||||
|
u := cloneURL(r.URL)
|
||||||
|
|
||||||
if r.TLS != nil {
|
if r.TLS != nil {
|
||||||
u.Scheme = "https"
|
u.Scheme = "https"
|
||||||
@@ -556,16 +581,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,10 +648,8 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +686,7 @@ func (s *Server) CheckDeletionToken(deletionToken, token, filename string) error
|
|||||||
|
|
||||||
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 s.storage.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@@ -672,6 +704,19 @@ func (s *Server) CheckDeletionToken(deletionToken, token, filename string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) purgeHandler() {
|
||||||
|
ticker := time.NewTicker(s.purgeInterval)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
err := s.storage.Purge(s.purgeDays)
|
||||||
|
log.Printf("error cleaning up expired files: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) deleteHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
@@ -720,7 +765,7 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, _, _, err := s.storage.Get(token, filename)
|
reader, _, err := s.storage.Get(token, filename)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
@@ -792,7 +837,7 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, _, contentLength, err := s.storage.Get(token, filename)
|
reader, contentLength, err := s.storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
@@ -851,7 +896,7 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, _, contentLength, err := s.storage.Get(token, filename)
|
reader, contentLength, err := s.storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
@@ -899,7 +944,8 @@ func (s *Server) headHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contentType, contentLength, err := s.storage.Head(token, filename)
|
contentType := metadata.ContentType
|
||||||
|
contentLength, err := s.storage.Head(token, filename)
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
@@ -933,7 +979,8 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, contentType, contentLength, err := s.storage.Get(token, filename)
|
contentType := metadata.ContentType
|
||||||
|
reader, contentLength, err := s.storage.Get(token, filename)
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
@@ -1010,7 +1057,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)
|
||||||
|
@@ -25,7 +25,10 @@ THE SOFTWARE.
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
crypto_rand "crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
gorillaHandlers "github.com/gorilla/handlers"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -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:] != "/" {
|
||||||
@@ -159,12 +175,25 @@ func Logger(logger *log.Logger) OptionFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MaxUploadSize(kbytes int64) OptionFn {
|
||||||
|
return func(srvr *Server) {
|
||||||
|
srvr.maxUploadSize = kbytes * 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
func RateLimit(requests int) OptionFn {
|
func RateLimit(requests int) OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
srvr.rateLimitRequests = requests
|
srvr.rateLimitRequests = requests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Purge(days, interval int) OptionFn {
|
||||||
|
return func(srvr *Server) {
|
||||||
|
srvr.purgeDays = time.Duration(days) * time.Hour * 24
|
||||||
|
srvr.purgeInterval = time.Duration(interval) * time.Hour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ForceHTTPs() OptionFn {
|
func ForceHTTPs() OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
srvr.forceHTTPs = true
|
srvr.forceHTTPs = true
|
||||||
@@ -255,8 +284,12 @@ type Server struct {
|
|||||||
|
|
||||||
locks map[string]*sync.Mutex
|
locks map[string]*sync.Mutex
|
||||||
|
|
||||||
|
maxUploadSize int64
|
||||||
rateLimitRequests int
|
rateLimitRequests int
|
||||||
|
|
||||||
|
purgeDays time.Duration
|
||||||
|
purgeInterval time.Duration
|
||||||
|
|
||||||
storage Storage
|
storage Storage
|
||||||
|
|
||||||
forceHTTPs bool
|
forceHTTPs bool
|
||||||
@@ -270,11 +303,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 +332,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 +452,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,
|
||||||
@@ -458,6 +510,10 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
s.logger.Printf("---------------------------")
|
s.logger.Printf("---------------------------")
|
||||||
|
|
||||||
|
if s.purgeDays > 0 {
|
||||||
|
go s.purgeHandler()
|
||||||
|
}
|
||||||
|
|
||||||
term := make(chan os.Signal, 1)
|
term := make(chan os.Signal, 1)
|
||||||
signal.Notify(term, os.Interrupt)
|
signal.Notify(term, os.Interrupt)
|
||||||
signal.Notify(term, syscall.SIGTERM)
|
signal.Notify(term, syscall.SIGTERM)
|
||||||
|
@@ -2,34 +2,38 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"mime"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"google.golang.org/api/drive/v3"
|
"google.golang.org/api/drive/v3"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"storj.io/common/storj"
|
||||||
|
"storj.io/uplink"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
|
Get(token string, filename string) (reader io.ReadCloser, contentLength uint64, err error)
|
||||||
Head(token string, filename string) (contentType string, contentLength uint64, err error)
|
Head(token string, filename string) (contentLength uint64, err error)
|
||||||
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
|
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
|
||||||
Delete(token string, filename string) error
|
Delete(token string, filename string) error
|
||||||
IsNotExist(err error) bool
|
IsNotExist(err error) bool
|
||||||
|
Purge(days time.Duration) error
|
||||||
|
|
||||||
Type() string
|
Type() string
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,7 @@ func (s *LocalStorage) Type() string {
|
|||||||
return "local"
|
return "local"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalStorage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
|
func (s *LocalStorage) Head(token string, filename string) (contentLength uint64, err error) {
|
||||||
path := filepath.Join(s.basedir, token, filename)
|
path := filepath.Join(s.basedir, token, filename)
|
||||||
|
|
||||||
var fi os.FileInfo
|
var fi os.FileInfo
|
||||||
@@ -58,12 +62,10 @@ func (s *LocalStorage) Head(token string, filename string) (contentType string,
|
|||||||
|
|
||||||
contentLength = uint64(fi.Size())
|
contentLength = uint64(fi.Size())
|
||||||
|
|
||||||
contentType = mime.TypeByExtension(filepath.Ext(filename))
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||||
path := filepath.Join(s.basedir, token, filename)
|
path := filepath.Join(s.basedir, token, filename)
|
||||||
|
|
||||||
// content type , content length
|
// content type , content length
|
||||||
@@ -78,8 +80,6 @@ func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser,
|
|||||||
|
|
||||||
contentLength = uint64(fi.Size())
|
contentLength = uint64(fi.Size())
|
||||||
|
|
||||||
contentType = mime.TypeByExtension(filepath.Ext(filename))
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +92,27 @@ func (s *LocalStorage) Delete(token string, filename string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *LocalStorage) Purge(days time.Duration) (err error) {
|
||||||
|
err = filepath.Walk(s.basedir,
|
||||||
|
func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.ModTime().Before(time.Now().Add(-1 * days)) {
|
||||||
|
err = os.Remove(path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (s *LocalStorage) IsNotExist(err error) bool {
|
func (s *LocalStorage) IsNotExist(err error) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
@@ -106,7 +127,7 @@ func (s *LocalStorage) Put(token string, filename string, reader io.Reader, cont
|
|||||||
|
|
||||||
path := filepath.Join(s.basedir, token)
|
path := filepath.Join(s.basedir, token)
|
||||||
|
|
||||||
if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
|
if err = os.MkdirAll(path, 0700); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,20 +150,28 @@ type S3Storage struct {
|
|||||||
session *session.Session
|
session *session.Session
|
||||||
s3 *s3.S3
|
s3 *s3.S3
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
purgeDays time.Duration
|
||||||
noMultipart bool
|
noMultipart bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewS3Storage(accessKey, secretKey, bucketName, region, endpoint string, logger *log.Logger, disableMultipart bool) (*S3Storage, error) {
|
func NewS3Storage(accessKey, secretKey, bucketName string, purgeDays int, region, endpoint string, disableMultipart bool, forcePathStyle bool, logger *log.Logger) (*S3Storage, error) {
|
||||||
sess := getAwsSession(accessKey, secretKey, region, endpoint)
|
sess := getAwsSession(accessKey, secretKey, region, endpoint, forcePathStyle)
|
||||||
|
|
||||||
return &S3Storage{bucket: bucketName, s3: s3.New(sess), session: sess, logger: logger, noMultipart: disableMultipart}, nil
|
return &S3Storage{
|
||||||
|
bucket: bucketName,
|
||||||
|
s3: s3.New(sess),
|
||||||
|
session: sess,
|
||||||
|
logger: logger,
|
||||||
|
noMultipart: disableMultipart,
|
||||||
|
purgeDays: time.Duration(purgeDays*24) * time.Hour,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) Type() string {
|
func (s *S3Storage) Type() string {
|
||||||
return "s3"
|
return "s3"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
|
func (s *S3Storage) Head(token string, filename string) (contentLength uint64, err error) {
|
||||||
key := fmt.Sprintf("%s/%s", token, filename)
|
key := fmt.Sprintf("%s/%s", token, filename)
|
||||||
|
|
||||||
headRequest := &s3.HeadObjectInput{
|
headRequest := &s3.HeadObjectInput{
|
||||||
@@ -156,10 +185,6 @@ func (s *S3Storage) Head(token string, filename string) (contentType string, con
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.ContentType != nil {
|
|
||||||
contentType = *response.ContentType
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.ContentLength != nil {
|
if response.ContentLength != nil {
|
||||||
contentLength = uint64(*response.ContentLength)
|
contentLength = uint64(*response.ContentLength)
|
||||||
}
|
}
|
||||||
@@ -167,6 +192,11 @@ func (s *S3Storage) Head(token string, filename string) (contentType string, con
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *S3Storage) Purge(days time.Duration) (err error) {
|
||||||
|
// NOOP expiration is set at upload time
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *S3Storage) IsNotExist(err error) bool {
|
func (s *S3Storage) IsNotExist(err error) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
@@ -182,7 +212,7 @@ func (s *S3Storage) IsNotExist(err error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||||
key := fmt.Sprintf("%s/%s", token, filename)
|
key := fmt.Sprintf("%s/%s", token, filename)
|
||||||
|
|
||||||
getRequest := &s3.GetObjectInput{
|
getRequest := &s3.GetObjectInput{
|
||||||
@@ -195,10 +225,6 @@ func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.ContentType != nil {
|
|
||||||
contentType = *response.ContentType
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.ContentLength != nil {
|
if response.ContentLength != nil {
|
||||||
contentLength = uint64(*response.ContentLength)
|
contentLength = uint64(*response.ContentLength)
|
||||||
}
|
}
|
||||||
@@ -243,16 +269,15 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content
|
|||||||
|
|
||||||
// Create an uploader with the session and custom options
|
// Create an uploader with the session and custom options
|
||||||
uploader := s3manager.NewUploader(s.session, func(u *s3manager.Uploader) {
|
uploader := s3manager.NewUploader(s.session, func(u *s3manager.Uploader) {
|
||||||
u.PartSize = (1 << 20) * 5 // The minimum/default allowed part size is 5MB
|
|
||||||
u.Concurrency = concurrency // default is 5
|
u.Concurrency = concurrency // default is 5
|
||||||
u.MaxUploadParts = concurrency
|
|
||||||
u.LeavePartsOnError = false
|
u.LeavePartsOnError = false
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = uploader.Upload(&s3manager.UploadInput{
|
_, err = uploader.Upload(&s3manager.UploadInput{
|
||||||
Bucket: aws.String(s.bucket),
|
Bucket: aws.String(s.bucket),
|
||||||
Key: aws.String(key),
|
Key: aws.String(key),
|
||||||
Body: reader,
|
Body: reader,
|
||||||
|
Expires: aws.Time(time.Now().Add(s.purgeDays)),
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -400,7 +425,7 @@ func (s *GDrive) Type() string {
|
|||||||
return "gdrive"
|
return "gdrive"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GDrive) Head(token string, filename string) (contentType string, contentLength uint64, err error) {
|
func (s *GDrive) Head(token string, filename string) (contentLength uint64, err error) {
|
||||||
var fileId string
|
var fileId string
|
||||||
fileId, err = s.findId(filename, token)
|
fileId, err = s.findId(filename, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -408,18 +433,16 @@ func (s *GDrive) Head(token string, filename string) (contentType string, conten
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fi *drive.File
|
var fi *drive.File
|
||||||
if fi, err = s.service.Files.Get(fileId).Fields("mimeType", "size").Do(); err != nil {
|
if fi, err = s.service.Files.Get(fileId).Fields("size").Do(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contentLength = uint64(fi.Size)
|
contentLength = uint64(fi.Size)
|
||||||
|
|
||||||
contentType = fi.MimeType
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GDrive) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
func (s *GDrive) Get(token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||||
var fileId string
|
var fileId string
|
||||||
fileId, err = s.findId(filename, token)
|
fileId, err = s.findId(filename, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -427,14 +450,13 @@ func (s *GDrive) Get(token string, filename string) (reader io.ReadCloser, conte
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fi *drive.File
|
var fi *drive.File
|
||||||
fi, err = s.service.Files.Get(fileId).Fields("mimeType", "size", "md5Checksum").Do()
|
fi, err = s.service.Files.Get(fileId).Fields("size", "md5Checksum").Do()
|
||||||
if !s.hasChecksum(fi) {
|
if !s.hasChecksum(fi) {
|
||||||
err = fmt.Errorf("Cannot find file %s/%s", token, filename)
|
err = fmt.Errorf("Cannot find file %s/%s", token, filename)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
contentLength = uint64(fi.Size)
|
contentLength = uint64(fi.Size)
|
||||||
contentType = fi.MimeType
|
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var res *http.Response
|
var res *http.Response
|
||||||
@@ -462,6 +484,34 @@ func (s *GDrive) Delete(token string, filename string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *GDrive) Purge(days time.Duration) (err error) {
|
||||||
|
nextPageToken := ""
|
||||||
|
|
||||||
|
expirationDate := time.Now().Add(-1 * days).Format(time.RFC3339)
|
||||||
|
q := fmt.Sprintf("'%s' in parents and modifiedTime < '%s' and mimeType!='%s' and trashed=false", s.rootId, expirationDate, GDriveDirectoryMimeType)
|
||||||
|
l, err := s.list(nextPageToken, q)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for 0 < len(l.Files) {
|
||||||
|
for _, fi := range l.Files {
|
||||||
|
err = s.service.Files.Delete(fi.Id).Do()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.NextPageToken == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err = s.list(l.NextPageToken, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (s *GDrive) IsNotExist(err error) bool {
|
func (s *GDrive) IsNotExist(err error) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if e, ok := err.(*googleapi.Error); ok {
|
if e, ok := err.(*googleapi.Error); ok {
|
||||||
@@ -563,3 +613,128 @@ func saveGDriveToken(path string, token *oauth2.Token, logger *log.Logger) {
|
|||||||
|
|
||||||
json.NewEncoder(f).Encode(token)
|
json.NewEncoder(f).Encode(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StorjStorage struct {
|
||||||
|
Storage
|
||||||
|
project *uplink.Project
|
||||||
|
bucket *uplink.Bucket
|
||||||
|
purgeDays time.Duration
|
||||||
|
logger *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStorjStorage(access, bucket string, purgeDays int, logger *log.Logger) (*StorjStorage, error) {
|
||||||
|
var instance StorjStorage
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
parsedAccess, err := uplink.ParseAccess(access)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.project, err = uplink.OpenProject(ctx, parsedAccess)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.bucket, err = instance.project.EnsureBucket(ctx, bucket)
|
||||||
|
if err != nil {
|
||||||
|
//Ignoring the error to return the one that occurred first, but try to clean up.
|
||||||
|
_ = instance.project.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.purgeDays = time.Duration(purgeDays*24) * time.Hour
|
||||||
|
|
||||||
|
instance.logger = logger
|
||||||
|
|
||||||
|
return &instance, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Type() string {
|
||||||
|
return "storj"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Head(token string, filename string) (contentLength uint64, err error) {
|
||||||
|
key := storj.JoinPaths(token, filename)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
obj, err := s.project.StatObject(ctx, s.bucket.Name, key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contentLength = uint64(obj.System.ContentLength)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Get(token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||||
|
key := storj.JoinPaths(token, filename)
|
||||||
|
|
||||||
|
s.logger.Printf("Getting file %s from Storj Bucket", filename)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
download, err := s.project.DownloadObject(ctx, s.bucket.Name, key, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contentLength = uint64(download.Info().System.ContentLength)
|
||||||
|
|
||||||
|
reader = download
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Delete(token string, filename string) (err error) {
|
||||||
|
key := storj.JoinPaths(token, filename)
|
||||||
|
|
||||||
|
s.logger.Printf("Deleting file %s from Storj Bucket", filename)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
_, err = s.project.DeleteObject(ctx, s.bucket.Name, key)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Purge(days time.Duration) (err error) {
|
||||||
|
// NOOP expiration is set at upload time
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) (err error) {
|
||||||
|
key := storj.JoinPaths(token, filename)
|
||||||
|
|
||||||
|
s.logger.Printf("Uploading file %s to Storj Bucket", filename)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
writer, err := s.project.UploadObject(ctx, s.bucket.Name, key, &uplink.UploadOptions{Expires: time.Now().Add(s.purgeDays)})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := io.Copy(writer, reader)
|
||||||
|
if err != nil || uint64(n) != contentLength {
|
||||||
|
//Ignoring the error to return the one that occurred first, but try to clean up.
|
||||||
|
_ = writer.Abort()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = writer.SetCustomMetadata(ctx, uplink.CustomMetadata{"content-type": contentType})
|
||||||
|
if err != nil {
|
||||||
|
//Ignoring the error to return the one that occurred first, but try to clean up.
|
||||||
|
_ = writer.Abort()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.Commit()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorjStorage) IsNotExist(err error) bool {
|
||||||
|
return errors.Is(err, uplink.ErrObjectNotFound)
|
||||||
|
}
|
||||||
|
@@ -25,7 +25,6 @@ THE SOFTWARE.
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
@@ -33,15 +32,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/golang/gddo/httputil/header"
|
"github.com/golang/gddo/httputil/header"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getAwsSession(accessKey, secretKey, region, endpoint string) *session.Session {
|
func getAwsSession(accessKey, secretKey, region, endpoint string, forcePathStyle bool) *session.Session {
|
||||||
return session.Must(session.NewSession(&aws.Config{
|
return session.Must(session.NewSession(&aws.Config{
|
||||||
Region: aws.String(region),
|
Region: aws.String(region),
|
||||||
Endpoint: aws.String(endpoint),
|
Endpoint: aws.String(endpoint),
|
||||||
Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
|
Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
|
||||||
|
S3ForcePathStyle: aws.Bool(forcePathStyle),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user