v0.2.4 release (#116) (#117)

This commit is contained in:
Graham Steffaniak 2024-02-09 18:13:02 -06:00 committed by GitHub
parent 0281aee56f
commit d9e583fea7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
85 changed files with 1827 additions and 2148 deletions

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go test -race -v ./... - run: cd backend && go test -race -v ./...
lint-backend: lint-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2
- run: cd backend && golangci-lint run - run: cd backend && golangci-lint run
format-backend: format-backend:
@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go fmt ./... - run: cd backend && go fmt ./...
lint-frontend: lint-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go test -race -v ./... - run: cd backend && go test -race -v ./...
lint-backend: lint-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2
- run: cd backend && golangci-lint run - run: cd backend && golangci-lint run
format-backend: format-backend:
@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go fmt ./... - run: cd backend && go fmt ./...
lint-frontend: lint-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go test -race -v ./... - run: cd backend && go test -race -v ./...
lint-backend: lint-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2
- run: cd backend && golangci-lint run - run: cd backend && golangci-lint run
format-backend: format-backend:
@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go fmt ./... - run: cd backend && go fmt ./...
lint-frontend: lint-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go test -race -v ./... - run: cd backend && go test -race -v ./...
lint-backend: lint-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2
- run: cd backend && golangci-lint run - run: cd backend && golangci-lint run
format-backend: format-backend:
@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: 1.21.1 go-version: 1.22.0
- run: cd backend && go fmt ./... - run: cd backend && go fmt ./...
lint-frontend: lint-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. For commit guidelines, please refer to [Standard Version](https://github.com/conventional-changelog/standard-version). All notable changes to this project will be documented in this file. For commit guidelines, please refer to [Standard Version](https://github.com/conventional-changelog/standard-version).
## v0.2.4
- Faature: [create-folder-feature](https://github.com/gtsteffaniak/filebrowser/pull/105)
- Feature: [playable shared video](https://github.com/filebrowser/filebrowser/issues/2537)
- Feature: photos, videos, and audio get embedded preview on share instead of icon
- FIX: sharable link bug, now uses special publicUser
- Bump go version to 1.22
- In prep for vue3 migration, npm modules removed:
- js-base64
- pretty-bytes
- whatwg-fetch
- lodash.throttle
- lodash.clonedeep
## v0.2.3 ## v0.2.3
- Feature: token expiration time now configurable - Feature: token expiration time now configurable

View File

@ -5,7 +5,7 @@ RUN npm ci --maxsockets 1
COPY ./frontend/ ./ COPY ./frontend/ ./
RUN npm run build RUN npm run build
FROM golang:1.21-alpine as base FROM golang:1.22-alpine as base
WORKDIR /app WORKDIR /app
COPY ./backend ./ COPY ./backend ./
RUN go get -u golang.org/x/net RUN go get -u golang.org/x/net

View File

@ -9,11 +9,9 @@
<img width="800" src="https://github.com/gtsteffaniak/filebrowser/assets/42989099/899152cf-3e69-4179-aa82-752af2df3fc6" title="Main Screenshot"> <img width="800" src="https://github.com/gtsteffaniak/filebrowser/assets/42989099/899152cf-3e69-4179-aa82-752af2df3fc6" title="Main Screenshot">
</p> </p>
> [!NOTE]
> Only intended to be used with docker.
> [!WARNING] > [!WARNING]
> Starting with v0.2.0, *ALL* configuration is done via `filebrowser.yaml` configuration file. > Starting with v0.2.0, *ALL* configuration is done via `filebrowser.yaml` configuration file.
> Starting with v0.2.4 *ALL* share links need to be re-created (due to security fix).
This fork makes the following significant changes to filebrowser for origin: This fork makes the following significant changes to filebrowser for origin:
@ -22,11 +20,11 @@ This fork makes the following significant changes to filebrowser for origin:
- realtime results as you type - realtime results as you type
- Works with more type filters - Works with more type filters
- interactive results page. - interactive results page.
1. [x] Revamped and simplified GUI navbar and sidebar menu. 2. [x] Revamped and simplified GUI navbar and sidebar menu.
1. [x] **IMPORTANT** Revamped configuration via `filebrowser.yml` config file. 3. [x] **IMPORTANT** Revamped configuration via `filebrowser.yml` config file.
1. [x] More configurations possible at a per-user level 4. [x] More configurations possible at a per-user level
- <img width="450" alt="image" src="https://github.com/gtsteffaniak/filebrowser/assets/42989099/625bd7c4-5ee9-4011-aaae-2a388ab0813b"> - <img width="450" alt="image" src="https://github.com/gtsteffaniak/filebrowser/assets/42989099/625bd7c4-5ee9-4011-aaae-2a388ab0813b">
1. [x] Additional compact view mode as well as refreshed view mode styles. 5. [x] Additional compact view mode as well as refreshed view mode styles.
## About ## About
@ -59,7 +57,7 @@ Using docker:
1. docker run (no persistent db): 1. docker run (no persistent db):
``` ```
docker run -it -v /path/to/folder:/srv -p 80:8080 gtstef/filebrowser docker run -it -v /path/to/folder:/srv -p 80:80 gtstef/filebrowser
``` ```
1. docker-compose: 1. docker-compose:
@ -75,7 +73,7 @@ services:
- './database:/database' # optional if you want db to persist - configure a path under "database" dir in config file. - './database:/database' # optional if you want db to persist - configure a path under "database" dir in config file.
- './filebrowser.yaml:/filebrowser.yaml' # required - './filebrowser.yaml:/filebrowser.yaml' # required
ports: ports:
- '80:8080' - '80:80'
image: gtstef/filebrowser image: gtstef/filebrowser
restart: always restart: always
``` ```
@ -91,7 +89,7 @@ services:
- './database:/database' # optional if you want db to persist - configure a path under "database" dir in config file. - './database:/database' # optional if you want db to persist - configure a path under "database" dir in config file.
- './filebrowser.yaml:/filebrowser.yaml' # required - './filebrowser.yaml:/filebrowser.yaml' # required
ports: ports:
- '80:8080' - '80:80'
image: gtstef/filebrowser image: gtstef/filebrowser
restart: always restart: always
volumes: volumes:
@ -103,12 +101,32 @@ volumes:
``` ```
Not using docker (not recommended)
```
./filebrowser -f <filebrowser.yml or other /path/to/config.yaml>
```
## Configuration ## Configuration
All configuration is now done via a single configuration file: `filebrowser.yaml`, here is an example minimal [configuration file](./backend/filebrowser.yaml). All configuration is now done via a single configuration file: `filebrowser.yaml`, here is an example minimal [configuration file](./backend/filebrowser.yaml).
View the [Configuration Help Page](./configuration.md) for available configuration options and other help. View the [Configuration Help Page](./configuration.md) for available configuration options and other help.
## Migration from filebrowser/filebrowser
If you are currently using filebrowser from the filebrowser/filebrowser repo, but want to try using this. I recommend you start fresh without reusing the database, but there are a few things you'll need to do if you must migrate:
1. Create a configuration file as mentioned above.
2. Copy your database file from the original filebrowser to the path of the new one.
3. Update the configuration file to use the database (under server in filebrowser.yml)
4. If you are using docker, update the docker-compose file or docker run command to use the config file as described in the install section above.
5. If you are not using docker, just make sure you run filebrowser -f filebrowser.yml and have valid filebrowser config.
The filebrowser application should run with the same user and rules that you have from the original. But keep in mind the differences that are mentioned at the top of this readme.
### background & help ### background & help
The original project filebrowser/filebrowser used multiple different ways to configure the server. The original project filebrowser/filebrowser used multiple different ways to configure the server.

View File

@ -145,7 +145,6 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
} }
if u == nil { if u == nil {
log.Println("creds", a.Cred.Password)
// create user with the provided credentials // create user with the provided credentials
d := &users.User{ d := &users.User{
Username: a.Cred.Username, Username: a.Cred.Username,

View File

@ -11,34 +11,34 @@ goos: linux
goarch: amd64 goarch: amd64
pkg: github.com/gtsteffaniak/filebrowser/files pkg: github.com/gtsteffaniak/filebrowser/files
cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz
BenchmarkFillIndex-8 10 3295862 ns/op 230448 B/op 1927 allocs/op BenchmarkFillIndex-8 10 3587120 ns/op 273640 B/op 2013 allocs/op
BenchmarkSearchAllIndexes-8 10 30033386 ns/op 19647893 B/op 298702 allocs/op BenchmarkSearchAllIndexes-8 10 31291180 ns/op 19500700 B/op 298636 allocs/op
PASS PASS
ok github.com/gtsteffaniak/filebrowser/files 0.392s ok github.com/gtsteffaniak/filebrowser/files 0.408s
PASS PASS
ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 h: 401 <nil>
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 h: 401 <nil>
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 h: 401 <nil>
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 h: 401 <nil>
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 Saving new user: username 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 Saving new user: publicUser
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 h: 401 <nil>
2023/11/24 13:57:20 h: 401 <nil> 2024/02/07 07:16:43 h: 401 <nil>
PASS PASS
ok github.com/gtsteffaniak/filebrowser/http 0.208s ok github.com/gtsteffaniak/filebrowser/http 0.202s
PASS PASS
ok github.com/gtsteffaniak/filebrowser/img 0.118s ok github.com/gtsteffaniak/filebrowser/img 0.125s
PASS PASS
ok github.com/gtsteffaniak/filebrowser/rules 0.002s ok github.com/gtsteffaniak/filebrowser/rules 0.002s
PASS PASS

View File

@ -1,5 +1,5 @@
server: server:
port: 8080 port: 80
baseURL: "/" baseURL: "/"
root: "/srv" root: "/srv"
auth: auth:

View File

@ -29,10 +29,9 @@ var textTypes = []string{
".yaml", ".yaml",
".yml", ".yml",
".json", ".json",
".bashrc",
".zshrc",
".env", ".env",
} }
var compressedFile = []string{ var compressedFile = []string{
".7z", ".7z",
".rar", ".rar",

View File

@ -15,6 +15,7 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"unicode/utf8"
"github.com/spf13/afero" "github.com/spf13/afero"
@ -119,7 +120,7 @@ func FileInfoFaster(opts FileOptions) (*FileInfo, error) {
adjustedPath := makeIndexPath(trimmed, index.Root) adjustedPath := makeIndexPath(trimmed, index.Root)
var info FileInfo var info FileInfo
info, exists := index.GetMetadataInfo(adjustedPath) info, exists := index.GetMetadataInfo(adjustedPath)
if exists { if exists && !opts.Content {
// Check if the cache time is less than 1 second // Check if the cache time is less than 1 second
if time.Since(info.CacheTime) > time.Second { if time.Since(info.CacheTime) > time.Second {
go refreshFileInfo(opts) go refreshFileInfo(opts)
@ -127,6 +128,11 @@ func FileInfoFaster(opts FileOptions) (*FileInfo, error) {
// refresh cache after // refresh cache after
return &info, nil return &info, nil
} else { } else {
// don't bother caching content
if opts.Content {
file, err := NewFileInfo(opts)
return file, err
}
updated := refreshFileInfo(opts) updated := refreshFileInfo(opts)
if !updated { if !updated {
file, err := NewFileInfo(opts) file, err := NewFileInfo(opts)
@ -144,23 +150,24 @@ func refreshFileInfo(opts FileOptions) bool {
if !opts.Checker.Check(opts.Path) { if !opts.Checker.Check(opts.Path) {
return false return false
} }
file, err := stat(opts.Path, opts) // Pass opts.Path here
if err != nil {
return false
}
index := GetIndex(rootPath) index := GetIndex(rootPath)
trimmed := strings.TrimPrefix(opts.Path, "/") trimmed := strings.TrimPrefix(opts.Path, "/")
if trimmed == "" { if trimmed == "" {
trimmed = "/" trimmed = "/"
} }
adjustedPath := makeIndexPath(trimmed, index.Root) adjustedPath := makeIndexPath(trimmed, index.Root)
file, err := stat(opts.Path, opts) // Pass opts.Path here
if err != nil {
return false
}
_ = file.detectType(adjustedPath, true, opts.Content, opts.ReadHeader)
if file.IsDir { if file.IsDir {
err := file.readListing(opts.Path, opts.Checker, opts.ReadHeader) err := file.readListing(opts.Path, opts.Checker, opts.ReadHeader)
if err != nil { if err != nil {
return false return false
} }
//_, exists := index.GetFileMetadata(adjustedPath) //_, exists := index.GetFileMetadata(adjustedPath)
return index.UpdateFileMetadata(adjustedPath, *file) return index.UpdateFileMetadata(adjustedPath, *file)
} else { } else {
//_, exists := index.GetFileMetadata(adjustedPath) //_, exists := index.GetFileMetadata(adjustedPath)
@ -191,7 +198,6 @@ func stat(path string, opts FileOptions) (*FileInfo, error) {
} }
} }
} }
if file == nil || file.IsSymlink { if file == nil || file.IsSymlink {
info, err := opts.Fs.Stat(opts.Path) info, err := opts.Fs.Stat(opts.Path)
if err != nil { if err != nil {
@ -272,12 +278,33 @@ func (i *FileInfo) RealPath() string {
return i.Path return i.Path
} }
// addContent reads and sets content based on the file type.
func (i *FileInfo) addContent(path string) error {
if !i.IsDir {
afs := &afero.Afero{Fs: i.Fs}
content, err := afs.ReadFile(path)
if err != nil {
return err
}
c := string(string(content))
if !utf8.ValidString(c) {
return nil
}
i.Content = string(c)
}
return nil
}
// detectType detects the file type. // detectType detects the file type.
func (i *FileInfo) detectType(path string, modify, saveContent, readHeader bool) error { func (i *FileInfo) detectType(path string, modify, saveContent, readHeader bool) error {
if IsNamedPipe(i.Mode) { if IsNamedPipe(i.Mode) {
i.Type = "blob" i.Type = "blob"
if saveContent {
return i.addContent(path)
}
return nil return nil
} }
var buffer []byte var buffer []byte
if readHeader { if readHeader {
buffer = i.readFirstBytes() buffer = i.readFirstBytes()
@ -286,23 +313,20 @@ func (i *FileInfo) detectType(path string, modify, saveContent, readHeader bool)
http.DetectContentType(buffer) http.DetectContentType(buffer)
} }
} }
ext := filepath.Ext(i.Name) ext := filepath.Ext(i.Name)
for _, fileType := range AllFiletypeOptions { for _, fileType := range AllFiletypeOptions {
if IsMatchingType(ext, fileType) { if IsMatchingType(ext, fileType) {
i.Type = fileType i.Type = fileType
} }
switch i.Type { switch i.Type {
case "text": case "text":
if !modify { if !modify {
i.Type = "textImmutable" i.Type = "textImmutable"
} }
if saveContent { if saveContent {
afs := &afero.Afero{Fs: i.Fs} return i.addContent(path)
content, err := afs.ReadFile(path)
if err != nil {
return err
}
i.Content = string(content)
} }
case "video": case "video":
parentDir := strings.TrimRight(path, i.Name) parentDir := strings.TrimRight(path, i.Name)
@ -310,12 +334,21 @@ func (i *FileInfo) detectType(path string, modify, saveContent, readHeader bool)
case "doc": case "doc":
if ext == ".pdf" { if ext == ".pdf" {
i.Type = "pdf" i.Type = "pdf"
return nil
}
if saveContent {
return i.addContent(path)
} }
} }
} }
if i.Type == "" { if i.Type == "" {
i.Type = "blob" i.Type = "blob"
if saveContent {
return i.addContent(path)
}
} }
return nil return nil
} }

View File

@ -28,23 +28,24 @@ func (si *Index) GetFileMetadata(adjustedPath string) (FileInfo, bool) {
// UpdateFileMetadata updates the FileInfo for the specified directory in the index. // UpdateFileMetadata updates the FileInfo for the specified directory in the index.
func (si *Index) UpdateFileMetadata(adjustedPath string, info FileInfo) bool { func (si *Index) UpdateFileMetadata(adjustedPath string, info FileInfo) bool {
si.mu.RLock() si.mu.Lock()
defer si.mu.Unlock()
dir, exists := si.Directories[adjustedPath] dir, exists := si.Directories[adjustedPath]
si.mu.RUnlock() if !exists {
if exists {
// Initialize the Metadata map if it is nil // Initialize the Metadata map if it is nil
if dir.Metadata == nil { if dir.Metadata == nil {
dir.Metadata = make(map[string]FileInfo) dir.Metadata = make(map[string]FileInfo)
} }
si.Directories[adjustedPath] = dir
// Release the read lock before calling SetFileMetadata // Release the read lock before calling SetFileMetadata
} }
return si.SetFileMetadata(adjustedPath, info) return si.SetFileMetadata(adjustedPath, info)
} }
// SetFileMetadata sets the FileInfo for the specified directory in the index. // SetFileMetadata sets the FileInfo for the specified directory in the index.
// internal use only
func (si *Index) SetFileMetadata(adjustedPath string, info FileInfo) bool { func (si *Index) SetFileMetadata(adjustedPath string, info FileInfo) bool {
si.mu.Lock()
defer si.mu.Unlock()
_, exists := si.Directories[adjustedPath] _, exists := si.Directories[adjustedPath]
if !exists { if !exists {
return false return false

View File

@ -1,56 +1,56 @@
module github.com/gtsteffaniak/filebrowser module github.com/gtsteffaniak/filebrowser
go 1.21 go 1.22.0
require ( require (
github.com/asdine/storm/v3 v3.2.1 github.com/asdine/storm/v3 v3.2.1
github.com/disintegration/imaging v1.6.2 github.com/disintegration/imaging v1.6.2
github.com/dsoprea/go-exif/v3 v3.0.1 github.com/dsoprea/go-exif/v3 v3.0.1
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
github.com/goccy/go-yaml v1.11.0 github.com/goccy/go-yaml v1.11.3
github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang-jwt/jwt/v4 v4.5.0
github.com/google/go-cmp v0.5.9 github.com/google/go-cmp v0.6.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.1
github.com/marusama/semaphore/v2 v2.5.0 github.com/marusama/semaphore/v2 v2.5.0
github.com/mholt/archiver/v3 v3.5.1 github.com/mholt/archiver/v3 v3.5.1
github.com/shirou/gopsutil/v3 v3.23.8 github.com/shirou/gopsutil/v3 v3.24.1
github.com/spf13/afero v1.9.5 github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
golang.org/x/crypto v0.17.0 golang.org/x/crypto v0.18.0
golang.org/x/image v0.12.0 golang.org/x/image v0.15.0
golang.org/x/text v0.14.0 golang.org/x/text v0.14.0
) )
require ( require (
github.com/andybalholm/brotli v1.0.1 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
github.com/fatih/color v1.10.0 // indirect github.com/fatih/color v1.16.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect github.com/go-errors/errors v1.5.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
github.com/golang/snappy v0.0.2 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.11.4 // indirect github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect github.com/klauspost/pgzip v1.2.6 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/nwaples/rardecode v1.1.0 // indirect github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/ulikunitz/xz v0.5.9 // indirect github.com/ulikunitz/xz v0.5.11 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.3.4 // indirect go.etcd.io/bbolt v1.3.8 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.16.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@ -1,60 +1,14 @@
cloud.google.com/go v0.26.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/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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
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/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
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/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
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/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
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=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
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/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863 h1:BRrxwOZBolJN4gIwvZMJY1tzqBvQgpaZiQRuIDD40jM=
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac=
github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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 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=
@ -80,14 +34,10 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU= github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
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/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@ -95,107 +45,58 @@ github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54= github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I=
github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
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/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
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/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
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/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -208,40 +109,44 @@ github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tp
github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ= github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI=
github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
@ -253,349 +158,75 @@ github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoi
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg= go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
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/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
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/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
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-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/lint v0.0.0-20201208152925-83fdc39ff7b5/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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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-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-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-20190501004415-9ce7a6920f09/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-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-20190628185345-da137c7871d7/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-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/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-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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/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/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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-20181221193216-37e7f081c4d4/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/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/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-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-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-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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/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-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-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-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
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/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-20180917221912-90fa682c2a6e/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-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-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
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.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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/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-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
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/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@ -603,13 +234,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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=
honnef.co/go/tools v0.0.1-2020.1.4/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=

Binary file not shown.

View File

@ -33,7 +33,6 @@ func (d *data) Check(path string) bool {
allow = rule.Allow allow = rule.Allow
} }
} }
for _, rule := range d.user.Rules { for _, rule := range d.user.Rules {
if rule.Matches(path) { if rule.Matches(path) {
allow = rule.Allow allow = rule.Allow

View File

@ -69,6 +69,7 @@ func NewHandler(
Handler(monkey(previewHandler(imgSvc, fileCache, server.EnableThumbnails, server.ResizePreview), "/api/preview")).Methods("GET") Handler(monkey(previewHandler(imgSvc, fileCache, server.EnableThumbnails, server.ResizePreview), "/api/preview")).Methods("GET")
api.PathPrefix("/search").Handler(monkey(searchHandler, "/api/search")).Methods("GET") api.PathPrefix("/search").Handler(monkey(searchHandler, "/api/search")).Methods("GET")
public := api.PathPrefix("/public").Subrouter() public := api.PathPrefix("/public").Subrouter()
public.Handle("/publicUser", monkey(publicUserGetHandler, "")).Methods("GET")
public.PathPrefix("/dl").Handler(monkey(publicDlHandler, "/api/public/dl/")).Methods("GET") public.PathPrefix("/dl").Handler(monkey(publicDlHandler, "/api/public/dl/")).Methods("GET")
public.PathPrefix("/share").Handler(monkey(publicShareHandler, "/api/public/share/")).Methods("GET") public.PathPrefix("/share").Handler(monkey(publicShareHandler, "/api/public/share/")).Methods("GET")
return stripPrefix(server.BaseURL, r), nil return stripPrefix(server.BaseURL, r), nil

View File

@ -12,33 +12,39 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"github.com/gtsteffaniak/filebrowser/files" "github.com/gtsteffaniak/filebrowser/files"
"github.com/gtsteffaniak/filebrowser/settings"
"github.com/gtsteffaniak/filebrowser/share" "github.com/gtsteffaniak/filebrowser/share"
"github.com/gtsteffaniak/filebrowser/users" "github.com/gtsteffaniak/filebrowser/users"
) )
var withHashFile = func(fn handleFunc) handleFunc { var withHashFile = func(fn handleFunc) handleFunc {
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
id, ifPath := ifPathWithName(r) id, path := ifPathWithName(r)
link, err := d.store.Share.GetByHash(id) link, err := d.store.Share.GetByHash(id)
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err
} }
if link.Hash != "" {
status, err := authenticateShareRequest(r, link) status, err := authenticateShareRequest(r, link)
if status != 0 || err != nil { if status != 0 || err != nil {
return status, err return status, err
}
} }
d.user = &users.PublicUser
user, err := d.store.Users.Get(d.server.Root, link.UserID) if path == "/" {
if err != nil { path = link.Path
return errToStatus(err), err } else if strings.HasPrefix("/"+path, link.Path) {
path = "/" + path
} else {
path = link.Path + "/" + path
} }
sharePath := settings.Config.Server.Root + path
d.user = user lastComponent := filepath.Base(sharePath)
basePath := filepath.Dir(sharePath)
fsPath := afero.NewBasePathFs(afero.NewOsFs(), basePath)
file, err := files.FileInfoFaster(files.FileOptions{ file, err := files.FileInfoFaster(files.FileOptions{
Fs: d.user.Fs, Fs: fsPath,
Path: link.Path, Path: lastComponent,
Modify: d.user.Perm.Modify, Modify: d.user.Perm.Modify,
Expand: false, Expand: false,
ReadHeader: d.server.TypeDetectionByHeader, ReadHeader: d.server.TypeDetectionByHeader,
@ -48,64 +54,37 @@ var withHashFile = func(fn handleFunc) handleFunc {
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err
} }
// share base path
basePath := link.Path
// file relative path
filePath := ""
if file.IsDir {
basePath = filepath.Dir(basePath)
filePath = ifPath
}
// set fs root to the shared file/folder
d.user.Fs = afero.NewBasePathFs(d.user.Fs, basePath)
file, err = files.FileInfoFaster(files.FileOptions{
Fs: d.user.Fs,
Path: filePath,
Modify: d.user.Perm.Modify,
Expand: true,
Checker: d,
Token: link.Token,
})
if err != nil {
return errToStatus(err), err
}
d.raw = file d.raw = file
return fn(w, r, d) return fn(w, r, d)
} }
} }
// ref to https://github.com/filebrowser/filebrowser/pull/727
// `/api/public/dl/MEEuZK-v/file-name.txt` for old browsers to save file with correct name
func ifPathWithName(r *http.Request) (id, filePath string) { func ifPathWithName(r *http.Request) (id, filePath string) {
pathElements := strings.Split(r.URL.Path, "/") pathElements := strings.Split(r.URL.Path, "/")
// prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name` id = pathElements[0]
// len(pathElements) will be 1, and golang will panic `runtime error: index out of range` allButFirst := path.Join(pathElements[1:]...)
if len(pathElements) == 1 {
switch len(pathElements) { allButFirst = "/"
case 1:
return r.URL.Path, "/"
default:
return pathElements[0], path.Join("/", path.Join(pathElements[1:]...))
} }
return id, allButFirst
} }
var publicShareHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { var publicShareHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
file := d.raw.(*files.FileInfo) file := d.raw.(*files.FileInfo)
file.Path = strings.TrimPrefix(file.Path, settings.Config.Server.Root)
if file.IsDir { if file.IsDir {
file.Listing.Sorting = users.Sorting{By: "name", Asc: false}
return renderJSON(w, r, file) return renderJSON(w, r, file)
} }
return renderJSON(w, r, file) return renderJSON(w, r, file)
}) })
var publicUserGetHandler = func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
// Call the actual handler logic here (e.g., renderJSON, etc.)
// You may need to replace `fn` with the actual handler logic.
return renderJSON(w, r, users.PublicUser)
}
var publicDlHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { var publicDlHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
file := d.raw.(*files.FileInfo) file := d.raw.(*files.FileInfo)
if !file.IsDir { if !file.IsDir {
@ -138,7 +117,6 @@ func authenticateShareRequest(r *http.Request, l *share.Link) (int, error) {
} }
return 0, err return 0, err
} }
return 0, nil return 0, nil
} }

View File

@ -26,7 +26,7 @@ func TestPublicShareHandlerAuthentication(t *testing.T) {
expectedStatusCode int expectedStatusCode int
}{ }{
"Public share, no auth required": { "Public share, no auth required": {
share: &share.Link{Hash: "h", UserID: 1}, share: &share.Link{Hash: "h"},
req: newHTTPRequest(t), req: newHTTPRequest(t),
expectedStatusCode: 200, expectedStatusCode: 200,
}, },
@ -82,9 +82,6 @@ func TestPublicShareHandlerAuthentication(t *testing.T) {
if err := storage.Share.Save(tc.share); err != nil { if err := storage.Share.Save(tc.share); err != nil {
t.Fatalf("failed to save share: %v", err) t.Fatalf("failed to save share: %v", err)
} }
if err := storage.Users.Save(&users.User{Username: "username", Password: "pw"}); err != nil {
t.Fatalf("failed to save user: %v", err)
}
if err := storage.Settings.Save(&settings.Settings{ if err := storage.Settings.Save(&settings.Settings{
Auth: settings.Auth{ Auth: settings.Auth{
Key: []byte("key"), Key: []byte("key"),
@ -100,7 +97,6 @@ func TestPublicShareHandlerAuthentication(t *testing.T) {
recorder := httptest.NewRecorder() recorder := httptest.NewRecorder()
handler := handle(handler, "", storage, &settings.Server{}) handler := handle(handler, "", storage, &settings.Server{})
handler.ServeHTTP(recorder, tc.req) handler.ServeHTTP(recorder, tc.req)
result := recorder.Result() result := recorder.Result()
defer result.Body.Close() defer result.Body.Close()

View File

@ -92,7 +92,6 @@ var rawHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data)
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err
} }
if files.IsNamedPipe(file.Mode) { if files.IsNamedPipe(file.Mode) {
setContentDisposition(w, r, file) setContentDisposition(w, r, file)
return 0, nil return 0, nil
@ -109,7 +108,6 @@ func addFile(ar archiver.Writer, d *data, path, commonPath string) error {
if !d.Check(path) { if !d.Check(path) {
return nil return nil
} }
info, err := d.user.Fs.Stat(path) info, err := d.user.Fs.Stat(path)
if err != nil { if err != nil {
return err return err

View File

@ -27,7 +27,7 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
Expand: true, Expand: true,
ReadHeader: d.server.TypeDetectionByHeader, ReadHeader: d.server.TypeDetectionByHeader,
Checker: d, Checker: d,
Content: true, Content: r.URL.Query().Get("content") == "true",
}) })
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err

View File

@ -22,7 +22,6 @@ func withPermShare(fn handleFunc) handleFunc {
if !d.user.Perm.Share { if !d.user.Perm.Share {
return http.StatusForbidden, nil return http.StatusForbidden, nil
} }
return fn(w, r, d) return fn(w, r, d)
}) })
} }
@ -51,7 +50,6 @@ var shareListHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
} }
return s[i].Expire < s[j].Expire return s[i].Expire < s[j].Expire
}) })
return renderJSON(w, r, s) return renderJSON(w, r, s)
}) })
@ -77,10 +75,15 @@ var shareDeleteHandler = withPermShare(func(w http.ResponseWriter, r *http.Reque
} }
err := d.store.Share.Delete(hash) err := d.store.Share.Delete(hash)
if err != nil {
return errToStatus(err), err
}
return errToStatus(err), err return errToStatus(err), err
}) })
var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
var s *share.Link var s *share.Link
var body share.CreateBody var body share.CreateBody
if r.Body != nil { if r.Body != nil {
@ -126,7 +129,7 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
if err != nil { if err != nil {
return status, err return status, err
} }
stringHash := ""
var token string var token string
if len(hash) > 0 { if len(hash) > 0 {
tokenBuffer := make([]byte, 24) //nolint:gomnd tokenBuffer := make([]byte, 24) //nolint:gomnd
@ -134,14 +137,14 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
token = base64.URLEncoding.EncodeToString(tokenBuffer) token = base64.URLEncoding.EncodeToString(tokenBuffer)
stringHash = string(hash)
} }
s = &share.Link{ s = &share.Link{
Path: r.URL.Path, Path: strings.TrimSuffix(r.URL.Path, "/"),
Hash: str, Hash: str,
Expire: expire, Expire: expire,
UserID: d.user.ID, UserID: d.user.ID,
PasswordHash: string(hash), PasswordHash: stringHash,
Token: token, Token: token,
} }
@ -153,6 +156,7 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
}) })
func getSharePasswordHash(body share.CreateBody) (data []byte, statuscode int, err error) { func getSharePasswordHash(body share.CreateBody) (data []byte, statuscode int, err error) {
if body.Password == "" { if body.Password == "" {
return nil, 0, nil return nil, 0, nil
} }

View File

@ -62,7 +62,6 @@ func withSelfOrAdmin(fn handleFunc) handleFunc {
if err != nil { if err != nil {
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
if d.user.ID != id && !d.user.Perm.Admin { if d.user.ID != id && !d.user.Perm.Admin {
return http.StatusForbidden, nil return http.StatusForbidden, nil
} }

View File

@ -13,7 +13,6 @@ import (
func renderJSON(w http.ResponseWriter, _ *http.Request, data interface{}) (int, error) { func renderJSON(w http.ResponseWriter, _ *http.Request, data interface{}) (int, error) {
marsh, err := json.Marshal(data) marsh, err := json.Marshal(data)
if err != nil { if err != nil {
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }

View File

@ -17,6 +17,7 @@ type Rule struct {
Allow bool `json:"allow"` Allow bool `json:"allow"`
Path string `json:"path"` Path string `json:"path"`
Regexp *Regexp `json:"regexp"` Regexp *Regexp `json:"regexp"`
Id string `json:"id"`
} }
// MatchHidden matches paths with a basename // MatchHidden matches paths with a basename

View File

@ -101,18 +101,18 @@ func (r *Runner) exec(raw, evt, path, dst string, user *users.User) error {
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
if !blocking { if !blocking {
log.Printf("[INFO] Nonblocking Command: \"%s\"", strings.Join(command, " ")) log.Printf("Nonblocking Command: \"%s\"", strings.Join(command, " "))
defer func() { defer func() {
go func() { go func() {
err := cmd.Wait() err := cmd.Wait()
if err != nil { if err != nil {
log.Printf("[INFO] Nonblocking Command \"%s\" failed: %s", strings.Join(command, " "), err) log.Printf("Nonblocking Command \"%s\" failed: %s", strings.Join(command, " "), err)
} }
}() }()
}() }()
return cmd.Start() return cmd.Start()
} }
log.Printf("[INFO] Blocking Command: \"%s\"", strings.Join(command, " ")) log.Printf("Blocking Command: \"%s\"", strings.Join(command, " "))
return cmd.Run() return cmd.Run()
} }

View File

@ -52,7 +52,7 @@ func setDefaults() Settings {
ResizePreview: false, ResizePreview: false,
EnableExec: false, EnableExec: false,
IndexingInterval: 5, IndexingInterval: 5,
Port: 8080, Port: 80,
NumImageProcessors: 4, NumImageProcessors: 4,
BaseURL: "", BaseURL: "",
Database: "database.db", Database: "database.db",

View File

@ -7,7 +7,7 @@ server:
enableThumbnails: false enableThumbnails: false
resizePreview: true resizePreview: true
typeDetectionByHeader: true typeDetectionByHeader: true
port: 8080 port: 80
baseURL: "/" baseURL: "/"
address: "" address: ""
log: "stdout" log: "stdout"

View File

@ -20,7 +20,7 @@ func (s settingsBackend) Save(set *settings.Settings) error {
func (s settingsBackend) GetServer() (*settings.Server, error) { func (s settingsBackend) GetServer() (*settings.Server, error) {
server := &settings.Server{ server := &settings.Server{
Port: 8080, Port: 80,
NumImageProcessors: 1, NumImageProcessors: 1,
} }
return server, get(s.db, "server", server) return server, get(s.db, "server", server)

View File

@ -45,11 +45,9 @@ func (st usersBackend) Gets() ([]*users.User, error) {
if err == storm.ErrNotFound { if err == storm.ErrNotFound {
return nil, errors.ErrNotExist return nil, errors.ErrNotExist
} }
if err != nil { if err != nil {
return allUsers, err return allUsers, err
} }
return allUsers, err return allUsers, err
} }

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/gtsteffaniak/filebrowser/errors" "github.com/gtsteffaniak/filebrowser/errors"
"github.com/gtsteffaniak/filebrowser/rules"
) )
// StorageBackend is the interface to implement for a users storage. // StorageBackend is the interface to implement for a users storage.
@ -18,6 +19,7 @@ type StorageBackend interface {
DeleteByUsername(string) error DeleteByUsername(string) error
} }
// Store is an interface for user storage.
type Store interface { type Store interface {
Get(baseScope string, id interface{}) (user *User, err error) Get(baseScope string, id interface{}) (user *User, err error)
Gets(baseScope string) ([]*User, error) Gets(baseScope string) ([]*User, error)
@ -25,6 +27,8 @@ type Store interface {
Save(user *User) error Save(user *User) error
Delete(id interface{}) error Delete(id interface{}) error
LastUpdate(id uint) int64 LastUpdate(id uint) int64
AddRule(username string, rule rules.Rule) error
DeleteRule(username string, ruleID string) error
} }
// Storage is a users storage. // Storage is a users storage.
@ -53,7 +57,7 @@ func (s *Storage) Get(baseScope string, id interface{}) (user *User, err error)
if err := user.Clean(baseScope); err != nil { if err := user.Clean(baseScope); err != nil {
return nil, err return nil, err
} }
return return user, err
} }
// Gets gets a list of all users. // Gets gets a list of all users.
@ -62,7 +66,6 @@ func (s *Storage) Gets(baseScope string) ([]*User, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, user := range users { for _, user := range users {
if err := user.Clean(baseScope); err != nil { //nolint:govet if err := user.Clean(baseScope); err != nil { //nolint:govet
return nil, err return nil, err
@ -90,6 +93,48 @@ func (s *Storage) Update(user *User, fields ...string) error {
return nil return nil
} }
// AddRule adds a rule to the user's rules list and updates the user in the database.
func (s *Storage) AddRule(userID string, rule rules.Rule) error {
user, err := s.Get("", userID)
if err != nil {
return err
}
user.Rules = append(user.Rules, rule)
err = s.Update(user, "Rules")
if err != nil {
return err
}
return nil
}
// DeleteRule deletes a rule specified by ID from the user's rules list and updates the user in the database.
func (s *Storage) DeleteRule(userID string, ruleID string) error {
user, err := s.Get("", userID)
if err != nil {
return err
}
// Find and remove the rule with the specified ID
var updatedRules []rules.Rule
for _, r := range user.Rules {
if r.Id != ruleID {
updatedRules = append(updatedRules, r)
}
}
user.Rules = updatedRules
err = s.Update(user, "Rules")
if err != nil {
return err
}
return nil
}
// Save saves the user in a storage. // Save saves the user in a storage.
func (s *Storage) Save(user *User) error { func (s *Storage) Save(user *User) error {
log.Println("Saving new user:", user.Username) log.Println("Saving new user:", user.Username)

View File

@ -47,6 +47,24 @@ type User struct {
DateFormat bool `json:"dateFormat"` DateFormat bool `json:"dateFormat"`
} }
var PublicUser = User{
Username: "publicUser", // temp user not registered
Password: "publicUser", // temp user not registered
Scope: "./",
ViewMode: "normal",
LockPassword: true,
Fs: afero.NewMemMapFs(),
Perm: Permissions{
Create: false,
Rename: false,
Modify: false,
Delete: false,
Share: true,
Download: true,
Admin: false,
},
}
// GetRules implements rules.Provider. // GetRules implements rules.Provider.
func (u *User) GetRules() []rules.Rule { func (u *User) GetRules() []rules.Rule {
return u.Rules return u.Rules

View File

@ -2,7 +2,7 @@ package version
var ( var (
// Version is the current File Browser version. // Version is the current File Browser version.
Version = "(0.2.3)" Version = "(0.2.4)"
// CommitSHA is the commmit sha. // CommitSHA is the commmit sha.
CommitSHA = "(unknown)" CommitSHA = "(unknown)"
) )

View File

@ -18,7 +18,7 @@ server:
enableThumbnails: false enableThumbnails: false
resizePreview: true resizePreview: true
typeDetectionByHeader: true typeDetectionByHeader: true
port: 8080 port: 80
baseURL: "/" baseURL: "/"
address: "" address: ""
log: "stdout" log: "stdout"
@ -74,7 +74,7 @@ server:
enableThumbnails: true enableThumbnails: true
enableExec: false enableExec: false
indexingInterval: 5 indexingInterval: 5
port: 8080 port: 80
numImageProcessors: 4 numImageProcessors: 4
baseURL: "" baseURL: ""
database: database.db database: database.db
@ -127,7 +127,7 @@ userDefaults:
- `typeDetectionByHeader`: This boolean value determines whether type detection is based on headers. - `typeDetectionByHeader`: This boolean value determines whether type detection is based on headers.
- `port`: This is the port number on which the server is running. Default: `8080` - `port`: This is the port number on which the server is running. Default: `80`
- `baseURL`: This is the base URL for the server. Default: `""` - `baseURL`: This is the base URL for the server. Default: `""`

47
frontend/original.json Normal file
View File

@ -0,0 +1,47 @@
{
"name": "filebrowser-frontend",
"version": "2.0.0",
"private": true,
"scripts": {
// vue 3 changes needed
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"fix": "npx vue-cli-service lint",
"watch": "vue-cli-service build --watch",
"lint": "eslint --ext .vue,.js src/",
"lint:fix": "eslint --ext .vue,.js --fix src/",
"format": "prettier --write ."
},
"dependencies": {
"ace-builds": "^1.24.2",
"clipboard": "^2.0.4",
"css-vars-ponyfill": "^2.4.3",
"file-loader": "^6.2.0", // UNNECESSARY IN VITE
X"js-base64": "^2.5.1", // REPLACE WITH EQUIVALENT JS
"lodash.clonedeep": "^4.5.0", // TOO OLD - REPLACE WITH JS
"lodash.throttle": "^4.1.1", // TOO OLD - REPLACE WITH JS
"material-icons": "^1.10.5",
"moment": "^2.29.4", // REPLACE WITH EQUIVALENT JS
"normalize.css": "^8.0.1", // REPLACE WITH EQUIVALENT JS
"noty": "^3.2.0-beta", // REPLACE WITH EQUIVALENT JS
X"pretty-bytes": "^6.0.0", // REPLACE WITH EQUIVALENT JS
"qrcode.vue": "^1.7.0", // UPDATE TO LATEST for VUE3
"utif": "^3.1.0", // SPIKE investigate replacement
"vue": "^2.6.10", // UPDATE to vue 3
"vue-async-computed": "^3.9.0", // REPLACE WITH EQUIVALENT JS
"vue-i18n": "^8.15.3", // REMOVE
"vue-lazyload": "^1.3.3", // REMOVE
"vue-router": "^3.1.3", // UPDATE to vue 3 @vue4 https://www.npmjs.com/package/vue-router
"vue-simple-progress": "^1.1.1", // REPLACE WITH EQUIVALENT JS
"vuex": "^3.1.2", // SPIKE: HOW TO REMOVE
"vuex-router-sync": "^5.0.0", // SPIKE: HOW TO REMOVE
X"whatwg-fetch": "^3.6.2"
},
"devDependencies": {
"@vue/cli-service": "^5.0.8", // REMOVE for VUE3
"compression-webpack-plugin": "^10.0.0", // REPLACE VUE3
"eslint": "^8.51.0",
"eslint-plugin-vue": "^9.17.0",
"vue-template-compiler": "^2.6.10" // REPLACE VUE3
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,14 +16,10 @@
"clipboard": "^2.0.4", "clipboard": "^2.0.4",
"css-vars-ponyfill": "^2.4.3", "css-vars-ponyfill": "^2.4.3",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"js-base64": "^2.5.1",
"lodash.clonedeep": "^4.5.0",
"lodash.throttle": "^4.1.1",
"material-icons": "^1.10.5", "material-icons": "^1.10.5",
"moment": "^2.29.4", "moment": "^2.29.4",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"noty": "^3.2.0-beta", "noty": "^3.2.0-beta",
"pretty-bytes": "^6.0.0",
"qrcode.vue": "^1.7.0", "qrcode.vue": "^1.7.0",
"utif": "^3.1.0", "utif": "^3.1.0",
"vue": "^2.6.10", "vue": "^2.6.10",
@ -33,8 +29,7 @@
"vue-router": "^3.1.3", "vue-router": "^3.1.3",
"vue-simple-progress": "^1.1.1", "vue-simple-progress": "^1.1.1",
"vuex": "^3.1.2", "vuex": "^3.1.2",
"vuex-router-sync": "^5.0.0", "vuex-router-sync": "^5.0.0"
"whatwg-fetch": "^3.6.2"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-service": "^5.0.8", "@vue/cli-service": "^5.0.8",
@ -42,10 +37,5 @@
"eslint": "^8.51.0", "eslint": "^8.51.0",
"eslint-plugin-vue": "^9.17.0", "eslint-plugin-vue": "^9.17.0",
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
}, }
"browserslist": [
"> 1%",
"last 2 versions",
"not ie < 11"
]
} }

View File

@ -2,10 +2,10 @@ import { createURL, fetchURL, removePrefix } from "./utils";
import { baseURL } from "@/utils/constants"; import { baseURL } from "@/utils/constants";
import store from "@/store"; import store from "@/store";
export async function fetch(url) { export async function fetch(url,content=false) {
url = removePrefix(url); url = removePrefix(url);
const res = await fetchURL(`/api/resources${url}`, {}); const res = await fetchURL(`/api/resources${url}?content=${content}`, {});
let data = await res.json(); let data = await res.json();
data.url = `/files${url}`; data.url = `/files${url}`;

View File

@ -1,20 +1,24 @@
import { fetchURL, removePrefix, createURL } from "./utils"; import { removePrefix, createURL } from "./utils";
import { baseURL } from "@/utils/constants"; import { baseURL } from "@/utils/constants";
export async function fetch(url, password = "") { export async function fetchPub(url, password = "") {
url = removePrefix(url); url = removePrefix(url);
const res = await fetch(
const res = await fetchURL( `/api/public/share${url}`,
`/api/public/share${url}`, {
{ headers: {
headers: { "X-SHARE-PASSWORD": encodeURIComponent(password) }, "X-SHARE-PASSWORD": encodeURIComponent(password),
}, },
false }
); );
if (res.status != 200) {
const error = new Error("000 No connection");
error.status = res.status;
throw error;
}
let data = await res.json(); let data = await res.json();
data.url = `/share${url}`; data.url = `/share${url}`;
if (data.isDir) { if (data.isDir) {
if (!data.url.endsWith("/")) data.url += "/"; if (!data.url.endsWith("/")) data.url += "/";
data.items = data.items.map((item, index) => { data.items = data.items.map((item, index) => {
@ -34,12 +38,10 @@ export async function fetch(url, password = "") {
export function download(format, hash, token, ...files) { export function download(format, hash, token, ...files) {
let url = `${baseURL}/api/public/dl/${hash}`; let url = `${baseURL}/api/public/dl/${hash}`;
if (files.length === 1) { if (files.length === 1) {
url += encodeURIComponent(files[0]) + "?"; url += encodeURIComponent(files[0]) + "?";
} else { } else {
let arg = ""; let arg = "";
for (let file of files) { for (let file of files) {
arg += encodeURIComponent(file) + ","; arg += encodeURIComponent(file) + ",";
} }
@ -60,11 +62,27 @@ export function download(format, hash, token, ...files) {
window.open(url); window.open(url);
} }
export function getPublicUser() {
return fetch("/api/public/publicUser")
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error("Error fetching public user:", error);
throw error;
});
}
export function getDownloadURL(share, inline = false) { export function getDownloadURL(share, inline = false) {
const params = { const params = {
...(inline && { inline: "true" }), ...(inline && { inline: "true" }),
...(share.token && { token: share.token }), ...(share.token && { token: share.token }),
}; };
if (share.path == undefined) {
return createURL("api/public/dl/" + share.hash + share.path, params, false); share.path = ""
}
return createURL("api/public/dl/" + share.hash + "/"+share.path, params, false);
} }

View File

@ -1,7 +1,7 @@
import { fetchURL, fetchJSON } from "./utils"; import { fetchURL, fetchJSON } from "./utils";
export async function getAll() { export async function getAll() {
return fetchJSON(`/api/users`, {}); return await fetchJSON(`/api/users`, {});
} }
export async function get(id) { export async function get(id) {

View File

@ -22,8 +22,7 @@ export async function fetchURL(url, opts, auth = true) {
}); });
} catch { } catch {
const error = new Error("000 No connection"); const error = new Error("000 No connection");
error.status = 0; error.status = res.status;
throw error; throw error;
} }

View File

@ -10,20 +10,27 @@
</component> </component>
<span v-for="(link, index) in items" :key="index"> <span v-for="(link, index) in items" :key="index">
<span class="chevron" <span class="chevron"><i class="material-icons">keyboard_arrow_right</i></span>
><i class="material-icons">keyboard_arrow_right</i></span
>
<component :is="element" :to="link.url">{{ link.name }}</component> <component :is="element" :to="link.url">{{ link.name }}</component>
</span> </span>
<action style="display: contents" v-if="showShare" icon="share" show="share" />
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex";
import Action from "@/components/header/Action";
export default { export default {
name: "breadcrumbs", name: "breadcrumbs",
components: {
Action,
},
props: ["base", "noLink"], props: ["base", "noLink"],
computed: { computed: {
...mapState(["req", "user"]),
items() { items() {
const relativePath = this.$route.path.replace(this.base, ""); const relativePath = this.$route.path.replace(this.base, "");
let parts = relativePath.split("/"); let parts = relativePath.split("/");
@ -68,6 +75,12 @@ export default {
return "router-link"; return "router-link";
}, },
showShare() {
if (this.$route.path.startsWith("/share")) {
return;
}
return this.user.perm.share;
},
}, },
}; };
</script> </script>

View File

@ -1,7 +1,12 @@
<template> <template>
<div class="button-group"> <div class="button-group">
<button v-for="(btn, index) in buttons" :key="index" :disabled="isDisabled" :class="{ active: activeButton === index && !isDisabled }" <button
@click="setActiveButton(index, btn.label)"> v-for="(btn, index) in buttons"
:key="index"
:disabled="isDisabled"
:class="{ active: activeButton === index && !isDisabled }"
@click="setActiveButton(index, btn.label)"
>
{{ btn.label }} {{ btn.label }}
</button> </button>
</div> </div>
@ -16,7 +21,7 @@ export default {
}, },
isDisabled: { isDisabled: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
initialActive: { initialActive: {
type: Number, type: Number,
@ -31,15 +36,15 @@ export default {
methods: { methods: {
setActiveButton(index, label) { setActiveButton(index, label) {
if (label == "Only Folders" && this.activeButton != index) { if (label == "Only Folders" && this.activeButton != index) {
console.log("Only Folders && this.activeButton != index") console.log("Only Folders && this.activeButton != index");
this.$emit("disableAll"); this.$emit("disableAll");
} }
if (label == "Only Folders" && this.activeButton == index) { if (label == "Only Folders" && this.activeButton == index) {
console.log("Only Folders && this.activeButton == index") console.log("Only Folders && this.activeButton == index");
this.$emit("enableAll"); this.$emit("enableAll");
} }
if (label == "Only Files" && this.activeButton != index) { if (label == "Only Files" && this.activeButton != index) {
console.log("Only Files && this.activeButton != index") console.log("Only Files && this.activeButton != index");
this.$emit("enableAll"); this.$emit("enableAll");
} }
// If the clicked button is already active, de-select it // If the clicked button is already active, de-select it
@ -72,7 +77,7 @@ export default {
<style scoped> <style scoped>
.button-group { .button-group {
margin:1em; margin: 1em;
display: flex; display: flex;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 1em; border-radius: 1em;
@ -93,7 +98,7 @@ button {
} }
/* Remove the border from the last button */ /* Remove the border from the last button */
.button-group>button:last-child { .button-group > button:last-child {
border-right: none; border-right: none;
} }
@ -102,7 +107,7 @@ button:hover {
} }
button.active { button.active {
background-color: var(--blue); background-color: var(--blue) !important;
color: #ffffff; color: #ffffff;
} }
</style> </style>

View File

@ -29,9 +29,7 @@
</div> </div>
<div v-if="isMobile && active" id="result" :class="{ hidden: !active }" ref="result"> <div v-if="isMobile && active" id="result" :class="{ hidden: !active }" ref="result">
<div id="result-list"> <div id="result-list">
<div class="button" style="width: 100%"> <div class="button" style="width: 100%">Search Context: {{ getContext }}</div>
Search Context: {{ getContext }}
</div>
<ul v-show="results.length > 0"> <ul v-show="results.length > 0">
<li <li
v-for="(s, k) in results" v-for="(s, k) in results"
@ -47,7 +45,7 @@
<i v-else-if="s.archive" class="material-icons archive-icons"> archive </i> <i v-else-if="s.archive" class="material-icons archive-icons"> archive </i>
<i v-else class="material-icons file-icons"> insert_drive_file </i> <i v-else class="material-icons file-icons"> insert_drive_file </i>
<span class="text-container"> <span class="text-container">
{{ basePath(s.path,s.dir) }}<b>{{ baseName(s.path) }}</b> {{ basePath(s.path, s.dir) }}<b>{{ baseName(s.path) }}</b>
</span> </span>
</router-link> </router-link>
</li> </li>
@ -178,7 +176,7 @@
<i v-else-if="s.archive" class="material-icons archive-icons"> archive </i> <i v-else-if="s.archive" class="material-icons archive-icons"> archive </i>
<i v-else class="material-icons file-icons"> insert_drive_file </i> <i v-else class="material-icons file-icons"> insert_drive_file </i>
<span class="text-container"> <span class="text-container">
{{ basePath(s.path,s.dir) }}<b>{{ baseName(s.path) }}</b> {{ basePath(s.path, s.dir) }}<b>{{ baseName(s.path) }}</b>
</span> </span>
</router-link> </router-link>
</li> </li>
@ -572,9 +570,9 @@ export default {
resultList.classList.add("active"); resultList.classList.add("active");
}, 100); }, 100);
}, },
show(val, old) { currentPrompt(val, old) {
this.active = val === "search"; this.active = val?.prompt === "search";
if (old === "search" && !this.active) { if (old?.prompt === "search" && !this.active) {
if (this.reload) { if (this.reload) {
this.setReload(true); this.setReload(true);
} }
@ -599,10 +597,15 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(["user", "show"]), ...mapState(["user"]),
...mapGetters(["isListing"]), ...mapGetters(["isListing", "currentPrompt", "currentPromptName"]),
showOverlay: function () {
return this.currentPrompt !== null && this.currentPrompt.prompt !== "more";
},
isDarkMode() { isDarkMode() {
return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode") ? this.user.darkMode : darkMode; return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode")
? this.user.darkMode
: darkMode;
}, },
showBoxes() { showBoxes() {
return this.searchTypes == ""; return this.searchTypes == "";
@ -632,11 +635,11 @@ export default {
return this.showHelp; return this.showHelp;
}, },
getContext() { getContext() {
let path = this.$route.path let path = this.$route.path;
path = path.slice(1); path = path.slice(1);
path = "./" + path.substring(path.indexOf("/") + 1); path = "./" + path.substring(path.indexOf("/") + 1);
path = path.replace(/\/+$/, "") + "/"; path = path.replace(/\/+$/, "") + "/";
return path return path;
}, },
}, },
mounted() { mounted() {
@ -644,6 +647,7 @@ export default {
this.handleResize(); // Call this once to set the initial width this.handleResize(); // Call this once to set the initial width
}, },
methods: { methods: {
...mapMutations(["showHover", "closeHovers", "setReload"]),
handleResize() { handleResize() {
this.width = window.innerWidth; this.width = window.innerWidth;
}, },
@ -652,15 +656,14 @@ export default {
await this.$nextTick(); await this.$nextTick();
setTimeout(() => this.$router.push(url), 0); setTimeout(() => this.$router.push(url), 0);
}, },
basePath(str,isDir) { basePath(str, isDir) {
let parts = str.replace(/(\/$|^\/)/, "").split("/"); let parts = str.replace(/(\/$|^\/)/, "").split("/");
if (parts.length <= 1) { if (parts.length <= 1) {
if (isDir) { if (isDir) {
return "/" return "/";
} }
return ""; return "";
} }
console.log("basePath",parts)
parts.pop(); parts.pop();
parts = parts.join("/") + "/"; parts = parts.join("/") + "/";
if (isDir) { if (isDir) {
@ -672,9 +675,8 @@ export default {
let parts = str.replace(/(\/$|^\/)/, "").split("/"); let parts = str.replace(/(\/$|^\/)/, "").split("/");
return parts.pop(); return parts.pop();
}, },
...mapMutations(["showHover", "closeHovers", "setReload"]),
open() { open() {
this.showHover("search"); this.$store.commit("showHover", "search");
}, },
close(event) { close(event) {
event.stopPropagation(); event.stopPropagation();

View File

@ -118,7 +118,7 @@ import {
} from "@/utils/constants"; } from "@/utils/constants";
import { files as api } from "@/api"; import { files as api } from "@/api";
import ProgressBar from "vue-simple-progress"; import ProgressBar from "vue-simple-progress";
import prettyBytes from "pretty-bytes"; import { getHumanReadableFilesize } from "@/utils/filesizes";
import { darkMode } from "@/utils/constants"; import { darkMode } from "@/utils/constants";
export default { export default {
@ -129,11 +129,13 @@ export default {
computed: { computed: {
...mapState(["user"]), ...mapState(["user"]),
isDarkMode() { isDarkMode() {
return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode") ? this.user.darkMode : darkMode; return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode")
? this.user.darkMode
: darkMode;
}, },
...mapGetters(["isLogged"]), ...mapGetters(["isLogged", "currentPrompt"]),
active() { active() {
return this.$store.state.show === "sidebar"; return this.currentPrompt?.prompt === "sidebar";
}, },
signup: () => signup, signup: () => signup,
version: () => version, version: () => version,
@ -154,8 +156,8 @@ export default {
try { try {
let usage = await api.usage(path); let usage = await api.usage(path);
usageStats = { usageStats = {
used: prettyBytes(usage.used / 1024, { binary: true }), used: getHumanReadableFilesize(usage.used / 1024),
total: prettyBytes(usage.total / 1024, { binary: true }), total: getHumanReadableFilesize(usage.total / 1024),
usedPercentage: Math.round((usage.used / usage.total) * 100), usedPercentage: Math.round((usage.used / usage.total) * 100),
}; };
} catch (error) { } catch (error) {

View File

@ -19,7 +19,7 @@
</div> </div>
</template> </template>
<script> <script>
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
import UTIF from "utif"; import UTIF from "utif";
export default { export default {

View File

@ -15,7 +15,6 @@ export default {
if (this.show) { if (this.show) {
this.$store.commit("showHover", this.show); this.$store.commit("showHover", this.show);
} }
this.$emit("action"); this.$emit("action");
}, },
}, },

View File

@ -1,31 +0,0 @@
<template>
<header>
<slot />
</header>
</template>
<script>
import { logoURL } from "@/utils/constants";
export default {
name: "header-bar",
props: ["showLogo", "showMenu"],
data: function () {
return {
logoURL,
};
},
methods: {
toggleSidebar() {
if ( this.$store.state.show == "sidebar" ) {
this.$store.commit("closeHovers");
} else {
this.$store.commit("showHover", "sidebar");
}
},
},
};
</script>
<style></style>

View File

@ -6,33 +6,49 @@
<div class="card-content"> <div class="card-content">
<p>{{ $t("prompts.copyMessage") }}</p> <p>{{ $t("prompts.copyMessage") }}</p>
<file-list @update:selected="(val) => (dest = val)"></file-list> <file-list ref="fileList" @update:selected="(val) => (dest = val)"> </file-list>
</div> </div>
<div class="card-action"> <div
<button class="card-action"
class="button button--flat button--grey" style="display: flex; align-items: center; justify-content: space-between"
@click="$store.commit('closeHovers')" >
:aria-label="$t('buttons.cancel')" <template v-if="user.perm.create">
:title="$t('buttons.cancel')" <button
> class="button button--flat"
{{ $t("buttons.cancel") }} @click="$refs.fileList.createDir()"
</button> :aria-label="$t('sidebar.newFolder')"
<button :title="$t('sidebar.newFolder')"
class="button button--flat" style="justify-self: left"
@click="copy" >
:aria-label="$t('buttons.copy')" <span>{{ $t("sidebar.newFolder") }}</span>
:title="$t('buttons.copy')" </button>
> </template>
{{ $t("buttons.copy") }} <div>
</button> <button
class="button button--flat button--grey"
@click="$store.commit('closeHovers')"
:aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')"
>
{{ $t("buttons.cancel") }}
</button>
<button
class="button button--flat"
@click="copy"
:aria-label="$t('buttons.copy')"
:title="$t('buttons.copy')"
>
{{ $t("buttons.copy") }}
</button>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import FileList from "./FileList"; import FileList from "./FileList.vue";
import { files as api } from "@/api"; import { files as api } from "@/api";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";
@ -46,7 +62,7 @@ export default {
dest: null, dest: null,
}; };
}, },
computed: mapState(["req", "selected"]), computed: mapState(["req", "selected", "user"]),
methods: { methods: {
copy: async function (event) { copy: async function (event) {
event.preventDefault(); event.preventDefault();

View File

@ -37,8 +37,8 @@ import buttons from "@/utils/buttons";
export default { export default {
name: "delete", name: "delete",
computed: { computed: {
...mapGetters(["isListing", "selectedCount"]), ...mapGetters(["isListing", "selectedCount", "currentPrompt"]),
...mapState(["req", "selected", "showConfirm"]), ...mapState(["req", "selected"]),
}, },
methods: { methods: {
...mapMutations(["closeHovers"]), ...mapMutations(["closeHovers"]),
@ -50,7 +50,7 @@ export default {
await api.remove(this.$route.path); await api.remove(this.$route.path);
buttons.success("delete"); buttons.success("delete");
this.showConfirm(); this.currentPrompt?.confirm();
this.closeHovers(); this.closeHovers();
return; return;
} }

View File

@ -11,7 +11,7 @@
v-for="(ext, format) in formats" v-for="(ext, format) in formats"
:key="format" :key="format"
class="button button--block" class="button button--block"
@click="showConfirm(format)" @click="currentPrompt.confirm(format)"
v-focus v-focus
> >
{{ ext }} {{ ext }}
@ -21,7 +21,7 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters } from "vuex";
export default { export default {
name: "download", name: "download",
@ -38,6 +38,7 @@ export default {
}, },
}; };
}, },
computed: mapState(["showConfirm"]), computed: {
}; ...mapGetters(["currentPrompt"]),
},};
</script> </script>

View File

@ -1,5 +1,6 @@
<template> <template>
<div> <div>
<div class="searchContext">Path: {{ nav }}</div>
<ul class="file-list"> <ul class="file-list">
<li <li
@click="itemClick" @click="itemClick"
@ -16,11 +17,6 @@
{{ item.name }} {{ item.name }}
</li> </li>
</ul> </ul>
<p>
{{ $t("prompts.currentlyNavigating") }} <code>{{ nav }}</code
>.
</p>
</div> </div>
</template> </template>
@ -133,6 +129,17 @@ export default {
this.selected = event.currentTarget.dataset.url; this.selected = event.currentTarget.dataset.url;
this.$emit("update:selected", this.selected); this.$emit("update:selected", this.selected);
}, },
createDir: async function () {
this.$store.commit("showHover", {
prompt: "newDir",
action: null,
confirm: null,
props: {
redirect: false,
base: this.current === this.$route.path ? null : this.current,
},
});
},
}, },
}; };
</script> </script>

View File

@ -5,34 +5,50 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<file-list @update:selected="(val) => (dest = val)"></file-list> <file-list ref="fileList" @update:selected="(val) => (dest = val)"> </file-list>
</div> </div>
<div class="card-action"> <div
<button class="card-action"
class="button button--flat button--grey" style="display: flex; align-items: center; justify-content: space-between"
@click="$store.commit('closeHovers')" >
:aria-label="$t('buttons.cancel')" <template v-if="user.perm.create">
:title="$t('buttons.cancel')" <button
> class="button button--flat"
{{ $t("buttons.cancel") }} @click="$refs.fileList.createDir()"
</button> :aria-label="$t('sidebar.newFolder')"
<button :title="$t('sidebar.newFolder')"
class="button button--flat" style="justify-self: left"
@click="move" >
:disabled="$route.path === dest" <span>{{ $t("sidebar.newFolder") }}</span>
:aria-label="$t('buttons.move')" </button>
:title="$t('buttons.move')" </template>
> <div>
{{ $t("buttons.move") }} <button
</button> class="button button--flat button--grey"
@click="$store.commit('closeHovers')"
:aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')"
>
{{ $t("buttons.cancel") }}
</button>
<button
class="button button--flat"
@click="move"
:disabled="$route.path === dest"
:aria-label="$t('buttons.move')"
:title="$t('buttons.move')"
>
{{ $t("buttons.move") }}
</button>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import FileList from "./FileList"; import FileList from "./FileList.vue";
import { files as api } from "@/api"; import { files as api } from "@/api";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";
@ -46,7 +62,7 @@ export default {
dest: null, dest: null,
}; };
}, },
computed: mapState(["req", "selected"]), computed: mapState(["req", "selected", "user"]),
methods: { methods: {
move: async function (event) { move: async function (event) {
event.preventDefault(); event.preventDefault();

View File

@ -43,6 +43,16 @@ import url from "@/utils/url";
export default { export default {
name: "new-dir", name: "new-dir",
props: {
redirect: {
type: Boolean,
default: true,
},
base: {
type: [String, null],
default: null,
},
},
data: function () { data: function () {
return { return {
name: "", name: "",
@ -57,7 +67,10 @@ export default {
if (this.new === "") return; if (this.new === "") return;
// Build the path of the new directory. // Build the path of the new directory.
let uri = this.isFiles ? this.$route.path + "/" : "/"; let uri;
if (this.base) uri = this.base;
else if (this.isFiles) uri = this.$route.path + "/";
else uri = "/";
if (!this.isListing) { if (!this.isListing) {
uri = url.removeLastDir(uri) + "/"; uri = url.removeLastDir(uri) + "/";
@ -68,7 +81,12 @@ export default {
try { try {
await api.post(uri); await api.post(uri);
this.$router.push({ path: uri }); if (this.redirect) {
this.$router.push({ path: uri });
} else if (!this.base) {
const res = await api.fetch(url.removeLastDir(uri) + "/");
this.$store.commit("updateRequest", res);
}
} catch (e) { } catch (e) {
this.$showError(e); this.$showError(e);
} }

View File

@ -1,26 +1,32 @@
<template> <template>
<div> <div>
<component ref="currentComponent" :is="currentComponent"></component> <component
<div v-if="showOverlay" @click="resetPrompts" class="overlay"></div> v-if="showOverlay"
:ref="currentPromptName"
:is="currentPromptName"
v-bind="currentPrompt.props"
>
</component>
</div> </div>
</template> </template>
<script> <script>
import Help from "./Help"; import Help from "./Help.vue";
import Info from "./Info"; import Info from "./Info.vue";
import Delete from "./Delete"; import Delete from "./Delete.vue";
import Rename from "./Rename"; import Rename from "./Rename.vue";
import Download from "./Download"; import Download from "./Download.vue";
import Move from "./Move"; import Move from "./Move.vue";
import Copy from "./Copy"; import Copy from "./Copy.vue";
import NewFile from "./NewFile"; import NewFile from "./NewFile.vue";
import NewDir from "./NewDir"; import NewDir from "./NewDir.vue";
import Replace from "./Replace"; import Replace from "./Replace.vue";
import ReplaceRename from "./ReplaceRename"; import ReplaceRename from "./ReplaceRename.vue";
import Share from "./Share"; import Share from "./Share.vue";
import Upload from "./Upload"; import Upload from "./Upload.vue";
import ShareDelete from "./ShareDelete"; import ShareDelete from "./ShareDelete.vue";
import { mapState } from "vuex"; import Sidebar from "../Sidebar.vue";
import { mapGetters, mapState } from "vuex";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
export default { export default {
@ -40,6 +46,7 @@ export default {
ReplaceRename, ReplaceRename,
Upload, Upload,
ShareDelete, ShareDelete,
Sidebar,
}, },
data: function () { data: function () {
return { return {
@ -52,7 +59,7 @@ export default {
}, },
created() { created() {
window.addEventListener("keydown", (event) => { window.addEventListener("keydown", (event) => {
if (this.show == null) return; if (this.currentPrompt == null) return;
let prompt = this.$refs.currentComponent; let prompt = this.$refs.currentComponent;
@ -64,7 +71,7 @@ export default {
// Enter // Enter
if (event.keyCode == 13) { if (event.keyCode == 13) {
switch (this.show) { switch (this.currentPrompt.prompt) {
case "delete": case "delete":
prompt.submit(); prompt.submit();
break; break;
@ -82,38 +89,12 @@ export default {
}); });
}, },
computed: { computed: {
...mapState(["show", "plugins"]), ...mapState(["plugins"]),
currentComponent: function () { ...mapGetters(["currentPrompt", "currentPromptName"]),
const matched =
[
"info",
"help",
"delete",
"rename",
"move",
"copy",
"newFile",
"newDir",
"download",
"replace",
"replace-rename",
"share",
"upload",
"share-delete",
].indexOf(this.show) >= 0;
return (matched && this.show) || null;
},
showOverlay: function () { showOverlay: function () {
return ( return this.currentPrompt !== null && this.currentPrompt.prompt !== "more";
this.show !== null && this.show !== "more"
);
},
},
methods: {
resetPrompts() {
this.$store.commit("closeHovers");
}, },
}, },
methods: {},
}; };
</script> </script>

View File

@ -11,7 +11,7 @@
<div class="card-action"> <div class="card-action">
<button <button
class="button button--flat button--grey" class="button button--flat button--grey"
@click="$store.commit('closeHovers')" @click="currentPrompt.action"
:aria-label="$t('buttons.cancel')" :aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')" :title="$t('buttons.cancel')"
> >
@ -19,7 +19,7 @@
</button> </button>
<button <button
class="button button--flat button--red" class="button button--flat button--red"
@click="showConfirm" @click="currentPrompt.confirm"
:aria-label="$t('buttons.replace')" :aria-label="$t('buttons.replace')"
:title="$t('buttons.replace')" :title="$t('buttons.replace')"
> >
@ -30,10 +30,10 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters } from "vuex";
export default { export default {
name: "replace", name: "replace",
computed: mapState(["showConfirm"]), computed: mapGetters(["currentPrompt"]),
}; };
</script> </script>

View File

@ -11,7 +11,7 @@
<div class="card-action"> <div class="card-action">
<button <button
class="button button--flat button--grey" class="button button--flat button--grey"
@click="$store.commit('closeHovers')" @click="(event) => currentPrompt.confirm(event, 'rename')"
:aria-label="$t('buttons.cancel')" :aria-label="$t('buttons.cancel')"
:title="$t('buttons.cancel')" :title="$t('buttons.cancel')"
> >
@ -19,7 +19,7 @@
</button> </button>
<button <button
class="button button--flat button--blue" class="button button--flat button--blue"
@click="(event) => showConfirm(event, 'rename')" @click="(event) => currentPrompt.confirm(event, 'overwrite')"
:aria-label="$t('buttons.rename')" :aria-label="$t('buttons.rename')"
:title="$t('buttons.rename')" :title="$t('buttons.rename')"
> >
@ -38,10 +38,9 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters } from "vuex";
export default { export default {
name: "replace-rename", name: "replace-rename",
computed: mapState(["showConfirm"]), computed: mapGetters(["currentPrompt"]),
}; };
</script> </script>

View File

@ -3,6 +3,7 @@
<div class="card-title"> <div class="card-title">
<h2>{{ $t("buttons.share") }}</h2> <h2>{{ $t("buttons.share") }}</h2>
</div> </div>
<div class="searchContext">Path: {{ getContext }}</div>
<template v-if="listing"> <template v-if="listing">
<div class="card-content"> <div class="card-content">
@ -17,9 +18,7 @@
<tr v-for="link in links" :key="link.hash"> <tr v-for="link in links" :key="link.hash">
<td>{{ link.hash }}</td> <td>{{ link.hash }}</td>
<td> <td>
<template v-if="link.expire !== 0">{{ <template v-if="link.expire !== 0">{{ humanTime(link.expire) }}</template>
humanTime(link.expire)
}}</template>
<template v-else>{{ $t("permanent") }}</template> <template v-else>{{ $t("permanent") }}</template>
</td> </td>
<td class="small"> <td class="small">
@ -96,11 +95,7 @@
</select> </select>
</div> </div>
<p>{{ $t("prompts.optionalPassword") }}</p> <p>{{ $t("prompts.optionalPassword") }}</p>
<input <input class="input input--block" type="password" v-model.trim="password" />
class="input input--block"
type="password"
v-model.trim="password"
/>
</div> </div>
<div class="card-action"> <div class="card-action">
@ -145,19 +140,24 @@ export default {
}, },
computed: { computed: {
...mapState(["req", "selected", "selectedCount"]), ...mapState(["req", "selected", "selectedCount"]),
...mapGetters(["isListing"]), ...mapGetters(["isListing", "selectedCount"]),
url() { url() {
if (!this.isListing) { if (!this.isListing) {
return this.$route.path; return this.$route.path;
} }
if (this.selectedCount != 1) {
if (this.selectedCount === 0 || this.selectedCount > 1) { // selecting current view image
// This shouldn't happen. return this.$route.path;
return;
} }
return this.req.items[this.selected[0]].url; return this.req.items[this.selected[0]].url;
}, },
getContext() {
let path = this.$route.path.replace("/files/", "./");
if (this.selectedCount == 1) {
path = path + this.req.items[this.selected[0]].name;
}
return path;
},
}, },
async beforeMount() { async beforeMount() {
try { try {
@ -226,9 +226,7 @@ export default {
return api.getShareURL(share); return api.getShareURL(share);
}, },
hasDownloadLink() { hasDownloadLink() {
return ( return this.selected.length === 1 && !this.req.items[this.selected[0]].isDir;
this.selected.length === 1 && !this.req.items[this.selected[0]].isDir
);
}, },
buildDownloadLink(share) { buildDownloadLink(share) {
return pub_api.getDownloadURL(share); return pub_api.getDownloadURL(share);

View File

@ -25,16 +25,15 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters } from "vuex";
export default { export default {
name: "share-delete", name: "share-delete",
computed: { computed: {
...mapState(["showConfirm"]), ...mapGetters(["currentPrompt"]),
}, },
methods: { methods: {
submit: function () { submit: function () {
this.showConfirm(); this.currentPrompt?.confirm();
}, },
}, },
}; };

View File

@ -57,7 +57,7 @@
flex: 10 0 25em; flex: 10 0 25em;
} }
.share__box__items #listing.list .item { .share__box__items #listingView.list .item {
cursor: pointer; cursor: pointer;
border-left: 0; border-left: 0;
border-right: 0; border-right: 0;
@ -65,11 +65,11 @@
border-top: 1px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, 0.1);
} }
.share__box__items #listing.list .item .name { .share__box__items #listingView.list .item .name {
width: 50%; width: 50%;
} }
.share__box__items #listing.list .item .modified { .share__box__items #listingView.list .item .modified {
width: 25%; width: 25%;
} }

View File

@ -2,11 +2,10 @@
body { body {
font-family: "Roboto", sans-serif; font-family: "Roboto", sans-serif;
padding-top: 4em; padding-top: 4em;
background-color: #fafafa; background-color: #f5f5f5;
color: #333333; color: #333333;
overflow:auto; overflow:auto;
overflow:initial; overflow:initial;
} }
body::-webkit-scrollbar { body::-webkit-scrollbar {
z-index: 1000; z-index: 1000;

View File

@ -97,20 +97,20 @@
} }
/* Listing items */ /* Listing items */
.dark-mode #listing .item { .dark-mode #listingView .item {
background: var(--surfacePrimary); background: var(--surfacePrimary);
color: var(--textPrimary); color: var(--textPrimary);
border-color: var(--divider) !important; border-color: var(--divider) !important;
} }
/* Listing item modified text */ /* Listing item modified text */
.dark-mode #listing .item .modified { .dark-mode #listingView .item .modified {
color: var(--textSecondary); color: var(--textSecondary);
} }
/* Listing header and span */ /* Listing header and span */
.dark-mode #listing h2, .dark-mode #listingView h2,
.dark-mode #listing.list .header span { .dark-mode #listingView.list .header span {
color: var(--textPrimary) !important; color: var(--textPrimary) !important;
} }
@ -265,6 +265,7 @@
/* Button group button */ /* Button group button */
.dark-mode .button-group button { .dark-mode .button-group button {
color: white; color: white;
background-color:var(--background);
} }
/* Result desktop */ /* Result desktop */

View File

@ -1,32 +1,32 @@
#listing { #listingView {
--item-selected: white; --item-selected: white;
transition: all; transition: all;
animation-duration: 0.25s; animation-duration: 0.25s;
} }
body.rtl #listing { body.rtl #listingView {
margin-right: 16em; margin-right: 16em;
} }
#listing h2 { #listingView h2 {
margin: 0 0 0 0.5em; margin: 0 0 0 0.5em;
font-size: .9em; font-size: .9em;
color: rgba(0, 0, 0, 0.38); color: rgba(0, 0, 0, 0.38);
font-weight: 500; font-weight: 500;
} }
#listing .item div:last-of-type * { #listingView .item div:last-of-type * {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
#listing>div { #listingView>div {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-start; justify-content: flex-start;
} }
#listing .item { #listingView .item {
background-color: #fff; background-color: #fff;
position: relative; position: relative;
display: flex; display: flex;
@ -38,32 +38,32 @@ body.rtl #listing {
user-select: none; user-select: none;
} }
#listing .item div:last-of-type { #listingView .item div:last-of-type {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
#listing .item p { #listingView .item p {
margin: 0; margin: 0;
} }
#listing .item .size, #listingView .item .size,
#listing .item .modified { #listingView .item .modified {
font-size: 0.9em; font-size: 0.9em;
} }
#listing .item .name { #listingView .item .name {
font-weight: bold; font-weight: bold;
} }
#listing .item i { #listingView .item i {
font-size: 4em; font-size: 4em;
margin-right: 0.1em; margin-right: 0.1em;
vertical-align: bottom; vertical-align: bottom;
} }
#listing .item img { #listingView .item img {
width: 4em; width: 4em;
height: 4em; height: 4em;
object-fit: cover; object-fit: cover;
@ -88,52 +88,52 @@ body.rtl #listing {
display: block; display: block;
} }
#listing { #listingView {
padding-top: 1em; padding-top: 1em;
padding-bottom: 1em; padding-bottom: 1em;
} }
#listing.gallery .item, #listingView.gallery .item,
#listing.compact .item, #listingView.compact .item,
#listing.normal .item, #listingView.normal .item,
#listing.list .item { #listingView.list .item {
margin: .5em; margin: .5em;
padding: 0.5em; padding: 0.5em;
border-radius: 1em; border-radius: 1em;
box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px, rgba(0, 0, 0, 0.12) 0px 1px 2px; box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px, rgba(0, 0, 0, 0.12) 0px 1px 2px;
} }
#listing.gallery .item { #listingView.gallery .item {
max-width: 300px; max-width: 300px;
} }
#listing.list .item, #listingView.list .item,
#listing.compact .item { #listingView.compact .item {
max-width: 100%; max-width: 100%;
border-radius: 0em; border-radius: 0em;
} }
#listing .item:hover { #listingView .item:hover {
box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24) !important; box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24) !important;
} }
#listing .header { #listingView .header {
display: none; display: none;
} }
#listing .item div:first-of-type { #listingView .item div:first-of-type {
width: 5em; width: 5em;
} }
#listing .item div:last-of-type { #listingView .item div:last-of-type {
width: calc(100% - 5vw); width: calc(100% - 5vw);
} }
#listing.gallery .item div:first-of-type { #listingView.gallery .item div:first-of-type {
width: 100%; width: 100%;
height: 12em; height: 12em;
} }
#listing.gallery .item div:last-of-type { #listingView.gallery .item div:last-of-type {
position: absolute; position: absolute;
bottom: 0.5em; bottom: 0.5em;
padding: 1em; padding: 1em;
@ -141,37 +141,37 @@ body.rtl #listing {
text-align: center; text-align: center;
} }
#listing.gallery .item[data-type=image] div:last-of-type { #listingView.gallery .item[data-type=image] div:last-of-type {
color: white; color: white;
background: linear-gradient(#0000, #0009); background: linear-gradient(#0000, #0009);
} }
#listing.gallery .item i { #listingView.gallery .item i {
width: 100%; width: 100%;
margin-right: 0; margin-right: 0;
font-size: 8em; font-size: 8em;
text-align: center; text-align: center;
} }
#listing.gallery .item img { #listingView.gallery .item img {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 0.5em; border-radius: 0.5em;
} }
#listing.gallery .size, #listingView.gallery .size,
#listing.gallery .modified { #listingView.gallery .modified {
display: none; display: none;
} }
#listing.compact { #listingView.compact {
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
margin: 0; margin: 0;
} }
#listing.compact .item { #listingView.compact .item {
width: 100%; width: 100%;
margin: 0; margin: 0;
border: 1px solid rgba(0, 0, 0, 0.1); border: 1px solid rgba(0, 0, 0, 0.1);
@ -179,44 +179,44 @@ body.rtl #listing {
border-top: 0; border-top: 0;
} }
#listing.compact h2 { #listingView.compact h2 {
display: none; display: none;
} }
#listing.compact .item div:first-of-type { #listingView.compact .item div:first-of-type {
width: 3em; width: 3em;
} }
#listing.compact .item div:first-of-type i { #listingView.compact .item div:first-of-type i {
font-size: 2em; font-size: 2em;
} }
#listing.compact .item div:first-of-type img { #listingView.compact .item div:first-of-type img {
width: 2em; width: 2em;
height: 2em; height: 2em;
} }
#listing.compact .item div:last-of-type { #listingView.compact .item div:last-of-type {
width: calc(100% - 3em); width: calc(100% - 3em);
display: flex; display: flex;
align-items: center; align-items: center;
} }
#listing.compact .item .name { #listingView.compact .item .name {
width: 50%; width: 50%;
} }
#listing.compact .item .size { #listingView.compact .item .size {
width: 25%; width: 25%;
} }
#listing.compact .header i { #listingView.compact .header i {
font-size: 1.5em; font-size: 1.5em;
vertical-align: middle; vertical-align: middle;
margin-left: .2em; margin-left: .2em;
} }
#listing.compact .header { #listingView.compact .header {
display: flex !important; display: flex !important;
background: var(--surfacePrimary); background: var(--surfacePrimary);
z-index: 999; z-index: 999;
@ -225,56 +225,56 @@ body.rtl #listing {
border-bottom: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.1);
} }
#listing.compact .header>div:first-child { #listingView.compact .header>div:first-child {
width: 0; width: 0;
} }
#listing.compact .header .name { #listingView.compact .header .name {
margin-right: 3em; margin-right: 3em;
} }
#listing.compact .header a { #listingView.compact .header a {
color: inherit; color: inherit;
} }
#listing.compact .header>div:first-child { #listingView.compact .header>div:first-child {
width: 0; width: 0;
} }
#listing.compact .name { #listingView.compact .name {
font-weight: normal; font-weight: normal;
} }
#listing.compact .header .name { #listingView.compact .header .name {
margin-right: 3em; margin-right: 3em;
} }
#listing.compact .header span { #listingView.compact .header span {
vertical-align: middle; vertical-align: middle;
} }
#listing.compact .header i { #listingView.compact .header i {
opacity: 0; opacity: 0;
transition: .1s ease all; transition: .1s ease all;
} }
#listing.compact .header p:hover i, #listingView.compact .header p:hover i,
#listing.compact .header .active i { #listingView.compact .header .active i {
opacity: 1; opacity: 1;
} }
#listing.compact .header .active { #listingView.compact .header .active {
font-weight: bold; font-weight: bold;
} }
#listing.list { #listingView.list {
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
margin: 0; margin: 0;
} }
#listing.list .item { #listingView.list .item {
width: 100%; width: 100%;
margin: 0; margin: 0;
border: 1px solid rgba(0, 0, 0, 0.1); border: 1px solid rgba(0, 0, 0, 0.1);
@ -282,54 +282,54 @@ body.rtl #listing {
border-top: 0; border-top: 0;
} }
#listing .item[aria-selected=true] { #listingView .item[aria-selected=true] {
background: var(--blue) !important; background: var(--blue) !important;
color: var(--item-selected) !important; color: var(--item-selected) !important;
} }
#listing.list .item div:first-of-type { #listingView.list .item div:first-of-type {
width: 3em; width: 3em;
} }
#listing.list .item div:first-of-type i { #listingView.list .item div:first-of-type i {
font-size: 2em; font-size: 2em;
} }
#listing.list .item div:first-of-type img { #listingView.list .item div:first-of-type img {
width: 2em; width: 2em;
height: 2em; height: 2em;
border-radius: 0.25em; border-radius: 0.25em;
} }
#listing.list .item div:last-of-type { #listingView.list .item div:last-of-type {
width: calc(100% - 3em); width: calc(100% - 3em);
display: flex; display: flex;
align-items: center; align-items: center;
} }
#listing.list .item .name { #listingView.list .item .name {
width: 50%; width: 50%;
} }
#listing.list .item .size { #listingView.list .item .size {
width: 25%; width: 25%;
} }
#listing .header { #listingView .header {
display: none !important; display: none !important;
background-color: #ccc; background-color: #ccc;
} }
#listing.list .header i { #listingView.list .header i {
font-size: 1.5em; font-size: 1.5em;
vertical-align: middle; vertical-align: middle;
margin-left: .2em; margin-left: .2em;
} }
#listing.compact .header, #listingView.compact .header,
#listing.list .header { #listingView.list .header {
display: flex !important; display: flex !important;
background: var(--surfacePrimary); background: white;
border-top-left-radius: 1em; border-top-left-radius: 1em;
border-top-right-radius: 1em; border-top-right-radius: 1em;
z-index: 999; z-index: 999;
@ -338,60 +338,60 @@ body.rtl #listing {
border: 0; border: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.1);
} }
#listing.list .item:first-child { #listingView.list .item:first-child {
margin-top: .5em; margin-top: .5em;
border-top-left-radius: 1em; border-top-left-radius: 1em;
border-top-right-radius: 1em; border-top-right-radius: 1em;
} }
#listing.list .item:last-child { #listingView.list .item:last-child {
margin-bottom: .5em; margin-bottom: .5em;
border-bottom-left-radius: 1em; border-bottom-left-radius: 1em;
border-bottom-right-radius: 1em; border-bottom-right-radius: 1em;
} }
#listing.list .header>div:first-child { #listingView.list .header>div:first-child {
width: 0; width: 0;
} }
#listing.list .header .name { #listingView.list .header .name {
margin-right: 3em; margin-right: 3em;
} }
#listing.list .header a { #listingView.list .header a {
color: inherit; color: inherit;
} }
#listing.list .header>div:first-child { #listingView.list .header>div:first-child {
width: 0; width: 0;
} }
#listing.list .name { #listingView.list .name {
font-weight: normal; font-weight: normal;
} }
#listing.list .header .name { #listingView.list .header .name {
margin-right: 3em; margin-right: 3em;
} }
#listing.list .header span { #listingView.list .header span {
vertical-align: middle; vertical-align: middle;
} }
#listing.list .header i { #listingView.list .header i {
opacity: 0; opacity: 0;
transition: .1s ease all; transition: .1s ease all;
} }
#listing.list .header p:hover i, #listingView.list .header p:hover i,
#listing.list .header .active i { #listingView.list .header .active i {
opacity: 1; opacity: 1;
} }
#listing.list .header .active { #listingView.list .header .active {
font-weight: bold; font-weight: bold;
} }
#listing #multiple-selection { #listingView #multiple-selection {
position: fixed; position: fixed;
bottom: -4em; bottom: -4em;
left: 0; left: 0;
@ -404,11 +404,11 @@ body.rtl #listing {
transition: .2s ease bottom; transition: .2s ease bottom;
} }
#listing #multiple-selection.active { #listingView #multiple-selection.active {
bottom: 0; bottom: 0;
} }
#listing #multiple-selection p, #listingView #multiple-selection p,
#listing #multiple-selection i { #listingView #multiple-selection i {
color: var(--item-selected); color: var(--item-selected);
} }

View File

@ -7,7 +7,7 @@
} }
@media (max-width: 800px) { @media (max-width: 800px) {
#listing.list .item div:last-of-type{ #listingView.list .item div:last-of-type{
display:block; display:block;
width:100%; width:100%;
} }
@ -15,7 +15,7 @@
padding-bottom: 5em; padding-bottom: 5em;
} }
#listing.list .item .name { #listingView.list .item .name {
width: 60%; width: 60%;
} }
@ -33,13 +33,13 @@
display: none; display: none;
} }
#listing { #listingView {
margin-bottom: 5em; margin-bottom: 5em;
} }
#listing .item { #listingView .item {
width: 100% width: 100%
} }
body.rtl #listing { body.rtl #listingView {
margin-right: unset; margin-right: unset;
} }
@ -120,7 +120,7 @@
@media (max-width: 450px) { @media (max-width: 450px) {
#listing.list .item .name { #listingView.list .item .name {
width: 100%; width: 100%;
} }
} }

View File

@ -138,14 +138,9 @@ main .spinner .bounce2 {
#previewer { #previewer {
background-color: rgba(0, 0, 0, 0.9); background-color: rgba(0, 0, 0, 0.9);
padding-top: 4em;
position: fixed;
top: 0;
left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 9999; z-index: 9999;
overflow: hidden;
} }
#previewer header { #previewer header {

View File

@ -1,4 +1,3 @@
import "whatwg-fetch";
import cssVars from "css-vars-ponyfill"; import cssVars from "css-vars-ponyfill";
import { sync } from "vuex-router-sync"; import { sync } from "vuex-router-sync";
import store from "@/store"; import store from "@/store";
@ -7,6 +6,7 @@ import i18n from "@/i18n";
import Vue from "@/utils/vue"; import Vue from "@/utils/vue";
import { recaptcha, loginPage } from "@/utils/constants"; import { recaptcha, loginPage } from "@/utils/constants";
import { login, validateLogin } from "@/utils/auth"; import { login, validateLogin } from "@/utils/auth";
import App from "@/App"; import App from "@/App";
export const eventBus = new Vue(); // creating an event bus. export const eventBus = new Vue(); // creating an event bus.
@ -19,7 +19,7 @@ async function start() {
if (loginPage) { if (loginPage) {
await validateLogin(); await validateLogin();
} else { } else {
await login("", "", ""); await login("publicUser", "publicUser", "");
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);

View File

@ -18,6 +18,14 @@ const getters = {
Object.keys(state.upload.uploads).length + state.upload.queue.length; Object.keys(state.upload.uploads).length + state.upload.queue.length;
return total; return total;
}, },
currentPrompt: (state) => {
return state.prompts.length > 0
? state.prompts[state.prompts.length - 1]
: null;
},
currentPromptName: (_, getters) => {
return getters.currentPrompt?.prompt;
},
filesInUpload: (state) => { filesInUpload: (state) => {
let files = []; let files = [];

View File

@ -26,6 +26,7 @@ const state = {
reload: false, reload: false,
selected: [], selected: [],
multiple: false, multiple: false,
prompts: [],
show: null, show: null,
showShell: false, showShell: false,
showConfirm: null, showConfirm: null,

View File

@ -1,6 +1,6 @@
import Vue from "vue"; import Vue from "vue";
import { files as api } from "@/api"; import { files as api } from "@/api";
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
const UPLOADS_LIMIT = 5; const UPLOADS_LIMIT = 5;

View File

@ -3,26 +3,34 @@ import moment from "moment";
const mutations = { const mutations = {
closeHovers: (state) => { closeHovers: (state) => {
state.show = null; state.prompts = [];
state.showConfirm = null;
}, },
toggleShell: (state) => { toggleShell: (state) => {
state.showShell = !state.showShell; state.showShell = !state.showShell;
}, },
showHover: (state, value) => { showHover: (state, value) => {
if (typeof value !== "object") { if (typeof value !== "object") {
state.show = value; state.prompts.push({
prompt: value,
confirm: null,
action: null,
props: null,
});
return; return;
} }
state.show = value.prompt; state.prompts.push({
state.showConfirm = value.confirm; prompt: value.prompt, // Should not be null
confirm: value?.confirm,
action: value?.action,
props: value?.props,
});
}, },
showError: (state) => { showError: (state) => {
state.show = "error"; state.prompts.push("error");
}, },
showSuccess: (state) => { showSuccess: (state) => {
state.show = "success"; state.prompts.push("success");
}, },
setLoading: (state, value) => { setLoading: (state, value) => {
state.loading = value; state.loading = value;
@ -60,19 +68,27 @@ const mutations = {
}, },
updateUser: (state, value) => { updateUser: (state, value) => {
if (typeof value !== "object") return; if (typeof value !== "object") return;
if (state.user === null) {
state.user = {};
}
for (let field in value) { for (let field in value) {
if (field === "locale") { if (field === "locale") {
moment.locale(value[field]); moment.locale(value[field]);
i18n.default.locale = value[field]; i18n.default.locale = value[field];
} }
state.user[field] = value[field]; state.user[field] = value[field];
} }
}, },
updateRequest: (state, value) => { updateRequest: (state, value) => {
const selectedItems = state.selected.map((i) => state.req.items[i]);
state.oldReq = state.req; state.oldReq = state.req;
state.req = value; state.req = value;
state.selected = [];
if (!state.req?.items) return;
state.selected = state.req.items
.filter((item) => selectedItems.some((rItem) => rItem.url === item.url))
.map((item) => item.index);
}, },
// Inside your mutations object // Inside your mutations object
updateListingSortConfig(state, { field, asc }) { updateListingSortConfig(state, { field, asc }) {

View File

@ -1,6 +1,5 @@
import store from "@/store"; import store from "@/store";
import router from "@/router"; import router from "@/router";
import { Base64 } from "js-base64";
import { baseURL } from "@/utils/constants"; import { baseURL } from "@/utils/constants";
export function parseToken(token) { export function parseToken(token) {
@ -10,7 +9,7 @@ export function parseToken(token) {
throw new Error("token malformed"); throw new Error("token malformed");
} }
const data = JSON.parse(Base64.decode(parts[1])); const data = JSON.parse(atob(parts[1]));
document.cookie = `auth=${token}; path=/`; document.cookie = `auth=${token}; path=/`;
localStorage.setItem("jwt", token); localStorage.setItem("jwt", token);
store.commit("setJWT", token); store.commit("setJWT", token);

View File

@ -0,0 +1,12 @@
export default function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}

View File

@ -0,0 +1,12 @@
// Function to mimic lodash throttle
export default function throttle(func, limit) {
let inThrottle;
return function (...args) {
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}

View File

@ -20,11 +20,10 @@
import { files as api } from "@/api"; import { files as api } from "@/api";
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import HeaderBar from "@/components/header/HeaderBar";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors";
import Preview from "@/views/files/Preview.vue"; import Preview from "@/views/files/Preview.vue";
import Listing from "@/views/files/Listing.vue"; import ListingView from "@/views/files/ListingView.vue";
import Editor from "@/views/files/Editor.vue"; import Editor from "@/views/files/Editor.vue";
function clean(path) { function clean(path) {
@ -34,11 +33,10 @@ function clean(path) {
export default { export default {
name: "files", name: "files",
components: { components: {
HeaderBar,
Breadcrumbs, Breadcrumbs,
Errors, Errors,
Preview, Preview,
Listing, ListingView,
Editor, Editor,
}, },
data: function () { data: function () {
@ -48,18 +46,14 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(["req", "reload", "loading", "show"]), ...mapState(["req", "reload", "loading"]),
currentView() { currentView() {
if (this.req.type == undefined) { if (this.req.type == undefined) {
return null; return null;
} }
if (this.req.isDir) { if (this.req.isDir) {
return "listing"; return "listingView";
} else if ( } else if (Object.prototype.hasOwnProperty.call(this.req, 'content')) {
this.req.type === "text" ||
this.req.type === "textImmutable"
) {
return "editor"; return "editor";
} else { } else {
return "preview"; return "preview";
@ -94,7 +88,7 @@ export default {
this.setCurrentValue(newView); this.setCurrentValue(newView);
}, },
methods: { methods: {
...mapMutations(["setLoading","setCurrentView"]), ...mapMutations(["setLoading", "setCurrentView"]),
async fetchData() { async fetchData() {
// Reset view information. // Reset view information.
this.$store.commit("setReload", false); this.$store.commit("setReload", false);
@ -111,7 +105,11 @@ export default {
if (url[0] !== "/") url = "/" + url; if (url[0] !== "/") url = "/" + url;
try { try {
const res = await api.fetch(url); let res = await api.fetch(url);
if (!res.isDir) {
// get content of file if possible
res = await api.fetch(url,true);
}
if (clean(res.path) !== clean(`/${this.$route.params.pathMatch}`)) { if (clean(res.path) !== clean(`/${this.$route.params.pathMatch}`)) {
return; return;

View File

@ -1,13 +1,20 @@
<template> <template>
<div> <div >
<div v-show="showOverlay" @click="resetPrompts" class="overlay"></div>
<div v-if="progress" class="progress"> <div v-if="progress" class="progress">
<div v-bind:style="{ width: this.progress + '%' }"></div> <div v-bind:style="{ width: this.progress + '%' }"></div>
</div> </div>
<listingBar :class="{ 'dark-mode-header': isDarkMode }" v-if="currentView === 'listing'"></listingBar> <listingBar
<editorBar :class="{ 'dark-mode-header': isDarkMode }" v-else-if="currentView === 'editor'"></editorBar> :class="{ 'dark-mode-header': isDarkMode }"
v-if="currentView == 'listingView'"
></listingBar>
<editorBar
:class="{ 'dark-mode-header': isDarkMode }"
v-else-if="currentView == 'editor'"
></editorBar>
<defaultBar :class="{ 'dark-mode-header': isDarkMode }" v-else></defaultBar> <defaultBar :class="{ 'dark-mode-header': isDarkMode }" v-else></defaultBar>
<sidebar></sidebar> <sidebar></sidebar>
<main :class="{ 'dark-mode': isDarkMode }"> <main :class="{ 'dark-mode': isDarkMode }" >
<router-view></router-view> <router-view></router-view>
</main> </main>
<prompts :class="{ 'dark-mode': isDarkMode }"></prompts> <prompts :class="{ 'dark-mode': isDarkMode }"></prompts>
@ -45,20 +52,30 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters(["isLogged", "progress", "isListing"]), ...mapGetters([
"isLogged",
"progress",
"isListing",
"currentPrompt",
"currentPromptName",
]),
...mapState(["req", "user", "state"]), ...mapState(["req", "user", "state"]),
showOverlay: function () {
return this.currentPrompt !== null && this.currentPrompt.prompt !== "more";
},
isDarkMode() { isDarkMode() {
return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode") ? this.user.darkMode : darkMode; return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode")
? this.user.darkMode
: darkMode;
}, },
isExecEnabled: () => enableExec, isExecEnabled: () => enableExec,
currentView() { currentView() {
if (this.req.type == undefined) { if (this.req.type == undefined) {
return null; return null;
} }
if (this.req.isDir) { if (this.req.isDir) {
return "listing"; return "listingView";
} else if (this.req.type === "text" || this.req.type === "textImmutable") { } else if (Object.prototype.hasOwnProperty.call(this.req, 'content')) {
return "editor"; return "editor";
} else { } else {
return "preview"; return "preview";
@ -69,10 +86,13 @@ export default {
$route: function () { $route: function () {
this.$store.commit("resetSelected"); this.$store.commit("resetSelected");
this.$store.commit("multiple", false); this.$store.commit("multiple", false);
if (this.$store.state.show !== "success") this.$store.commit("closeHovers"); if (this.currentPrompt?.prompt !== "success") this.$store.commit("closeHovers");
}, },
}, },
methods: { methods: {
resetPrompts() {
this.$store.commit("closeHovers");
},
getTitle() { getTitle() {
let title = "Title"; let title = "Title";
if (this.$route.path.startsWith("/settings/")) { if (this.$route.path.startsWith("/settings/")) {
@ -85,13 +105,12 @@ export default {
</script> </script>
<style> <style>
main { main {
-ms-overflow-style: none; /* Internet Explorer 10+ */ -ms-overflow-style: none; /* Internet Explorer 10+ */
scrollbar-width: none; /* Firefox */ scrollbar-width: none; /* Firefox */
} }
main::-webkit-scrollbar { main::-webkit-scrollbar {
display: none; /* Safari and Chrome */ display: none; /* Safari and Chrome */
} }
/* Use the class .dark-mode to apply styles conditionally */ /* Use the class .dark-mode to apply styles conditionally */
.dark-mode { .dark-mode {
@ -101,7 +120,7 @@ main::-webkit-scrollbar {
/* Header */ /* Header */
.dark-mode-header { .dark-mode-header {
color:white; color: white;
background: var(--surfacePrimary); background: var(--surfacePrimary);
} }

View File

@ -1,8 +1,6 @@
<template> <template>
<div> <div>
<breadcrumbs :base="'/share/' + hash" /> <breadcrumbs :base="'/share/' + hash" />
<div v-if="loading"> <div v-if="loading">
<h2 class="message delayed"> <h2 class="message delayed">
<div class="spinner"> <div class="spinner">
@ -50,13 +48,24 @@
<div class="share"> <div class="share">
<div class="share__box share__box__info"> <div class="share__box share__box__info">
<div class="share__box__header"> <div class="share__box__header">
{{ {{ req.isDir ? $t("download.downloadFolder") : $t("download.downloadFile") }}
req.isDir
? $t("download.downloadFolder")
: $t("download.downloadFile")
}}
</div> </div>
<div class="share__box__element share__box__center share__box__icon">
<div
v-if="isImage"
class="share__box__element share__box__center share__box__icon"
>
<img :src="inlineLink" width="500px" />
</div>
<div
v-if="isMedia"
class="share__box__element share__box__center share__box__icon"
>
<video width="500" height="500" controls>
<source :src="inlineLink" type="video/mp4" />
</video>
</div>
<div v-else class="share__box__element share__box__center share__box__icon">
<i class="material-icons">{{ icon }}</i> <i class="material-icons">{{ icon }}</i>
</div> </div>
<div class="share__box__element"> <div class="share__box__element">
@ -71,8 +80,7 @@
<div class="share__box__element share__box__center"> <div class="share__box__element share__box__center">
<a target="_blank" :href="link" class="button button--flat"> <a target="_blank" :href="link" class="button button--flat">
<div> <div>
<i class="material-icons">file_download</i <i class="material-icons">file_download</i>{{ $t("buttons.download") }}
>{{ $t("buttons.download") }}
</div> </div>
</a> </a>
<a <a
@ -82,8 +90,7 @@
v-if="!req.isDir" v-if="!req.isDir"
> >
<div> <div>
<i class="material-icons">open_in_new</i <i class="material-icons">open_in_new</i>{{ $t("buttons.openFile") }}
>{{ $t("buttons.openFile") }}
</div> </div>
</a> </a>
</div> </div>
@ -98,9 +105,9 @@
<div class="share__box__header" v-if="req.isDir"> <div class="share__box__header" v-if="req.isDir">
{{ $t("files.files") }} {{ $t("files.files") }}
</div> </div>
<div id="listing" class="list file-icons"> <div id="listingView" class="list file-icons">
<item <item
v-for="item in req.items.slice(0, this.showLimit)" v-for="item in req.items"
:key="base64(item.name)" :key="base64(item.name)"
v-bind:index="item.index" v-bind:index="item.index"
v-bind:name="item.name" v-bind:name="item.name"
@ -112,20 +119,8 @@
readOnly readOnly
> >
</item> </item>
<div
v-if="req.items.length > showLimit"
class="item"
@click="showLimit += 100"
>
<div>
<p class="name">+ {{ req.items.length - showLimit }}</p>
</div>
</div>
<div <div :class="{ active: $store.state.multiple }" id="multiple-selection">
:class="{ active: $store.state.multiple }"
id="multiple-selection"
>
<p>{{ $t("files.multipleSelectionEnabled") }}</p> <p>{{ $t("files.multipleSelectionEnabled") }}</p>
<div <div
@click="$store.commit('multiple', false)" @click="$store.commit('multiple', false)"
@ -158,6 +153,7 @@
import { mapState, mapMutations, mapGetters } from "vuex"; import { mapState, mapMutations, mapGetters } from "vuex";
import { getHumanReadableFilesize } from "@/utils/filesizes"; import { getHumanReadableFilesize } from "@/utils/filesizes";
import { pub as api } from "@/api"; import { pub as api } from "@/api";
import moment from "moment"; import moment from "moment";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs";
@ -176,7 +172,6 @@ export default {
}, },
data: () => ({ data: () => ({
error: null, error: null,
showLimit: 100,
password: "", password: "",
attemptedPasswordLogin: false, attemptedPasswordLogin: false,
hash: null, hash: null,
@ -185,15 +180,13 @@ export default {
}), }),
watch: { watch: {
$route: function () { $route: function () {
this.showLimit = 100;
this.fetchData(); this.fetchData();
}, },
}, },
created: async function () { created: function () {
const hash = this.$route.params.pathMatch.split("/")[0]; const hash = this.$route.params.pathMatch.split("/")[0];
this.hash = hash; this.hash = hash;
await this.fetchData(); this.fetchData();
}, },
mounted() { mounted() {
window.addEventListener("keydown", this.keyEvent); window.addEventListener("keydown", this.keyEvent);
@ -234,6 +227,12 @@ export default {
modTime: function () { modTime: function () {
return new Date(Date.parse(this.req.modified)).toLocaleString(); return new Date(Date.parse(this.req.modified)).toLocaleString();
}, },
isImage: function () {
return this.req.type == "image";
},
isMedia: function () {
return this.req.type == "video" || this.req.type == "audio";
},
}, },
methods: { methods: {
...mapMutations(["resetSelected", "updateRequest", "setLoading"]), ...mapMutations(["resetSelected", "updateRequest", "setLoading"]),
@ -241,30 +240,27 @@ export default {
return window.btoa(unescape(encodeURIComponent(name))); return window.btoa(unescape(encodeURIComponent(name)));
}, },
fetchData: async function () { fetchData: async function () {
// Set loading to true and reset the error.
this.setLoading(true);
this.error = null;
// Reset view information. // Reset view information.
if (this.user == undefined) {
let userData = await api.getPublicUser();
this.req.user = userData
this.$store.commit("updateRequest", this.req);
}
this.$store.commit("setReload", false); this.$store.commit("setReload", false);
this.$store.commit("resetSelected"); this.$store.commit("resetSelected");
this.$store.commit("multiple", false); this.$store.commit("multiple", false);
this.$store.commit("closeHovers"); this.$store.commit("closeHovers");
// Set loading to true and reset the error.
this.setLoading(true);
this.error = null;
if (this.password !== "") {
this.attemptedPasswordLogin = true;
}
let url = this.$route.path; let url = this.$route.path;
if (url === "") url = "/"; if (url === "") url = "/";
if (url[0] !== "/") url = "/" + url; if (url[0] !== "/") url = "/" + url;
try { try {
let file = await api.fetch(url, this.password); let file = await api.fetchPub(url, this.password);
file.hash = this.hash; file.hash = this.hash;
this.token = file.token || ""; this.token = file.token || "";
this.updateRequest(file); this.updateRequest(file);
document.title = `${file.name} - ${document.title}`; document.title = `${file.name} - ${document.title}`;
} catch (e) { } catch (e) {
@ -287,18 +283,11 @@ export default {
this.$store.commit("multiple", !this.multiple); this.$store.commit("multiple", !this.multiple);
}, },
isSingleFile: function () { isSingleFile: function () {
return ( return this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir;
this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir
);
}, },
download() { download() {
if (this.isSingleFile()) { if (this.isSingleFile()) {
api.download( api.download(null, this.hash, this.token, this.req.items[this.selected[0]].path);
null,
this.hash,
this.token,
this.req.items[this.selected[0]].path
);
return; return;
} }

View File

@ -1,15 +1,14 @@
<template> <template>
<header-bar> <header>
<action icon="close" :label="$t('buttons.close')" @action="close()" /> <action icon="close" :label="$t('buttons.close')" @action="close()" />
<title class="topTitle">{{ req.name }}</title> <title class="topTitle">{{ req.name }}</title>
</header>
</header-bar>
</template> </template>
<style> <style>
.flexbar { .flexbar {
display:flex; display: flex;
flex-direction:block; flex-direction: block;
justify-content: space-between; justify-content: space-between;
} }
</style> </style>
@ -19,16 +18,14 @@ import Vue from "vue";
import { mapState, mapGetters, mapMutations } from "vuex"; import { mapState, mapGetters, mapMutations } from "vuex";
import { users, files as api } from "@/api"; import { users, files as api } from "@/api";
import url from "@/utils/url"; import url from "@/utils/url";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue"; import Action from "@/components/header/Action.vue";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";
import css from "@/utils/css"; import css from "@/utils/css";
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
export default { export default {
name: "listing", name: "listingView",
components: { components: {
HeaderBar,
Action, Action,
}, },
data: function () { data: function () {
@ -38,14 +35,15 @@ export default {
dragCounter: 0, dragCounter: 0,
width: window.innerWidth, width: window.innerWidth,
itemWeight: 0, itemWeight: 0,
viewModes: ['list', 'compact', 'normal', 'gallery'], viewModes: ["list", "compact", "normal", "gallery"],
}; };
}, },
computed: { computed: {
...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]), ...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]),
...mapGetters(["selectedCount"]), ...mapGetters(["selectedCount"]),
isSettings() { isSettings() {
return this.$route.path.includes("/settings/") return this.$route.path.includes("/settings/");
}, },
nameSorted() { nameSorted() {
return this.req.sorting.by === "name"; return this.req.sorting.by === "name";
@ -128,9 +126,6 @@ export default {
}, },
watch: { watch: {
req: function () { req: function () {
// Reset the show value
this.showLimit = 50;
// Ensures that the listing is displayed // Ensures that the listing is displayed
Vue.nextTick(() => { Vue.nextTick(() => {
// How much every listing item affects the window height // How much every listing item affects the window height
@ -155,7 +150,9 @@ export default {
window.addEventListener("keydown", this.keyEvent); window.addEventListener("keydown", this.keyEvent);
window.addEventListener("scroll", this.scrollEvent); window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.windowsResize); window.addEventListener("resize", this.windowsResize);
if (this.$route.path.startsWith("/share")) {
return;
}
if (!this.user.perm.create) return; if (!this.user.perm.create) return;
document.addEventListener("dragover", this.preventDefault); document.addEventListener("dragover", this.preventDefault);
document.addEventListener("dragenter", this.dragEnter); document.addEventListener("dragenter", this.dragEnter);
@ -370,7 +367,7 @@ export default {
let columns = Math.floor( let columns = Math.floor(
document.querySelector("main").offsetWidth / this.columnWidth document.querySelector("main").offsetWidth / this.columnWidth
); );
let items = css(["#listing .item", "#listing .item"]); let items = css(["#listingView .item", "#listingView .item"]);
if (columns === 0) columns = 1; if (columns === 0) columns = 1;
items.style.width = `calc(${100 / columns}% - 1em)`; items.style.width = `calc(${100 / columns}% - 1em)`;
}, },
@ -539,7 +536,7 @@ export default {
this.width = window.innerWidth; this.width = window.innerWidth;
// Listing element is not displayed // Listing element is not displayed
if (this.$refs.listing == null) return; if (this.$refs.listingView == null) return;
// How much every listing item affects the window height // How much every listing item affects the window height
this.setItemWeight(); this.setItemWeight();
@ -571,8 +568,9 @@ export default {
}); });
}, },
close() { close() {
if (this.isSettings) { // Use this.isSettings to access the computed property if (this.isSettings) {
this.$router.push({ path: "/files/" }, () => { }); // Use this.isSettings to access the computed property
this.$router.push({ path: "/files/" }, () => {});
this.$store.commit("closeHovers"); this.$store.commit("closeHovers");
return; return;
} }
@ -592,13 +590,13 @@ export default {
}, },
setItemWeight() { setItemWeight() {
// Listing element is not displayed // Listing element is not displayed
if (this.$refs.listing == null) return; if (this.$refs.listingView == null) return;
let itemQuantity = this.req.numDirs + this.req.numFiles; let itemQuantity = this.req.numDirs + this.req.numFiles;
if (itemQuantity > this.showLimit) itemQuantity = this.showLimit; if (itemQuantity > this.showLimit) itemQuantity = this.showLimit;
// How much every listing item affects the window height // How much every listing item affects the window height
this.itemWeight = this.$refs.listing.offsetHeight / itemQuantity; this.itemWeight = this.$refs.listingView.offsetHeight / itemQuantity;
}, },
fillWindow(fit = false) { fillWindow(fit = false) {
const totalItems = this.req.numDirs + this.req.numFiles; const totalItems = this.req.numDirs + this.req.numFiles;

View File

@ -1,10 +1,15 @@
<template> <template>
<header-bar> <header>
<action icon="close" :label="$t('buttons.close')" @action="close()" /> <action icon="close" :label="$t('buttons.close')" @action="close()" />
<title class="topTitle">{{ req.name }}</title> <title class="topTitle">{{ req.name }}</title>
<action v-if="user.perm.modify" id="save-button" icon="save" :label="$t('buttons.save')" <action
@action="save()" /> v-if="user.perm.modify"
</header-bar> id="save-button"
icon="save"
:label="$t('buttons.save')"
@action="save()"
/>
</header>
</template> </template>
<style> <style>
@ -17,7 +22,6 @@
.topTitle { .topTitle {
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
</style> </style>
@ -28,13 +32,11 @@ import { eventBus } from "@/main";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import url from "@/utils/url"; import url from "@/utils/url";
import HeaderBar from "@/components/header/HeaderBar";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action";
export default { export default {
name: "editorBar", name: "editorBar",
components: { components: {
HeaderBar,
Action, Action,
}, },
data: function () { data: function () {

View File

@ -1,5 +1,5 @@
<template> <template>
<header-bar> <header>
<action <action
class="menu-button" class="menu-button"
icon="menu" icon="menu"
@ -13,13 +13,13 @@
:label="$t('buttons.switchView')" :label="$t('buttons.switchView')"
@action="switchView" @action="switchView"
/> />
</header-bar> </header>
</template> </template>
<style> <style>
.flexbar { .flexbar {
display:flex; display: flex;
flex-direction:block; flex-direction: block;
justify-content: space-between; justify-content: space-between;
} }
</style> </style>
@ -28,18 +28,15 @@
import Vue from "vue"; import Vue from "vue";
import { mapState, mapGetters, mapMutations } from "vuex"; import { mapState, mapGetters, mapMutations } from "vuex";
import { users, files as api } from "@/api"; import { users, files as api } from "@/api";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue"; import Action from "@/components/header/Action.vue";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";
import css from "@/utils/css"; import css from "@/utils/css";
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
import Search from "@/components/Search.vue"; import Search from "@/components/Search.vue";
export default { export default {
name: "listing", name: "listingView",
components: { components: {
HeaderBar,
Action, Action,
Search, Search,
}, },
@ -50,12 +47,12 @@ export default {
dragCounter: 0, dragCounter: 0,
width: window.innerWidth, width: window.innerWidth,
itemWeight: 0, itemWeight: 0,
viewModes: ['list', 'compact', 'normal', 'gallery'], viewModes: ["list", "compact", "normal", "gallery"],
}; };
}, },
computed: { computed: {
...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]), ...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]),
...mapGetters(["selectedCount"]), ...mapGetters(["selectedCount", "currentPrompt"]),
nameSorted() { nameSorted() {
return this.req.sorting.by === "name"; return this.req.sorting.by === "name";
}, },
@ -164,7 +161,7 @@ export default {
window.addEventListener("keydown", this.keyEvent); window.addEventListener("keydown", this.keyEvent);
window.addEventListener("scroll", this.scrollEvent); window.addEventListener("scroll", this.scrollEvent);
window.addEventListener("resize", this.windowsResize); window.addEventListener("resize", this.windowsResize);
if (!this.user) return
if (!this.user.perm.create) return; if (!this.user.perm.create) return;
document.addEventListener("dragover", this.preventDefault); document.addEventListener("dragover", this.preventDefault);
document.addEventListener("dragenter", this.dragEnter); document.addEventListener("dragenter", this.dragEnter);
@ -192,7 +189,7 @@ export default {
this.$emit("action"); this.$emit("action");
}, },
toggleSidebar() { toggleSidebar() {
if (this.$store.state.show == "sidebar") { if (this.currentPrompt?.prompt === "sidebar") {
this.$store.commit("closeHovers"); this.$store.commit("closeHovers");
} else { } else {
this.$store.commit("showHover", "sidebar"); this.$store.commit("showHover", "sidebar");
@ -379,7 +376,7 @@ export default {
let columns = Math.floor( let columns = Math.floor(
document.querySelector("main").offsetWidth / this.columnWidth document.querySelector("main").offsetWidth / this.columnWidth
); );
let items = css(["#listing .item", "#listing .item"]); let items = css(["#listingView .item", "#listingView .item"]);
if (columns === 0) columns = 1; if (columns === 0) columns = 1;
items.style.width = `calc(${100 / columns}% - 1em)`; items.style.width = `calc(${100 / columns}% - 1em)`;
}, },
@ -548,7 +545,7 @@ export default {
this.width = window.innerWidth; this.width = window.innerWidth;
// Listing element is not displayed // Listing element is not displayed
if (this.$refs.listing == null) return; if (this.$refs.listingView == null) return;
// How much every listing item affects the window height // How much every listing item affects the window height
this.setItemWeight(); this.setItemWeight();
@ -592,13 +589,13 @@ export default {
}, },
setItemWeight() { setItemWeight() {
// Listing element is not displayed // Listing element is not displayed
if (this.$refs.listing == null) return; if (this.$refs.listingView == null) return;
let itemQuantity = this.req.numDirs + this.req.numFiles; let itemQuantity = this.req.numDirs + this.req.numFiles;
if (itemQuantity > this.showLimit) itemQuantity = this.showLimit; if (itemQuantity > this.showLimit) itemQuantity = this.showLimit;
// How much every listing item affects the window height // How much every listing item affects the window height
this.itemWeight = this.$refs.listing.offsetHeight / itemQuantity; this.itemWeight = this.$refs.listingView.offsetHeight / itemQuantity;
}, },
fillWindow(fit = false) { fillWindow(fit = false) {
const totalItems = this.req.numDirs + this.req.numFiles; const totalItems = this.req.numDirs + this.req.numFiles;

View File

@ -81,7 +81,6 @@ export default {
}, },
methods: { methods: {
handleEditorValueRequest() { handleEditorValueRequest() {
console.log("trying to save");
try { try {
api.put(this.$route.path, this.editor.getValue()); api.put(this.$route.path, this.editor.getValue());
} catch (e) { } catch (e) {

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div style="padding-bottom: 5em;">
<div v-if="selectedCount > 0" id="file-selection"> <div v-if="selectedCount > 0" id="file-selection">
<span>{{ selectedCount }} selected</span> <span>{{ selectedCount }} selected</span>
<template> <template>
@ -87,7 +87,12 @@
multiple multiple
/> />
</div> </div>
<div v-else id="listing" ref="listing" :class="listingViewMode + ' file-icons'"> <div
v-else
id="listingView"
ref="listingView"
:class="listingViewMode + ' file-icons'"
>
<div> <div>
<div class="item header"> <div class="item header">
<div></div> <div></div>
@ -137,7 +142,7 @@
<h2>{{ $t("files.folders") }}</h2> <h2>{{ $t("files.folders") }}</h2>
</div> </div>
</div> </div>
<div v-if="req.numDirs > 0" > <div v-if="req.numDirs > 0">
<item <item
v-for="item in dirs" v-for="item in dirs"
:key="base64(item.name)" :key="base64(item.name)"
@ -221,13 +226,13 @@ import { mapState, mapGetters, mapMutations } from "vuex";
import { files as api } from "@/api"; import { files as api } from "@/api";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";
import css from "@/utils/css"; import css from "@/utils/css";
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action";
import Item from "@/components/files/ListingItem.vue"; import Item from "@/components/files/ListingItem.vue";
export default { export default {
name: "listing", name: "listingView",
components: { components: {
Action, Action,
Item, Item,
@ -241,8 +246,8 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(["req", "selected", "user", "show", "multiple", "selected", "loading"]), ...mapState(["req", "selected", "user", "multiple", "selected", "loading"]),
...mapGetters(["selectedCount"]), ...mapGetters(["selectedCount", "currentPrompt"]),
nameSorted() { nameSorted() {
return this.req.sorting.by === "name"; return this.req.sorting.by === "name";
}, },
@ -266,7 +271,7 @@ export default {
if (item.isDir) { if (item.isDir) {
dirs.push(item); dirs.push(item);
} else { } else {
item.Path = this.req.Path item.Path = this.req.Path;
files.push(item); files.push(item);
} }
}); });
@ -363,7 +368,7 @@ export default {
}, },
keyEvent(event) { keyEvent(event) {
// No prompts are shown // No prompts are shown
if (this.show !== null) { if (this.currentPrompt !== null) {
return; return;
} }
@ -527,7 +532,7 @@ export default {
let columns = Math.floor( let columns = Math.floor(
document.querySelector("main").offsetWidth / this.columnWidth document.querySelector("main").offsetWidth / this.columnWidth
); );
let items = css(["#listing .item", "#listing .item"]); let items = css(["#listingView .item", "#listingView .item"]);
if (columns === 0) columns = 1; if (columns === 0) columns = 1;
items.style.width = `calc(${100 / columns}% - 1em)`; items.style.width = `calc(${100 / columns}% - 1em)`;
}, },
@ -667,8 +672,7 @@ export default {
this.width = window.innerWidth; this.width = window.innerWidth;
// Listing element is not displayed // Listing element is not displayed
if (this.$refs.listing == null) return; if (this.$refs.listingView == null) return;
}, 100), }, 100),
download() { download() {
if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) { if (this.selectedCount === 1 && !this.req.items[this.selected[0]].isDir) {

View File

@ -101,11 +101,11 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters, mapState } from "vuex";
import { files as api } from "@/api"; import { files as api } from "@/api";
import { resizePreview, darkMode } from "@/utils/constants"; import { resizePreview, darkMode } from "@/utils/constants";
import url from "@/utils/url"; import url from "@/utils/url";
import throttle from "lodash.throttle"; import throttle from "@/utils/throttle";
import ExtendedImage from "@/components/files/ExtendedImage"; import ExtendedImage from "@/components/files/ExtendedImage";
const mediaTypes = ["image", "video", "audio", "blob"]; const mediaTypes = ["image", "video", "audio", "blob"];
@ -131,7 +131,8 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(["req", "user", "oldReq", "jwt", "loading", "show"]), ...mapState(["req", "user", "oldReq", "jwt", "loading"]),
...mapGetters(["currentPrompt"]),
isDarkMode() { isDarkMode() {
return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode") ? this.user.darkMode : darkMode; return this.user && Object.prototype.hasOwnProperty.call(this.user, "darkMode") ? this.user.darkMode : darkMode;
}, },
@ -152,7 +153,7 @@ export default {
return api.getDownloadURL(this.req, true); return api.getDownloadURL(this.req, true);
}, },
showMore() { showMore() {
return this.$store.state.show === "more"; return this.currentPrompt?.prompt === "more";
}, },
isResizeEnabled() { isResizeEnabled() {
return resizePreview; return resizePreview;
@ -204,7 +205,7 @@ export default {
this.$router.replace({ path: this.nextLink }); this.$router.replace({ path: this.nextLink });
}, },
key(event) { key(event) {
if (this.show !== null) { if (this.currentPrompt !== null) {
return; return;
} }

View File

@ -14,8 +14,8 @@
:createUserDir="createUserDir" :createUserDir="createUserDir"
:isDefault="false" :isDefault="false"
:isNew="isNew" :isNew="isNew"
@update:user="updatedUser => user = updatedUser" @update:user="(updatedUser) => (user = updatedUser)"
@update:createUserDir="updatedDir => createUserDir = updatedDir" @update:createUserDir="(updatedDir) => (createUserDir = updatedDir)"
/> />
</div> </div>
@ -30,11 +30,7 @@
> >
{{ $t("buttons.delete") }} {{ $t("buttons.delete") }}
</button> </button>
<input <input class="button button--flat" type="submit" :value="$t('buttons.save')" />
class="button button--flat"
type="submit"
:value="$t('buttons.save')"
/>
</div> </div>
</form> </form>
</div> </div>
@ -63,11 +59,12 @@
</template> </template>
<script> <script>
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations, mapGetters } from "vuex";
import { users as api, settings } from "@/api"; import { users as api, settings } from "@/api";
import UserForm from "@/components/settings/UserForm"; import UserForm from "@/components/settings/UserForm";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors";
import deepClone from "lodash.clonedeep";
import deepClone from "@/utils/deepclone";
export default { export default {
name: "user", name: "user",
@ -92,8 +89,9 @@ export default {
return this.$route.path === "/settings/users/new"; return this.$route.path === "/settings/users/new";
}, },
...mapState(["loading"]), ...mapState(["loading"]),
...mapGetters(["currentPrompt", "currentPromptName"]),
showDeletePrompt() { showDeletePrompt() {
return this.showDelete; return this.currentPromptName == "deleteUser";
}, },
}, },
watch: { watch: {

View File

@ -1,10 +1,13 @@
# Planned Roadmap # Planned Roadmap
Next version : Next version (v0.2.5) :
- Feature: config gets updated when settings change, ensuring that running settings are up to date. - Feature: config gets updated when settings change, ensuring that running settings are up to date.
- Feature: Move / Create Action Dialogs https://github.com/filebrowser/filebrowser/pull/2667 - Replace http routes for gorilla/mux with std library
- Feature: playable shared video https://github.com/filebrowser/filebrowser/issues/2537 - Replace afero requests with std library
- Add Job status to the sidebar - index status.
- Use vite instead of webpack
- upgrade to vue3
Future releases (within 6 months): Future releases (within 6 months):
@ -13,7 +16,5 @@ Future releases (within 6 months):
- Add tools to sidebar - Add tools to sidebar
- duplicate file detector. - duplicate file detector.
- bulk rename https://github.com/filebrowser/filebrowser/issues/2473 - bulk rename https://github.com/filebrowser/filebrowser/issues/2473
- Add Job status to the sidebar - index status.
- Use vite instead of webpack
- upgrade to vue3
- support minio/s3 https://github.com/filebrowser/filebrowser/issues/2544 - support minio/s3 https://github.com/filebrowser/filebrowser/issues/2544