mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-04 03:49:12 -05:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97625ccc26 | ||
|
|
4fe746d9aa | ||
|
|
4f8cdd41ee | ||
|
|
406e3646e5 | ||
|
|
9d21b91124 | ||
|
|
b806026990 | ||
|
|
341b79814e | ||
|
|
319916124b | ||
|
|
b08b99e284 | ||
|
|
f565df628c | ||
|
|
855c6dc67b | ||
|
|
dc5e10fa2c | ||
|
|
b857e57a35 | ||
|
|
f42f041f53 | ||
|
|
6b6b2c6194 | ||
|
|
d70eb569f2 | ||
|
|
21c074cc2c | ||
|
|
f23c41221b | ||
|
|
24e230d455 | ||
|
|
31daa20367 | ||
|
|
e4d0f9dd6c | ||
|
|
df2ac7aaeb | ||
|
|
b96b23957b | ||
|
|
265ce139c5 | ||
|
|
48c95eb41d | ||
|
|
937895be69 | ||
|
|
a3886f778d | ||
|
|
6aecc2622c | ||
|
|
c55b205a0b | ||
|
|
2fcf7006e6 | ||
|
|
bf61e485a6 | ||
|
|
b2886f11b1 | ||
|
|
11ece5d89e | ||
|
|
cf68dfac43 | ||
|
|
c44de2cd58 | ||
|
|
6ff5ed6d23 | ||
|
|
25ec2b63ab | ||
|
|
c5ab71d7a5 | ||
|
|
1fc4c9d9c5 | ||
|
|
bebf2c259c | ||
|
|
b7d526903e | ||
|
|
92917c9f62 | ||
|
|
a7d7325e9b | ||
|
|
465823237f | ||
|
|
5a1f996e56 | ||
|
|
229b6a292c | ||
|
|
c84e47a7b2 | ||
|
|
daf7baaeff | ||
|
|
a4a1231e92 | ||
|
|
b99dee3ac3 |
54
.github/workflows/build-infra-dockers.yaml
vendored
Normal file
54
.github/workflows/build-infra-dockers.yaml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Build Infrastructure Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- infrastructure
|
||||
|
||||
env:
|
||||
GO_VERSION: "^1.20.5"
|
||||
CGO_ENABLED: "0"
|
||||
BUILD_USER: docker
|
||||
BUILD_HOST: github.syncthing.net
|
||||
|
||||
jobs:
|
||||
|
||||
docker-syncthing:
|
||||
name: Build and push Docker images
|
||||
runs-on: ubuntu-latest
|
||||
environment: docker
|
||||
strategy:
|
||||
matrix:
|
||||
pkg:
|
||||
- stcrashreceiver
|
||||
- strelaypoolsrv
|
||||
- stupgrades
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build binaries
|
||||
run: |
|
||||
for arch in arm64 amd64; do
|
||||
go run build.go -goos linux -goarch "$arch" build ${{ matrix.pkg }}
|
||||
mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-"$arch"
|
||||
done
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.${{ matrix.pkg }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: syncthing/${{ matrix.pkg }}:latest,syncthing/${{ matrix.pkg }}:${{ github.sha }}
|
||||
80
.github/workflows/build-syncthing.yaml
vendored
80
.github/workflows/build-syncthing.yaml
vendored
@@ -3,6 +3,9 @@ name: Build Syncthing
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
schedule:
|
||||
# Run nightly build at 05:00 UTC
|
||||
- cron: '00 05 * * *'
|
||||
|
||||
env:
|
||||
# The go version to use for builds. We set check-latest to true when
|
||||
@@ -69,9 +72,19 @@ jobs:
|
||||
run: |
|
||||
go run build.go
|
||||
|
||||
- name: Install go-test-json-to-loki
|
||||
run: |
|
||||
go install calmh.dev/go-test-json-to-loki@latest
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
go run build.go test
|
||||
go run build.go test | go-test-json-to-loki
|
||||
env:
|
||||
GOFLAGS: "-json"
|
||||
LOKI_URL: ${{ secrets.LOKI_URL }}
|
||||
LOKI_USER: ${{ secrets.LOKI_USER }}
|
||||
LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }}
|
||||
LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}"
|
||||
|
||||
#
|
||||
# Meta checks for formatting, copyright, etc
|
||||
@@ -112,6 +125,7 @@ jobs:
|
||||
- package-cross
|
||||
- package-source
|
||||
- package-debian
|
||||
- govulncheck
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -602,7 +616,7 @@ jobs:
|
||||
|
||||
publish-release-files:
|
||||
name: Publish release files
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release')
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/release'
|
||||
environment: signing
|
||||
needs:
|
||||
- sign-for-upgrade
|
||||
@@ -630,7 +644,7 @@ jobs:
|
||||
version=$(go run build.go version)
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
|
||||
- name: Push to Spaces
|
||||
- name: Push to Spaces (${{ env.VERSION }})
|
||||
uses: docker://docker.io/rclone/rclone:latest
|
||||
env:
|
||||
RCLONE_CONFIG_SPACES_TYPE: s3
|
||||
@@ -642,6 +656,22 @@ jobs:
|
||||
with:
|
||||
args: sync packages spaces:syncthing/release/${{ env.VERSION }}
|
||||
|
||||
- name: Push to Spaces (latest)
|
||||
uses: docker://docker.io/rclone/rclone:latest
|
||||
env:
|
||||
RCLONE_CONFIG_SPACES_TYPE: s3
|
||||
RCLONE_CONFIG_SPACES_PROVIDER: DigitalOcean
|
||||
RCLONE_CONFIG_SPACES_ACCESS_KEY_ID: ${{ secrets.SPACES_KEY }}
|
||||
RCLONE_CONFIG_SPACES_SECRET_ACCESS_KEY: ${{ secrets.SPACES_SECRET }}
|
||||
RCLONE_CONFIG_SPACES_ENDPOINT: ams3.digitaloceanspaces.com
|
||||
RCLONE_CONFIG_SPACES_ACL: public-read
|
||||
with:
|
||||
args: sync spaces:syncthing/release/${{ env.VERSION }} spaces:syncthing/release/latest
|
||||
|
||||
#
|
||||
# Build and push to Docker Hub
|
||||
#
|
||||
|
||||
docker-syncthing:
|
||||
name: Build and push Docker images
|
||||
runs-on: ubuntu-latest
|
||||
@@ -656,10 +686,13 @@ jobs:
|
||||
include:
|
||||
- pkg: syncthing
|
||||
dockerfile: Dockerfile
|
||||
image: syncthing/syncthing
|
||||
- pkg: strelaysrv
|
||||
dockerfile: Dockerfile.strelaysrv
|
||||
image: syncthing/relaysrv
|
||||
- pkg: stdiscosrv
|
||||
dockerfile: Dockerfile.stdiscosrv
|
||||
image: syncthing/discosrv
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -680,7 +713,7 @@ jobs:
|
||||
|
||||
- name: Build binaries
|
||||
run: |
|
||||
for arch in arm64 amd64; do
|
||||
for arch in amd64 arm64 arm; do
|
||||
go run build.go -goos linux -goarch "$arch" -no-upgrade build ${{ matrix.pkg }}
|
||||
mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-"$arch"
|
||||
done
|
||||
@@ -688,8 +721,15 @@ jobs:
|
||||
CGO_ENABLED: "0"
|
||||
BUILD_USER: docker
|
||||
|
||||
- name: Check if we will be able to push images
|
||||
run: |
|
||||
if [[ "${{ secrets.DOCKERHUB_TOKEN }}" != "" ]]; then
|
||||
echo "DOCKER_PUSH=true" >> $GITHUB_ENV;
|
||||
fi
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
if: env.DOCKER_PUSH == 'true'
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -705,13 +745,13 @@ jobs:
|
||||
echo Release version, pushing to :latest and version tags
|
||||
major=${version%.*.*}
|
||||
minor=${version%.*}
|
||||
tags=syncthing/${{ matrix.pkg }}:$version,syncthing/${{ matrix.pkg }}:$major,syncthing/${{ matrix.pkg }}:$minor,syncthing/${{ matrix.pkg }}:latest
|
||||
tags=${{ matrix.image }}:$version,${{ matrix.image }}:$major,${{ matrix.image }}:$minor,${{ matrix.image }}:latest
|
||||
elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then
|
||||
echo Release candidate, pushing to :rc
|
||||
tags=syncthing/${{ matrix.pkg }}:rc
|
||||
tags=${{ matrix.image }}:rc
|
||||
else
|
||||
echo Development version, pushing to :edge
|
||||
tags=syncthing/${{ matrix.pkg }}:edge
|
||||
tags=${{ matrix.image }}:edge
|
||||
fi
|
||||
echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV
|
||||
|
||||
@@ -720,6 +760,28 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/7
|
||||
push: ${{ env.DOCKER_PUSH == 'true' }}
|
||||
tags: ${{ env.DOCKER_TAGS }}
|
||||
|
||||
#
|
||||
# Check for known vulnerabilities in Go dependencies
|
||||
#
|
||||
|
||||
govulncheck:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run govulncheck
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
check-latest: true
|
||||
|
||||
- name: run govulncheck
|
||||
run: |
|
||||
go run build.go assets
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
govulncheck ./...
|
||||
|
||||
5
AUTHORS
5
AUTHORS
@@ -71,11 +71,12 @@ Carsten Hagemann (carstenhag) <moter8@gmail.com> <carsten@chagemann.de>
|
||||
Cathryne Linenweaver (Cathryne) <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com> <katrinleinweber@MAC.local>
|
||||
Cedric Staniewski (xduugu) <cedric@gmx.ca>
|
||||
chenrui <rui@meetup.com>
|
||||
Chih-Hsuan Yen <yan12125@gmail.com>
|
||||
Chih-Hsuan Yen <yan12125@gmail.com> <1937689+yan12125@users.noreply.github.com>
|
||||
Choongkyu <choongkyu.kim+gh@gmail.com> <vapidlyrapid+gh@gmail.com>
|
||||
Chris Howie (cdhowie) <me@chrishowie.com>
|
||||
Chris Joel (cdata) <chris@scriptolo.gy>
|
||||
Chris Tonkinson <chris@masterbran.ch>
|
||||
Christian Kujau <ckujau@users.noreply.github.com>
|
||||
Christian Prescott <me@christianprescott.com>
|
||||
chucic <chucic@seznam.cz>
|
||||
Colin Kennedy (moshen) <moshen.colin@gmail.com>
|
||||
@@ -105,6 +106,7 @@ Dominik Heidler (asdil12) <dominik@heidler.eu>
|
||||
Elias Jarlebring (jarlebring) <jarlebring@gmail.com>
|
||||
Elliot Huffman <thelich2@gmail.com>
|
||||
Emil Hessman (ceh) <emil@hessman.se>
|
||||
Emil Lundberg <emil@emlun.se>
|
||||
Eng Zer Jun <engzerjun@gmail.com>
|
||||
entity0xfe <109791748+entity0xfe@users.noreply.github.com> <entity0xfe@my.domain>
|
||||
Eric Lesiuta <elesiuta@gmail.com>
|
||||
@@ -220,6 +222,7 @@ Michael Ploujnikov (plouj) <ploujj@gmail.com>
|
||||
Michael Rienstra <mrienstra@gmail.com>
|
||||
Michael Tilli (pyfisch) <pyfisch@gmail.com>
|
||||
MichaIng <micha@dietpi.com>
|
||||
Migelo <miha@filetki.si>
|
||||
Mike Boone <mike@boonedocks.net>
|
||||
MikeLund <MikeLund@users.noreply.github.com>
|
||||
MikolajTwarog <43782609+MikolajTwarog@users.noreply.github.com>
|
||||
|
||||
@@ -44,5 +44,6 @@ HEALTHCHECK --interval=1m --timeout=10s \
|
||||
CMD curl -fkLsS -m 2 127.0.0.1:8384/rest/noauth/health | grep -o --color=never OK || exit 1
|
||||
|
||||
ENV STGUIADDRESS=0.0.0.0:8384
|
||||
ENV STHOMEDIR=/var/syncthing/config
|
||||
RUN chmod 755 /bin/entrypoint.sh
|
||||
ENTRYPOINT ["/bin/entrypoint.sh", "/bin/syncthing", "-home", "/var/syncthing/config"]
|
||||
ENTRYPOINT ["/bin/entrypoint.sh", "/bin/syncthing"]
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
ENV BUILD_HOST=syncthing.net
|
||||
ENV BUILD_USER=docker
|
||||
RUN rm -f stcrashreceiver && go run build.go build stcrashreceiver
|
||||
|
||||
FROM alpine
|
||||
ARG TARGETARCH
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
COPY --from=builder /src/stcrashreceiver /bin/stcrashreceiver
|
||||
COPY stcrashreceiver-linux-${TARGETARCH} /bin/stcrashreceiver
|
||||
|
||||
ENTRYPOINT [ "/bin/stcrashreceiver" ]
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
ENV BUILD_HOST=syncthing.net
|
||||
ENV BUILD_USER=docker
|
||||
RUN rm -f strelaysrv && go run build.go -no-upgrade build strelaypoolsrv
|
||||
|
||||
FROM alpine
|
||||
ARG TARGETARCH
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
@@ -19,8 +9,8 @@ ENV PUID=1000 PGID=1000 MAXMIND_KEY=
|
||||
RUN mkdir /var/strelaypoolsrv && chown 1000 /var/strelaypoolsrv
|
||||
USER 1000
|
||||
|
||||
COPY --from=builder /src/strelaypoolsrv /bin/strelaypoolsrv
|
||||
COPY --from=builder /src/script/strelaypoolsrv-entrypoint.sh /bin/entrypoint.sh
|
||||
COPY strelaypoolsrv-linux-${TARGETARCH} /bin/strelaypoolsrv
|
||||
COPY script/strelaypoolsrv-entrypoint.sh /bin/entrypoint.sh
|
||||
|
||||
WORKDIR /var/strelaypoolsrv
|
||||
ENTRYPOINT ["/bin/entrypoint.sh", "/bin/strelaypoolsrv", "-listen", ":8080"]
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
ENV BUILD_HOST=syncthing.net
|
||||
ENV BUILD_USER=docker
|
||||
RUN rm -f stupgrades && go run build.go build stupgrades
|
||||
|
||||
FROM alpine
|
||||
ARG TARGETARCH
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
COPY --from=builder /src/stupgrades /bin/stupgrades
|
||||
COPY stupgrades-linux-${TARGETARCH} /bin/stupgrades
|
||||
|
||||
ENTRYPOINT [ "/bin/stupgrades" ]
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://build.syncthing.net/viewType.html?buildTypeId=Syncthing_BuildLinuxCross&guest=1)
|
||||
[](https://build.syncthing.net/viewType.html?buildTypeId=Syncthing_BuildWindows&guest=1)
|
||||
[](https://build.syncthing.net/viewType.html?buildTypeId=Syncthing_BuildMac&guest=1)
|
||||
[](https://www.mozilla.org/MPL/2.0/)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/88)
|
||||
[](https://goreportcard.com/report/github.com/syncthing/syncthing)
|
||||
|
||||
8
build.go
8
build.go
@@ -214,11 +214,17 @@ var targets = map[string]target{
|
||||
binaryName: "stupgrades",
|
||||
},
|
||||
"stcrashreceiver": {
|
||||
name: "stupgrastcrashreceiverdes",
|
||||
name: "stcrashreceiver",
|
||||
description: "Syncthing Crash Server",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/stcrashreceiver"},
|
||||
binaryName: "stcrashreceiver",
|
||||
},
|
||||
"ursrv": {
|
||||
name: "ursrv",
|
||||
description: "Syncthing Usage Reporting Server",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/ursrv"},
|
||||
binaryName: "ursrv",
|
||||
},
|
||||
}
|
||||
|
||||
func initTargets() {
|
||||
|
||||
@@ -69,6 +69,9 @@ func main() {
|
||||
}
|
||||
|
||||
mux.Handle("/", cr)
|
||||
mux.HandleFunc("/ping", func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte("OK"))
|
||||
})
|
||||
|
||||
if params.DSN != "" {
|
||||
mux.HandleFunc("/newcrash/failure", handleFailureFn(params.DSN, filepath.Join(params.Dir, "failure_reports")))
|
||||
|
||||
@@ -215,7 +215,13 @@ func crashReportFingerprint(message string) []string {
|
||||
}
|
||||
|
||||
// syncthing v1.1.4-rc.1+30-g6aaae618-dirty-crashrep "Erbium Earthworm" (go1.12.5 darwin-amd64) jb@kvin.kastelo.net 2019-05-23 16:08:14 UTC [foo, bar]
|
||||
var longVersionRE = regexp.MustCompile(`syncthing\s+(v[^\s]+)\s+"([^"]+)"\s\(([^\s]+)\s+([^-]+)-([^)]+)\)\s+([^\s]+)[^\[]*(?:\[(.+)\])?$`)
|
||||
// or, somewhere along the way the "+" in the version tag disappeared:
|
||||
// syncthing v1.23.7-dev.26.gdf7b56ae.dirty-stversionextra "Fermium Flea" (go1.20.5 darwin-arm64) jb@ok.kastelo.net 2023-07-12 06:55:26 UTC [Some Wrapper, purego, stnoupgrade]
|
||||
var (
|
||||
longVersionRE = regexp.MustCompile(`syncthing\s+(v[^\s]+)\s+"([^"]+)"\s\(([^\s]+)\s+([^-]+)-([^)]+)\)\s+([^\s]+)[^\[]*(?:\[(.+)\])?$`)
|
||||
gitExtraRE = regexp.MustCompile(`\.\d+\.g[0-9a-f]+`) // ".1.g6aaae618"
|
||||
gitExtraSepRE = regexp.MustCompile(`[.-]`) // dot or dash
|
||||
)
|
||||
|
||||
type version struct {
|
||||
version string // "v1.1.4-rc.1+30-g6aaae618-dirty-crashrep"
|
||||
@@ -257,10 +263,21 @@ func parseVersion(line string) (version, error) {
|
||||
builder: m[6],
|
||||
}
|
||||
|
||||
parts := strings.Split(v.version, "+")
|
||||
// Split the version tag into tag and commit. This is old style
|
||||
// v1.2.3-something.4+11-g12345678 or newer with just dots
|
||||
// v1.2.3-something.4.11.g12345678 or v1.2.3-dev.11.g12345678.
|
||||
parts := []string{v.version}
|
||||
if strings.Contains(v.version, "+") {
|
||||
parts = strings.Split(v.version, "+")
|
||||
} else {
|
||||
idxs := gitExtraRE.FindStringIndex(v.version)
|
||||
if len(idxs) > 0 {
|
||||
parts = []string{v.version[:idxs[0]], v.version[idxs[0]+1:]}
|
||||
}
|
||||
}
|
||||
v.tag = parts[0]
|
||||
if len(parts) > 1 {
|
||||
fields := strings.Split(parts[1], "-")
|
||||
fields := gitExtraSepRE.Split(parts[1], -1)
|
||||
if len(fields) >= 2 && strings.HasPrefix(fields[1], "g") {
|
||||
v.commit = fields[1][1:]
|
||||
}
|
||||
|
||||
@@ -44,6 +44,20 @@ func TestParseVersion(t *testing.T) {
|
||||
extra: []string{"foo", "bar"},
|
||||
},
|
||||
},
|
||||
{
|
||||
longVersion: `syncthing v1.23.7-dev.26.gdf7b56ae-stversionextra "Fermium Flea" (go1.20.5 darwin-arm64) jb@ok.kastelo.net 2023-07-12 06:55:26 UTC [Some Wrapper, purego, stnoupgrade]`,
|
||||
parsed: version{
|
||||
version: "v1.23.7-dev.26.gdf7b56ae-stversionextra",
|
||||
tag: "v1.23.7-dev",
|
||||
commit: "df7b56ae",
|
||||
codename: "Fermium Flea",
|
||||
runtime: "go1.20.5",
|
||||
goos: "darwin",
|
||||
goarch: "arm64",
|
||||
builder: "jb@ok.kastelo.net",
|
||||
extra: []string{"Some Wrapper", "purego", "stnoupgrade"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
uptimeSeconds: 0,
|
||||
};
|
||||
$scope.map = L.map('map').setView([40.90296, 1.90925], 2);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
{
|
||||
attribution: 'Leaflet',
|
||||
maxZoom: 17
|
||||
|
||||
@@ -36,8 +36,14 @@ func listener(_, addr string, config *tls.Config, token string) {
|
||||
for {
|
||||
conn, isTLS, err := listener.AcceptNoWrapTLS()
|
||||
if err != nil {
|
||||
// Conn may be nil if accept failed, or non-nil if the initial
|
||||
// read to figure out if it's TLS or not failed. In the latter
|
||||
// case, close the connection before moving on.
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
if debug {
|
||||
log.Println("Listener failed to accept connection from", conn.RemoteAddr(), ". Possibly a TCP Ping.")
|
||||
log.Println("Listener failed to accept:", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ type githubReleases struct {
|
||||
url string
|
||||
}
|
||||
|
||||
func (p *githubReleases) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
func (p *githubReleases) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
|
||||
log.Println("Fetching", p.url)
|
||||
rels := upgrade.FetchLatestReleases(p.url, "")
|
||||
if rels == nil {
|
||||
|
||||
@@ -9,8 +9,8 @@ package cmdutil
|
||||
// CommonOptions are reused among several subcommands
|
||||
type CommonOptions struct {
|
||||
buildCommonOptions
|
||||
ConfDir string `name:"config" placeholder:"PATH" help:"Set configuration directory (config and keys)"`
|
||||
HomeDir string `name:"home" placeholder:"PATH" help:"Set configuration and data directory"`
|
||||
ConfDir string `name:"config" placeholder:"PATH" env:"STCONFDIR" help:"Set configuration directory (config and keys)"`
|
||||
HomeDir string `name:"home" placeholder:"PATH" env:"STHOMEDIR" help:"Set configuration and data directory"`
|
||||
NoDefaultFolder bool `env:"STNODEFAULTFOLDER" help:"Don't create the \"default\" folder on first startup"`
|
||||
SkipPortProbing bool `help:"Don't try to find free ports for GUI and listen addresses on first startup"`
|
||||
}
|
||||
|
||||
@@ -99,6 +99,11 @@ above.
|
||||
"minio" for the github.com/minio/sha256-simd implementation,
|
||||
and blank (the default) for auto detection.
|
||||
|
||||
STVERSIONEXTRA Add extra information to the version string in logs and the
|
||||
version line in the GUI. Can be set to the name of a wrapper
|
||||
or tool controlling syncthing to communicate this to the end
|
||||
user.
|
||||
|
||||
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
|
||||
available CPU cores.
|
||||
|
||||
@@ -144,9 +149,9 @@ type serveOptions struct {
|
||||
Audit bool `help:"Write events to audit file"`
|
||||
AuditFile string `name:"auditfile" placeholder:"PATH" help:"Specify audit file (use \"-\" for stdout, \"--\" for stderr)"`
|
||||
BrowserOnly bool `help:"Open GUI in browser"`
|
||||
DataDir string `name:"data" placeholder:"PATH" help:"Set data directory (database and logs)"`
|
||||
DataDir string `name:"data" placeholder:"PATH" env:"STDATADIR" help:"Set data directory (database and logs)"`
|
||||
DeviceID bool `help:"Show the device ID"`
|
||||
GenerateDir string `name:"generate" placeholder:"PATH" help:"Generate key and config in specified dir, then exit"` //DEPRECATED: replaced by subcommand!
|
||||
GenerateDir string `name:"generate" placeholder:"PATH" help:"Generate key and config in specified dir, then exit"` // DEPRECATED: replaced by subcommand!
|
||||
GUIAddress string `name:"gui-address" placeholder:"URL" help:"Override GUI address (e.g. \"http://192.0.2.42:8443\")"`
|
||||
GUIAPIKey string `name:"gui-apikey" placeholder:"API-KEY" help:"Override GUI API key"`
|
||||
LogFile string `name:"logfile" default:"${logFile}" placeholder:"PATH" help:"Log file name (see below)"`
|
||||
@@ -354,7 +359,7 @@ func (options serveOptions) Run() error {
|
||||
}
|
||||
|
||||
// Ensure that our home directory exists.
|
||||
if err := syncthing.EnsureDir(locations.GetBaseDir(locations.ConfigBaseDir), 0700); err != nil {
|
||||
if err := syncthing.EnsureDir(locations.GetBaseDir(locations.ConfigBaseDir), 0o700); err != nil {
|
||||
l.Warnln("Failure on home directory:", err)
|
||||
os.Exit(svcutil.ExitError.AsInt())
|
||||
}
|
||||
@@ -722,7 +727,6 @@ func setupSignalHandling(app *syncthing.App) {
|
||||
func loadOrDefaultConfig() (config.Wrapper, error) {
|
||||
cfgFile := locations.Get(locations.ConfigFile)
|
||||
cfg, _, err := config.Load(cfgFile, protocol.EmptyDeviceID, events.NoopLogger)
|
||||
|
||||
if err != nil {
|
||||
newCfg := config.New(protocol.EmptyDeviceID)
|
||||
return config.Wrap(cfgFile, newCfg, protocol.EmptyDeviceID, events.NoopLogger), nil
|
||||
@@ -750,7 +754,7 @@ func auditWriter(auditFile string) io.Writer {
|
||||
} else {
|
||||
auditFlags = os.O_WRONLY | os.O_CREATE | os.O_APPEND
|
||||
}
|
||||
fd, err = os.OpenFile(auditFile, auditFlags, 0600)
|
||||
fd, err = os.OpenFile(auditFile, auditFlags, 0o600)
|
||||
if err != nil {
|
||||
l.Warnln("Audit:", err)
|
||||
os.Exit(svcutil.ExitError.AsInt())
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
// 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 main
|
||||
package aggregate
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
@@ -15,26 +16,21 @@ import (
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var dbConn = getEnvDefault("UR_DB_URL", "postgres://user:password@localhost/ur?sslmode=disable")
|
||||
|
||||
func getEnvDefault(key, def string) string {
|
||||
if val := os.Getenv(key); val != "" {
|
||||
return val
|
||||
}
|
||||
return def
|
||||
type CLI struct {
|
||||
DBConn string `env:"UR_DB_URL" default:"postgres://user:password@localhost/ur?sslmode=disable"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
func (cli *CLI) Run() error {
|
||||
log.SetFlags(log.Ltime | log.Ldate)
|
||||
log.SetOutput(os.Stdout)
|
||||
|
||||
db, err := sql.Open("postgres", dbConn)
|
||||
db, err := sql.Open("postgres", cli.DBConn)
|
||||
if err != nil {
|
||||
log.Fatalln("database:", err)
|
||||
return fmt.Errorf("database: %w", err)
|
||||
}
|
||||
err = setupDB(db)
|
||||
if err != nil {
|
||||
log.Fatalln("database:", err)
|
||||
return fmt.Errorf("database: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -87,16 +83,6 @@ func setupDB(db *sql.DB) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS UserMovement (
|
||||
Day TIMESTAMP NOT NULL,
|
||||
Added INTEGER NOT NULL,
|
||||
Bounced INTEGER NOT NULL,
|
||||
Removed INTEGER NOT NULL
|
||||
)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS Performance (
|
||||
Day TIMESTAMP NOT NULL,
|
||||
TotFiles INTEGER NOT NULL,
|
||||
@@ -136,11 +122,6 @@ func setupDB(db *sql.DB) error {
|
||||
_, _ = db.Exec(`CREATE INDEX VersionDayIndex ON VersionSummary (Day)`)
|
||||
}
|
||||
|
||||
row = db.QueryRow(`SELECT 'MovementDayIndex'::regclass`)
|
||||
if err := row.Scan(&t); err != nil {
|
||||
_, _ = db.Exec(`CREATE INDEX MovementDayIndex ON UserMovement (Day)`)
|
||||
}
|
||||
|
||||
row = db.QueryRow(`SELECT 'PerformanceDayIndex'::regclass`)
|
||||
if err := row.Scan(&t); err != nil {
|
||||
_, _ = db.Exec(`CREATE INDEX PerformanceDayIndex ON Performance (Day)`)
|
||||
@@ -185,87 +166,6 @@ func aggregateVersionSummary(db *sql.DB, since time.Time) (int64, error) {
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
func aggregateUserMovement(db *sql.DB) (int64, error) {
|
||||
rows, err := db.Query(`SELECT
|
||||
DATE_TRUNC('day', Received) AS Day,
|
||||
Report->>'uniqueID'
|
||||
FROM ReportsJson
|
||||
WHERE
|
||||
Report->>'uniqueID' IS NOT NULL
|
||||
AND Received < DATE_TRUNC('day', NOW())
|
||||
AND Report->>'version' like 'v_.%'
|
||||
ORDER BY Day
|
||||
`)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
firstSeen := make(map[string]time.Time)
|
||||
lastSeen := make(map[string]time.Time)
|
||||
var minTs time.Time
|
||||
minTs = minTs.In(time.UTC)
|
||||
|
||||
for rows.Next() {
|
||||
var ts time.Time
|
||||
var id string
|
||||
if err := rows.Scan(&ts, &id); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if minTs.IsZero() {
|
||||
minTs = ts
|
||||
}
|
||||
if _, ok := firstSeen[id]; !ok {
|
||||
firstSeen[id] = ts
|
||||
}
|
||||
lastSeen[id] = ts
|
||||
}
|
||||
|
||||
type sumRow struct {
|
||||
day time.Time
|
||||
added int
|
||||
removed int
|
||||
bounced int
|
||||
}
|
||||
var sumRows []sumRow
|
||||
for t := minTs; t.Before(time.Now().Truncate(24 * time.Hour)); t = t.AddDate(0, 0, 1) {
|
||||
var added, removed, bounced int
|
||||
old := t.Before(time.Now().AddDate(0, 0, -30))
|
||||
for id, first := range firstSeen {
|
||||
last := lastSeen[id]
|
||||
if first.Equal(t) && last.Equal(t) && old {
|
||||
bounced++
|
||||
continue
|
||||
}
|
||||
if first.Equal(t) {
|
||||
added++
|
||||
}
|
||||
if last == t && old {
|
||||
removed++
|
||||
}
|
||||
}
|
||||
sumRows = append(sumRows, sumRow{t, added, removed, bounced})
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, err := tx.Exec("DELETE FROM UserMovement"); err != nil {
|
||||
tx.Rollback()
|
||||
return 0, err
|
||||
}
|
||||
for _, r := range sumRows {
|
||||
if _, err := tx.Exec("INSERT INTO UserMovement (Day, Added, Removed, Bounced) VALUES ($1, $2, $3, $4)", r.day, r.added, r.removed, r.bounced); err != nil {
|
||||
tx.Rollback()
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return int64(len(sumRows)), tx.Commit()
|
||||
}
|
||||
|
||||
func aggregatePerformance(db *sql.DB, since time.Time) (int64, error) {
|
||||
res, err := db.Exec(`INSERT INTO Performance (
|
||||
SELECT
|
||||
1169
cmd/ursrv/main.go
1169
cmd/ursrv/main.go
File diff suppressed because it is too large
Load Diff
@@ -4,7 +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/.
|
||||
|
||||
package main
|
||||
package serve
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
@@ -145,7 +145,7 @@ func statsForFloats(data []float64) [4]float64 {
|
||||
return res
|
||||
}
|
||||
|
||||
func group(by func(string) string, as []analytic, perGroup int) []analytic {
|
||||
func group(by func(string) string, as []analytic, perGroup int, otherPct float64) []analytic {
|
||||
var res []analytic
|
||||
|
||||
next:
|
||||
@@ -170,6 +170,25 @@ next:
|
||||
}
|
||||
|
||||
sort.Sort(analyticList(res))
|
||||
|
||||
if otherPct > 0 {
|
||||
// Groups with less than otherPCt go into "Other"
|
||||
other := analytic{
|
||||
Key: "Other",
|
||||
}
|
||||
for i := 0; i < len(res); i++ {
|
||||
if res[i].Percentage < otherPct || res[i].Key == "Other" {
|
||||
other.Count += res[i].Count
|
||||
other.Percentage += res[i].Percentage
|
||||
res = append(res[:i], res[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
if other.Count > 0 {
|
||||
res = append(res, other)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -4,7 +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/.
|
||||
|
||||
package main
|
||||
package serve
|
||||
|
||||
import "testing"
|
||||
|
||||
@@ -4,7 +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/.
|
||||
|
||||
package main
|
||||
package serve
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
1114
cmd/ursrv/serve/serve.go
Normal file
1114
cmd/ursrv/serve/serve.go
Normal file
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
@@ -197,7 +197,7 @@ found in the LICENSE file.
|
||||
};
|
||||
|
||||
var baseLayer = L.tileLayer(
|
||||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',{
|
||||
attribution: '...',
|
||||
maxZoom: 18
|
||||
}
|
||||
@@ -454,13 +454,13 @@ found in the LICENSE file.
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Builder</th>
|
||||
<th>Distribution Channel</th>
|
||||
<th class="text-right">Devices</th>
|
||||
<th class="text-right">Share</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .builders}}
|
||||
{{range .distributions}}
|
||||
<tr>
|
||||
<td>{{.Key}}</td>
|
||||
<td class="text-right">{{.Count}}</td>
|
||||
@@ -475,13 +475,13 @@ found in the LICENSE file.
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Distribution Channel</th>
|
||||
<th>Builder</th>
|
||||
<th class="text-right">Devices</th>
|
||||
<th class="text-right">Share</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .distributions}}
|
||||
{{range .builders}}
|
||||
<tr>
|
||||
<td>{{.Key}}</td>
|
||||
<td class="text-right">{{.Count}}</td>
|
||||
@@ -1,3 +1,4 @@
|
||||
# Increase maximum receive socket buffer size to 2MiB for QUIC connections
|
||||
# see https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size
|
||||
net.core.rmem_max = 2097152
|
||||
# Increase maximum socket buffer sizes to 2.5MiB for QUIC connections
|
||||
# see https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes
|
||||
net.core.rmem_max = 2621440
|
||||
net.core.wmem_max = 2621440
|
||||
|
||||
36
go.mod
36
go.mod
@@ -5,7 +5,7 @@ go 1.19
|
||||
require (
|
||||
github.com/AudriusButkevicius/pfilter v0.0.11
|
||||
github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f
|
||||
github.com/alecthomas/kong v0.7.1
|
||||
github.com/alecthomas/kong v0.8.0
|
||||
github.com/calmh/incontainer v0.0.0-20221224152218-b3e71b103d7a
|
||||
github.com/calmh/xdr v1.1.0
|
||||
github.com/ccding/go-stun v0.1.4
|
||||
@@ -22,7 +22,7 @@ require (
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/greatroar/blobloom v0.7.2
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.4
|
||||
github.com/jackpal/gateway v1.0.10
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
@@ -33,29 +33,29 @@ require (
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0
|
||||
github.com/minio/sha256-simd v1.0.1
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
|
||||
github.com/oschwald/geoip2-golang v1.8.0
|
||||
github.com/pierrec/lz4/v4 v4.1.17
|
||||
github.com/oschwald/geoip2-golang v1.9.0
|
||||
github.com/pierrec/lz4/v4 v4.1.18
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.15.1
|
||||
github.com/prometheus/client_golang v1.16.0
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/prometheus/procfs v0.11.0 // indirect
|
||||
github.com/quic-go/quic-go v0.34.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/sasha-s/go-deadlock v0.3.1
|
||||
github.com/shirou/gopsutil/v3 v3.23.5
|
||||
github.com/shirou/gopsutil/v3 v3.23.6
|
||||
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
|
||||
github.com/thejerf/suture/v4 v4.0.2
|
||||
github.com/urfave/cli v1.22.14
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
golang.org/x/crypto v0.10.0
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.11.0
|
||||
golang.org/x/sys v0.9.0
|
||||
golang.org/x/text v0.10.0
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.12.0
|
||||
golang.org/x/sys v0.10.0
|
||||
golang.org/x/text v0.11.0
|
||||
golang.org/x/time v0.3.0
|
||||
golang.org/x/tools v0.9.3
|
||||
google.golang.org/protobuf v1.30.0
|
||||
golang.org/x/tools v0.11.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -65,10 +65,10 @@ require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
|
||||
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.10.0 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.11.0 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20230518223814-80aa455d8761 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
@@ -76,7 +76,7 @@ require (
|
||||
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 // indirect
|
||||
)
|
||||
|
||||
// https://github.com/gobwas/glob/pull/55
|
||||
|
||||
77
go.sum
77
go.sum
@@ -6,8 +6,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
|
||||
github.com/alecthomas/kong v0.7.1 h1:azoTh0IOfwlAX3qN9sHWTxACE2oV8Bg2gAwBsMwDQY4=
|
||||
github.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
|
||||
github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s=
|
||||
github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
|
||||
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
@@ -81,12 +81,12 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs=
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
|
||||
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA=
|
||||
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
|
||||
github.com/greatroar/blobloom v0.7.2 h1:F30MGLHOcb4zr0pwCPTcKdlTM70rEgkf+LzdUPc5ss8=
|
||||
github.com/greatroar/blobloom v0.7.2/go.mod h1:mjMJ1hh1wjGVfr93QIHJ6FfDNVrA0IELv8OvMHJxHKs=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.4 h1:7GHuZcgid37q8o5i3QI9KMT4nCWQQ3Kx3Ov6bb9MfK0=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.4/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -127,22 +127,22 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
|
||||
github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
|
||||
github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6SLNcKTs=
|
||||
github.com/oschwald/geoip2-golang v1.8.0/go.mod h1:R7bRvYjOeaoenAp9sKRS8GX5bJWcZ0laWO5+DauEktw=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
||||
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
|
||||
github.com/oschwald/geoip2-golang v1.9.0 h1:uvD3O6fXAXs+usU+UGExshpdP13GAqp4GBrzN7IgKZc=
|
||||
github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOMi2zSFXizL3K81Y=
|
||||
github.com/oschwald/maxminddb-golang v1.11.0 h1:aSXMqYR/EPNjGE8epgqwDay+P30hCBZIveY0WZbAWh0=
|
||||
github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfglAFj3PuCmui13+P9zDg=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/petermattis/goid v0.0.0-20230518223814-80aa455d8761 h1:W04oB3d0J01W5jgYRGKsV8LCM6g9EkCvPkZcmFuy0OE=
|
||||
github.com/petermattis/goid v0.0.0-20230518223814-80aa455d8761/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
|
||||
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -151,14 +151,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
|
||||
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
|
||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
||||
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
|
||||
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk=
|
||||
github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
|
||||
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
|
||||
@@ -172,8 +172,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
|
||||
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
|
||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||
github.com/shirou/gopsutil/v3 v3.23.5 h1:5SgDCeQ0KW0S4N0znjeM/eFHXXOKyv2dVNgRq/c9P6Y=
|
||||
github.com/shirou/gopsutil/v3 v3.23.5/go.mod h1:Ng3Maa27Q2KARVJ0SPZF5NdrQSC3XHKP8IIWrHgMeLY=
|
||||
github.com/shirou/gopsutil/v3 v3.23.6 h1:5y46WPI9QBKBbK7EEccUPNXpJpNrvPuTD0O2zHEHT08=
|
||||
github.com/shirou/gopsutil/v3 v3.23.6/go.mod h1:j7QX50DrXYggrpN30W0Mo+I4/8U2UUIQrnrhqUeWrAU=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -184,7 +184,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2 h1:F4snRP//nIuTTW9LYEzVH4HVwDG9T3M4t8y/2nqMbiY=
|
||||
@@ -211,17 +210,17 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/exp v0.0.0-20230711023510-fffb14384f22 h1:FqrVOBQxQ8r/UwwXibI0KMolVhvFiGobSfdE33deHJM=
|
||||
golang.org/x/exp v0.0.0-20230711023510-fffb14384f22/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -236,8 +235,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -246,7 +245,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -275,9 +274,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -288,8 +287,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -300,8 +299,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
|
||||
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -315,8 +314,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
|
||||
@@ -574,13 +574,6 @@ html[lang|="ko"] i {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Prevent buttons from jumping up and down
|
||||
when a tooltip is shown for one of them. */
|
||||
.btn-group-vertical > .tooltip + .btn,
|
||||
.btn-group-vertical > .tooltip + .btn-group {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.select-on-click {
|
||||
-webkit-user-select: all;
|
||||
user-select: all;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Cancel": "إلغاء",
|
||||
"Changelog": "سجل التغيير",
|
||||
"Clean out after": "نظف بعد",
|
||||
"Cleaning Versions": "إصدارات نظيفة",
|
||||
"Cleanup Interval": "الفاصل الزمني للتنظيف",
|
||||
"Click to see full identification string and QR code.": "انقر لرؤية سلسلة التعريف الكاملة ورمز الاستجابة السريعة QR.",
|
||||
"Close": "أغلق",
|
||||
@@ -65,6 +66,7 @@
|
||||
"Connection Error": "خطأ في الإتصال",
|
||||
"Connection Type": "نوع الاتصال",
|
||||
"Connections": "اتصالات",
|
||||
"Connections via relays might be rate limited by the relay": "قد يكون معدل التوصيلات عبر المرحلات محدودًا بواسطة المرحل",
|
||||
"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 original": "منسوخ من الأصل",
|
||||
@@ -83,12 +85,18 @@
|
||||
"Default Ignore Patterns": "أنماط التجاهل الافتراضية",
|
||||
"Defaults": "الافتراضات",
|
||||
"Delete": "حذف",
|
||||
"Delete Unexpected Items": "حذف العناصر غير المتوقعة",
|
||||
"Deleted {%file%}": "حُذِفت {{file}}",
|
||||
"Deselect All": "الغاء تحديد الكل",
|
||||
"Deselect devices to stop sharing this folder with.": "قم بإلغاء تحديد الأجهزة لإيقاف مشاركة هذا المجلد معها.",
|
||||
"Deselect folders to stop sharing with this device.": "قم بإلغاء تحديد المجلدات لإيقاف المشاركة مع هذا الجهاز.",
|
||||
"Device": "جهاز",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "الجهاز \"{{الاسم}}\" ({{الجهاز}} في {{العنوان}}) يرغب في الاتصال، إضافة جهاز جديد؟",
|
||||
"Device Certificate": "شهادة الجهاز",
|
||||
"Device ID": "هوية الجهاز",
|
||||
"Device Identification": "هوية الجهاز",
|
||||
"Device Name": "أسم الجهاز",
|
||||
"Device is untrusted, enter encryption password": "الجهاز غير موثوق به، أدخل كلمة مرور التشفير",
|
||||
"Device rate limits": "حدود معدل نقل البيانات",
|
||||
"Device that last modified the item": "اخر جهاز جهاز عدل على العنصر",
|
||||
"Devices": "الأجهزة",
|
||||
@@ -97,11 +105,17 @@
|
||||
"Disabled periodic scanning and disabled watching for changes": "تعطيل المسح الدوري ومشاهدة التغييرات",
|
||||
"Disabled periodic scanning and enabled watching for changes": "تعطيل المسح الدوري وتفعيل مشاهدة التغييرات",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "تعطيل المسح الدوري وفشل إعداد مشاهدة التغييرات، إعادة المحاولة كل 1 دقيقة:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "تعطيل مقارنة أذونات الملفات ومزامنتها. مفيد على الأنظمة ذات الأذونات غير الموجودة أو المخصصة (مثل FAT و exFAT و Synology و Android).",
|
||||
"Discard": "تجاهل",
|
||||
"Disconnected": "غير متصل",
|
||||
"Disconnected (Inactive)": "غير متصل (غير نشط)",
|
||||
"Disconnected (Unused)": "غير متصل (غير مستخدم)",
|
||||
"Discovered": "مكتشفة",
|
||||
"Discovery": "اكتشاف",
|
||||
"Discovery Failures": "فشل الاكتشاف",
|
||||
"Discovery Status": "حالة الاكتشاف",
|
||||
"Dismiss": "رفض",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "لا تقم بإضافته إلى قائمة التجاهل، لذلك قد يتكرر هذا الإشعار.",
|
||||
"Do not restore": "الغاء الاستعادة",
|
||||
"Do not restore all": "الغاء استعادة الكل",
|
||||
"Do you want to enable watching for changes for all your folders?": "هل تريد تفعيل مراقبة التغيرات على كل المجلدات؟",
|
||||
@@ -111,6 +125,7 @@
|
||||
"Downloading": "جاري التحميل",
|
||||
"Edit": "تعديل",
|
||||
"Edit Device": "تعديل الجهاز",
|
||||
"Edit Device Defaults": "تحرير الإعدادات الافتراضية للجهاز",
|
||||
"Edit Folder": "تعديل المجلد",
|
||||
"Editing {%path%}.": "تعديل {{path}}.",
|
||||
"Enable Crash Reporting": "تفعيل التبليغ عن الاخطاء",
|
||||
@@ -301,7 +316,6 @@
|
||||
"This is a major version upgrade.": "ترقية أساسية ",
|
||||
"Time": "الوقت",
|
||||
"Time the item was last modified": "توقيت اخر تعديل للعنصر",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "نوع",
|
||||
"Unavailable": "غير متوفر",
|
||||
"Unavailable/Disabled by administrator or maintainer": "غير متوفر/معطل من قبل المسؤول أو الصيانة",
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "The maximum time to keep a version (in days, set to 0 to keep versions forever).",
|
||||
"The number of old versions to keep, per file.": "Колькі старых вэрсій трымаць, для кожнага файлу.",
|
||||
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
|
||||
"Twitter": "Twitter",
|
||||
"Unknown": "Невядома",
|
||||
"Up to Date": "Найноўшае",
|
||||
"Upgrade To {%version%}": "Upgrade To {{version}}",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"A device with that ID is already added.": "Устройство с този идентификатор вече е добавено.",
|
||||
"A negative number of days doesn't make sense.": "Отрицателният брой дни е безсмислен.",
|
||||
"A new major version may not be compatible with previous versions.": "Ново значимо издание, което може да е несъвместимо с предните издания.",
|
||||
"API Key": "Ключ за ППИ",
|
||||
"API Key": "API Ключ",
|
||||
"About": "Относно",
|
||||
"Action": "Действие",
|
||||
"Actions": "Действия",
|
||||
@@ -94,7 +94,7 @@
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Устройство \"{{name}}\" ({{device}}) с адрес {{address}} желае да се свърже. Да бъде ли добавено?",
|
||||
"Device Certificate": "Сертификат на устройството",
|
||||
"Device ID": "Идентификатор на устройство",
|
||||
"Device Identification": "Идентификатор на устройство",
|
||||
"Device Identification": "Идентификация на устройство",
|
||||
"Device Name": "Име на устройството",
|
||||
"Device is untrusted, enter encryption password": "Устройството е недоверено, въведете парола за шифроване",
|
||||
"Device rate limits": "Ограничаване на скоростта",
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Днес",
|
||||
"Trash Can": "Кошче за отпадъци",
|
||||
"Trash Can File Versioning": "Версии от вида „кошче за отпадъци“",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Вид",
|
||||
"UNIX Permissions": "Права на UNIX",
|
||||
"Unavailable": "Няма налични",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Avui",
|
||||
"Trash Can": "Paperera",
|
||||
"Trash Can File Versioning": "Paperera de versionat de fitxers",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipus",
|
||||
"UNIX Permissions": "Permisos UNIX",
|
||||
"Unavailable": "No disponible",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Avui",
|
||||
"Trash Can": "Paperera",
|
||||
"Trash Can File Versioning": "Versionat d'arxius de la paperera",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipus",
|
||||
"UNIX Permissions": "Permisos UNIX",
|
||||
"Unavailable": "No disponible",
|
||||
|
||||
@@ -415,7 +415,6 @@
|
||||
"Today": "Dnes",
|
||||
"Trash Can": "Koš",
|
||||
"Trash Can File Versioning": "Ponechávat jednu předchozí verzi (jako Koš) ",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Typ",
|
||||
"UNIX Permissions": "UNIX oprávnění",
|
||||
"Unavailable": "Nedostupné",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "I dag",
|
||||
"Trash Can": "Affaldskurv",
|
||||
"Trash Can File Versioning": "Versionering med papirkurv",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX rettigheder",
|
||||
"Unavailable": "Ikke tilgængelig",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Heute",
|
||||
"Trash Can": "Papierkorb",
|
||||
"Trash Can File Versioning": "Papierkorb Dateiversionierung",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Typ",
|
||||
"UNIX Permissions": "UNIX-Berechtigungen",
|
||||
"Unavailable": "Nicht verfügbar",
|
||||
|
||||
@@ -314,7 +314,6 @@
|
||||
"Time": "Χρόνος",
|
||||
"Time the item was last modified": "Ώρα τελευταίας τροποποίησης του στοιχείου",
|
||||
"Trash Can File Versioning": "Τήρηση εκδόσεων κάδου ανακύκλωσης",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Τύπος",
|
||||
"UNIX Permissions": "Άδειες αρχείων UNIX",
|
||||
"Unavailable": "Μη διαθέσιμο",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Today",
|
||||
"Trash Can": "Trash Can",
|
||||
"Trash Can File Versioning": "Bin File Versioning",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"Unavailable": "Unavailable",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Today",
|
||||
"Trash Can": "Rubbish Bin",
|
||||
"Trash Can File Versioning": "Rubbish Bin File Versioning",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"Unavailable": "Unavailable",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Today",
|
||||
"Trash Can": "Trash Can",
|
||||
"Trash Can File Versioning": "Trash Can File Versioning",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"Unavailable": "Unavailable",
|
||||
|
||||
@@ -317,7 +317,6 @@
|
||||
"Time": "Tempo",
|
||||
"Time the item was last modified": "Tempo de lasta modifo de la ero",
|
||||
"Trash Can File Versioning": "Rubuja Dosiera Versionado",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "Permesoj UNIX",
|
||||
"Unavailable": "Ne disponebla",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Hoy",
|
||||
"Trash Can": "Papelera",
|
||||
"Trash Can File Versioning": "Versionado de archivos de la papelera",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "Permisos de UNIX",
|
||||
"Unavailable": "No disponible",
|
||||
|
||||
@@ -113,7 +113,6 @@
|
||||
"The folder path cannot be blank.": "Kausta asukoht ei tohi olla tühi!",
|
||||
"The following items could not be synchronized.": "Järgnevaid üksusi ei õnnestunud sünkroniseerida.",
|
||||
"The maximum age must be a number and cannot be blank.": "Maksimaalne vanus peab olema arv ning ei tohi olla tühi.",
|
||||
"Twitter": "Twitter",
|
||||
"Unknown": "Teadmata",
|
||||
"Upload Rate": "Üleslaadimise Kiirus",
|
||||
"Use HTTPS for GUI": "Kasuta HTTPS'i GUI jaoks",
|
||||
|
||||
@@ -384,7 +384,6 @@
|
||||
"Time": "Ordua",
|
||||
"Time the item was last modified": "Itema azkenekoz aldatu zen ordua",
|
||||
"Trash Can File Versioning": "Zakarrontzia",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Mota",
|
||||
"UNIX Permissions": "UNIX baimenak",
|
||||
"Unavailable": "Ez dago erabilgarri",
|
||||
|
||||
@@ -310,7 +310,6 @@
|
||||
"Time": "Aika",
|
||||
"Time the item was last modified": "Aika jolloin kohdetta viimeksi muokattiin",
|
||||
"Trash Can File Versioning": "Roskakorin tiedostoversiointi",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tyyppi",
|
||||
"Unavailable": "Ei saatavilla",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Ei saatavilla / ylläpitäjän estämä.",
|
||||
|
||||
@@ -210,7 +210,6 @@
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Ce réglage contrôle l'espace disque requis dans le disque qui abrite votre répertoire utilisateur (pour la base de données d'indexation).",
|
||||
"Time": "Heure",
|
||||
"Trash Can File Versioning": "Style poubelle",
|
||||
"Twitter": "Twitter",
|
||||
"Unknown": "Inconnu",
|
||||
"Unshared": "Non partagé",
|
||||
"Up to Date": "À jour",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"About": "À propos",
|
||||
"Action": "Action",
|
||||
"Actions": "Actions",
|
||||
"Active filter rules": "Règles de filtrage actives",
|
||||
"Active filter rules": "Filtres enregistrés",
|
||||
"Add": "Ajouter",
|
||||
"Add Device": "Ajouter l'appareil",
|
||||
"Add Folder": "Ajouter un partage",
|
||||
@@ -135,8 +135,8 @@
|
||||
"Enabled": "Activée",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Active la synchronisation des attributs étendus. Cette option peut nécessiter d'exécuter Syncthing avec élévation de privilèges.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Active l'envoi des attributs étendus mais ignore leur réception. Cette option peut provoquer une dégradation notable des performances. L'envoi est toujours activé si on choisit l'option \"Synchroniser les attributs étendus\".",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Active la synchronisation de l'attribut \"Propriétaire\". Cette option nécessite habituellement d'exécuter Syncthing avec élévation de privilèges.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Active l'envoi de l'attribut \"Propriétaire\" mais ignore sa réception. Cette option peut provoquer une dégradation notable des performances. L'envoi est toujours activé si on choisit l'option \"Synchroniser le propriétaire\".",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Active la synchronisation bidirectionnelle de l'attribut \"Propriétaire\". Cette option nécessite habituellement d'exécuter Syncthing avec élévation de privilèges.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Active l'envoi de l'attribut local \"Propriétaire\" mais ignore sa réception de la part des autres appareils. Cette option peut provoquer une dégradation notable des performances. L'envoi est toujours activé si on choisit l'option \"Synchroniser l'appartenance\".",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Nombre positif (p.ex, \"2.35\") et unité. Pourcentage de l'espace disque total.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Entrez un numéro de port non-privilégié (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Entrer les adresses (\"tcp://ip:port\" ou \"tcp://hôte:port\") séparées par une virgule, ou \"dynamic\" afin d'activer la recherche automatique de l'adresse.",
|
||||
@@ -144,7 +144,7 @@
|
||||
"Enter up to three octal digits.": "Entrez jusqu'à 3 chiffres octaux.",
|
||||
"Error": "Erreur",
|
||||
"Extended Attributes": "Attributs étendus",
|
||||
"Extended Attributes Filter": "Filtre d'attributs étendus",
|
||||
"Extended Attributes Filter": "Filtres d'attributs étendus",
|
||||
"External": "Gestion externe",
|
||||
"External File Versioning": "Gestion externe des versions de fichiers",
|
||||
"Failed Items": "Éléments en échec",
|
||||
@@ -186,7 +186,7 @@
|
||||
"Global Discovery Servers": "Serveurs de découverte globale",
|
||||
"Global State": "État global",
|
||||
"Help": "Aide (en anglais)",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Remarque : quand la règle par défaut est le rejet, seules les règles de rejet sont prises en compte. Envisagez d'ajouter * (Accepter tout) comme dernière règle.",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Remarque : vous n'avez indiqué que des filtres de refus alors que le comportement par défaut est déjà le refus. Envisagez d'ajouter * (Partager tout les autres attributs non spécifiés) comme dernier filtre (coché) pour inverser le comportement par défaut.",
|
||||
"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": "Identifiant abrégé",
|
||||
@@ -253,7 +253,7 @@
|
||||
"No": "Non",
|
||||
"No File Versioning": "Sans",
|
||||
"No files will be deleted as a result of this operation.": "Aucun fichier ne sera supprimé à la suite de cette opération.",
|
||||
"No rules set": "Aucune règle définie (accepter tout)",
|
||||
"No rules set": "Aucun filtre défini (partager tous les attributs)",
|
||||
"No upgrades": "Pas de mises à jour",
|
||||
"Not shared": "Non partagé",
|
||||
"Notice": "Notification",
|
||||
@@ -336,7 +336,7 @@
|
||||
"Send & Receive": "Envoi & réception",
|
||||
"Send Extended Attributes": "Envoyer les attributs étendus",
|
||||
"Send Only": "Envoi (lecture seule)",
|
||||
"Send Ownership": "Envoyer le propriétaire",
|
||||
"Send Ownership": "Envoyer l'appartenance",
|
||||
"Set Ignores on Added Folder": "Définir des exclusions pour le nouveau partage",
|
||||
"Settings": "Configuration",
|
||||
"Share": "Partager",
|
||||
@@ -378,7 +378,7 @@
|
||||
"Support": "Forum",
|
||||
"Support Bundle": "Kit d'assistance",
|
||||
"Sync Extended Attributes": "Synchroniser les attributs étendus",
|
||||
"Sync Ownership": "Synchroniser le propriétaire",
|
||||
"Sync Ownership": "Synchroniser l'appartenance",
|
||||
"Sync Protocol Listen Addresses": "Adresses d'écoute du protocole de synchronisation",
|
||||
"Sync Status": "État de la synchronisation",
|
||||
"Syncing": "Synchronisation en cours",
|
||||
@@ -444,11 +444,10 @@
|
||||
"Time": "Heure",
|
||||
"Time the item was last modified": "Dernière modification de l'élément",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Pour connecter votre appareil avec celui nommé \"{{devicename}}\", ajoutez ce nouvel appareil distant portant cet identifiant de votre côté :",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Activez les règles souhaitées en cochant la case. Laissez décoché pour ignorer la règle.",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Partagez l'attribut spécifié en cochant la case. Laissez décoché pour refuser (comportement par défaut dès la première règle pour les attributs non spécifiés).",
|
||||
"Today": "Aujourd'hui",
|
||||
"Trash Can": "Corbeille",
|
||||
"Trash Can File Versioning": "Style poubelle",
|
||||
"Twitter": "Piaf",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "Permissions UNIX",
|
||||
"Unavailable": "Indisponible",
|
||||
@@ -519,7 +518,7 @@
|
||||
"full documentation": "Documentation complète ici (en anglais)",
|
||||
"items": "élément(s)",
|
||||
"modified": "modifié",
|
||||
"permit": "accepter",
|
||||
"permit": "partager tous les attributs",
|
||||
"seconds": "secondes",
|
||||
"theme-name-black": "Noir",
|
||||
"theme-name-dark": "Sombre",
|
||||
|
||||
@@ -368,7 +368,6 @@
|
||||
"Time": "Tiid",
|
||||
"Time the item was last modified": "Tiidstip dat it ûnderdiel foar it lest oanpast waard.",
|
||||
"Trash Can File Versioning": "Jiskefet-triemferzjebehear",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX-Rjochten",
|
||||
"Unavailable": "Net beskikber",
|
||||
|
||||
@@ -22,6 +22,5 @@
|
||||
"Alphabetic": "Alfabética",
|
||||
"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.": "Un comando externo xestiona as versións. Ten que eliminar o ficheiro do cartafol compartido. Si a ruta ao aplicativo contén espazos, deberían ir acotados.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"LDAP": "LDAP",
|
||||
"Twitter": "Twitter"
|
||||
"LDAP": "LDAP"
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@
|
||||
"Source Code": "קוד מקור",
|
||||
"Support": "תמיכה",
|
||||
"Syncing": "כעת בסנכרון",
|
||||
"Twitter": "Twitter",
|
||||
"Upgrade": "שדרוג",
|
||||
"Upgrade To {%version%}": "שדרוג לגרסה {{version}}",
|
||||
"Upgrading": "כעת בשדרוג",
|
||||
|
||||
@@ -18,6 +18,5 @@
|
||||
"Allowed Networks": "Dozvoljene mreže",
|
||||
"Alphabetic": "Abecednim redom",
|
||||
"Apply": "Primijeni",
|
||||
"LDAP": "LDAP",
|
||||
"Twitter": "Twitter"
|
||||
"LDAP": "LDAP"
|
||||
}
|
||||
|
||||
@@ -439,7 +439,6 @@
|
||||
"Today": "Ma",
|
||||
"Trash Can": "Szemetes",
|
||||
"Trash Can File Versioning": "Szemetes fájlverzió-követés",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Típus",
|
||||
"UNIX Permissions": "UNIX jogosultságok",
|
||||
"Unavailable": "Nem elérhető",
|
||||
|
||||
@@ -395,7 +395,6 @@
|
||||
"Time the item was last modified": "Waktu file terakhir dimodifikasi",
|
||||
"Today": "Hari Ini",
|
||||
"Trash Can File Versioning": "Pemversian Berkas Tempat Sampah",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipe",
|
||||
"UNIX Permissions": "Izin UNIX",
|
||||
"Unavailable": "Tidak Tersedia",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Oggi",
|
||||
"Trash Can": "Cestino",
|
||||
"Trash Can File Versioning": "Controllo Versione con Cestino",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "Permessi UNIX",
|
||||
"Unavailable": "Non disponibile",
|
||||
|
||||
@@ -379,7 +379,6 @@
|
||||
"Time the item was last modified": "項目を最後に変更した日時",
|
||||
"Today": "今日",
|
||||
"Trash Can File Versioning": "ゴミ箱によるバージョン管理",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "タイプ",
|
||||
"UNIX Permissions": "UNIX パーミッション",
|
||||
"Unavailable": "利用不可",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "오늘",
|
||||
"Trash Can": "휴지통",
|
||||
"Trash Can File Versioning": "휴지통을 통한 파일 버전 관리",
|
||||
"Twitter": "트위터",
|
||||
"Type": "유형",
|
||||
"UNIX Permissions": "UNIX 권한",
|
||||
"Unavailable": "변경 불가",
|
||||
|
||||
@@ -376,7 +376,6 @@
|
||||
"Today": "Šiandien",
|
||||
"Trash Can": "Šiukšlinė",
|
||||
"Trash Can File Versioning": "Šiukšliadėžės versijų valdymas",
|
||||
"Twitter": "„Twitter“",
|
||||
"Type": "Tipas",
|
||||
"UNIX Permissions": "UNIX leidimai",
|
||||
"Unavailable": "Neprieinama",
|
||||
|
||||
@@ -294,7 +294,6 @@
|
||||
"Time": "Klokkeslett",
|
||||
"Time the item was last modified": "Tidspunktet elementet sist ble endret",
|
||||
"Trash Can File Versioning": "Papirkurv versjonskontroll",
|
||||
"Twitter": "Twitter",
|
||||
"Unavailable": "Utilgjengelig",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Utilgjengelig/avskrudd av administrator eller vedlikeholder",
|
||||
"Undecided (will prompt)": "Ikke bestemt (vil spørre)",
|
||||
|
||||
@@ -24,6 +24,5 @@
|
||||
"Copied from elsewhere": "अन्यत्रबाट प्रतिलिपित्",
|
||||
"Copied from original": "मूलबाट प्रतिलिपित्",
|
||||
"Danger!": "खतरा!",
|
||||
"LDAP": "LDAP",
|
||||
"Twitter": "Twitter"
|
||||
"LDAP": "LDAP"
|
||||
}
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Vandaag",
|
||||
"Trash Can": "Prullenbak",
|
||||
"Trash Can File Versioning": "Prullenbak-versiebeheer",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX-machtigingen",
|
||||
"Unavailable": "Niet beschikbaar",
|
||||
|
||||
@@ -231,7 +231,6 @@
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Dette kan lett gje datasnokar tilgang til å lesa og endra vilkårlege filer på denne maskina.",
|
||||
"This is a major version upgrade.": "Dette er ei hovudoppgradering",
|
||||
"Trash Can File Versioning": "Papirkorg-filutgåvehandtering",
|
||||
"Twitter": "Twitter",
|
||||
"Unknown": "Ukjent",
|
||||
"Unshared": "Ikkje delt",
|
||||
"Up to Date": "Oppdatert",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Dzisiaj",
|
||||
"Trash Can": "Kosz",
|
||||
"Trash Can File Versioning": "Wersjonowanie plików w koszu",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Rodzaj",
|
||||
"UNIX Permissions": "UNIX-owe uprawnienia",
|
||||
"Unavailable": "Niedostępne",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Hoje",
|
||||
"Trash Can": "Cesto de Lixo",
|
||||
"Trash Can File Versioning": "Lixeira",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "Permissões UNIX",
|
||||
"Unavailable": "Não disponível",
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
"A new major version may not be compatible with previous versions.": "Uma nova versão principal pode não ser compatível com versões anteriores.",
|
||||
"API Key": "Chave da API",
|
||||
"About": "Acerca da aplicação",
|
||||
"Action": "Acção",
|
||||
"Actions": "Acções",
|
||||
"Action": "Operação",
|
||||
"Actions": "Operações",
|
||||
"Active filter rules": "Regras de filtros em uso",
|
||||
"Add": "Adicionar",
|
||||
"Add Device": "Adicionar dispositivo",
|
||||
"Add Folder": "Adicionar pasta",
|
||||
"Add Remote Device": "Adicionar dispositivo remoto",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Adicione dispositivos do apresentador à nossa lista de dispositivos para ter pastas mutuamente partilhadas.",
|
||||
"Add filter entry": "Adicionar filtro",
|
||||
"Add ignore patterns": "Adicionar padrões de exclusão",
|
||||
"Add new folder?": "Adicionar nova pasta?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Para além disso o intervalo entre verificações completas irá ser aumentado (vezes 60, ou seja, um novo valor predefinido de 1h). Também o pode configurar manualmente para cada pasta, posteriormente, depois de seleccionar Não.",
|
||||
@@ -53,7 +55,7 @@
|
||||
"Cleaning Versions": "Limpando versões",
|
||||
"Cleanup Interval": "Intervalo entre limpezas",
|
||||
"Click to see full identification string and QR code.": "Clique para ver a identificação completa e o código QR.",
|
||||
"Close": "Fechar",
|
||||
"Close": "Dispensar",
|
||||
"Command": "Comando",
|
||||
"Comment, when used at the start of a line": "Comentário, quando usado no início de uma linha",
|
||||
"Compression": "Compressão",
|
||||
@@ -76,6 +78,7 @@
|
||||
"Danger!": "Perigo!",
|
||||
"Database Location": "Localização da base de dados",
|
||||
"Debugging Facilities": "Recursos de depuração",
|
||||
"Default": "Predefinido",
|
||||
"Default Configuration": "Configuração predefinida",
|
||||
"Default Device": "Dispositivo predefinido",
|
||||
"Default Folder": "Pasta predefinida",
|
||||
@@ -111,7 +114,7 @@
|
||||
"Discovery": "Descoberta",
|
||||
"Discovery Failures": "Falhas da descoberta",
|
||||
"Discovery Status": "Estado da descoberta",
|
||||
"Dismiss": "Fechar",
|
||||
"Dismiss": "Dispensar",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "Não adicionar à lista dos ignorados, para que esta notificação volte a aparecer.",
|
||||
"Do not restore": "Não restaurar",
|
||||
"Do not restore all": "Não restaurar nenhum",
|
||||
@@ -141,6 +144,7 @@
|
||||
"Enter up to three octal digits.": "Insira de um a três dígitos em octal.",
|
||||
"Error": "Erro",
|
||||
"Extended Attributes": "Atributos estendidos",
|
||||
"Extended Attributes Filter": "Filtro de atributos extendidos",
|
||||
"External": "Externa",
|
||||
"External File Versioning": "Externa",
|
||||
"Failed Items": "Itens que falharam",
|
||||
@@ -182,6 +186,7 @@
|
||||
"Global Discovery Servers": "Servidores de descoberta global",
|
||||
"Global State": "Estado global",
|
||||
"Help": "Ajuda",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Dica: quando a predefinição é \"negar\", apenas as regras de negação são encontradas. Considere adicionar \"permitir tudo\" como última regra.",
|
||||
"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": "Identificação",
|
||||
@@ -228,8 +233,10 @@
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "O acompanhamento do final do registo está em pausa. Desloque para o final para continuar.",
|
||||
"Logs": "Registos",
|
||||
"Major Upgrade": "Actualização importante",
|
||||
"Mass actions": "Acções em massa",
|
||||
"Mass actions": "Operações em massa",
|
||||
"Maximum Age": "Idade máxima",
|
||||
"Maximum single entry size": "Tamanho máximo das entradas únicas",
|
||||
"Maximum total size": "Tamanho máximo total",
|
||||
"Metadata Only": "Metadados apenas",
|
||||
"Minimum Free Disk Space": "Espaço livre mínimo no disco",
|
||||
"Mod. Device": "Dispositivo mod.",
|
||||
@@ -246,6 +253,7 @@
|
||||
"No": "Não",
|
||||
"No File Versioning": "Nenhuma",
|
||||
"No files will be deleted as a result of this operation.": "Nenhum ficheiro será eliminado como resultado desta operação.",
|
||||
"No rules set": "Não foram definidas regras",
|
||||
"No upgrades": "Sem actualizações",
|
||||
"Not shared": "Não partilhada",
|
||||
"Notice": "Avisos",
|
||||
@@ -396,7 +404,7 @@
|
||||
"The cleanup interval cannot be blank.": "O intervalo entre limpezas não pode estar vazio.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "A configuração foi gravada mas não activada. O Syncthing tem que reiniciar para activar a nova configuração.",
|
||||
"The device ID cannot be blank.": "O ID do dispositivo não pode estar vazio.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "O ID do dispositivo a colocar aqui pode ser obtido no menu \"Acções > Mostrar ID\" do outro dispositivo. Espaços e hífenes são opcionais (ignorados).",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "O ID do dispositivo a colocar aqui pode ser obtido no menu \"Operações > Mostrar ID\" do outro dispositivo. Espaços e hífenes são opcionais (ignorados).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "O relatório de utilização cifrado é enviado diariamente. É utilizado para rastrear plataformas comuns, tamanhos de pastas e versões da aplicação. Se o tipo de dados do relatório for alterado, será notificado novamente através desta janela.",
|
||||
"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.": "O ID do dispositivo fornecido não parece ser válido. Deveria ter 52 ou 56 caracteres constituídos por letras e números, com espaços e hífenes opcionais.",
|
||||
"The folder ID cannot be blank.": "O ID da pasta não pode estar vazio.",
|
||||
@@ -436,10 +444,10 @@
|
||||
"Time": "Quando",
|
||||
"Time the item was last modified": "Quando o item foi modificado pela última vez",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Para se ligar ao dispositivo Syncthing com o nome \"{{devicename}}\", adicione um novo dispositivo remoto do seu lado com este ID:",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Para permitir uma regra, marque a caixa. Para negar uma regra, deixe-a desmarcada.",
|
||||
"Today": "Hoje",
|
||||
"Trash Can": "Lixo",
|
||||
"Trash Can File Versioning": "Reciclagem",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "Permissões UNIX",
|
||||
"Unavailable": "Indisponível",
|
||||
@@ -465,6 +473,8 @@
|
||||
"Use notifications from the filesystem to detect changed items.": "Usar notificações do sistema de ficheiros para detectar itens alterados.",
|
||||
"User Home": "Pasta do utilizador",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "O nome de utilizador e a respectiva senha para a autenticação na interface gráfica não foram definidos. Considere efectuar essa configuração.",
|
||||
"Using a QUIC connection over LAN": "Usando uma ligação QUIC sobre LAN",
|
||||
"Using a QUIC connection over WAN": "Usando uma ligação QUIC sobre WAN",
|
||||
"Using a direct TCP connection over LAN": "Usando uma ligação TCP directa sobre LAN",
|
||||
"Using a direct TCP connection over WAN": "Usando uma ligação TCP directa sobre WAN",
|
||||
"Version": "Versão",
|
||||
@@ -499,10 +509,16 @@
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "A sua aplicação de SMS deverá abrir para deixar escolher o destinatário e enviar a partir do seu próprio número.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "A sua aplicação de email deverá abrir para deixar escolher o destinatário e enviar a partir do seu próprio endereço.",
|
||||
"days": "dias",
|
||||
"deleted": "eliminada",
|
||||
"deny": "negar",
|
||||
"directories": "pastas",
|
||||
"file": "ficheiro",
|
||||
"files": "ficheiros",
|
||||
"folder": "pasta",
|
||||
"full documentation": "documentação completa",
|
||||
"items": "itens",
|
||||
"modified": "modificada",
|
||||
"permit": "permitir",
|
||||
"seconds": "segundos",
|
||||
"theme-name-black": "Preto",
|
||||
"theme-name-dark": "Escuro",
|
||||
|
||||
@@ -360,7 +360,6 @@
|
||||
"Time": "Time",
|
||||
"Time the item was last modified": "Time the item was last modified",
|
||||
"Trash Can File Versioning": "Trash Can File Versioning",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"Unavailable": "Unavailable",
|
||||
|
||||
@@ -432,7 +432,6 @@
|
||||
"Today": "Сегодня",
|
||||
"Trash Can": "Корзина",
|
||||
"Trash Can File Versioning": "Использовать версионность для файлов в Корзине",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Тип",
|
||||
"UNIX Permissions": "Разрешения UNIX",
|
||||
"Unavailable": "Недоступно",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"Add Folder": "බහාලුමක් යොදන්න",
|
||||
"Add Remote Device": "දුරස්ථ උපාංගයක් යොදන්න",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "අන්යෝන්ය වශයෙන් බෙදා ගත් ෆෝල්ඩර සඳහා, අපගේ උපාංග ලැයිස්තුවට හඳුන්වා දෙන්නා වෙතින් උපාංග එක් කරන්න.",
|
||||
"Add filter entry": "පෙරීමේ නිවේශිතයක් යොදන්න",
|
||||
"Add ignore patterns": "නොසලකා හැරීමේ රටා එක් කරන්න",
|
||||
"Add new folder?": "නව බහාලුම යොදනවාද?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "අතිරේකව සම්පූර්ණ නැවත පරිලෝකනය කිරීමේ පරතරය වැඩි වනු ඇත (වාර 60, එනම් 1h හි නව පෙරනිමිය). අංක තේරීමෙන් පසුව ඔබට සෑම ෆෝල්ඩරයක් සඳහාම එය අතින් වින්යාසගත කළ හැක.",
|
||||
@@ -37,14 +38,16 @@
|
||||
"Are you sure you want to restore {%count%} files?": "ඔබට ගොනු {{count}} ක් ප්රත්යර්පණය කිරීමට වුවමනාද?",
|
||||
"Are you sure you want to revert all local changes?": "ඔබට සියලු දේශීය වෙනස්කම් ප්රතිවර්තනය කිරීමට අවශ්ය බව විශ්වාසද?",
|
||||
"Are you sure you want to upgrade?": "ඔබට උත්ශ්රේණි කිරීමට වුවමනාද?",
|
||||
"Authors": "කතුවරුන්",
|
||||
"Auto Accept": "ස්වයං පිළිගැනීම",
|
||||
"Automatic Crash Reporting": "ස්වයංක්රීය බිඳවැටීම් වාර්තා කිරීම",
|
||||
"Automatic Crash Reporting": "ස්වයංක්රීය බිඳවැටීම් වාර්තාකරණය",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "ස්වයංක්රීය උත්ශ්රේණිගත කිරීම දැන් ස්ථායී නිකුතු සහ නිදහස් අපේක්ෂකයින් අතර තේරීම ඉදිරිපත් කරයි.",
|
||||
"Automatic upgrades": "ස්වයංක්රීය උත්ශ්රේණි",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "අපේක්ෂක නිකුතු සඳහා ස්වයංක්රීය උත්ශ්රේණි කිරීම් සැමවිටම සක්රීය වේ.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "මෙම උපාංගය පෙරනිමි මාර්ගයේ ප්රචාරණය කරන ෆෝල්ඩර ස්වයංක්රීයව සාදන්න හෝ බෙදාගන්න.",
|
||||
"Available debug logging facilities:": "පවතින දෝශ නිරාකරණය කිරීමේ පහසුකම්:",
|
||||
"Be careful!": "පරෙස්සම් වෙන්න!",
|
||||
"Body:": "අන්තර්ගතය:",
|
||||
"Bugs": "දෝෂ",
|
||||
"Cancel": "අවලංගු",
|
||||
"Changelog": "වෙනස්කම්",
|
||||
@@ -56,6 +59,8 @@
|
||||
"Command": "විධානය",
|
||||
"Comment, when used at the start of a line": "පේළියක ආරම්භයේ භාවිතා කරන විට අදහස් දක්වන්න",
|
||||
"Compression": "සම්පීඩනය",
|
||||
"Configuration Directory": "වින්යාස නාමාවලිය",
|
||||
"Configuration File": "වින්යාස ගොනුව",
|
||||
"Configured": "වින්යාසගතයි",
|
||||
"Connected (Unused)": "සම්බන්ධයි (භාවිතයේ නැත)",
|
||||
"Connection Error": "සම්බන්ධතාවයේ දෝෂයකි",
|
||||
@@ -64,10 +69,15 @@
|
||||
"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.": "වෙනස්කම් සඳහා අඛණ්ඩව නැරඹීම දැන් සමමුහුර්තකරණය තුළ පවතී. මෙය තැටියේ වෙනස්කම් හඳුනාගෙන වෙනස් කරන ලද මාර්ගවල පමණක් ස්කෑන් කිරීමක් නිකුත් කරයි. ප්රතිලාභ නම් වෙනස්කම් ඉක්මනින් ප්රචාරණය වීම සහ අඩු සම්පූර්ණ ස්කෑන් අවශ්ය වීමයි.",
|
||||
"Copied from elsewhere": "වෙනත් තැනකින් පිටපත් කර ඇත",
|
||||
"Copied from original": "මුල් පිටපතෙන් පිටපත් කර ඇත",
|
||||
"Copied!": "පිටපත් විය!",
|
||||
"Copy": "පිටපතක්",
|
||||
"Copy failed! Try to select and copy manually.": "පිටපත් වීමට අසමත් විය! අතින් තෝරා පිටපත් කිරීමට බලන්න.",
|
||||
"Currently Shared With Devices": "දැනට උපාංග සමඟ බෙදාගෙන ඇත",
|
||||
"Custom Range": "අභිරුචි පරාසය",
|
||||
"Danger!": "අනතුර!",
|
||||
"Database Location": "දත්ත සමුදායේ ස්ථානය",
|
||||
"Debugging Facilities": "නිදොස්කරණ පහසුකම්",
|
||||
"Default": "පෙරනිමි",
|
||||
"Default Configuration": "පෙරනිමි වින්යාසය",
|
||||
"Default Device": "පෙරනිමි උපාංගය",
|
||||
"Default Folder": "පෙරනිමි බහාලුම",
|
||||
@@ -81,6 +91,7 @@
|
||||
"Deselect folders to stop sharing with this device.": "මෙම උපාංගය සමඟ බෙදා ගැනීම නැවැත්වීමට ෆෝල්ඩර තේරීම ඉවත් කරන්න.",
|
||||
"Device": "උපාංගය",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "උපාංගය \"{{name}}\" ({{device}} ට {{address}}) සම්බන්ධ වීමට අවශ්යයි. නව උපාංගයක් එක් කරන්නද?",
|
||||
"Device Certificate": "උපාංගයේ සහතිකය",
|
||||
"Device ID": "උපාංගයේ හැඳු.",
|
||||
"Device Identification": "උපාංගයේ හැඳුනුම",
|
||||
"Device Name": "උපාංගයේ නම",
|
||||
@@ -96,26 +107,27 @@
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "ගොනු අවසර සංසන්දනය කිරීම සහ සමමුහුර්ත කිරීම අබල කරයි. නොපවතින හෝ අභිරුචි අවසර සහිත පද්ධති මත ප්රයෝජනවත් වේ (උදා: FAT, exFAT, Synology, Android).",
|
||||
"Discard": "ඉවතලන්න",
|
||||
"Disconnected": "විසන්ධියි",
|
||||
"Disconnected (Inactive)": "විසන්ධියි (අක්රිය)",
|
||||
"Disconnected (Unused)": "විසන්ධියි (භාවිතයේ නැත)",
|
||||
"Discovered": "සොයා ගන්නා ලදී",
|
||||
"Discovery": "සොයාගැනීම",
|
||||
"Discovery Failures": "සොයාගැනීමේ අසාර්ථකත්වය",
|
||||
"Discovery Status": "සොයාගැනීමේ තත්ත්වය",
|
||||
"Discovery Status": "සොයාගැනීමේ තත්වය",
|
||||
"Dismiss": "අහකට",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "එය නොසලකා හැරීමේ ලැයිස්තුවට එක් නොකරන්න, එබැවින් මෙම දැනුම්දීම නැවත සිදු විය හැක.",
|
||||
"Do not restore": "ප්රත්යර්පණය නොකරන්න",
|
||||
"Do not restore all": "සියල්ල ප්රත්යර්පණය නොකරන්න",
|
||||
"Do you want to enable watching for changes for all your folders?": "ඔබට ඔබගේ සියලුම ෆෝල්ඩර සඳහා වෙනස්කම් නැරඹීම සබල කිරීමට අවශ්යද?",
|
||||
"Documentation": "ප්රලේඛනය",
|
||||
"Download Rate": "බාගත කිරීමේ අනුපාතය",
|
||||
"Download Rate": "බාගැනීමේ අනුපාතය",
|
||||
"Downloaded": "බාගත වී ඇත",
|
||||
"Downloading": "බාගැනෙමින්",
|
||||
"Edit": "සංස්කරණය",
|
||||
"Edit Device": "උපාංගය සංස්කරණය",
|
||||
"Edit Device Defaults": "උපාංග පෙරනිමි සංස්කරණය කරන්න",
|
||||
"Edit Device Defaults": "පෙරනිමි සංස්කරණය කරන්න",
|
||||
"Edit Folder": "බහාලුම සංස්කරණය",
|
||||
"Edit Folder Defaults": "ෆෝල්ඩර පෙරනිමි සංස්කරණය කරන්න",
|
||||
"Editing {%path%}.": "සංස්කරණය {{path}}.",
|
||||
"Editing {%path%}.": "{{path}} සංශෝධනය.",
|
||||
"Enable Crash Reporting": "බිඳවැටීම් වාර්තා කිරීම සබල කරන්න",
|
||||
"Enable NAT traversal": "NAT සංක්රමණය සබල කරන්න",
|
||||
"Enable Relaying": "Relaying සබල කරන්න",
|
||||
@@ -127,11 +139,11 @@
|
||||
"Enter up to three octal digits.": "අෂ්ටක ඉලක්කම් තුනක් දක්වා ඇතුළු කරන්න.",
|
||||
"Error": "දෝෂයකි",
|
||||
"External": "බාහිර",
|
||||
"External File Versioning": "බාහිර ගොනු අනුවාදය",
|
||||
"External File Versioning": "බාහිර ගොනු අනුවාදනය",
|
||||
"Failed Items": "අසාර්ථක අයිතම",
|
||||
"Failed to load file versions.": "ගොනු අනුවාද පූරණය කිරීමට අසමත් විය.",
|
||||
"Failed to load ignore patterns.": "නොසලකා හැරීමේ රටා පූරණය කිරීමට අසමත් විය.",
|
||||
"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": "ගොනු අනුවාදය",
|
||||
@@ -151,12 +163,15 @@
|
||||
"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)": "සම්පූර්ණ නැවත ස්කෑන් පරතරය (ය)",
|
||||
"Forever": "සදහටම",
|
||||
"Full Rescan Interval (s)": "පූර්ණ සුපිරික්සීමේ පරතරය (ත.)",
|
||||
"GUI": "GUI",
|
||||
"GUI / API HTTPS Certificate": "GUI / යෙ.ක්ර.මු. HTTPS සහතිකය",
|
||||
"GUI Authentication Password": "GUI සත්යාපන මුරපදය",
|
||||
"GUI Authentication User": "GUI සත්යාපන පරිශ්රීලක",
|
||||
"GUI Authentication: Set User and Password": "GUI සත්යාපනය: පරිශ්රීලක හා මුරපදය සකසන්න",
|
||||
"GUI Listen Address": "GUI සවන්දීමේ ලිපිනය",
|
||||
"GUI Override Directory": "GUI අභිබවන නාමාවලිය",
|
||||
"GUI Theme": "GUI තේමාව",
|
||||
"General": "සාමාන්ය",
|
||||
"Generate": "උත්පාදනය",
|
||||
@@ -174,7 +189,7 @@
|
||||
"Ignore Permissions": "අවසර නොසලකන්න",
|
||||
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "නොසලකා හැරීමේ රටා එකතු කළ හැක්කේ ෆෝල්ඩරය නිර්මාණය කිරීමෙන් පසුව පමණි. පරීක්ෂා කළහොත්, නොසලකා හැරීමේ රටා ඇතුළු කිරීමට ආදාන ක්ෂේත්රයක් සුරැකීමෙන් පසුව ඉදිරිපත් කෙරේ.",
|
||||
"Ignored Devices": "නොසැලකූ උපාංග",
|
||||
"Ignored Folders": "නොසැලකූ බහාලුම්",
|
||||
"Ignored Folders": "නොසලකන බහාලුම්",
|
||||
"Ignored at": "දී නොසලකා හරින ලදී",
|
||||
"Incoming Rate Limit (KiB/s)": "එන අනුපාත සීමාව (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "වැරදි වින්යාසය ඔබගේ ෆෝල්ඩර අන්තර්ගතයට හානි කළ හැකි අතර සමමුහුර්ත කිරීම අක්රිය කරයි.",
|
||||
@@ -191,6 +206,7 @@
|
||||
"Last seen": "අවසන දුටුවේ",
|
||||
"Latest Change": "නවතම වෙනස",
|
||||
"Learn more": "තව දැනගන්න",
|
||||
"Learn more at {%url%}": "{{url}} හරහා තව දැනගන්න",
|
||||
"Limit": "සීමාව",
|
||||
"Listener Failures": "සවන්දෙන්නන්ගේ අසාර්ථකත්වය",
|
||||
"Listener Status": "සවන්දෙන්නන්ගේ තත්ත්වය",
|
||||
@@ -198,49 +214,58 @@
|
||||
"Loading data...": "දත්ත පූරණය වෙමින්...",
|
||||
"Loading...": "පූරණය වෙමින්...",
|
||||
"Local Additions": "දේශීය එකතු කිරීම්",
|
||||
"Local Discovery": "ස්ථානීය සොයාගැනීම",
|
||||
"Local Discovery": "ස්ථානීයව සොයාගැනීම",
|
||||
"Local State": "ස්ථානීය තත්වය",
|
||||
"Local State (Total)": "ස්ථානීය තත්වය (මුළු)",
|
||||
"Locally Changed Items": "දේශීයව වෙනස් කරන ලද අයිතම",
|
||||
"Log": "සටහන",
|
||||
"Log File": "සටහන් ගොනුව",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "ලොග් වලිගය විරාම කරන ලදී. ඉදිරියට යාමට පහළට අනුචලනය කරන්න.",
|
||||
"Logs": "සටහන්",
|
||||
"Major Upgrade": "ප්රධාන උත්ශ්රේණි කිරීම",
|
||||
"Major Upgrade": "ප්රධාන උත්ශ්රේණි කිරීම",
|
||||
"Mass actions": "මහා ක්රියා",
|
||||
"Maximum Age": "උපරිම වයස",
|
||||
"Maximum single entry size": "තනි නිවේශිතයක උපරිම ප්රමාණය",
|
||||
"Maximum total size": "උපරිම මුළු ප්රමාණය",
|
||||
"Metadata Only": "පාරදත්ත පමණි",
|
||||
"Minimum Free Disk Space": "අවම තැටියේ ඉඩ",
|
||||
"Mod. Device": "mod. උපාංගය",
|
||||
"Mod. Time": "mod. කාලය",
|
||||
"More than a month ago": "මාසයකට පෙර",
|
||||
"More than a week ago": "සතියකට පෙර",
|
||||
"More than a year ago": "වසරකට පෙර",
|
||||
"Move to top of queue": "පෝලිමේ මුලට ගෙනයන්න",
|
||||
"Multi level wildcard (matches multiple directory levels)": "බහු මට්ටමේ වයිල්ඩ්කාඩ් (බහු ඩිරෙක්ටරි මට්ටම් වලට ගැලපේ)",
|
||||
"Never": "කවදාවත්",
|
||||
"New Device": "නව උපාංගය",
|
||||
"New Folder": "නව බහාලුම",
|
||||
"Newest First": "අලුත්ම මුලින්ම",
|
||||
"Newest First": "නව දෑ පළමුව",
|
||||
"No": "නැහැ",
|
||||
"No File Versioning": "ගොනු අනුවාදනයක් නැත",
|
||||
"No files will be deleted as a result of this operation.": "මෙම මෙහෙයුමේ ප්රතිඵලයක් ලෙස කිසිදු ගොනුවක් මකා නොදමනු ඇත.",
|
||||
"No rules set": "නීති සකසා නැත",
|
||||
"No upgrades": "උත්ශ්රේණි නැත",
|
||||
"Not shared": "බෙදාගෙන නැත",
|
||||
"Notice": "දැන්වීම",
|
||||
"OK": "හරි",
|
||||
"Off": "අක්රියයි",
|
||||
"Oldest First": "පැරණිතම පළමු",
|
||||
"Oldest First": "පරණ දෑ පළමුව",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "ෆෝල්ඩරය සඳහා විකල්ප විස්තර ලේබලය. එක් එක් උපාංගය මත වෙනස් විය හැක.",
|
||||
"Options": "විකල්ප",
|
||||
"Out of Sync": "සමමුහුර්ත නොවේ",
|
||||
"Out of Sync Items": "අයිතම සමමුහුර්ත නොවේ",
|
||||
"Out of Sync": "සමමුහූර්ත නොවේ",
|
||||
"Out of Sync Items": "සමමුහූර්ත නොවන අථක",
|
||||
"Outgoing Rate Limit (KiB/s)": "පිටතට යන ගාස්තු සීමාව (KiB/s)",
|
||||
"Override": "අභිබවන්න",
|
||||
"Override Changes": "වෙනස්කම් අභිබවන්න",
|
||||
"Ownership": "අයිතිය",
|
||||
"Path": "මාර්ගය",
|
||||
"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": "දේශීය පරිගණකයේ ෆෝල්ඩරය වෙත මාර්ගය. එය නොමැති නම් නිර්මාණය වනු ඇත. tilde අක්ෂරය (~) සඳහා කෙටි මගක් ලෙස භාවිතා කළ හැක",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "අනුවාද ගබඩා කළ යුතු මාර්ගය (බෙදාගත් ෆෝල්ඩරයේ පෙරනිමි .stversions නාමාවලිය සඳහා හිස්ව තබන්න).",
|
||||
"Pause": "විරාමය",
|
||||
"Pause All": "සියල්ල විරාමය",
|
||||
"Paused": "විරාමයි",
|
||||
"Paused (Unused)": "විරාමයි (භාවිතා නොකළ)",
|
||||
"Paths": "මාර්ග",
|
||||
"Pause": "විරාමයක්",
|
||||
"Pause All": "සියල්ලට විරාමයක්",
|
||||
"Paused": "විරාමයකි",
|
||||
"Paused (Unused)": "විරාමයකි (භාවිතා නොකළ)",
|
||||
"Pending changes": "පොරොත්තු වෙනස්කම්",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "ලබා දී ඇති කාල සීමාව තුළ වරින් වර ස්කෑන් කිරීම සහ වෙනස්කම් සඳහා අබල කර බැලීම",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "ලබා දී ඇති කාල සීමාව තුළ වරින් වර ස්කෑන් කිරීම සහ වෙනස්කම් සඳහා නැරඹීම සබල කර ඇත",
|
||||
@@ -251,9 +276,12 @@
|
||||
"Please wait": "රැඳෙන්න",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "නාමාවලිය ඉවත් කිරීම වළක්වන්නේ නම් ගොනුව මකා දැමිය හැකි බව පෙන්නුම් කරන උපසර්ගය",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "සංවේදිතාවකින් තොරව රටාව ගැලපිය යුතු බව පෙන්නුම් කරන උපසර්ගය",
|
||||
"Preparing to Sync": "සමමුහූර්තයට සූදානම් ස්ථානයේ",
|
||||
"Preparing to Sync": "සමමුහූර්තයට සූදානම් වෙමින්",
|
||||
"Preview": "පෙරදසුන",
|
||||
"Preview Usage Report": "භාවිත වාර්තාවේ පෙරදසුන",
|
||||
"QR code": "QR කේතය",
|
||||
"QUIC LAN": "QUIC LAN",
|
||||
"QUIC WAN": "QUIC WAN",
|
||||
"Quick guide to supported patterns": "සහාය දක්වන රටා සඳහා ඉක්මන් මාර්ගෝපදේශය",
|
||||
"Random": "අහඹු",
|
||||
"Receive Encrypted": "සංකේතිිතව ලබන්න",
|
||||
@@ -269,15 +297,15 @@
|
||||
"Remove Device": "උපාංගය ඉවත් කරන්න",
|
||||
"Remove Folder": "බහාලුම ඉවත් කරන්න",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "ෆෝල්ඩරය සඳහා අවශ්ය හඳුනාගැනීම. සියලුම පොකුරු උපාංග මත සමාන විය යුතුය.",
|
||||
"Rescan": "නැවත ස්කෑන් කරන්න",
|
||||
"Rescan All": "සියල්ල නැවත ස්කෑන් කරන්න",
|
||||
"Rescan": "යළි සුපිරික්සන්න",
|
||||
"Rescan All": "සියල්ල යළි සුපිරික්සන්න",
|
||||
"Rescans": "නැවත ස්කෑන් කරයි",
|
||||
"Restart": "යළි අරඹන්න",
|
||||
"Restart Needed": "නැවත ආරම්භ කිරීම අවශ්යයි",
|
||||
"Restarting": "යළි ඇරඹෙමින්",
|
||||
"Restore": "ප්රත්යර්පණය",
|
||||
"Restore Versions": "අනුවාද ප්රත්යර්පණය",
|
||||
"Resume": "අරඹන්න",
|
||||
"Resume": "නැවතත්",
|
||||
"Resume All": "සියල්ල නැවතත්",
|
||||
"Reused": "යළි භාවිත",
|
||||
"Revert": "ආපසු හරවන්න",
|
||||
@@ -294,10 +322,13 @@
|
||||
"Select oldest version": "පරණම අනුවාදය තෝරන්න",
|
||||
"Send & Receive": "යැවීම සහ ලැබීම",
|
||||
"Send Only": "යැවීම පමණි",
|
||||
"Send Ownership": "අයිතිය යවන්න",
|
||||
"Set Ignores on Added Folder": "එකතු කළ ෆෝල්ඩරයේ නොසලකා හැරීම් සකසන්න",
|
||||
"Settings": "සැකසුම්",
|
||||
"Share": "බෙදාගන්න",
|
||||
"Share Folder": "බහාලුම බෙදාගන්න",
|
||||
"Share by Email": "වි-තැපෑලෙන් බෙදාගන්න",
|
||||
"Share by SMS": "කෙටි පණිවුඩ මගින් බෙදාගන්න",
|
||||
"Share this folder?": "මෙම බහාලුම බෙදා ගන්නද?",
|
||||
"Shared Folders": "බෙදාගත් බහාලුම්",
|
||||
"Shared With": "සමඟ බෙදාගෙන ඇත",
|
||||
@@ -329,10 +360,14 @@
|
||||
"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.": "සංකේතනය කළ දත්ත පමණක් ගබඩා කර සමමුහුර්ත කරයි. සියලුම සම්බන්ධිත උපාංගවල ඇති ෆෝල්ඩර එකම මුරපදයකින් හෝ \"{{receiveEncrypted}}\" වර්ගයට අයත් විය යුතුය.",
|
||||
"Subject:": "මාතෘකාව:",
|
||||
"Support": "සහාය",
|
||||
"Support Bundle": "ආධාරක බණ්ඩලය",
|
||||
"Sync Ownership": "සමමුහූර්ත අයිතිය",
|
||||
"Sync Protocol Listen Addresses": "ප්රොටෝකෝලය සවන්දීමේ ලිපින සමමුහුර්ත කරන්න",
|
||||
"Sync Status": "සමමුහූර්ත තත්වය",
|
||||
"Syncing": "සමමුහූර්තය",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "\"{{devicename}}\" සඳහා සයින්තින් උපාංගයේ හැඳු.",
|
||||
"Syncthing has been shut down.": "සමමුහුර්ත කිරීම වසා ඇත.",
|
||||
"Syncthing includes the following software or portions thereof:": "සමමුහුර්තකරණයට පහත මෘදුකාංග හෝ එහි කොටස් ඇතුළත් වේ:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "සමමුහුර්ත කිරීම MPL v2.0 ලෙස බලපත්ර ලබා ඇති නිදහස් සහ විවෘත මූලාශ්ර මෘදුකාංගයකි.",
|
||||
@@ -343,6 +378,8 @@
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "සමමුහුර්තකරණය දැන් සංවර්ධකයින්ට බිඳවැටීම් ස්වයංක්රීයව වාර්තා කිරීමට සහය දක්වයි. මෙම විශේෂාංගය පෙරනිමියෙන් සක්රිය කර ඇත.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "සමමුහුර්ත කිරීම අක්රිය වී ඇති බවක් පෙනේ, නැතහොත් ඔබගේ අන්තර්ජාල සම්බන්ධතාවයේ ගැටලුවක් තිබේ. නැවත උත්සාහ කරමින්…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "සමමුහුර්ත කිරීම ඔබගේ ඉල්ලීම සැකසීමේ ගැටලුවක් අත්විඳින බව පෙනේ. ගැටලුව දිගටම පවතින්නේ නම් කරුණාකර පිටුව නැවුම් කරන්න හෝ සමමුහුර්ත කිරීම නැවත ආරම්භ කරන්න.",
|
||||
"TCP LAN": "TCP LAN",
|
||||
"TCP WAN": "TCP WAN",
|
||||
"Take me back": "මාව ආපසු ගන්න",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "GUI ලිපිනය ආරම්භක විකල්ප මගින් අභිබවා යයි. ප්රතික්ෂේප කිරීම ක්රියාත්මක වන විට මෙහි වෙනස්කම් බල නොපායි.",
|
||||
"The Syncthing Authors": "සයින්තින් කතුවරුන්",
|
||||
@@ -363,6 +400,7 @@
|
||||
"The following items could not be synchronized.": "පහත අථක සමමුහූර්ත කිරීමට නොහැකිය.",
|
||||
"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 text will automatically be inserted into a new message.": "පහත පෙළ නව පණිවිඩයකට ස්වයංක්රීයව ඇතුළු කෙරේ.",
|
||||
"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.": "අනුවාද නාමාවලිය තුළ පිරිසිදු කිරීම ධාවනය කිරීම සඳහා තත්පර කිහිපයකින් පරතරය. ආවර්තිතා පිරිසිදු කිරීම අක්රිය කිරීමට ශුන්ය.",
|
||||
@@ -389,10 +427,10 @@
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "මෙම සිටුවම නිවසේ (එනම්, දර්ශක දත්ත ගබඩාව) තැටියේ අවශ්ය නිදහස් ඉඩ පාලනය කරයි.",
|
||||
"Time": "කාලය",
|
||||
"Time the item was last modified": "අයිතමය අවසන් වරට වෙනස් කළ වේලාව",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "\"{{devicename}}\" සයින්තින් උපාංගය සමඟ සම්බන්ධ වීමට, මෙම හැඳු. සහිත නව දුරස්ථ උපාංගයක් ඔබගේ පසට එක් කරන්න:",
|
||||
"Today": "අද",
|
||||
"Trash Can": "කසල බඳුන",
|
||||
"Trash Can File Versioning": "කුණු කූඩය ගොනු අනුවාදය",
|
||||
"Twitter": "ට්විටර්",
|
||||
"Type": "වර්ගය",
|
||||
"UNIX Permissions": "UNIX අවසර",
|
||||
"Unavailable": "නොතිබේ",
|
||||
@@ -417,6 +455,10 @@
|
||||
"Use HTTPS for GUI": "GUI සඳහා HTTPS භාවිතා කරන්න",
|
||||
"Use notifications from the filesystem to detect changed items.": "වෙනස් කළ අයිතම හඳුනා ගැනීමට ගොනු පද්ධතියෙන් දැනුම්දීම් භාවිතා කරන්න.",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "GUI සත්යාපනය සඳහා පරිශීලක නාමය/මුරපදය සකසා නොමැත. කරුණාකර එය පිහිටුවීම සලකා බලන්න.",
|
||||
"Using a QUIC connection over LAN": "LAN හරහා QUIC සම්බන්ධතාවයක් භාවිතය",
|
||||
"Using a QUIC connection over WAN": "WAN හරහා QUIC සම්බන්ධතාවයක් භාවිතය",
|
||||
"Using a direct TCP connection over LAN": "LAN හරහා සෘජු TCP සම්බන්ධතාවයක් භාවිතය",
|
||||
"Using a direct TCP connection over WAN": "WAN හරහා සෘජු TCP සම්බන්ධතාවයක් භාවිතය",
|
||||
"Version": "අනුවාදය",
|
||||
"Versions": "අනුවාද",
|
||||
"Versions Path": "අනුවාද මාර්ගය",
|
||||
@@ -437,19 +479,28 @@
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "නව ෆෝල්ඩරයක් එකතු කරන විට, උපාංග අතර ෆෝල්ඩර එකට ගැටගැසීමට ෆෝල්ඩර හැඳුනුම්පත භාවිතා කරන බව මතක තබා ගන්න. ඒවා සිද්ධි සංවේදී වන අතර සියලුම උපාංග අතර හරියටම ගැළපිය යුතුය.",
|
||||
"Yes": "ඔව්",
|
||||
"Yesterday": "ඊයේ",
|
||||
"You can also copy and paste the text into a new message manually.": "ඔබට අතින් නව පණිවිඩයකට පෙළ පිටපත් කර ඇලවීමට හැකිය.",
|
||||
"You can also select one of these nearby devices:": "මෙම ආසන්න උපාංග වලින් එකක් ද තේරීමට හැකිය:",
|
||||
"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 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.": "ඔබ කිසිවිටෙක \"{{receiveEncrypted}}\" ෆෝල්ඩරයකට දේශීයව කිසිවක් එකතු කිරීම හෝ වෙනස් කිරීම නොකළ යුතුය.",
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "ලබන්නා තේරීමට සහ එය ඔබගේම අංකයෙන් යැවීමට කෙටි පණිවිඩ යෙදුම විවෘත විය යුතුය.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "ලබන්නා තේරීමට සහ එය ඔබගේම ලිපිනයෙන් යැවීමට වි-තැපැල් යෙදුම විවෘත විය යුතුය.",
|
||||
"days": "දවස්",
|
||||
"deleted": "මකා ඇත",
|
||||
"deny": "ප්රතිෂේධනය",
|
||||
"directories": "නාමාවලි",
|
||||
"file": "ගොනුව",
|
||||
"files": "ගොනු",
|
||||
"folder": "බහාලුම",
|
||||
"full documentation": "පූර්ණ ප්රලේඛනය",
|
||||
"items": "අථක",
|
||||
"modified": "සංශෝධිතයි",
|
||||
"permit": "අවසරය",
|
||||
"seconds": "තත්පර",
|
||||
"theme-name-black": "කළු",
|
||||
"theme-name-dark": "අඳුරු",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Dnes",
|
||||
"Trash Can": "Kôš",
|
||||
"Trash Can File Versioning": "Verzie súborov v koši",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Typ",
|
||||
"UNIX Permissions": "UNIX povolenia",
|
||||
"Unavailable": "Nedostupné",
|
||||
|
||||
@@ -395,7 +395,6 @@
|
||||
"Today": "Danes",
|
||||
"Trash Can": "Koš",
|
||||
"Trash Can File Versioning": "Beleženje različic datotek s Smetnjakom",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Vrsta",
|
||||
"UNIX Permissions": "UNIX dovoljenja",
|
||||
"Unavailable": "Ni na voljo",
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
"Scanning": "Duke skanuar",
|
||||
"Select a version": "Zgjidh një version",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing është program falas dhe Open Source liçensuar si MPL v2.0.",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Lloji",
|
||||
"Yes": "Po",
|
||||
"days": "ditë",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Idag",
|
||||
"Trash Can": "Papperskorgen",
|
||||
"Trash Can File Versioning": "Papperskorgs filversionshantering",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Typ",
|
||||
"UNIX Permissions": "UNIX-behörigheter",
|
||||
"Unavailable": "Otillgänglig",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "Bugün",
|
||||
"Trash Can": "Çöp Kutusu",
|
||||
"Trash Can File Versioning": "Çöp Kutusu Dosyası Sürümlendirme",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Tür",
|
||||
"UNIX Permissions": "Unix İzinleri",
|
||||
"Unavailable": "Kullanılamaz",
|
||||
|
||||
@@ -439,7 +439,6 @@
|
||||
"Today": "Сьогодні",
|
||||
"Trash Can": "Смітник",
|
||||
"Trash Can File Versioning": "Версіювання файлів у кошику",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "Тип",
|
||||
"UNIX Permissions": "UNIX дозволи",
|
||||
"Unavailable": "Недоступно",
|
||||
|
||||
@@ -205,7 +205,6 @@
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Th.tác này có thể khiến tin tặc dễ dàng tr.cập để đọc và th.đổi bất kỳ t.tin nào trên máy của bạn.",
|
||||
"This is a major version upgrade.": "Đây là bản nâng cấp quan trọng.",
|
||||
"Trash Can File Versioning": "Kiểu thùng rác",
|
||||
"Twitter": "Twitter",
|
||||
"Unknown": "Không biết",
|
||||
"Unshared": "Chưa chia sẻ",
|
||||
"Up to Date": "Đã đồng bộ",
|
||||
|
||||
@@ -448,7 +448,6 @@
|
||||
"Today": "今天",
|
||||
"Trash Can": "回收站",
|
||||
"Trash Can File Versioning": "回收站式版本控制",
|
||||
"Twitter": "推特",
|
||||
"Type": "类型",
|
||||
"UNIX Permissions": "UNIX权限",
|
||||
"Unavailable": "无效",
|
||||
|
||||
@@ -434,7 +434,6 @@
|
||||
"Today": "今天",
|
||||
"Trash Can": "回收站",
|
||||
"Trash Can File Versioning": "回收站式版本控制",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "類型",
|
||||
"UNIX Permissions": "UNIX權限",
|
||||
"Unavailable": "無效",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"Add Folder": "添加資料夾",
|
||||
"Add Remote Device": "新增遠端裝置",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "對於共享的資料夾,匯入引入者的裝置清單。",
|
||||
"Add ignore patterns": "新增忽略模式",
|
||||
"Add new folder?": "新增資料夾?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "另外,完整地重新掃瞄的間隔將增大(時間 60,例如:新的預設值為 1 小時)。您也可以在選擇「否」後,手動配置每個資料夾的時間間隔。",
|
||||
"Address": "位址",
|
||||
@@ -18,6 +19,7 @@
|
||||
"Advanced": "進階",
|
||||
"Advanced Configuration": "進階配置",
|
||||
"All Data": "全部資料",
|
||||
"All Time": "所有時間",
|
||||
"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": "允許的網路",
|
||||
@@ -391,7 +393,6 @@
|
||||
"Time": "時間",
|
||||
"Time the item was last modified": "前次修改時間",
|
||||
"Trash Can File Versioning": "垃圾筒式檔案版本控制",
|
||||
"Twitter": "Twitter",
|
||||
"Type": "類型",
|
||||
"UNIX Permissions": "UNIX 權限",
|
||||
"Unavailable": "無法使用",
|
||||
|
||||
@@ -555,8 +555,8 @@
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-share-alt"></span> <span translate>Shared With</span></th>
|
||||
<td class="text-right no-overflow-ellipse word-break-all">
|
||||
<span ng-repeat="device in folder.devices">
|
||||
<span ng-if="device.deviceID != myID" ng-switch="completion[device.deviceID][folder.id].remoteState">
|
||||
<span ng-repeat="device in otherDevices(folder.devices)">
|
||||
<span ng-switch="completion[device.deviceID][folder.id].remoteState">
|
||||
<span ng-switch-when="notSharing" data-original-title="{{'The remote device has not accepted sharing this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>1</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-when="paused" data-original-title="{{'The remote device has paused this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>2</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-default>{{deviceName(devices[device.deviceID])}}<span ng-if="!$last">,</span></span>
|
||||
@@ -963,7 +963,6 @@
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing/releases" target="_blank"><span class="far fa-file-alt"></span> <span translate>Changelog</span></a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing/issues" target="_blank"><span class="fas fa-bug"></span> <span translate>Bugs</span></a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing" target="_blank"><span class="fas fa-wrench"></span> <span translate>Source Code</span></a></li>
|
||||
<li><a class="navbar-link" href="https://twitter.com/syncthing" target="_blank"><span class="fab fa-twitter"></span> <span translate>Twitter</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -1022,7 +1021,6 @@
|
||||
<script type="text/javascript" src="syncthing/core/eventService.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/identiconDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/languageSelectDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/lastErrorComponentFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/localeService.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/modalDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/metricFilter.js"></script>
|
||||
|
||||
@@ -26,7 +26,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, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Eric P, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, 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 O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, 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, K.B.Dharun Krishna, Kalle Laine, Karol Różycki, Kebin Liu, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, 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, Martchus, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, 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, Ryan Qian, 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, Vik, Vil Brekin, Vladimir Rusinov, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, bt90, chenrui, chucic, cui fliter, derekriemer, desbma, entity0xfe, georgespatton, ghjklw, guangwu, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, luzpaz, marco-m, mclang, mv1005, otbutz, overkill, perewa, red_led, rubenbe, sec65, villekalliomaki, 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, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Emil Lundberg, Eng Zer Jun, Eric Lesiuta, Eric P, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, 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 O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, 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, K.B.Dharun Krishna, Kalle Laine, Karol Różycki, Kebin Liu, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, 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, Martchus, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, 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, Ryan Qian, 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, Vik, Vil Brekin, Vladimir Rusinov, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, bt90, chenrui, chucic, cui fliter, derekriemer, desbma, entity0xfe, georgespatton, ghjklw, guangwu, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, luzpaz, marco-m, mclang, mv1005, otbutz, overkill, perewa, red_led, rubenbe, sec65, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
angular.module('syncthing.core')
|
||||
.filter('lastErrorComponent', function () {
|
||||
return function (input) {
|
||||
if (input === undefined)
|
||||
return "";
|
||||
var parts = input.split(/:\s*/);
|
||||
if (!parts || parts.length < 1) {
|
||||
return input;
|
||||
}
|
||||
return parts[parts.length - 1];
|
||||
};
|
||||
});
|
||||
@@ -740,20 +740,12 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
function pathJoin(base, name) {
|
||||
base = expandTilde(base);
|
||||
if (base[base.length - 1] !== $scope.system.pathSeparator) {
|
||||
return base + $scope.system.pathSeparator + name;
|
||||
}
|
||||
return base + name;
|
||||
}
|
||||
|
||||
function expandTilde(path) {
|
||||
if (path && path.trim().charAt(0) === '~') {
|
||||
return $scope.system.tilde + path.trim().substring(1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
function shouldSetDefaultFolderPath() {
|
||||
return $scope.config.defaults.folder.path && $scope.folderEditor.folderPath.$pristine && $scope.editingFolderNew();
|
||||
}
|
||||
@@ -1900,8 +1892,11 @@ angular.module('syncthing.core')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.otherDevices = function () {
|
||||
return $scope.deviceList().filter(function (n) {
|
||||
$scope.otherDevices = function (devices) {
|
||||
if (devices === undefined) {
|
||||
devices = $scope.deviceList();
|
||||
}
|
||||
return devices.filter(function (n) {
|
||||
return n.deviceID !== $scope.myID;
|
||||
});
|
||||
};
|
||||
@@ -1988,7 +1983,7 @@ angular.module('syncthing.core')
|
||||
if (!newvalue) {
|
||||
return;
|
||||
}
|
||||
$scope.currentFolder.path = expandTilde(newvalue);
|
||||
$scope.currentFolder.path = newvalue;
|
||||
$http.get(urlbase + '/system/browse', {
|
||||
params: { current: newvalue }
|
||||
}).success(function (data) {
|
||||
@@ -3056,7 +3051,11 @@ angular.module('syncthing.core')
|
||||
arch += " Container";
|
||||
}
|
||||
|
||||
return $scope.version.version + ', ' + os + ' (' + arch + ')';
|
||||
var verStr = $scope.version.version;
|
||||
if ($scope.version.extra) {
|
||||
verStr += ' (' + $scope.version.extra + ')';
|
||||
}
|
||||
return verStr + ', ' + os + ' (' + arch + ')';
|
||||
};
|
||||
|
||||
$scope.versionBase = function () {
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
<input ng-if="editingDeviceNew()" name="deviceID" id="deviceID" class="form-control text-monospace" type="text" ng-model="currentDevice.deviceID" required="" valid-deviceid list="discovery-list" aria-required="true" />
|
||||
<div ng-if="!editingDeviceNew()" class="well well-sm form-control text-monospace" style="height: auto;" select-on-click>{{currentDevice.deviceID}}</div>
|
||||
<div id="shareDeviceIdButtons" class="input-group-btn">
|
||||
<button type="button" class="btn btn-default" ng-click="copyToClipboard($event, currentDevice.deviceID)" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Copy' | translate }}">
|
||||
<button data-container="body" type="button" class="btn btn-default" ng-click="copyToClipboard($event, currentDevice.deviceID)" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Copy' | translate }}">
|
||||
<span class="fa fa-lg fa-clone"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" ng-click="shareDeviceIdDialog('email')" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Share by Email' | translate }}">
|
||||
<button data-container="body" type="button" class="btn btn-default" ng-click="shareDeviceIdDialog('email')" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Share by Email' | translate }}">
|
||||
<span class="fa fa-lg fa-envelope-o"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" ng-click="shareDeviceIdDialog('sms')" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Share by SMS' | translate }}">
|
||||
<button data-container="body" type="button" class="btn btn-default" ng-click="shareDeviceIdDialog('sms')" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Share by SMS' | translate }}">
|
||||
<span class="fa fa-lg fa-comments-o"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#idqr" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Show QR' | translate }}">
|
||||
<button data-container="body" type="button" class="btn btn-default" data-toggle="modal" data-target="#idqr" ng-disabled="editingDeviceNew() && !deviceEditor.deviceID.$valid" tooltip data-original-title="{{ 'Show QR' | translate }}">
|
||||
<span class="fa fa-lg fa-qrcode"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-if="currentFolder.syncXattrs">
|
||||
<div class="row" ng-if="currentFolder.syncXattrs || currentFolder.sendXattrs">
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
<label translate>Extended Attributes Filter</label>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<table class="table table-striped table-dynamic">
|
||||
<tr dir-paginate="e in failed.errors | itemsPerPage: failed.perpage" current-page="failed.page" total-items="model[failed.folder].pullErrors" pagination-id="failed">
|
||||
<td>{{e.path}}</td>
|
||||
<td><abbr tooltip data-original-title="{{e.error}}">{{e.error | lastErrorComponent}}</abbr></td>
|
||||
<td>{{e.error}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<dir-pagination-controls on-page-change="refreshFailed(newPageNumber, failed.perpage)" pagination-id="failed"></dir-pagination-controls>
|
||||
|
||||
@@ -713,6 +713,7 @@ func (*service) getSystemVersion(w http.ResponseWriter, _ *http.Request) {
|
||||
"version": build.Version,
|
||||
"codename": build.Codename,
|
||||
"longVersion": build.LongVersion,
|
||||
"extra": build.Extra,
|
||||
"os": runtime.GOOS,
|
||||
"arch": runtime.GOARCH,
|
||||
"isBeta": build.IsBeta,
|
||||
|
||||
@@ -39,7 +39,7 @@ func emitLoginAttempt(success bool, username, address string, evLogger events.Lo
|
||||
|
||||
func basicAuthAndSessionMiddleware(cookieName string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, next http.Handler, evLogger events.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if guiCfg.IsValidAPIKey(r.Header.Get("X-API-Key")) {
|
||||
if hasValidAPIKeyHeader(r, guiCfg) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func newCsrfManager(unique string, prefix string, apiKeyValidator apiKeyValidato
|
||||
|
||||
func (m *csrfManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Allow requests carrying a valid API key
|
||||
if m.apiKeyValidator.IsValidAPIKey(r.Header.Get("X-API-Key")) {
|
||||
if hasValidAPIKeyHeader(r, m.apiKeyValidator) {
|
||||
// Set the access-control-allow-origin header for CORS requests
|
||||
// since a valid API key has been provided
|
||||
w.Header().Add("Access-Control-Allow-Origin", "*")
|
||||
@@ -178,3 +178,14 @@ func (m *csrfManager) load() {
|
||||
m.tokens = append(m.tokens, s.Text())
|
||||
}
|
||||
}
|
||||
|
||||
func hasValidAPIKeyHeader(r *http.Request, validator apiKeyValidator) bool {
|
||||
if key := r.Header.Get("X-API-Key"); validator.IsValidAPIKey(key) {
|
||||
return true
|
||||
}
|
||||
if auth := r.Header.Get("Authorization"); strings.HasPrefix(strings.ToLower(auth), "bearer ") {
|
||||
bearerToken := auth[len("bearer "):]
|
||||
return validator.IsValidAPIKey(bearerToken)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ var (
|
||||
|
||||
func init() {
|
||||
dev1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
|
||||
apiCfg.GUIReturns(config.GUIConfiguration{APIKey: testAPIKey})
|
||||
apiCfg.GUIReturns(config.GUIConfiguration{APIKey: testAPIKey, RawAddress: "127.0.0.1:0"})
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -496,7 +496,9 @@ func TestAPIServiceRequests(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(cases[0].URL, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testHTTPRequest(t, baseURL, tc, testAPIKey)
|
||||
})
|
||||
}
|
||||
@@ -557,69 +559,132 @@ func TestHTTPLogin(t *testing.T) {
|
||||
|
||||
cfg := newMockedConfig()
|
||||
cfg.GUIReturns(config.GUIConfiguration{
|
||||
User: "üser",
|
||||
Password: "$2a$10$IdIZTxTg/dCNuNEGlmLynOjqg4B1FvDKuIV5e0BB3pnWVHNb8.GSq", // bcrypt of "räksmörgås" in UTF-8
|
||||
User: "üser",
|
||||
Password: "$2a$10$IdIZTxTg/dCNuNEGlmLynOjqg4B1FvDKuIV5e0BB3pnWVHNb8.GSq", // bcrypt of "räksmörgås" in UTF-8
|
||||
RawAddress: "127.0.0.1:0",
|
||||
APIKey: testAPIKey,
|
||||
})
|
||||
baseURL, cancel, err := startHTTP(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
// Verify rejection when not using authorization
|
||||
t.Run("no auth is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for unauthed request", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for unauthed request", resp.StatusCode)
|
||||
}
|
||||
t.Run("incorrect password is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.SetBasicAuth("üser", "rksmrgs")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for incorrect password", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
// Verify that incorrect password is rejected
|
||||
t.Run("incorrect username is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.SetBasicAuth("user", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for incorrect username", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
req.SetBasicAuth("üser", "rksmrgs")
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for incorrect password", resp.StatusCode)
|
||||
}
|
||||
t.Run("UTF-8 auth works", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.SetBasicAuth("üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for authed request (UTF-8)", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
// Verify that incorrect username is rejected
|
||||
t.Run("ISO-8859-1 auth work", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.SetBasicAuth("\xfcser", "r\xe4ksm\xf6rg\xe5s") // escaped ISO-8859-1
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for authed request (ISO-8859-1)", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
req.SetBasicAuth("user", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for incorrect username", resp.StatusCode)
|
||||
}
|
||||
t.Run("bad X-API-Key is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.Header.Set("X-API-Key", testAPIKey+"X")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for bad API key", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
// Verify that UTF-8 auth works
|
||||
t.Run("good X-API-Key is accepted", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.Header.Set("X-API-Key", testAPIKey)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for API key", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
req.SetBasicAuth("üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for authed request (UTF-8)", resp.StatusCode)
|
||||
}
|
||||
t.Run("bad Bearer is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+testAPIKey+"X")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Errorf("Unexpected non-401 return code %d for bad API key", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
// Verify that ISO-8859-1 auth
|
||||
|
||||
req.SetBasicAuth("\xfcser", "r\xe4ksm\xf6rg\xe5s") // escaped ISO-8859-1
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for authed request (ISO-8859-1)", resp.StatusCode)
|
||||
}
|
||||
t.Run("good Bearer is accepted", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+testAPIKey)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for API key", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) {
|
||||
@@ -681,7 +746,7 @@ func TestCSRFRequired(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting base URL:", err)
|
||||
}
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
cli := &http.Client{
|
||||
Timeout: time.Minute,
|
||||
@@ -709,42 +774,87 @@ func TestCSRFRequired(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Calling on /rest without a token should fail
|
||||
t.Run("/rest without a token should fail", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp, err := cli.Get(baseURL + "/rest/system/config")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Getting /rest/system/config without CSRF token should fail, not", resp.Status)
|
||||
}
|
||||
})
|
||||
|
||||
resp, err = cli.Get(baseURL + "/rest/system/config")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Getting /rest/system/config without CSRF token should fail, not", resp.Status)
|
||||
}
|
||||
t.Run("/rest with a token should succeed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("X-"+csrfTokenName, csrfTokenValue)
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatal("Getting /rest/system/config with CSRF token should succeed, not", resp.Status)
|
||||
}
|
||||
})
|
||||
|
||||
// Calling on /rest with a token should succeed
|
||||
t.Run("/rest with an incorrect API key should fail, X-API-Key version", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("X-API-Key", testAPIKey+"X")
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Getting /rest/system/config with incorrect API token should fail, not", resp.Status)
|
||||
}
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("X-"+csrfTokenName, csrfTokenValue)
|
||||
resp, err = cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatal("Getting /rest/system/config with CSRF token should succeed, not", resp.Status)
|
||||
}
|
||||
t.Run("/rest with an incorrect API key should fail, Bearer auth version", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+testAPIKey+"X")
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Getting /rest/system/config with incorrect API token should fail, not", resp.Status)
|
||||
}
|
||||
})
|
||||
|
||||
// Calling on /rest with the API key should succeed
|
||||
t.Run("/rest with the API key should succeed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("X-API-Key", testAPIKey)
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatal("Getting /rest/system/config with API key should succeed, not", resp.Status)
|
||||
}
|
||||
})
|
||||
|
||||
req, _ = http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("X-API-Key", testAPIKey)
|
||||
resp, err = cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatal("Getting /rest/system/config with API key should succeed, not", resp.Status)
|
||||
}
|
||||
t.Run("/rest with the API key as a bearer token should succeed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req, _ := http.NewRequest("GET", baseURL+"/rest/system/config", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+testAPIKey)
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting /rest/system/config:", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatal("Getting /rest/system/config with API key should succeed, not", resp.Status)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRandomString(t *testing.T) {
|
||||
@@ -943,30 +1053,31 @@ func TestHostCheck(t *testing.T) {
|
||||
t.Error("Incorrect host header, check disabled: expected 200 OK, not", resp.Status)
|
||||
}
|
||||
|
||||
// A server bound to a wildcard address also doesn't do the check
|
||||
if !testing.Short() {
|
||||
// A server bound to a wildcard address also doesn't do the check
|
||||
|
||||
cfg = newMockedConfig()
|
||||
cfg.GUIReturns(config.GUIConfiguration{
|
||||
RawAddress: "0.0.0.0:0",
|
||||
InsecureSkipHostCheck: true,
|
||||
})
|
||||
baseURL, cancel, err = startHTTP(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cancel()
|
||||
cfg = newMockedConfig()
|
||||
cfg.GUIReturns(config.GUIConfiguration{
|
||||
RawAddress: "0.0.0.0:0",
|
||||
})
|
||||
baseURL, cancel, err = startHTTP(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
// A request with a suspicious Host header should be allowed
|
||||
// A request with a suspicious Host header should be allowed
|
||||
|
||||
req, _ = http.NewRequest("GET", baseURL, nil)
|
||||
req.Host = "example.com"
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Error("Incorrect host header, wildcard bound: expected 200 OK, not", resp.Status)
|
||||
req, _ = http.NewRequest("GET", baseURL, nil)
|
||||
req.Host = "example.com"
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Error("Incorrect host header, wildcard bound: expected 200 OK, not", resp.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// This should all work over IPv6 as well
|
||||
|
||||
@@ -35,6 +35,7 @@ var (
|
||||
IsCandidate bool
|
||||
IsBeta bool
|
||||
LongVersion string
|
||||
Extra string
|
||||
|
||||
allowedVersionExp = regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z0-9]+)*(\.\d+)*(\+\d+-g[0-9a-f]+)?(-[^\s]+)?$`)
|
||||
|
||||
@@ -46,6 +47,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
const versionExtraAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-. "
|
||||
|
||||
func init() {
|
||||
if Version != "unknown-dev" {
|
||||
// If not a generic dev build, version string should come from git describe
|
||||
@@ -75,6 +78,7 @@ func setBuildData() {
|
||||
IsRelease = exp.MatchString(Version)
|
||||
IsCandidate = strings.Contains(Version, "-rc.")
|
||||
IsBeta = strings.Contains(Version, "-")
|
||||
Extra = filterString(os.Getenv("STVERSIONEXTRA"), versionExtraAllowedChars)
|
||||
|
||||
stamp, _ := strconv.Atoi(Stamp)
|
||||
Date = time.Unix(int64(stamp), 0)
|
||||
@@ -103,7 +107,22 @@ func TagsList() []string {
|
||||
tags = append(tags, strings.ToLower(envVar))
|
||||
}
|
||||
}
|
||||
if Extra != "" {
|
||||
tags = append(tags, Extra)
|
||||
}
|
||||
|
||||
sort.Strings(tags)
|
||||
return tags
|
||||
}
|
||||
|
||||
// filterString returns a copy of s with all characters not in allowedChars
|
||||
// removed.
|
||||
func filterString(s, allowedChars string) string {
|
||||
var res strings.Builder
|
||||
for _, c := range s {
|
||||
if strings.ContainsRune(allowedChars, c) {
|
||||
res.WriteRune(c)
|
||||
}
|
||||
}
|
||||
return res.String()
|
||||
}
|
||||
|
||||
@@ -35,3 +35,23 @@ func TestAllowedVersions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterString(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
filter string
|
||||
output string
|
||||
}{
|
||||
{"abcba", "abc", "abcba"},
|
||||
{"abcba", "ab", "abba"},
|
||||
{"abcba", "c", "c"},
|
||||
{"abcba", "!", ""},
|
||||
{"Foo (v1.5)", versionExtraAllowedChars, "Foo v1.5"},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
if out := filterString(c.input, c.filter); out != c.output {
|
||||
t.Errorf("%d: %q != %q", i, out, c.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
package connections
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var errNotInBuild = fmt.Errorf("%w: disabled at build time", errUnsupported)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -65,7 +65,7 @@ func (d *relayDialer) Dial(ctx context.Context, id protocol.DeviceID, uri *url.U
|
||||
return newInternalConn(tc, connTypeRelayClient, false, d.wanPriority), nil
|
||||
}
|
||||
|
||||
func (d *relayDialer) Priority(host string) int {
|
||||
func (d *relayDialer) Priority(_ string) int {
|
||||
return d.wanPriority
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user