Compare commits
78
Commits
v1.16.0
...
v1.18.0-rc.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a22689328 | ||
|
|
ce65aea0ab | ||
|
|
45edad867c | ||
|
|
ea0a408849 | ||
|
|
18592af993 | ||
|
|
b1e0e7b923 | ||
|
|
1e212a8dc6 | ||
|
|
0e9d2a13af | ||
|
|
6494a9332d | ||
|
|
41baccb85d | ||
|
|
52eb7392c4 | ||
|
|
855c53ad02 | ||
|
|
004eded398 | ||
|
|
df48276300 | ||
|
|
accaf23aa3 | ||
|
|
de6fe4dc6f | ||
|
|
08f6a91441 | ||
|
|
95c9561e97 | ||
|
|
fcb19518c7 | ||
|
|
fbaf696821 | ||
|
|
abe3483a8f | ||
|
|
22e09334ec | ||
|
|
58592e3ef1 | ||
|
|
0126188ba7 | ||
|
|
5bdb6798a9 | ||
|
|
ab2729ab79 | ||
|
|
58e81fdffb | ||
|
|
0619a27872 | ||
|
|
0e52ce830a | ||
|
|
97437cad64 | ||
|
|
5b90a98650 | ||
|
|
96dae7bfec | ||
|
|
93a02c677e | ||
|
|
0d054f9b64 | ||
|
|
1107f6eb5f | ||
|
|
3650364017 | ||
|
|
086508f51a | ||
|
|
4ace451013 | ||
|
|
c9ea773a22 | ||
|
|
0f4ae7636d | ||
|
|
87d3a8363b | ||
|
|
c494ced21f | ||
|
|
a8e2fc6f61 | ||
|
|
aca1b45e93 | ||
|
|
5cb2a10138 | ||
|
|
411796606c | ||
|
|
1a9b54c9fa | ||
|
|
c7f4f15272 | ||
|
|
713527facf | ||
|
|
6e662dc9fc | ||
|
|
eb178caf3a | ||
|
|
adf3f641ce | ||
|
|
6157c766de | ||
|
|
745cd4744a | ||
|
|
faf15b4567 | ||
|
|
3746c899b7 | ||
|
|
7bbca12ff8 | ||
|
|
3967b39a17 | ||
|
|
2b2d24fe20 | ||
|
|
f4e112f404 | ||
|
|
87a0eecc31 | ||
|
|
f09dcb98eb | ||
|
|
f90870b99f | ||
|
|
75b58eb480 | ||
|
|
ed9cb923fb | ||
|
|
dd39556759 | ||
|
|
d5141c6d51 | ||
|
|
5675644341 | ||
|
|
1f30383866 | ||
|
|
40531ef247 | ||
|
|
366700dc36 | ||
|
|
f23fd683a9 | ||
|
|
755ed6f69f | ||
|
|
66662cd678 | ||
|
|
8734fa65fc | ||
|
|
c53e5c5f17 | ||
|
|
74823e81e9 | ||
|
|
ef4b8a2cf8 |
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 10
|
||||
@@ -19,3 +19,4 @@ deb
|
||||
/repos
|
||||
/proto/scripts/protoc-gen-gosyncthing
|
||||
/gui/next-gen-gui
|
||||
.idea
|
||||
|
||||
@@ -82,7 +82,7 @@ deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.c
|
||||
Denis A. (dva) <denisva@gmail.com>
|
||||
Dennis Wilson (snnd) <dw@risu.io>
|
||||
dependabot-preview[bot] <dependabot-preview[bot]@users.noreply.github.com> <27856297+dependabot-preview[bot]@users.noreply.github.com>
|
||||
dependabot[bot] <dependabot[bot]@users.noreply.github.com>
|
||||
dependabot[bot] <dependabot[bot]@users.noreply.github.com> <49699333+dependabot[bot]@users.noreply.github.com>
|
||||
derekriemer <derek.riemer@colorado.edu>
|
||||
desbma <desbma@users.noreply.github.com>
|
||||
Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com>
|
||||
@@ -100,6 +100,7 @@ Felix Lampe <mail@flampe.de>
|
||||
Felix Unterpaintner (bigbear2nd) <bigbear2nd@gmail.com>
|
||||
Francois-Xavier Gsell (zukoo) <fxgsell@gmail.com>
|
||||
Frank Isemann (fti7) <frank@isemann.name>
|
||||
Gahl Saraf <saraf.gahl@gmail.com>
|
||||
georgespatton <georgespatton@users.noreply.github.com>
|
||||
ghjklw <malo@jaffre.info>
|
||||
Gilli Sigurdsson (gillisig) <gilli@vx.is>
|
||||
@@ -113,6 +114,7 @@ Heiko Zuerker (Smiley73) <heiko@zuerker.org>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro>
|
||||
Iain Barnett <iainspeed@gmail.com>
|
||||
Ian Johnson (anonymouse64) <ian.johnson@canonical.com> <person.uwsome@gmail.com>
|
||||
Ikko Ashimine <eltociear@gmail.com>
|
||||
Ilya Brin <464157+ilyabrin@users.noreply.github.com>
|
||||
Iskander Sharipov (Alex) <quasilyte@gmail.com>
|
||||
Jaakko Hannikainen (jgke) <jgke@jgke.fi>
|
||||
@@ -203,6 +205,7 @@ NoLooseEnds <jon.koslung@gmail.com>
|
||||
Oliver Freyermuth <o.freyermuth@googlemail.com>
|
||||
otbutz <tbutz@optitool.de>
|
||||
Otiel <Otiel@users.noreply.github.com>
|
||||
overkill <22098433+0verk1ll@users.noreply.github.com>
|
||||
Oyebanji Jacob Mayowa <oyebanji05@gmail.com>
|
||||
Pablo <pbaeyens31+github@gmail.com>
|
||||
Pascal Jungblut (pascalj) <github@pascalj.com> <mail@pascal-jungblut.com>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Reporting Bugs
|
||||
|
||||
Please file bugs in the [Github Issue
|
||||
Please file bugs in the [GitHub Issue
|
||||
Tracker](https://github.com/syncthing/syncthing/issues). Include at
|
||||
least the following:
|
||||
|
||||
|
||||
+1
-4
@@ -16,8 +16,7 @@ the name of the Syncthing instance can be optionally defined by using
|
||||
**Docker cli**
|
||||
```
|
||||
$ docker pull syncthing/syncthing
|
||||
$ docker run --sysctl net.core.rmem_max=2097152 \
|
||||
-p 8384:8384 -p 22000:22000/tcp -p 22000:22000/udp \
|
||||
$ docker run -p 8384:8384 -p 22000:22000/tcp -p 22000:22000/udp \
|
||||
-v /wherever/st-sync:/var/syncthing \
|
||||
--hostname=my-syncthing \
|
||||
syncthing/syncthing:latest
|
||||
@@ -41,8 +40,6 @@ services:
|
||||
- 8384:8384
|
||||
- 22000:22000/tcp
|
||||
- 22000:22000/udp
|
||||
sysctls:
|
||||
- net.core.rmem_max=2097152
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
|
||||
@@ -73,9 +73,8 @@ This helps the team understand what are the biggest pain points for our users, a
|
||||
|
||||
## Getting in Touch
|
||||
|
||||
The first and best point of contact is the [Forum][8]. There is also an IRC
|
||||
channel, `#syncthing` on [freenode][4] (with a [web client][9]), for talking
|
||||
directly to developers and users. If you've found something that is clearly a
|
||||
The first and best point of contact is the [Forum][8].
|
||||
If you've found something that is clearly a
|
||||
bug, feel free to report it in the [GitHub issue tracker][10].
|
||||
|
||||
## Building
|
||||
@@ -102,12 +101,10 @@ All code is licensed under the [MPLv2 License][7].
|
||||
[1]: https://docs.syncthing.net/specs/bep-v1.html
|
||||
[2]: https://docs.syncthing.net/intro/getting-started.html
|
||||
[3]: https://github.com/syncthing/syncthing/blob/main/etc
|
||||
[4]: https://www.freenode.net/
|
||||
[5]: https://docs.syncthing.net/dev/building.html
|
||||
[6]: https://docs.syncthing.net/
|
||||
[7]: https://github.com/syncthing/syncthing/blob/main/LICENSE
|
||||
[8]: https://forum.syncthing.net/
|
||||
[9]: https://kiwiirc.com/client/irc.freenode.net/#syncthing
|
||||
[10]: https://github.com/syncthing/syncthing/issues
|
||||
[11]: https://docs.syncthing.net/users/contrib.html#gui-wrappers
|
||||
[12]: https://www.bountysource.com/teams/syncthing/issues
|
||||
|
||||
@@ -50,7 +50,9 @@ var (
|
||||
benchRun string
|
||||
debugBinary bool
|
||||
coverage bool
|
||||
long bool
|
||||
timeout = "120s"
|
||||
longTimeout = "600s"
|
||||
numVersions = 5
|
||||
withNextGenGUI = os.Getenv("BUILD_NEXT_GEN_GUI") != ""
|
||||
)
|
||||
@@ -202,18 +204,6 @@ var targets = map[string]target{
|
||||
},
|
||||
}
|
||||
|
||||
// These are repos we need to clone to run "go generate"
|
||||
|
||||
type dependencyRepo struct {
|
||||
path string
|
||||
repo string
|
||||
commit string
|
||||
}
|
||||
|
||||
var dependencyRepos = []dependencyRepo{
|
||||
{path: "xdr", repo: "https://github.com/calmh/xdr.git", commit: "08e072f9cb16"},
|
||||
}
|
||||
|
||||
func initTargets() {
|
||||
all := targets["all"]
|
||||
pkgs, _ := filepath.Glob("cmd/*")
|
||||
@@ -375,6 +365,7 @@ func parseFlags() {
|
||||
flag.StringVar(&cc, "cc", os.Getenv("CC"), "Set CC environment variable for `go build`")
|
||||
flag.BoolVar(&debugBinary, "debug-binary", debugBinary, "Create unoptimized binary to use with delve, set -gcflags='-N -l' and omit -ldflags")
|
||||
flag.BoolVar(&coverage, "coverage", coverage, "Write coverage profile of tests to coverage.txt")
|
||||
flag.BoolVar(&long, "long", long, "Run tests without the -short flag")
|
||||
flag.IntVar(&numVersions, "num-versions", numVersions, "Number of versions for changelog command")
|
||||
flag.StringVar(&run, "run", "", "Specify which tests to run")
|
||||
flag.StringVar(&benchRun, "bench", "", "Specify which benchmarks to run")
|
||||
@@ -386,7 +377,13 @@ func test(tags []string, pkgs ...string) {
|
||||
lazyRebuildAssets()
|
||||
|
||||
tags = append(tags, "purego")
|
||||
args := []string{"test", "-short", "-timeout", timeout, "-tags", strings.Join(tags, " ")}
|
||||
args := []string{"test", "-tags", strings.Join(tags, " ")}
|
||||
if long {
|
||||
timeout = longTimeout
|
||||
} else {
|
||||
args = append(args, "-short")
|
||||
}
|
||||
args = append(args, "-timeout", timeout)
|
||||
|
||||
if runtime.GOARCH == "amd64" {
|
||||
switch runtime.GOOS {
|
||||
@@ -871,28 +868,24 @@ func shouldRebuildAssets(target, srcdir string) bool {
|
||||
|
||||
func proto() {
|
||||
pv := protobufVersion()
|
||||
dependencyRepos = append(dependencyRepos,
|
||||
dependencyRepo{path: "protobuf", repo: "https://github.com/gogo/protobuf.git", commit: pv},
|
||||
)
|
||||
repo := "https://github.com/gogo/protobuf.git"
|
||||
path := filepath.Join("repos", "protobuf")
|
||||
|
||||
runPrint(goCmd, "get", fmt.Sprintf("github.com/gogo/protobuf/protoc-gen-gogofast@%v", pv))
|
||||
os.MkdirAll("repos", 0755)
|
||||
for _, dep := range dependencyRepos {
|
||||
path := filepath.Join("repos", dep.path)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
runPrintInDir("repos", "git", "clone", dep.repo, dep.path)
|
||||
} else {
|
||||
runPrintInDir(path, "git", "fetch")
|
||||
}
|
||||
runPrintInDir(path, "git", "checkout", dep.commit)
|
||||
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
runPrint("git", "clone", repo, path)
|
||||
} else {
|
||||
runPrintInDir(path, "git", "fetch")
|
||||
}
|
||||
runPrintInDir(path, "git", "checkout", pv)
|
||||
|
||||
runPrint(goCmd, "generate", "github.com/syncthing/syncthing/cmd/stdiscosrv")
|
||||
runPrint(goCmd, "generate", "proto/generate.go")
|
||||
}
|
||||
|
||||
func testmocks() {
|
||||
runPrint(goCmd, "get", "golang.org/x/tools/cmd/goimports")
|
||||
runPrint(goCmd, "get", "github.com/maxbrunsfeld/counterfeiter/v6")
|
||||
args := []string{
|
||||
"generate",
|
||||
"github.com/syncthing/syncthing/lib/config",
|
||||
|
||||
@@ -510,10 +510,7 @@ func (m *DatabaseRecord) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -648,10 +645,7 @@ func (m *ReplicationRecord) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -752,10 +746,7 @@ func (m *DatabaseAddress) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthDatabase
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -46,18 +46,18 @@
|
||||
<h1>Relay Pool Data</h1>
|
||||
<div ng-if="relays === undefined" class="text-center">
|
||||
<img src="https://cdnjs.cloudflare.com/ajax/libs/galleriffic/2.0.1/css/loader.gif" alt=""/>
|
||||
<p>Please wait while we gather data</p>
|
||||
<p>Please wait while we gather data…</p>
|
||||
</div>
|
||||
<div>
|
||||
<div ng-show="relays !== undefined" class="ng-hide">
|
||||
<p>
|
||||
The relays listed on this page are not managed or vetted by the Syncthing project.
|
||||
Each relay is the responsibility of the relay operator.
|
||||
Currently {{ relays.length }} relays online.
|
||||
Currently {{ relays.length }} relays are online.
|
||||
</p>
|
||||
</div>
|
||||
<div id="map"></div> <!-- Can't hide the map, otherwise it freaks out -->
|
||||
<p>The circle size represents how much bytes the relay transferred relative to other relays</p>
|
||||
<p>The circle size represents how much bytes the relay has transferred relatively to other relays.</p>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table table-striped table-condensed table">
|
||||
@@ -188,7 +188,7 @@
|
||||
<hr>
|
||||
<p>
|
||||
This product includes GeoLite2 data created by MaxMind, available from
|
||||
<a href="http://www.maxmind.com">http://www.maxmind.com</a>.
|
||||
<a href="https://www.maxmind.com">https://www.maxmind.com</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func main() {
|
||||
|
||||
if join {
|
||||
log.Println("Creating client")
|
||||
relay, err := client.NewClient(uri, []tls.Certificate{cert}, nil, 10*time.Second)
|
||||
relay, err := client.NewClient(uri, []tls.Certificate{cert}, 10*time.Second)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -134,12 +134,14 @@ func (c *apiClient) Post(url, body string) (*http.Response, error) {
|
||||
return c.Do(request)
|
||||
}
|
||||
|
||||
var errNotFound = errors.New("invalid endpoint or API call")
|
||||
|
||||
func checkResponse(response *http.Response) error {
|
||||
if response.StatusCode == 404 {
|
||||
return errors.New("invalid endpoint or API call")
|
||||
} else if response.StatusCode == 403 {
|
||||
if response.StatusCode == http.StatusNotFound {
|
||||
return errNotFound
|
||||
} else if response.StatusCode == http.StatusUnauthorized {
|
||||
return errors.New("invalid API key")
|
||||
} else if response.StatusCode != 200 {
|
||||
} else if response.StatusCode != http.StatusOK {
|
||||
data, err := responseToBArray(response)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -8,6 +8,7 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@@ -35,7 +36,10 @@ var debugCommand = cli.Command{
|
||||
|
||||
func debugFile() cli.ActionFunc {
|
||||
return func(c *cli.Context) error {
|
||||
return indexDumpOutput(fmt.Sprintf("debug/file?folder=%v&file=%v", c.Args()[0], normalizePath(c.Args()[1])))(c)
|
||||
query := make(url.Values)
|
||||
query.Set("folder", c.Args()[0])
|
||||
query.Set("file", normalizePath(c.Args()[1]))
|
||||
return indexDumpOutput("debug/file?" + query.Encode())(c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-30
@@ -8,13 +8,13 @@ package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/flynn-archive/go-shlex"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
@@ -97,38 +97,41 @@ func Run() error {
|
||||
operationCommand,
|
||||
errorsCommand,
|
||||
debugCommand,
|
||||
{
|
||||
Name: "-",
|
||||
HideHelp: true,
|
||||
Usage: "Read commands from stdin",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
if ctx.NArg() > 0 {
|
||||
return errors.New("command does not expect any arguments")
|
||||
}
|
||||
|
||||
// Drop the `-` not to recurse into self.
|
||||
args := make([]string, len(os.Args)-1)
|
||||
copy(args, os.Args)
|
||||
|
||||
fmt.Println("Reading commands from stdin...", args)
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
input, err := shlex.Split(scanner.Text())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing input")
|
||||
}
|
||||
if len(input) == 0 {
|
||||
continue
|
||||
}
|
||||
err = app.Run(append(args, input...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return scanner.Err()
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
tty := isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd())
|
||||
if !tty {
|
||||
// Not a TTY, consume from stdin
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
input, err := shlex.Split(scanner.Text())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing input")
|
||||
}
|
||||
if len(input) == 0 {
|
||||
continue
|
||||
}
|
||||
err = app.Run(append(os.Args, input...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = scanner.Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = app.Run(os.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return app.Run(os.Args)
|
||||
}
|
||||
|
||||
func parseFlags(c *preCli) error {
|
||||
|
||||
@@ -48,6 +48,9 @@ func indexDumpOutput(url string) cli.ActionFunc {
|
||||
return err
|
||||
}
|
||||
response, err := client.Get(url)
|
||||
if errors.Is(err, errNotFound) {
|
||||
return errors.New("not found (folder/file not in database)")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+20
-17
@@ -47,32 +47,32 @@ func main() {
|
||||
func runAggregation(db *sql.DB) {
|
||||
since := maxIndexedDay(db, "VersionSummary")
|
||||
log.Println("Aggregating VersionSummary data since", since)
|
||||
rows, err := aggregateVersionSummary(db, since)
|
||||
rows, err := aggregateVersionSummary(db, since.Add(24*time.Hour))
|
||||
if err != nil {
|
||||
log.Fatalln("aggregate:", err)
|
||||
log.Println("aggregate:", err)
|
||||
}
|
||||
log.Println("Inserted", rows, "rows")
|
||||
|
||||
log.Println("Aggregating UserMovement data")
|
||||
rows, err = aggregateUserMovement(db)
|
||||
if err != nil {
|
||||
log.Fatalln("aggregate:", err)
|
||||
log.Println("aggregate:", err)
|
||||
}
|
||||
log.Println("Inserted", rows, "rows")
|
||||
|
||||
log.Println("Aggregating Performance data")
|
||||
since = maxIndexedDay(db, "Performance")
|
||||
rows, err = aggregatePerformance(db, since)
|
||||
log.Println("Aggregating Performance data since", since)
|
||||
rows, err = aggregatePerformance(db, since.Add(24*time.Hour))
|
||||
if err != nil {
|
||||
log.Fatalln("aggregate:", err)
|
||||
log.Println("aggregate:", err)
|
||||
}
|
||||
log.Println("Inserted", rows, "rows")
|
||||
|
||||
log.Println("Aggregating BlockStats data")
|
||||
since = maxIndexedDay(db, "BlockStats")
|
||||
rows, err = aggregateBlockStats(db, since)
|
||||
log.Println("Aggregating BlockStats data since", since)
|
||||
rows, err = aggregateBlockStats(db, since.Add(24*time.Hour))
|
||||
if err != nil {
|
||||
log.Fatalln("aggregate:", err)
|
||||
log.Println("aggregate:", err)
|
||||
}
|
||||
log.Println("Inserted", rows, "rows")
|
||||
}
|
||||
@@ -163,7 +163,7 @@ func setupDB(db *sql.DB) error {
|
||||
|
||||
func maxIndexedDay(db *sql.DB, table string) time.Time {
|
||||
var t time.Time
|
||||
row := db.QueryRow("SELECT MAX(Day) FROM " + table)
|
||||
row := db.QueryRow("SELECT MAX(DATE_TRUNC('day', Day)) FROM " + table)
|
||||
err := row.Scan(&t)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
@@ -179,8 +179,8 @@ func aggregateVersionSummary(db *sql.DB, since time.Time) (int64, error) {
|
||||
COUNT(*) AS Count
|
||||
FROM ReportsJson
|
||||
WHERE
|
||||
DATE_TRUNC('day', Received) > $1
|
||||
AND DATE_TRUNC('day', Received) < DATE_TRUNC('day', NOW())
|
||||
Received > $1
|
||||
AND Received < DATE_TRUNC('day', NOW())
|
||||
AND Report->>'version' like 'v_.%'
|
||||
GROUP BY Day, Ver
|
||||
);
|
||||
@@ -198,7 +198,8 @@ func aggregateUserMovement(db *sql.DB) (int64, error) {
|
||||
Report->>'uniqueID'
|
||||
FROM ReportsJson
|
||||
WHERE
|
||||
DATE_TRUNC('day', Received) < DATE_TRUNC('day', NOW())
|
||||
Report->>'uniqueID' IS NOT NULL
|
||||
AND Received < DATE_TRUNC('day', NOW())
|
||||
AND Report->>'version' like 'v_.%'
|
||||
ORDER BY Day
|
||||
`)
|
||||
@@ -283,9 +284,11 @@ func aggregatePerformance(db *sql.DB, since time.Time) (int64, error) {
|
||||
AVG((Report->>'memoryUsageMiB')::numeric) As MemoryUsageMiB
|
||||
FROM ReportsJson
|
||||
WHERE
|
||||
DATE_TRUNC('day', Received) > $1
|
||||
AND DATE_TRUNC('day', Received) < DATE_TRUNC('day', NOW())
|
||||
Received > $1
|
||||
AND Received < DATE_TRUNC('day', NOW())
|
||||
AND Report->>'version' like 'v_.%'
|
||||
/* Some custom implementation reported bytes when we expect megabytes, cap at petabyte */
|
||||
AND (Report->>'memorySize')::numeric < 1073741824
|
||||
GROUP BY Day
|
||||
);
|
||||
`, since)
|
||||
@@ -312,8 +315,8 @@ func aggregateBlockStats(db *sql.DB, since time.Time) (int64, error) {
|
||||
SUM((Report->'blockStats'->>'copyElsewhere')::numeric) AS CopyElsewhere
|
||||
FROM ReportsJson
|
||||
WHERE
|
||||
DATE_TRUNC('day', Received) > $1
|
||||
AND DATE_TRUNC('day', Received) < DATE_TRUNC('day', NOW())
|
||||
Received > $1
|
||||
AND Received < DATE_TRUNC('day', NOW())
|
||||
AND (Report->>'urVersion')::numeric >= 3
|
||||
AND Report->>'version' like 'v_.%'
|
||||
AND Report->>'version' NOT LIKE 'v0.14.40%'
|
||||
|
||||
@@ -1,57 +1,58 @@
|
||||
module github.com/syncthing/syncthing
|
||||
|
||||
require (
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210218141631-7468b85d810a
|
||||
github.com/AudriusButkevicius/recli v0.0.5
|
||||
github.com/alecthomas/kong v0.2.12
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210511165305-e9aaf99ab213
|
||||
github.com/AudriusButkevicius/recli v0.0.6
|
||||
github.com/alecthomas/kong v0.2.16
|
||||
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e
|
||||
github.com/calmh/xdr v1.1.0
|
||||
github.com/ccding/go-stun v0.1.3
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect
|
||||
github.com/certifi/gocertifi v0.0.0-20210429200110-83314bf6d27c // indirect
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/d4l3k/messagediff v1.2.1
|
||||
github.com/dchest/siphash v1.2.2
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||
github.com/getsentry/raven-go v0.2.0
|
||||
github.com/go-ldap/ldap/v3 v3.2.4
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.3.0
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/greatroar/blobloom v0.5.0
|
||||
github.com/hashicorp/golang-lru v0.5.1
|
||||
github.com/jackpal/gateway v1.0.6
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/greatroar/blobloom v0.7.0
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/jackpal/gateway v1.0.7
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/lib/pq v1.8.0
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
||||
github.com/lib/pq v1.10.1
|
||||
github.com/lucas-clemente/quic-go v0.19.3
|
||||
github.com/maruel/panicparse v1.5.1
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0 // indirect
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/maruel/panicparse v1.6.1
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0
|
||||
github.com/minio/sha256-simd v1.0.0
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/gomega v1.10.3 // indirect
|
||||
github.com/oschwald/geoip2-golang v1.4.0
|
||||
github.com/oschwald/geoip2-golang v1.5.0
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.8.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/shirou/gopsutil/v3 v3.20.11
|
||||
github.com/shirou/gopsutil/v3 v3.21.4
|
||||
github.com/syncthing/notify v0.0.0-20210308121556-f45149b04939
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7
|
||||
github.com/thejerf/suture/v4 v4.0.0
|
||||
github.com/urfave/cli v1.22.4
|
||||
github.com/thejerf/suture/v4 v4.0.1
|
||||
github.com/urfave/cli v1.22.5
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
|
||||
golang.org/x/text v0.3.4
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887
|
||||
golang.org/x/text v0.3.6
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
golang.org/x/tools v0.1.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
)
|
||||
|
||||
go 1.14
|
||||
|
||||
@@ -7,10 +7,10 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210218141631-7468b85d810a h1:dUzIAgRmHLIUU0PT+OJ0X1WI5j1hlLbf+G420gUjIQg=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210218141631-7468b85d810a/go.mod h1:1N0EEx/irz4B1qV17wW82TFbjQrE7oX316Cki6eDY0Q=
|
||||
github.com/AudriusButkevicius/recli v0.0.5 h1:xUa55PvWTHBm17T6RvjElRO3y5tALpdceH86vhzQ5wg=
|
||||
github.com/AudriusButkevicius/recli v0.0.5/go.mod h1:Q2E26yc6RvWWEz/TJ/goUp6yXvipYdJI096hpoaqsNs=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210511165305-e9aaf99ab213 h1:9E6vGKdipZ+AAkU19TUb5JQKMf44CGAYMtXDAyfonO4=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20210511165305-e9aaf99ab213/go.mod h1:EEEtt5r8y0gGHlRFF2+cLx0WUy/rKHnjALmom5E0+74=
|
||||
github.com/AudriusButkevicius/recli v0.0.6 h1:hY9KH09vIbx0fYpkvdWbvnh67uDiuJEVDGhXlefysDQ=
|
||||
github.com/AudriusButkevicius/recli v0.0.6/go.mod h1:Nhfib1j/VFnLrXL9cHgA+/n2O6P5THuWelOnbfPNd78=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
@@ -21,8 +21,8 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUW
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/kong v0.2.12 h1:X3kkCOXGUNzLmiu+nQtoxWqj4U2a39MpSJR3QdQXOwI=
|
||||
github.com/alecthomas/kong v0.2.12/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/kong v0.2.16 h1:F232CiYSn54Tnl1sJGTeHmx4vJDNLVP2b9yCVMOQwHQ=
|
||||
github.com/alecthomas/kong v0.2.16/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -50,14 +50,12 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7
|
||||
github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE=
|
||||
github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/ccding/go-stun v0.1.2 h1:1CZhjVwfyO/jGxk06a+0OSOGBWZu588kuZQQO4nihsw=
|
||||
github.com/ccding/go-stun v0.1.2/go.mod h1:3FK1bMar37f7jqVY7q/63k3OMX1c47pGCufzt3X0sYE=
|
||||
github.com/ccding/go-stun v0.1.3 h1:uEAFsxqPBuo4tvILfloEHUBO3b4BlEAMnx2PZdh54jE=
|
||||
github.com/ccding/go-stun v0.1.3/go.mod h1:cCZjJ1J3WFSJV6Wj8Y9Di8JMTsEXh6uv2eNmLzKaUeM=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/certifi/gocertifi v0.0.0-20210429200110-83314bf6d27c h1:Tt0GPSnn14HRN/+db/WGBPDnUykj4b7EBNtBdHVQFiY=
|
||||
github.com/certifi/gocertifi v0.0.0-20210429200110-83314bf6d27c/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
@@ -72,8 +70,9 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
|
||||
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
@@ -106,14 +105,15 @@ github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JY
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 h1:u7utq56RUFiynqUzgVMFDymapcOtQ/MZkh3H4QYkxag=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-ldap/ldap/v3 v3.2.4 h1:PFavAq2xTgzo/loE8qNXcQaofAaqIpI4WgaLdv+1l3E=
|
||||
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ=
|
||||
github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
@@ -127,20 +127,23 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
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.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -150,8 +153,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
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.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/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -160,8 +165,11 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
|
||||
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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -176,12 +184,13 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/greatroar/blobloom v0.5.0 h1:jNbCsgDpZ23AI6jgZsXm7oFatkFaLCxr+ZWzlYasONU=
|
||||
github.com/greatroar/blobloom v0.5.0/go.mod h1:M+yFtr/P96aNZYDYowvNWL3WdDluSMK2PPPHN49LMw8=
|
||||
github.com/greatroar/blobloom v0.7.0 h1:gZXk/iFa20AgD3merUnWBIJmsvUJTsTJExO6+7N7Mlw=
|
||||
github.com/greatroar/blobloom v0.7.0/go.mod h1:M+yFtr/P96aNZYDYowvNWL3WdDluSMK2PPPHN49LMw8=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
@@ -198,8 +207,9 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
@@ -208,8 +218,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk=
|
||||
github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM=
|
||||
github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
@@ -228,8 +238,11 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -238,8 +251,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.1 h1:6VXZrLU0jHBYyAqrSPa+MgPfnSvTPuMgK+k0o5kVFWo=
|
||||
github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lucas-clemente/quic-go v0.19.3 h1:eCDQqvGBB+kCTkA0XrAFtNe81FMa0/fn4QSoeAbmiF4=
|
||||
@@ -252,10 +265,13 @@ github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl5
|
||||
github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07VxbSabxn5A5gZQ=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/maruel/panicparse v1.5.1 h1:hUPcXI7ubtEqj/k+P34KsHQqb86zuVk7zBfkP6tBBPc=
|
||||
github.com/maruel/panicparse v1.5.1/go.mod h1:aOutY/MUjdj80R0AEVI9qE2zHqig+67t2ffUDDiLzAM=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.4 h1:RehYMOyRW8hPVEja1KBVsFVNSm35Jj9Mvs5yNoZZ28A=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/maruel/panicparse v1.6.1 h1:803MjBzGcUgE1vYgg3UMNq3G1oyYeKkMu3t6hBS97x0=
|
||||
github.com/maruel/panicparse v1.6.1/go.mod h1:uoxI4w9gJL6XahaYPMq/z9uadrdr1SyHuQwV2q80Mm0=
|
||||
github.com/maruel/panicparse/v2 v2.1.1/go.mod h1:AeTWdCE4lcq8OKsLb6cHSj1RWHVSnV9HBCk7sKLF4Jg=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
@@ -265,11 +281,11 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0 h1:8E6DrFvII6QR4eJ3PkFvV+lc03P+2qwqTPLm1ax7694=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0/go.mod h1:fcEyUyXZXoV4Abw8DX0t7wyL8mCDxXyU4iAFZfT3IHw=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
@@ -321,10 +337,10 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/oschwald/geoip2-golang v1.4.0 h1:5RlrjCgRyIGDz/mBmPfnAF4h8k0IAcRv9PvrpOfz+Ug=
|
||||
github.com/oschwald/geoip2-golang v1.4.0/go.mod h1:8QwxJvRImBH+Zl6Aa6MaIcs5YdlZSTKtzmPGzQqi9ng=
|
||||
github.com/oschwald/maxminddb-golang v1.6.0 h1:KAJSjdHQ8Kv45nFIbtoLGrGWqHFajOIm7skTyz/+Dls=
|
||||
github.com/oschwald/maxminddb-golang v1.6.0/go.mod h1:DUJFucBg2cvqx42YmDa/+xHvb0elJtOm3o4aFQ/nb/w=
|
||||
github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw=
|
||||
github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
@@ -347,8 +363,8 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
|
||||
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
|
||||
github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg=
|
||||
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -361,34 +377,36 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
|
||||
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y=
|
||||
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil/v3 v3.20.11 h1:NeVf1K0cgxsWz+N3671ojRptdgzvp7BXL3KV21R0JnA=
|
||||
github.com/shirou/gopsutil/v3 v3.20.11/go.mod h1:igHnfak0qnw1biGeI2qKQvu0ZkwvEkUcCLlYhZzdr/4=
|
||||
github.com/shirou/gopsutil/v3 v3.21.4 h1:XB/+p+kVnyYLuPHCfa99lxz2aJyvVhnyd+FxZqH/k7M=
|
||||
github.com/shirou/gopsutil/v3 v3.21.4/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
@@ -409,7 +427,6 @@ github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
@@ -432,25 +449,29 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syncthing/notify v0.0.0-20210308121556-f45149b04939 h1:InjitJPCBfhc1/DP0Z8OglJq5qvQD+J0o64TFyenf68=
|
||||
github.com/syncthing/notify v0.0.0-20210308121556-f45149b04939/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7 h1:udtnv1cokhJYqnUfCMCppJ71bFN9VKfG1BQ6UsYZnx8=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/thejerf/suture/v4 v4.0.0 h1:GX3X+1Qaewtj9flL2wgoTBfLA5NcmrCY39TJRpPbUrI=
|
||||
github.com/thejerf/suture/v4 v4.0.0/go.mod h1:g0e8vwskm9tI0jRjxrnA6lSr0q6OfPdWJVX7G5bVWRs=
|
||||
github.com/thejerf/suture/v4 v4.0.1 h1:CLnC1wxLAiHA5zTbbvhSWMupVuGe5ZJ7YddWE3lvb4M=
|
||||
github.com/thejerf/suture/v4 v4.0.1/go.mod h1:g0e8vwskm9tI0jRjxrnA6lSr0q6OfPdWJVX7G5bVWRs=
|
||||
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
||||
github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
|
||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
@@ -478,8 +499,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -489,6 +510,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -510,6 +532,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/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-20200520004742-59133d7f0dd7/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=
|
||||
@@ -517,8 +540,9 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -531,6 +555,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
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-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/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -560,29 +585,35 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
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.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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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=
|
||||
@@ -595,7 +626,9 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/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-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -619,6 +652,7 @@ google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRn
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
@@ -630,14 +664,17 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
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.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
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=
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Натиснете, за да видите грешки при откриването",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Затвори",
|
||||
"Command": "Команда",
|
||||
"Comment, when used at the start of a line": "Коментар, използван в началото на реда",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Помощ",
|
||||
"Home page": "Начална страница",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Игнорирай",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Clica per a vore els fallos en el descobriment",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Tancar",
|
||||
"Command": "Comando",
|
||||
"Comment, when used at the start of a line": "Comentar, quant s'utilitza al principi d'una línia",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Ajuda",
|
||||
"Home page": "Pàgina inicial",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignorar",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Mazání verzí",
|
||||
"Cleanup Interval": "Interval mazání",
|
||||
"Click to see discovery failures": "Kliknutím zobrazíte nezdary při objevování",
|
||||
"Click to see full identification string and QR code.": "Kliknutím zobrazíte úplnou identifikaci a QR kód.",
|
||||
"Close": "Zavřít",
|
||||
"Command": "Příkaz",
|
||||
"Comment, when used at the start of a line": "Pokud použito na jeho začátku, je řádek považován za komentář",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Nápověda",
|
||||
"Home page": "Domovská stránka",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Nicméně Vaše současná nastavení značí, že si nepřejete funkci povolit. Automatické hlášení pádů tedy bylo vypnuto.",
|
||||
"Identification": "Identifikace",
|
||||
"If untrusted, enter encryption password": "V případě nedůvěryhodnosti zadat šifrovací heslo",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Pokud chcete ostatním uživatelům tohoto počítače zabránit v přístupu k Syncthing (a skrze něj tedy ke svým souborům), zvažte nastavení ověřování se.",
|
||||
"Ignore": "Ignorovat",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"Advanced": "Avanceret",
|
||||
"Advanced Configuration": "Avanceret konfiguration",
|
||||
"All Data": "Alt data",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Alle mapper delt med denne enhed, skal beskyttes med adgangskode, således at alle sendte data er ikke-læsbare uden den angivne adgangskode.",
|
||||
"Allow Anonymous Usage Reporting?": "Tillad anonym brugerstatistik?",
|
||||
"Allowed Networks": "Tilladte netværk",
|
||||
"Alphabetic": "Alfabetisk",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Rydder op i versioner",
|
||||
"Cleanup Interval": "Ryd op interval",
|
||||
"Click to see discovery failures": "Klik for at se opdagelsesfejl",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Luk",
|
||||
"Command": "Kommando",
|
||||
"Comment, when used at the start of a line": "Kommentar, når den bruges i starten af en linje",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Hjælp",
|
||||
"Home page": "Hjem",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Hvis ikke troværdig, indtast krypteringsadgangskode",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignorér",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Versionen bereinigen",
|
||||
"Cleanup Interval": "Bereinigungsintervall",
|
||||
"Click to see discovery failures": "Klick um Gerätesuchfehler anzuzeigen",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Schließen",
|
||||
"Command": "Befehl",
|
||||
"Comment, when used at the start of a line": "Kommentar, wenn am Anfang der Zeile benutzt.",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Hilfe",
|
||||
"Home page": "Homepage",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ihre aktuellen Einstellungen weisen jedoch daraufhin, dass Sie die Aktivierung möglicherweise nicht wünschen. Wir haben die automatischen Absturzberichte für Sie deaktiviert.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Wenn nicht vertraut, geben Sie das Verschlüsselungspasswort ein",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Falls Sie andere Benutzer dieses Computers daran hindern möchten auf Syncthing und somit ihren Dateien Zugriff zu haben, setzen Sie bitte einen Benutzernamen und Passwort.",
|
||||
"Ignore": "Ignorieren",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Πατήστε για να δείτε τις αποτυχίες ανεύρεσης συσκευών",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Τέλος",
|
||||
"Command": "Εντολή",
|
||||
"Comment, when used at the start of a line": "Σχόλιο, όταν χρησιμοποιείται στην αρχή μιας γραμμής",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Βοήθεια",
|
||||
"Home page": "Αρχική σελίδα",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ωστόσο, σύμφωνα με τις τρέχουσες ρυθμίσεις σας, μάλλον δεν επιθυμείτε αυτή τη λειτουργία. Οι αναφορές σφαλμάτων απενεργοποιήθηκαν.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Αγνόησε",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Close",
|
||||
"Command": "Command",
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Home page",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignore",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Close",
|
||||
"Command": "Command",
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Home page",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignore",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Close",
|
||||
"Command": "Command",
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
@@ -93,6 +94,8 @@
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
"Dismiss": "Dismiss",
|
||||
"Do not add it to the ignore list, so this notification may recurr.": "Do not add it to the ignore list, so this notification may recurr.",
|
||||
"Do not restore": "Do not restore",
|
||||
"Do not restore all": "Do not restore all",
|
||||
"Do you want to enable watching for changes for all your folders?": "Do you want to enable watching for changes for all your folders?",
|
||||
@@ -153,6 +156,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Home page",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignore",
|
||||
@@ -225,6 +229,7 @@
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "Permanently add it to the ignore list, suppressing further notifications.",
|
||||
"Permissions": "Permissions",
|
||||
"Please consult the release notes before performing a major upgrade.": "Please consult the release notes before performing a major upgrade.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Please set a GUI Authentication User and Password in the Settings dialog.",
|
||||
@@ -284,6 +289,8 @@
|
||||
"Sharing": "Sharing",
|
||||
"Show ID": "Show ID",
|
||||
"Show QR": "Show QR",
|
||||
"Show detailed discovery status": "Show detailed discovery status",
|
||||
"Show detailed listener status": "Show detailed listener status",
|
||||
"Show diff with previous version": "Show diff with previous version",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
|
||||
@@ -293,7 +300,9 @@
|
||||
"Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)",
|
||||
"Size": "Size",
|
||||
"Smallest First": "Smallest First",
|
||||
"Some discovery methods could not be established for finding other devices or announcing this device:": "Some discovery methods could not be established for finding other devices or announcing this device:",
|
||||
"Some items could not be restored:": "Some items could not be restored:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "Some listening addresses could not be enabled to accept connections:",
|
||||
"Source Code": "Source Code",
|
||||
"Stable releases and release candidates": "Stable releases and release candidates",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
|
||||
@@ -310,6 +319,8 @@
|
||||
"Syncthing has been shut down.": "Syncthing has been shut down.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing includes the following software or portions thereof:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing is Free and Open Source Software licensed as MPL v2.0.",
|
||||
"Syncthing is listening on the following network addresses for connection attempts from other devices:": "Syncthing is listening on the following network addresses for connection attempts from other devices:",
|
||||
"Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.": "Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.",
|
||||
"Syncthing is restarting.": "Syncthing is restarting.",
|
||||
"Syncthing is upgrading.": "Syncthing is upgrading.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
@@ -334,6 +345,7 @@
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.",
|
||||
"The following items could not be synchronized.": "The following items could not be synchronized.",
|
||||
"The following items were changed locally.": "The following items were changed locally.",
|
||||
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "The following methods are used to discover other devices on the network and announce this device to be found by others:",
|
||||
"The following unexpected items were found.": "The following unexpected items were found.",
|
||||
"The interval must be a positive number of seconds.": "The interval must be a positive number of seconds.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
@@ -351,6 +363,7 @@
|
||||
"They are retried automatically and will be synced when the error is resolved.": "They are retried automatically and will be synced when the error is resolved.",
|
||||
"This Device": "This Device",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
|
||||
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.",
|
||||
"This is a major version upgrade.": "This is a major version upgrade.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
|
||||
"Time": "Time",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Alklaku por vidi malsukcesajn malkovrojn",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Fermi",
|
||||
"Command": "Komando",
|
||||
"Comment, when used at the start of a line": "Komento, kiam uzita ĉe la komenco de lineo",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Helpo",
|
||||
"Home page": "Hejma paĝo",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignoru",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Limpiando Versiones",
|
||||
"Cleanup Interval": "Intervalo de Limpieza",
|
||||
"Click to see discovery failures": "Clica para ver fallos de descubrimiento.",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Cerrar",
|
||||
"Command": "Acción",
|
||||
"Comment, when used at the start of a line": "Comentar, cuando se usa al comienzo de una línea",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Ayuda",
|
||||
"Home page": "Página de inicio",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Sin embargo, su configuración actual indica que puede no querer habilitarlo. Hemos deshabilitado el informe automático de errores por usted.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Si no es de confianza, ingrese la contraseña de cifrado.",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Si quiere impedirle a otros usuarios de esta computadora acceder a Syncthing y, a través de este, a sus archivos, considere establecer la autenticación.",
|
||||
"Ignore": "Ignorar",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Limpiando Versiones",
|
||||
"Cleanup Interval": "Intervalo de Limpieza",
|
||||
"Click to see discovery failures": "Clica para ver fallos de descubrimiento.",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Cerrar",
|
||||
"Command": "Acción",
|
||||
"Comment, when used at the start of a line": "Comentar, cuando se usa al comienzo de una línea",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Ayuda",
|
||||
"Home page": "Página de inicio",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Sin embargo, su configuración actual indica que puede no quererla activa. Hemos desactivado los informes automáticos de fallos por usted.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Si no es de confianza, introduzca la contraseña de cifrado",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Si desea evitar que otros usuarios de esta computadora accedan a Syncthing y, a través de él, a sus archivos, considere establecer la autenticación.",
|
||||
"Ignore": "Ignorar",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Bertsio garbiketa",
|
||||
"Cleanup Interval": "Garbiketa-tartea",
|
||||
"Click to see discovery failures": "Klik egin hutsegiteak ikusteko",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Hetsi",
|
||||
"Command": "Kontrolagailua",
|
||||
"Comment, when used at the start of a line": "Komentarioa, lerro baten hastean delarik",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Laguntza",
|
||||
"Home page": "Harrera",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Hala ere, zure ezarpenen arabera baliteke aktibatu nahi ez izatea. Txostenen bidalketa automatikoa desaktibatu dugu zuretzat.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Fidagarria ez bada, idatzi enkriptatzeko pasahitza",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Ordenagailu honetako beste erabiltzaile batzuk Syncthing-era eta haren bidez zure fitxategietara sartzea eragotzi nahi baduzu, kontuan izan autentifikazioa konfiguratu behar duzula.",
|
||||
"Ignore": "Kontuan ez hartu",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Klikkaa nähdäksesi etsinnässä tapahtuneet virheet",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Sulje",
|
||||
"Command": "Komento",
|
||||
"Comment, when used at the start of a line": "Kommentti, käytettäessä rivin alussa",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Apua",
|
||||
"Home page": "Kotisivu",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ohita",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Purge des versions",
|
||||
"Cleanup Interval": "Intervalle de purge",
|
||||
"Click to see discovery failures": "Voir les échecs de découverte",
|
||||
"Click to see full identification string and QR code.": "Voir la chaîne d'identification complète et le code QR.",
|
||||
"Close": "Fermer",
|
||||
"Command": "Commande",
|
||||
"Comment, when used at the start of a line": "Commentaire lorsque utilisé en début de ligne",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Aide (en anglais)",
|
||||
"Home page": "Page d'accueil",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Cependant, vos réglages indiquent que vous pourriez souhaiter ne pas l'activer. Nous avons désactivé pour vous l'envoi automatique des rapports.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Entrez un mot de passe pour chiffrer",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Si vous voulez empêcher d'autres utilisateurs de cet appareil à accéder à Syncthing, et via Syncthing à vos fichiers, prenez quelques secondes pour régler l'authentification. ",
|
||||
"Ignore": "Refuser",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Klik om ûntdekkingsflaters te besjen",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Slute",
|
||||
"Command": "Kommando",
|
||||
"Comment, when used at the start of a line": "Kommentaar, wannear as brûkt by it begjin fan in rige",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Hiemstee",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Lykwols, jo aktuele ynstellings litte sjen dat jo it miskien net oan sette wol. Wy hawwe automatysk rapportearjen fan fêstrinnen foar jo útsetten.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Negearje",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Tisztító verziók",
|
||||
"Cleanup Interval": "Tisztítási intervallum",
|
||||
"Click to see discovery failures": "Kattints ide a felfedezési hibák megtekintéséhez",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Bezárás",
|
||||
"Command": "Parancs",
|
||||
"Comment, when used at the start of a line": "Megjegyzés, a sor elején használva",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Súgó",
|
||||
"Home page": "Főoldal",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "A jelenlegi beállítások azonban azt jelzik, hogy nem kívánja engedélyezni. Az automatikus összeomlás-jelentés ezért letiltásra került.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Ha nem megbízható, adjon hozzá titkosítási jelszót",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Ha kívánatos, hogy a számítógép többi felhasználója ne tudja elérni a Syncthinget, sem annak fájljait, érdemes az azonosítást beállítani.",
|
||||
"Ignore": "Mellőzés",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Il controllo versione è gestito da un comando esterno. Quest'ultimo deve rimuovere il file dalla cartella condivisa. Se il percorso dell'applicazione contiene spazi, deve essere indicato tra virgolette.",
|
||||
"Anonymous Usage Reporting": "Statistiche Anonime di Utilizzo",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Il formato delle statistiche anonime di utilizzo è cambiato. Vuoi passare al nuovo formato?",
|
||||
"Are you sure you want to continue?": "Are you sure you want to continue?",
|
||||
"Are you sure you want to continue?": "Sei sicuro di voler continuare?",
|
||||
"Are you sure you want to permanently delete all these files?": "Sei sicuro di voler eliminare definitivamente tutti questi file?",
|
||||
"Are you sure you want to remove device {%name%}?": "Sei sicuro di voler rimuovere il dispositivo {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Sei sicuro di voler rimuovere la cartella {{label}}?",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Pulizia Versioni",
|
||||
"Cleanup Interval": "Intervallo di Pulizia",
|
||||
"Click to see discovery failures": "Clicca per vedere gli errori di rilevamento",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Chiudi",
|
||||
"Command": "Comando",
|
||||
"Comment, when used at the start of a line": "Per commentare, va inserito all'inizio di una riga",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Aiuto",
|
||||
"Home page": "Pagina home",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Tuttavia, le impostazioni correnti indicano che potresti non volerla attiva. Abbiamo disattivato la segnalazione automatica degli arresti anomali per te.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Se non attendibile, immettere la password di crittografia",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Se vuoi impedire ad altri utenti di questo computer di accedere a Syncthing e attraverso di esso ai tuoi file, prendi in considerazione la configurazione dell'autenticazione.",
|
||||
"Ignore": "Ignora",
|
||||
@@ -163,7 +165,7 @@
|
||||
"Ignored at": "Ignorato a",
|
||||
"Incoming Rate Limit (KiB/s)": "Limite Velocità in Ingresso (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Una configurazione non corretta potrebbe danneggiare il contenuto delle cartelle e rendere Syncthing inoperativo.",
|
||||
"Introduced By": "Introdotto Da",
|
||||
"Introduced By": "Introdotto da",
|
||||
"Introducer": "Introduttore",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversione della condizione indicata (ad es. non escludere)",
|
||||
"Keep Versions": "Versioni Mantenute",
|
||||
@@ -378,7 +380,7 @@
|
||||
"Uptime": "Tempo di Funzionamento",
|
||||
"Usage reporting is always enabled for candidate releases.": "Le segnalazioni di utilizzo sono sempre abilitate le versioni candidate al rilascio.",
|
||||
"Use HTTPS for GUI": "Utilizza HTTPS per l'interfaccia grafica",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Utente/Password non sono stati impostati per l'autenticazione GUI. Considerane la configurazione.",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Utente/password non sono stati impostati per autenticazione GUI. Considerane la configurazione.",
|
||||
"Version": "Versione",
|
||||
"Versions": "Versioni",
|
||||
"Versions Path": "Percorso Cartella Versioni",
|
||||
@@ -386,7 +388,7 @@
|
||||
"Waiting to Clean": "In attesa di Pulizia",
|
||||
"Waiting to Scan": "In attesa di Scansione",
|
||||
"Waiting to Sync": "In attesa di Sincronizzazione",
|
||||
"Warning": "Warning",
|
||||
"Warning": "Attenzione",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Attenzione, questo percorso è una cartella superiore di una cartella esistente \"{{otherFolder}}\".",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Attenzione, questo percorso è una cartella superiore di una cartella esistente \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Attenzione, questo percorso è una sottocartella di una cartella esistente \"{{otherFolder}}\".",
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.",
|
||||
"Anonymous Usage Reporting": "匿名での使用状況レポート",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "匿名での使用状況レポートのフォーマットが変わりました。新形式でのレポートに移行しますか?",
|
||||
"Are you sure you want to continue?": "Are you sure you want to continue?",
|
||||
"Are you sure you want to permanently delete all these files?": "Are you sure you want to permanently delete all these files?",
|
||||
"Are you sure you want to continue?": "続行してもよろしいですか?",
|
||||
"Are you sure you want to permanently delete all these files?": "これらのファイルをすべて完全に削除してもよろしいですか?",
|
||||
"Are you sure you want to remove device {%name%}?": "デバイス {{name}} を削除してよろしいですか?",
|
||||
"Are you sure you want to remove folder {%label%}?": "フォルダー {{label}} を削除してよろしいですか?",
|
||||
"Are you sure you want to restore {%count%} files?": "Are you sure you want to restore {{count}} files?",
|
||||
"Are you sure you want to restore {%count%} files?": "{{count}} ファイルを復元してもよろしいですか?",
|
||||
"Are you sure you want to upgrade?": "アップグレードしてよろしいですか?",
|
||||
"Auto Accept": "自動承諾",
|
||||
"Automatic Crash Reporting": "自動クラッシュレポート",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "接続に失敗した探索サーバーを確認するにはクリックしてください",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "閉じる",
|
||||
"Command": "コマンド",
|
||||
"Comment, when used at the start of a line": "行頭で使用するとコメント行になります",
|
||||
@@ -62,12 +63,12 @@
|
||||
"Currently Shared With Devices": "現在共有中のデバイス",
|
||||
"Danger!": "危険!",
|
||||
"Debugging Facilities": "デバッグ機能",
|
||||
"Default Configuration": "Default Configuration",
|
||||
"Default Device": "Default Device",
|
||||
"Default Folder": "Default Folder",
|
||||
"Default Configuration": "デフォルトの設定",
|
||||
"Default Device": "デフォルトのデバイス",
|
||||
"Default Folder": "デフォルトのフォルダー",
|
||||
"Default Folder Path": "デフォルトのフォルダーパス",
|
||||
"Defaults": "Defaults",
|
||||
"Delete Unexpected Items": "Delete Unexpected Items",
|
||||
"Defaults": "デフォルト",
|
||||
"Delete Unexpected Items": "予期しないアイテムを削除",
|
||||
"Deleted": "削除",
|
||||
"Deselect All": "すべて選択解除",
|
||||
"Deselect devices to stop sharing this folder with.": "このフォルダの共有を停止したいデバイスがある場合は、当該デバイスの選択を解除してください。",
|
||||
@@ -102,9 +103,9 @@
|
||||
"Downloading": "ダウンロード中",
|
||||
"Edit": "編集",
|
||||
"Edit Device": "デバイスの編集",
|
||||
"Edit Device Defaults": "Edit Device Defaults",
|
||||
"Edit Device Defaults": "デバイスのデフォルトの編集",
|
||||
"Edit Folder": "フォルダーの編集",
|
||||
"Edit Folder Defaults": "Edit Folder Defaults",
|
||||
"Edit Folder Defaults": "フォルダーのデフォルトの編集",
|
||||
"Editing {%path%}.": "{{path}} を編集中",
|
||||
"Enable Crash Reporting": "クラッシュレポートを有効にする",
|
||||
"Enable NAT traversal": "NATトラバーサルを有効にする",
|
||||
@@ -153,7 +154,8 @@
|
||||
"Help": "ヘルプ",
|
||||
"Home page": "ホームページ",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "信頼しない場合、暗号化パスワードを入力",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "無視",
|
||||
"Ignore Patterns": "無視するファイル名",
|
||||
@@ -202,7 +204,7 @@
|
||||
"No File Versioning": "バージョン管理をしない",
|
||||
"No files will be deleted as a result of this operation.": "この操作を行っても、ファイルが削除されることはありません。",
|
||||
"No upgrades": "アップグレードしない",
|
||||
"Not shared": "Not shared",
|
||||
"Not shared": "非共有",
|
||||
"Notice": "通知",
|
||||
"OK": "OK",
|
||||
"Off": "オフ",
|
||||
@@ -279,7 +281,7 @@
|
||||
"Share Folder": "フォルダーを共有する",
|
||||
"Share Folders With Device": "このデバイスと共有するフォルダー",
|
||||
"Share this folder?": "このフォルダーを共有しますか?",
|
||||
"Shared Folders": "Shared Folders",
|
||||
"Shared Folders": "共有中のフォルダー",
|
||||
"Shared With": "共有中のデバイス",
|
||||
"Sharing": "共有",
|
||||
"Show ID": "IDを表示",
|
||||
@@ -367,8 +369,8 @@
|
||||
"Unknown": "不明",
|
||||
"Unshared": "非共有",
|
||||
"Unshared Devices": "非共有のデバイス",
|
||||
"Unshared Folders": "Unshared Folders",
|
||||
"Untrusted": "Untrusted",
|
||||
"Unshared Folders": "非共有のフォルダー",
|
||||
"Untrusted": "信頼しない",
|
||||
"Up to Date": "最新",
|
||||
"Updated": "更新",
|
||||
"Upgrade": "アップグレード",
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
"Allow Anonymous Usage Reporting?": "익명 사용 보고서를 보내시겠습니까?",
|
||||
"Allowed Networks": "허가된 네트워크",
|
||||
"Alphabetic": "알파벳순",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "외부 커맨드가 파일 버전을 관리합니다. 공유된 폴더에서 파일을 삭제해야 합니다. 응용 프로그램의 경로에 공백이 있으면 따옴표로 묶어야합니다.",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "외부 명령이 파일 버전을 관리합니다. 공유 폴더에서 파일을 삭제해야 합니다. 응용 프로그램의 경로에 공백이 있으면 따옴표로 묶어야 합니다.",
|
||||
"Anonymous Usage Reporting": "익명 사용 보고서",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "익명 사용 리포트의 형식이 변경되었습니다. 새 형식으로 이동 하시겠습니까?",
|
||||
"Are you sure you want to continue?": "Are you sure you want to continue?",
|
||||
"Are you sure you want to permanently delete all these files?": "Are you sure you want to permanently delete all these files?",
|
||||
"Are you sure you want to remove device {%name%}?": "{{name}} 기기를 정말로 제거하시겠습니까?",
|
||||
"Are you sure you want to remove folder {%label%}?": "{{label}} 폴더를 제거 하시겠습니까?",
|
||||
"Are you sure you want to restore {%count%} files?": "{{count}} 개의 파일을 복원 하시겠습니까?",
|
||||
"Are you sure you want to continue?": "계속하시겠습니까?",
|
||||
"Are you sure you want to permanently delete all these files?": "모든 파일을 영구 삭제하시겠습니까?",
|
||||
"Are you sure you want to remove device {%name%}?": "{{name}} 기기를 제거하시겠습니까?",
|
||||
"Are you sure you want to remove folder {%label%}?": "{{label}} 폴더를 제거하시겠습니까?",
|
||||
"Are you sure you want to restore {%count%} files?": "{{count}} 개의 파일을 복원하시겠습니까?",
|
||||
"Are you sure you want to upgrade?": "업그레이드를 하시겠습니까?",
|
||||
"Auto Accept": "자동 수락",
|
||||
"Automatic Crash Reporting": "자동 충돌 보고",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "버전 정리 중",
|
||||
"Cleanup Interval": "정리 간격",
|
||||
"Click to see discovery failures": "탐색 실패 보기",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "닫기",
|
||||
"Command": "커맨드",
|
||||
"Comment, when used at the start of a line": "명령행에서 시작을 할수 있어요.",
|
||||
@@ -58,16 +59,16 @@
|
||||
"Copied from elsewhere": "다른 곳에서 복사됨",
|
||||
"Copied from original": "원본에서 복사됨",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 the following Contributors:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "무시 패턴 만들기, {{path}}에 존재하는 파일을 덮어쓰기 합니다",
|
||||
"Currently Shared With Devices": "현재 공유된 기기들",
|
||||
"Danger!": "경고!",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "무시 패턴 생성 중, {{path}}에 존재하는 파일을 덮어 씁니다.",
|
||||
"Currently Shared With Devices": "현재 공유된 기기",
|
||||
"Danger!": "위험!",
|
||||
"Debugging Facilities": "디버깅 기능",
|
||||
"Default Configuration": "기본 설정",
|
||||
"Default Device": "기본 기기",
|
||||
"Default Folder": "기본 폴더",
|
||||
"Default Folder Path": "기본 폴더 경로",
|
||||
"Defaults": "기본 설정",
|
||||
"Delete Unexpected Items": "Delete Unexpected Items",
|
||||
"Delete Unexpected Items": "예기치 못한 항목 삭제",
|
||||
"Deleted": "삭제됨",
|
||||
"Deselect All": "모두 선택 해제",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
@@ -77,8 +78,8 @@
|
||||
"Device ID": "기기 ID",
|
||||
"Device Identification": "기기 식별자",
|
||||
"Device Name": "기기 이름",
|
||||
"Device is untrusted, enter encryption password": "Device is untrusted, enter encryption password",
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device is untrusted, enter encryption password": "신뢰하지 않는 기기, 암호화 비밀번호를 입력하세요",
|
||||
"Device rate limits": "기기 속도 제한",
|
||||
"Device that last modified the item": "항목을 마지막으로 수정 한 기기",
|
||||
"Devices": "기기",
|
||||
"Disable Crash Reporting": "충돌 보고 해제",
|
||||
@@ -87,7 +88,7 @@
|
||||
"Disabled periodic scanning and enabled watching for changes": "주기적 탐색을 사용 중지하고 변경 사항 감시 하기",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Discard",
|
||||
"Discard": "무시",
|
||||
"Disconnected": "연결 끊김",
|
||||
"Disconnected (Unused)": "연결 해제됨 (미사용)",
|
||||
"Discovered": "탐색됨",
|
||||
@@ -118,7 +119,7 @@
|
||||
"Error": "오류",
|
||||
"External File Versioning": "외부 파일 버전 관리",
|
||||
"Failed Items": "실패한 항목",
|
||||
"Failed to setup, retrying": "Failed to setup, retrying",
|
||||
"Failed to setup, retrying": "설정 적용 실패, 재시도 중",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "IPv6 네트워크에 연결되지 않은 경우 IPv6 서버에 연결 할 수 없습니다.",
|
||||
"File Pull Order": "파일 동기화 순서",
|
||||
"File Versioning": "파일 버전 관리",
|
||||
@@ -153,10 +154,11 @@
|
||||
"Help": "도움말",
|
||||
"Home page": "홈페이지",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "신뢰하지 않는 경우 암호화 비밀번호를 입력하세요",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "무시",
|
||||
"Ignore Patterns": "패턴 무시",
|
||||
"Ignore Patterns": "무시 패턴",
|
||||
"Ignore Permissions": "권한 무시",
|
||||
"Ignored Devices": "무시된 기기",
|
||||
"Ignored Folders": "무시된 폴더",
|
||||
@@ -173,15 +175,15 @@
|
||||
"Last seen": "마지막 접속",
|
||||
"Latest Change": "최신 변경",
|
||||
"Learn more": "더 알아보기",
|
||||
"Limit": "Limit",
|
||||
"Limit": "제한",
|
||||
"Listeners": "수신자",
|
||||
"Loading data...": "데이터 불러오는중...",
|
||||
"Loading...": "불러오는 중...",
|
||||
"Local Additions": "로컬 변경사항",
|
||||
"Local Additions": "로컬 변경 항목",
|
||||
"Local Discovery": "로컬 노드 검색",
|
||||
"Local State": "로컬 상태",
|
||||
"Local State (Total)": "로컬 상태 (합계)",
|
||||
"Locally Changed Items": "Locally Changed Items",
|
||||
"Locally Changed Items": "로컬 변경 항목",
|
||||
"Log": "기록",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Log tailing paused. Scroll to the bottom to continue.",
|
||||
"Logs": "기록",
|
||||
@@ -238,7 +240,7 @@
|
||||
"Random": "무작위",
|
||||
"Receive Encrypted": "암호화 수신",
|
||||
"Receive Only": "수신 전용",
|
||||
"Received data is already encrypted": "Received data is already encrypted",
|
||||
"Received data is already encrypted": "수신된 데이터는 이미 암호화되어 있습니다",
|
||||
"Recent Changes": "최근 변경",
|
||||
"Reduced by ignore patterns": "무시 패턴으로 축소",
|
||||
"Release Notes": "릴리즈 노트",
|
||||
@@ -260,7 +262,7 @@
|
||||
"Resume": "재개",
|
||||
"Resume All": "모두 재개",
|
||||
"Reused": "재개",
|
||||
"Revert Local Changes": "로컬 변경사항 복귀",
|
||||
"Revert Local Changes": "로컬 변경 항목 복원",
|
||||
"Save": "저장",
|
||||
"Scan Time Remaining": "탐색 남은 시간",
|
||||
"Scanning": "탐색 중",
|
||||
@@ -268,7 +270,7 @@
|
||||
"Select All": "모두 선택",
|
||||
"Select a version": "버전 선택",
|
||||
"Select additional devices to share this folder with.": "이 폴더를 추가로 공유할 기기를 선택하세요.",
|
||||
"Select additional folders to share with this device.": "Select additional folders to share with this device.",
|
||||
"Select additional folders to share with this device.": "이 기기와 공유할 추가 폴더를 선택하세요.",
|
||||
"Select latest version": "가장 최신 버전 선택",
|
||||
"Select oldest version": "가장 오래된 버전 선택",
|
||||
"Select the folders to share with this device.": "이 기기와 공유할 폴더를 선택합니다.",
|
||||
@@ -333,8 +335,8 @@
|
||||
"The folder path cannot be blank.": "폴더 경로는 비워 둘 수 없습니다.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "다음과 같은 간격이 사용됩니다: 첫 한 시간 동안은 버전이 매 30초마다 유지되며, 첫 하루 동안은 매 시간, 첫 한 달 동안은 매 일마다 유지됩니다. 그리고 최대 날짜까지는 버전이 매 주마다 유지됩니다.",
|
||||
"The following items could not be synchronized.": "이 항목들은 동기화 할 수 없습니다.",
|
||||
"The following items were changed locally.": "The following items were changed locally.",
|
||||
"The following unexpected items were found.": "The following unexpected items were found.",
|
||||
"The following items were changed locally.": "다음 로컬 변경 항목이 발견되었습니다.",
|
||||
"The following unexpected items were found.": "예기치 못한 항목이 발견되었습니다.",
|
||||
"The interval must be a positive number of seconds.": "간격은 초 단위의 자연수여야 합니다.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
"The maximum age must be a number and cannot be blank.": "최대 보존 기간은 숫자여야 하며 비워 둘 수 없습니다.",
|
||||
@@ -347,7 +349,7 @@
|
||||
"The rate limit must be a non-negative number (0: no limit)": "대역폭 제한 설정은 반드시 양수로 입력해야 합니다 (0: 무제한)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "재탐색 간격은 초단위이며 양수로 입력해야 합니다.",
|
||||
"There are no devices to share this folder with.": "이 폴더를 공유할 기기가 없습니다.",
|
||||
"There are no folders to share with this device.": "There are no folders to share with this device.",
|
||||
"There are no folders to share with this device.": "이 기기와 공유할 폴더가 없습니다.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "오류가 해결되면 자동적으로 동기화 됩니다.",
|
||||
"This Device": "현재 기기",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "이 설정은 해커가 손쉽게 사용자 컴퓨터의 모든 파일을 읽고 변경할 수 있도록 할 수 있습니다.",
|
||||
@@ -361,14 +363,14 @@
|
||||
"Unavailable": "불가능",
|
||||
"Unavailable/Disabled by administrator or maintainer": "운영자 또는 관리자에 의해 불가능/비활성화 됨",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unexpected Items": "Unexpected Items",
|
||||
"Unexpected items have been found in this folder.": "Unexpected items have been found in this folder.",
|
||||
"Unignore": "Unignore",
|
||||
"Unexpected Items": "예기치 못한 항목",
|
||||
"Unexpected items have been found in this folder.": "이 폴더에 예기치 못한 항목이 발견되었습니다.",
|
||||
"Unignore": "무시 취소",
|
||||
"Unknown": "알 수 없음",
|
||||
"Unshared": "공유되지 않음",
|
||||
"Unshared Devices": "공유되지 않은 기기",
|
||||
"Unshared Folders": "Unshared Folders",
|
||||
"Untrusted": "Untrusted",
|
||||
"Unshared Folders": "공유되지 않은 폴더",
|
||||
"Untrusted": "신뢰하지 않음",
|
||||
"Up to Date": "최신 데이터",
|
||||
"Updated": "업데이트 완료",
|
||||
"Upgrade": "업데이트",
|
||||
@@ -386,12 +388,12 @@
|
||||
"Waiting to Clean": "정리 대기 중",
|
||||
"Waiting to Scan": "탐색 대기 중",
|
||||
"Waiting to Sync": "동기화 대기 중",
|
||||
"Warning": "Warning",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolder}}\" 의 상위 폴더 입니다.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}}) 의 상위 폴더 입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolder}}\" 의 하위 폴더 입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}}) 의 하위 폴더 입니다.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "경고 : {{syncthingInotify}} 와 같은 외부 감시 도구를 사용하는 경우 비활성화되어 있는지 확인해야 합니다.",
|
||||
"Warning": "경고",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "경고 : 이 경로는 현재 존재하는 폴더 \"{{otherFolder}}\"의 상위 폴더입니다.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고 : 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}})의 상위 폴더입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "경고 : 이 경로는 현재 존재하는 폴더 \"{{otherFolder}}\"의 하위 폴더입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고 : 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}})의 하위 폴더입니다.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "경고 : {{syncthingInotify}}와 같은 외부 감시 도구를 사용하는 경우 비활성화되어 있는지 확인해야 합니다.",
|
||||
"Watch for Changes": "변경 사항 감시",
|
||||
"Watching for Changes": "변경 사항 감시",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Watching for changes discovers most changes without periodic scanning.",
|
||||
@@ -402,7 +404,7 @@
|
||||
"You can change your choice at any time in the Settings dialog.": "설정창 에서 언제든지 원하시는 때에 설정을 변경하는 것이 가능합니다.",
|
||||
"You can read more about the two release channels at the link below.": "이 두 개의 출시 채널에 대해 아래 링크에서 자세하게 읽어 보실 수 있습니다.",
|
||||
"You have no ignored devices.": "무시된 기기가 없습니다.",
|
||||
"You have no ignored folders.": "You have no ignored folders.",
|
||||
"You have no ignored folders.": "무시된 폴더가 없습니다.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "저장되지 않은 변경이 있습니다. 변경사항을 무시하시겠습니까?",
|
||||
"You must keep at least one version.": "최소 한 개의 버전은 유지해야 합니다.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "You should never add or change anything locally in a \"{{receiveEncrypted}}\" folder.",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Spustelėkite, norėdami pamatyti matomumo nesėkmes",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Užverti",
|
||||
"Command": "Komanda",
|
||||
"Comment, when used at the start of a line": "Komentaras naudojamas naujoje eilutėje",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Pagalba",
|
||||
"Home page": "Pagrindinis puslapis",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Vis dėlto, jūsų esami nustatymai nurodo, kad jūs, greičiausiai, nenorite turėti jas įjungtas. Mes jums išjungėme automatines ataskaitas apie strigtis.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jei norite neleisti kitiems šio kompiuterio vartotojams gauti prieigą prie Syncthing, o per ją, prieigą prie jūsų failų, tuomet apsvarstykite galimybę nusistatyti tapatybės nustatymą.",
|
||||
"Ignore": "Nepaisyti",
|
||||
@@ -361,8 +363,8 @@
|
||||
"Unavailable": "Neprieinama",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Neprieinama/Išjungta administratoriaus ar prižiūrėtojo",
|
||||
"Undecided (will prompt)": "Nenuspręsta (bus klausiama)",
|
||||
"Unexpected Items": "Unexpected Items",
|
||||
"Unexpected items have been found in this folder.": "Unexpected items have been found in this folder.",
|
||||
"Unexpected Items": "Netikėti elementai",
|
||||
"Unexpected items have been found in this folder.": "Šiame aplanke rasta netikėtų elementų.",
|
||||
"Unignore": "Nustoti nepaisyti",
|
||||
"Unknown": "Nežinoma",
|
||||
"Unshared": "Nesidalinama",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Klikk for å se oppslagsfeil",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Lukk",
|
||||
"Command": "Kommando",
|
||||
"Comment, when used at the start of a line": "Kommentar, når det blir brukt i starten av en linje.",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Hjelp",
|
||||
"Home page": "Hjemmeside",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignorer",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Versies opruimen",
|
||||
"Cleanup Interval": "Opruiminterval",
|
||||
"Click to see discovery failures": "Klikken om detectieproblemen weer te geven",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Sluiten",
|
||||
"Command": "Opdracht",
|
||||
"Comment, when used at the start of a line": "Opmerking, wanneer gebruikt aan het begin van een regel",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Startpagina",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Uw huidige instellingen geven echter aan dat u het misschien niet wilt inschakelen. We hebben de automatische crashrapportage voor u uitgeschakeld.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Indien niet vertrouwd, versleutelingswachtwoord opgeven",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Als u wilt voorkomen dat andere gebruikers op deze computer toegang krijgen tot Syncthing en daardoor uw bestanden, kunt u overwegen om authenticatie in te stellen.",
|
||||
"Ignore": "Negeren",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"Advanced": "Zaawansowane",
|
||||
"Advanced Configuration": "Zaawansowane ustawienia",
|
||||
"All Data": "Wszystkie dane",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Wszystkie foldery współdzielone z tym urządzeniem muszą być zabezpieczone hasłem, tak aby żadne przesyłane dane nie były możliwe do odczytu bez podania tego hasła.",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Wszystkie foldery współdzielone z tym urządzeniem muszą być zabezpieczone hasłem, tak aby wszystkie przesyłane dane były nie do odczytu bez podania danego hasła.",
|
||||
"Allow Anonymous Usage Reporting?": "Czy chcesz zezwolić na anonimowe statystyki użycia?",
|
||||
"Allowed Networks": "Dozwolone sieci",
|
||||
"Alphabetic": "Alfabetycznie",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Czyszczenie wersji",
|
||||
"Cleanup Interval": "Przedział czasowy czyszczenia",
|
||||
"Click to see discovery failures": "Kliknij tutaj, aby zobaczyć błędy odnajdywania",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Zamknij",
|
||||
"Command": "Polecenie",
|
||||
"Comment, when used at the start of a line": "Komentarz, jeżeli znajduje się na początku linii",
|
||||
@@ -58,7 +59,7 @@
|
||||
"Copied from elsewhere": "Skopiowane z innego miejsca ",
|
||||
"Copied from original": "Skopiowane z oryginału",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Wszelkie prawa zastrzeżone © 2014-2019 dla współtwórców:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Ustawianie wzorów ignorowania, nadpisze istniejący plik w {{path}}.",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Tworzenie wzorów ignorowania, nadpisze istniejący plik w {{path}}.",
|
||||
"Currently Shared With Devices": "Obecnie współdzielony z urządzeniami",
|
||||
"Danger!": "Niebezpieczeństwo!",
|
||||
"Debugging Facilities": "Narzędzia do debugowania",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Pomoc",
|
||||
"Home page": "Strona domowa",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Niemniej jednak, obecne ustawienia wskazują, że możesz nie chcieć włączać tej funkcji. Automatyczne zgłaszanie awarii zostało wyłączone na tym urządzeniu.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Jeżeli folder jest niezaufany, wprowadź szyfrujące hasło",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jeżeli chcesz zakazać innym użytkownikom tego komputera dostępu do Syncthing, a przez niego do swoich plików, zastanów się nad włączeniem uwierzytelniania.",
|
||||
"Ignore": "Ignoruj",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Limpando Versões",
|
||||
"Cleanup Interval": "Intervalo de Limpeza",
|
||||
"Click to see discovery failures": "Clique para ver as falhas na descoberta de dispositivos",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Fechar",
|
||||
"Command": "Comando",
|
||||
"Comment, when used at the start of a line": "Comentário, se usado no início de uma linha",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Ajuda",
|
||||
"Home page": "Página inicial",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Se o dispositivo não é confiável, digite a senha de criptografia",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignorar",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Limpando versões",
|
||||
"Cleanup Interval": "Intervalo entre limpezas",
|
||||
"Click to see discovery failures": "Clique para ver as falhas da pesquisa",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Fechar",
|
||||
"Command": "Comando",
|
||||
"Comment, when used at the start of a line": "Comentário, quando usado no início de uma linha",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Ajuda",
|
||||
"Home page": "Página do projecto",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Contudo, a sua configuração actual indica que pode não a querer activada. Nós desactivámos automaticamente o relatório de estouro para si.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Se não for fiável, insira uma senha de encriptação",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Se quiser evitar que outros utilizadores neste computador acedam ao Syncthing e, através dele, aos seus ficheiros, considere configurar a autenticação.",
|
||||
"Ignore": "Ignorar",
|
||||
|
||||
@@ -42,9 +42,10 @@
|
||||
"Bugs": "Ошибки",
|
||||
"Changelog": "Журнал изменений",
|
||||
"Clean out after": "Очистить после",
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleaning Versions": "Очистка Версий",
|
||||
"Cleanup Interval": "Интервал очистки",
|
||||
"Click to see discovery failures": "Щёлкните, чтобы посмотреть ошибки",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Закрыть",
|
||||
"Command": "Команда",
|
||||
"Comment, when used at the start of a line": "Комментарий, если используется в начале строки",
|
||||
@@ -77,7 +78,7 @@
|
||||
"Device ID": "ID устройства",
|
||||
"Device Identification": "Идентификация устройства",
|
||||
"Device Name": "Имя устройства",
|
||||
"Device is untrusted, enter encryption password": "Device is untrusted, enter encryption password",
|
||||
"Device is untrusted, enter encryption password": "Устройство ненадёжно, укажите пароль шифрования",
|
||||
"Device rate limits": "Ограничения скорости для устройства",
|
||||
"Device that last modified the item": "Устройство, последним изменившее объект",
|
||||
"Devices": "Устройства",
|
||||
@@ -102,9 +103,9 @@
|
||||
"Downloading": "Загрузка",
|
||||
"Edit": "Редактировать",
|
||||
"Edit Device": "Редактирование устройства",
|
||||
"Edit Device Defaults": "Edit Device Defaults",
|
||||
"Edit Device Defaults": "Изменить умолчания устройства",
|
||||
"Edit Folder": "Редактирование папки",
|
||||
"Edit Folder Defaults": "Edit Folder Defaults",
|
||||
"Edit Folder Defaults": "Изменить умолчания папки",
|
||||
"Editing {%path%}.": "Правка {{path}}.",
|
||||
"Enable Crash Reporting": "Включить отчёты о сбоях",
|
||||
"Enable NAT traversal": "Включить NAT traversal",
|
||||
@@ -134,8 +135,8 @@
|
||||
"Folder Label": "Ярлык папки",
|
||||
"Folder Path": "Путь к папке",
|
||||
"Folder Type": "Тип папки",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Folder type \"{{receiveEncrypted}}\" can only be set when adding a new folder.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Folder type \"{{receiveEncrypted}}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип папки \"{{receiveEncrypted}}\" может быть указан только при создании новой.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип папки \"{{receiveEncrypted}}\" не может быть изменён после добавления. Вам необходимо убрать папку, удалить или дешифровать данные на диске, а затем добавить папку заново.",
|
||||
"Folders": "Папки",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Для следующих папок произошла ошибка при запуске отслеживания изменений. Попытки будут повторяться раз в минуту, и ошибки скоро могут быть устранены. Если этого не произойдёт, попробуйте разобраться в причинах и попросите поддержки, если у вас не получится.",
|
||||
"Full Rescan Interval (s)": "Интервал полного сканирования (в секундах)",
|
||||
@@ -153,7 +154,8 @@
|
||||
"Help": "Помощь",
|
||||
"Home page": "Сайт",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ваши настройки указывают что вы не хотите, чтобы эта функция была включена. Мы отключили отправку отчетов о сбоях.",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Если ненадёжное, укажите пароль шифрования",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Если вы хотите запретить другим пользователям на этом компьютере доступ к Syncthing и через него к вашим файлам, подумайте о настройке аутентификации.",
|
||||
"Ignore": "Игнорировать",
|
||||
"Ignore Patterns": "Шаблоны игнорирования",
|
||||
@@ -328,8 +330,8 @@
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Введён недопустимый ID устройства. Он должен состоять из букв и цифр, может включать пробелы и дефисы, длина должна быть 52 или 56 символов.",
|
||||
"The folder ID cannot be blank.": "ID папки не может быть пустым.",
|
||||
"The folder ID must be unique.": "ID папки должен быть уникальным.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Содержание папки на других устройствах будет перезаписано и станет идентично этому устройству. Файлы, отсутствующие здесь, будут удалены на других устройствах.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Содержание папки на этом устройстве будет перезаписано и станет идентично другим устройствам. Новые файлы на этом устройстве будут удалены.",
|
||||
"The folder path cannot be blank.": "Путь к папке не должен быть пустым.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Используются следующие интервалы: в первый час версия меняется каждые 30 секунд, в первый день - каждый час, первые 30 дней - каждый день, после, до максимального срока - каждую неделю.",
|
||||
"The following items could not be synchronized.": "Невозможно синхронизировать следующие объекты",
|
||||
@@ -368,7 +370,7 @@
|
||||
"Unshared": "Необщедоступно",
|
||||
"Unshared Devices": "Устройства без общего доступа",
|
||||
"Unshared Folders": "Необщедоступные папки",
|
||||
"Untrusted": "Untrusted",
|
||||
"Untrusted": "Ненадёжный",
|
||||
"Up to Date": "В актуальном состоянии",
|
||||
"Updated": "Обновлено",
|
||||
"Upgrade": "Обновить",
|
||||
@@ -414,5 +416,5 @@
|
||||
"seconds": "сек.",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} хочет поделиться папкой «{{folder}}».",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} хочет поделиться папкой «{{folderlabel}}» ({{folder}}).",
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} might reintroduce this device."
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} может повторно рекомендовать это устройство."
|
||||
}
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Interval čistenia",
|
||||
"Click to see discovery failures": "Kliknite pre zobrazenie zlyhaní zisťovania.",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Zatvoriť",
|
||||
"Command": "Príkaz",
|
||||
"Comment, when used at the start of a line": "Komentár, keď použité na začiatku riadku",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Pomoc",
|
||||
"Home page": "Domovská stránka",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Ak nie je dôveryhodný, uveďte heslo na dešifrovanie",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignorovať",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Rensningsversioner",
|
||||
"Cleanup Interval": "Rensningsintervall",
|
||||
"Click to see discovery failures": "Klicka för att se upptäcktsmisslyckanden",
|
||||
"Click to see full identification string and QR code.": "Klicka för att se fullständig identifieringssträng och QR-kod.",
|
||||
"Close": "Stäng",
|
||||
"Command": "Kommando",
|
||||
"Comment, when used at the start of a line": "Kommentara, vid användning i början av en rad.",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Hjälp",
|
||||
"Home page": "Webbplats",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Dina aktuella inställningar visar dock att du kanske inte vill att den ska aktiveras. Vi har inaktiverat automatisk krasch rapportering för dig.",
|
||||
"Identification": "Identifiering",
|
||||
"If untrusted, enter encryption password": "Om opålitlig, ange krypteringslösenord",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Om du vill förhindra att andra användare på denna dator får åtkomst till Syncthing och genom det dina filer, överväg att ställa in autentisering.",
|
||||
"Ignore": "Ignorera",
|
||||
@@ -161,7 +163,7 @@
|
||||
"Ignored Devices": "Ignorerade enheter",
|
||||
"Ignored Folders": "Ignorerade mappar",
|
||||
"Ignored at": "Ignorerad vid",
|
||||
"Incoming Rate Limit (KiB/s)": "Inkommande hastighetsbegränsning (KiB/s)",
|
||||
"Incoming Rate Limit (KiB/s)": "Inkommande hastighetsgräns (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Inkorrekt konfiguration kan skada innehållet i mappen and få Syncthing att sluta fungera.",
|
||||
"Introduced By": "Introducerad av",
|
||||
"Introducer": "Introduktör",
|
||||
@@ -211,7 +213,7 @@
|
||||
"Options": "Alternativ",
|
||||
"Out of Sync": "Osynkroniserad",
|
||||
"Out of Sync Items": "Osynkroniserade objekt",
|
||||
"Outgoing Rate Limit (KiB/s)": "Utgående hastighetsbegränsning (KiB/s)",
|
||||
"Outgoing Rate Limit (KiB/s)": "Utgående hastighetsgräns (KiB/s)",
|
||||
"Override Changes": "Åsidosätt förändringar",
|
||||
"Path": "Sökväg",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Sökväg till mappen på din dator. Kommer att skapas om det inte finns. Tecknet tilde (~) kan användas som en genväg för",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Sürümleri Temizleme",
|
||||
"Cleanup Interval": "Aralığı Temizle",
|
||||
"Click to see discovery failures": "Keşif hatalarını görmek için tıklayın",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Kapat",
|
||||
"Command": "Komut",
|
||||
"Comment, when used at the start of a line": "Açıklama, bir satırın başında kullanıldığında",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Yardım",
|
||||
"Home page": "Ana Sayfa",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ancak, şu anki ayarlarınız etkinleştirilmesini istemediğinizi gösterir. Sizin için otomatik çökme bildirmeyi etkisizleştirdik.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "Eğer güvenilmezse, şifreleme parolasını girin",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Eğer bu bilgisayardaki diğer kullanıcıların Syncthing'e ve onun aracılığıyla dosyalarınıza erişmesini önlemek istiyorsanız, kimlik doğrulamasını ayarlamayı düşünün.",
|
||||
"Ignore": "Yoksay",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "Очищення версій",
|
||||
"Cleanup Interval": "Інтервал очищення",
|
||||
"Click to see discovery failures": "Клікніть, щоб переглянути помилки виявлення",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Закрити",
|
||||
"Command": "Команда",
|
||||
"Comment, when used at the start of a line": "Коментар, якщо використовується на початку рядка",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "Допомога",
|
||||
"Home page": "Домашня сторінка",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Однак ваші поточні налаштування вказують, що ви, можливо, не хочете, щоб це було ввімкнено. Ми відключили автоматичне повідомлення про аварійне завершення роботи.",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Якщо ви хочете заборонити іншим користувачам цього комп’ютера отримувати доступ до Syncthing і через нього до своїх файлів, подумайте про налаштування автентифікації.",
|
||||
"Ignore": "Ігнорувати",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"A device with that ID is already added.": "您已添加过相同 ID 的设备",
|
||||
"A negative number of days doesn't make sense.": "负数天数没有意义。",
|
||||
"A negative number of days doesn't make sense.": "天数不能为负。",
|
||||
"A new major version may not be compatible with previous versions.": "重大更新可能与之前的版本之间无法兼容",
|
||||
"API Key": "API Key",
|
||||
"About": "关于",
|
||||
@@ -18,14 +18,14 @@
|
||||
"Advanced": "高级",
|
||||
"Advanced Configuration": "高级配置",
|
||||
"All Data": "所有数据",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "与此设备共享的所有文件夹都必须有密码保护,这样所有发送的数据在没有密码的情况下是不可读的。",
|
||||
"Allow Anonymous Usage Reporting?": "允许匿名使用报告?",
|
||||
"Allowed Networks": "允许的网络",
|
||||
"Alphabetic": "字母顺序",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "外部命令接管了版本控制。该外部命令必须自行从共享文件夹中删除该文件。如果此应用程序的路径包含空格,应该用半角引号括起来。",
|
||||
"Anonymous Usage Reporting": "匿名使用报告",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "匿名使用情况的报告格式已经变更。是否要迁移到新的格式?",
|
||||
"Are you sure you want to continue?": "Are you sure you want to continue?",
|
||||
"Are you sure you want to continue?": "您确定要继续吗?",
|
||||
"Are you sure you want to permanently delete all these files?": "确认要永久删除这些文件吗?",
|
||||
"Are you sure you want to remove device {%name%}?": "您确定要移除设备 {{name}} 吗?",
|
||||
"Are you sure you want to remove folder {%label%}?": "您确定要移除文件夹 {{label}} 吗?",
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "清除版本",
|
||||
"Cleanup Interval": "清除间隔",
|
||||
"Click to see discovery failures": "点击查看设备发现错误",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "关闭",
|
||||
"Command": "命令",
|
||||
"Comment, when used at the start of a line": "注释,在行首使用",
|
||||
@@ -55,23 +56,23 @@
|
||||
"Connection Type": "连接类型",
|
||||
"Connections": "连接",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Syncthing 现在可以持续监视更改了。这将检测磁盘上的更改,然后对有修改的路径发起扫描。这样的好处是更改可以更快地传播,且需要的完整扫描会更少。",
|
||||
"Copied from elsewhere": "从其他设备复制",
|
||||
"Copied from elsewhere": "从其它设备复制",
|
||||
"Copied from original": "从源复制",
|
||||
"Copyright © 2014-2019 the following Contributors:": "版权所有 © 2014-2019 以下贡献者:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "正在创建忽略模式,覆盖位于 {{path}} 的已有文件。",
|
||||
"Currently Shared With Devices": "当前设备已共享",
|
||||
"Danger!": "危险!",
|
||||
"Debugging Facilities": "调试功能",
|
||||
"Default Configuration": "Default Configuration",
|
||||
"Default Device": "Default Device",
|
||||
"Default Folder": "Default Folder",
|
||||
"Default Configuration": "默认配置",
|
||||
"Default Device": "默认设备",
|
||||
"Default Folder": "默认文件夹",
|
||||
"Default Folder Path": "默认文件夹路径",
|
||||
"Defaults": "Defaults",
|
||||
"Delete Unexpected Items": "Delete Unexpected Items",
|
||||
"Defaults": "默认值",
|
||||
"Delete Unexpected Items": "删除特殊项目",
|
||||
"Deleted": "已删除",
|
||||
"Deselect All": "取消全选",
|
||||
"Deselect devices to stop sharing this folder with.": "反选设备以停止共享此文件夹",
|
||||
"Deselect folders to stop sharing with this device.": "Deselect folders to stop sharing with this device.",
|
||||
"Deselect folders to stop sharing with this device.": "取消选择文件夹以停止与此设备共享。",
|
||||
"Device": "设备",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "设备 \"{{name}}\"(位于 {{address}} 的 {{device}})请求连接。是否添加新设备?",
|
||||
"Device ID": "设备 ID",
|
||||
@@ -102,9 +103,9 @@
|
||||
"Downloading": "下载中",
|
||||
"Edit": "选项",
|
||||
"Edit Device": "编辑设备",
|
||||
"Edit Device Defaults": "Edit Device Defaults",
|
||||
"Edit Device Defaults": "编辑设备默认值",
|
||||
"Edit Folder": "编辑文件夹",
|
||||
"Edit Folder Defaults": "Edit Folder Defaults",
|
||||
"Edit Folder Defaults": "编辑文件夹默认值",
|
||||
"Editing {%path%}.": "正在编辑 {{path}}。",
|
||||
"Enable Crash Reporting": "启用自动发送崩溃报告",
|
||||
"Enable NAT traversal": "启用 NAT 遍历",
|
||||
@@ -134,11 +135,11 @@
|
||||
"Folder Label": "文件夹标签",
|
||||
"Folder Path": "文件夹路径",
|
||||
"Folder Type": "文件夹类型",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Folder type \"{{receiveEncrypted}}\" can only be set when adding a new folder.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Folder type \"{{receiveEncrypted}}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "只能在添加新文件夹时设置文件夹类型{{receiveEncrypted}}”",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "添加文件夹后,无法更改文件夹类型“ {{receiveEncrypted}}”。您需要删除该文件夹,删除或解密磁盘上的数据,然后再次添加该文件夹。",
|
||||
"Folders": "文件夹",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "开始监视下列文件夹时发生错误。由于每分钟都会重试,所以错误可能很快就消失。如果它们仍存在,请试着修复潜在问题,如不会则请求帮助。",
|
||||
"Full Rescan Interval (s)": "完整扫描间隔",
|
||||
"Full Rescan Interval (s)": "完整扫描间隔(秒)",
|
||||
"GUI": "图形用户界面",
|
||||
"GUI Authentication Password": "图形管理界面密码",
|
||||
"GUI Authentication User": "图形管理界面用户名",
|
||||
@@ -153,7 +154,8 @@
|
||||
"Help": "帮助",
|
||||
"Home page": "主页",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "我们已经为您关闭了自动崩溃报告发送功能,因为您当前的设置显示您可能并不想启用该功能。",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "如想更安全,请输入加密密码",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "如果要阻止此计算机上的其他用户访问Syncthing并通过它访问文件,请考虑设置身份验证。",
|
||||
"Ignore": "忽略",
|
||||
"Ignore Patterns": "忽略模式",
|
||||
@@ -165,7 +167,7 @@
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "错误的配置可能损坏您文件夹内的内容,使得 Syncthing 无法工作。",
|
||||
"Introduced By": "介绍自",
|
||||
"Introducer": "作为中介",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "对本条件取反(例如:不要排除某项)",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "反转本条件(即:不排除)",
|
||||
"Keep Versions": "保留版本数量",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "大文件优先",
|
||||
@@ -202,7 +204,7 @@
|
||||
"No File Versioning": "不启用版本控制",
|
||||
"No files will be deleted as a result of this operation.": "此操作结果不会删除任何文件。",
|
||||
"No upgrades": "无更新",
|
||||
"Not shared": "Not shared",
|
||||
"Not shared": "不共享",
|
||||
"Notice": "提示",
|
||||
"OK": "确定",
|
||||
"Off": "关闭",
|
||||
@@ -236,15 +238,15 @@
|
||||
"Preview Usage Report": "预览使用报告",
|
||||
"Quick guide to supported patterns": "支持的通配符的简单教程:",
|
||||
"Random": "随机顺序",
|
||||
"Receive Encrypted": "Receive Encrypted",
|
||||
"Receive Encrypted": "加密接收",
|
||||
"Receive Only": "仅接收",
|
||||
"Received data is already encrypted": "Received data is already encrypted",
|
||||
"Received data is already encrypted": "已加密接收到的数据",
|
||||
"Recent Changes": "最近更改",
|
||||
"Reduced by ignore patterns": "已由忽略模式缩减",
|
||||
"Release Notes": "发布说明",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "发布候选版包含最新的特性和修复。它们跟传统的 Syncthing 双周发布版类似。",
|
||||
"Remote Devices": "远程设备",
|
||||
"Remote GUI": "Remote GUI",
|
||||
"Remote GUI": "远程GUI",
|
||||
"Remove": "移除",
|
||||
"Remove Device": "移除设备",
|
||||
"Remove Folder": "移除文件夹",
|
||||
@@ -268,7 +270,7 @@
|
||||
"Select All": "全选",
|
||||
"Select a version": "选择版本",
|
||||
"Select additional devices to share this folder with.": "选择其他共享此文件夹的设备",
|
||||
"Select additional folders to share with this device.": "Select additional folders to share with this device.",
|
||||
"Select additional folders to share with this device.": "选择要与此设备共享的其它文件夹。",
|
||||
"Select latest version": "选择最新的版本",
|
||||
"Select oldest version": "选择最旧的版本",
|
||||
"Select the folders to share with this device.": "选择与该设备共享的文件夹。",
|
||||
@@ -279,7 +281,7 @@
|
||||
"Share Folder": "共享文件夹",
|
||||
"Share Folders With Device": "将指定文件夹共享给设备",
|
||||
"Share this folder?": "是否共享该文件夹?",
|
||||
"Shared Folders": "Shared Folders",
|
||||
"Shared Folders": "共享文件夹",
|
||||
"Shared With": "共享给",
|
||||
"Sharing": "共享",
|
||||
"Show ID": "显示 ID",
|
||||
@@ -302,7 +304,7 @@
|
||||
"Start Browser": "启动浏览器",
|
||||
"Statistics": "统计",
|
||||
"Stopped": "已停止",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{{receiveEncrypted}}\" too.",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "仅存储和同步加密的数据。所有连接的设备上的文件夹也需要使用相同的密码设置,或者也必须设置为“ {{receiveEncrypted}}”类型。",
|
||||
"Support": "支持",
|
||||
"Support Bundle": "支持捆绑包",
|
||||
"Sync Protocol Listen Addresses": "协议监听地址",
|
||||
@@ -328,13 +330,13 @@
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "输入的设备 ID 似乎无效。设备 ID 包含字母和数字,长度为 52 或 56,空格和横线不计在内。",
|
||||
"The folder ID cannot be blank.": "文件夹 ID 不能为空。",
|
||||
"The folder ID must be unique.": "文件夹 ID 不得重复。",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "其它设备上的文件夹内容将被覆盖,以与此设备相同。此处不存在的文件将在其他设备上删除。",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "该设备上的文件夹内容将被覆盖,使其与其他设备相同。在此处新添加的文件将被删除。",
|
||||
"The folder path cannot be blank.": "文件夹路径不能为空。",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "保留的历史版本会遵循以下条件:最近一小时内的历史版本,更新间隔小于三十秒的仅保留一份。最近一天内的历史版本,更新间隔小于一小时的仅保留一份。最近一个月内的历史版本,更新间隔小于一天的仅保留一份。距离现在超过一个月且小于最长保留时间的,更新间隔小于一周的仅保留一份。",
|
||||
"The following items could not be synchronized.": "下列项目无法被同步。",
|
||||
"The following items were changed locally.": "下列项目存在本地更改。",
|
||||
"The following unexpected items were found.": "The following unexpected items were found.",
|
||||
"The following unexpected items were found.": "找到了以下特殊项。",
|
||||
"The interval must be a positive number of seconds.": "间隔必须为正数秒。",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "在版本目录中运行清理的间隔(秒)。0表示禁用定期清除。",
|
||||
"The maximum age must be a number and cannot be blank.": "最长保留时间必须为数字,且不能为空。",
|
||||
@@ -347,7 +349,7 @@
|
||||
"The rate limit must be a non-negative number (0: no limit)": "传输速度限制为非负整数(0 表示不限制)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "扫描间隔单位为秒,且不能为负数。",
|
||||
"There are no devices to share this folder with.": "没有设备共享此文件夹",
|
||||
"There are no folders to share with this device.": "There are no folders to share with this device.",
|
||||
"There are no folders to share with this device.": "没有文件夹与此设备共享。",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "系统将会自动重试,当错误被解决时,它们将会被同步。",
|
||||
"This Device": "当前设备",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "这会让骇客能够轻而易举地访问及修改您的文件。",
|
||||
@@ -361,14 +363,14 @@
|
||||
"Unavailable": "无效",
|
||||
"Unavailable/Disabled by administrator or maintainer": "无效/禁用(由管理员或维护者)",
|
||||
"Undecided (will prompt)": "待定(将提示)",
|
||||
"Unexpected Items": "Unexpected Items",
|
||||
"Unexpected items have been found in this folder.": "Unexpected items have been found in this folder.",
|
||||
"Unexpected Items": "特殊项目",
|
||||
"Unexpected items have been found in this folder.": "在此文件夹中发现了特殊项目",
|
||||
"Unignore": "解除忽略",
|
||||
"Unknown": "未知",
|
||||
"Unshared": "未共享",
|
||||
"Unshared Devices": "未共享设备",
|
||||
"Unshared Folders": "Unshared Folders",
|
||||
"Untrusted": "Untrusted",
|
||||
"Unshared": "非共享",
|
||||
"Unshared Devices": "非共享设备",
|
||||
"Unshared Folders": "非共享文件夹",
|
||||
"Untrusted": "不可信的",
|
||||
"Up to Date": "同步完成",
|
||||
"Updated": "已更新",
|
||||
"Upgrade": "更新",
|
||||
@@ -386,7 +388,7 @@
|
||||
"Waiting to Clean": "等待清除",
|
||||
"Waiting to Scan": "等待扫描",
|
||||
"Waiting to Sync": "等待同步",
|
||||
"Warning": "Warning",
|
||||
"Warning": "警告",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "警告,该路径是已有文件夹\"{{otherFolder}}\"的上级目录。",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "警告,该路径是已有文件夹\"{{otherFolderLabel}}\" ({{otherFolder}})的上级目录。",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "警告,该路径是已有文件夹\"{{otherFolder}}\"的下级目录。",
|
||||
@@ -405,7 +407,7 @@
|
||||
"You have no ignored folders.": "你没有已忽略的文件夹。",
|
||||
"You have unsaved changes. Do you really want to discard them?": "你有未保存的更改。你真的要丢弃它们吗?",
|
||||
"You must keep at least one version.": "您必须保留至少一个版本。",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "You should never add or change anything locally in a \"{{receiveEncrypted}}\" folder.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "您绝对不应在“ {{receiveEncrypted}}”文件夹中添加或更改任何本地内容。",
|
||||
"days": "天",
|
||||
"directories": "目录",
|
||||
"files": "文件",
|
||||
@@ -414,5 +416,5 @@
|
||||
"seconds": "秒",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} 想将 “{{folder}}” 文件夹共享给您。",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} 想要共享 \"{{folderlabel}}\" ({{folder}}) 文件夹给您。",
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} might reintroduce this device."
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}}可能会重新引入此设备。"
|
||||
}
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "清除版本",
|
||||
"Cleanup Interval": "清除間隔",
|
||||
"Click to see discovery failures": "點擊查看設備發現錯誤",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "關閉",
|
||||
"Command": "命令",
|
||||
"Comment, when used at the start of a line": "註釋,在行首使用",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "幫助",
|
||||
"Home page": "主頁",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "我們已經為您關閉了自動崩潰報告發送功能,因為您當前的設置顯示您可能並不想啟用該功能。",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "如果不受信任,請輸入加密密碼",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "如果要阻止此計算機上的其他用戶訪問Syncthing並通過它訪問文件,請考慮設置身份驗證。",
|
||||
"Ignore": "忽略",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"Cleaning Versions": "正在清除歷史版本",
|
||||
"Cleanup Interval": "清除間隔",
|
||||
"Click to see discovery failures": "點擊以查閱失敗的探索",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "關閉",
|
||||
"Command": "指令",
|
||||
"Comment, when used at the start of a line": "註解,當輸入在一行的開頭時",
|
||||
@@ -153,6 +154,7 @@
|
||||
"Help": "說明",
|
||||
"Home page": "首頁",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "但是,當前設定表明您可能不希望啟用它。我們為您停用了當機自動回報。",
|
||||
"Identification": "Identification",
|
||||
"If untrusted, enter encryption password": "如未受信任,請輸入加密密碼",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "如果您想防止在此電腦上的其他使用者存取 Syncthing 及其文件,請考慮設定身份驗證。",
|
||||
"Ignore": "忽略",
|
||||
|
||||
+36
-20
@@ -102,7 +102,7 @@
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="" ng-click="showSettings()"><span class="fas fa-fw fa-cog"></span> <span translate>Settings</span></a></li>
|
||||
<li><a href="" data-toggle="modal" data-target="#idqr" ng-click="currentDevice=thisDevice()"><span class="fas fa-fw fa-qrcode"></span> <span translate>Show ID</span></a></li>
|
||||
<li><a href="" ng-click="showDeviceIdentification(thisDevice())"><span class="fas fa-fw fa-qrcode"></span> <span translate>Show ID</span></a></li>
|
||||
<li class="divider" aria-hidden="true"></li>
|
||||
<li><a href="" ng-click="shutdown()"><span class="fas fa-fw fa-power-off"></span> <span translate>Shutdown</span></a></li>
|
||||
<li><a href="" ng-click="restart()"><span class="fas fa-fw fa-refresh"></span> <span translate>Restart</span></a></li>
|
||||
@@ -209,10 +209,13 @@
|
||||
</div>
|
||||
<div class="panel-footer clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="dismissPendingDevice(deviceID)" tooltip data-original-title="{{'Do not add it to the ignore list, so this notification may recurr.' | translate}}">
|
||||
<span class="far fa-clock"></span> <span translate>Dismiss</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="addDevice(deviceID, pendingDevice.name)">
|
||||
<span class="fas fa-plus"></span> <span translate>Add Device</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreDevice(deviceID, pendingDevice)">
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreDevice(deviceID, pendingDevice)" tooltip data-original-title="{{'Permanently add it to the ignore list, suppressing further notifications.' | translate}}">
|
||||
<span class="fas fa-times"></span> <span translate>Ignore</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -250,13 +253,16 @@
|
||||
</div>
|
||||
<div class="panel-footer clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="dismissPendingFolder(folderID, deviceID)" tooltip data-original-title="{{'Do not add it to the ignore list, so this notification may recurr.' | translate}}">
|
||||
<span class="far fa-clock"></span> <span translate>Dismiss</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="addFolderAndShare(folderID, pendingFolder, deviceID)" ng-if="!folders[folderID]">
|
||||
<span class="fas fa-check"></span> <span translate>Add</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="shareFolderWithDevice(folderID, deviceID)" ng-if="folders[folderID]">
|
||||
<span class="fas fa-check"></span> <span translate>Share</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreFolder(deviceID, folderID, offeringDevice)">
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreFolder(deviceID, folderID, offeringDevice)" tooltip data-original-title="{{'Permanently add it to the ignore list, suppressing further notifications.' | translate}}">
|
||||
<span class="fas fa-times"></span> <span translate>Ignore</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -560,7 +566,7 @@
|
||||
<button ng-if="folder.paused" type="button" class="btn btn-sm btn-default" ng-click="setFolderPause(folder.id, false)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="restoreVersions.show(folder.id)" ng-if="folder.versioning.type && folder.versioning.type != 'external'">
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="restoreVersions.show(folder.id)" ng-if="folder.versioning.type && folder.versioning.type != 'external'" ng-disabled="folder.paused">
|
||||
<span class="fas fa-undo"></span> <span translate>Versions</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="rescanFolder(folder.id)" ng-disabled="['idle', 'stopped', 'unshared', 'outofsync', 'faileditems', 'localadditions'].indexOf(folderStatus(folder)) < 0">
|
||||
@@ -655,26 +661,20 @@
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-sitemap"></span> <span translate>Listeners</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="listenersFailed.length == 0" class="data text-success">
|
||||
<span>{{listenersTotal}}/{{listenersTotal}}</span>
|
||||
</span>
|
||||
<span ng-if="listenersFailed.length != 0" class="data" ng-class="{'text-danger': listenersFailed.length == listenersTotal}">
|
||||
<span popover data-trigger="hover" data-placement="bottom" data-html="true" data-content="{{listenersFailed.join('<br>\n')}}">
|
||||
{{listenersTotal-listenersFailed.length}}/{{listenersTotal}}
|
||||
</span>
|
||||
<span class="data" tooltip data-original-title="{{'Show detailed listener status' | translate}}.">
|
||||
<a href="" style="color:inherit" ng-class="{'text-success': listenersFailed.length == 0, 'text-danger': listenersFailed.length == listenersTotal}" ng-click="showListenerStatus()">
|
||||
{{listenersTotal-listenersFailed.length}}/{{listenersTotal}}
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="system.discoveryEnabled">
|
||||
<th><span class="fas fa-fw fa-map-signs"></span> <span translate>Discovery</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="discoveryFailed.length == 0" class="data text-success">
|
||||
<span>{{discoveryTotal}}/{{discoveryTotal}}</span>
|
||||
</span>
|
||||
<span ng-if="discoveryFailed.length != 0" class="data" ng-class="{'text-danger': discoveryFailed.length == discoveryTotal}">
|
||||
<span popover data-trigger="hover" data-placement="bottom" data-content="{{'Click to see discovery failures' | translate}}.">
|
||||
<a href="" style="color:inherit" ng-click="showDiscoveryFailures()">{{discoveryTotal-discoveryFailed.length}}/{{discoveryTotal}}</a>
|
||||
</span>
|
||||
<span class="data" tooltip data-original-title="{{'Show detailed discovery status' | translate}}.">
|
||||
<a href="" style="color:inherit" ng-class="{'text-success': discoveryFailed.length == 0, 'text-danger': discoveryFailed.length == discoveryTotal}" ng-click="showDiscoveryStatus()">
|
||||
{{discoveryTotal-discoveryFailed.length}}/{{discoveryTotal}}
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -682,6 +682,14 @@
|
||||
<th><span class="far fa-fw fa-clock"></span> <span translate>Uptime</span></th>
|
||||
<td class="text-right">{{system.uptime | duration:"m"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-qrcode"></span> <span translate>Identification</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{'Click to see full identification string and QR code.' | translate}}">
|
||||
<a href="" ng-click="showDeviceIdentification(thisDevice())">{{deviceShortID(deviceCfg.deviceID)}}</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-tag"></span> <span translate>Version</span></th>
|
||||
<td class="text-right">
|
||||
@@ -713,7 +721,7 @@
|
||||
<span ng-switch-when="disconnected"><span class="hidden-xs" translate>Disconnected</span><span class="visible-xs" aria-label="{{'Disconnected' | translate}}"><i class="fas fa-fw fa-power-off"></i></span></span>
|
||||
<span ng-switch-when="unused-disconnected"><span class="hidden-xs" translate>Disconnected (Unused)</span><span class="visible-xs" aria-label="{{'Disconnected (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
</span>
|
||||
<span>{{deviceName(deviceCfg)}}</span>
|
||||
<div class="panel-title-text">{{deviceName(deviceCfg)}}</div>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="device-{{$index}}" class="panel-collapse collapse">
|
||||
@@ -806,6 +814,14 @@
|
||||
<th><span class="far fa-fw fa-handshake-o"></span> <span translate>Introduced By</span></th>
|
||||
<td class="text-right">{{ deviceName(devices[deviceCfg.introducedBy]) || deviceCfg.introducedBy.substring(0, 5) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-qrcode"></span> <span translate>Identification</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{'Click to see full identification string and QR code.' | translate}}">
|
||||
<a href="" ng-click="showDeviceIdentification(deviceCfg)">{{deviceShortID(deviceCfg.deviceID)}}</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="connections[deviceCfg.deviceID].clientVersion">
|
||||
<th><span class="fas fa-fw fa-tag"></span> <span translate>Version</span></th>
|
||||
<td class="text-right">{{connections[deviceCfg.deviceID].clientVersion}}</td>
|
||||
@@ -905,7 +921,7 @@
|
||||
<ng-include src="'syncthing/core/upgradeModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/majorUpgradeModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/aboutModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/connectivityStatusModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/removeFolderDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/revertOverrideView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/removeDeviceDialogView.html'"></ng-include>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<h4 class="text-center" translate>The Syncthing Authors</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Tomasz Wilczyński, Wulf Weich, dependabot-preview[bot], greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Alessandro G., Alex Lindeman, Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eric Lesiuta, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Jörg Thalheim, Jędrzej Kula, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, bt90, chenrui, chucic, deepsource-autofix[bot], dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, mclang, mv1005, otbutz, perewa, rubenbe, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙
|
||||
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Tomasz Wilczyński, Wulf Weich, dependabot-preview[bot], greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Alessandro G., Alex Lindeman, Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eric Lesiuta, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Jörg Thalheim, Jędrzej Kula, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, bt90, chenrui, chucic, deepsource-autofix[bot], dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, mclang, mv1005, otbutz, overkill, perewa, rubenbe, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<modal id="connectivity-status" status="{{connectivityStatusParams.status}}" icon="fas fa-fw {{connectivityStatusParams.type == 'listeners' ? 'fa-sitemap' : 'fa-map-signs'}}" heading="{{connectivityStatusParams.heading}}" large="no" closeable="yes">
|
||||
<div class="modal-body" ng-switch="connectivityStatusParams.type">
|
||||
<div ng-switch-when="listeners">
|
||||
<p translate ng-if="listenersRunning.length == 0">
|
||||
Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.
|
||||
</p>
|
||||
<div ng-if="listenersRunning.length > 0">
|
||||
<p translate>
|
||||
Syncthing is listening on the following network addresses for connection attempts from other devices:
|
||||
</p>
|
||||
<ul>
|
||||
<li ng-repeat="listener in listenersRunning">{{listener}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-if="listenersFailed.length > 0">
|
||||
<p translate>
|
||||
Some listening addresses could not be enabled to accept connections:
|
||||
</p>
|
||||
<ul>
|
||||
<li ng-repeat="listener in listenersFailed">{{listener}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-default><!-- discovery methods -->
|
||||
<p translate ng-if="discoveryRunning.length == 0">
|
||||
This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.
|
||||
</p>
|
||||
<div ng-if="discoveryRunning.length > 0">
|
||||
<p translate>
|
||||
The following methods are used to discover other devices on the network and announce this device to be found by others:
|
||||
</p>
|
||||
<ul>
|
||||
<li ng-repeat="discovery in discoveryRunning">{{discovery}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-if="discoveryFailed.length > 0">
|
||||
<p translate>
|
||||
Some discovery methods could not be established for finding other devices or announcing this device:
|
||||
</p>
|
||||
<ul>
|
||||
<li ng-repeat="discovery in discoveryFailed">{{discovery}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-offset-2 col-md-8">
|
||||
<div class="panel panel-default">
|
||||
<div translate class="panel-body">
|
||||
Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -1,21 +0,0 @@
|
||||
<modal id="discovery-failures" status="danger" icon="fas fa-exclamation-circle" heading="{{'Discovery Failures' | translate}}" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<ul>
|
||||
<li ng-repeat="failure in discoveryFailed">{{failure}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-offset-2 col-md-8">
|
||||
<div class="panel panel-default">
|
||||
<div translate class="panel-body">
|
||||
Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -42,7 +42,7 @@ angular.module('syncthing.core')
|
||||
$scope.pendingFolders = {};
|
||||
$scope.progress = {};
|
||||
$scope.version = {};
|
||||
$scope.needed = {}
|
||||
$scope.needed = {};
|
||||
$scope.neededFolder = '';
|
||||
$scope.failed = {};
|
||||
$scope.localChanged = {};
|
||||
@@ -471,22 +471,30 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
var listenersFailed = [];
|
||||
var listenersRunning = [];
|
||||
for (var address in data.connectionServiceStatus) {
|
||||
if (data.connectionServiceStatus[address].error) {
|
||||
listenersFailed.push(address + ": " + data.connectionServiceStatus[address].error);
|
||||
} else {
|
||||
listenersRunning.push(address);
|
||||
}
|
||||
}
|
||||
$scope.listenersFailed = listenersFailed;
|
||||
$scope.listenersRunning = listenersRunning;
|
||||
$scope.listenersTotal = $scope.sizeOf(data.connectionServiceStatus);
|
||||
|
||||
$scope.discoveryTotal = data.discoveryMethods;
|
||||
var discoveryFailed = [];
|
||||
for (var disco in data.discoveryErrors) {
|
||||
if (data.discoveryErrors[disco]) {
|
||||
discoveryFailed.push(disco + ": " + data.discoveryErrors[disco]);
|
||||
var discoveryRunning = [];
|
||||
for (var disco in data.discoveryStatus) {
|
||||
if (data.discoveryStatus[disco] && data.discoveryStatus[disco].error) {
|
||||
discoveryFailed.push(disco + ": " + data.discoveryStatus[disco].error);
|
||||
} else {
|
||||
discoveryRunning.push(disco);
|
||||
}
|
||||
}
|
||||
$scope.discoveryFailed = discoveryFailed;
|
||||
$scope.discoveryRunning = discoveryRunning;
|
||||
$scope.discoveryTotal = $scope.sizeOf(data.discoveryStatus);
|
||||
|
||||
refreshNoAuthWarning();
|
||||
|
||||
@@ -673,7 +681,7 @@ angular.module('syncthing.core')
|
||||
console.log("refreshNeed", $scope.neededFolder, data);
|
||||
parseNeeded(data);
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
};
|
||||
|
||||
function needAction(file) {
|
||||
var fDelete = 4096;
|
||||
@@ -1010,7 +1018,7 @@ angular.module('syncthing.core')
|
||||
if (days > 31) {
|
||||
return '> 1 month';
|
||||
}
|
||||
res.push('' + days + 'd')
|
||||
res.push('' + days + 'd');
|
||||
seconds = seconds % 86400;
|
||||
}
|
||||
|
||||
@@ -1018,7 +1026,7 @@ angular.module('syncthing.core')
|
||||
var hours = 0;
|
||||
if (seconds > 3600) {
|
||||
hours = Math.floor(seconds / 3600);
|
||||
res.push('' + hours + 'h')
|
||||
res.push('' + hours + 'h');
|
||||
seconds = seconds % 3600;
|
||||
}
|
||||
|
||||
@@ -1202,13 +1210,20 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.deviceName = function (deviceCfg) {
|
||||
if (typeof deviceCfg === 'undefined' || typeof deviceCfg.deviceID === 'undefined') {
|
||||
if (typeof deviceCfg === 'undefined') {
|
||||
return "";
|
||||
}
|
||||
if (deviceCfg.name) {
|
||||
return deviceCfg.name;
|
||||
}
|
||||
return deviceCfg.deviceID.substr(0, 6);
|
||||
return $scope.deviceShortID(deviceCfg.deviceID);
|
||||
};
|
||||
|
||||
$scope.deviceShortID = function (deviceID) {
|
||||
if (typeof deviceID === 'undefined') {
|
||||
return "";
|
||||
}
|
||||
return deviceID.substr(0, 6);
|
||||
};
|
||||
|
||||
$scope.thisDeviceName = function () {
|
||||
@@ -1222,6 +1237,11 @@ angular.module('syncthing.core')
|
||||
return device.deviceID.substr(0, 6);
|
||||
};
|
||||
|
||||
$scope.showDeviceIdentification = function (deviceCfg) {
|
||||
$scope.currentDevice = deviceCfg;
|
||||
$('#idqr').modal();
|
||||
};
|
||||
|
||||
$scope.setDevicePause = function (device, pause) {
|
||||
$scope.devices[device].paused = pause;
|
||||
$scope.config.devices = $scope.deviceList();
|
||||
@@ -1237,8 +1257,34 @@ angular.module('syncthing.core')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.showDiscoveryFailures = function () {
|
||||
$('#discovery-failures').modal();
|
||||
$scope.showListenerStatus = function () {
|
||||
var params = {
|
||||
type: 'listeners',
|
||||
};
|
||||
if ($scope.listenersFailed.length > 0) {
|
||||
params.status = 'danger';
|
||||
params.heading = $translate.instant("Listener Failures");
|
||||
} else {
|
||||
params.status = 'default';
|
||||
params.heading = $translate.instant("Listener Status");
|
||||
}
|
||||
$scope.connectivityStatusParams = params;
|
||||
$('#connectivity-status').modal();
|
||||
};
|
||||
|
||||
$scope.showDiscoveryStatus = function () {
|
||||
var params = {
|
||||
type: 'discovery',
|
||||
};
|
||||
if ($scope.discoveryFailed.length > 0) {
|
||||
params.status = 'danger';
|
||||
params.heading = $translate.instant("Discovery Failures");
|
||||
} else {
|
||||
params.status = 'default';
|
||||
params.heading = $translate.instant("Discovery Status");
|
||||
}
|
||||
$scope.connectivityStatusParams = params;
|
||||
$('#connectivity-status').modal();
|
||||
};
|
||||
|
||||
$scope.logging = {
|
||||
@@ -1703,6 +1749,10 @@ angular.module('syncthing.core')
|
||||
$scope.saveConfig();
|
||||
};
|
||||
|
||||
$scope.dismissPendingDevice = function (deviceID) {
|
||||
$http.delete(urlbase + '/cluster/pending/devices?device=' + encodeURIComponent(deviceID));
|
||||
};
|
||||
|
||||
$scope.unignoreDeviceFromTemporaryConfig = function (ignoredDevice) {
|
||||
$scope.tmpRemoteIgnoredDevices = $scope.tmpRemoteIgnoredDevices.filter(function (existingIgnoredDevice) {
|
||||
return ignoredDevice.deviceID !== existingIgnoredDevice.deviceID;
|
||||
@@ -1759,7 +1809,7 @@ angular.module('syncthing.core')
|
||||
};
|
||||
$scope.config.devices = deviceList($scope.devices);
|
||||
$scope.saveConfig();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.isAtleastOneDevicePausedStateSetTo = function (pause) {
|
||||
for (var id in $scope.devices) {
|
||||
@@ -1768,8 +1818,8 @@ angular.module('syncthing.core')
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
$scope.errorList = function () {
|
||||
if (!$scope.errors) {
|
||||
@@ -2117,7 +2167,7 @@ angular.module('syncthing.core')
|
||||
folderCfg.versioning.params.command = '' + folderCfg._guiVersioning.externalCommand;
|
||||
break;
|
||||
default:
|
||||
delete folderCfg.versioning;
|
||||
folderCfg.versioning = {type: ''};
|
||||
}
|
||||
delete folderCfg._guiVersioning;
|
||||
|
||||
@@ -2174,6 +2224,11 @@ angular.module('syncthing.core')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.dismissPendingFolder = function (folderID, deviceID) {
|
||||
$http.delete(urlbase + '/cluster/pending/folders?folder=' + encodeURIComponent(folderID)
|
||||
+ '&device=' + encodeURIComponent(deviceID));
|
||||
};
|
||||
|
||||
$scope.sharesFolder = function (folderCfg) {
|
||||
var names = [];
|
||||
folderCfg.devices.forEach(function (device) {
|
||||
@@ -2779,7 +2834,7 @@ angular.module('syncthing.core')
|
||||
var time = $filter('date')(status.when, "HH:mm:ss")
|
||||
var err = status.error.replace(/.+: /, '');
|
||||
return err + " (" + time + ")";
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setCrashReportingEnabled = function (enabled) {
|
||||
$scope.config.options.crashReportingEnabled = enabled;
|
||||
@@ -2791,7 +2846,7 @@ angular.module('syncthing.core')
|
||||
(address.indexOf('/') == 0 ||
|
||||
address.indexOf('unix://') == 0 ||
|
||||
address.indexOf('unixs://') == 0);
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('shareTemplate', function () {
|
||||
return {
|
||||
|
||||
+70
-10
@@ -32,7 +32,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
metrics "github.com/rcrowley/go-metrics"
|
||||
"github.com/rcrowley/go-metrics"
|
||||
"github.com/thejerf/suture/v4"
|
||||
"github.com/vitrun/qart/qr"
|
||||
"golang.org/x/text/runes"
|
||||
@@ -162,7 +162,7 @@ func (s *service) getListener(guiCfg config.GUIConfiguration) (net.Listener, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsCfg := tlsutil.SecureDefault()
|
||||
tlsCfg := tlsutil.SecureDefaultWithTLS12()
|
||||
tlsCfg.Certificates = []tls.Certificate{cert}
|
||||
|
||||
if guiCfg.Network() == "unix" {
|
||||
@@ -291,6 +291,10 @@ func (s *service) Serve(ctx context.Context) error {
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/resume", s.makeDevicePauseHandler(false)) // [device]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/debug", s.postSystemDebug) // [enable] [disable]
|
||||
|
||||
// The DELETE handlers
|
||||
restMux.HandlerFunc(http.MethodDelete, "/rest/cluster/pending/devices", s.deletePendingDevices) // device
|
||||
restMux.HandlerFunc(http.MethodDelete, "/rest/cluster/pending/folders", s.deletePendingFolders) // folder [device]
|
||||
|
||||
// Config endpoints
|
||||
|
||||
configBuilder := &configMuxBuilder{
|
||||
@@ -632,6 +636,21 @@ func (s *service) getPendingDevices(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, devices)
|
||||
}
|
||||
|
||||
func (s *service) deletePendingDevices(w http.ResponseWriter, r *http.Request) {
|
||||
qs := r.URL.Query()
|
||||
|
||||
device := qs.Get("device")
|
||||
deviceID, err := protocol.DeviceIDFromString(device)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.model.DismissPendingDevice(deviceID); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) getPendingFolders(w http.ResponseWriter, r *http.Request) {
|
||||
qs := r.URL.Query()
|
||||
|
||||
@@ -650,6 +669,22 @@ func (s *service) getPendingFolders(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, folders)
|
||||
}
|
||||
|
||||
func (s *service) deletePendingFolders(w http.ResponseWriter, r *http.Request) {
|
||||
qs := r.URL.Query()
|
||||
|
||||
device := qs.Get("device")
|
||||
deviceID, err := protocol.DeviceIDFromString(device)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
folderID := qs.Get("folder")
|
||||
|
||||
if err := s.model.DismissPendingFolder(deviceID, folderID); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) restPing(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, map[string]string{"ping": "pong"})
|
||||
}
|
||||
@@ -915,11 +950,16 @@ func (s *service) getDBFile(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
mtimeMapping, mtimeErr := s.model.GetMtimeMapping(folder, file)
|
||||
|
||||
sendJSON(w, map[string]interface{}{
|
||||
"global": jsonFileInfo(gf),
|
||||
"local": jsonFileInfo(lf),
|
||||
"availability": av,
|
||||
"mtime": map[string]interface{}{
|
||||
"err": mtimeErr,
|
||||
"value": mtimeMapping,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -934,6 +974,8 @@ func (s *service) getDebugFile(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
mtimeMapping, mtimeErr := s.model.GetMtimeMapping(folder, file)
|
||||
|
||||
lf, _ := snap.Get(protocol.LocalDeviceID, file)
|
||||
gf, _ := snap.GetGlobal(file)
|
||||
av := snap.Availability(file)
|
||||
@@ -944,6 +986,10 @@ func (s *service) getDebugFile(w http.ResponseWriter, r *http.Request) {
|
||||
"local": jsonFileInfo(lf),
|
||||
"availability": av,
|
||||
"globalVersions": vl.String(),
|
||||
"mtime": map[string]interface{}{
|
||||
"err": mtimeErr,
|
||||
"value": mtimeMapping,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1012,16 +1058,16 @@ func (s *service) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
||||
res["tilde"] = tilde
|
||||
if s.cfg.Options().LocalAnnEnabled || s.cfg.Options().GlobalAnnEnabled {
|
||||
res["discoveryEnabled"] = true
|
||||
discoErrors := make(map[string]string)
|
||||
discoMethods := 0
|
||||
for disco, err := range s.discoverer.ChildErrors() {
|
||||
discoMethods++
|
||||
if err != nil {
|
||||
discoErrors[disco] = err.Error()
|
||||
discoStatus := s.discoverer.ChildErrors()
|
||||
res["discoveryStatus"] = discoveryStatusMap(discoStatus)
|
||||
res["discoveryMethods"] = len(discoStatus) // DEPRECATED: Redundant, only for backwards compatibility, should be removed.
|
||||
discoErrors := make(map[string]*string, len(discoStatus))
|
||||
for s, e := range discoStatus {
|
||||
if e != nil {
|
||||
discoErrors[s] = errorString(e)
|
||||
}
|
||||
}
|
||||
res["discoveryMethods"] = discoMethods
|
||||
res["discoveryErrors"] = discoErrors
|
||||
res["discoveryErrors"] = discoErrors // DEPRECATED: Redundant, only for backwards compatibility, should be removed.
|
||||
}
|
||||
|
||||
res["connectionServiceStatus"] = s.connectionsService.ListenerStatus()
|
||||
@@ -1894,6 +1940,20 @@ func errorString(err error) *string {
|
||||
return nil
|
||||
}
|
||||
|
||||
type discoveryStatusEntry struct {
|
||||
Error *string `json:"error"`
|
||||
}
|
||||
|
||||
func discoveryStatusMap(errs map[string]error) map[string]discoveryStatusEntry {
|
||||
out := make(map[string]discoveryStatusEntry, len(errs))
|
||||
for s, e := range errs {
|
||||
out[s] = discoveryStatusEntry{
|
||||
Error: errorString(e),
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// sanitizedHostname returns the given name in a suitable form for use as
|
||||
// the common name in a certificate, or an error.
|
||||
func sanitizedHostname(name string) (string, error) {
|
||||
|
||||
+3
-13
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
"github.com/syncthing/syncthing/lib/ur"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
@@ -126,6 +127,7 @@ func TestStopAfterBrokenConfig(t *testing.T) {
|
||||
|
||||
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
|
||||
srv.started = make(chan string)
|
||||
|
||||
sup := suture.New("test", svcutil.SpecWithDebugLogger(l))
|
||||
@@ -1178,7 +1180,7 @@ func TestBrowse(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
ret := browseFiles(tc.current, fs.FilesystemTypeBasic)
|
||||
if !equalStrings(ret, tc.returns) {
|
||||
if !util.EqualStrings(ret, tc.returns) {
|
||||
t.Errorf("browseFiles(%q) => %q, expected %q", tc.current, ret, tc.returns)
|
||||
}
|
||||
}
|
||||
@@ -1389,18 +1391,6 @@ func TestSanitizedHostname(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func equalStrings(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// runningInContainer returns true if we are inside Docker or LXC. It might
|
||||
// be prone to false negatives if things change in the future, but likely
|
||||
// not false positives.
|
||||
|
||||
+44
-29
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
type configMuxBuilder struct {
|
||||
@@ -63,10 +64,15 @@ func (c *configMuxBuilder) registerFolders(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
var folders []config.FolderConfiguration
|
||||
if err := unmarshalTo(r.Body, &folders); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
data, err := unmarshalToRawMessages(r.Body)
|
||||
folders := make([]config.FolderConfiguration, len(data))
|
||||
defaultFolder := c.cfg.DefaultFolder()
|
||||
for i, bs := range data {
|
||||
folders[i] = defaultFolder.Copy()
|
||||
if err := json.Unmarshal(bs, &folders[i]); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
waiter, err := c.cfg.Modify(func(cfg *config.Configuration) {
|
||||
cfg.SetFolders(folders)
|
||||
@@ -79,7 +85,7 @@ func (c *configMuxBuilder) registerFolders(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPost, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustFolder(w, r, config.FolderConfiguration{}, false)
|
||||
c.adjustFolder(w, r, c.cfg.DefaultFolder(), false)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -89,10 +95,15 @@ func (c *configMuxBuilder) registerDevices(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
var devices []config.DeviceConfiguration
|
||||
if err := unmarshalTo(r.Body, &devices); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
data, err := unmarshalToRawMessages(r.Body)
|
||||
devices := make([]config.DeviceConfiguration, len(data))
|
||||
defaultDevice := c.cfg.DefaultDevice()
|
||||
for i, bs := range data {
|
||||
devices[i] = defaultDevice.Copy()
|
||||
if err := json.Unmarshal(bs, &devices[i]); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
waiter, err := c.cfg.Modify(func(cfg *config.Configuration) {
|
||||
cfg.SetDevices(devices)
|
||||
@@ -105,19 +116,7 @@ func (c *configMuxBuilder) registerDevices(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPost, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
var device config.DeviceConfiguration
|
||||
if err := unmarshalTo(r.Body, &device); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.Modify(func(cfg *config.Configuration) {
|
||||
cfg.SetDevice(device)
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
c.adjustDevice(w, r, c.cfg.DefaultDevice(), false)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ func (c *configMuxBuilder) registerFolder(path string) {
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
c.adjustFolder(w, r, config.FolderConfiguration{}, false)
|
||||
c.adjustFolder(w, r, c.cfg.DefaultFolder(), false)
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
@@ -176,7 +175,7 @@ func (c *configMuxBuilder) registerDevice(path string) {
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
c.adjustDevice(w, r, config.DeviceConfiguration{}, false)
|
||||
c.adjustDevice(w, r, c.cfg.DefaultDevice(), false)
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
@@ -206,7 +205,9 @@ func (c *configMuxBuilder) registerDefaultFolder(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustFolder(w, r, config.FolderConfiguration{}, true)
|
||||
var cfg config.FolderConfiguration
|
||||
util.SetDefaults(&cfg)
|
||||
c.adjustFolder(w, r, cfg, true)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -220,7 +221,9 @@ func (c *configMuxBuilder) registerDefaultDevice(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustDevice(w, r, config.DeviceConfiguration{}, true)
|
||||
var cfg config.DeviceConfiguration
|
||||
util.SetDefaults(&cfg)
|
||||
c.adjustDevice(w, r, cfg, true)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -234,7 +237,9 @@ func (c *configMuxBuilder) registerOptions(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustOptions(w, r, config.OptionsConfiguration{})
|
||||
var cfg config.OptionsConfiguration
|
||||
util.SetDefaults(&cfg)
|
||||
c.adjustOptions(w, r, cfg)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -248,7 +253,9 @@ func (c *configMuxBuilder) registerLDAP(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustLDAP(w, r, config.LDAPConfiguration{})
|
||||
var cfg config.LDAPConfiguration
|
||||
util.SetDefaults(&cfg)
|
||||
c.adjustLDAP(w, r, cfg)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -262,7 +269,9 @@ func (c *configMuxBuilder) registerGUI(path string) {
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustGUI(w, r, config.GUIConfiguration{})
|
||||
var cfg config.GUIConfiguration
|
||||
util.SetDefaults(&cfg)
|
||||
c.adjustGUI(w, r, cfg)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -403,6 +412,12 @@ func unmarshalTo(body io.ReadCloser, to interface{}) error {
|
||||
return json.Unmarshal(bs, to)
|
||||
}
|
||||
|
||||
func unmarshalToRawMessages(body io.ReadCloser) ([]json.RawMessage, error) {
|
||||
var data []json.RawMessage
|
||||
err := unmarshalTo(body, &data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func checkGUIPassword(oldPassword, newPassword string) (string, error) {
|
||||
if newPassword == oldPassword {
|
||||
return newPassword, nil
|
||||
|
||||
+29
-4
@@ -163,19 +163,44 @@ func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, int, error) {
|
||||
}
|
||||
|
||||
func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
|
||||
var cfg Configuration
|
||||
|
||||
util.SetDefaults(&cfg)
|
||||
|
||||
bs, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
|
||||
var cfg Configuration
|
||||
|
||||
util.SetDefaults(&cfg)
|
||||
|
||||
if err := json.Unmarshal(bs, &cfg); err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
|
||||
// Unmarshal list of devices and folders separately to set defaults
|
||||
var rawFoldersDevices struct {
|
||||
Folders []json.RawMessage
|
||||
Devices []json.RawMessage
|
||||
}
|
||||
if err := json.Unmarshal(bs, &rawFoldersDevices); err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
|
||||
cfg.Folders = make([]FolderConfiguration, len(rawFoldersDevices.Folders))
|
||||
for i, bs := range rawFoldersDevices.Folders {
|
||||
cfg.Folders[i] = cfg.Defaults.Folder.Copy()
|
||||
if err := json.Unmarshal(bs, &cfg.Folders[i]); err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
}
|
||||
|
||||
cfg.Devices = make([]DeviceConfiguration, len(rawFoldersDevices.Devices))
|
||||
for i, bs := range rawFoldersDevices.Devices {
|
||||
cfg.Devices[i] = cfg.Defaults.Device.Copy()
|
||||
if err := json.Unmarshal(bs, &cfg.Devices[i]); err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := cfg.prepare(myID); err != nil {
|
||||
return Configuration{}, err
|
||||
}
|
||||
|
||||
@@ -721,10 +721,7 @@ func (m *Configuration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -840,10 +837,7 @@ func (m *Defaults) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -1343,3 +1343,30 @@ func TestInternalVersioningConfiguration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReceiveEncryptedFolderFixed(t *testing.T) {
|
||||
cfg := Configuration{
|
||||
Folders: []FolderConfiguration{
|
||||
{
|
||||
ID: "foo",
|
||||
Path: "testdata",
|
||||
Type: FolderTypeReceiveEncrypted,
|
||||
DisableTempIndexes: false,
|
||||
IgnorePerms: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cfg.prepare(device1)
|
||||
|
||||
if len(cfg.Folders) != 1 {
|
||||
t.Fatal("Expected one folder")
|
||||
}
|
||||
f := cfg.Folders[0]
|
||||
if !f.DisableTempIndexes {
|
||||
t.Error("DisableTempIndexes should be true")
|
||||
}
|
||||
if !f.IgnorePerms {
|
||||
t.Error("IgnorePerms should be true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,10 +924,7 @@ func (m *DeviceConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -214,6 +214,7 @@ func (f *FolderConfiguration) prepare(myID protocol.DeviceID, existingDevices ma
|
||||
}
|
||||
|
||||
if f.Type == FolderTypeReceiveEncrypted {
|
||||
f.DisableTempIndexes = true
|
||||
f.IgnorePerms = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,10 +968,7 @@ func (m *FolderDeviceConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthFolderconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthFolderconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -1823,10 +1820,7 @@ func (m *FolderConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthFolderconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthFolderconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -702,10 +702,7 @@ func (m *GUIConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -425,10 +425,7 @@ func (m *LDAPConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -435,10 +435,7 @@ func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -618,10 +615,7 @@ func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -81,6 +81,9 @@ type OptionsConfiguration struct {
|
||||
// meaning no limit. Affects incoming connections and prevents
|
||||
// attempting outgoing connections.
|
||||
ConnectionLimitMax int `protobuf:"varint,52,opt,name=connection_limit_max,json=connectionLimitMax,proto3,casttype=int" json:"connectionLimitMax" xml:"connectionLimitMax"`
|
||||
// When set, this allows TLS 1.2 on sync connections, where we otherwise
|
||||
// default to TLS 1.3+ only.
|
||||
InsecureAllowOldTLSVersions bool `protobuf:"varint,53,opt,name=insecure_allow_old_tls_versions,json=insecureAllowOldTlsVersions,proto3" json:"insecureAllowOldTLSVersions" xml:"insecureAllowOldTLSVersions"`
|
||||
// Legacy deprecated
|
||||
DeprecatedUPnPEnabled bool `protobuf:"varint,9000,opt,name=upnp_enabled,json=upnpEnabled,proto3" json:"-" xml:"upnpEnabled,omitempty"` // Deprecated: Do not use.
|
||||
DeprecatedUPnPLeaseM int `protobuf:"varint,9001,opt,name=upnp_lease_m,json=upnpLeaseM,proto3,casttype=int" json:"-" xml:"upnpLeaseMinutes,omitempty"` // Deprecated: Do not use.
|
||||
@@ -133,209 +136,213 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_d09882599506ca03 = []byte{
|
||||
// 3218 bytes of a gzipped FileDescriptorProto
|
||||
// 3295 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x5a, 0x5d, 0x6c, 0x1d, 0x47,
|
||||
0xf5, 0xcf, 0x26, 0x4d, 0xda, 0x6c, 0x1c, 0x27, 0x1e, 0x3b, 0xf6, 0x36, 0x49, 0xbd, 0xee, 0xcd,
|
||||
0x4d, 0xeb, 0x7e, 0x25, 0xb6, 0x93, 0xe6, 0x9f, 0x46, 0xfa, 0xab, 0xf8, 0xa3, 0x26, 0x6e, 0xec,
|
||||
0xc4, 0x1a, 0xdb, 0x2a, 0x2a, 0x42, 0xab, 0xb9, 0x7b, 0xe7, 0xda, 0x8b, 0xf7, 0xce, 0xde, 0xee,
|
||||
0xcc, 0xfa, 0xda, 0x2d, 0x82, 0xaa, 0x88, 0x8f, 0x37, 0xc0, 0xe2, 0x43, 0x02, 0x09, 0x15, 0x01,
|
||||
0x12, 0xa5, 0x14, 0x21, 0x21, 0x21, 0xc1, 0x0b, 0x08, 0x09, 0xa9, 0x82, 0x07, 0xfb, 0xb1, 0x12,
|
||||
0x65, 0x51, 0x9d, 0x3e, 0xdd, 0x07, 0x1e, 0xee, 0xa3, 0x79, 0x41, 0x33, 0xfb, 0x35, 0xbb, 0x3b,
|
||||
0xb7, 0xc9, 0xdb, 0xdd, 0xf3, 0x3b, 0x73, 0xe6, 0x77, 0xe6, 0xe3, 0xcc, 0x39, 0x33, 0x57, 0xbf,
|
||||
0xec, 0x3a, 0xb5, 0xab, 0xb6, 0x47, 0x1a, 0xce, 0xfa, 0x55, 0xaf, 0xc5, 0x1c, 0x8f, 0xd0, 0xe8,
|
||||
0x2b, 0xf0, 0x11, 0xff, 0xba, 0xd2, 0xf2, 0x3d, 0xe6, 0x81, 0x13, 0x91, 0xf0, 0xfc, 0x88, 0xa4,
|
||||
0xce, 0x02, 0xe2, 0x90, 0xf5, 0x48, 0xe1, 0xfc, 0x39, 0x09, 0xa0, 0xce, 0x9b, 0x38, 0x16, 0x9f,
|
||||
0xc4, 0xdb, 0x2c, 0xfa, 0x59, 0xf9, 0xe8, 0xb6, 0x3e, 0x74, 0x2f, 0xea, 0x61, 0x56, 0xee, 0x01,
|
||||
0xfc, 0x54, 0xd3, 0xcf, 0xba, 0x0e, 0x65, 0x98, 0x58, 0xa8, 0x5e, 0xf7, 0x31, 0xa5, 0x98, 0x1a,
|
||||
0xda, 0xd8, 0xb1, 0xf1, 0x93, 0x33, 0xf4, 0x20, 0x34, 0x01, 0x44, 0xed, 0x45, 0x01, 0x4f, 0x27,
|
||||
0x68, 0x27, 0x34, 0xcf, 0xb8, 0x79, 0x51, 0x37, 0x34, 0x2f, 0x6f, 0x37, 0xdd, 0x5b, 0x95, 0x9c,
|
||||
0xbc, 0x32, 0x56, 0xc7, 0x0d, 0x14, 0xb8, 0xec, 0x56, 0x25, 0xfe, 0x51, 0x39, 0xdc, 0xab, 0x3e,
|
||||
0x1a, 0xff, 0xde, 0xdd, 0xaf, 0x2a, 0x8c, 0xc3, 0xa2, 0x69, 0xf0, 0x1f, 0x4d, 0x37, 0xd6, 0x5d,
|
||||
0xaf, 0x86, 0x5c, 0xab, 0xee, 0x50, 0xdb, 0xdb, 0xc2, 0xfe, 0x8e, 0x45, 0xb1, 0xbf, 0x85, 0x7d,
|
||||
0x6a, 0x1c, 0x15, 0x44, 0x7f, 0xaf, 0x1d, 0x84, 0xe6, 0x20, 0x44, 0xed, 0xcf, 0x0b, 0xbd, 0x69,
|
||||
0x42, 0x56, 0x22, 0xbc, 0x13, 0x9a, 0xe7, 0xd6, 0x13, 0x99, 0x17, 0x10, 0x1b, 0xc7, 0x40, 0x37,
|
||||
0x34, 0x9f, 0x17, 0x84, 0x55, 0xa8, 0x82, 0x77, 0x67, 0xaf, 0x3a, 0xa4, 0x52, 0xed, 0xee, 0x55,
|
||||
0xd5, 0x1d, 0xe4, 0x1d, 0x55, 0x71, 0x83, 0xc3, 0x51, 0xc3, 0xb9, 0xc4, 0xa9, 0x58, 0x0e, 0x3e,
|
||||
0x55, 0x39, 0x8c, 0x09, 0xaa, 0xb9, 0xb8, 0x6e, 0x1c, 0x1b, 0xd3, 0xc6, 0x1f, 0x9b, 0x79, 0x8f,
|
||||
0x3b, 0x7c, 0x36, 0xb5, 0xf8, 0x4a, 0x04, 0x96, 0xbd, 0x8d, 0x81, 0x6e, 0x68, 0x3e, 0xab, 0xf0,
|
||||
0x36, 0x46, 0x25, 0x77, 0x99, 0x1f, 0x60, 0xee, 0x6b, 0x0f, 0x33, 0xbd, 0x80, 0xc3, 0xbd, 0xea,
|
||||
0x23, 0xbc, 0xe9, 0xee, 0x7e, 0xb5, 0x44, 0xaa, 0xe4, 0x66, 0x2c, 0x07, 0x1f, 0x6b, 0xfa, 0x88,
|
||||
0xeb, 0xd9, 0x4a, 0x2f, 0x1f, 0x11, 0x5e, 0xfe, 0x9c, 0x7b, 0x79, 0x66, 0x91, 0xeb, 0xe4, 0x9c,
|
||||
0x1c, 0x72, 0x63, 0x51, 0xc1, 0xc7, 0x67, 0xa2, 0x25, 0xa8, 0x00, 0x15, 0x2e, 0xaa, 0x8d, 0xf4,
|
||||
0x90, 0x4b, 0x0e, 0x16, 0xf9, 0xc0, 0x73, 0xa2, 0x41, 0xc9, 0xbd, 0x7f, 0x68, 0xfa, 0x60, 0xe4,
|
||||
0x1e, 0x8a, 0x6d, 0x59, 0x2d, 0xcf, 0x67, 0xc6, 0xf1, 0x31, 0x6d, 0xfc, 0xf8, 0xcc, 0x8f, 0xb9,
|
||||
0x6b, 0x7d, 0x89, 0xa9, 0x65, 0xcf, 0x67, 0x9d, 0xd0, 0x1c, 0xc8, 0x75, 0xcd, 0x85, 0xdd, 0xd0,
|
||||
0x7c, 0xba, 0xec, 0x14, 0x47, 0x24, 0x8f, 0xa6, 0x26, 0x27, 0xa6, 0xfe, 0xaf, 0x72, 0x18, 0x9a,
|
||||
0xc7, 0x1c, 0xc2, 0x3a, 0x7b, 0x55, 0x85, 0x19, 0x95, 0xf0, 0x70, 0xaf, 0x7a, 0x5c, 0x34, 0xdd,
|
||||
0xdd, 0xaf, 0xe6, 0x98, 0xc0, 0xb2, 0x2e, 0xf8, 0xfa, 0x51, 0x7d, 0xac, 0xe0, 0x4d, 0x33, 0x70,
|
||||
0x99, 0x63, 0x23, 0xca, 0x92, 0xb8, 0x61, 0x9c, 0x18, 0xd3, 0xc6, 0x4f, 0xce, 0xfc, 0x91, 0xbb,
|
||||
0xd6, 0x9f, 0x18, 0x5c, 0x9a, 0xe5, 0x3b, 0xb9, 0x13, 0x9a, 0x83, 0x39, 0xa3, 0x91, 0xb8, 0x1b,
|
||||
0x9a, 0x37, 0xca, 0xee, 0x45, 0x98, 0xe4, 0xe0, 0x17, 0x1b, 0x8d, 0xc9, 0xa9, 0x5b, 0xb7, 0x6e,
|
||||
0x5e, 0xbb, 0x79, 0xfd, 0x4b, 0xb7, 0x22, 0x6f, 0x3b, 0x7b, 0x55, 0xa5, 0x41, 0xb5, 0xf8, 0x70,
|
||||
0xaf, 0x0a, 0xca, 0x46, 0x76, 0xf7, 0xab, 0x05, 0x9a, 0xf0, 0x89, 0x7c, 0xe3, 0xc4, 0xc3, 0x38,
|
||||
0x18, 0x81, 0x7b, 0xfa, 0xe9, 0x26, 0xda, 0xb6, 0x28, 0x26, 0x75, 0x6b, 0xb3, 0xd6, 0xa2, 0xc6,
|
||||
0xa3, 0x62, 0x32, 0x9f, 0xeb, 0x84, 0xe6, 0xa9, 0x26, 0xda, 0x5e, 0xc1, 0xa4, 0x7e, 0xa7, 0xd6,
|
||||
0xe2, 0xc1, 0x65, 0x40, 0xb8, 0x25, 0xc9, 0x92, 0xf9, 0x81, 0xb2, 0x62, 0x62, 0xd0, 0xc7, 0xf6,
|
||||
0x56, 0x64, 0xf0, 0xb1, 0x9c, 0x41, 0x88, 0xed, 0xad, 0xa2, 0xc1, 0x44, 0x96, 0x33, 0x98, 0x08,
|
||||
0xc1, 0x1f, 0x34, 0x7d, 0xc4, 0xc7, 0xb6, 0x47, 0x08, 0xb6, 0x79, 0x78, 0xb7, 0x1c, 0xc2, 0xb0,
|
||||
0xbf, 0x85, 0x5c, 0x8b, 0x1a, 0x27, 0x85, 0xed, 0xaf, 0x8a, 0xa0, 0x9e, 0xa8, 0x2c, 0xc4, 0xf0,
|
||||
0x0a, 0x8f, 0x1d, 0x72, 0xc3, 0x14, 0xe8, 0x86, 0xe6, 0xb8, 0xe8, 0x5b, 0x89, 0x4a, 0xb3, 0x74,
|
||||
0x63, 0x22, 0xa1, 0x74, 0xb8, 0x57, 0x3d, 0x7a, 0x63, 0x42, 0xc4, 0xf7, 0x52, 0x3f, 0x50, 0xdd,
|
||||
0x0b, 0x68, 0xe8, 0xfd, 0x3e, 0x76, 0xd1, 0x0e, 0x4d, 0x63, 0x80, 0x2e, 0x62, 0xc0, 0xcb, 0x9d,
|
||||
0xd0, 0x3c, 0x1d, 0x21, 0xd9, 0x46, 0xaf, 0xc4, 0x84, 0x24, 0x69, 0x71, 0x87, 0x27, 0x3b, 0x16,
|
||||
0xe6, 0x1b, 0x83, 0x77, 0x8e, 0xea, 0x17, 0xe2, 0x8e, 0x52, 0x22, 0xd9, 0x20, 0x35, 0x8d, 0x53,
|
||||
0x62, 0x90, 0xfe, 0xca, 0xd7, 0xf0, 0x08, 0xe4, 0x7a, 0x25, 0x17, 0x96, 0x3a, 0xa1, 0x39, 0xe2,
|
||||
0xab, 0xa1, 0x34, 0xd0, 0xf6, 0xc0, 0x25, 0x96, 0x93, 0x13, 0xd2, 0x96, 0xed, 0x69, 0xaf, 0x37,
|
||||
0xc4, 0x07, 0x79, 0x92, 0x0f, 0x72, 0x2f, 0x9a, 0xd0, 0x88, 0xfc, 0x2c, 0x23, 0xa0, 0xa6, 0x9f,
|
||||
0xa6, 0x0c, 0xf9, 0xcc, 0xaa, 0xf9, 0x5e, 0x9b, 0x62, 0xdf, 0xe8, 0x13, 0x63, 0xfd, 0xff, 0x9d,
|
||||
0xd0, 0xec, 0x13, 0xc0, 0x4c, 0x24, 0xef, 0x86, 0xe6, 0x93, 0xc2, 0x1d, 0x59, 0xd8, 0x73, 0xa4,
|
||||
0x73, 0x4d, 0xc1, 0x2f, 0x35, 0xfd, 0x1c, 0x41, 0xcc, 0x62, 0x3e, 0xe2, 0xa7, 0x1a, 0x72, 0xd3,
|
||||
0x89, 0xed, 0x17, 0x9d, 0xbd, 0x71, 0x10, 0x9a, 0xfa, 0xdd, 0xe9, 0xd5, 0x2c, 0xac, 0xeb, 0x04,
|
||||
0xb1, 0x6c, 0x8e, 0x4d, 0xd1, 0x71, 0x26, 0x52, 0x84, 0x70, 0xb9, 0x41, 0xee, 0x4b, 0x0a, 0xd7,
|
||||
0x52, 0x17, 0x70, 0x90, 0x20, 0xb6, 0x9a, 0xd0, 0x49, 0x16, 0xc4, 0x9f, 0x4a, 0x3c, 0x5d, 0x8c,
|
||||
0x28, 0xb6, 0x9a, 0xc6, 0x19, 0xb1, 0x14, 0xbe, 0xc9, 0x97, 0xc2, 0xc9, 0xbb, 0xd3, 0xab, 0x8b,
|
||||
0x5c, 0xcc, 0x27, 0xff, 0x0c, 0x41, 0x2c, 0xfa, 0x70, 0x48, 0xc0, 0x44, 0xf2, 0x53, 0x49, 0xc8,
|
||||
0xca, 0x72, 0xe5, 0xde, 0xe8, 0xec, 0x55, 0x4b, 0xed, 0xcb, 0xa2, 0x74, 0x07, 0x65, 0x1d, 0x43,
|
||||
0x20, 0xb3, 0x8f, 0x64, 0xe0, 0xef, 0x9a, 0x3e, 0x92, 0x27, 0xef, 0x63, 0x82, 0xdb, 0x62, 0x25,
|
||||
0x9f, 0x15, 0xf4, 0x77, 0x39, 0xfd, 0x53, 0x77, 0xa7, 0x57, 0x61, 0x04, 0x70, 0x07, 0x06, 0x08,
|
||||
0x62, 0xc9, 0x67, 0xea, 0x42, 0x35, 0x71, 0x21, 0x8f, 0x48, 0x4e, 0x5c, 0x93, 0x9d, 0x50, 0xd8,
|
||||
0x50, 0x09, 0xb9, 0x23, 0xd7, 0xb8, 0x23, 0x32, 0x05, 0x38, 0x24, 0xbb, 0x92, 0x48, 0x15, 0xce,
|
||||
0x30, 0xa7, 0x89, 0xbd, 0x80, 0x59, 0xd4, 0x18, 0xc8, 0x3b, 0xb3, 0x1a, 0x01, 0x2b, 0xb1, 0x33,
|
||||
0xc9, 0x27, 0x5f, 0xe9, 0xf5, 0x9c, 0x33, 0x79, 0xa4, 0xd7, 0xf6, 0x53, 0xd8, 0x50, 0x09, 0xd3,
|
||||
0x2d, 0x27, 0x53, 0xc8, 0x3b, 0x93, 0x48, 0xc1, 0x4f, 0x34, 0xdd, 0x08, 0x28, 0x5a, 0xc7, 0x96,
|
||||
0x8f, 0xf9, 0xb9, 0xef, 0x90, 0x75, 0x0b, 0xd9, 0x36, 0x6e, 0x31, 0x5c, 0x37, 0x80, 0xf0, 0x06,
|
||||
0xf1, 0x1d, 0xb0, 0x06, 0xa7, 0x63, 0x29, 0xdf, 0x01, 0x81, 0x9f, 0x7c, 0x75, 0x43, 0xf3, 0xac,
|
||||
0x70, 0x22, 0x13, 0x49, 0x84, 0x65, 0xc5, 0xdc, 0x17, 0x5f, 0xf1, 0x99, 0x49, 0x38, 0x2c, 0x28,
|
||||
0xc0, 0x84, 0x41, 0x22, 0x07, 0x6f, 0xe9, 0x43, 0x45, 0x72, 0x14, 0x63, 0x62, 0x0c, 0x0a, 0x62,
|
||||
0x0b, 0x07, 0xa1, 0x79, 0x62, 0x0d, 0xae, 0x60, 0x4c, 0x3a, 0xa1, 0x79, 0x22, 0xf0, 0xf9, 0xaf,
|
||||
0x6e, 0x68, 0xf6, 0xc5, 0x84, 0xf8, 0xa7, 0x44, 0x26, 0x51, 0x48, 0x7f, 0xed, 0xee, 0x57, 0xe3,
|
||||
0xe6, 0x10, 0xe4, 0x09, 0x70, 0x19, 0xf8, 0x81, 0xa6, 0x3f, 0x5e, 0xec, 0x3d, 0x20, 0xce, 0x1b,
|
||||
0x01, 0xb6, 0x9c, 0xba, 0x31, 0x24, 0x92, 0x88, 0xd7, 0xa3, 0xb1, 0x59, 0x13, 0xe2, 0x85, 0xb9,
|
||||
0x68, 0x6c, 0xe2, 0x2f, 0x79, 0x6c, 0x12, 0x85, 0x4a, 0x34, 0x28, 0xc9, 0x67, 0x57, 0xfe, 0x8a,
|
||||
0x07, 0x25, 0xc1, 0x8a, 0x83, 0x92, 0x68, 0x81, 0xbf, 0x68, 0xfa, 0x60, 0x89, 0x97, 0xef, 0x1a,
|
||||
0xe7, 0x04, 0xa3, 0xef, 0xf0, 0xb5, 0x77, 0x7c, 0x0d, 0xae, 0xc1, 0xc5, 0x4e, 0x68, 0x1e, 0x0f,
|
||||
0xfc, 0x35, 0xb8, 0xd8, 0x0d, 0xcd, 0x9b, 0x09, 0x11, 0xb8, 0x28, 0xad, 0xae, 0x0d, 0xc6, 0x5a,
|
||||
0xf4, 0xd6, 0xd5, 0xab, 0x75, 0xc4, 0xd0, 0x15, 0xba, 0x43, 0x6c, 0xb6, 0xc1, 0x8b, 0x35, 0x82,
|
||||
0xd9, 0x55, 0x82, 0xdb, 0x5c, 0xca, 0x09, 0xc7, 0x46, 0x92, 0x1f, 0x87, 0x7b, 0xd5, 0x87, 0x68,
|
||||
0xb8, 0xbb, 0x5f, 0x8d, 0x58, 0xc0, 0x81, 0x82, 0x1f, 0xbe, 0x0b, 0xfe, 0xad, 0xe9, 0x66, 0xd1,
|
||||
0x85, 0x96, 0x47, 0xf9, 0x09, 0x47, 0xb1, 0x1d, 0xf8, 0xd8, 0xdd, 0x31, 0x86, 0x45, 0xf8, 0xfd,
|
||||
0x91, 0xa8, 0x20, 0xd6, 0xe0, 0xb2, 0x47, 0xd9, 0x42, 0x0a, 0x76, 0x42, 0xf3, 0x6c, 0xe0, 0xe7,
|
||||
0x65, 0xdd, 0xd0, 0x7c, 0x2a, 0x76, 0x32, 0x0f, 0x48, 0xfe, 0x36, 0x90, 0x4b, 0x45, 0x48, 0x2e,
|
||||
0xb7, 0x56, 0xc8, 0x78, 0xe6, 0x29, 0x5a, 0xf0, 0x7a, 0xa1, 0x48, 0x01, 0x5e, 0xcc, 0xbb, 0x95,
|
||||
0x47, 0xc1, 0xbf, 0x14, 0x1e, 0x3a, 0xc4, 0x61, 0x0e, 0xaf, 0x23, 0xf8, 0x79, 0x67, 0x51, 0x63,
|
||||
0x44, 0xac, 0xe2, 0x1f, 0x8a, 0xea, 0x61, 0x0d, 0x2e, 0x44, 0xe8, 0x1c, 0x07, 0x79, 0xc0, 0x38,
|
||||
0x13, 0xf8, 0x39, 0x51, 0x1a, 0x2e, 0x0a, 0x72, 0x39, 0x58, 0xdc, 0x9c, 0xc8, 0x05, 0xf0, 0xa2,
|
||||
0x85, 0xb2, 0x88, 0x9f, 0x40, 0xbc, 0x15, 0x2f, 0x18, 0x0a, 0x14, 0xe0, 0x85, 0xbc, 0x83, 0x39,
|
||||
0x10, 0x78, 0xfa, 0x80, 0x8f, 0xa3, 0xc3, 0xd9, 0x23, 0x56, 0x1b, 0x6d, 0xe2, 0xa0, 0x65, 0x18,
|
||||
0x62, 0xca, 0x66, 0x39, 0xf9, 0x18, 0xbc, 0x47, 0x5e, 0x13, 0x50, 0x4a, 0xbe, 0x20, 0xef, 0x79,
|
||||
0x48, 0x17, 0x0d, 0x80, 0x6f, 0x69, 0xfa, 0x08, 0x0a, 0x98, 0x67, 0x05, 0xad, 0x75, 0x1f, 0xd5,
|
||||
0x71, 0x96, 0x0c, 0x6d, 0x18, 0x8f, 0x8b, 0x81, 0x5c, 0xe6, 0x25, 0x17, 0x57, 0x59, 0x8b, 0x34,
|
||||
0x92, 0x3c, 0xe2, 0x76, 0x5a, 0x9d, 0xa8, 0x40, 0x79, 0xf8, 0xa6, 0xe4, 0xcc, 0x70, 0x72, 0x0a,
|
||||
0x2a, 0xad, 0x81, 0xa6, 0x3e, 0x92, 0x70, 0x60, 0x9e, 0xd5, 0xf2, 0xf9, 0x14, 0x8b, 0xb3, 0x98,
|
||||
0x1a, 0xe7, 0xc5, 0x00, 0xdc, 0xe0, 0x44, 0x62, 0x95, 0x55, 0x6f, 0xd9, 0xc7, 0x30, 0xc6, 0xbb,
|
||||
0xa1, 0x79, 0x3e, 0x9a, 0x42, 0x05, 0x58, 0x81, 0xca, 0x36, 0x60, 0x4b, 0x07, 0x9b, 0x18, 0xb7,
|
||||
0x2c, 0x86, 0x9b, 0x2d, 0xcf, 0x47, 0xbe, 0x83, 0xa9, 0xb5, 0x61, 0x5c, 0x10, 0x2e, 0xdf, 0xe6,
|
||||
0x1b, 0x81, 0xa3, 0xab, 0x19, 0xc8, 0xdd, 0xbd, 0x24, 0x7a, 0x29, 0x02, 0x72, 0x2d, 0x76, 0x5d,
|
||||
0x76, 0x75, 0xea, 0x3a, 0x2c, 0x59, 0x01, 0x3b, 0xfa, 0xa0, 0x8d, 0xec, 0x0d, 0x6c, 0x39, 0xeb,
|
||||
0xc4, 0xf3, 0x71, 0xdd, 0x6a, 0x38, 0x2e, 0xa6, 0xc6, 0x45, 0xe1, 0xe2, 0x02, 0x3f, 0xd1, 0x04,
|
||||
0xbc, 0x10, 0xa1, 0xf3, 0x1c, 0x4c, 0x07, 0xba, 0x84, 0x94, 0xf6, 0x60, 0xba, 0xb7, 0x60, 0xd9,
|
||||
0x0c, 0xf8, 0x9e, 0xa6, 0x9f, 0x6f, 0xf9, 0xde, 0x3a, 0x2f, 0x66, 0xac, 0xa0, 0x55, 0x47, 0x0c,
|
||||
0xcb, 0x05, 0xc2, 0x13, 0xc2, 0xf7, 0x55, 0x9e, 0xdf, 0x26, 0x5a, 0x6b, 0x42, 0x49, 0x2e, 0x06,
|
||||
0xa2, 0x22, 0xbb, 0x07, 0x2e, 0xd1, 0x79, 0x51, 0x1a, 0x08, 0xed, 0x45, 0xd8, 0xcb, 0x22, 0x78,
|
||||
0x47, 0xd3, 0x87, 0x5d, 0xa7, 0xe9, 0x30, 0xab, 0x86, 0x48, 0xbd, 0xed, 0xd4, 0xd9, 0x86, 0xe5,
|
||||
0x10, 0xcb, 0x45, 0xc4, 0x18, 0x15, 0x43, 0xb2, 0x24, 0x8a, 0x47, 0xae, 0x31, 0x93, 0x28, 0x2c,
|
||||
0x90, 0x45, 0x44, 0xb2, 0x82, 0xbf, 0x8c, 0x7d, 0xc6, 0xb0, 0xa8, 0x4c, 0x81, 0xb7, 0x35, 0x1d,
|
||||
0x34, 0x1d, 0x62, 0x6d, 0x78, 0x4d, 0x6c, 0xd5, 0x1d, 0xba, 0x69, 0x35, 0x7c, 0x8c, 0x0d, 0x73,
|
||||
0x4c, 0x1b, 0x3f, 0x35, 0xd5, 0x77, 0x25, 0xba, 0x59, 0xbb, 0xb2, 0xe2, 0xbc, 0x89, 0x67, 0x5e,
|
||||
0xf9, 0x30, 0x34, 0x8f, 0xf0, 0x9d, 0xd8, 0x74, 0xc8, 0x6d, 0xaf, 0x89, 0xe7, 0x1c, 0xba, 0x39,
|
||||
0xef, 0x63, 0x9c, 0xae, 0x8e, 0x82, 0x5c, 0xde, 0x07, 0x63, 0x97, 0x39, 0x91, 0x63, 0x93, 0x63,
|
||||
0x97, 0x61, 0xb1, 0x39, 0xb8, 0xaf, 0xe9, 0x7d, 0xc9, 0x7a, 0x17, 0xc7, 0xce, 0x98, 0x38, 0x76,
|
||||
0xfe, 0x2c, 0x52, 0x9e, 0x64, 0xd1, 0x46, 0x87, 0xcf, 0x29, 0x3f, 0xfb, 0xec, 0x86, 0xe6, 0x5c,
|
||||
0x52, 0x71, 0x24, 0x32, 0xc5, 0x41, 0x14, 0xef, 0x00, 0x5a, 0x38, 0x53, 0x9a, 0x98, 0xa1, 0x2b,
|
||||
0x5f, 0xa6, 0x1e, 0xe1, 0xb1, 0x3b, 0x67, 0x36, 0xff, 0x79, 0xb8, 0x57, 0x1d, 0x7f, 0x58, 0x53,
|
||||
0x3c, 0x3f, 0x92, 0xf8, 0xc2, 0xcc, 0x8e, 0xef, 0x82, 0xd7, 0xf4, 0x01, 0xe4, 0xb6, 0x79, 0xf5,
|
||||
0x15, 0xdd, 0x26, 0x10, 0xcc, 0xa8, 0xf1, 0xa4, 0xb8, 0xc4, 0xe3, 0x45, 0xef, 0x99, 0x08, 0x14,
|
||||
0x55, 0xf9, 0x5d, 0xcc, 0xf8, 0xc2, 0x1f, 0x8a, 0x22, 0x4c, 0x4e, 0x5e, 0x81, 0x45, 0x45, 0xf0,
|
||||
0x5f, 0x4d, 0x1f, 0xf7, 0xb6, 0xb0, 0xdf, 0xf6, 0x1d, 0xc6, 0x03, 0x47, 0xd3, 0x63, 0xd8, 0xaa,
|
||||
0xe3, 0x2d, 0xc7, 0xc6, 0x16, 0x41, 0x4d, 0x4c, 0x79, 0x38, 0x8d, 0x0b, 0x21, 0xa3, 0x92, 0x5d,
|
||||
0x2f, 0x8d, 0xdc, 0x4b, 0x1a, 0x41, 0xd1, 0x66, 0x0e, 0x6f, 0xdd, 0xe5, 0xea, 0x9d, 0xd0, 0xbc,
|
||||
0xe4, 0x95, 0x20, 0xc7, 0xc6, 0x02, 0xbd, 0x47, 0x66, 0x23, 0x53, 0xdd, 0xd0, 0x7c, 0x49, 0x10,
|
||||
0x7c, 0x08, 0xdd, 0xde, 0x8b, 0x92, 0x57, 0x71, 0x3d, 0x78, 0xc0, 0x87, 0x61, 0x01, 0xbe, 0xa6,
|
||||
0x9f, 0xe3, 0x61, 0xcc, 0x72, 0x48, 0x1d, 0x6f, 0x5b, 0x7c, 0x25, 0xd7, 0x5c, 0xcf, 0xde, 0xa4,
|
||||
0xc6, 0x25, 0xb1, 0xa5, 0xf9, 0xa2, 0x01, 0x5c, 0x61, 0x81, 0xe3, 0x4b, 0x0e, 0x99, 0x11, 0x68,
|
||||
0x7a, 0x6b, 0x5b, 0x86, 0x94, 0x99, 0x72, 0x94, 0xff, 0x42, 0x85, 0x25, 0xf0, 0x4f, 0x9e, 0xee,
|
||||
0x12, 0x64, 0x6f, 0xe2, 0xba, 0x45, 0x3c, 0xe6, 0x34, 0x1c, 0x1b, 0x45, 0xf7, 0x0f, 0x75, 0x6a,
|
||||
0x54, 0xc5, 0xfc, 0xbe, 0xcb, 0x87, 0x7b, 0x78, 0x2d, 0x52, 0xba, 0x2b, 0xe9, 0x2c, 0xcc, 0xf1,
|
||||
0xd1, 0x1e, 0x0e, 0x94, 0x48, 0x37, 0x34, 0x2f, 0x44, 0xa1, 0x5d, 0x05, 0x8b, 0xbb, 0x4a, 0x25,
|
||||
0xd2, 0xdd, 0xab, 0xf6, 0xb0, 0xb8, 0xbb, 0x5f, 0xed, 0xc1, 0x02, 0x2a, 0x5b, 0xd4, 0x29, 0x80,
|
||||
0xfa, 0x69, 0xe6, 0xa3, 0x46, 0xc3, 0xb1, 0x2d, 0xdb, 0x45, 0x94, 0x1a, 0x97, 0xc5, 0xb0, 0xbe,
|
||||
0xc0, 0xeb, 0xe5, 0x18, 0x98, 0xe5, 0xf2, 0x6e, 0x68, 0x82, 0x68, 0x40, 0x25, 0x61, 0x7a, 0x51,
|
||||
0x93, 0x53, 0x05, 0x6f, 0xe9, 0x83, 0xf1, 0x10, 0x5b, 0x0d, 0xcf, 0xad, 0x63, 0xdf, 0x6a, 0x21,
|
||||
0xb6, 0x61, 0x3c, 0x25, 0x76, 0xfd, 0x9d, 0x83, 0xd0, 0xbc, 0x30, 0x87, 0x5b, 0x3e, 0xb6, 0x11,
|
||||
0xc3, 0xf5, 0xb9, 0x48, 0x71, 0x5e, 0xe8, 0x2d, 0x23, 0xb6, 0xd1, 0x09, 0x4d, 0xed, 0x85, 0xb4,
|
||||
0x3a, 0xaf, 0x17, 0xe1, 0xe7, 0xbd, 0xa6, 0xc3, 0x27, 0x89, 0xed, 0x54, 0x0c, 0x0d, 0x0e, 0x94,
|
||||
0x70, 0xb0, 0xa9, 0x9f, 0xa5, 0x98, 0x59, 0xae, 0xd7, 0xb6, 0x5a, 0xbe, 0xe3, 0xf9, 0x0e, 0xdb,
|
||||
0x31, 0x9e, 0x16, 0x9b, 0x62, 0xba, 0x13, 0x9a, 0xfd, 0x14, 0xb3, 0x45, 0xaf, 0xbd, 0x1c, 0x23,
|
||||
0x69, 0x64, 0xcb, 0x8b, 0x7b, 0xa6, 0x18, 0x85, 0xe6, 0xe0, 0x3d, 0x4d, 0x1f, 0x6e, 0xa2, 0xed,
|
||||
0xc4, 0x4d, 0xdb, 0x23, 0x76, 0xe0, 0xfb, 0x98, 0xd8, 0x3b, 0xc6, 0xb8, 0x18, 0x47, 0x2a, 0x2e,
|
||||
0x5b, 0x50, 0x7b, 0x09, 0x6d, 0x47, 0x1c, 0x67, 0x33, 0x15, 0x7e, 0xe4, 0x37, 0x15, 0xf2, 0xf4,
|
||||
0xc8, 0x57, 0x81, 0xc9, 0x90, 0x8b, 0xdb, 0x11, 0xb5, 0x5d, 0xa8, 0xb4, 0x0a, 0x3e, 0xd6, 0xf4,
|
||||
0x41, 0xdb, 0x47, 0x74, 0xa3, 0x50, 0x03, 0x3c, 0x23, 0xa6, 0xe5, 0x7d, 0x51, 0x03, 0xcc, 0x26,
|
||||
0x35, 0x80, 0x1d, 0xd7, 0x00, 0xf3, 0xd1, 0xd9, 0xcc, 0x9b, 0x65, 0xd9, 0xb8, 0x32, 0x0c, 0x0b,
|
||||
0x9d, 0x72, 0x5e, 0x2f, 0xc4, 0x7c, 0x2d, 0x0f, 0x94, 0x8c, 0xf0, 0xea, 0xc0, 0x8e, 0xab, 0x83,
|
||||
0xea, 0xc3, 0x98, 0xe1, 0xf5, 0xc1, 0x6c, 0x54, 0x1f, 0x14, 0x8c, 0xf9, 0x2e, 0xf8, 0x99, 0xa6,
|
||||
0x8f, 0x14, 0xdd, 0x4b, 0xae, 0x65, 0x9e, 0x15, 0xf3, 0xef, 0x1c, 0x84, 0xe6, 0xc9, 0x59, 0x28,
|
||||
0xbd, 0x28, 0xe4, 0xad, 0x14, 0x5f, 0x14, 0x94, 0x68, 0xaf, 0xa5, 0xb1, 0xbb, 0x5f, 0xcd, 0x6c,
|
||||
0x43, 0xb5, 0x65, 0xf0, 0x0d, 0x4d, 0x1f, 0xa6, 0x2c, 0x20, 0x16, 0xcf, 0x9c, 0x90, 0xeb, 0x6c,
|
||||
0x61, 0x2b, 0xca, 0x87, 0xa9, 0xf1, 0x5c, 0x9a, 0x8f, 0x0e, 0x72, 0x8d, 0x3b, 0x89, 0xc2, 0x0a,
|
||||
0xc7, 0x57, 0xd2, 0x2c, 0x49, 0x81, 0xe5, 0x93, 0x79, 0x29, 0xa0, 0x1d, 0x9b, 0xbc, 0x39, 0x01,
|
||||
0x55, 0xd6, 0x78, 0x8d, 0x5c, 0xa0, 0xc1, 0xe3, 0x2a, 0x35, 0x9e, 0x17, 0x24, 0x5e, 0xe5, 0x89,
|
||||
0x5a, 0xae, 0xd9, 0x92, 0x43, 0xb2, 0x5a, 0xa2, 0x84, 0xc8, 0x39, 0x62, 0x2e, 0xa0, 0x4e, 0x4d,
|
||||
0xc0, 0xb2, 0x1d, 0x9e, 0x95, 0xf7, 0x89, 0xde, 0x93, 0x87, 0xae, 0x17, 0x44, 0x0c, 0xad, 0x1f,
|
||||
0x84, 0x66, 0x3f, 0x44, 0xed, 0x15, 0x16, 0x48, 0x4f, 0x5c, 0xa7, 0x68, 0xf6, 0x99, 0x5e, 0x46,
|
||||
0x65, 0xb2, 0x07, 0x3e, 0xc3, 0x15, 0x2c, 0x42, 0xd9, 0x1e, 0xd8, 0xd2, 0xcf, 0xf0, 0xb2, 0xb3,
|
||||
0x86, 0x28, 0xb6, 0xa2, 0x37, 0x47, 0xe3, 0xca, 0x98, 0x36, 0xde, 0x3f, 0xd5, 0x9f, 0xa4, 0x45,
|
||||
0xab, 0x42, 0x2a, 0x6e, 0x0f, 0xfb, 0x13, 0xd5, 0x48, 0x96, 0x46, 0x8e, 0xbc, 0xb8, 0x32, 0x16,
|
||||
0x17, 0x21, 0xf1, 0xf2, 0x78, 0x7b, 0xbf, 0xaa, 0xc1, 0x42, 0x53, 0xf0, 0xfd, 0xa3, 0xfa, 0x25,
|
||||
0x1e, 0x35, 0xd2, 0x70, 0xc1, 0x8b, 0x58, 0xdb, 0x6b, 0xf2, 0x25, 0xeb, 0xe3, 0x37, 0x02, 0x4c,
|
||||
0x99, 0xb5, 0xe9, 0xd4, 0x8c, 0xab, 0x62, 0x3a, 0xfe, 0xa6, 0xc5, 0x6f, 0x95, 0x4b, 0x68, 0x7b,
|
||||
0x76, 0x01, 0x46, 0xf8, 0x1d, 0x67, 0xa6, 0x13, 0x9a, 0x66, 0x13, 0x6d, 0xa7, 0x5b, 0x9c, 0x2d,
|
||||
0xc4, 0x36, 0x32, 0x95, 0xf4, 0x14, 0x7c, 0x80, 0x9e, 0x54, 0x00, 0x3e, 0xd0, 0xe4, 0x83, 0x55,
|
||||
0xe2, 0xd7, 0xcf, 0x02, 0x5d, 0xf8, 0x80, 0x66, 0x35, 0xf0, 0xa9, 0xa6, 0x0f, 0xa7, 0x4f, 0x30,
|
||||
0x2e, 0x92, 0x1f, 0x6d, 0x27, 0xc4, 0x06, 0xfe, 0x80, 0x8f, 0xc4, 0x50, 0xf2, 0x84, 0xb1, 0x38,
|
||||
0x7d, 0x57, 0x7e, 0xb7, 0x1d, 0x42, 0x0a, 0x79, 0x9a, 0x48, 0xab, 0x40, 0xd5, 0xcb, 0x99, 0xd2,
|
||||
0x48, 0x0f, 0xb9, 0xb4, 0xf5, 0x95, 0xa4, 0x60, 0xd6, 0x0a, 0x49, 0x8f, 0xbe, 0x5b, 0xfa, 0x79,
|
||||
0xf1, 0xca, 0xd2, 0x08, 0x5c, 0x37, 0xce, 0x6a, 0x3c, 0x92, 0x94, 0xa8, 0xc6, 0xa4, 0xf0, 0xf4,
|
||||
0x16, 0xcf, 0x1a, 0xb8, 0xd6, 0x7c, 0xe0, 0xba, 0x22, 0x1f, 0xb9, 0x47, 0xe2, 0xa2, 0xb2, 0x1b,
|
||||
0x9a, 0x17, 0xe3, 0x23, 0x4b, 0x05, 0x57, 0x60, 0x8f, 0x76, 0xe0, 0x55, 0xfd, 0x74, 0x03, 0x23,
|
||||
0x16, 0xf8, 0xd8, 0x6a, 0xb8, 0x68, 0x9d, 0x1a, 0x53, 0x62, 0xdf, 0x5d, 0xe6, 0x27, 0x7d, 0x0c,
|
||||
0xcc, 0x73, 0x79, 0xfa, 0x22, 0x23, 0x09, 0x2b, 0x30, 0xa7, 0x02, 0xda, 0xfa, 0x88, 0xf4, 0x10,
|
||||
0x13, 0xd5, 0x38, 0x98, 0x78, 0xc1, 0xfa, 0x86, 0x71, 0x4d, 0x2c, 0xda, 0x97, 0x45, 0x78, 0x4d,
|
||||
0x55, 0x16, 0xb9, 0xc6, 0x2b, 0x42, 0x21, 0xcd, 0x7a, 0x94, 0x68, 0x9a, 0x51, 0xa8, 0x1b, 0x83,
|
||||
0x4d, 0x7d, 0xa8, 0xd4, 0x71, 0x13, 0x6d, 0x1b, 0xd7, 0x45, 0xaf, 0x2f, 0xf1, 0x64, 0xb0, 0xd0,
|
||||
0x70, 0x09, 0x6d, 0x77, 0x43, 0xd3, 0x50, 0x75, 0xb9, 0x84, 0xb6, 0xd3, 0xfe, 0x14, 0xcd, 0xc0,
|
||||
0x57, 0xf4, 0xbe, 0xa0, 0x45, 0x5a, 0xe9, 0x31, 0xf2, 0xab, 0x79, 0x31, 0x39, 0x5f, 0x38, 0x08,
|
||||
0xcd, 0x73, 0x59, 0x06, 0xb3, 0xb6, 0x4c, 0x96, 0xb3, 0x33, 0x45, 0xe4, 0x2e, 0x71, 0x5a, 0xd7,
|
||||
0x22, 0xad, 0x18, 0x90, 0xb2, 0x96, 0xdd, 0xfd, 0xaa, 0xba, 0xb1, 0xa1, 0xc1, 0x53, 0x52, 0x13,
|
||||
0xf0, 0x0b, 0x2d, 0xee, 0x3e, 0xb9, 0xb4, 0x7f, 0x6f, 0x5e, 0x38, 0xf9, 0xb6, 0xd8, 0x05, 0x79,
|
||||
0x13, 0xe9, 0x05, 0xbe, 0xe8, 0x7e, 0x2c, 0xed, 0x5e, 0xbe, 0x78, 0x97, 0x38, 0x64, 0xdb, 0xfd,
|
||||
0x7c, 0x6f, 0x2d, 0xbe, 0xac, 0x55, 0xbd, 0x18, 0x1a, 0xd4, 0xb3, 0x56, 0xe0, 0x77, 0x9a, 0xde,
|
||||
0x2f, 0x68, 0x66, 0xd7, 0xf3, 0xbf, 0x8e, 0x88, 0x7e, 0x5b, 0x64, 0xc5, 0x79, 0x13, 0xd2, 0x55,
|
||||
0xbd, 0xa0, 0x5a, 0x49, 0xa9, 0xe6, 0x2f, 0xd7, 0x95, 0x64, 0x2f, 0x7e, 0x96, 0x1e, 0xcf, 0x7d,
|
||||
0xd5, 0x7d, 0x19, 0x1a, 0xec, 0x93, 0x5b, 0x66, 0x94, 0xb3, 0x4b, 0xf8, 0xf7, 0x7b, 0x53, 0x96,
|
||||
0x2e, 0xe4, 0x0b, 0x94, 0xf3, 0x57, 0xe8, 0xbd, 0x29, 0xf7, 0xd2, 0x2b, 0x53, 0x4e, 0x34, 0x13,
|
||||
0xca, 0xe9, 0x9d, 0x7b, 0x43, 0x8f, 0x1e, 0xfb, 0xd2, 0x43, 0xf3, 0x37, 0xf3, 0x62, 0xf7, 0x7e,
|
||||
0x2e, 0xcf, 0x57, 0xbc, 0x97, 0x65, 0xa7, 0xa7, 0xb4, 0x18, 0xfd, 0x0c, 0xc9, 0xa7, 0xd0, 0x7d,
|
||||
0x12, 0x42, 0xc5, 0x95, 0x45, 0xf9, 0xb6, 0xc0, 0x6a, 0xd9, 0xcc, 0xf8, 0x80, 0x0f, 0x91, 0x36,
|
||||
0xb3, 0x74, 0x10, 0x9a, 0x17, 0xb3, 0x1e, 0x97, 0xf2, 0xb5, 0xfe, 0xb2, 0xcd, 0xf2, 0xe3, 0xd4,
|
||||
0x2c, 0xe1, 0xf9, 0xee, 0x41, 0x59, 0x81, 0x67, 0x08, 0x43, 0x85, 0xf3, 0x91, 0xda, 0x88, 0x50,
|
||||
0xe3, 0xb7, 0xd1, 0x2c, 0xad, 0x16, 0x28, 0xc8, 0xe7, 0xca, 0x0a, 0x57, 0x2c, 0x50, 0x28, 0xe1,
|
||||
0xe5, 0xa9, 0x12, 0x4c, 0x4a, 0x7a, 0x33, 0x77, 0x3e, 0xfc, 0x64, 0xf4, 0xc8, 0xfe, 0x27, 0xa3,
|
||||
0x47, 0x3e, 0x3c, 0x18, 0xd5, 0xf6, 0x0f, 0x46, 0xb5, 0xef, 0xde, 0x1f, 0x3d, 0xf2, 0xee, 0xfd,
|
||||
0x51, 0x6d, 0xff, 0xfe, 0xe8, 0x91, 0x8f, 0xee, 0x8f, 0x1e, 0x79, 0xfd, 0x99, 0x75, 0x87, 0x6d,
|
||||
0x04, 0xb5, 0x2b, 0xb6, 0xd7, 0xbc, 0x9a, 0x66, 0xad, 0xd2, 0xaf, 0xec, 0xdf, 0x4b, 0xb5, 0x13,
|
||||
0xe2, 0xef, 0x4a, 0xd7, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x30, 0xd1, 0x0d, 0x1a, 0x25,
|
||||
0x00, 0x00,
|
||||
0xd9, 0xce, 0x26, 0x4d, 0xda, 0x6c, 0x1c, 0x27, 0x1e, 0x3b, 0xf6, 0x36, 0x49, 0xbd, 0xee, 0xc9,
|
||||
0x49, 0xeb, 0xfe, 0x25, 0xb6, 0x93, 0xe6, 0x4b, 0x23, 0x7d, 0xea, 0xe7, 0x9f, 0xfa, 0xab, 0x1b,
|
||||
0x3b, 0xb1, 0xc6, 0xf6, 0xd7, 0x4f, 0x45, 0x68, 0x35, 0xde, 0x9d, 0x63, 0x2f, 0xde, 0x33, 0x7b,
|
||||
0xba, 0x33, 0xeb, 0x9f, 0x16, 0x41, 0x55, 0x04, 0xe5, 0x0e, 0xb0, 0xf8, 0x91, 0x40, 0x42, 0x45,
|
||||
0x80, 0x44, 0x29, 0x45, 0x48, 0x48, 0x48, 0x70, 0x43, 0x85, 0x84, 0x54, 0xc1, 0x85, 0x7d, 0x89,
|
||||
0x44, 0x59, 0x54, 0xa7, 0x57, 0xe7, 0x82, 0x8b, 0x73, 0x69, 0x6e, 0xd0, 0xcc, 0xfe, 0xcd, 0xee,
|
||||
0xce, 0x49, 0x72, 0x77, 0xf6, 0x7d, 0xde, 0x79, 0xe7, 0x79, 0xe7, 0xe7, 0x9d, 0xf7, 0x9d, 0x39,
|
||||
0xfa, 0x65, 0xcf, 0x5d, 0xbd, 0x6a, 0xfb, 0xa4, 0xe1, 0xae, 0x5d, 0xf5, 0x5b, 0xcc, 0xf5, 0x09,
|
||||
0x8d, 0xbf, 0xc2, 0x00, 0xf1, 0xaf, 0x2b, 0xad, 0xc0, 0x67, 0x3e, 0x38, 0x11, 0x0b, 0xcf, 0x0f,
|
||||
0x49, 0xea, 0x2c, 0x24, 0x2e, 0x59, 0x8b, 0x15, 0xce, 0x9f, 0x93, 0x00, 0xea, 0xbe, 0x85, 0x13,
|
||||
0xf1, 0x49, 0xbc, 0xcd, 0xe2, 0x9f, 0xb5, 0x83, 0xd7, 0xf4, 0x81, 0xbb, 0x71, 0x0f, 0xd3, 0x72,
|
||||
0x0f, 0xe0, 0xc7, 0x9a, 0x7e, 0xd6, 0x73, 0x29, 0xc3, 0xc4, 0x42, 0x8e, 0x13, 0x60, 0x4a, 0x31,
|
||||
0x35, 0xb4, 0x91, 0x63, 0xa3, 0x27, 0xa7, 0xe8, 0x41, 0x64, 0x02, 0x88, 0xb6, 0xe6, 0x05, 0x3c,
|
||||
0x99, 0xa2, 0xed, 0xc8, 0x3c, 0xe3, 0x15, 0x45, 0x9d, 0xc8, 0xbc, 0xbc, 0xdd, 0xf4, 0x6e, 0xd5,
|
||||
0x0a, 0xf2, 0xda, 0x88, 0x83, 0x1b, 0x28, 0xf4, 0xd8, 0xad, 0x5a, 0xf2, 0xa3, 0x76, 0xb8, 0x57,
|
||||
0x7f, 0x34, 0xf9, 0xbd, 0xbb, 0x5f, 0x57, 0x18, 0x87, 0x65, 0xd3, 0xe0, 0x5f, 0x9a, 0x6e, 0xac,
|
||||
0x79, 0xfe, 0x2a, 0xf2, 0x2c, 0xc7, 0xa5, 0xb6, 0xbf, 0x89, 0x83, 0x1d, 0x8b, 0xe2, 0x60, 0x13,
|
||||
0x07, 0xd4, 0x38, 0x2a, 0x88, 0xfe, 0x56, 0x3b, 0x88, 0xcc, 0x7e, 0x88, 0xb6, 0xfe, 0x57, 0xe8,
|
||||
0x4d, 0x12, 0xb2, 0x14, 0xe3, 0xed, 0xc8, 0x3c, 0xb7, 0x96, 0xca, 0xfc, 0x90, 0xd8, 0x38, 0x01,
|
||||
0x3a, 0x91, 0xf9, 0xbc, 0x20, 0xac, 0x42, 0x15, 0xbc, 0xdb, 0x7b, 0xf5, 0x01, 0x95, 0x6a, 0x67,
|
||||
0xaf, 0xae, 0xee, 0xa0, 0xe8, 0xa8, 0x8a, 0x1b, 0x1c, 0x8c, 0x1b, 0xce, 0xa4, 0x4e, 0x25, 0x72,
|
||||
0xf0, 0xb9, 0xca, 0x61, 0x4c, 0xd0, 0xaa, 0x87, 0x1d, 0xe3, 0xd8, 0x88, 0x36, 0xfa, 0xd8, 0xd4,
|
||||
0x07, 0xdc, 0xe1, 0xb3, 0x99, 0xc5, 0x57, 0x62, 0xb0, 0xea, 0x6d, 0x02, 0x74, 0x22, 0xf3, 0x59,
|
||||
0x85, 0xb7, 0x09, 0x2a, 0xb9, 0xcb, 0x82, 0x10, 0x73, 0x5f, 0xbb, 0x98, 0xe9, 0x06, 0x1c, 0xee,
|
||||
0xd5, 0x1f, 0xe1, 0x4d, 0x77, 0xf7, 0xeb, 0x15, 0x52, 0x15, 0x37, 0x13, 0x39, 0xf8, 0x54, 0xd3,
|
||||
0x87, 0x3c, 0xdf, 0x56, 0x7a, 0xf9, 0x88, 0xf0, 0xf2, 0xa7, 0xdc, 0xcb, 0x33, 0xf3, 0x5c, 0xa7,
|
||||
0xe0, 0xe4, 0x80, 0x97, 0x88, 0x4a, 0x3e, 0x3e, 0x13, 0x2f, 0x41, 0x05, 0xa8, 0x70, 0x51, 0x6d,
|
||||
0xa4, 0x8b, 0x5c, 0x72, 0xb0, 0xcc, 0x07, 0x9e, 0x13, 0x0d, 0x2a, 0xee, 0xfd, 0x55, 0xd3, 0xfb,
|
||||
0x63, 0xf7, 0x50, 0x62, 0xcb, 0x6a, 0xf9, 0x01, 0x33, 0x8e, 0x8f, 0x68, 0xa3, 0xc7, 0xa7, 0x7e,
|
||||
0xc8, 0x5d, 0xeb, 0x49, 0x4d, 0x2d, 0xfa, 0x01, 0x6b, 0x47, 0x66, 0x5f, 0xa1, 0x6b, 0x2e, 0xec,
|
||||
0x44, 0xe6, 0xd3, 0x55, 0xa7, 0x38, 0x22, 0x79, 0x34, 0x31, 0x3e, 0x36, 0xf1, 0x5f, 0xb5, 0xc3,
|
||||
0xc8, 0x3c, 0xe6, 0x12, 0xd6, 0xde, 0xab, 0x2b, 0xcc, 0xa8, 0x84, 0x87, 0x7b, 0xf5, 0xe3, 0xa2,
|
||||
0xe9, 0xee, 0x7e, 0xbd, 0xc0, 0x04, 0x56, 0x75, 0xc1, 0xd7, 0x8e, 0xea, 0x23, 0x25, 0x6f, 0x9a,
|
||||
0xa1, 0xc7, 0x5c, 0x1b, 0x51, 0x96, 0xc6, 0x0d, 0xe3, 0xc4, 0x88, 0x36, 0x7a, 0x72, 0xea, 0xf7,
|
||||
0xdc, 0xb5, 0xde, 0xd4, 0xe0, 0xc2, 0x34, 0xdf, 0xc9, 0xed, 0xc8, 0xec, 0x2f, 0x18, 0x8d, 0xc5,
|
||||
0x9d, 0xc8, 0xbc, 0x51, 0x75, 0x2f, 0xc6, 0x24, 0x07, 0xbf, 0xd0, 0x68, 0x8c, 0x4f, 0xdc, 0xba,
|
||||
0x75, 0xf3, 0xda, 0xcd, 0xeb, 0x5f, 0xbc, 0x15, 0x7b, 0xdb, 0xde, 0xab, 0x2b, 0x0d, 0xaa, 0xc5,
|
||||
0x87, 0x7b, 0x75, 0x50, 0x35, 0xb2, 0xbb, 0x5f, 0x2f, 0xd1, 0x84, 0x4f, 0x14, 0x1b, 0xa7, 0x1e,
|
||||
0x26, 0xc1, 0x08, 0xdc, 0xd5, 0x4f, 0x37, 0xd1, 0xb6, 0x45, 0x31, 0x71, 0xac, 0x8d, 0xd5, 0x16,
|
||||
0x35, 0x1e, 0x15, 0x93, 0xf9, 0x5c, 0x3b, 0x32, 0x4f, 0x35, 0xd1, 0xf6, 0x12, 0x26, 0xce, 0xed,
|
||||
0xd5, 0x16, 0x0f, 0x2e, 0x7d, 0xc2, 0x2d, 0x49, 0x96, 0xce, 0x0f, 0x94, 0x15, 0x53, 0x83, 0x01,
|
||||
0xb6, 0x37, 0x63, 0x83, 0x8f, 0x15, 0x0c, 0x42, 0x6c, 0x6f, 0x96, 0x0d, 0xa6, 0xb2, 0x82, 0xc1,
|
||||
0x54, 0x08, 0x7e, 0xa7, 0xe9, 0x43, 0x01, 0xb6, 0x7d, 0x42, 0xb0, 0xcd, 0xc3, 0xbb, 0xe5, 0x12,
|
||||
0x86, 0x83, 0x4d, 0xe4, 0x59, 0xd4, 0x38, 0x29, 0x6c, 0x7f, 0x45, 0x04, 0xf5, 0x54, 0x65, 0x2e,
|
||||
0x81, 0x97, 0x78, 0xec, 0x90, 0x1b, 0x66, 0x40, 0x27, 0x32, 0x47, 0x45, 0xdf, 0x4a, 0x54, 0x9a,
|
||||
0xa5, 0x1b, 0x63, 0x29, 0xa5, 0xc3, 0xbd, 0xfa, 0xd1, 0x1b, 0x63, 0x22, 0xbe, 0x57, 0xfa, 0x81,
|
||||
0xea, 0x5e, 0x40, 0x43, 0xef, 0x0d, 0xb0, 0x87, 0x76, 0x68, 0x16, 0x03, 0x74, 0x11, 0x03, 0x5e,
|
||||
0x6e, 0x47, 0xe6, 0xe9, 0x18, 0xc9, 0x37, 0x7a, 0x2d, 0x21, 0x24, 0x49, 0xcb, 0x3b, 0x3c, 0xdd,
|
||||
0xb1, 0xb0, 0xd8, 0x18, 0xbc, 0x7b, 0x54, 0xbf, 0x90, 0x74, 0x94, 0x11, 0xc9, 0x07, 0xa9, 0x69,
|
||||
0x9c, 0x12, 0x83, 0xf4, 0x27, 0xbe, 0x86, 0x87, 0x20, 0xd7, 0xab, 0xb8, 0xb0, 0xd0, 0x8e, 0xcc,
|
||||
0xa1, 0x40, 0x0d, 0x65, 0x81, 0xb6, 0x0b, 0x2e, 0xb1, 0x1c, 0x1f, 0x93, 0xb6, 0x6c, 0x57, 0x7b,
|
||||
0xdd, 0x21, 0x3e, 0xc8, 0xe3, 0x7c, 0x90, 0xbb, 0xd1, 0x84, 0x46, 0xec, 0x67, 0x15, 0x01, 0xab,
|
||||
0xfa, 0x69, 0xca, 0x50, 0xc0, 0xac, 0xd5, 0xc0, 0xdf, 0xa2, 0x38, 0x30, 0x7a, 0xc4, 0x58, 0xff,
|
||||
0x77, 0x3b, 0x32, 0x7b, 0x04, 0x30, 0x15, 0xcb, 0x3b, 0x91, 0xf9, 0xa4, 0x70, 0x47, 0x16, 0x76,
|
||||
0x1d, 0xe9, 0x42, 0x53, 0xf0, 0x73, 0x4d, 0x3f, 0x47, 0x10, 0xb3, 0x58, 0x80, 0xf8, 0xa9, 0x86,
|
||||
0xbc, 0x6c, 0x62, 0x7b, 0x45, 0x67, 0x6f, 0x1e, 0x44, 0xa6, 0x7e, 0x67, 0x72, 0x39, 0x0f, 0xeb,
|
||||
0x3a, 0x41, 0x2c, 0x9f, 0x63, 0x53, 0x74, 0x9c, 0x8b, 0x14, 0x21, 0x5c, 0x6e, 0x50, 0xf8, 0x92,
|
||||
0xc2, 0xb5, 0xd4, 0x05, 0xec, 0x27, 0x88, 0x2d, 0xa7, 0x74, 0xd2, 0x05, 0xf1, 0x87, 0x0a, 0x4f,
|
||||
0x0f, 0x23, 0x8a, 0xad, 0xa6, 0x71, 0x46, 0x2c, 0x85, 0x6f, 0xf0, 0xa5, 0x70, 0xf2, 0xce, 0xe4,
|
||||
0xf2, 0x3c, 0x17, 0xf3, 0xc9, 0x3f, 0x43, 0x10, 0x8b, 0x3f, 0x5c, 0x12, 0x32, 0x91, 0xfc, 0xd4,
|
||||
0x52, 0xb2, 0xb2, 0x5c, 0xb9, 0x37, 0xda, 0x7b, 0xf5, 0x4a, 0xfb, 0xaa, 0x28, 0xdb, 0x41, 0x79,
|
||||
0xc7, 0x10, 0xc8, 0xec, 0x63, 0x19, 0xf8, 0x8b, 0xa6, 0x0f, 0x15, 0xc9, 0x07, 0x98, 0xe0, 0x2d,
|
||||
0xb1, 0x92, 0xcf, 0x0a, 0xfa, 0xbb, 0x9c, 0xfe, 0xa9, 0x3b, 0x93, 0xcb, 0x30, 0x06, 0xb8, 0x03,
|
||||
0x7d, 0x04, 0xb1, 0xf4, 0x33, 0x73, 0xa1, 0x9e, 0xba, 0x50, 0x44, 0x24, 0x27, 0xae, 0xc9, 0x4e,
|
||||
0x28, 0x6c, 0xa8, 0x84, 0xdc, 0x91, 0x6b, 0xdc, 0x11, 0x99, 0x02, 0x1c, 0x90, 0x5d, 0x49, 0xa5,
|
||||
0x0a, 0x67, 0x98, 0xdb, 0xc4, 0x7e, 0xc8, 0x2c, 0x6a, 0xf4, 0x15, 0x9d, 0x59, 0x8e, 0x81, 0xa5,
|
||||
0xc4, 0x99, 0xf4, 0x93, 0xaf, 0x74, 0xa7, 0xe0, 0x4c, 0x11, 0xe9, 0xb6, 0xfd, 0x14, 0x36, 0x54,
|
||||
0xc2, 0x6c, 0xcb, 0xc9, 0x14, 0x8a, 0xce, 0xa4, 0x52, 0xf0, 0x23, 0x4d, 0x37, 0x42, 0x8a, 0xd6,
|
||||
0xb0, 0x15, 0x60, 0x7e, 0xee, 0xbb, 0x64, 0xcd, 0x42, 0xb6, 0x8d, 0x5b, 0x0c, 0x3b, 0x06, 0x10,
|
||||
0xde, 0x20, 0xbe, 0x03, 0x56, 0xe0, 0x64, 0x22, 0xe5, 0x3b, 0x20, 0x0c, 0xd2, 0xaf, 0x4e, 0x64,
|
||||
0x9e, 0x15, 0x4e, 0xe4, 0x22, 0x89, 0xb0, 0xac, 0x58, 0xf8, 0xe2, 0x2b, 0x3e, 0x37, 0x09, 0x07,
|
||||
0x05, 0x05, 0x98, 0x32, 0x48, 0xe5, 0xe0, 0x6d, 0x7d, 0xa0, 0x4c, 0x8e, 0x62, 0x4c, 0x8c, 0x7e,
|
||||
0x41, 0x6c, 0xee, 0x20, 0x32, 0x4f, 0xac, 0xc0, 0x25, 0x8c, 0x49, 0x3b, 0x32, 0x4f, 0x84, 0x01,
|
||||
0xff, 0xd5, 0x89, 0xcc, 0x9e, 0x84, 0x10, 0xff, 0x94, 0xc8, 0xa4, 0x0a, 0xd9, 0xaf, 0xdd, 0xfd,
|
||||
0x7a, 0xd2, 0x1c, 0x82, 0x22, 0x01, 0x2e, 0x03, 0xdf, 0xd3, 0xf4, 0xc7, 0xcb, 0xbd, 0x87, 0xc4,
|
||||
0x7d, 0x33, 0xc4, 0x96, 0xeb, 0x18, 0x03, 0x22, 0x89, 0x78, 0x23, 0x1e, 0x9b, 0x15, 0x21, 0x9e,
|
||||
0x9b, 0x89, 0xc7, 0x26, 0xf9, 0x92, 0xc7, 0x26, 0x55, 0xa8, 0xc5, 0x83, 0x92, 0x7e, 0x76, 0xe4,
|
||||
0xaf, 0x64, 0x50, 0x52, 0xac, 0x3c, 0x28, 0xa9, 0x16, 0xf8, 0x58, 0xd3, 0xfb, 0x2b, 0xbc, 0x02,
|
||||
0xcf, 0x38, 0x27, 0x18, 0x7d, 0x8b, 0xaf, 0xbd, 0xe3, 0x2b, 0x70, 0x05, 0xce, 0xb7, 0x23, 0xf3,
|
||||
0x78, 0x18, 0xac, 0xc0, 0xf9, 0x4e, 0x64, 0xde, 0x4c, 0x89, 0xc0, 0x79, 0x69, 0x75, 0xad, 0x33,
|
||||
0xd6, 0xa2, 0xb7, 0xae, 0x5e, 0x75, 0x10, 0x43, 0x57, 0xe8, 0x0e, 0xb1, 0xd9, 0x3a, 0x2f, 0xd6,
|
||||
0x08, 0x66, 0x57, 0x09, 0xde, 0xe2, 0x52, 0x4e, 0x38, 0x31, 0x92, 0xfe, 0x38, 0xdc, 0xab, 0x3f,
|
||||
0x44, 0xc3, 0xdd, 0xfd, 0x7a, 0xcc, 0x02, 0xf6, 0x95, 0xfc, 0x08, 0x3c, 0xf0, 0x4f, 0x4d, 0x37,
|
||||
0xcb, 0x2e, 0xb4, 0x7c, 0xca, 0x4f, 0x38, 0x8a, 0xed, 0x30, 0xc0, 0xde, 0x8e, 0x31, 0x28, 0xc2,
|
||||
0xef, 0x0f, 0x44, 0x05, 0xb1, 0x02, 0x17, 0x7d, 0xca, 0xe6, 0x32, 0xb0, 0x1d, 0x99, 0x67, 0xc3,
|
||||
0xa0, 0x28, 0xeb, 0x44, 0xe6, 0x53, 0x89, 0x93, 0x45, 0x40, 0xf2, 0xb7, 0x81, 0x3c, 0x2a, 0x42,
|
||||
0x72, 0xb5, 0xb5, 0x42, 0xc6, 0x33, 0x4f, 0xd1, 0x82, 0xd7, 0x0b, 0x65, 0x0a, 0xf0, 0x62, 0xd1,
|
||||
0xad, 0x22, 0x0a, 0xfe, 0xa1, 0xf0, 0xd0, 0x25, 0x2e, 0x73, 0x79, 0x1d, 0xc1, 0xcf, 0x3b, 0x8b,
|
||||
0x1a, 0x43, 0x62, 0x15, 0x7f, 0x5f, 0x54, 0x0f, 0x2b, 0x70, 0x2e, 0x46, 0x67, 0x38, 0xc8, 0x03,
|
||||
0xc6, 0x99, 0x30, 0x28, 0x88, 0xb2, 0x70, 0x51, 0x92, 0xcb, 0xc1, 0xe2, 0xe6, 0x58, 0x21, 0x80,
|
||||
0x97, 0x2d, 0x54, 0x45, 0xfc, 0x04, 0xe2, 0xad, 0x78, 0xc1, 0x50, 0xa2, 0x00, 0x2f, 0x14, 0x1d,
|
||||
0x2c, 0x80, 0xc0, 0xd7, 0xfb, 0x02, 0x1c, 0x1f, 0xce, 0x3e, 0xb1, 0xb6, 0xd0, 0x06, 0x0e, 0x5b,
|
||||
0x86, 0x21, 0xa6, 0x6c, 0x9a, 0x93, 0x4f, 0xc0, 0xbb, 0xe4, 0x75, 0x01, 0x65, 0xe4, 0x4b, 0xf2,
|
||||
0xae, 0x87, 0x74, 0xd9, 0x00, 0x78, 0x4f, 0xd3, 0x87, 0x50, 0xc8, 0x7c, 0x2b, 0x6c, 0xad, 0x05,
|
||||
0xc8, 0xc1, 0x79, 0x32, 0xb4, 0x6e, 0x3c, 0x2e, 0x06, 0x72, 0x91, 0x97, 0x5c, 0x5c, 0x65, 0x25,
|
||||
0xd6, 0x48, 0xf3, 0x88, 0x57, 0xb3, 0xea, 0x44, 0x05, 0xca, 0xc3, 0x37, 0x21, 0x67, 0x86, 0xe3,
|
||||
0x13, 0x50, 0x69, 0x0d, 0x34, 0xf5, 0xa1, 0x94, 0x03, 0xf3, 0xad, 0x56, 0xc0, 0xa7, 0x58, 0x9c,
|
||||
0xc5, 0xd4, 0x38, 0x2f, 0x06, 0xe0, 0x06, 0x27, 0x92, 0xa8, 0x2c, 0xfb, 0x8b, 0x01, 0x86, 0x09,
|
||||
0xde, 0x89, 0xcc, 0xf3, 0xf1, 0x14, 0x2a, 0xc0, 0x1a, 0x54, 0xb6, 0x01, 0x9b, 0x3a, 0xd8, 0xc0,
|
||||
0xb8, 0x65, 0x31, 0xdc, 0x6c, 0xf9, 0x01, 0x0a, 0x5c, 0x4c, 0xad, 0x75, 0xe3, 0x82, 0x70, 0xf9,
|
||||
0x55, 0xbe, 0x11, 0x38, 0xba, 0x9c, 0x83, 0xdc, 0xdd, 0x4b, 0xa2, 0x97, 0x32, 0x20, 0xd7, 0x62,
|
||||
0xd7, 0x65, 0x57, 0x27, 0xae, 0xc3, 0x8a, 0x15, 0xb0, 0xa3, 0xf7, 0xdb, 0xc8, 0x5e, 0xc7, 0x96,
|
||||
0xbb, 0x46, 0xfc, 0x00, 0x3b, 0x56, 0xc3, 0xf5, 0x30, 0x35, 0x2e, 0x0a, 0x17, 0xe7, 0xf8, 0x89,
|
||||
0x26, 0xe0, 0xb9, 0x18, 0x9d, 0xe5, 0x60, 0x36, 0xd0, 0x15, 0xa4, 0xb2, 0x07, 0xb3, 0xbd, 0x05,
|
||||
0xab, 0x66, 0xc0, 0x77, 0x34, 0xfd, 0x7c, 0x2b, 0xf0, 0xd7, 0x78, 0x31, 0x63, 0x85, 0x2d, 0x07,
|
||||
0x31, 0x2c, 0x17, 0x08, 0x4f, 0x08, 0xdf, 0x97, 0x79, 0x7e, 0x9b, 0x6a, 0xad, 0x08, 0x25, 0xb9,
|
||||
0x18, 0x88, 0x8b, 0xec, 0x2e, 0xb8, 0x44, 0xe7, 0x45, 0x69, 0x20, 0xb4, 0x17, 0x61, 0x37, 0x8b,
|
||||
0xe0, 0x5d, 0x4d, 0x1f, 0xf4, 0xdc, 0xa6, 0xcb, 0xac, 0x55, 0x44, 0x9c, 0x2d, 0xd7, 0x61, 0xeb,
|
||||
0x96, 0x4b, 0x2c, 0x0f, 0x11, 0x63, 0x58, 0x0c, 0xc9, 0x82, 0x28, 0x1e, 0xb9, 0xc6, 0x54, 0xaa,
|
||||
0x30, 0x47, 0xe6, 0x11, 0xc9, 0x0b, 0xfe, 0x2a, 0x76, 0x9f, 0x61, 0x51, 0x99, 0x02, 0xef, 0x68,
|
||||
0x3a, 0x68, 0xba, 0xc4, 0x5a, 0xf7, 0x9b, 0xd8, 0x72, 0x5c, 0xba, 0x61, 0x35, 0x02, 0x8c, 0x0d,
|
||||
0x73, 0x44, 0x1b, 0x3d, 0x35, 0xd1, 0x73, 0x25, 0xbe, 0x59, 0xbb, 0xb2, 0xe4, 0xbe, 0x85, 0xa7,
|
||||
0x5e, 0xf9, 0x24, 0x32, 0x8f, 0xf0, 0x9d, 0xd8, 0x74, 0xc9, 0xab, 0x7e, 0x13, 0xcf, 0xb8, 0x74,
|
||||
0x63, 0x36, 0xc0, 0x38, 0x5b, 0x1d, 0x25, 0xb9, 0xbc, 0x0f, 0x46, 0x2e, 0x73, 0x22, 0xc7, 0xc6,
|
||||
0x47, 0x2e, 0xc3, 0x72, 0x73, 0x70, 0x4f, 0xd3, 0x7b, 0xd2, 0xf5, 0x2e, 0x8e, 0x9d, 0x11, 0x71,
|
||||
0xec, 0xfc, 0x51, 0xa4, 0x3c, 0xe9, 0xa2, 0x8d, 0x0f, 0x9f, 0x53, 0x41, 0xfe, 0xd9, 0x89, 0xcc,
|
||||
0x99, 0xb4, 0xe2, 0x48, 0x65, 0x8a, 0x83, 0x28, 0xd9, 0x01, 0xb4, 0x74, 0xa6, 0x34, 0x31, 0x43,
|
||||
0x57, 0xbe, 0x44, 0x7d, 0xc2, 0x63, 0x77, 0xc1, 0x6c, 0xf1, 0xf3, 0x70, 0xaf, 0x3e, 0xfa, 0xb0,
|
||||
0xa6, 0x78, 0x7e, 0x24, 0xf1, 0x85, 0xb9, 0x9d, 0xc0, 0x03, 0xaf, 0xeb, 0x7d, 0xc8, 0xdb, 0xe2,
|
||||
0xd5, 0x57, 0x7c, 0x9b, 0x40, 0x30, 0xa3, 0xc6, 0x93, 0xe2, 0x12, 0x8f, 0x17, 0xbd, 0x67, 0x62,
|
||||
0x50, 0x54, 0xe5, 0x77, 0x30, 0xe3, 0x0b, 0x7f, 0x20, 0x8e, 0x30, 0x05, 0x79, 0x0d, 0x96, 0x15,
|
||||
0xc1, 0xbf, 0x35, 0x7d, 0xd4, 0xdf, 0xc4, 0xc1, 0x56, 0xe0, 0x32, 0x1e, 0x38, 0x9a, 0x3e, 0xc3,
|
||||
0x96, 0x83, 0x37, 0x5d, 0x1b, 0x5b, 0x04, 0x35, 0x31, 0xe5, 0xe1, 0x34, 0x29, 0x84, 0x8c, 0x5a,
|
||||
0x7e, 0xbd, 0x34, 0x74, 0x37, 0x6d, 0x04, 0x45, 0x9b, 0x19, 0xbc, 0x79, 0x87, 0xab, 0xb7, 0x23,
|
||||
0xf3, 0x92, 0x5f, 0x81, 0x5c, 0x1b, 0x0b, 0xf4, 0x2e, 0x99, 0x8e, 0x4d, 0x75, 0x22, 0xf3, 0x25,
|
||||
0x41, 0xf0, 0x21, 0x74, 0xbb, 0x2f, 0x4a, 0x5e, 0xc5, 0x75, 0xe1, 0x01, 0x1f, 0x86, 0x05, 0xf8,
|
||||
0xaa, 0x7e, 0x8e, 0x87, 0x31, 0xcb, 0x25, 0x0e, 0xde, 0xb6, 0xf8, 0x4a, 0x5e, 0xf5, 0x7c, 0x7b,
|
||||
0x83, 0x1a, 0x97, 0xc4, 0x96, 0xe6, 0x8b, 0x06, 0x70, 0x85, 0x39, 0x8e, 0x2f, 0xb8, 0x64, 0x4a,
|
||||
0xa0, 0xd9, 0xad, 0x6d, 0x15, 0x52, 0x66, 0xca, 0x71, 0xfe, 0x0b, 0x15, 0x96, 0xc0, 0xdf, 0x79,
|
||||
0xba, 0x4b, 0x90, 0xbd, 0x81, 0x1d, 0x8b, 0xf8, 0xcc, 0x6d, 0xb8, 0x36, 0x8a, 0xef, 0x1f, 0x1c,
|
||||
0x6a, 0xd4, 0xc5, 0xfc, 0xbe, 0xcf, 0x87, 0x7b, 0x70, 0x25, 0x56, 0xba, 0x23, 0xe9, 0xcc, 0xcd,
|
||||
0xf0, 0xd1, 0x1e, 0x0c, 0x95, 0x48, 0x27, 0x32, 0x2f, 0xc4, 0xa1, 0x5d, 0x05, 0x8b, 0xbb, 0x4a,
|
||||
0x25, 0xd2, 0xd9, 0xab, 0x77, 0xb1, 0xb8, 0xbb, 0x5f, 0xef, 0xc2, 0x02, 0x2a, 0x5b, 0x38, 0x14,
|
||||
0x40, 0xfd, 0x34, 0x0b, 0x50, 0xa3, 0xe1, 0xda, 0x96, 0xed, 0x21, 0x4a, 0x8d, 0xcb, 0x62, 0x58,
|
||||
0x5f, 0xe0, 0xf5, 0x72, 0x02, 0x4c, 0x73, 0x79, 0x27, 0x32, 0x41, 0x3c, 0xa0, 0x92, 0x30, 0xbb,
|
||||
0xa8, 0x29, 0xa8, 0x82, 0xb7, 0xf5, 0xfe, 0x64, 0x88, 0xad, 0x86, 0xef, 0x39, 0x38, 0xb0, 0x5a,
|
||||
0x88, 0xad, 0x1b, 0x4f, 0x89, 0x5d, 0x7f, 0xfb, 0x20, 0x32, 0x2f, 0xcc, 0xe0, 0x56, 0x80, 0x6d,
|
||||
0xc4, 0xb0, 0x33, 0x13, 0x2b, 0xce, 0x0a, 0xbd, 0x45, 0xc4, 0xd6, 0xdb, 0x91, 0xa9, 0xbd, 0x90,
|
||||
0x55, 0xe7, 0x4e, 0x19, 0x7e, 0xde, 0x6f, 0xba, 0x7c, 0x92, 0xd8, 0x4e, 0xcd, 0xd0, 0x60, 0x5f,
|
||||
0x05, 0x07, 0x1b, 0xfa, 0x59, 0x8a, 0x99, 0xe5, 0xf9, 0x5b, 0x56, 0x2b, 0x70, 0xfd, 0xc0, 0x65,
|
||||
0x3b, 0xc6, 0xd3, 0x62, 0x53, 0x4c, 0xb6, 0x23, 0xb3, 0x97, 0x62, 0x36, 0xef, 0x6f, 0x2d, 0x26,
|
||||
0x48, 0x16, 0xd9, 0x8a, 0xe2, 0xae, 0x29, 0x46, 0xa9, 0x39, 0xf8, 0x40, 0xd3, 0x07, 0x9b, 0x68,
|
||||
0x3b, 0x75, 0xd3, 0xf6, 0x89, 0x1d, 0x06, 0x01, 0x26, 0xf6, 0x8e, 0x31, 0x2a, 0xc6, 0x91, 0x8a,
|
||||
0xcb, 0x16, 0xb4, 0xb5, 0x80, 0xb6, 0x63, 0x8e, 0xd3, 0xb9, 0x0a, 0x3f, 0xf2, 0x9b, 0x0a, 0x79,
|
||||
0x76, 0xe4, 0xab, 0xc0, 0x74, 0xc8, 0xc5, 0xed, 0x88, 0xda, 0x2e, 0x54, 0x5a, 0x05, 0x9f, 0x6a,
|
||||
0x7a, 0xbf, 0x1d, 0x20, 0xba, 0x5e, 0xaa, 0x01, 0x9e, 0x11, 0xd3, 0xf2, 0xa1, 0xa8, 0x01, 0xa6,
|
||||
0xd3, 0x1a, 0xc0, 0x4e, 0x6a, 0x80, 0xd9, 0xf8, 0x6c, 0xe6, 0xcd, 0xf2, 0x6c, 0x5c, 0x19, 0x86,
|
||||
0x85, 0x4e, 0x35, 0xaf, 0x17, 0x62, 0xbe, 0x96, 0xfb, 0x2a, 0x46, 0x78, 0x75, 0x60, 0x27, 0xd5,
|
||||
0x41, 0xfd, 0x61, 0xcc, 0xf0, 0xfa, 0x60, 0x3a, 0xae, 0x0f, 0x4a, 0xc6, 0x02, 0x0f, 0xfc, 0x44,
|
||||
0xd3, 0x87, 0xca, 0xee, 0xa5, 0xd7, 0x32, 0xcf, 0x8a, 0xf9, 0x77, 0x0f, 0x22, 0xf3, 0xe4, 0x34,
|
||||
0x94, 0x5e, 0x14, 0x8a, 0x56, 0xca, 0x2f, 0x0a, 0x4a, 0xb4, 0xdb, 0xd2, 0xd8, 0xdd, 0xaf, 0xe7,
|
||||
0xb6, 0xa1, 0xda, 0x32, 0xf8, 0xba, 0xa6, 0x0f, 0x52, 0x16, 0x12, 0x8b, 0x67, 0x4e, 0xc8, 0x73,
|
||||
0x37, 0xb1, 0x15, 0xe7, 0xc3, 0xd4, 0x78, 0x2e, 0xcb, 0x47, 0xfb, 0xb9, 0xc6, 0xed, 0x54, 0x61,
|
||||
0x89, 0xe3, 0x4b, 0x59, 0x96, 0xa4, 0xc0, 0x8a, 0xc9, 0xbc, 0x14, 0xd0, 0x8e, 0x8d, 0xdf, 0x1c,
|
||||
0x83, 0x2a, 0x6b, 0xbc, 0x46, 0x2e, 0xd1, 0xe0, 0x71, 0x95, 0x1a, 0xcf, 0x0b, 0x12, 0xaf, 0xf1,
|
||||
0x44, 0xad, 0xd0, 0x6c, 0xc1, 0x25, 0x79, 0x2d, 0x51, 0x41, 0xe4, 0x1c, 0xb1, 0x10, 0x50, 0x27,
|
||||
0xc6, 0x60, 0xd5, 0x0e, 0xcf, 0xca, 0x7b, 0x44, 0xef, 0xe9, 0x43, 0xd7, 0x0b, 0x22, 0x86, 0x3a,
|
||||
0x07, 0x91, 0xd9, 0x0b, 0xd1, 0xd6, 0x12, 0x0b, 0xa5, 0x27, 0xae, 0x53, 0x34, 0xff, 0xcc, 0x2e,
|
||||
0xa3, 0x72, 0xd9, 0x03, 0x9f, 0xe1, 0x4a, 0x16, 0xa1, 0x6c, 0x0f, 0x6c, 0xea, 0x67, 0x78, 0xd9,
|
||||
0xb9, 0x8a, 0x28, 0xb6, 0xe2, 0x37, 0x47, 0xe3, 0xca, 0x88, 0x36, 0xda, 0x3b, 0xd1, 0x9b, 0xa6,
|
||||
0x45, 0xcb, 0x42, 0x2a, 0x6e, 0x0f, 0x7b, 0x53, 0xd5, 0x58, 0x96, 0x45, 0x8e, 0xa2, 0xb8, 0x36,
|
||||
0x92, 0x14, 0x21, 0xc9, 0xf2, 0x78, 0x67, 0xbf, 0xae, 0xc1, 0x52, 0x53, 0xf0, 0xdd, 0xa3, 0xfa,
|
||||
0x25, 0x1e, 0x35, 0xb2, 0x70, 0xc1, 0x8b, 0x58, 0xdb, 0x6f, 0xf2, 0x25, 0x1b, 0xe0, 0x37, 0x43,
|
||||
0x4c, 0x99, 0xb5, 0xe1, 0xae, 0x1a, 0x57, 0xc5, 0x74, 0xfc, 0x59, 0x4b, 0xde, 0x2a, 0x17, 0xd0,
|
||||
0xf6, 0xf4, 0x1c, 0x8c, 0xf1, 0xdb, 0xee, 0x54, 0x3b, 0x32, 0xcd, 0x26, 0xda, 0xce, 0xb6, 0x38,
|
||||
0x9b, 0x4b, 0x6c, 0xe4, 0x2a, 0xd9, 0x29, 0xf8, 0x00, 0x3d, 0xa9, 0x00, 0x7c, 0xa0, 0xc9, 0x07,
|
||||
0xab, 0x24, 0xaf, 0x9f, 0x25, 0xba, 0xf0, 0x01, 0xcd, 0x56, 0xc1, 0xe7, 0x9a, 0x3e, 0x98, 0x3d,
|
||||
0xc1, 0x78, 0x48, 0x7e, 0xb4, 0x1d, 0x13, 0x1b, 0xf8, 0x23, 0x3e, 0x12, 0x03, 0xe9, 0x13, 0xc6,
|
||||
0xfc, 0xe4, 0x1d, 0xf9, 0xdd, 0x76, 0x00, 0x29, 0xe4, 0x59, 0x22, 0xad, 0x02, 0x55, 0x2f, 0x67,
|
||||
0x4a, 0x23, 0x5d, 0xe4, 0xd2, 0xd6, 0x57, 0x92, 0x82, 0x79, 0x2b, 0x24, 0x3d, 0xfa, 0x6e, 0xea,
|
||||
0xe7, 0xc5, 0x2b, 0x4b, 0x23, 0xf4, 0xbc, 0x24, 0xab, 0xf1, 0x49, 0x5a, 0xa2, 0x1a, 0xe3, 0xc2,
|
||||
0xd3, 0x5b, 0x3c, 0x6b, 0xe0, 0x5a, 0xb3, 0xa1, 0xe7, 0x89, 0x7c, 0xe4, 0x2e, 0x49, 0x8a, 0xca,
|
||||
0x4e, 0x64, 0x5e, 0x4c, 0x8e, 0x2c, 0x15, 0x5c, 0x83, 0x5d, 0xda, 0x81, 0xd7, 0xf4, 0xd3, 0x0d,
|
||||
0x8c, 0x58, 0x18, 0x60, 0xab, 0xe1, 0xa1, 0x35, 0x6a, 0x4c, 0x88, 0x7d, 0x77, 0x99, 0x9f, 0xf4,
|
||||
0x09, 0x30, 0xcb, 0xe5, 0xd9, 0x8b, 0x8c, 0x24, 0xac, 0xc1, 0x82, 0x0a, 0xd8, 0xd2, 0x87, 0xa4,
|
||||
0x87, 0x98, 0xb8, 0xc6, 0xc1, 0xc4, 0x0f, 0xd7, 0xd6, 0x8d, 0x6b, 0x62, 0xd1, 0xbe, 0x2c, 0xc2,
|
||||
0x6b, 0xa6, 0x32, 0xcf, 0x35, 0x5e, 0x11, 0x0a, 0x59, 0xd6, 0xa3, 0x44, 0xb3, 0x8c, 0x42, 0xdd,
|
||||
0x18, 0x6c, 0xe8, 0x03, 0x95, 0x8e, 0x9b, 0x68, 0xdb, 0xb8, 0x2e, 0x7a, 0x7d, 0x89, 0x27, 0x83,
|
||||
0xa5, 0x86, 0x0b, 0x68, 0xbb, 0x13, 0x99, 0x86, 0xaa, 0xcb, 0x05, 0xb4, 0x9d, 0xf5, 0xa7, 0x68,
|
||||
0x06, 0xde, 0x3b, 0xaa, 0x9b, 0xe9, 0xed, 0x92, 0x85, 0x3c, 0x9e, 0x52, 0xf8, 0x9e, 0x63, 0x31,
|
||||
0x8f, 0x5a, 0x3c, 0x7e, 0xb8, 0x3e, 0xa1, 0xc6, 0x8b, 0x62, 0xbe, 0x3e, 0xe6, 0x2b, 0xf3, 0x42,
|
||||
0x7a, 0x97, 0x33, 0xc9, 0x55, 0xef, 0x7a, 0xce, 0xf2, 0xfc, 0xd2, 0xff, 0x25, 0x7a, 0xed, 0xc8,
|
||||
0xbc, 0xe0, 0x76, 0x87, 0xb3, 0x7c, 0xe7, 0x3e, 0x3a, 0x7c, 0x7d, 0xde, 0xd7, 0xc6, 0xfd, 0xe1,
|
||||
0xdd, 0xfd, 0xfa, 0xfd, 0x08, 0xc2, 0x6a, 0x5b, 0x8f, 0xa6, 0x20, 0xf8, 0xb2, 0xde, 0x13, 0xb6,
|
||||
0x48, 0x2b, 0x3b, 0x50, 0x7f, 0x31, 0x2b, 0xdc, 0xfe, 0xff, 0x83, 0xc8, 0x3c, 0x97, 0xe7, 0x72,
|
||||
0x2b, 0x8b, 0x64, 0x31, 0x3f, 0x5d, 0x45, 0x16, 0x97, 0x24, 0xb8, 0x2d, 0xd2, 0x4a, 0x00, 0x29,
|
||||
0x7f, 0xdb, 0xdd, 0xaf, 0xab, 0x1b, 0x1b, 0x1a, 0x3c, 0x25, 0x35, 0x01, 0x3f, 0xd3, 0x92, 0xee,
|
||||
0xd3, 0xe7, 0x8b, 0x0f, 0x66, 0xc5, 0x74, 0xbf, 0x23, 0xe2, 0x41, 0xd1, 0x44, 0xf6, 0x94, 0x21,
|
||||
0xba, 0x1f, 0xc9, 0xba, 0x97, 0x9f, 0x20, 0x24, 0x0e, 0x79, 0xe0, 0x3b, 0xdf, 0x5d, 0x8b, 0x6f,
|
||||
0x70, 0x55, 0x2f, 0x86, 0x06, 0xf5, 0xbc, 0x15, 0xf8, 0x8d, 0xa6, 0xf7, 0x0a, 0x9a, 0xf9, 0x43,
|
||||
0xc5, 0x2f, 0x63, 0xa2, 0xdf, 0x14, 0xf5, 0x41, 0xd1, 0x84, 0xf4, 0x68, 0x21, 0xa8, 0xd6, 0x32,
|
||||
0xaa, 0xc5, 0x67, 0x06, 0x25, 0xd9, 0x8b, 0xf7, 0xd3, 0xe3, 0x55, 0x80, 0xba, 0x2f, 0x43, 0x83,
|
||||
0x3d, 0x72, 0xcb, 0x9c, 0x72, 0xfe, 0x1c, 0xf1, 0x61, 0x77, 0xca, 0xd2, 0xd3, 0x44, 0x89, 0x72,
|
||||
0xf1, 0x31, 0xa1, 0x3b, 0xe5, 0x6e, 0x7a, 0x55, 0xca, 0xa9, 0x66, 0x4a, 0x39, 0x7b, 0x7d, 0x68,
|
||||
0xe8, 0xf1, 0xb3, 0x67, 0x96, 0x3e, 0xfc, 0x6a, 0x56, 0xc4, 0xb1, 0xff, 0x29, 0xf2, 0x15, 0x2f,
|
||||
0x87, 0x79, 0x1e, 0x21, 0x2d, 0xc6, 0x20, 0x47, 0x8a, 0xc5, 0x44, 0x8f, 0x84, 0x50, 0x71, 0x79,
|
||||
0x53, 0xbd, 0x37, 0xb1, 0x5a, 0x36, 0x33, 0x3e, 0xe2, 0x43, 0xa4, 0x4d, 0x2d, 0x1c, 0x44, 0xe6,
|
||||
0xc5, 0xbc, 0xc7, 0x85, 0xe2, 0xad, 0xc7, 0xa2, 0xcd, 0x8a, 0xe3, 0xd4, 0xac, 0xe0, 0xc5, 0xee,
|
||||
0x41, 0x55, 0x81, 0xe7, 0x4a, 0x03, 0xa5, 0x4c, 0x81, 0xda, 0x88, 0x50, 0xe3, 0xd7, 0xf1, 0x2c,
|
||||
0x2d, 0x97, 0x28, 0xc8, 0x27, 0xec, 0x12, 0x57, 0x2c, 0x51, 0xa8, 0xe0, 0xd5, 0xa9, 0x12, 0x4c,
|
||||
0x2a, 0x7a, 0x53, 0xb7, 0x3f, 0xf9, 0x6c, 0xf8, 0xc8, 0xfe, 0x67, 0xc3, 0x47, 0x3e, 0x39, 0x18,
|
||||
0xd6, 0xf6, 0x0f, 0x86, 0xb5, 0x6f, 0xdf, 0x1b, 0x3e, 0xf2, 0xfe, 0xbd, 0x61, 0x6d, 0xff, 0xde,
|
||||
0xf0, 0x91, 0xbf, 0xdd, 0x1b, 0x3e, 0xf2, 0xc6, 0x33, 0x6b, 0x2e, 0x5b, 0x0f, 0x57, 0xaf, 0xd8,
|
||||
0x7e, 0xf3, 0x6a, 0x96, 0xbf, 0x4b, 0xbf, 0xf2, 0xff, 0x71, 0xad, 0x9e, 0x10, 0x7f, 0xdc, 0xba,
|
||||
0xf6, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x3d, 0xe9, 0x4b, 0x24, 0x26, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *OptionsConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
@@ -431,6 +438,18 @@ func (m *OptionsConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i--
|
||||
dAtA[i] = 0xc0
|
||||
}
|
||||
if m.InsecureAllowOldTLSVersions {
|
||||
i--
|
||||
if m.InsecureAllowOldTLSVersions {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x3
|
||||
i--
|
||||
dAtA[i] = 0xa8
|
||||
}
|
||||
if m.ConnectionLimitMax != 0 {
|
||||
i = encodeVarintOptionsconfiguration(dAtA, i, uint64(m.ConnectionLimitMax))
|
||||
i--
|
||||
@@ -1072,6 +1091,9 @@ func (m *OptionsConfiguration) ProtoSize() (n int) {
|
||||
if m.ConnectionLimitMax != 0 {
|
||||
n += 2 + sovOptionsconfiguration(uint64(m.ConnectionLimitMax))
|
||||
}
|
||||
if m.InsecureAllowOldTLSVersions {
|
||||
n += 3
|
||||
}
|
||||
if m.DeprecatedUPnPEnabled {
|
||||
n += 4
|
||||
}
|
||||
@@ -2288,6 +2310,26 @@ func (m *OptionsConfiguration) Unmarshal(dAtA []byte) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 53:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAllowOldTLSVersions", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOptionsconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureAllowOldTLSVersions = bool(v != 0)
|
||||
case 9000:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field DeprecatedUPnPEnabled", wireType)
|
||||
@@ -2433,10 +2475,7 @@ func (m *OptionsConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthOptionsconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthOptionsconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -235,10 +235,7 @@ func (m *Size) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -403,7 +403,7 @@ func (m *VersioningConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
@@ -490,10 +490,7 @@ func (m *VersioningConfiguration) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:generate -command counterfeiter go run github.com/maxbrunsfeld/counterfeiter/v6
|
||||
//go:generate counterfeiter -o mocks/mocked_wrapper.go --fake-name Wrapper . Wrapper
|
||||
|
||||
package config
|
||||
|
||||
@@ -8,12 +8,26 @@ package connections
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thejerf/suture/v4"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
)
|
||||
|
||||
func TestFixupPort(t *testing.T) {
|
||||
@@ -216,3 +230,196 @@ func TestConnectionStatus(t *testing.T) {
|
||||
|
||||
check(nil, nil)
|
||||
}
|
||||
|
||||
func BenchmarkConnections(pb *testing.B) {
|
||||
addrs := []string{
|
||||
"tcp://127.0.0.1:0",
|
||||
"quic://127.0.0.1:0",
|
||||
"relay://127.0.0.1:22067",
|
||||
}
|
||||
sizes := []int{
|
||||
1 << 10,
|
||||
1 << 15,
|
||||
1 << 20,
|
||||
1 << 22,
|
||||
}
|
||||
haveRelay := false
|
||||
// Check if we have a relay running locally
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:22067", 100*time.Millisecond)
|
||||
if err == nil {
|
||||
haveRelay = true
|
||||
_ = conn.Close()
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
for _, sz := range sizes {
|
||||
for _, direction := range []string{"cs", "sc"} {
|
||||
proto := strings.SplitN(addr, ":", 2)[0]
|
||||
pb.Run(fmt.Sprintf("%s_%d_%s", proto, sz, direction), func(b *testing.B) {
|
||||
if proto == "relay" && !haveRelay {
|
||||
b.Skip("could not connect to relay")
|
||||
}
|
||||
withConnectionPair(b, addr, func(client, server internalConn) {
|
||||
if direction == "sc" {
|
||||
server, client = client, server
|
||||
}
|
||||
data := make([]byte, sz)
|
||||
if _, err := rand.Read(data); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
total := 0
|
||||
wg := sync.NewWaitGroup()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
if err := sendMsg(client, data); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
if err := recvMsg(server, data); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
total += sz
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Wait()
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(total / b.N))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendMsg(c internalConn, buf []byte) error {
|
||||
n, err := c.Write(buf)
|
||||
if n != len(buf) || err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func recvMsg(c internalConn, buf []byte) error {
|
||||
for read := 0; read != len(buf); {
|
||||
n, err := c.Read(buf)
|
||||
read += n
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func withConnectionPair(b *testing.B, connUri string, h func(client, server internalConn)) {
|
||||
// Root of the service tree.
|
||||
supervisor := suture.New("main", suture.Spec{
|
||||
PassThroughPanics: true,
|
||||
})
|
||||
|
||||
cert := mustGetCert(b)
|
||||
deviceId := protocol.NewDeviceID(cert.Certificate[0])
|
||||
tlsCfg := tlsutil.SecureDefaultTLS13()
|
||||
tlsCfg.Certificates = []tls.Certificate{cert}
|
||||
tlsCfg.NextProtos = []string{"bench"}
|
||||
tlsCfg.ClientAuth = tls.RequestClientCert
|
||||
tlsCfg.SessionTicketsDisabled = true
|
||||
tlsCfg.InsecureSkipVerify = true
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
supervisor.ServeBackground(ctx)
|
||||
|
||||
cfg := config.Configuration{
|
||||
Options: config.OptionsConfiguration{
|
||||
RelaysEnabled: true,
|
||||
},
|
||||
}
|
||||
wcfg := config.Wrap("", cfg, deviceId, events.NoopLogger)
|
||||
uri, err := url.Parse(connUri)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
lf, err := getListenerFactory(cfg, uri)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
natSvc := nat.NewService(deviceId, wcfg)
|
||||
conns := make(chan internalConn, 1)
|
||||
listenSvc := lf.New(uri, wcfg, tlsCfg, conns, natSvc)
|
||||
supervisor.Add(listenSvc)
|
||||
|
||||
var addr *url.URL
|
||||
for {
|
||||
addrs := listenSvc.LANAddresses()
|
||||
if len(addrs) > 0 {
|
||||
if !strings.HasSuffix(addrs[0].Host, ":0") {
|
||||
addr = addrs[0]
|
||||
break
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
|
||||
df, err := getDialerFactory(cfg, addr)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
dialer := df.New(cfg.Options, tlsCfg)
|
||||
|
||||
// Relays might take some time to register the device, so dial multiple times
|
||||
clientConn, err := dialer.Dial(ctx, deviceId, addr)
|
||||
if err != nil {
|
||||
for i := 0; i < 10 && err != nil; i++ {
|
||||
clientConn, err = dialer.Dial(ctx, deviceId, addr)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := []byte("hello")
|
||||
|
||||
// Quic does not start a stream until some data is sent through, so send something for the AcceptStream
|
||||
// to fire on the other side.
|
||||
if err := sendMsg(clientConn, data); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
serverConn := <-conns
|
||||
|
||||
if err := recvMsg(serverConn, data); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
h(clientConn, serverConn)
|
||||
|
||||
_ = clientConn.Close()
|
||||
_ = serverConn.Close()
|
||||
}
|
||||
|
||||
func mustGetCert(b *testing.B) tls.Certificate {
|
||||
f1, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
f1.Close()
|
||||
f2, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
f2.Close()
|
||||
cert, err := tlsutil.NewCertificate(f1.Name(), f2.Name(), "bench", 10)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
_ = os.Remove(f1.Name())
|
||||
_ = os.Remove(f2.Name())
|
||||
return cert
|
||||
}
|
||||
|
||||
@@ -93,8 +93,15 @@ func (d *quicDialer) Dial(ctx context.Context, _ protocol.DeviceID, uri *url.URL
|
||||
type quicDialerFactory struct{}
|
||||
|
||||
func (quicDialerFactory) New(opts config.OptionsConfiguration, tlsCfg *tls.Config) genericDialer {
|
||||
// So the idea is that we should probably try dialing every 20 seconds.
|
||||
// However it would still be nice if this was adjustable/proportional to ReconnectIntervalS
|
||||
// But prevent something silly like 1/3 = 0 etc.
|
||||
quicInterval := opts.ReconnectIntervalS / 3
|
||||
if quicInterval < 10 {
|
||||
quicInterval = 10
|
||||
}
|
||||
return &quicDialer{commonDialer{
|
||||
reconnectInterval: time.Duration(opts.ReconnectIntervalS) * time.Second,
|
||||
reconnectInterval: time.Duration(quicInterval) * time.Second,
|
||||
tlsCfg: tlsCfg,
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ type quicListener struct {
|
||||
factory listenerFactory
|
||||
|
||||
address *url.URL
|
||||
laddr net.Addr
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
@@ -82,18 +83,33 @@ func (t *quicListener) OnExternalAddressChanged(address *stun.Host, via string)
|
||||
func (t *quicListener) serve(ctx context.Context) error {
|
||||
network := strings.ReplaceAll(t.uri.Scheme, "quic", "udp")
|
||||
|
||||
packetConn, err := net.ListenPacket(network, t.uri.Host)
|
||||
udpAddr, err := net.ResolveUDPAddr(network, t.uri.Host)
|
||||
if err != nil {
|
||||
l.Infoln("Listen (BEP/quic):", err)
|
||||
return err
|
||||
}
|
||||
defer func() { _ = packetConn.Close() }()
|
||||
|
||||
svc, conn := stun.New(t.cfg, t, packetConn)
|
||||
defer func() { _ = conn.Close() }()
|
||||
wrapped := &stunConnQUICWrapper{
|
||||
udpConn, err := net.ListenUDP(network, udpAddr)
|
||||
if err != nil {
|
||||
l.Infoln("Listen (BEP/quic):", err)
|
||||
return err
|
||||
}
|
||||
defer func() { _ = udpConn.Close() }()
|
||||
|
||||
svc, conn := stun.New(t.cfg, t, udpConn)
|
||||
defer conn.Close()
|
||||
|
||||
quicWrapper := quicWrapper{
|
||||
PacketConn: conn,
|
||||
underlying: packetConn.(*net.UDPConn),
|
||||
underlying: udpConn,
|
||||
}
|
||||
var wrapped net.PacketConn = &quicWrapper
|
||||
|
||||
if oobConn, ok := conn.(oobConn); ok {
|
||||
l.Debugf("wrapping in oob conn")
|
||||
wrapped = &oobConnWrapper{
|
||||
quicWrapper, oobConn,
|
||||
}
|
||||
}
|
||||
|
||||
go svc.Serve(ctx)
|
||||
@@ -106,12 +122,22 @@ func (t *quicListener) serve(ctx context.Context) error {
|
||||
l.Infoln("Listen (BEP/quic):", err)
|
||||
return err
|
||||
}
|
||||
t.notifyAddressesChanged(t)
|
||||
defer listener.Close()
|
||||
|
||||
t.notifyAddressesChanged(t)
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
l.Infof("QUIC listener (%v) starting", packetConn.LocalAddr())
|
||||
defer l.Infof("QUIC listener (%v) shutting down", packetConn.LocalAddr())
|
||||
l.Infof("QUIC listener (%v) starting", udpConn.LocalAddr())
|
||||
defer l.Infof("QUIC listener (%v) shutting down", udpConn.LocalAddr())
|
||||
|
||||
t.mut.Lock()
|
||||
t.laddr = udpConn.LocalAddr()
|
||||
t.mut.Unlock()
|
||||
defer func() {
|
||||
t.mut.Lock()
|
||||
t.laddr = nil
|
||||
t.mut.Unlock()
|
||||
}()
|
||||
|
||||
acceptFailures := 0
|
||||
const maxAcceptFailures = 10
|
||||
@@ -164,8 +190,8 @@ func (t *quicListener) URI() *url.URL {
|
||||
}
|
||||
|
||||
func (t *quicListener) WANAddresses() []*url.URL {
|
||||
uris := []*url.URL{t.uri}
|
||||
t.mut.Lock()
|
||||
uris := []*url.URL{maybeReplacePort(t.uri, t.laddr)}
|
||||
if t.address != nil {
|
||||
uris = append(uris, t.address)
|
||||
}
|
||||
@@ -174,9 +200,12 @@ func (t *quicListener) WANAddresses() []*url.URL {
|
||||
}
|
||||
|
||||
func (t *quicListener) LANAddresses() []*url.URL {
|
||||
addrs := []*url.URL{t.uri}
|
||||
network := strings.ReplaceAll(t.uri.Scheme, "quic", "udp")
|
||||
addrs = append(addrs, getURLsForAllAdaptersIfUnspecified(network, t.uri)...)
|
||||
t.mut.Lock()
|
||||
uri := maybeReplacePort(t.uri, t.laddr)
|
||||
t.mut.Unlock()
|
||||
addrs := []*url.URL{uri}
|
||||
network := strings.ReplaceAll(uri.Scheme, "quic", "udp")
|
||||
addrs = append(addrs, getURLsForAllAdaptersIfUnspecified(network, uri)...)
|
||||
return addrs
|
||||
}
|
||||
|
||||
@@ -219,17 +248,32 @@ func (quicListenerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type stunConnQUICWrapper struct {
|
||||
// quicWrapper provides methods used by quic
|
||||
// https://github.com/lucas-clemente/quic-go/blob/master/packet_handler_map.go#L85
|
||||
type quicWrapper struct {
|
||||
net.PacketConn
|
||||
underlying *net.UDPConn
|
||||
}
|
||||
|
||||
// SetReadBuffer is required by QUIC < v0.20.0
|
||||
func (s *stunConnQUICWrapper) SetReadBuffer(size int) error {
|
||||
// SetReadBuffer is required by QUIC
|
||||
func (s *quicWrapper) SetReadBuffer(size int) error {
|
||||
return s.underlying.SetReadBuffer(size)
|
||||
}
|
||||
|
||||
// SyscallConn is required by QUIC
|
||||
func (s *stunConnQUICWrapper) SyscallConn() (syscall.RawConn, error) {
|
||||
func (s *quicWrapper) SyscallConn() (syscall.RawConn, error) {
|
||||
return s.underlying.SyscallConn()
|
||||
}
|
||||
|
||||
// oobConn is used to assert that stun package returned a net.PacketConn that implements this interface.
|
||||
// If it does, we then wrap quicWrapper in oobConnWrapper, to expose those methods to QUIC package.
|
||||
type oobConn interface {
|
||||
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
|
||||
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
|
||||
}
|
||||
|
||||
// See: https://pkg.go.dev/github.com/lucas-clemente/quic-go#OOBCapablePacketConn
|
||||
type oobConnWrapper struct {
|
||||
quicWrapper
|
||||
oobConn
|
||||
}
|
||||
|
||||
@@ -44,38 +44,39 @@ type relayListener struct {
|
||||
}
|
||||
|
||||
func (t *relayListener) serve(ctx context.Context) error {
|
||||
clnt, err := client.NewClient(t.uri, t.tlsCfg.Certificates, nil, 10*time.Second)
|
||||
clnt, err := client.NewClient(t.uri, t.tlsCfg.Certificates, 10*time.Second)
|
||||
if err != nil {
|
||||
l.Infoln("Listen (BEP/relay):", err)
|
||||
return err
|
||||
}
|
||||
invitations := clnt.Invitations()
|
||||
|
||||
t.mut.Lock()
|
||||
t.client = clnt
|
||||
go clnt.Serve(ctx)
|
||||
t.mut.Unlock()
|
||||
|
||||
// Start with nil, so that we send a addresses changed notification as soon as we connect somewhere.
|
||||
var oldURI *url.URL
|
||||
|
||||
l.Infof("Relay listener (%v) starting", t)
|
||||
defer l.Infof("Relay listener (%v) shutting down", t)
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
invitationCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
go t.handleInvitations(invitationCtx, clnt)
|
||||
|
||||
return clnt.Serve(ctx)
|
||||
}
|
||||
|
||||
func (t *relayListener) handleInvitations(ctx context.Context, clnt client.RelayClient) {
|
||||
invitations := clnt.Invitations()
|
||||
|
||||
// Start with nil, so that we send a addresses changed notification as soon as we connect somewhere.
|
||||
var oldURI *url.URL
|
||||
|
||||
for {
|
||||
select {
|
||||
case inv, ok := <-invitations:
|
||||
if !ok {
|
||||
if err := clnt.Error(); err != nil {
|
||||
l.Infoln("Listen (BEP/relay):", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
case inv := <-invitations:
|
||||
conn, err := client.JoinSession(ctx, inv)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != context.Canceled {
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
l.Infoln("Listen (BEP/relay): joining session:", err)
|
||||
}
|
||||
continue
|
||||
@@ -119,7 +120,7 @@ func (t *relayListener) serve(ctx context.Context) error {
|
||||
}
|
||||
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-23
@@ -4,6 +4,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:generate -command counterfeiter go run github.com/maxbrunsfeld/counterfeiter/v6
|
||||
//go:generate counterfeiter -o mocks/service.go --fake-name Service . Service
|
||||
|
||||
package connections
|
||||
@@ -141,10 +142,10 @@ type service struct {
|
||||
natService *nat.Service
|
||||
evLogger events.Logger
|
||||
|
||||
listenersMut sync.RWMutex
|
||||
listeners map[string]genericListener
|
||||
listenerTokens map[string]suture.ServiceToken
|
||||
listenerSupervisor *suture.Supervisor
|
||||
deviceAddressesChanged chan struct{}
|
||||
listenersMut sync.RWMutex
|
||||
listeners map[string]genericListener
|
||||
listenerTokens map[string]suture.ServiceToken
|
||||
}
|
||||
|
||||
func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, bepProtocolName string, tlsDefaultCommonName string, evLogger events.Logger) Service {
|
||||
@@ -165,22 +166,10 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
|
||||
natService: nat.NewService(myID, cfg),
|
||||
evLogger: evLogger,
|
||||
|
||||
listenersMut: sync.NewRWMutex(),
|
||||
listeners: make(map[string]genericListener),
|
||||
listenerTokens: make(map[string]suture.ServiceToken),
|
||||
|
||||
// A listener can fail twice, rapidly. Any more than that and it
|
||||
// will be put on suspension for ten minutes. Restarts and changes
|
||||
// due to config are done by removing and adding services, so are
|
||||
// not subject to these limitations.
|
||||
listenerSupervisor: suture.New("c.S.listenerSupervisor", suture.Spec{
|
||||
EventHook: func(e suture.Event) {
|
||||
l.Infoln(e)
|
||||
},
|
||||
FailureThreshold: 2,
|
||||
FailureBackoff: 600 * time.Second,
|
||||
PassThroughPanics: true,
|
||||
}),
|
||||
deviceAddressesChanged: make(chan struct{}, 1),
|
||||
listenersMut: sync.NewRWMutex(),
|
||||
listeners: make(map[string]genericListener),
|
||||
listenerTokens: make(map[string]suture.ServiceToken),
|
||||
}
|
||||
cfg.Subscribe(service)
|
||||
|
||||
@@ -198,7 +187,6 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
|
||||
|
||||
service.Add(svcutil.AsService(service.connect, fmt.Sprintf("%s/connect", service)))
|
||||
service.Add(svcutil.AsService(service.handle, fmt.Sprintf("%s/handle", service)))
|
||||
service.Add(service.listenerSupervisor)
|
||||
service.Add(service.natService)
|
||||
|
||||
svcutil.OnSupervisorDone(service.Supervisor, func() {
|
||||
@@ -392,6 +380,7 @@ func (s *service) connect(ctx context.Context) error {
|
||||
l.Debugln("Next connection loop in", sleep)
|
||||
|
||||
select {
|
||||
case <-s.deviceAddressesChanged:
|
||||
case <-time.After(sleep):
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
@@ -644,8 +633,18 @@ func (s *service) createListener(factory listenerFactory, uri *url.URL) bool {
|
||||
|
||||
listener := factory.New(uri, s.cfg, s.tlsCfg, s.conns, s.natService)
|
||||
listener.OnAddressesChanged(s.logListenAddressesChangedEvent)
|
||||
|
||||
// Retrying a listener many times in rapid succession is unlikely to help,
|
||||
// thus back off quickly. A listener may soon be functional again, e.g. due
|
||||
// to a network interface coming back online - retry every minute.
|
||||
spec := svcutil.SpecWithInfoLogger(l)
|
||||
spec.FailureThreshold = 2
|
||||
spec.FailureBackoff = time.Minute
|
||||
sup := suture.New(fmt.Sprintf("listenerSupervisor@%v", listener), spec)
|
||||
sup.Add(listener)
|
||||
|
||||
s.listeners[uri.String()] = listener
|
||||
s.listenerTokens[uri.String()] = s.listenerSupervisor.Add(listener)
|
||||
s.listenerTokens[uri.String()] = s.Add(sup)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -675,6 +674,8 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
}
|
||||
}
|
||||
|
||||
s.checkAndSignalConnectLoopOnUpdatedDevices(from, to)
|
||||
|
||||
s.listenersMut.Lock()
|
||||
seen := make(map[string]struct{})
|
||||
for _, addr := range to.Options.ListenAddresses() {
|
||||
@@ -723,7 +724,7 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
for addr, listener := range s.listeners {
|
||||
if _, ok := seen[addr]; !ok || listener.Factory().Valid(to) != nil {
|
||||
l.Debugln("Stopping listener", addr)
|
||||
s.listenerSupervisor.Remove(s.listenerTokens[addr])
|
||||
s.Remove(s.listenerTokens[addr])
|
||||
delete(s.listenerTokens, addr)
|
||||
delete(s.listeners, addr)
|
||||
}
|
||||
@@ -733,6 +734,25 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *service) checkAndSignalConnectLoopOnUpdatedDevices(from, to config.Configuration) {
|
||||
oldDevices := make(map[protocol.DeviceID]config.DeviceConfiguration, len(from.Devices))
|
||||
for _, dev := range from.Devices {
|
||||
oldDevices[dev.DeviceID] = dev
|
||||
}
|
||||
|
||||
for _, dev := range to.Devices {
|
||||
oldDev, ok := oldDevices[dev.DeviceID]
|
||||
if !ok || !util.EqualStrings(oldDev.Addresses, dev.Addresses) {
|
||||
select {
|
||||
case s.deviceAddressesChanged <- struct{}{}:
|
||||
default:
|
||||
// channel is blocked - a config update is already pending for the connection loop.
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) AllAddresses() []string {
|
||||
s.listenersMut.RLock()
|
||||
var addrs []string
|
||||
|
||||
@@ -40,6 +40,7 @@ type tcpListener struct {
|
||||
|
||||
natService *nat.Service
|
||||
mapping *nat.Mapping
|
||||
laddr net.Addr
|
||||
|
||||
mut sync.RWMutex
|
||||
}
|
||||
@@ -60,25 +61,37 @@ func (t *tcpListener) serve(ctx context.Context) error {
|
||||
l.Infoln("Listen (BEP/tcp):", err)
|
||||
return err
|
||||
}
|
||||
t.notifyAddressesChanged(t)
|
||||
registry.Register(t.uri.Scheme, tcaddr)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
// We might bind to :0, so use the port we've been given.
|
||||
tcaddr = listener.Addr().(*net.TCPAddr)
|
||||
|
||||
t.notifyAddressesChanged(t)
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
registry.Register(t.uri.Scheme, tcaddr)
|
||||
defer registry.Unregister(t.uri.Scheme, tcaddr)
|
||||
|
||||
l.Infof("TCP listener (%v) starting", listener.Addr())
|
||||
defer l.Infof("TCP listener (%v) shutting down", listener.Addr())
|
||||
l.Infof("TCP listener (%v) starting", tcaddr)
|
||||
defer l.Infof("TCP listener (%v) shutting down", tcaddr)
|
||||
|
||||
mapping := t.natService.NewMapping(nat.TCP, tcaddr.IP, tcaddr.Port)
|
||||
mapping.OnChanged(func(_ *nat.Mapping, _, _ []nat.Address) {
|
||||
t.notifyAddressesChanged(t)
|
||||
})
|
||||
// Should be called after t.mapping is nil'ed out.
|
||||
defer t.natService.RemoveMapping(mapping)
|
||||
|
||||
t.mut.Lock()
|
||||
t.mapping = mapping
|
||||
t.laddr = tcaddr
|
||||
t.mut.Unlock()
|
||||
defer func() {
|
||||
t.mut.Lock()
|
||||
t.mapping = nil
|
||||
t.laddr = nil
|
||||
t.mut.Unlock()
|
||||
}()
|
||||
|
||||
acceptFailures := 0
|
||||
const maxAcceptFailures = 10
|
||||
@@ -94,9 +107,6 @@ func (t *tcpListener) serve(ctx context.Context) error {
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
}
|
||||
t.mut.Lock()
|
||||
t.mapping = nil
|
||||
t.mut.Unlock()
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
@@ -146,8 +156,10 @@ func (t *tcpListener) URI() *url.URL {
|
||||
}
|
||||
|
||||
func (t *tcpListener) WANAddresses() []*url.URL {
|
||||
uris := []*url.URL{t.uri}
|
||||
t.mut.RLock()
|
||||
uris := []*url.URL{
|
||||
maybeReplacePort(t.uri, t.laddr),
|
||||
}
|
||||
if t.mapping != nil {
|
||||
addrs := t.mapping.ExternalAddresses()
|
||||
for _, addr := range addrs {
|
||||
@@ -179,8 +191,11 @@ func (t *tcpListener) WANAddresses() []*url.URL {
|
||||
}
|
||||
|
||||
func (t *tcpListener) LANAddresses() []*url.URL {
|
||||
addrs := []*url.URL{t.uri}
|
||||
addrs = append(addrs, getURLsForAllAdaptersIfUnspecified(t.uri.Scheme, t.uri)...)
|
||||
t.mut.RLock()
|
||||
uri := maybeReplacePort(t.uri, t.laddr)
|
||||
t.mut.RUnlock()
|
||||
addrs := []*url.URL{uri}
|
||||
addrs = append(addrs, getURLsForAllAdaptersIfUnspecified(uri.Scheme, uri)...)
|
||||
return addrs
|
||||
}
|
||||
|
||||
|
||||
@@ -117,3 +117,30 @@ func isV4Local(ip net.IP) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func maybeReplacePort(uri *url.URL, laddr net.Addr) *url.URL {
|
||||
if laddr == nil {
|
||||
return uri
|
||||
}
|
||||
|
||||
host, portStr, err := net.SplitHostPort(uri.Host)
|
||||
if err != nil {
|
||||
return uri
|
||||
}
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
return uri
|
||||
}
|
||||
if port != 0 {
|
||||
return uri
|
||||
}
|
||||
|
||||
_, lportStr, err := net.SplitHostPort(laddr.String())
|
||||
if err != nil {
|
||||
return uri
|
||||
}
|
||||
|
||||
uriCopy := *uri
|
||||
uriCopy.Host = net.JoinHostPort(host, lportStr)
|
||||
return &uriCopy
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ const (
|
||||
// KeyTypeFolderStatistic <folder ID as string> <some string> = some value
|
||||
KeyTypeFolderStatistic byte = 4
|
||||
|
||||
// KeyTypeVirtualMtime <int32 folder ID> <file name> = dbMtime
|
||||
// KeyTypeVirtualMtime <int32 folder ID> <file name> = mtimeMapping
|
||||
KeyTypeVirtualMtime byte = 5
|
||||
|
||||
// KeyTypeFolderIdx <int32 id> = string value
|
||||
|
||||
+90
-24
@@ -70,6 +70,9 @@ type Lowlevel struct {
|
||||
recheckInterval time.Duration
|
||||
oneFileSetCreated chan struct{}
|
||||
evLogger events.Logger
|
||||
|
||||
blockFilter *bloomFilter
|
||||
versionFilter *bloomFilter
|
||||
}
|
||||
|
||||
func NewLowlevel(backend backend.Backend, evLogger events.Logger, opts ...Option) (*Lowlevel, error) {
|
||||
@@ -587,6 +590,18 @@ func (db *Lowlevel) dropFolderIndexIDs(folder []byte) error {
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *Lowlevel) dropIndexIDs() error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
if err := t.deleteKeyPrefix([]byte{KeyTypeIndexID}); err != nil {
|
||||
return err
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *Lowlevel) dropMtimes(folder []byte) error {
|
||||
key, err := db.keyer.GenerateMtimesKey(nil, folder)
|
||||
if err != nil {
|
||||
@@ -663,7 +678,7 @@ func (db *Lowlevel) timeUntil(key string, every time.Duration) time.Duration {
|
||||
return sleepTime
|
||||
}
|
||||
|
||||
func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
func (db *Lowlevel) gcIndirect(ctx context.Context) (err error) {
|
||||
// The indirection GC uses bloom filters to track used block lists and
|
||||
// versions. This means iterating over all items, adding their hashes to
|
||||
// the filter, then iterating over the indirected items and removing
|
||||
@@ -674,8 +689,29 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
// Indirection GC needs to run when there are no modifications to the
|
||||
// FileInfos or indirected items.
|
||||
|
||||
l.Debugln("Starting database GC")
|
||||
|
||||
// Create a new set of bloom filters, while holding the gcMut which
|
||||
// guarantees that no other modifications are happening concurrently.
|
||||
|
||||
db.gcMut.Lock()
|
||||
defer db.gcMut.Unlock()
|
||||
capacity := indirectGCBloomCapacity
|
||||
if db.gcKeyCount > capacity {
|
||||
capacity = db.gcKeyCount
|
||||
}
|
||||
db.blockFilter = newBloomFilter(capacity)
|
||||
db.versionFilter = newBloomFilter(capacity)
|
||||
db.gcMut.Unlock()
|
||||
|
||||
defer func() {
|
||||
// Forget the bloom filters on the way out.
|
||||
db.gcMut.Lock()
|
||||
db.blockFilter = nil
|
||||
db.versionFilter = nil
|
||||
db.gcMut.Unlock()
|
||||
}()
|
||||
|
||||
var discardedBlocks, matchedBlocks, discardedVersions, matchedVersions int
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
@@ -688,16 +724,13 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
// items. For simplicity's sake we track just one count, which is the
|
||||
// highest of the various indirected items.
|
||||
|
||||
capacity := indirectGCBloomCapacity
|
||||
if db.gcKeyCount > capacity {
|
||||
capacity = db.gcKeyCount
|
||||
}
|
||||
blockFilter := newBloomFilter(capacity)
|
||||
versionFilter := newBloomFilter(capacity)
|
||||
|
||||
// Iterate the FileInfos, unmarshal the block and version hashes and
|
||||
// add them to the filter.
|
||||
|
||||
// This happens concurrently with normal database modifications, though
|
||||
// those modifications will now also add their blocks and versions to
|
||||
// the bloom filters.
|
||||
|
||||
it, err := t.NewPrefixIterator([]byte{KeyTypeDevice})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -714,18 +747,35 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
if err := hashes.Unmarshal(it.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(hashes.BlocksHash) > 0 {
|
||||
blockFilter.add(hashes.BlocksHash)
|
||||
}
|
||||
if len(hashes.VersionHash) > 0 {
|
||||
versionFilter.add(hashes.VersionHash)
|
||||
}
|
||||
db.recordIndirectionHashes(hashes)
|
||||
}
|
||||
it.Release()
|
||||
if err := it.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// For the next phase we grab the GC lock again and hold it for the rest
|
||||
// of the method call. Now there can't be any further modifications to
|
||||
// the database or the bloom filters.
|
||||
|
||||
db.gcMut.Lock()
|
||||
defer db.gcMut.Unlock()
|
||||
|
||||
// Only print something if the process takes more than "a moment".
|
||||
logWait := make(chan struct{})
|
||||
logTimer := time.AfterFunc(10*time.Second, func() {
|
||||
l.Infoln("Database GC in progress - many Syncthing operations will be unresponsive until it's finished")
|
||||
close(logWait)
|
||||
})
|
||||
defer func() {
|
||||
if logTimer.Stop() {
|
||||
return
|
||||
}
|
||||
<-logWait // Make sure messages are sent in order.
|
||||
l.Infof("Database GC complete (discarded/remaining: %v/%v blocks, %v/%v versions)",
|
||||
discardedBlocks, matchedBlocks, discardedVersions, matchedVersions)
|
||||
}()
|
||||
|
||||
// Iterate over block lists, removing keys with hashes that don't match
|
||||
// the filter.
|
||||
|
||||
@@ -734,7 +784,6 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
defer it.Release()
|
||||
matchedBlocks := 0
|
||||
for it.Next() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -743,13 +792,14 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
}
|
||||
|
||||
key := blockListKey(it.Key())
|
||||
if blockFilter.has(key.Hash()) {
|
||||
if db.blockFilter.has(key.Hash()) {
|
||||
matchedBlocks++
|
||||
continue
|
||||
}
|
||||
if err := t.Delete(key); err != nil {
|
||||
return err
|
||||
}
|
||||
discardedBlocks++
|
||||
}
|
||||
it.Release()
|
||||
if err := it.Error(); err != nil {
|
||||
@@ -763,7 +813,6 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
matchedVersions := 0
|
||||
for it.Next() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -772,13 +821,14 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
}
|
||||
|
||||
key := versionKey(it.Key())
|
||||
if versionFilter.has(key.Hash()) {
|
||||
if db.versionFilter.has(key.Hash()) {
|
||||
matchedVersions++
|
||||
continue
|
||||
}
|
||||
if err := t.Delete(key); err != nil {
|
||||
return err
|
||||
}
|
||||
discardedVersions++
|
||||
}
|
||||
it.Release()
|
||||
if err := it.Error(); err != nil {
|
||||
@@ -795,15 +845,31 @@ func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.Compact()
|
||||
l.Debugf("Finished GC (discarded/remaining: %v/%v blocks, %v/%v versions)", discardedBlocks, matchedBlocks, discardedVersions, matchedVersions)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newBloomFilter(capacity int) bloomFilter {
|
||||
func (db *Lowlevel) recordIndirectionHashesForFile(f *protocol.FileInfo) {
|
||||
db.recordIndirectionHashes(IndirectionHashesOnly{BlocksHash: f.BlocksHash, VersionHash: f.VersionHash})
|
||||
}
|
||||
|
||||
func (db *Lowlevel) recordIndirectionHashes(hs IndirectionHashesOnly) {
|
||||
// must be called with gcMut held (at least read-held)
|
||||
if db.blockFilter != nil && len(hs.BlocksHash) > 0 {
|
||||
db.blockFilter.add(hs.BlocksHash)
|
||||
}
|
||||
if db.versionFilter != nil && len(hs.VersionHash) > 0 {
|
||||
db.versionFilter.add(hs.VersionHash)
|
||||
}
|
||||
}
|
||||
|
||||
func newBloomFilter(capacity int) *bloomFilter {
|
||||
var buf [16]byte
|
||||
io.ReadFull(rand.Reader, buf[:])
|
||||
|
||||
return bloomFilter{
|
||||
f: blobloom.NewOptimized(blobloom.Config{
|
||||
return &bloomFilter{
|
||||
f: blobloom.NewSyncOptimized(blobloom.Config{
|
||||
Capacity: uint64(capacity),
|
||||
FPRate: indirectGCBloomFalsePositiveRate,
|
||||
MaxBits: 8 * indirectGCBloomMaxBytes,
|
||||
@@ -815,7 +881,7 @@ func newBloomFilter(capacity int) bloomFilter {
|
||||
}
|
||||
|
||||
type bloomFilter struct {
|
||||
f *blobloom.Filter
|
||||
f *blobloom.SyncFilter
|
||||
k0, k1 uint64 // Random key for SipHash.
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -26,11 +26,13 @@ func (db *Lowlevel) AddOrUpdatePendingDevice(device protocol.DeviceID, name, add
|
||||
return db.Put(key, bs)
|
||||
}
|
||||
|
||||
func (db *Lowlevel) RemovePendingDevice(device protocol.DeviceID) {
|
||||
func (db *Lowlevel) RemovePendingDevice(device protocol.DeviceID) error {
|
||||
key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
|
||||
if err := db.Delete(key); err != nil {
|
||||
l.Warnf("Failed to remove pending device entry: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PendingDevices enumerates all entries. Invalid ones are dropped from the database
|
||||
@@ -79,32 +81,35 @@ func (db *Lowlevel) AddOrUpdatePendingFolder(id string, of ObservedFolder, devic
|
||||
}
|
||||
|
||||
// RemovePendingFolderForDevice removes entries for specific folder / device combinations.
|
||||
func (db *Lowlevel) RemovePendingFolderForDevice(id string, device protocol.DeviceID) {
|
||||
func (db *Lowlevel) RemovePendingFolderForDevice(id string, device protocol.DeviceID) error {
|
||||
key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err := db.Delete(key); err != nil {
|
||||
l.Warnf("Failed to remove pending folder entry: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovePendingFolder removes all entries matching a specific folder ID.
|
||||
func (db *Lowlevel) RemovePendingFolder(id string) {
|
||||
func (db *Lowlevel) RemovePendingFolder(id string) error {
|
||||
iter, err := db.NewPrefixIterator([]byte{KeyTypePendingFolder})
|
||||
if err != nil {
|
||||
l.Infof("Could not iterate through pending folder entries: %v", err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
defer iter.Release()
|
||||
for iter.Next() {
|
||||
if id != string(db.keyer.FolderFromPendingFolderKey(iter.Key())) {
|
||||
continue
|
||||
}
|
||||
if err := db.Delete(iter.Key()); err != nil {
|
||||
if err = db.Delete(iter.Key()); err != nil {
|
||||
l.Warnf("Failed to remove pending folder entry: %v", err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Consolidated information about a pending folder
|
||||
|
||||
+54
-1
@@ -20,7 +20,7 @@ import (
|
||||
// do not put restrictions on downgrades (e.g. for repairs after a bugfix).
|
||||
const (
|
||||
dbVersion = 14
|
||||
dbMigrationVersion = 16
|
||||
dbMigrationVersion = 18
|
||||
dbMinSyncthingVersion = "v1.9.0"
|
||||
)
|
||||
|
||||
@@ -101,6 +101,8 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
{13, 13, "v1.7.0", db.updateSchemaTo13},
|
||||
{14, 14, "v1.9.0", db.updateSchemaTo14},
|
||||
{14, 16, "v1.9.0", db.checkRepairMigration},
|
||||
{14, 17, "v1.9.0", db.migration17},
|
||||
{14, 18, "v1.9.0", db.dropIndexIDsMigration},
|
||||
}
|
||||
|
||||
for _, m := range migrations {
|
||||
@@ -783,6 +785,57 @@ func (db *schemaUpdater) checkRepairMigration(_ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// migration17 finds all files that were pulled as invalid from an invalid
|
||||
// global and make sure they get scanned/pulled again.
|
||||
func (db *schemaUpdater) migration17(prev int) error {
|
||||
if prev < 16 {
|
||||
// Issue was introduced in migration to 16
|
||||
return nil
|
||||
}
|
||||
t, err := db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
meta, err := db.loadMetadataTracker(folderStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
batch := NewFileInfoBatch(func(fs []protocol.FileInfo) error {
|
||||
return db.updateLocalFiles(folder, fs, meta)
|
||||
})
|
||||
var innerErr error
|
||||
err = t.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(fi protocol.FileIntf) bool {
|
||||
if fi.IsInvalid() && fi.FileLocalFlags() == 0 {
|
||||
f := fi.(protocol.FileInfo)
|
||||
f.SetMustRescan()
|
||||
f.Version = protocol.Vector{}
|
||||
batch.Append(f)
|
||||
innerErr = batch.FlushIfFull()
|
||||
return innerErr == nil
|
||||
}
|
||||
return true
|
||||
})
|
||||
if innerErr != nil {
|
||||
return innerErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) dropIndexIDsMigration(_ int) error {
|
||||
return db.dropIndexIDs()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) rewriteGlobals(t readWriteTransaction) error {
|
||||
it, err := t.NewPrefixIterator([]byte{KeyTypeGlobal})
|
||||
if err != nil {
|
||||
|
||||
+1
-10
@@ -451,21 +451,12 @@ func DropDeltaIndexIDs(db *Lowlevel) {
|
||||
}
|
||||
opStr := "DropDeltaIndexIDs"
|
||||
l.Debugf(opStr)
|
||||
dbi, err := db.NewPrefixIterator([]byte{KeyTypeIndexID})
|
||||
err := db.dropIndexIDs()
|
||||
if backend.IsClosed(err) {
|
||||
return
|
||||
} else if err != nil {
|
||||
fatalError(err, opStr, db)
|
||||
}
|
||||
defer dbi.Release()
|
||||
for dbi.Next() {
|
||||
if err := db.Delete(dbi.Key()); err != nil && !backend.IsClosed(err) {
|
||||
fatalError(err, opStr, db)
|
||||
}
|
||||
}
|
||||
if err := dbi.Error(); err != nil && !backend.IsClosed(err) {
|
||||
fatalError(err, opStr, db)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeFilenamesAndDropDuplicates(fs []protocol.FileInfo) []protocol.FileInfo {
|
||||
|
||||
@@ -472,7 +472,6 @@ func TestNeedWithInvalid(t *testing.T) {
|
||||
remote0Have[0],
|
||||
remote1Have[0],
|
||||
remote0Have[2],
|
||||
remote1Have[2],
|
||||
}
|
||||
|
||||
replace(s, protocol.LocalDeviceID, localHave)
|
||||
|
||||
+11
-44
@@ -1652,10 +1652,7 @@ func (m *FileVersion) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -1739,10 +1736,7 @@ func (m *VersionList) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2222,10 +2216,7 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2309,10 +2300,7 @@ func (m *BlockList) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2430,10 +2418,7 @@ func (m *IndirectionHashesOnly) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2650,10 +2635,7 @@ func (m *Counts) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2756,10 +2738,7 @@ func (m *CountsSet) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -2916,10 +2895,7 @@ func (m *FileVersionDeprecated) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -3003,10 +2979,7 @@ func (m *VersionListDeprecated) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -3141,10 +3114,7 @@ func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
@@ -3291,10 +3261,7 @@ func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
+18
-4
@@ -398,12 +398,16 @@ func (t *readOnlyTransaction) withBlocksHash(folder, hash []byte, iterator Itera
|
||||
f.Name = osutil.NativeFilename(f.Name)
|
||||
|
||||
if !bytes.Equal(f.BlocksHash, hash) {
|
||||
l.Warnf("Mismatching block map list hashes: got %x expected %x", f.BlocksHash, hash)
|
||||
msg := "Mismatching block map list hashes"
|
||||
t.evLogger.Log(events.Failure, fmt.Sprintln(msg, "in withBlocksHash"))
|
||||
l.Warnf("%v: got %x expected %x", msg, f.BlocksHash, hash)
|
||||
continue
|
||||
}
|
||||
|
||||
if f.IsDeleted() || f.IsInvalid() || f.IsDirectory() || f.IsSymlink() {
|
||||
l.Warnf("Found something of unexpected type in block list map: %s", f)
|
||||
msg := "Found something of unexpected type in block list map"
|
||||
t.evLogger.Log(events.Failure, fmt.Sprintln(msg, "in withBlocksHash"))
|
||||
l.Warnf("%v: %s", msg, f)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -534,6 +538,11 @@ func (t *readOnlyTransaction) withNeedLocal(folder []byte, truncate bool, fn Ite
|
||||
type readWriteTransaction struct {
|
||||
backend.WriteTransaction
|
||||
readOnlyTransaction
|
||||
indirectionTracker
|
||||
}
|
||||
|
||||
type indirectionTracker interface {
|
||||
recordIndirectionHashesForFile(f *protocol.FileInfo)
|
||||
}
|
||||
|
||||
func (db *Lowlevel) newReadWriteTransaction(hooks ...backend.CommitHook) (readWriteTransaction, error) {
|
||||
@@ -547,6 +556,7 @@ func (db *Lowlevel) newReadWriteTransaction(hooks ...backend.CommitHook) (readWr
|
||||
ReadTransaction: tran,
|
||||
keyer: db.keyer,
|
||||
},
|
||||
indirectionTracker: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -606,6 +616,8 @@ func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo) error {
|
||||
fi.VersionHash = nil
|
||||
}
|
||||
|
||||
t.indirectionTracker.recordIndirectionHashesForFile(&fi)
|
||||
|
||||
fiBs := mustMarshal(&fi)
|
||||
return t.Put(fkey, fiBs)
|
||||
}
|
||||
@@ -774,8 +786,10 @@ func (t readWriteTransaction) updateLocalNeed(keyBuf, folder, name []byte, add b
|
||||
}
|
||||
|
||||
func Need(global FileVersion, haveLocal bool, localVersion protocol.Vector) bool {
|
||||
// We never need a file without a valid version.
|
||||
if global.Version.IsEmpty() {
|
||||
// We never need an invalid file or a file without a valid version (just
|
||||
// another way of expressing "invalid", really, until we fix that
|
||||
// part...).
|
||||
if global.IsInvalid() || global.Version.IsEmpty() {
|
||||
return false
|
||||
}
|
||||
// We don't need a deleted file if we don't have it.
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2021 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/syncthing/syncthing/lib/protocol"
|
||||
|
||||
// How many files to send in each Index/IndexUpdate message.
|
||||
const (
|
||||
MaxBatchSizeBytes = 250 * 1024 // Aim for making index messages no larger than 250 KiB (uncompressed)
|
||||
MaxBatchSizeFiles = 1000 // Either way, don't include more files than this
|
||||
)
|
||||
|
||||
// FileInfoBatch is a utility to do file operations on the database in suitably
|
||||
// sized batches.
|
||||
type FileInfoBatch struct {
|
||||
infos []protocol.FileInfo
|
||||
size int
|
||||
flushFn func([]protocol.FileInfo) error
|
||||
}
|
||||
|
||||
func NewFileInfoBatch(fn func([]protocol.FileInfo) error) *FileInfoBatch {
|
||||
return &FileInfoBatch{
|
||||
infos: make([]protocol.FileInfo, 0, MaxBatchSizeFiles),
|
||||
flushFn: fn,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) SetFlushFunc(fn func([]protocol.FileInfo) error) {
|
||||
b.flushFn = fn
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Append(f protocol.FileInfo) {
|
||||
b.infos = append(b.infos, f)
|
||||
b.size += f.ProtoSize()
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Full() bool {
|
||||
return len(b.infos) >= MaxBatchSizeFiles || b.size >= MaxBatchSizeBytes
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) FlushIfFull() error {
|
||||
if b.Full() {
|
||||
return b.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Flush() error {
|
||||
if len(b.infos) == 0 {
|
||||
return nil
|
||||
}
|
||||
if err := b.flushFn(b.infos); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Reset() {
|
||||
b.infos = b.infos[:0]
|
||||
b.size = 0
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Size() int {
|
||||
return b.size
|
||||
}
|
||||
@@ -298,10 +298,7 @@ func (m *Announce) Unmarshal(dAtA []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthLocal
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:generate -command counterfeiter go run github.com/maxbrunsfeld/counterfeiter/v6
|
||||
//go:generate counterfeiter -o mocks/manager.go --fake-name Manager . Manager
|
||||
|
||||
package discover
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:generate -command counterfeiter go run github.com/maxbrunsfeld/counterfeiter/v6
|
||||
//go:generate counterfeiter -o mocks/buffered_subscription.go --fake-name BufferedSubscription . BufferedSubscription
|
||||
|
||||
// Package events provides event subscription and polling functionality.
|
||||
|
||||
@@ -330,6 +330,14 @@ func (f *BasicFilesystem) SameFile(fi1, fi2 FileInfo) bool {
|
||||
return os.SameFile(f1.osFileInfo(), f2.osFileInfo())
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) underlying() (Filesystem, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) wrapperType() filesystemWrapperType {
|
||||
return filesystemWrapperTypeNone
|
||||
}
|
||||
|
||||
// basicFile implements the fs.File interface on top of an os.File
|
||||
type basicFile struct {
|
||||
*os.File
|
||||
|
||||
@@ -10,8 +10,9 @@ package fs
|
||||
|
||||
import "github.com/syncthing/notify"
|
||||
|
||||
// notify.InAttrib is not only required for permissions, but also mod. time changes
|
||||
const (
|
||||
subEventMask = notify.InCreate | notify.InMovedTo | notify.InDelete | notify.InDeleteSelf | notify.InModify | notify.InMovedFrom | notify.InMoveSelf
|
||||
permEventMask = notify.InAttrib
|
||||
subEventMask = notify.InCreate | notify.InMovedTo | notify.InDelete | notify.InDeleteSelf | notify.InModify | notify.InMovedFrom | notify.InMoveSelf | notify.InAttrib
|
||||
permEventMask = 0
|
||||
rmEventMask = notify.InDelete | notify.InDeleteSelf | notify.InMovedFrom | notify.InMoveSelf
|
||||
)
|
||||
|
||||
@@ -13,7 +13,8 @@ import "github.com/syncthing/notify"
|
||||
const (
|
||||
// Platform independent notify.Create is required, as kqueue does not have
|
||||
// any event signalling file creation, but notify does generate those internally.
|
||||
subEventMask = notify.NoteDelete | notify.NoteWrite | notify.NoteRename | notify.Create
|
||||
permEventMask = notify.NoteAttrib | notify.NoteExtend
|
||||
// NoteAttrib is not only required for permissions, but also mod. time changes
|
||||
subEventMask = notify.NoteDelete | notify.NoteWrite | notify.NoteRename | notify.Create | notify.NoteAttrib | notify.NoteExtend
|
||||
permEventMask = 0
|
||||
rmEventMask = notify.NoteDelete | notify.NoteRename
|
||||
)
|
||||
|
||||
@@ -87,7 +87,7 @@ func TestWatchIgnore(t *testing.T) {
|
||||
{name, NonRemove},
|
||||
}
|
||||
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), skipIgnoredDirs: true})
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), skipIgnoredDirs: true}, false)
|
||||
}
|
||||
|
||||
func TestWatchInclude(t *testing.T) {
|
||||
@@ -114,7 +114,7 @@ func TestWatchInclude(t *testing.T) {
|
||||
{name, NonRemove},
|
||||
}
|
||||
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), include: filepath.Join(name, included)})
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{ignore: filepath.Join(name, ignored), include: filepath.Join(name, included)}, false)
|
||||
}
|
||||
|
||||
func TestWatchRename(t *testing.T) {
|
||||
@@ -146,7 +146,7 @@ func TestWatchRename(t *testing.T) {
|
||||
|
||||
// set the "allow others" flag because we might get the create of
|
||||
// "oldfile" initially
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{})
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
|
||||
}
|
||||
|
||||
// TestWatchWinRoot checks that a watch at a drive letter does not panic due to
|
||||
@@ -308,7 +308,7 @@ func TestWatchOverflow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{})
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
|
||||
}
|
||||
|
||||
func TestWatchErrorLinuxInterpretation(t *testing.T) {
|
||||
@@ -413,7 +413,39 @@ func TestWatchIssue4877(t *testing.T) {
|
||||
testFs = origTestFs
|
||||
}()
|
||||
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{})
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, false)
|
||||
}
|
||||
|
||||
func TestWatchModTime(t *testing.T) {
|
||||
name := "modtime"
|
||||
|
||||
file := createTestFile(name, "foo")
|
||||
path := filepath.Join(name, file)
|
||||
now := time.Now()
|
||||
before := now.Add(-10 * time.Second)
|
||||
if err := testFs.Chtimes(path, before, before); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testCase := func() {
|
||||
if err := testFs.Chtimes(path, now, now); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
expectedEvents := []Event{
|
||||
{file, NonRemove},
|
||||
}
|
||||
|
||||
var allowedEvents []Event
|
||||
// Apparently an event for the parent is also sent on mac
|
||||
if runtime.GOOS == "darwin" {
|
||||
allowedEvents = []Event{
|
||||
{name, NonRemove},
|
||||
}
|
||||
}
|
||||
|
||||
testScenario(t, name, testCase, expectedEvents, allowedEvents, fakeMatcher{}, true)
|
||||
}
|
||||
|
||||
// path relative to folder root, also creates parent dirs if necessary
|
||||
@@ -442,7 +474,7 @@ func sleepMs(ms int) {
|
||||
time.Sleep(time.Duration(ms) * time.Millisecond)
|
||||
}
|
||||
|
||||
func testScenario(t *testing.T, name string, testCase func(), expectedEvents, allowedEvents []Event, fm fakeMatcher) {
|
||||
func testScenario(t *testing.T, name string, testCase func(), expectedEvents, allowedEvents []Event, fm fakeMatcher, ignorePerms bool) {
|
||||
if err := testFs.MkdirAll(name, 0755); err != nil {
|
||||
panic(fmt.Sprintf("Failed to create directory %s: %s", name, err))
|
||||
}
|
||||
@@ -451,7 +483,7 @@ func testScenario(t *testing.T, name string, testCase func(), expectedEvents, al
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
eventChan, errChan, err := testFs.Watch(name, fm, ctx, false)
|
||||
eventChan, errChan, err := testFs.Watch(name, fm, ctx, ignorePerms)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -157,9 +157,9 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
||||
// pathseparator.
|
||||
func (f *BasicFilesystem) unrootedChecked(absPath string, roots []string) (string, error) {
|
||||
absPath = f.resolveWin83(absPath)
|
||||
lowerAbsPath := UnicodeLowercase(absPath)
|
||||
lowerAbsPath := UnicodeLowercaseNormalized(absPath)
|
||||
for _, root := range roots {
|
||||
lowerRoot := UnicodeLowercase(root)
|
||||
lowerRoot := UnicodeLowercaseNormalized(root)
|
||||
if lowerAbsPath+string(PathSeparator) == lowerRoot {
|
||||
return ".", nil
|
||||
}
|
||||
@@ -171,7 +171,7 @@ func (f *BasicFilesystem) unrootedChecked(absPath string, roots []string) (strin
|
||||
}
|
||||
|
||||
func rel(path, prefix string) string {
|
||||
lowerRel := strings.TrimPrefix(strings.TrimPrefix(UnicodeLowercase(path), UnicodeLowercase(prefix)), string(PathSeparator))
|
||||
lowerRel := strings.TrimPrefix(strings.TrimPrefix(UnicodeLowercaseNormalized(path), UnicodeLowercaseNormalized(prefix)), string(PathSeparator))
|
||||
return path[len(path)-len(lowerRel):]
|
||||
}
|
||||
|
||||
@@ -193,8 +193,8 @@ func (f *BasicFilesystem) resolveWin83(absPath string) string {
|
||||
}
|
||||
// Failed getting the long path. Return the part of the path which is
|
||||
// already a long path.
|
||||
lowerRoot := UnicodeLowercase(f.root)
|
||||
for absPath = filepath.Dir(absPath); strings.HasPrefix(UnicodeLowercase(absPath), lowerRoot); absPath = filepath.Dir(absPath) {
|
||||
lowerRoot := UnicodeLowercaseNormalized(f.root)
|
||||
for absPath = filepath.Dir(absPath); strings.HasPrefix(UnicodeLowercaseNormalized(absPath), lowerRoot); absPath = filepath.Dir(absPath) {
|
||||
if !isMaybeWin83(absPath) {
|
||||
return absPath
|
||||
}
|
||||
|
||||
+15
-3
@@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -339,6 +340,14 @@ func (f *caseFilesystem) Unhide(name string) error {
|
||||
return f.Filesystem.Unhide(name)
|
||||
}
|
||||
|
||||
func (f *caseFilesystem) underlying() (Filesystem, bool) {
|
||||
return f.Filesystem, true
|
||||
}
|
||||
|
||||
func (f *caseFilesystem) wrapperType() filesystemWrapperType {
|
||||
return filesystemWrapperTypeCase
|
||||
}
|
||||
|
||||
func (f *caseFilesystem) checkCase(name string) error {
|
||||
var err error
|
||||
if name, err = Canonicalize(name); err != nil {
|
||||
@@ -367,7 +376,10 @@ func (f *caseFilesystem) checkCaseExisting(name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if realName != name {
|
||||
// We normalize the normalization (hah!) of the strings before
|
||||
// comparing, as we don't want to treat a normalization difference as a
|
||||
// case conflict.
|
||||
if norm.NFC.String(realName) != norm.NFC.String(name) {
|
||||
return &ErrCaseConflict{name, realName}
|
||||
}
|
||||
return nil
|
||||
@@ -416,7 +428,7 @@ func (r *defaultRealCaser) realCase(name string) (string, error) {
|
||||
lastLower := ""
|
||||
for _, n := range dirNames {
|
||||
node.children[n] = struct{}{}
|
||||
lower := UnicodeLowercase(n)
|
||||
lower := UnicodeLowercaseNormalized(n)
|
||||
if lower != lastLower {
|
||||
node.lowerToReal[lower] = n
|
||||
lastLower = n
|
||||
@@ -429,7 +441,7 @@ func (r *defaultRealCaser) realCase(name string) (string, error) {
|
||||
|
||||
// Try to find a direct or case match
|
||||
if _, ok := node.children[comp]; !ok {
|
||||
comp, ok = node.lowerToReal[UnicodeLowercase(comp)]
|
||||
comp, ok = node.lowerToReal[UnicodeLowercaseNormalized(comp)]
|
||||
if !ok {
|
||||
return "", ErrNotExist
|
||||
}
|
||||
|
||||
+12
-3
@@ -161,7 +161,10 @@ func BenchmarkWalkCaseFakeFS100k(b *testing.B) {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.Run("rawfs", func(b *testing.B) {
|
||||
fakefs := unwrapFilesystem(fsys).(*fakefs)
|
||||
var fakefs *fakeFS
|
||||
if ffs, ok := unwrapFilesystem(fsys, filesystemWrapperTypeNone); ok {
|
||||
fakefs = ffs.(*fakeFS)
|
||||
}
|
||||
fakefs.resetCounters()
|
||||
benchmarkWalkFakeFS(b, fsys, paths, 0, "")
|
||||
fakefs.reportMetricsPerOp(b)
|
||||
@@ -174,7 +177,10 @@ func BenchmarkWalkCaseFakeFS100k(b *testing.B) {
|
||||
Filesystem: fsys,
|
||||
realCaser: newDefaultRealCaser(fsys),
|
||||
}
|
||||
fakefs := unwrapFilesystem(fsys).(*fakefs)
|
||||
var fakefs *fakeFS
|
||||
if ffs, ok := unwrapFilesystem(fsys, filesystemWrapperTypeNone); ok {
|
||||
fakefs = ffs.(*fakeFS)
|
||||
}
|
||||
fakefs.resetCounters()
|
||||
benchmarkWalkFakeFS(b, casefs, paths, 0, "")
|
||||
fakefs.reportMetricsPerOp(b)
|
||||
@@ -197,7 +203,10 @@ func BenchmarkWalkCaseFakeFS100k(b *testing.B) {
|
||||
Filesystem: fsys,
|
||||
realCaser: newDefaultRealCaser(fsys),
|
||||
}
|
||||
fakefs := unwrapFilesystem(fsys).(*fakefs)
|
||||
var fakefs *fakeFS
|
||||
if ffs, ok := unwrapFilesystem(fsys, filesystemWrapperTypeNone); ok {
|
||||
fakefs = ffs.(*fakeFS)
|
||||
}
|
||||
fakefs.resetCounters()
|
||||
benchmarkWalkFakeFS(b, casefs, paths, otherOpEvery, otherOpPath)
|
||||
fakefs.reportMetricsPerOp(b)
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
// reason for existence is the Windows version, which allows creating
|
||||
// symlinks when non-elevated.
|
||||
func DebugSymlinkForTestsOnly(oldFs, newFs Filesystem, oldname, newname string) error {
|
||||
if caseFs, ok := unwrapFilesystem(newFs).(*caseFilesystem); ok {
|
||||
if fs, ok := unwrapFilesystem(newFs, filesystemWrapperTypeCase); ok {
|
||||
caseFs := fs.(*caseFilesystem)
|
||||
if err := caseFs.checkCase(newname); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,3 +52,11 @@ func (fs *errorFilesystem) SameFile(fi1, fi2 FileInfo) bool { return false }
|
||||
func (fs *errorFilesystem) Watch(path string, ignore Matcher, ctx context.Context, ignorePerms bool) (<-chan Event, <-chan error, error) {
|
||||
return nil, nil, fs.err
|
||||
}
|
||||
|
||||
func (fs *errorFilesystem) underlying() (Filesystem, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (fs *errorFilesystem) wrapperType() filesystemWrapperType {
|
||||
return filesystemWrapperTypeError
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user