Compare commits
80 Commits
v0.108.0-b
...
2499-rewri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1be2bab4d | ||
|
|
53cd9b7a1a | ||
|
|
d8d7a5c335 | ||
|
|
18a6066df5 | ||
|
|
18392943fa | ||
|
|
c2abedec70 | ||
|
|
bbdcc673a2 | ||
|
|
d3bf5fcb05 | ||
|
|
5a794411d9 | ||
|
|
8e058b8042 | ||
|
|
d76834f843 | ||
|
|
e7fc61a997 | ||
|
|
97af23b0af | ||
|
|
5480bed1f7 | ||
|
|
c5fb7e6b0d | ||
|
|
9efc381224 | ||
|
|
e481922d91 | ||
|
|
defde7d0fe | ||
|
|
0c03063c8a | ||
|
|
0ddd8e3dcc | ||
|
|
48cbc7bdf0 | ||
|
|
299371e0fd | ||
|
|
12f52f07c5 | ||
|
|
de08ef0077 | ||
|
|
cfab157146 | ||
|
|
ec05ee16fe | ||
|
|
c1b537c14b | ||
|
|
990311c9e0 | ||
|
|
526c358697 | ||
|
|
d77b743c7b | ||
|
|
e657899c32 | ||
|
|
fb3602853a | ||
|
|
2cf171f21e | ||
|
|
e56f465ad8 | ||
|
|
a8e80bc583 | ||
|
|
9a186d0a8a | ||
|
|
2d29455d7f | ||
|
|
8d453e75a4 | ||
|
|
de9f9e9eb8 | ||
|
|
fa49d74aa8 | ||
|
|
f0cf6cce9a | ||
|
|
55a0dec144 | ||
|
|
6d1adf74b1 | ||
|
|
6b607e982b | ||
|
|
01652e6ab2 | ||
|
|
09f88cf21d | ||
|
|
e6f8aeeebe | ||
|
|
fafd7a1e82 | ||
|
|
53a366ed46 | ||
|
|
9c4bed31e7 | ||
|
|
23c16a13aa | ||
|
|
36d90b152e | ||
|
|
08282dc4d9 | ||
|
|
93882d6860 | ||
|
|
167b112511 | ||
|
|
98af0e000e | ||
|
|
2bfdcbbc10 | ||
|
|
8fdbcc005c | ||
|
|
464fbf0b54 | ||
|
|
a7d02fa935 | ||
|
|
af8f64ac00 | ||
|
|
c139287787 | ||
|
|
fa0fd90ddd | ||
|
|
c5565a9e4e | ||
|
|
ac7634da37 | ||
|
|
746e9df727 | ||
|
|
3dd7393b3f | ||
|
|
9c9d6b48e3 | ||
|
|
9951d861d1 | ||
|
|
8a935d4ffb | ||
|
|
bf10f157ab | ||
|
|
15f5876e33 | ||
|
|
04c8e3b288 | ||
|
|
cebbb69a4c | ||
|
|
a272b61ed6 | ||
|
|
b86250737e | ||
|
|
a149d816d9 | ||
|
|
67d89660ca | ||
|
|
2a85d7dd7e | ||
|
|
68d13fcc2b |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -6,6 +6,11 @@
|
|||||||
website
|
website
|
||||||
'name': 'AdGuard filters issues'
|
'name': 'AdGuard filters issues'
|
||||||
'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github'
|
'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github'
|
||||||
|
- 'about': >
|
||||||
|
Please send requests for new blocked services and vetted filtering lists
|
||||||
|
to the Hostlists Registry repository
|
||||||
|
'name': 'Blocked services and vetted filtering rule lists: AdGuard Hostlists Registry'
|
||||||
|
'url': 'https://github.com/AdguardTeam/HostlistsRegistry'
|
||||||
- 'about': >
|
- 'about': >
|
||||||
Please use GitHub Discussions for questions
|
Please use GitHub Discussions for questions
|
||||||
'name': 'Q&A Discussions'
|
'name': 'Q&A Discussions'
|
||||||
|
|||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
'name': 'build'
|
'name': 'build'
|
||||||
|
|
||||||
'env':
|
'env':
|
||||||
'GO_VERSION': '1.18.7'
|
'GO_VERSION': '1.18.9'
|
||||||
'NODE_VERSION': '14'
|
'NODE_VERSION': '14'
|
||||||
|
|
||||||
'on':
|
'on':
|
||||||
|
|||||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
'name': 'lint'
|
'name': 'lint'
|
||||||
|
|
||||||
'env':
|
'env':
|
||||||
'GO_VERSION': '1.18.7'
|
'GO_VERSION': '1.18.9'
|
||||||
|
|
||||||
'on':
|
'on':
|
||||||
'push':
|
'push':
|
||||||
|
|||||||
188
CHANGELOG.md
188
CHANGELOG.md
@@ -12,11 +12,151 @@ and this project adheres to
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
## [v0.108.0] - TBA (APPROX.)
|
## [v0.108.0] - TBA
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
## [v0.107.22] - 2222-12-28 (APPROX.)
|
||||||
|
|
||||||
|
See also the [v0.107.22 GitHub milestone][ms-v0.107.22].
|
||||||
|
|
||||||
|
[ms-v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/milestone/58?closed=1
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.107.21] - 2122-12-15
|
||||||
|
|
||||||
|
See also the [v0.107.21 GitHub milestone][ms-v0.107.21].
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- The URLs of the default filters for new installations are synchronized to
|
||||||
|
those introduced in v0.107.20 ([#5238]).
|
||||||
|
|
||||||
|
**NOTE:** Some users may need to re-add the lists from the vetted filter lists
|
||||||
|
to update the URLs to the new ones. Custom filters added by users themselves
|
||||||
|
do not require re-adding.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `AdGuardHome --update` freezing when another instance of AdGuard Home is
|
||||||
|
running ([#4223], [#5191]).
|
||||||
|
- The `--update` flag performing an update even with the same version.
|
||||||
|
- Failing HTTPS redirection on saving the encryption settings ([#4898]).
|
||||||
|
- Zeroing rules counter of erroneusly edited filtering rule lists ([#5290]).
|
||||||
|
- Filters updating strategy, which could sometimes lead to use of broken or
|
||||||
|
incompletely downloaded lists ([#5258]).
|
||||||
|
- Errors popping up during updates of settings, which could sometimes cause the
|
||||||
|
server to stop responding ([#5251]).
|
||||||
|
|
||||||
|
[#4898]: https://github.com/AdguardTeam/AdGuardHome/issues/4898
|
||||||
|
[#5191]: https://github.com/AdguardTeam/AdGuardHome/issues/5191
|
||||||
|
[#5238]: https://github.com/AdguardTeam/AdGuardHome/issues/5238
|
||||||
|
[#5251]: https://github.com/AdguardTeam/AdGuardHome/issues/5251
|
||||||
|
[#5258]: https://github.com/AdguardTeam/AdGuardHome/issues/5258
|
||||||
|
[#5290]: https://github.com/AdguardTeam/AdGuardHome/issues/5290
|
||||||
|
|
||||||
|
[ms-v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/milestone/57?closed=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.107.20] - 2022-12-07
|
||||||
|
|
||||||
|
See also the [v0.107.20 GitHub milestone][ms-v0.107.20].
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Go version has been updated to prevent the possibility of exploiting the
|
||||||
|
CVE-2022-41717 and CVE-2022-41720 Go vulnerabilities fixed in [Go
|
||||||
|
1.18.9][go-1.18.9].
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The ability to clear the DNS cache ([#5190]).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- DHCP server initialization errors are now logged at debug level if the server
|
||||||
|
itself disabled ([#4944]).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Wrong validation error messages on the DHCP configuration page ([#5208]).
|
||||||
|
- Slow upstream checks making the API unresponsive ([#5193]).
|
||||||
|
- The TLS initialization errors preventing AdGuard Home from starting ([#5189]).
|
||||||
|
Instead, AdGuard Home disables encryption and shows an error message on the
|
||||||
|
encryption settings page in the UI, which was the intended previous behavior.
|
||||||
|
- URLs of some vetted blocklists.
|
||||||
|
|
||||||
|
[#4944]: https://github.com/AdguardTeam/AdGuardHome/issues/4944
|
||||||
|
[#5189]: https://github.com/AdguardTeam/AdGuardHome/issues/5189
|
||||||
|
[#5190]: https://github.com/AdguardTeam/AdGuardHome/issues/5190
|
||||||
|
[#5193]: https://github.com/AdguardTeam/AdGuardHome/issues/5193
|
||||||
|
[#5208]: https://github.com/AdguardTeam/AdGuardHome/issues/5208
|
||||||
|
|
||||||
|
[go-1.18.9]: https://groups.google.com/g/golang-announce/c/L_3rmdT0BMU
|
||||||
|
[ms-v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/milestone/56?closed=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.107.19] - 2022-11-23
|
||||||
|
|
||||||
|
See also the [v0.107.19 GitHub milestone][ms-v0.107.19].
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The ability to block popular Mastodon instances
|
||||||
|
([AdguardTeam/HostlistsRegistry#100]).
|
||||||
|
- The new `--update` command-line option, which allows updating AdGuard Home
|
||||||
|
silently ([#4223]).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Minor UI changes.
|
||||||
|
|
||||||
|
[#4223]: https://github.com/AdguardTeam/AdGuardHome/issues/4223
|
||||||
|
|
||||||
|
[ms-v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/milestone/55?closed=1
|
||||||
|
|
||||||
|
[AdguardTeam/HostlistsRegistry#100]: https://github.com/AdguardTeam/HostlistsRegistry/pull/100
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.107.18] - 2022-11-08
|
||||||
|
|
||||||
|
See also the [v0.107.18 GitHub milestone][ms-v0.107.18].
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Crash on some systems when domains from system hosts files are processed
|
||||||
|
([#5089]).
|
||||||
|
|
||||||
|
[#5089]: https://github.com/AdguardTeam/AdGuardHome/issues/5089
|
||||||
|
|
||||||
|
[ms-v0.107.18]: https://github.com/AdguardTeam/AdGuardHome/milestone/54?closed=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [v0.107.17] - 2022-11-02
|
||||||
|
|
||||||
|
See also the [v0.107.17 GitHub milestone][ms-v0.107.17].
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Go version has been updated to prevent the possibility of exploiting the
|
||||||
|
CVE-2022-41716 Go vulnerability fixed in [Go 1.18.8][go-1.18.8].
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The warning message when adding a certificate having no IP addresses
|
||||||
|
([#4898]).
|
||||||
|
- Several new blockable services ([#3972]). Those will now be more in sync with
|
||||||
|
the services that are already blockable in AdGuard DNS.
|
||||||
|
- A new HTTP API, `GET /control/blocked_services/all`, that lists all available
|
||||||
|
blocked services and their data, such as SVG icons ([#3972]).
|
||||||
- The new optional `tls.override_tls_ciphers` property, which allows
|
- The new optional `tls.override_tls_ciphers` property, which allows
|
||||||
overriding TLS ciphers used by AdGuard Home ([#4925], [#4990]).
|
overriding TLS ciphers used by AdGuard Home ([#4925], [#4990]).
|
||||||
- The ability to serve DNS on link-local IPv6 addresses ([#2926]).
|
- The ability to serve DNS on link-local IPv6 addresses ([#2926]).
|
||||||
@@ -26,10 +166,20 @@ and this project adheres to
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- DNS-over-TLS resolvers aren't returned anymore when the configured TLS
|
||||||
|
certificate contains no IP addresses ([#4927]).
|
||||||
- Responses with `SERVFAIL` code are now cached for at least 30 seconds.
|
- Responses with `SERVFAIL` code are now cached for at least 30 seconds.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
- The `GET /control/blocked_services/services` HTTP API; use the new
|
||||||
|
`GET /control/blocked_services/all` API instead ([#3972]).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- ClientIDs not working when using DNS-over-HTTPS with HTTP/3.
|
||||||
|
- Editing the URL of an enabled rule list also includes validation of the filter
|
||||||
|
contents preventing from saving a bad one ([#4916]).
|
||||||
- The default value of `dns.cache_size` accidentally set to 0 has now been
|
- The default value of `dns.cache_size` accidentally set to 0 has now been
|
||||||
reverted to 4 MiB ([#5010]).
|
reverted to 4 MiB ([#5010]).
|
||||||
- Responses for which the DNSSEC validation had explicitly been omitted aren't
|
- Responses for which the DNSSEC validation had explicitly been omitted aren't
|
||||||
@@ -38,6 +188,9 @@ and this project adheres to
|
|||||||
|
|
||||||
[#2926]: https://github.com/AdguardTeam/AdGuardHome/issues/2926
|
[#2926]: https://github.com/AdguardTeam/AdGuardHome/issues/2926
|
||||||
[#3418]: https://github.com/AdguardTeam/AdGuardHome/issues/3418
|
[#3418]: https://github.com/AdguardTeam/AdGuardHome/issues/3418
|
||||||
|
[#3972]: https://github.com/AdguardTeam/AdGuardHome/issues/3972
|
||||||
|
[#4898]: https://github.com/AdguardTeam/AdGuardHome/issues/4898
|
||||||
|
[#4916]: https://github.com/AdguardTeam/AdGuardHome/issues/4916
|
||||||
[#4925]: https://github.com/AdguardTeam/AdGuardHome/issues/4925
|
[#4925]: https://github.com/AdguardTeam/AdGuardHome/issues/4925
|
||||||
[#4942]: https://github.com/AdguardTeam/AdGuardHome/issues/4942
|
[#4942]: https://github.com/AdguardTeam/AdGuardHome/issues/4942
|
||||||
[#4986]: https://github.com/AdguardTeam/AdGuardHome/issues/4986
|
[#4986]: https://github.com/AdguardTeam/AdGuardHome/issues/4986
|
||||||
@@ -45,17 +198,9 @@ and this project adheres to
|
|||||||
[#4993]: https://github.com/AdguardTeam/AdGuardHome/issues/4993
|
[#4993]: https://github.com/AdguardTeam/AdGuardHome/issues/4993
|
||||||
[#5010]: https://github.com/AdguardTeam/AdGuardHome/issues/5010
|
[#5010]: https://github.com/AdguardTeam/AdGuardHome/issues/5010
|
||||||
|
|
||||||
[clientid]: https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#clientid
|
[clientid]: https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#clientid
|
||||||
|
[go-1.18.8]: https://groups.google.com/g/golang-announce/c/mbHY1UY3BaM
|
||||||
|
[ms-v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/milestone/53?closed=1
|
||||||
|
|
||||||
<!--
|
|
||||||
## [v0.107.17] - 2022-11-02 (APPROX.)
|
|
||||||
|
|
||||||
See also the [v0.107.17 GitHub milestone][ms-v0.107.17].
|
|
||||||
|
|
||||||
[ms-v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/milestone/52?closed=1
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +209,7 @@ See also the [v0.107.17 GitHub milestone][ms-v0.107.17].
|
|||||||
This is a security update. There is no GitHub milestone, since no GitHub issues
|
This is a security update. There is no GitHub milestone, since no GitHub issues
|
||||||
were resolved.
|
were resolved.
|
||||||
|
|
||||||
## Security
|
### Security
|
||||||
|
|
||||||
- Go version has been updated to prevent the possibility of exploiting the
|
- Go version has been updated to prevent the possibility of exploiting the
|
||||||
CVE-2022-2879, CVE-2022-2880, and CVE-2022-41715 Go vulnerabilities fixed in
|
CVE-2022-2879, CVE-2022-2880, and CVE-2022-41715 Go vulnerabilities fixed in
|
||||||
@@ -798,7 +943,7 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
|
|||||||
- Query log search now supports internationalized domains ([#3012]).
|
- Query log search now supports internationalized domains ([#3012]).
|
||||||
- Internationalized domains are now shown decoded in the query log with the
|
- Internationalized domains are now shown decoded in the query log with the
|
||||||
original encoded version shown in request details ([#3013]).
|
original encoded version shown in request details ([#3013]).
|
||||||
- When /etc/hosts-type rules have several IPs for one host, all IPs are now
|
- When `/etc/hosts`-type rules have several IPs for one host, all IPs are now
|
||||||
returned instead of only the first one ([#1381]).
|
returned instead of only the first one ([#1381]).
|
||||||
- Property `rlimit_nofile` is now in the `os` object of the configuration
|
- Property `rlimit_nofile` is now in the `os` object of the configuration
|
||||||
file, together with the new `group` and `user` properties ([#2763]).
|
file, together with the new `group` and `user` properties ([#2763]).
|
||||||
@@ -1056,7 +1201,7 @@ See also the [v0.106.0 GitHub milestone][ms-v0.106.0].
|
|||||||
- Hostname uniqueness validation in the DHCP server ([#2952]).
|
- Hostname uniqueness validation in the DHCP server ([#2952]).
|
||||||
- Hostname generating for DHCP clients which don't provide their own ([#2723]).
|
- Hostname generating for DHCP clients which don't provide their own ([#2723]).
|
||||||
- New flag `--no-etc-hosts` to disable client domain name lookups in the
|
- New flag `--no-etc-hosts` to disable client domain name lookups in the
|
||||||
operating system's /etc/hosts files ([#1947]).
|
operating system's `/etc/hosts` files ([#1947]).
|
||||||
- The ability to set up custom upstreams to resolve PTR queries for local
|
- The ability to set up custom upstreams to resolve PTR queries for local
|
||||||
addresses and to disable the automatic resolving of clients' addresses
|
addresses and to disable the automatic resolving of clients' addresses
|
||||||
([#2704]).
|
([#2704]).
|
||||||
@@ -1373,11 +1518,16 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
|
|||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.17...HEAD
|
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.22...HEAD
|
||||||
[v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.16...v0.107.17
|
[v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.21...v0.107.22
|
||||||
-->
|
-->
|
||||||
|
|
||||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.16...HEAD
|
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.21...HEAD
|
||||||
|
[v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.20...v0.107.21
|
||||||
|
[v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.19...v0.107.20
|
||||||
|
[v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.18...v0.107.19
|
||||||
|
[v0.107.18]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.17...v0.107.18
|
||||||
|
[v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.16...v0.107.17
|
||||||
[v0.107.16]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.15...v0.107.16
|
[v0.107.16]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.15...v0.107.16
|
||||||
[v0.107.15]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.14...v0.107.15
|
[v0.107.15]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.14...v0.107.15
|
||||||
[v0.107.14]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.13...v0.107.14
|
[v0.107.14]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.13...v0.107.14
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# Make sure to sync any changes with the branch overrides below.
|
# Make sure to sync any changes with the branch overrides below.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'edge'
|
'channel': 'edge'
|
||||||
'dockerGo': 'adguard/golang-ubuntu:5.2'
|
'dockerGo': 'adguard/golang-ubuntu:5.4'
|
||||||
|
|
||||||
'stages':
|
'stages':
|
||||||
- 'Build frontend':
|
- 'Build frontend':
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
# need to build a few of these.
|
# need to build a few of these.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'beta'
|
'channel': 'beta'
|
||||||
'dockerGo': 'adguard/golang-ubuntu:5.2'
|
'dockerGo': 'adguard/golang-ubuntu:5.4'
|
||||||
# release-vX.Y.Z branches are the branches from which the actual final release
|
# release-vX.Y.Z branches are the branches from which the actual final release
|
||||||
# is built.
|
# is built.
|
||||||
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
|
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
|
||||||
@@ -337,4 +337,4 @@
|
|||||||
# are the ones that actually get released.
|
# are the ones that actually get released.
|
||||||
'variables':
|
'variables':
|
||||||
'channel': 'release'
|
'channel': 'release'
|
||||||
'dockerGo': 'adguard/golang-ubuntu:5.2'
|
'dockerGo': 'adguard/golang-ubuntu:5.4'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
'key': 'AHBRTSPECS'
|
'key': 'AHBRTSPECS'
|
||||||
'name': 'AdGuard Home - Build and run tests'
|
'name': 'AdGuard Home - Build and run tests'
|
||||||
'variables':
|
'variables':
|
||||||
'dockerGo': 'adguard/golang-ubuntu:5.2'
|
'dockerGo': 'adguard/golang-ubuntu:5.4'
|
||||||
|
|
||||||
'stages':
|
'stages':
|
||||||
- 'Tests':
|
- 'Tests':
|
||||||
|
|||||||
@@ -392,6 +392,7 @@
|
|||||||
"encryption_issuer": "المصدر",
|
"encryption_issuer": "المصدر",
|
||||||
"encryption_hostnames": "اسم المستضيف",
|
"encryption_hostnames": "اسم المستضيف",
|
||||||
"encryption_reset": "هل أنت متأكد أنك تريد إعادة تعيين إعدادات التشفير؟",
|
"encryption_reset": "هل أنت متأكد أنك تريد إعادة تعيين إعدادات التشفير؟",
|
||||||
|
"encryption_warning": "تحذير",
|
||||||
"topline_expiring_certificate": "شهادة SSL الخاصة بك على وشك الانتهاء. قم بتحديث <0>إعدادات التشفير</0>.",
|
"topline_expiring_certificate": "شهادة SSL الخاصة بك على وشك الانتهاء. قم بتحديث <0>إعدادات التشفير</0>.",
|
||||||
"topline_expired_certificate": "انتهت صلاحية شهادة SSL الخاصة بك. قم بتحديث <0>إعدادات التشفير</0>.",
|
"topline_expired_certificate": "انتهت صلاحية شهادة SSL الخاصة بك. قم بتحديث <0>إعدادات التشفير</0>.",
|
||||||
"form_error_port_range": "أدخل رقم المنفذ في النطاق 80-65535",
|
"form_error_port_range": "أدخل رقم المنفذ في النطاق 80-65535",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Налады DHCP IPv6",
|
"dhcp_ipv6_settings": "Налады DHCP IPv6",
|
||||||
"form_error_required": "Абавязковае поле",
|
"form_error_required": "Абавязковае поле",
|
||||||
"form_error_ip4_format": "Няслушны IPv4-адрас",
|
"form_error_ip4_format": "Няслушны IPv4-адрас",
|
||||||
"form_error_ip4_range_start_format": "Няслушны IPv4-адрас пачатку дыяпазону",
|
|
||||||
"form_error_ip4_range_end_format": "Няслушны IPv4-адрас канца дыяпазону",
|
|
||||||
"form_error_ip4_gateway_format": "Няслушны IPv4-адрас шлюза",
|
"form_error_ip4_gateway_format": "Няслушны IPv4-адрас шлюза",
|
||||||
"form_error_ip6_format": "Няслушны IPv6-адрас",
|
"form_error_ip6_format": "Няслушны IPv6-адрас",
|
||||||
"form_error_ip_format": "Няслушны IP-адрас",
|
"form_error_ip_format": "Няслушны IP-адрас",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Павінна быць па-за дыяпазонам «{{start}}»-«{{end}}»",
|
"out_of_range_error": "Павінна быць па-за дыяпазонам «{{start}}»-«{{end}}»",
|
||||||
"lower_range_start_error": "Павінна быць менш за пачатак дыяпазону",
|
"lower_range_start_error": "Павінна быць менш за пачатак дыяпазону",
|
||||||
"greater_range_start_error": "Павінна быць больш за пачатак дыяпазону",
|
"greater_range_start_error": "Павінна быць больш за пачатак дыяпазону",
|
||||||
"greater_range_end_error": "Павінна быць больш за канец дыяпазону",
|
|
||||||
"subnet_error": "Адрасы павінны быць усярэдзіне адной падсеткі",
|
"subnet_error": "Адрасы павінны быць усярэдзіне адной падсеткі",
|
||||||
"gateway_or_subnet_invalid": "Некарэктная маска падсеткі",
|
"gateway_or_subnet_invalid": "Некарэктная маска падсеткі",
|
||||||
"dhcp_form_gateway_input": "IP-адрас шлюза",
|
"dhcp_form_gateway_input": "IP-адрас шлюза",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Выдавец",
|
"encryption_issuer": "Выдавец",
|
||||||
"encryption_hostnames": "Імёны хастоў",
|
"encryption_hostnames": "Імёны хастоў",
|
||||||
"encryption_reset": "Вы ўпэўнены, што хочаце скінуць налады шыфравання?",
|
"encryption_reset": "Вы ўпэўнены, што хочаце скінуць налады шыфравання?",
|
||||||
|
"encryption_warning": "Папярэджанне",
|
||||||
"topline_expiring_certificate": "Ваш SSL-сертыфікат хутка мінае. Абновіце <0>Налады шыфравання</0>.",
|
"topline_expiring_certificate": "Ваш SSL-сертыфікат хутка мінае. Абновіце <0>Налады шыфравання</0>.",
|
||||||
"topline_expired_certificate": "Ваш SSL-сертыфікат мінуў. Абновіце <0>Налады шыфравання</0>.",
|
"topline_expired_certificate": "Ваш SSL-сертыфікат мінуў. Абновіце <0>Налады шыфравання</0>.",
|
||||||
"form_error_port_range": "Увядзіце нумар порта з інтэрвалу 80-65535",
|
"form_error_port_range": "Увядзіце нумар порта з інтэрвалу 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Бяспечны інтэрнэт",
|
"safe_browsing": "Бяспечны інтэрнэт",
|
||||||
"served_from_cache": "{{value}} <i>(атрымана з кэша)</i>",
|
"served_from_cache": "{{value}} <i>(атрымана з кэша)</i>",
|
||||||
"form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў",
|
"form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў",
|
||||||
"anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яго ў <1>Агульных наладах</1> ."
|
"anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яго ў <1>Агульных наладах</1> .",
|
||||||
|
"confirm_dns_cache_clear": "Вы ўпэўнены, што хочаце ачысціць кэш DNS?",
|
||||||
|
"cache_cleared": "Кэш DNS паспяхова ачышчаны",
|
||||||
|
"clear_cache": "Ачысціць кэш"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,6 +244,7 @@
|
|||||||
"encryption_issuer": "Изпълнител",
|
"encryption_issuer": "Изпълнител",
|
||||||
"encryption_hostnames": "Имена на хоста",
|
"encryption_hostnames": "Имена на хоста",
|
||||||
"encryption_reset": "Сигурни ли сте че искате да изтриете настройките за криптиране?",
|
"encryption_reset": "Сигурни ли сте че искате да изтриете настройките за криптиране?",
|
||||||
|
"encryption_warning": "Внимание",
|
||||||
"topline_expiring_certificate": "Вашият SSL сертификат изтича. Обнови <0>Настройки за криптиране</0>.",
|
"topline_expiring_certificate": "Вашият SSL сертификат изтича. Обнови <0>Настройки за криптиране</0>.",
|
||||||
"topline_expired_certificate": "Вашият SSL сертификат е изтекъл. Обнови <0>Настройки за криптиране</0>.",
|
"topline_expired_certificate": "Вашият SSL сертификат е изтекъл. Обнови <0>Настройки за криптиране</0>.",
|
||||||
"form_error_port_range": "Въведете порт в диапазона 80-65535",
|
"form_error_port_range": "Въведете порт в диапазона 80-65535",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Nastavení DHCP IPv6",
|
"dhcp_ipv6_settings": "Nastavení DHCP IPv6",
|
||||||
"form_error_required": "Povinné pole",
|
"form_error_required": "Povinné pole",
|
||||||
"form_error_ip4_format": "Neplatná adresa IPv4",
|
"form_error_ip4_format": "Neplatná adresa IPv4",
|
||||||
"form_error_ip4_range_start_format": "Neplatná adresa IPv4 na začátku rozsahu",
|
|
||||||
"form_error_ip4_range_end_format": "Neplatná adresa IPv4 na konci rozsahu",
|
|
||||||
"form_error_ip4_gateway_format": "Neplatná adresa IPv4 brány",
|
"form_error_ip4_gateway_format": "Neplatná adresa IPv4 brány",
|
||||||
"form_error_ip6_format": "Neplatná adresa IPv6",
|
"form_error_ip6_format": "Neplatná adresa IPv6",
|
||||||
"form_error_ip_format": "Neplatná IP adresa",
|
"form_error_ip_format": "Neplatná IP adresa",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Musí být mimo rozsah \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Musí být mimo rozsah \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Musí být menší než začátek rozsahu",
|
"lower_range_start_error": "Musí být menší než začátek rozsahu",
|
||||||
"greater_range_start_error": "Musí být větší než začátek rozsahu",
|
"greater_range_start_error": "Musí být větší než začátek rozsahu",
|
||||||
"greater_range_end_error": "Musí být větší než konec rozsahu",
|
|
||||||
"subnet_error": "Adresy musí být v jedné podsíti",
|
"subnet_error": "Adresy musí být v jedné podsíti",
|
||||||
"gateway_or_subnet_invalid": "Neplatná maska podsítě",
|
"gateway_or_subnet_invalid": "Neplatná maska podsítě",
|
||||||
"dhcp_form_gateway_input": "IP brána",
|
"dhcp_form_gateway_input": "IP brána",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Vydavatel",
|
"encryption_issuer": "Vydavatel",
|
||||||
"encryption_hostnames": "Názvy hostitelů",
|
"encryption_hostnames": "Názvy hostitelů",
|
||||||
"encryption_reset": "Opravdu chcete obnovit nastavení šifrování?",
|
"encryption_reset": "Opravdu chcete obnovit nastavení šifrování?",
|
||||||
|
"encryption_warning": "Varování",
|
||||||
"topline_expiring_certificate": "Váš SSL certifikát brzy vyprší. Aktualizujte <0>Nastavení šifrování</0>.",
|
"topline_expiring_certificate": "Váš SSL certifikát brzy vyprší. Aktualizujte <0>Nastavení šifrování</0>.",
|
||||||
"topline_expired_certificate": "Váš SSL certifikát vypršel. Aktualizujte <0>Nastavení šifrování</0>.",
|
"topline_expired_certificate": "Váš SSL certifikát vypršel. Aktualizujte <0>Nastavení šifrování</0>.",
|
||||||
"form_error_port_range": "Zadejte číslo portu v rozmezí 80-65535",
|
"form_error_port_range": "Zadejte číslo portu v rozmezí 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Bezpečné prohlížení",
|
"safe_browsing": "Bezpečné prohlížení",
|
||||||
"served_from_cache": "{{value}} <i>(převzato z mezipaměti)</i>",
|
"served_from_cache": "{{value}} <i>(převzato z mezipaměti)</i>",
|
||||||
"form_error_password_length": "Heslo musí být alespoň {{value}} znaků dlouhé",
|
"form_error_password_length": "Heslo musí být alespoň {{value}} znaků dlouhé",
|
||||||
"anonymizer_notification": "<0>Poznámka:</0> Anonymizace IP je zapnuta. Můžete ji vypnout v <1>Obecných nastaveních</1>."
|
"anonymizer_notification": "<0>Poznámka:</0> Anonymizace IP je zapnuta. Můžete ji vypnout v <1>Obecných nastaveních</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Opravdu chcete vymazat mezipaměť DNS?",
|
||||||
|
"cache_cleared": "Mezipaměť DNS úspěšně vymazána",
|
||||||
|
"clear_cache": "Vymazat mezipaměť"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6-indstillinger",
|
"dhcp_ipv6_settings": "DHCP IPv6-indstillinger",
|
||||||
"form_error_required": "Obligatorisk felt",
|
"form_error_required": "Obligatorisk felt",
|
||||||
"form_error_ip4_format": "Ugyldig IPv4-adresse",
|
"form_error_ip4_format": "Ugyldig IPv4-adresse",
|
||||||
"form_error_ip4_range_start_format": "Ugyldig IPv4-startadresse for området",
|
|
||||||
"form_error_ip4_range_end_format": "Ugyldig IPv4-slutadresse for området",
|
|
||||||
"form_error_ip4_gateway_format": "Ugyldig IPv4 gateway-adresse",
|
"form_error_ip4_gateway_format": "Ugyldig IPv4 gateway-adresse",
|
||||||
"form_error_ip6_format": "Ugyldig IPv6-adresse",
|
"form_error_ip6_format": "Ugyldig IPv6-adresse",
|
||||||
"form_error_ip_format": "Ugyldig IP-adresse",
|
"form_error_ip_format": "Ugyldig IP-adresse",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "Skal være uden for området \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Skal være uden for området \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Skal være mindre end starten på området",
|
"lower_range_start_error": "Skal være mindre end starten på området",
|
||||||
"greater_range_start_error": "Skal være større end starten på området",
|
"greater_range_start_error": "Skal være større end starten på området",
|
||||||
"greater_range_end_error": "Skal være større end områdeslutning",
|
|
||||||
"subnet_error": "Adresser ska være i ét undernet",
|
"subnet_error": "Adresser ska være i ét undernet",
|
||||||
"gateway_or_subnet_invalid": "Undernetmaske ugyldig",
|
"gateway_or_subnet_invalid": "Ugyldig undernetmaske",
|
||||||
"dhcp_form_gateway_input": "Gateway IP",
|
"dhcp_form_gateway_input": "Gateway IP",
|
||||||
"dhcp_form_subnet_input": "Undernetmaske",
|
"dhcp_form_subnet_input": "Undernetmaske",
|
||||||
"dhcp_form_range_title": "Interval af IP-adresser",
|
"dhcp_form_range_title": "Interval af IP-adresser",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Udsteder",
|
"encryption_issuer": "Udsteder",
|
||||||
"encryption_hostnames": "Værtsnavne",
|
"encryption_hostnames": "Værtsnavne",
|
||||||
"encryption_reset": "Sikker på, at du vil nulstille krypteringsindstillingerne?",
|
"encryption_reset": "Sikker på, at du vil nulstille krypteringsindstillingerne?",
|
||||||
|
"encryption_warning": "Advarsel",
|
||||||
"topline_expiring_certificate": "Dit SSL-certifikat er ved at udløbe. Opdatér <0>Krypteringsindstillinger</0>.",
|
"topline_expiring_certificate": "Dit SSL-certifikat er ved at udløbe. Opdatér <0>Krypteringsindstillinger</0>.",
|
||||||
"topline_expired_certificate": "Dit SSL-certifikat er udløbet. Opdatér <0>Krypteringsindstillinger</0>.",
|
"topline_expired_certificate": "Dit SSL-certifikat er udløbet. Opdatér <0>Krypteringsindstillinger</0>.",
|
||||||
"form_error_port_range": "Angiv portnummer i intervallet 80-65535",
|
"form_error_port_range": "Angiv portnummer i intervallet 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Sikker Browsing",
|
"safe_browsing": "Sikker Browsing",
|
||||||
"served_from_cache": "{{value}} <i>(leveret fra cache)</i>",
|
"served_from_cache": "{{value}} <i>(leveret fra cache)</i>",
|
||||||
"form_error_password_length": "Adgangskoden skal udgøre mindst {{value}} tegn.",
|
"form_error_password_length": "Adgangskoden skal udgøre mindst {{value}} tegn.",
|
||||||
"anonymizer_notification": "<0>Bemærk:</0> IP-anonymisering er aktiveret. Det kan deaktiveres via <1>Generelle indstillinger</1>."
|
"anonymizer_notification": "<0>Bemærk:</0> IP-anonymisering er aktiveret. Det kan deaktiveres via <1>Generelle indstillinger</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Sikker på, at DNS-cache skal ryddes?",
|
||||||
|
"cache_cleared": "DNS-cache hermed ryddet",
|
||||||
|
"clear_cache": "Ryd cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP-IPv6-Einstellungen",
|
"dhcp_ipv6_settings": "DHCP-IPv6-Einstellungen",
|
||||||
"form_error_required": "Pflichtfeld",
|
"form_error_required": "Pflichtfeld",
|
||||||
"form_error_ip4_format": "Ungültige IPv4-Adresse",
|
"form_error_ip4_format": "Ungültige IPv4-Adresse",
|
||||||
"form_error_ip4_range_start_format": "Ungültiger Bereichsbeginn der IPv4-Adresse",
|
|
||||||
"form_error_ip4_range_end_format": "Ungültiges Bereichsende der IPv4-Adresse",
|
|
||||||
"form_error_ip4_gateway_format": "Ungültige IPv4-Adresse des Gateways",
|
"form_error_ip4_gateway_format": "Ungültige IPv4-Adresse des Gateways",
|
||||||
"form_error_ip6_format": "Ungültige IPv6-Adresse",
|
"form_error_ip6_format": "Ungültige IPv6-Adresse",
|
||||||
"form_error_ip_format": "Ungültige IP-Adresse",
|
"form_error_ip_format": "Ungültige IP-Adresse",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Muss außerhalb des Bereichs „{{start}}“-„{{end}}“ liegen",
|
"out_of_range_error": "Muss außerhalb des Bereichs „{{start}}“-„{{end}}“ liegen",
|
||||||
"lower_range_start_error": "Muss niedriger als der Bereichsbeginn sein",
|
"lower_range_start_error": "Muss niedriger als der Bereichsbeginn sein",
|
||||||
"greater_range_start_error": "Muss größer als der Bereichsbeginn sein",
|
"greater_range_start_error": "Muss größer als der Bereichsbeginn sein",
|
||||||
"greater_range_end_error": "Muss größer als das Bereichsende sein",
|
|
||||||
"subnet_error": "Die Adressen müssen innerhalb eines Subnetzes liegen",
|
"subnet_error": "Die Adressen müssen innerhalb eines Subnetzes liegen",
|
||||||
"gateway_or_subnet_invalid": "Ungültige Subnetzmaske",
|
"gateway_or_subnet_invalid": "Ungültige Subnetzmaske",
|
||||||
"dhcp_form_gateway_input": "Gateway-IP",
|
"dhcp_form_gateway_input": "Gateway-IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Ausgestellt von",
|
"encryption_issuer": "Ausgestellt von",
|
||||||
"encryption_hostnames": "Hostnamen",
|
"encryption_hostnames": "Hostnamen",
|
||||||
"encryption_reset": "Möchten Sie die Verschlüsselungseinstellungen wirklich zurücksetzen?",
|
"encryption_reset": "Möchten Sie die Verschlüsselungseinstellungen wirklich zurücksetzen?",
|
||||||
|
"encryption_warning": "Warnhinweis",
|
||||||
"topline_expiring_certificate": "Ihr SSL-Zertifikat läuft demnächst ab. Aktualisieren Sie Ihre <0>Verschlüsselungseinstellungen</0>.",
|
"topline_expiring_certificate": "Ihr SSL-Zertifikat läuft demnächst ab. Aktualisieren Sie Ihre <0>Verschlüsselungseinstellungen</0>.",
|
||||||
"topline_expired_certificate": "Ihr SSL-Zertifikat ist abgelaufen. Aktualisieren Sie Ihre <0>Verschlüsselungseinstellungen</0>.",
|
"topline_expired_certificate": "Ihr SSL-Zertifikat ist abgelaufen. Aktualisieren Sie Ihre <0>Verschlüsselungseinstellungen</0>.",
|
||||||
"form_error_port_range": "Geben Sie die Portnummer zwischen 80 und 65535 ein",
|
"form_error_port_range": "Geben Sie die Portnummer zwischen 80 und 65535 ein",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Internetsicherheit",
|
"safe_browsing": "Internetsicherheit",
|
||||||
"served_from_cache": "{{value}} <i>(aus dem Cache abgerufen)</i>",
|
"served_from_cache": "{{value}} <i>(aus dem Cache abgerufen)</i>",
|
||||||
"form_error_password_length": "Das Passwort muss mindestens {{value}} Zeichen enthalten",
|
"form_error_password_length": "Das Passwort muss mindestens {{value}} Zeichen enthalten",
|
||||||
"anonymizer_notification": "<0>Hinweis:</0> Die IP-Anonymisierung ist aktiviert. Sie können sie in den <1>Allgemeinen Einstellungen</1> deaktivieren."
|
"anonymizer_notification": "<0>Hinweis:</0> Die IP-Anonymisierung ist aktiviert. Sie können sie in den <1>Allgemeinen Einstellungen</1> deaktivieren.",
|
||||||
|
"confirm_dns_cache_clear": "Möchten Sie den DNS-Cache wirklich leeren?",
|
||||||
|
"cache_cleared": "DNS-Cache erfolgreich geleert",
|
||||||
|
"clear_cache": "Cache leeren"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 Settings",
|
"dhcp_ipv6_settings": "DHCP IPv6 Settings",
|
||||||
"form_error_required": "Required field",
|
"form_error_required": "Required field",
|
||||||
"form_error_ip4_format": "Invalid IPv4 address",
|
"form_error_ip4_format": "Invalid IPv4 address",
|
||||||
"form_error_ip4_range_start_format": "Invalid IPv4 address of the range start",
|
|
||||||
"form_error_ip4_range_end_format": "Invalid IPv4 address of the range end",
|
|
||||||
"form_error_ip4_gateway_format": "Invalid IPv4 address of the gateway",
|
"form_error_ip4_gateway_format": "Invalid IPv4 address of the gateway",
|
||||||
"form_error_ip6_format": "Invalid IPv6 address",
|
"form_error_ip6_format": "Invalid IPv6 address",
|
||||||
"form_error_ip_format": "Invalid IP address",
|
"form_error_ip_format": "Invalid IP address",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "Must be out of range \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Must be out of range \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Must be lower than range start",
|
"lower_range_start_error": "Must be lower than range start",
|
||||||
"greater_range_start_error": "Must be greater than range start",
|
"greater_range_start_error": "Must be greater than range start",
|
||||||
"greater_range_end_error": "Must be greater than range end",
|
|
||||||
"subnet_error": "Addresses must be in one subnet",
|
"subnet_error": "Addresses must be in one subnet",
|
||||||
"gateway_or_subnet_invalid": "Subnet mask invalid",
|
"gateway_or_subnet_invalid": "Invalid subnet mask",
|
||||||
"dhcp_form_gateway_input": "Gateway IP",
|
"dhcp_form_gateway_input": "Gateway IP",
|
||||||
"dhcp_form_subnet_input": "Subnet mask",
|
"dhcp_form_subnet_input": "Subnet mask",
|
||||||
"dhcp_form_range_title": "Range of IP addresses",
|
"dhcp_form_range_title": "Range of IP addresses",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Issuer",
|
"encryption_issuer": "Issuer",
|
||||||
"encryption_hostnames": "Hostnames",
|
"encryption_hostnames": "Hostnames",
|
||||||
"encryption_reset": "Are you sure you want to reset encryption settings?",
|
"encryption_reset": "Are you sure you want to reset encryption settings?",
|
||||||
|
"encryption_warning": "Warning",
|
||||||
"topline_expiring_certificate": "Your SSL certificate is about to expire. Update <0>Encryption settings</0>.",
|
"topline_expiring_certificate": "Your SSL certificate is about to expire. Update <0>Encryption settings</0>.",
|
||||||
"topline_expired_certificate": "Your SSL certificate is expired. Update <0>Encryption settings</0>.",
|
"topline_expired_certificate": "Your SSL certificate is expired. Update <0>Encryption settings</0>.",
|
||||||
"form_error_port_range": "Enter port number in the range of 80-65535",
|
"form_error_port_range": "Enter port number in the range of 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Safe Browsing",
|
"safe_browsing": "Safe Browsing",
|
||||||
"served_from_cache": "{{value}} <i>(served from cache)</i>",
|
"served_from_cache": "{{value}} <i>(served from cache)</i>",
|
||||||
"form_error_password_length": "Password must be at least {{value}} characters long",
|
"form_error_password_length": "Password must be at least {{value}} characters long",
|
||||||
"anonymizer_notification": "<0>Note:</0> IP anonymization is enabled. You can disable it in <1>General settings</1>."
|
"anonymizer_notification": "<0>Note:</0> IP anonymization is enabled. You can disable it in <1>General settings</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Are you sure you want to clear DNS cache?",
|
||||||
|
"cache_cleared": "DNS cache successfully cleared",
|
||||||
|
"clear_cache": "Clear cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Configuración DHCP IPv6",
|
"dhcp_ipv6_settings": "Configuración DHCP IPv6",
|
||||||
"form_error_required": "Campo obligatorio",
|
"form_error_required": "Campo obligatorio",
|
||||||
"form_error_ip4_format": "Dirección IPv4 no válida",
|
"form_error_ip4_format": "Dirección IPv4 no válida",
|
||||||
"form_error_ip4_range_start_format": "Dirección IPv4 no válida del inicio de rango",
|
|
||||||
"form_error_ip4_range_end_format": "Dirección IPv4 no válida del final de rango",
|
|
||||||
"form_error_ip4_gateway_format": "Dirección IPv4 no válida de la puerta de enlace",
|
"form_error_ip4_gateway_format": "Dirección IPv4 no válida de la puerta de enlace",
|
||||||
"form_error_ip6_format": "Dirección IPv6 no válida",
|
"form_error_ip6_format": "Dirección IPv6 no válida",
|
||||||
"form_error_ip_format": "Dirección IP no válida",
|
"form_error_ip_format": "Dirección IP no válida",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Debe estar fuera del rango \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Debe estar fuera del rango \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Debe ser inferior que el inicio de rango",
|
"lower_range_start_error": "Debe ser inferior que el inicio de rango",
|
||||||
"greater_range_start_error": "Debe ser mayor que el inicio de rango",
|
"greater_range_start_error": "Debe ser mayor que el inicio de rango",
|
||||||
"greater_range_end_error": "Debe ser mayor que el final de rango",
|
|
||||||
"subnet_error": "Las direcciones deben estar en una subred",
|
"subnet_error": "Las direcciones deben estar en una subred",
|
||||||
"gateway_or_subnet_invalid": "Máscara de subred no válida",
|
"gateway_or_subnet_invalid": "Máscara de subred no válida",
|
||||||
"dhcp_form_gateway_input": "IP de puerta de enlace",
|
"dhcp_form_gateway_input": "IP de puerta de enlace",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Emisor",
|
"encryption_issuer": "Emisor",
|
||||||
"encryption_hostnames": "Nombres de hosts",
|
"encryption_hostnames": "Nombres de hosts",
|
||||||
"encryption_reset": "¿Estás seguro de que deseas restablecer la configuración de cifrado?",
|
"encryption_reset": "¿Estás seguro de que deseas restablecer la configuración de cifrado?",
|
||||||
|
"encryption_warning": "Advertencia",
|
||||||
"topline_expiring_certificate": "Tu certificado SSL está a punto de expirar. Actualiza la <0>configuración de cifrado</0>.",
|
"topline_expiring_certificate": "Tu certificado SSL está a punto de expirar. Actualiza la <0>configuración de cifrado</0>.",
|
||||||
"topline_expired_certificate": "Tu certificado SSL ha expirado. Actualiza la <0>configuración de cifrado</0>.",
|
"topline_expired_certificate": "Tu certificado SSL ha expirado. Actualiza la <0>configuración de cifrado</0>.",
|
||||||
"form_error_port_range": "Ingresa el número del puerto en el rango de 80 a 65535",
|
"form_error_port_range": "Ingresa el número del puerto en el rango de 80 a 65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navegación segura",
|
"safe_browsing": "Navegación segura",
|
||||||
"served_from_cache": "{{value}} <i>(servido desde la caché)</i>",
|
"served_from_cache": "{{value}} <i>(servido desde la caché)</i>",
|
||||||
"form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres",
|
"form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres",
|
||||||
"anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>."
|
"anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>.",
|
||||||
|
"confirm_dns_cache_clear": "¿Estás seguro de que deseas borrar la caché de DNS?",
|
||||||
|
"cache_cleared": "Caché DNS borrado con éxito",
|
||||||
|
"clear_cache": "Borrar caché"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
"encryption_issuer": "صادر کننده",
|
"encryption_issuer": "صادر کننده",
|
||||||
"encryption_hostnames": "نام میزبان",
|
"encryption_hostnames": "نام میزبان",
|
||||||
"encryption_reset": "آیا میخواهید تنظیمات رمزگُذاری به پیش فرض بازگردد؟",
|
"encryption_reset": "آیا میخواهید تنظیمات رمزگُذاری به پیش فرض بازگردد؟",
|
||||||
|
"encryption_warning": "هشدار",
|
||||||
"topline_expiring_certificate": "گواهینامه اِس اِس اِل شما در صدد انقضاء است. <0>تنظیمات رمزگُذاری</0> را بروز رسانی کنید.",
|
"topline_expiring_certificate": "گواهینامه اِس اِس اِل شما در صدد انقضاء است. <0>تنظیمات رمزگُذاری</0> را بروز رسانی کنید.",
|
||||||
"topline_expired_certificate": "گواهینامه اِس اِس اِل شما منقضی شده است. <0>تنظیمات رمزگُذاری</0> را بروز رسانی کنید.",
|
"topline_expired_certificate": "گواهینامه اِس اِس اِل شما منقضی شده است. <0>تنظیمات رمزگُذاری</0> را بروز رسانی کنید.",
|
||||||
"form_error_port_range": "مقدار پورت را در محدوده 80-65535 وارد کنید",
|
"form_error_port_range": "مقدار پورت را در محدوده 80-65535 وارد کنید",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP:n IPv6-asetukset",
|
"dhcp_ipv6_settings": "DHCP:n IPv6-asetukset",
|
||||||
"form_error_required": "Pakollinen kenttä",
|
"form_error_required": "Pakollinen kenttä",
|
||||||
"form_error_ip4_format": "Virheellinen IPv4-osoite",
|
"form_error_ip4_format": "Virheellinen IPv4-osoite",
|
||||||
"form_error_ip4_range_start_format": "Virheellinen IPv4-osoitealueen aloitusosoite",
|
|
||||||
"form_error_ip4_range_end_format": "Virheellinen IPv4-osoitealueen päätösosoite",
|
|
||||||
"form_error_ip4_gateway_format": "Virheellinen yhdyskäytävän IPv4-osoite",
|
"form_error_ip4_gateway_format": "Virheellinen yhdyskäytävän IPv4-osoite",
|
||||||
"form_error_ip6_format": "Virheellinen IPv6-osoite",
|
"form_error_ip6_format": "Virheellinen IPv6-osoite",
|
||||||
"form_error_ip_format": "Virheellinen IP-osoite",
|
"form_error_ip_format": "Virheellinen IP-osoite",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Oltava alueen \"{{start}}\" - \"{{end}}\" ulkopuolella",
|
"out_of_range_error": "Oltava alueen \"{{start}}\" - \"{{end}}\" ulkopuolella",
|
||||||
"lower_range_start_error": "Oltava alueen aloitusarvoa pienempi",
|
"lower_range_start_error": "Oltava alueen aloitusarvoa pienempi",
|
||||||
"greater_range_start_error": "Oltava alueen aloitusarvoa suurempi",
|
"greater_range_start_error": "Oltava alueen aloitusarvoa suurempi",
|
||||||
"greater_range_end_error": "Oltava alueen päätösarvoa pienempi",
|
|
||||||
"subnet_error": "Osoitteiden tulee olla yhdessä aliverkossa",
|
"subnet_error": "Osoitteiden tulee olla yhdessä aliverkossa",
|
||||||
"gateway_or_subnet_invalid": "Virheellinen aliverkon peite",
|
"gateway_or_subnet_invalid": "Virheellinen aliverkon peite",
|
||||||
"dhcp_form_gateway_input": "Yhdyskäytävän IP-osoite",
|
"dhcp_form_gateway_input": "Yhdyskäytävän IP-osoite",
|
||||||
@@ -88,7 +85,7 @@
|
|||||||
"response_details": "Vastauksen tiedot",
|
"response_details": "Vastauksen tiedot",
|
||||||
"request_details": "Pyynnön tiedot",
|
"request_details": "Pyynnön tiedot",
|
||||||
"client_details": "Päätelaitteen tiedot",
|
"client_details": "Päätelaitteen tiedot",
|
||||||
"details": "Tiedot",
|
"details": "Yksityiskohdat",
|
||||||
"back": "Takaisin",
|
"back": "Takaisin",
|
||||||
"dashboard": "Tila",
|
"dashboard": "Tila",
|
||||||
"settings": "Asetukset",
|
"settings": "Asetukset",
|
||||||
@@ -275,7 +272,7 @@
|
|||||||
"nxdomain": "NXDOMAIN",
|
"nxdomain": "NXDOMAIN",
|
||||||
"refused": "REFUSED",
|
"refused": "REFUSED",
|
||||||
"null_ip": "Tyhjä IP",
|
"null_ip": "Tyhjä IP",
|
||||||
"custom_ip": "Oma IP",
|
"custom_ip": "Oma IP-osoite",
|
||||||
"blocking_ipv4": "IPv4-esto",
|
"blocking_ipv4": "IPv4-esto",
|
||||||
"blocking_ipv6": "IPv6-esto",
|
"blocking_ipv6": "IPv6-esto",
|
||||||
"dnscrypt": "DNSCrypt",
|
"dnscrypt": "DNSCrypt",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Toimittaja",
|
"encryption_issuer": "Toimittaja",
|
||||||
"encryption_hostnames": "Isäntänimet",
|
"encryption_hostnames": "Isäntänimet",
|
||||||
"encryption_reset": "Haluatko varmasti palauttaa salausasetukset?",
|
"encryption_reset": "Haluatko varmasti palauttaa salausasetukset?",
|
||||||
|
"encryption_warning": "Varoitus",
|
||||||
"topline_expiring_certificate": "SSL-varmenteesi on erääntymässä. Päivitä <0>Salausasetukset</0>.",
|
"topline_expiring_certificate": "SSL-varmenteesi on erääntymässä. Päivitä <0>Salausasetukset</0>.",
|
||||||
"topline_expired_certificate": "SSL-varmenteesi on erääntynyt. Päivitä <0>Salausasetukset</0>.",
|
"topline_expired_certificate": "SSL-varmenteesi on erääntynyt. Päivitä <0>Salausasetukset</0>.",
|
||||||
"form_error_port_range": "Syötä portti väliltä 80-65535",
|
"form_error_port_range": "Syötä portti väliltä 80-65535",
|
||||||
@@ -415,8 +413,8 @@
|
|||||||
"clients_title": "Pysyvät päätelaitteet",
|
"clients_title": "Pysyvät päätelaitteet",
|
||||||
"clients_desc": "Määritä pysyvät AdGuard Homeen yhdistetyt päätelaitetiedot.",
|
"clients_desc": "Määritä pysyvät AdGuard Homeen yhdistetyt päätelaitetiedot.",
|
||||||
"settings_global": "Yleinen",
|
"settings_global": "Yleinen",
|
||||||
"settings_custom": "Oma",
|
"settings_custom": "Muut aiheet",
|
||||||
"table_client": "Päätelaite",
|
"table_client": "Asiakas",
|
||||||
"table_name": "Nimi",
|
"table_name": "Nimi",
|
||||||
"save_btn": "Tallenna",
|
"save_btn": "Tallenna",
|
||||||
"client_add": "Lisää päätelaite",
|
"client_add": "Lisää päätelaite",
|
||||||
@@ -542,8 +540,8 @@
|
|||||||
"descr": "Kuvaus",
|
"descr": "Kuvaus",
|
||||||
"whois": "WHOIS",
|
"whois": "WHOIS",
|
||||||
"filtering_rules_learn_more": "<0>Lue lisää</0> omien hosts-listojesi luonnista.",
|
"filtering_rules_learn_more": "<0>Lue lisää</0> omien hosts-listojesi luonnista.",
|
||||||
"blocked_by_response": "Vastauksen sisältämän CNAME:n tai IP:n estämä",
|
"blocked_by_response": "Estetty vastauksen CNAME:n tai IP:n perusteella",
|
||||||
"blocked_by_cname_or_ip": "CNAME:n tai IP:n estämä",
|
"blocked_by_cname_or_ip": "Estetty CNAME:n tai IP:n perusteella",
|
||||||
"try_again": "Yritä uudelleen",
|
"try_again": "Yritä uudelleen",
|
||||||
"domain_desc": "Syötä korvattava verkkotunnus tai jokerimerkki.",
|
"domain_desc": "Syötä korvattava verkkotunnus tai jokerimerkki.",
|
||||||
"example_rewrite_domain": "korvaa vain tämän verkkotunnuksen vastaukset",
|
"example_rewrite_domain": "korvaa vain tämän verkkotunnuksen vastaukset",
|
||||||
@@ -597,7 +595,7 @@
|
|||||||
"show_whitelisted_responses": "Sallitut",
|
"show_whitelisted_responses": "Sallitut",
|
||||||
"show_processed_responses": "Käsitelty",
|
"show_processed_responses": "Käsitelty",
|
||||||
"blocked_safebrowsing": "Turvallisen selauksen estämät",
|
"blocked_safebrowsing": "Turvallisen selauksen estämät",
|
||||||
"blocked_adult_websites": "Lapsilukon estämät",
|
"blocked_adult_websites": "Estetty lapsilukolla",
|
||||||
"blocked_threats": "Estetyt uhat",
|
"blocked_threats": "Estetyt uhat",
|
||||||
"allowed": "Sallitut",
|
"allowed": "Sallitut",
|
||||||
"filtered": "Suodatetut",
|
"filtered": "Suodatetut",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Turvallinen selaus",
|
"safe_browsing": "Turvallinen selaus",
|
||||||
"served_from_cache": "{{value}} <i>(jaettu välimuistista)</i>",
|
"served_from_cache": "{{value}} <i>(jaettu välimuistista)</i>",
|
||||||
"form_error_password_length": "Salasanan on oltava ainakin {{value}} merkkiä",
|
"form_error_password_length": "Salasanan on oltava ainakin {{value}} merkkiä",
|
||||||
"anonymizer_notification": "<0>Huomioi:</0> IP-osoitteen anonymisointi on käytössä. Voit poistaa sen käytöstä <1>Yleisistä asetuksista</1>."
|
"anonymizer_notification": "<0>Huomioi:</0> IP-osoitteen anonymisointi on käytössä. Voit poistaa sen käytöstä <1>Yleisistä asetuksista</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Haluatko varmasti tyhjentää DNS-välimuistin?",
|
||||||
|
"cache_cleared": "DNS-välimuistin tyhjennys onnistui",
|
||||||
|
"clear_cache": "Tyhjennä välimuisti"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Paramètres IPv6 du DHCP",
|
"dhcp_ipv6_settings": "Paramètres IPv6 du DHCP",
|
||||||
"form_error_required": "Champ requis",
|
"form_error_required": "Champ requis",
|
||||||
"form_error_ip4_format": "Adresse IPv4 invalide",
|
"form_error_ip4_format": "Adresse IPv4 invalide",
|
||||||
"form_error_ip4_range_start_format": "Adresse de début de plage IPv4 incorrecte",
|
|
||||||
"form_error_ip4_range_end_format": "Adresse de fin de plage IPv4 incorrecte",
|
|
||||||
"form_error_ip4_gateway_format": "Adresse de passerelle IPv4 invalide",
|
"form_error_ip4_gateway_format": "Adresse de passerelle IPv4 invalide",
|
||||||
"form_error_ip6_format": "Adresse IPv6 invalide",
|
"form_error_ip6_format": "Adresse IPv6 invalide",
|
||||||
"form_error_ip_format": "Adresse IP invalide",
|
"form_error_ip_format": "Adresse IP invalide",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "Doit être hors plage « {{start}} » - « {{end}} »",
|
"out_of_range_error": "Doit être hors plage « {{start}} » - « {{end}} »",
|
||||||
"lower_range_start_error": "Doit être inférieur au début de plage",
|
"lower_range_start_error": "Doit être inférieur au début de plage",
|
||||||
"greater_range_start_error": "Doit être supérieur au début de plage",
|
"greater_range_start_error": "Doit être supérieur au début de plage",
|
||||||
"greater_range_end_error": "Doit être supérieur à la fin de plage",
|
|
||||||
"subnet_error": "Les adresses doivent être dans le même sous-réseau",
|
"subnet_error": "Les adresses doivent être dans le même sous-réseau",
|
||||||
"gateway_or_subnet_invalid": "Masque de sous-réseau invalide",
|
"gateway_or_subnet_invalid": "Masque de sous-réseau invalide.",
|
||||||
"dhcp_form_gateway_input": "IP de la passerelle",
|
"dhcp_form_gateway_input": "IP de la passerelle",
|
||||||
"dhcp_form_subnet_input": "Masque de sous-réseau",
|
"dhcp_form_subnet_input": "Masque de sous-réseau",
|
||||||
"dhcp_form_range_title": "Rangée des adresses IP",
|
"dhcp_form_range_title": "Rangée des adresses IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Émetteur",
|
"encryption_issuer": "Émetteur",
|
||||||
"encryption_hostnames": "Noms d'hôte",
|
"encryption_hostnames": "Noms d'hôte",
|
||||||
"encryption_reset": "Voulez-vous vraiment réinitialiser les paramètres de chiffrement ?",
|
"encryption_reset": "Voulez-vous vraiment réinitialiser les paramètres de chiffrement ?",
|
||||||
|
"encryption_warning": "Attention",
|
||||||
"topline_expiring_certificate": "Votre certificat SSL est sur le point d'expirer. Mettez à jour vos <0>Paramètres de chiffrement</0>.",
|
"topline_expiring_certificate": "Votre certificat SSL est sur le point d'expirer. Mettez à jour vos <0>Paramètres de chiffrement</0>.",
|
||||||
"topline_expired_certificate": "Votre certificat SSL a expiré. Mettez à jour vos <0>Paramètres de chiffrement</0>.",
|
"topline_expired_certificate": "Votre certificat SSL a expiré. Mettez à jour vos <0>Paramètres de chiffrement</0>.",
|
||||||
"form_error_port_range": "Saisissez une valeur de port entre 80 et 65535",
|
"form_error_port_range": "Saisissez une valeur de port entre 80 et 65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navigation sécurisée",
|
"safe_browsing": "Navigation sécurisée",
|
||||||
"served_from_cache": "{{value}} <i>(depuis le cache)</i>",
|
"served_from_cache": "{{value}} <i>(depuis le cache)</i>",
|
||||||
"form_error_password_length": "Le mot de passe doit comporter au moins {{value}} caractères",
|
"form_error_password_length": "Le mot de passe doit comporter au moins {{value}} caractères",
|
||||||
"anonymizer_notification": "<0>Note :</0> L'anonymisation IP est activée. Vous pouvez la désactiver dans les <1>paramètres généraux</1>."
|
"anonymizer_notification": "<0>Note :</0> L'anonymisation IP est activée. Vous pouvez la désactiver dans les <1>paramètres généraux</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Voulez-vous vraiment vider le cache DNS ?",
|
||||||
|
"cache_cleared": "Le cache DNS a été vidé",
|
||||||
|
"clear_cache": "Vider le cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 postavke",
|
"dhcp_ipv6_settings": "DHCP IPv6 postavke",
|
||||||
"form_error_required": "Obavezno polje",
|
"form_error_required": "Obavezno polje",
|
||||||
"form_error_ip4_format": "Nevažeća IPv4 adresa",
|
"form_error_ip4_format": "Nevažeća IPv4 adresa",
|
||||||
"form_error_ip4_range_start_format": "Nepravilan početak ranga IPv4 adresa",
|
|
||||||
"form_error_ip4_range_end_format": "Nepravilan kraj ranga IPv4 adresa",
|
|
||||||
"form_error_ip4_gateway_format": "Nepravilna IPV4 adresa čvora",
|
"form_error_ip4_gateway_format": "Nepravilna IPV4 adresa čvora",
|
||||||
"form_error_ip6_format": "Nevažeći IPv6 adresa",
|
"form_error_ip6_format": "Nevažeći IPv6 adresa",
|
||||||
"form_error_ip_format": "Nepravilna IP adresa",
|
"form_error_ip_format": "Nepravilna IP adresa",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "Mora biti izvan ranga \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Mora biti izvan ranga \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Mora biti niže od početnog ranga",
|
"lower_range_start_error": "Mora biti niže od početnog ranga",
|
||||||
"greater_range_start_error": "Mora biti veće od krajnjeg ranga",
|
"greater_range_start_error": "Mora biti veće od krajnjeg ranga",
|
||||||
"greater_range_end_error": "Mora biti veće od krajnjeg ranga",
|
|
||||||
"subnet_error": "Adrese moraju biti iz iste podmreže",
|
"subnet_error": "Adrese moraju biti iz iste podmreže",
|
||||||
"gateway_or_subnet_invalid": "Maska podmreže je neprvilna",
|
"gateway_or_subnet_invalid": "Nevažeća podmrežna maska",
|
||||||
"dhcp_form_gateway_input": "Gateway IP",
|
"dhcp_form_gateway_input": "Gateway IP",
|
||||||
"dhcp_form_subnet_input": "Subnet maskiranje",
|
"dhcp_form_subnet_input": "Subnet maskiranje",
|
||||||
"dhcp_form_range_title": "Raspon IP adresa",
|
"dhcp_form_range_title": "Raspon IP adresa",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Izdavač",
|
"encryption_issuer": "Izdavač",
|
||||||
"encryption_hostnames": "Nazivi računala",
|
"encryption_hostnames": "Nazivi računala",
|
||||||
"encryption_reset": "Jeste li sigurni da želite poništiti postavke šifriranja?",
|
"encryption_reset": "Jeste li sigurni da želite poništiti postavke šifriranja?",
|
||||||
|
"encryption_warning": "Upozorenje",
|
||||||
"topline_expiring_certificate": "Vaš SSL certifikat uskoro ističe. Ažurirajte <0>Postavke šifriranja</0>.",
|
"topline_expiring_certificate": "Vaš SSL certifikat uskoro ističe. Ažurirajte <0>Postavke šifriranja</0>.",
|
||||||
"topline_expired_certificate": "Vaš SSL certifikat je istekao. Ažurirajte <0>Postavke šifriranja</0>.",
|
"topline_expired_certificate": "Vaš SSL certifikat je istekao. Ažurirajte <0>Postavke šifriranja</0>.",
|
||||||
"form_error_port_range": "Unesite broj porta od 80 do 65536",
|
"form_error_port_range": "Unesite broj porta od 80 do 65536",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Sigurno surfanje",
|
"safe_browsing": "Sigurno surfanje",
|
||||||
"served_from_cache": "{{value}} <i>(dohvaćeno iz predmemorije)</i>",
|
"served_from_cache": "{{value}} <i>(dohvaćeno iz predmemorije)</i>",
|
||||||
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
|
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
|
||||||
"anonymizer_notification": "<0>Napomena:</0>IP anonimizacija je omogućena. Možete ju onemogućiti u <1>općim postavkama</1>."
|
"anonymizer_notification": "<0>Napomena:</0>IP anonimizacija je omogućena. Možete ju onemogućiti u <1>općim postavkama</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Jeste li sigurni da želite očistiti DNS predmemoriju?",
|
||||||
|
"cache_cleared": "DNS predmemorija je uspješno izbrisana",
|
||||||
|
"clear_cache": "Očisti predmemoriju"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 Beállítások",
|
"dhcp_ipv6_settings": "DHCP IPv6 Beállítások",
|
||||||
"form_error_required": "Kötelező mező",
|
"form_error_required": "Kötelező mező",
|
||||||
"form_error_ip4_format": "Érvénytelen IPv4 cím",
|
"form_error_ip4_format": "Érvénytelen IPv4 cím",
|
||||||
"form_error_ip4_range_start_format": "Érvénytelen IPv4-cím a tartomány kezdetéhez",
|
|
||||||
"form_error_ip4_range_end_format": "Érvénytelen IPv4-cím a tartomány végén",
|
|
||||||
"form_error_ip4_gateway_format": "Az átjáróhoz (gateway) érvénytelen IPv4 cím lett megadva",
|
"form_error_ip4_gateway_format": "Az átjáróhoz (gateway) érvénytelen IPv4 cím lett megadva",
|
||||||
"form_error_ip6_format": "Érvénytelen IPv6 cím",
|
"form_error_ip6_format": "Érvénytelen IPv6 cím",
|
||||||
"form_error_ip_format": "Érvénytelen IP-cím",
|
"form_error_ip_format": "Érvénytelen IP-cím",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "A következő tartományon kívül legyen: \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "A következő tartományon kívül legyen: \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete",
|
"lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete",
|
||||||
"greater_range_start_error": "Nagyobbnak kell lennie, mint a tartomány kezdete",
|
"greater_range_start_error": "Nagyobbnak kell lennie, mint a tartomány kezdete",
|
||||||
"greater_range_end_error": "Nagyobb legyen, mint a tartomány vége",
|
|
||||||
"subnet_error": "A címeknek egy alhálózatban kell lenniük",
|
"subnet_error": "A címeknek egy alhálózatban kell lenniük",
|
||||||
"gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen",
|
"gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen",
|
||||||
"dhcp_form_gateway_input": "Átjáró IP",
|
"dhcp_form_gateway_input": "Átjáró IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Kibocsátó",
|
"encryption_issuer": "Kibocsátó",
|
||||||
"encryption_hostnames": "Hosztnevek",
|
"encryption_hostnames": "Hosztnevek",
|
||||||
"encryption_reset": "Biztosan visszaállítja a titkosítási beállításokat?",
|
"encryption_reset": "Biztosan visszaállítja a titkosítási beállításokat?",
|
||||||
|
"encryption_warning": "Figyelmeztetés",
|
||||||
"topline_expiring_certificate": "Az SSL-tanúsítványa hamarosan lejár. Frissítse a <0>Titkosítási beállításokat</0>.",
|
"topline_expiring_certificate": "Az SSL-tanúsítványa hamarosan lejár. Frissítse a <0>Titkosítási beállításokat</0>.",
|
||||||
"topline_expired_certificate": "Az SSL-tanúsítványa lejárt. Frissítse a <0>Titkosítási beállításokat</0>.",
|
"topline_expired_certificate": "Az SSL-tanúsítványa lejárt. Frissítse a <0>Titkosítási beállításokat</0>.",
|
||||||
"form_error_port_range": "Adjon meg egy portszámot a 80-65535 tartományon belül",
|
"form_error_port_range": "Adjon meg egy portszámot a 80-65535 tartományon belül",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Biztonságos böngészés",
|
"safe_browsing": "Biztonságos böngészés",
|
||||||
"served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>",
|
"served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>",
|
||||||
"form_error_password_length": "A jelszó legalább {{value}} karakter hosszú kell, hogy legyen",
|
"form_error_password_length": "A jelszó legalább {{value}} karakter hosszú kell, hogy legyen",
|
||||||
"anonymizer_notification": "<0>Megjegyzés:</0> Az IP anonimizálás engedélyezve van. Az <1>Általános beállításoknál letilthatja</1> ."
|
"anonymizer_notification": "<0>Megjegyzés:</0> Az IP anonimizálás engedélyezve van. Az <1>Általános beállításoknál letilthatja</1> .",
|
||||||
|
"confirm_dns_cache_clear": "Biztos benne, hogy törölni szeretné a DNS-gyorsítótárat?",
|
||||||
|
"cache_cleared": "A DNS gyorsítótár sikeresen törlődött",
|
||||||
|
"clear_cache": "Gyorsítótár törlése"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Pengaturan DHCP IPv6",
|
"dhcp_ipv6_settings": "Pengaturan DHCP IPv6",
|
||||||
"form_error_required": "Kolom yang harus diisi",
|
"form_error_required": "Kolom yang harus diisi",
|
||||||
"form_error_ip4_format": "Alamat IPv4 tidak valid",
|
"form_error_ip4_format": "Alamat IPv4 tidak valid",
|
||||||
"form_error_ip4_range_start_format": "Alamat IPv4 tidak valid dari rentang awal",
|
|
||||||
"form_error_ip4_range_end_format": "Alamat IPv4 tidak valid dari rentang akhir",
|
|
||||||
"form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid",
|
"form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid",
|
||||||
"form_error_ip6_format": "Alamat IPv6 tidak valid",
|
"form_error_ip6_format": "Alamat IPv6 tidak valid",
|
||||||
"form_error_ip_format": "Alamat IP tidak valid",
|
"form_error_ip_format": "Alamat IP tidak valid",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Harus lebih rendah dari rentang awal",
|
"lower_range_start_error": "Harus lebih rendah dari rentang awal",
|
||||||
"greater_range_start_error": "Harus lebih besar dari rentang awal",
|
"greater_range_start_error": "Harus lebih besar dari rentang awal",
|
||||||
"greater_range_end_error": "Harus lebih besar dari rentang akhir",
|
|
||||||
"subnet_error": "Alamat harus dalam satu subnet",
|
"subnet_error": "Alamat harus dalam satu subnet",
|
||||||
"gateway_or_subnet_invalid": "Subnet mask tidak valid",
|
"gateway_or_subnet_invalid": "Subnet mask tidak valid",
|
||||||
"dhcp_form_gateway_input": "IP gateway",
|
"dhcp_form_gateway_input": "IP gateway",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Penerbit",
|
"encryption_issuer": "Penerbit",
|
||||||
"encryption_hostnames": "Nama host",
|
"encryption_hostnames": "Nama host",
|
||||||
"encryption_reset": "Anda yakin ingin mengatur ulang pengaturan enkripsi?",
|
"encryption_reset": "Anda yakin ingin mengatur ulang pengaturan enkripsi?",
|
||||||
|
"encryption_warning": "Perhatian",
|
||||||
"topline_expiring_certificate": "Sertifikat SSL Anda hampir kedaluwarsa. Perbarui <0>Pengaturan enkripsi</0>.",
|
"topline_expiring_certificate": "Sertifikat SSL Anda hampir kedaluwarsa. Perbarui <0>Pengaturan enkripsi</0>.",
|
||||||
"topline_expired_certificate": "Sertifikat SSL Anda kedaluwarsa. Perbarui <0>Pengaturan enkripsi</0>.",
|
"topline_expired_certificate": "Sertifikat SSL Anda kedaluwarsa. Perbarui <0>Pengaturan enkripsi</0>.",
|
||||||
"form_error_port_range": "Masukkan nomor port di kisaran 80-65535",
|
"form_error_port_range": "Masukkan nomor port di kisaran 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Penjelajahan Aman",
|
"safe_browsing": "Penjelajahan Aman",
|
||||||
"served_from_cache": "{{value}} <i>(disajikan dari cache)</i>",
|
"served_from_cache": "{{value}} <i>(disajikan dari cache)</i>",
|
||||||
"form_error_password_length": "Kata sandi harus minimal {{value}} karakter",
|
"form_error_password_length": "Kata sandi harus minimal {{value}} karakter",
|
||||||
"anonymizer_notification": "<0>Catatan:</0> Anonimisasi IP diaktifkan. Anda dapat menonaktifkannya di <1>Pengaturan umum</1> ."
|
"anonymizer_notification": "<0>Catatan:</0> Anonimisasi IP diaktifkan. Anda dapat menonaktifkannya di <1>Pengaturan umum</1> .",
|
||||||
|
"confirm_dns_cache_clear": "Apakah Anda yakin ingin menghapus cache DNS?",
|
||||||
|
"cache_cleared": "Cache DNS berhasil dibersihkan",
|
||||||
|
"clear_cache": "Hapus cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Impostazioni DHCP IPv6",
|
"dhcp_ipv6_settings": "Impostazioni DHCP IPv6",
|
||||||
"form_error_required": "Campo richiesto",
|
"form_error_required": "Campo richiesto",
|
||||||
"form_error_ip4_format": "Indirizzo IPv4 non valido",
|
"form_error_ip4_format": "Indirizzo IPv4 non valido",
|
||||||
"form_error_ip4_range_start_format": "Indirizzo IPV4 non valido dell'intervallo iniziale",
|
|
||||||
"form_error_ip4_range_end_format": "Indirizzo IPV4 non valido dell'intervallo finale",
|
|
||||||
"form_error_ip4_gateway_format": "Indirizzo gateway IPv4 non valido",
|
"form_error_ip4_gateway_format": "Indirizzo gateway IPv4 non valido",
|
||||||
"form_error_ip6_format": "Indirizzo IPv6 non valido",
|
"form_error_ip6_format": "Indirizzo IPv6 non valido",
|
||||||
"form_error_ip_format": "Indirizzo IP non valido",
|
"form_error_ip_format": "Indirizzo IP non valido",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Deve essere fuori intervallo \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Deve essere fuori intervallo \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Deve essere inferiore dell'intervallo di inizio",
|
"lower_range_start_error": "Deve essere inferiore dell'intervallo di inizio",
|
||||||
"greater_range_start_error": "Deve essere maggiore dell'intervallo di inizio",
|
"greater_range_start_error": "Deve essere maggiore dell'intervallo di inizio",
|
||||||
"greater_range_end_error": "Deve essere maggiore dell'intervallo di fine",
|
|
||||||
"subnet_error": "Gli indirizzi devono trovarsi in una sottorete",
|
"subnet_error": "Gli indirizzi devono trovarsi in una sottorete",
|
||||||
"gateway_or_subnet_invalid": "Maschera di sottorete non valida",
|
"gateway_or_subnet_invalid": "Maschera di sottorete non valida",
|
||||||
"dhcp_form_gateway_input": "IP Gateway",
|
"dhcp_form_gateway_input": "IP Gateway",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Emittente",
|
"encryption_issuer": "Emittente",
|
||||||
"encryption_hostnames": "Nomi host",
|
"encryption_hostnames": "Nomi host",
|
||||||
"encryption_reset": "Sei sicuro di voler ripristinare le impostazioni di crittografia?",
|
"encryption_reset": "Sei sicuro di voler ripristinare le impostazioni di crittografia?",
|
||||||
|
"encryption_warning": "Attenzione",
|
||||||
"topline_expiring_certificate": "Il tuo certificato SSL sta per scadere. Aggiorna le<0> Impostazioni di crittografia </ 0>.",
|
"topline_expiring_certificate": "Il tuo certificato SSL sta per scadere. Aggiorna le<0> Impostazioni di crittografia </ 0>.",
|
||||||
"topline_expired_certificate": "Il tuo certificato SSL è scaduto. Aggiorna le <0> Impostazioni di crittografia </ 0>.",
|
"topline_expired_certificate": "Il tuo certificato SSL è scaduto. Aggiorna le <0> Impostazioni di crittografia </ 0>.",
|
||||||
"form_error_port_range": "Immettere il valore della porta nell'intervallo 80-65535",
|
"form_error_port_range": "Immettere il valore della porta nell'intervallo 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navigazione Sicura",
|
"safe_browsing": "Navigazione Sicura",
|
||||||
"served_from_cache": "{{value}} <i>(fornito dalla cache)</i>",
|
"served_from_cache": "{{value}} <i>(fornito dalla cache)</i>",
|
||||||
"form_error_password_length": "La password deve contenere almeno {{value}} caratteri",
|
"form_error_password_length": "La password deve contenere almeno {{value}} caratteri",
|
||||||
"anonymizer_notification": "<0>Attenzione:</0> L'anonimizzazione dell'IP è abilitata. Puoi disabilitarla in <1>Impostazioni generali</1>."
|
"anonymizer_notification": "<0>Attenzione:</0> L'anonimizzazione dell'IP è abilitata. Puoi disabilitarla in <1>Impostazioni generali</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Sei sicuro di voler cancellare la cache DNS?",
|
||||||
|
"cache_cleared": "Cache DNS è stata cancellata correttamente",
|
||||||
|
"clear_cache": "Cancella cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 設定",
|
"dhcp_ipv6_settings": "DHCP IPv6 設定",
|
||||||
"form_error_required": "必須項目です",
|
"form_error_required": "必須項目です",
|
||||||
"form_error_ip4_format": "IPv4アドレスが無効です",
|
"form_error_ip4_format": "IPv4アドレスが無効です",
|
||||||
"form_error_ip4_range_start_format": "範囲開始のIPv4アドレスが無効です",
|
|
||||||
"form_error_ip4_range_end_format": "範囲終了のIPv4アドレスが無効です",
|
|
||||||
"form_error_ip4_gateway_format": "ゲートウェイのIPv4アドレスが無効です",
|
"form_error_ip4_gateway_format": "ゲートウェイのIPv4アドレスが無効です",
|
||||||
"form_error_ip6_format": "IPv6アドレスが無効です",
|
"form_error_ip6_format": "IPv6アドレスが無効です",
|
||||||
"form_error_ip_format": "IPアドレスが無効です",
|
"form_error_ip_format": "IPアドレスが無効です",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "\"{{start}}\"〜\"{{end}}\" の範囲外である必要があります",
|
"out_of_range_error": "\"{{start}}\"〜\"{{end}}\" の範囲外である必要があります",
|
||||||
"lower_range_start_error": "範囲開始よりも低い値である必要があります",
|
"lower_range_start_error": "範囲開始よりも低い値である必要があります",
|
||||||
"greater_range_start_error": "範囲開始値より大きい値でなければなりません",
|
"greater_range_start_error": "範囲開始値より大きい値でなければなりません",
|
||||||
"greater_range_end_error": "範囲終了値より大きい値でなければなりません",
|
|
||||||
"subnet_error": "両アドレスが同じサブネット内にある必要があります",
|
"subnet_error": "両アドレスが同じサブネット内にある必要があります",
|
||||||
"gateway_or_subnet_invalid": "サブネットマスクが無効です",
|
"gateway_or_subnet_invalid": "サブネットマスクが無効です",
|
||||||
"dhcp_form_gateway_input": "ゲートウェイIP",
|
"dhcp_form_gateway_input": "ゲートウェイIP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "発行者",
|
"encryption_issuer": "発行者",
|
||||||
"encryption_hostnames": "ホスト名",
|
"encryption_hostnames": "ホスト名",
|
||||||
"encryption_reset": "暗号化設定をリセットして良いですか?",
|
"encryption_reset": "暗号化設定をリセットして良いですか?",
|
||||||
|
"encryption_warning": "警告",
|
||||||
"topline_expiring_certificate": "SSL証明書は期限切れになります。<0>暗号化設定</0>を更新します。",
|
"topline_expiring_certificate": "SSL証明書は期限切れになります。<0>暗号化設定</0>を更新します。",
|
||||||
"topline_expired_certificate": "SSL証明書は期限切れです。<0>暗号化設定</0>を更新します。",
|
"topline_expired_certificate": "SSL証明書は期限切れです。<0>暗号化設定</0>を更新します。",
|
||||||
"form_error_port_range": "80〜65535 の範囲内でポート番号を入力してください",
|
"form_error_port_range": "80〜65535 の範囲内でポート番号を入力してください",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "セーフブラウジング",
|
"safe_browsing": "セーフブラウジング",
|
||||||
"served_from_cache": "{{value}} <i>(キャッシュから応答)</i>",
|
"served_from_cache": "{{value}} <i>(キャッシュから応答)</i>",
|
||||||
"form_error_password_length": "パスワードは{{value}}文字以上にしてください",
|
"form_error_password_length": "パスワードは{{value}}文字以上にしてください",
|
||||||
"anonymizer_notification": "【<0>注意</0>】IPの匿名化が有効になっています。 <1>一般設定</1>で無効にできます。"
|
"anonymizer_notification": "【<0>注意</0>】IPの匿名化が有効になっています。 <1>一般設定</1>で無効にできます。",
|
||||||
|
"confirm_dns_cache_clear": "DNS キャッシュをクリアしてもよろしいですか?",
|
||||||
|
"cache_cleared": "DNSキャッシュのクリア完了です。",
|
||||||
|
"clear_cache": "キャッシュをクリアする"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 설정",
|
"dhcp_ipv6_settings": "DHCP IPv6 설정",
|
||||||
"form_error_required": "필수 영역",
|
"form_error_required": "필수 영역",
|
||||||
"form_error_ip4_format": "잘못된 IPv4 형식",
|
"form_error_ip4_format": "잘못된 IPv4 형식",
|
||||||
"form_error_ip4_range_start_format": "잘못된 범위 시작 IPv4 형식",
|
|
||||||
"form_error_ip4_range_end_format": "잘못된 범위 종료 IPv4 형식",
|
|
||||||
"form_error_ip4_gateway_format": "잘못된 게이트웨이 IPv4 형식",
|
"form_error_ip4_gateway_format": "잘못된 게이트웨이 IPv4 형식",
|
||||||
"form_error_ip6_format": "잘못된 IPv6 주소",
|
"form_error_ip6_format": "잘못된 IPv6 주소",
|
||||||
"form_error_ip_format": "잘못된 IP 주소",
|
"form_error_ip_format": "잘못된 IP 주소",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "'{{start}}'-'{{end}}' 범위 밖이어야 합니다",
|
"out_of_range_error": "'{{start}}'-'{{end}}' 범위 밖이어야 합니다",
|
||||||
"lower_range_start_error": "범위 시작보다 작은 값이어야 합니다",
|
"lower_range_start_error": "범위 시작보다 작은 값이어야 합니다",
|
||||||
"greater_range_start_error": "범위 시작보다 큰 값이어야 합니다",
|
"greater_range_start_error": "범위 시작보다 큰 값이어야 합니다",
|
||||||
"greater_range_end_error": "범위 종료보다 큰 값이어야 합니다",
|
|
||||||
"subnet_error": "주소는 하나의 서브넷에 있어야 합니다",
|
"subnet_error": "주소는 하나의 서브넷에 있어야 합니다",
|
||||||
"gateway_or_subnet_invalid": "잘못된 서브넷 마스크",
|
"gateway_or_subnet_invalid": "잘못된 서브넷 마스크",
|
||||||
"dhcp_form_gateway_input": "게이트웨이 IP",
|
"dhcp_form_gateway_input": "게이트웨이 IP",
|
||||||
@@ -223,7 +220,7 @@
|
|||||||
"example_upstream_tcp_hostname": "일반 DNS (TCP를 통한, 호스트명);",
|
"example_upstream_tcp_hostname": "일반 DNS (TCP를 통한, 호스트명);",
|
||||||
"all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다",
|
"all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다",
|
||||||
"updated_upstream_dns_toast": "업스트림 서버가 성공적으로 저장되었습니다",
|
"updated_upstream_dns_toast": "업스트림 서버가 성공적으로 저장되었습니다",
|
||||||
"dns_test_ok_toast": "특정 DNS 서버들은 정상적으로 동작 중입니다",
|
"dns_test_ok_toast": "지정된 DNS 서버가 올바르게 작동하고 있습니다.",
|
||||||
"dns_test_not_ok_toast": "서버 '{{key}}': 사용할 수 없습니다, 제대로 작성했는지 확인하세요",
|
"dns_test_not_ok_toast": "서버 '{{key}}': 사용할 수 없습니다, 제대로 작성했는지 확인하세요",
|
||||||
"dns_test_warning_toast": "업스트림 '{{key}}'이(가) 테스트 요청에 응답하지 않으며 제대로 작동하지 않을 수 있습니다",
|
"dns_test_warning_toast": "업스트림 '{{key}}'이(가) 테스트 요청에 응답하지 않으며 제대로 작동하지 않을 수 있습니다",
|
||||||
"unblock": "차단 해제",
|
"unblock": "차단 해제",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "발행자",
|
"encryption_issuer": "발행자",
|
||||||
"encryption_hostnames": "호스트 이름",
|
"encryption_hostnames": "호스트 이름",
|
||||||
"encryption_reset": "암호화 설정을 재설정하시겠습니까?",
|
"encryption_reset": "암호화 설정을 재설정하시겠습니까?",
|
||||||
|
"encryption_warning": "경고",
|
||||||
"topline_expiring_certificate": "SSL 인증서가 곧 만료됩니다. 업데이트<0> 암호화 설정</0>.",
|
"topline_expiring_certificate": "SSL 인증서가 곧 만료됩니다. 업데이트<0> 암호화 설정</0>.",
|
||||||
"topline_expired_certificate": "SSL 인증서가 만료되었습니다. 업데이트<0> 암호화 설정</0>.",
|
"topline_expired_certificate": "SSL 인증서가 만료되었습니다. 업데이트<0> 암호화 설정</0>.",
|
||||||
"form_error_port_range": "80-65535 범위의 포트 번호를 입력하세요",
|
"form_error_port_range": "80-65535 범위의 포트 번호를 입력하세요",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "세이프 브라우징",
|
"safe_browsing": "세이프 브라우징",
|
||||||
"served_from_cache": "{{value}} <i>(캐시에서 제공)</i>",
|
"served_from_cache": "{{value}} <i>(캐시에서 제공)</i>",
|
||||||
"form_error_password_length": "비밀번호는 {{value}}자 이상이어야 합니다",
|
"form_error_password_length": "비밀번호는 {{value}}자 이상이어야 합니다",
|
||||||
"anonymizer_notification": "<0>참고:</0> IP 익명화가 활성화되었습니다. <1>일반 설정</1>에서 비활성화할 수 있습니다."
|
"anonymizer_notification": "<0>참고:</0> IP 익명화가 활성화되었습니다. <1>일반 설정</1>에서 비활성화할 수 있습니다.",
|
||||||
|
"confirm_dns_cache_clear": "정말로 DNS 캐시를 지우시겠습니까?",
|
||||||
|
"cache_cleared": "DNS 캐시를 성공적으로 지웠습니다",
|
||||||
|
"clear_cache": "캐시 지우기"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 instellingen",
|
"dhcp_ipv6_settings": "DHCP IPv6 instellingen",
|
||||||
"form_error_required": "Vereist veld",
|
"form_error_required": "Vereist veld",
|
||||||
"form_error_ip4_format": "Ongeldig IPv4-adres",
|
"form_error_ip4_format": "Ongeldig IPv4-adres",
|
||||||
"form_error_ip4_range_start_format": "Ongeldig IPv4-adres start bereik",
|
|
||||||
"form_error_ip4_range_end_format": "Ongeldig IPv4-adres einde bereik",
|
|
||||||
"form_error_ip4_gateway_format": "Ongeldig IPv4-adres van de gateway",
|
"form_error_ip4_gateway_format": "Ongeldig IPv4-adres van de gateway",
|
||||||
"form_error_ip6_format": "Ongeldig IPv6-adres",
|
"form_error_ip6_format": "Ongeldig IPv6-adres",
|
||||||
"form_error_ip_format": "Ongeldig IP-adres",
|
"form_error_ip_format": "Ongeldig IP-adres",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "Moet buiten bereik zijn \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Moet buiten bereik zijn \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Moet lager zijn dan begin reeks",
|
"lower_range_start_error": "Moet lager zijn dan begin reeks",
|
||||||
"greater_range_start_error": "Moet groter zijn dan begin reeks",
|
"greater_range_start_error": "Moet groter zijn dan begin reeks",
|
||||||
"greater_range_end_error": "Moet groter zijn dan einde reeks",
|
|
||||||
"subnet_error": "Adressen moeten in één subnet vallen",
|
"subnet_error": "Adressen moeten in één subnet vallen",
|
||||||
"gateway_or_subnet_invalid": "Subnetmasker ongeldig",
|
"gateway_or_subnet_invalid": "Ongeldig subnetmasker",
|
||||||
"dhcp_form_gateway_input": "Gateway IP",
|
"dhcp_form_gateway_input": "Gateway IP",
|
||||||
"dhcp_form_subnet_input": "Subnet mask",
|
"dhcp_form_subnet_input": "Subnet mask",
|
||||||
"dhcp_form_range_title": "Bereik van IP adressen",
|
"dhcp_form_range_title": "Bereik van IP adressen",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Uitgever",
|
"encryption_issuer": "Uitgever",
|
||||||
"encryption_hostnames": "Hostnamen",
|
"encryption_hostnames": "Hostnamen",
|
||||||
"encryption_reset": "Ben je zeker dat je de encryptie instellingen wil resetten?",
|
"encryption_reset": "Ben je zeker dat je de encryptie instellingen wil resetten?",
|
||||||
|
"encryption_warning": "Waarschuwing",
|
||||||
"topline_expiring_certificate": "Jouw SSL-certificaat vervalt binnenkort. Werk de <0>encryptie-instellingen</0> bij.",
|
"topline_expiring_certificate": "Jouw SSL-certificaat vervalt binnenkort. Werk de <0>encryptie-instellingen</0> bij.",
|
||||||
"topline_expired_certificate": "Jouw SSL-certificaat is vervallen. Werk de <0>encryptie-instellingen</0> bij.",
|
"topline_expired_certificate": "Jouw SSL-certificaat is vervallen. Werk de <0>encryptie-instellingen</0> bij.",
|
||||||
"form_error_port_range": "Poortnummer invoeren tussen 80 en 65535",
|
"form_error_port_range": "Poortnummer invoeren tussen 80 en 65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Veilig browsen",
|
"safe_browsing": "Veilig browsen",
|
||||||
"served_from_cache": "{{value}} <i>(geleverd vanuit cache)</i>",
|
"served_from_cache": "{{value}} <i>(geleverd vanuit cache)</i>",
|
||||||
"form_error_password_length": "Wachtwoord moet minimaal {{value}} tekens lang zijn",
|
"form_error_password_length": "Wachtwoord moet minimaal {{value}} tekens lang zijn",
|
||||||
"anonymizer_notification": "<0>Opmerking:</0> IP-anonimisering is ingeschakeld. Je kunt het uitschakelen in <1>Algemene instellingen</1>."
|
"anonymizer_notification": "<0>Opmerking:</0> IP-anonimisering is ingeschakeld. Je kunt het uitschakelen in <1>Algemene instellingen</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Weet je zeker dat je de DNS-cache wilt wissen?",
|
||||||
|
"cache_cleared": "DNS-cache succesvol gewist",
|
||||||
|
"clear_cache": "Cache wissen"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -373,6 +373,7 @@
|
|||||||
"encryption_issuer": "Utsteder",
|
"encryption_issuer": "Utsteder",
|
||||||
"encryption_hostnames": "Vertsnavn",
|
"encryption_hostnames": "Vertsnavn",
|
||||||
"encryption_reset": "Er du sikker på at du vil tilbakestille krypteringsinnstillingene?",
|
"encryption_reset": "Er du sikker på at du vil tilbakestille krypteringsinnstillingene?",
|
||||||
|
"encryption_warning": "Advarsel",
|
||||||
"topline_expiring_certificate": "Ditt SSL-sertifikat er i ferd med å utløpe. Oppdater <0>Krypteringsinnstillinger</0>.",
|
"topline_expiring_certificate": "Ditt SSL-sertifikat er i ferd med å utløpe. Oppdater <0>Krypteringsinnstillinger</0>.",
|
||||||
"topline_expired_certificate": "SSL-sertifikatet har utløpt. Oppdater <0>Krypteringsinnstillinger</0>.",
|
"topline_expired_certificate": "SSL-sertifikatet har utløpt. Oppdater <0>Krypteringsinnstillinger</0>.",
|
||||||
"form_error_port_range": "Skriv inn et portnummer i området 80-65535",
|
"form_error_port_range": "Skriv inn et portnummer i området 80-65535",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Ustawienia serwera DHCP IPv6",
|
"dhcp_ipv6_settings": "Ustawienia serwera DHCP IPv6",
|
||||||
"form_error_required": "Pole wymagane",
|
"form_error_required": "Pole wymagane",
|
||||||
"form_error_ip4_format": "Nieprawidłowy adres IPv4",
|
"form_error_ip4_format": "Nieprawidłowy adres IPv4",
|
||||||
"form_error_ip4_range_start_format": "Nieprawidłowy adres IPv4 początku zakresu",
|
|
||||||
"form_error_ip4_range_end_format": "Nieprawidłowy adres IPv4 końca zakresu",
|
|
||||||
"form_error_ip4_gateway_format": "Nieprawidłowy adres IPv4 bramy",
|
"form_error_ip4_gateway_format": "Nieprawidłowy adres IPv4 bramy",
|
||||||
"form_error_ip6_format": "Nieprawidłowy adres IPv6",
|
"form_error_ip6_format": "Nieprawidłowy adres IPv6",
|
||||||
"form_error_ip_format": "Nieprawidłowy adres IP",
|
"form_error_ip_format": "Nieprawidłowy adres IP",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Musi być spoza zakresu \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Musi być spoza zakresu \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Musi być niższy niż początek zakresu",
|
"lower_range_start_error": "Musi być niższy niż początek zakresu",
|
||||||
"greater_range_start_error": "Musi być większy niż początek zakresu",
|
"greater_range_start_error": "Musi być większy niż początek zakresu",
|
||||||
"greater_range_end_error": "Musi być większy niż koniec zakresu",
|
|
||||||
"subnet_error": "Adresy muszą należeć do jednej podsieci",
|
"subnet_error": "Adresy muszą należeć do jednej podsieci",
|
||||||
"gateway_or_subnet_invalid": "Nieprawidłowa maska podsieci",
|
"gateway_or_subnet_invalid": "Nieprawidłowa maska podsieci",
|
||||||
"dhcp_form_gateway_input": "Adres IP bramy",
|
"dhcp_form_gateway_input": "Adres IP bramy",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Zgłaszający",
|
"encryption_issuer": "Zgłaszający",
|
||||||
"encryption_hostnames": "Nazwy hostów",
|
"encryption_hostnames": "Nazwy hostów",
|
||||||
"encryption_reset": "Czy na pewno chcesz zresetować ustawienia szyfrowania?",
|
"encryption_reset": "Czy na pewno chcesz zresetować ustawienia szyfrowania?",
|
||||||
|
"encryption_warning": "Uwaga!",
|
||||||
"topline_expiring_certificate": "Twój certyfikat SSL wkrótce wygaśnie. Zaktualizuj <0>Ustawienia szyfrowania</0>.",
|
"topline_expiring_certificate": "Twój certyfikat SSL wkrótce wygaśnie. Zaktualizuj <0>Ustawienia szyfrowania</0>.",
|
||||||
"topline_expired_certificate": "Twój certyfikat SSL wygasł. Zaktualizuj <0>Ustawienia szyfrowania</0>.",
|
"topline_expired_certificate": "Twój certyfikat SSL wygasł. Zaktualizuj <0>Ustawienia szyfrowania</0>.",
|
||||||
"form_error_port_range": "Wpisz numer portu z zakresu 80-65535",
|
"form_error_port_range": "Wpisz numer portu z zakresu 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Bezpieczne przeglądanie",
|
"safe_browsing": "Bezpieczne przeglądanie",
|
||||||
"served_from_cache": "{{value}} <i>(podawane z pamięci podręcznej)</i>",
|
"served_from_cache": "{{value}} <i>(podawane z pamięci podręcznej)</i>",
|
||||||
"form_error_password_length": "Hasło musi mieć co najmniej {{value}} znaków",
|
"form_error_password_length": "Hasło musi mieć co najmniej {{value}} znaków",
|
||||||
"anonymizer_notification": "<0>Uwaga:</0> Anonimizacja IP jest włączona. Możesz ją wyłączyć w <1>Ustawieniach ogólnych</1>."
|
"anonymizer_notification": "<0>Uwaga:</0> Anonimizacja IP jest włączona. Możesz ją wyłączyć w <1>Ustawieniach ogólnych</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Czy na pewno chcesz wyczyścić pamięć podręczną DNS?",
|
||||||
|
"cache_cleared": "Pamięć podręczna DNS została pomyślnie wyczyszczona",
|
||||||
|
"clear_cache": "Wyczyść pamięć podręczną"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Configurações DHCP IPv6",
|
"dhcp_ipv6_settings": "Configurações DHCP IPv6",
|
||||||
"form_error_required": "Campo obrigatório",
|
"form_error_required": "Campo obrigatório",
|
||||||
"form_error_ip4_format": "Endereço de IPv4 inválido",
|
"form_error_ip4_format": "Endereço de IPv4 inválido",
|
||||||
"form_error_ip4_range_start_format": "Endereço IPv4 de início de intervalo inválido",
|
|
||||||
"form_error_ip4_range_end_format": "Endereço IPv4 de fim de intervalo inválido.",
|
|
||||||
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
|
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
|
||||||
"form_error_ip6_format": "Endereço de IPv6 inválido",
|
"form_error_ip6_format": "Endereço de IPv6 inválido",
|
||||||
"form_error_ip_format": "Endereço de IP inválido",
|
"form_error_ip_format": "Endereço de IP inválido",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Deve ser inferior ao início do intervalo",
|
"lower_range_start_error": "Deve ser inferior ao início do intervalo",
|
||||||
"greater_range_start_error": "Deve ser maior que o início do intervalo",
|
"greater_range_start_error": "Deve ser maior que o início do intervalo",
|
||||||
"greater_range_end_error": "Deve ser maior que o fim do intervalo",
|
|
||||||
"subnet_error": "Endereços devem estar em uma sub-rede",
|
"subnet_error": "Endereços devem estar em uma sub-rede",
|
||||||
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
|
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
|
||||||
"dhcp_form_gateway_input": "IP do gateway",
|
"dhcp_form_gateway_input": "IP do gateway",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Emissor",
|
"encryption_issuer": "Emissor",
|
||||||
"encryption_hostnames": "Nomes dos servidores",
|
"encryption_hostnames": "Nomes dos servidores",
|
||||||
"encryption_reset": "Você tem certeza de que deseja redefinir a configuração de criptografia?",
|
"encryption_reset": "Você tem certeza de que deseja redefinir a configuração de criptografia?",
|
||||||
|
"encryption_warning": "Aviso",
|
||||||
"topline_expiring_certificate": "Seu certificado SSL está prestes a expirar. Atualize suas <0>configurações de criptografia</]0>",
|
"topline_expiring_certificate": "Seu certificado SSL está prestes a expirar. Atualize suas <0>configurações de criptografia</]0>",
|
||||||
"topline_expired_certificate": "Seu certificado SSL está expirado. Atualize suas <0>configurações de criptografia</0>",
|
"topline_expired_certificate": "Seu certificado SSL está expirado. Atualize suas <0>configurações de criptografia</0>",
|
||||||
"form_error_port_range": "Digite um número de porta entre 80 e 65535",
|
"form_error_port_range": "Digite um número de porta entre 80 e 65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navegação segura",
|
"safe_browsing": "Navegação segura",
|
||||||
"served_from_cache": "{{value}} <i>(servido do cache)</i>",
|
"served_from_cache": "{{value}} <i>(servido do cache)</i>",
|
||||||
"form_error_password_length": "A senha deve ter pelo menos {{value}} caracteres",
|
"form_error_password_length": "A senha deve ter pelo menos {{value}} caracteres",
|
||||||
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-lo em <1>Configurações gerais</1>."
|
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-lo em <1>Configurações gerais</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Tem certeza de que deseja limpar o cache DNS?",
|
||||||
|
"cache_cleared": "Cache DNS limpo com sucesso",
|
||||||
|
"clear_cache": "Limpar cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Definições DHCP IPv6",
|
"dhcp_ipv6_settings": "Definições DHCP IPv6",
|
||||||
"form_error_required": "Campo obrigatório",
|
"form_error_required": "Campo obrigatório",
|
||||||
"form_error_ip4_format": "Endereço de IPv4 inválido",
|
"form_error_ip4_format": "Endereço de IPv4 inválido",
|
||||||
"form_error_ip4_range_start_format": "Endereço IPv4 de início de intervalo inválido",
|
|
||||||
"form_error_ip4_range_end_format": "Endereço IPv4 de fim de intervalo inválido",
|
|
||||||
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
|
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
|
||||||
"form_error_ip6_format": "Endereço de IPv6 inválido",
|
"form_error_ip6_format": "Endereço de IPv6 inválido",
|
||||||
"form_error_ip_format": "Endereço de email inválido",
|
"form_error_ip_format": "Endereço de email inválido",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Deve ser inferior ao início do intervalo",
|
"lower_range_start_error": "Deve ser inferior ao início do intervalo",
|
||||||
"greater_range_start_error": "Deve ser maior que o início do intervalo",
|
"greater_range_start_error": "Deve ser maior que o início do intervalo",
|
||||||
"greater_range_end_error": "Deve ser maior que o fim do intervalo",
|
|
||||||
"subnet_error": "Os endereços devem estar em uma sub-rede",
|
"subnet_error": "Os endereços devem estar em uma sub-rede",
|
||||||
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
|
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
|
||||||
"dhcp_form_gateway_input": "IP do gateway",
|
"dhcp_form_gateway_input": "IP do gateway",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Emissor",
|
"encryption_issuer": "Emissor",
|
||||||
"encryption_hostnames": "Nomes dos servidores",
|
"encryption_hostnames": "Nomes dos servidores",
|
||||||
"encryption_reset": "Tem a certeza de que deseja repor a definição de criptografia?",
|
"encryption_reset": "Tem a certeza de que deseja repor a definição de criptografia?",
|
||||||
|
"encryption_warning": "Aviso",
|
||||||
"topline_expiring_certificate": "O seu certificado SSL está prestes a expirar. Atualize as suas <0>definições de criptografia</0>.",
|
"topline_expiring_certificate": "O seu certificado SSL está prestes a expirar. Atualize as suas <0>definições de criptografia</0>.",
|
||||||
"topline_expired_certificate": "O seu certificado SSL está expirado. Atualize as suas <0>definições de criptografia</0>.",
|
"topline_expired_certificate": "O seu certificado SSL está expirado. Atualize as suas <0>definições de criptografia</0>.",
|
||||||
"form_error_port_range": "Digite um numero de porta entre 80 e 65535",
|
"form_error_port_range": "Digite um numero de porta entre 80 e 65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navegação segura",
|
"safe_browsing": "Navegação segura",
|
||||||
"served_from_cache": "{{value}} <i>(servido do cache)</i>",
|
"served_from_cache": "{{value}} <i>(servido do cache)</i>",
|
||||||
"form_error_password_length": "A palavra-passe deve ter pelo menos {{value}} caracteres",
|
"form_error_password_length": "A palavra-passe deve ter pelo menos {{value}} caracteres",
|
||||||
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-la em <1>Definições gerais</1>."
|
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-la em <1>Definições gerais</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Tem certeza de que quer limpar a cache DNS?",
|
||||||
|
"cache_cleared": "O cache DNS foi apagado com sucesso",
|
||||||
|
"clear_cache": "Limpar cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Setări DHCP IPv6",
|
"dhcp_ipv6_settings": "Setări DHCP IPv6",
|
||||||
"form_error_required": "Câmp obligatoriu",
|
"form_error_required": "Câmp obligatoriu",
|
||||||
"form_error_ip4_format": "Adresă IPv4 nevalidă",
|
"form_error_ip4_format": "Adresă IPv4 nevalidă",
|
||||||
"form_error_ip4_range_start_format": "Adresă IPv4 nevalidă pentru începutul intervalului",
|
|
||||||
"form_error_ip4_range_end_format": "Adresă IPv4 nevalidă a sfârșitului intervalului",
|
|
||||||
"form_error_ip4_gateway_format": "Adresă IPv4 nevalidă a gateway-ului",
|
"form_error_ip4_gateway_format": "Adresă IPv4 nevalidă a gateway-ului",
|
||||||
"form_error_ip6_format": "Adresa IPv6 nevalidă",
|
"form_error_ip6_format": "Adresa IPv6 nevalidă",
|
||||||
"form_error_ip_format": "Adresă IP nevalidă",
|
"form_error_ip_format": "Adresă IP nevalidă",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Trebuie să fie în afara intervalului „{{start}}”-„{{end}}”",
|
"out_of_range_error": "Trebuie să fie în afara intervalului „{{start}}”-„{{end}}”",
|
||||||
"lower_range_start_error": "Trebuie să fie mai mică decât începutul intervalului",
|
"lower_range_start_error": "Trebuie să fie mai mică decât începutul intervalului",
|
||||||
"greater_range_start_error": "Trebuie să fie mai mare decât începutul intervalului",
|
"greater_range_start_error": "Trebuie să fie mai mare decât începutul intervalului",
|
||||||
"greater_range_end_error": "Trebuie să fie mai mare decât sfârșitul intervalului",
|
|
||||||
"subnet_error": "Adresele trebuie să fie în aceeași subrețea",
|
"subnet_error": "Adresele trebuie să fie în aceeași subrețea",
|
||||||
"gateway_or_subnet_invalid": "Mască de subrețea nevalidă",
|
"gateway_or_subnet_invalid": "Mască de subrețea nevalidă",
|
||||||
"dhcp_form_gateway_input": "IP Gateway",
|
"dhcp_form_gateway_input": "IP Gateway",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Emitent",
|
"encryption_issuer": "Emitent",
|
||||||
"encryption_hostnames": "Nume de host",
|
"encryption_hostnames": "Nume de host",
|
||||||
"encryption_reset": "Sunteți sigur că doriți să resetați setările de criptare?",
|
"encryption_reset": "Sunteți sigur că doriți să resetați setările de criptare?",
|
||||||
|
"encryption_warning": "Avertisment",
|
||||||
"topline_expiring_certificate": "Certificatul dvs. SSL este pe cale să expire. Actualizați <0>Setările de criptare</0>.",
|
"topline_expiring_certificate": "Certificatul dvs. SSL este pe cale să expire. Actualizați <0>Setările de criptare</0>.",
|
||||||
"topline_expired_certificate": "Certificatul dvs. SSL a expirat. Actualizați <0>Setările de criptare</0>.",
|
"topline_expired_certificate": "Certificatul dvs. SSL a expirat. Actualizați <0>Setările de criptare</0>.",
|
||||||
"form_error_port_range": "Introduceți valoarea portului între 80-65535",
|
"form_error_port_range": "Introduceți valoarea portului între 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Navigare în siguranță",
|
"safe_browsing": "Navigare în siguranță",
|
||||||
"served_from_cache": "{{value}} <i>(furnizat din cache)</i>",
|
"served_from_cache": "{{value}} <i>(furnizat din cache)</i>",
|
||||||
"form_error_password_length": "Parola trebuie să aibă cel puțin {{value}} caractere",
|
"form_error_password_length": "Parola trebuie să aibă cel puțin {{value}} caractere",
|
||||||
"anonymizer_notification": "<0>Nota:</0> Anonimizarea IP este activată. Puteți să o dezactivați în <1>Setări generale</1>."
|
"anonymizer_notification": "<0>Nota:</0> Anonimizarea IP este activată. Puteți să o dezactivați în <1>Setări generale</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Sunteți sigur că doriți să ștergeți memoria cache DNS?",
|
||||||
|
"cache_cleared": "Cache-ul DNS a fost golit cu succes",
|
||||||
|
"clear_cache": "Goliți memoria cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Настройки DHCP IPv6",
|
"dhcp_ipv6_settings": "Настройки DHCP IPv6",
|
||||||
"form_error_required": "Обязательное поле",
|
"form_error_required": "Обязательное поле",
|
||||||
"form_error_ip4_format": "Некорректный IPv4-адрес",
|
"form_error_ip4_format": "Некорректный IPv4-адрес",
|
||||||
"form_error_ip4_range_start_format": "Некорректный IPv4-адрес начала диапазона",
|
|
||||||
"form_error_ip4_range_end_format": "Некорректный IPv4-адрес конца диапазона",
|
|
||||||
"form_error_ip4_gateway_format": "Некорректный IPv4-адрес шлюза",
|
"form_error_ip4_gateway_format": "Некорректный IPv4-адрес шлюза",
|
||||||
"form_error_ip6_format": "Некорректный IPv6-адрес",
|
"form_error_ip6_format": "Некорректный IPv6-адрес",
|
||||||
"form_error_ip_format": "Некорректный IP-адрес",
|
"form_error_ip_format": "Некорректный IP-адрес",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Должно быть вне диапазона «{{start}}»-«{{end}}»",
|
"out_of_range_error": "Должно быть вне диапазона «{{start}}»-«{{end}}»",
|
||||||
"lower_range_start_error": "Должно быть меньше начала диапазона",
|
"lower_range_start_error": "Должно быть меньше начала диапазона",
|
||||||
"greater_range_start_error": "Должно быть больше начала диапазона",
|
"greater_range_start_error": "Должно быть больше начала диапазона",
|
||||||
"greater_range_end_error": "Должно быть больше конца диапазона",
|
|
||||||
"subnet_error": "Адреса должны быть внутри одной подсети",
|
"subnet_error": "Адреса должны быть внутри одной подсети",
|
||||||
"gateway_or_subnet_invalid": "Некорректная маска подсети",
|
"gateway_or_subnet_invalid": "Некорректная маска подсети",
|
||||||
"dhcp_form_gateway_input": "IP-адрес шлюза",
|
"dhcp_form_gateway_input": "IP-адрес шлюза",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Издатель",
|
"encryption_issuer": "Издатель",
|
||||||
"encryption_hostnames": "Имена хостов",
|
"encryption_hostnames": "Имена хостов",
|
||||||
"encryption_reset": "Вы уверены, что хотите сбросить настройки шифрования?",
|
"encryption_reset": "Вы уверены, что хотите сбросить настройки шифрования?",
|
||||||
|
"encryption_warning": "Предупреждение",
|
||||||
"topline_expiring_certificate": "Ваш SSL-сертификат скоро истекает. Обновите <0>Настройки шифрования</0>.",
|
"topline_expiring_certificate": "Ваш SSL-сертификат скоро истекает. Обновите <0>Настройки шифрования</0>.",
|
||||||
"topline_expired_certificate": "Ваш SSL-сертификат истёк. Обновите <0>Настройки шифрования</0>.",
|
"topline_expired_certificate": "Ваш SSL-сертификат истёк. Обновите <0>Настройки шифрования</0>.",
|
||||||
"form_error_port_range": "Введите номер порта из интервала 80-65535",
|
"form_error_port_range": "Введите номер порта из интервала 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Безопасный интернет",
|
"safe_browsing": "Безопасный интернет",
|
||||||
"served_from_cache": "{{value}} <i>(получено из кеша)</i>",
|
"served_from_cache": "{{value}} <i>(получено из кеша)</i>",
|
||||||
"form_error_password_length": "Пароль должен быть длиной не меньше {{value}} символов",
|
"form_error_password_length": "Пароль должен быть длиной не меньше {{value}} символов",
|
||||||
"anonymizer_notification": "<0>Внимание:</0> включена анонимизация IP-адресов. Вы можете отключить её в разделе <1>Основные настройки</1>."
|
"anonymizer_notification": "<0>Внимание:</0> включена анонимизация IP-адресов. Вы можете отключить её в разделе <1>Основные настройки</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Вы уверены, что хотите очистить кеш DNS?",
|
||||||
|
"cache_cleared": "Кеш DNS успешно очищен",
|
||||||
|
"clear_cache": "Очистить кеш"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
"number_of_dns_query_to_safe_search": "ආරක්ෂිත සෙවීම බලාත්මක කළ සෙවුම් යන්ත්ර සඳහා ව.නා.ප. ඉල්ලීම් ගණන",
|
"number_of_dns_query_to_safe_search": "ආරක්ෂිත සෙවීම බලාත්මක කළ සෙවුම් යන්ත්ර සඳහා ව.නා.ප. ඉල්ලීම් ගණන",
|
||||||
"average_processing_time": "සාමාන්ය සැකසුම් කාලය",
|
"average_processing_time": "සාමාන්ය සැකසුම් කාලය",
|
||||||
"average_processing_time_hint": "ව.නා.ප. ඉල්ලීමක් සැකසීමේ සාමාන්ය කාලය මිලි තත්පර වලින්",
|
"average_processing_time_hint": "ව.නා.ප. ඉල්ලීමක් සැකසීමේ සාමාන්ය කාලය මිලි තත්පර වලින්",
|
||||||
"block_domain_use_filters_and_hosts": "පෙරහන් සහ ධාරක ගොනු භාවිතා කරමින් වසම් අවහිර කරන්න",
|
"block_domain_use_filters_and_hosts": "පෙරහන් හා සත්කාරක ගොනු භාවිතයෙන් වසම් අවහිර කරන්න",
|
||||||
"filters_block_toggle_hint": "ඔබට අවහිර කිරීමේ නීති <a>පෙරහන්</a> තුළ පිහිටුවිය හැකිය.",
|
"filters_block_toggle_hint": "ඔබට අවහිර කිරීමේ නීති <a>පෙරහන්</a> තුළ පිහිටුවිය හැකිය.",
|
||||||
"use_adguard_browsing_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ වියමන සේවාව භාවිතා කරන්න",
|
"use_adguard_browsing_sec": "ඇඩ්ගාර්ඩ් පිරික්සුම් ආරක්ෂණ වියමන සේවාව භාවිතා කරන්න",
|
||||||
"use_adguard_browsing_sec_hint": "ඇඩ්ගාර්ඩ් හෝම් විසින් පිරික්සුම් ආරක්ෂණ වියමන සේවාව මගින් වසම අවහිර කර ඇත්දැයි පරීක්ෂා කරයි. එය සිදු කිරීමට රහස්යතා-හිතකාමී බැලීමේ යෙ.ක්ර.මු. භාවිතා කෙරේ: වසමේ කෙටි උපසර්ගයක SHA256 පූරකයක් පමණක් සේවාදායකය වෙත යවනු ලැබේ.",
|
"use_adguard_browsing_sec_hint": "ඇඩ්ගාර්ඩ් හෝම් විසින් පිරික්සුම් ආරක්ෂණ වියමන සේවාව මගින් වසම අවහිර කර ඇත්දැයි පරීක්ෂා කරයි. එය සිදු කිරීමට රහස්යතා-හිතකාමී බැලීමේ යෙ.ක්ර.මු. භාවිතා කෙරේ: වසමේ කෙටි උපසර්ගයක SHA256 පූරකයක් පමණක් සේවාදායකය වෙත යවනු ලැබේ.",
|
||||||
@@ -575,7 +575,7 @@
|
|||||||
"blocklist": "අවහිර කිරීමේ ලැයිස්තුව",
|
"blocklist": "අවහිර කිරීමේ ලැයිස්තුව",
|
||||||
"milliseconds_abbreviation": "මිලි තත්.",
|
"milliseconds_abbreviation": "මිලි තත්.",
|
||||||
"cache_size": "නිහිතයෙහි ප්රමාණය",
|
"cache_size": "නිහිතයෙහි ප්රමාණය",
|
||||||
"cache_size_desc": "ව.නා.ප. නිහිතයෙහි ප්රමාණය (බයිට)",
|
"cache_size_desc": "ව.නා.ප. නිහිතයෙහි ප්රමාණය (බයිට). නිහිතය අබල කිරීමට, හිස්ව තබන්න.",
|
||||||
"cache_ttl_min_override": "අවම පව. කා. අභිබවන්න",
|
"cache_ttl_min_override": "අවම පව. කා. අභිබවන්න",
|
||||||
"cache_ttl_max_override": "උපරිම පව. කා. අභිබවන්න",
|
"cache_ttl_max_override": "උපරිම පව. කා. අභිබවන්න",
|
||||||
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්රමාණය යොදන්න (බයිට)",
|
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්රමාණය යොදන්න (බයිට)",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Nastavenia DHCP IPv6",
|
"dhcp_ipv6_settings": "Nastavenia DHCP IPv6",
|
||||||
"form_error_required": "Povinná položka.",
|
"form_error_required": "Povinná položka.",
|
||||||
"form_error_ip4_format": "Neplatná IPv4 adresa",
|
"form_error_ip4_format": "Neplatná IPv4 adresa",
|
||||||
"form_error_ip4_range_start_format": "Neplatný začiatok rozsahu IPv4 formátu",
|
|
||||||
"form_error_ip4_range_end_format": "Neplatný koniec rozsahu IPv4 formátu",
|
|
||||||
"form_error_ip4_gateway_format": "Neplatná IPv4 adresa brány",
|
"form_error_ip4_gateway_format": "Neplatná IPv4 adresa brány",
|
||||||
"form_error_ip6_format": "Neplatná IPv6 adresa",
|
"form_error_ip6_format": "Neplatná IPv6 adresa",
|
||||||
"form_error_ip_format": "Neplatná IP adresa",
|
"form_error_ip_format": "Neplatná IP adresa",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Musí byť mimo rozsahu \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Musí byť mimo rozsahu \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Musí byť nižšie ako začiatok rozsahu",
|
"lower_range_start_error": "Musí byť nižšie ako začiatok rozsahu",
|
||||||
"greater_range_start_error": "Musí byť väčšie ako začiatok rozsahu",
|
"greater_range_start_error": "Musí byť väčšie ako začiatok rozsahu",
|
||||||
"greater_range_end_error": "Musí byť väčšie ako koniec rozsahu",
|
|
||||||
"subnet_error": "Adresy musia byť v spoločnej podsieti",
|
"subnet_error": "Adresy musia byť v spoločnej podsieti",
|
||||||
"gateway_or_subnet_invalid": "Maska podsiete je neplatná",
|
"gateway_or_subnet_invalid": "Maska podsiete je neplatná",
|
||||||
"dhcp_form_gateway_input": "IP brána",
|
"dhcp_form_gateway_input": "IP brána",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Vydavateľ",
|
"encryption_issuer": "Vydavateľ",
|
||||||
"encryption_hostnames": "Názvy hostiteľov",
|
"encryption_hostnames": "Názvy hostiteľov",
|
||||||
"encryption_reset": "Naozaj chcete obnoviť nastavenia šifrovania?",
|
"encryption_reset": "Naozaj chcete obnoviť nastavenia šifrovania?",
|
||||||
|
"encryption_warning": "Varovanie",
|
||||||
"topline_expiring_certificate": "Váš SSL certifikát čoskoro vyprší. Aktualizujte <0>Nastavenia šifrovania</0>.",
|
"topline_expiring_certificate": "Váš SSL certifikát čoskoro vyprší. Aktualizujte <0>Nastavenia šifrovania</0>.",
|
||||||
"topline_expired_certificate": "Váš SSL certifikát vypršal. Aktualizujte <0>Nastavenia šifrovania</0>.",
|
"topline_expired_certificate": "Váš SSL certifikát vypršal. Aktualizujte <0>Nastavenia šifrovania</0>.",
|
||||||
"form_error_port_range": "Zadajte číslo portu v rozsahu 80-65535",
|
"form_error_port_range": "Zadajte číslo portu v rozsahu 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Bezpečné prehliadanie",
|
"safe_browsing": "Bezpečné prehliadanie",
|
||||||
"served_from_cache": "{{value}} <i>(prevzatá z cache pamäte)</i>",
|
"served_from_cache": "{{value}} <i>(prevzatá z cache pamäte)</i>",
|
||||||
"form_error_password_length": "Heslo musí mať dĺžku aspoň {{value}} znakov",
|
"form_error_password_length": "Heslo musí mať dĺžku aspoň {{value}} znakov",
|
||||||
"anonymizer_notification": "<0>Poznámka:</0> Anonymizácia IP je zapnutá. Môžete ju vypnúť vo <1>Všeobecných nastaveniach</1>."
|
"anonymizer_notification": "<0>Poznámka:</0> Anonymizácia IP je zapnutá. Môžete ju vypnúť vo <1>Všeobecných nastaveniach</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Naozaj chcete vymazať vyrovnávaciu pamäť DNS?",
|
||||||
|
"cache_cleared": "Vyrovnávacia pamäť DNS bola úspešne vymazaná",
|
||||||
|
"clear_cache": "Vymazať vyrovnávaciu pamäť"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Nastavitve DHCP IPv6",
|
"dhcp_ipv6_settings": "Nastavitve DHCP IPv6",
|
||||||
"form_error_required": "Zahtevano polje.",
|
"form_error_required": "Zahtevano polje.",
|
||||||
"form_error_ip4_format": "Neveljaven naslov IPv4.",
|
"form_error_ip4_format": "Neveljaven naslov IPv4.",
|
||||||
"form_error_ip4_range_start_format": "Neveljaven začetek razpona naslova IPv4",
|
|
||||||
"form_error_ip4_range_end_format": "Neveljaven konec razpona naslova IPv4",
|
|
||||||
"form_error_ip4_gateway_format": "Neveljaven naslov IPv4 prehoda",
|
"form_error_ip4_gateway_format": "Neveljaven naslov IPv4 prehoda",
|
||||||
"form_error_ip6_format": "Neveljaven naslov IPv6",
|
"form_error_ip6_format": "Neveljaven naslov IPv6",
|
||||||
"form_error_ip_format": "Neveljaven naslov IP",
|
"form_error_ip_format": "Neveljaven naslov IP",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Mora biti izven razpona \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Mora biti izven razpona \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Mora biti manjši od začetka razpona",
|
"lower_range_start_error": "Mora biti manjši od začetka razpona",
|
||||||
"greater_range_start_error": "Mora biti večji od začetka razpona",
|
"greater_range_start_error": "Mora biti večji od začetka razpona",
|
||||||
"greater_range_end_error": "Mora biti večji od konca razpona",
|
|
||||||
"subnet_error": "Naslovi morajo biti v enem podomrežju",
|
"subnet_error": "Naslovi morajo biti v enem podomrežju",
|
||||||
"gateway_or_subnet_invalid": "Maska podomrežja ni veljavna",
|
"gateway_or_subnet_invalid": "Maska podomrežja ni veljavna",
|
||||||
"dhcp_form_gateway_input": "IP prehoda",
|
"dhcp_form_gateway_input": "IP prehoda",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Izdajatelj",
|
"encryption_issuer": "Izdajatelj",
|
||||||
"encryption_hostnames": "Imena gostiteljev",
|
"encryption_hostnames": "Imena gostiteljev",
|
||||||
"encryption_reset": "Ali ste prepričani, da želite ponastaviti nastavitve šifriranja?",
|
"encryption_reset": "Ali ste prepričani, da želite ponastaviti nastavitve šifriranja?",
|
||||||
|
"encryption_warning": "Opozorilo",
|
||||||
"topline_expiring_certificate": "Vaš e digitalno potrdilo SSL bo kmalu poteklol. Posodobite <0>Nastavitve šifriranja</0>.",
|
"topline_expiring_certificate": "Vaš e digitalno potrdilo SSL bo kmalu poteklol. Posodobite <0>Nastavitve šifriranja</0>.",
|
||||||
"topline_expired_certificate": "Vaše digitalno potrdilo SSL je poteklo. Posodobi <0>Nastavitve šifriranja</0>.",
|
"topline_expired_certificate": "Vaše digitalno potrdilo SSL je poteklo. Posodobi <0>Nastavitve šifriranja</0>.",
|
||||||
"form_error_port_range": "Vnesite številko vrat v razponu med 80-65535",
|
"form_error_port_range": "Vnesite številko vrat v razponu med 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Varno brskanje",
|
"safe_browsing": "Varno brskanje",
|
||||||
"served_from_cache": "{{value}} <i>(postreženo iz predpomnilnika)</i>",
|
"served_from_cache": "{{value}} <i>(postreženo iz predpomnilnika)</i>",
|
||||||
"form_error_password_length": "Geslo mora vsebovati najmanj {{value}} znakov",
|
"form_error_password_length": "Geslo mora vsebovati najmanj {{value}} znakov",
|
||||||
"anonymizer_notification": "<0>Opomba:</0> Anonimizacija IP je omogočena. Onemogočite ga lahko v <1>Splošnih nastavitvah</1>."
|
"anonymizer_notification": "<0>Opomba:</0> Anonimizacija IP je omogočena. Onemogočite ga lahko v <1>Splošnih nastavitvah</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Ali ste prepričani, da želite počistiti predpomnilnik DNS?",
|
||||||
|
"cache_cleared": "Predpomnilnik DNS je bil uspešno počiščen",
|
||||||
|
"clear_cache": "Počisti predpomnilnik"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 postavke",
|
"dhcp_ipv6_settings": "DHCP IPv6 postavke",
|
||||||
"form_error_required": "Obavezno polje",
|
"form_error_required": "Obavezno polje",
|
||||||
"form_error_ip4_format": "Nevažeća IPv4 adresa",
|
"form_error_ip4_format": "Nevažeća IPv4 adresa",
|
||||||
"form_error_ip4_range_start_format": "Nevažeća IPv4 addresa početnog opsega",
|
|
||||||
"form_error_ip4_range_end_format": "Nevažeća IPv4 addresa završnog opsega",
|
|
||||||
"form_error_ip4_gateway_format": "Nevažeća IPv4 addresa prozala",
|
"form_error_ip4_gateway_format": "Nevažeća IPv4 addresa prozala",
|
||||||
"form_error_ip6_format": "Nevažeća IPv6 adresa",
|
"form_error_ip6_format": "Nevažeća IPv6 adresa",
|
||||||
"form_error_ip_format": "Nevažeća IP adresa",
|
"form_error_ip_format": "Nevažeća IP adresa",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Mora biti izvan opsega \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Mora biti izvan opsega \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Mora biti manje od početnog opsega",
|
"lower_range_start_error": "Mora biti manje od početnog opsega",
|
||||||
"greater_range_start_error": "Mora biti veće od početnog opsega",
|
"greater_range_start_error": "Mora biti veće od početnog opsega",
|
||||||
"greater_range_end_error": "Mora biti veće od završnog opsega",
|
|
||||||
"subnet_error": "Asrese moraju biti u jednoj subnet",
|
"subnet_error": "Asrese moraju biti u jednoj subnet",
|
||||||
"gateway_or_subnet_invalid": "Subnet mask nevažeća",
|
"gateway_or_subnet_invalid": "Subnet mask nevažeća",
|
||||||
"dhcp_form_gateway_input": "IP mrežnog prolaza",
|
"dhcp_form_gateway_input": "IP mrežnog prolaza",
|
||||||
@@ -215,7 +212,7 @@
|
|||||||
"example_upstream_udp": "uobičajen DNS (preko UDP, imena domaćina);",
|
"example_upstream_udp": "uobičajen DNS (preko UDP, imena domaćina);",
|
||||||
"example_upstream_dot": "šifrovano <0>DNS-over-TLS</0>;",
|
"example_upstream_dot": "šifrovano <0>DNS-over-TLS</0>;",
|
||||||
"example_upstream_doh": "šifrovano <0>DNS-over-HTTPS</0>;",
|
"example_upstream_doh": "šifrovano <0>DNS-over-HTTPS</0>;",
|
||||||
"example_upstream_doh3": "šifrovani DNS-over-HTTPS sa prinudnim <0>HTTP/3</0> i bez povratka na HTTP/2 ili ispod;",
|
"example_upstream_doh3": "šifrovani DNS-over-HTTPS sa prinudnim <0>HTTP/3</0> bez povratka na HTTP/2 ili ispod;",
|
||||||
"example_upstream_doq": "šifrovano <0>DNS-over-QUIC</0>;",
|
"example_upstream_doq": "šifrovano <0>DNS-over-QUIC</0>;",
|
||||||
"example_upstream_sdns": "<0>DNS brojeve</0> za <1>DNSCrypt</1> ili <2>DNS-over-HTTPS</2> razrešivače;",
|
"example_upstream_sdns": "<0>DNS brojeve</0> za <1>DNSCrypt</1> ili <2>DNS-over-HTTPS</2> razrešivače;",
|
||||||
"example_upstream_tcp": "uobičajeni DNS (preko TCP);",
|
"example_upstream_tcp": "uobičajeni DNS (preko TCP);",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Izdavač",
|
"encryption_issuer": "Izdavač",
|
||||||
"encryption_hostnames": "Imena hostova",
|
"encryption_hostnames": "Imena hostova",
|
||||||
"encryption_reset": "Jeste li sigurni da želite dda resetujete postavke šifrovanja?",
|
"encryption_reset": "Jeste li sigurni da želite dda resetujete postavke šifrovanja?",
|
||||||
|
"encryption_warning": "Upozorenje",
|
||||||
"topline_expiring_certificate": "Vaš SSL sertifikat uskoro ističe. Ažurirajte <0>postavke šifrovanja</0>.",
|
"topline_expiring_certificate": "Vaš SSL sertifikat uskoro ističe. Ažurirajte <0>postavke šifrovanja</0>.",
|
||||||
"topline_expired_certificate": "Vaš SSL sertifikat je istekao. Ažurirajte <0>postavke šifrovanja</0>.",
|
"topline_expired_certificate": "Vaš SSL sertifikat je istekao. Ažurirajte <0>postavke šifrovanja</0>.",
|
||||||
"form_error_port_range": "Unesite vrednost porta u opsegu od 80-65535",
|
"form_error_port_range": "Unesite vrednost porta u opsegu od 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Sigurno pregledanje",
|
"safe_browsing": "Sigurno pregledanje",
|
||||||
"served_from_cache": "{{value}} <i>(posluženo iz predmemorije)</i>",
|
"served_from_cache": "{{value}} <i>(posluženo iz predmemorije)</i>",
|
||||||
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
|
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
|
||||||
"anonymizer_notification": "<0>Nota:</0> IP prepoznavanje je omogućeno. Možete ga onemogućiti u opštim <1>postavkama</1>."
|
"anonymizer_notification": "<0>Nota:</0> IP prepoznavanje je omogućeno. Možete ga onemogućiti u opštim <1>postavkama</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Želite li zaista da obrišite DNS keš?",
|
||||||
|
"cache_cleared": "DNS keš je uspešno očišćen",
|
||||||
|
"clear_cache": "Obriši keš memoriju"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 inställningar",
|
"dhcp_ipv6_settings": "DHCP IPv6 inställningar",
|
||||||
"form_error_required": "Obligatoriskt fält",
|
"form_error_required": "Obligatoriskt fält",
|
||||||
"form_error_ip4_format": "Ogiltig IPv4-adress",
|
"form_error_ip4_format": "Ogiltig IPv4-adress",
|
||||||
"form_error_ip4_range_start_format": "Ogiltig IPv4-adress för starten av intervallet",
|
|
||||||
"form_error_ip4_range_end_format": "Ogiltig IPv4-adress för slutet av intervallet",
|
|
||||||
"form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen",
|
"form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen",
|
||||||
"form_error_ip6_format": "Ogiltig IPv6-adress",
|
"form_error_ip6_format": "Ogiltig IPv6-adress",
|
||||||
"form_error_ip_format": "Ogiltig IP-adress",
|
"form_error_ip_format": "Ogiltig IP-adress",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Måste vara lägre än starten på intervallet",
|
"lower_range_start_error": "Måste vara lägre än starten på intervallet",
|
||||||
"greater_range_start_error": "Måste vara högre än starten på intervallet",
|
"greater_range_start_error": "Måste vara högre än starten på intervallet",
|
||||||
"greater_range_end_error": "Måste vara större än intervallets slut",
|
|
||||||
"subnet_error": "Adresser måste finnas i ett subnät",
|
"subnet_error": "Adresser måste finnas i ett subnät",
|
||||||
"gateway_or_subnet_invalid": "Subnätmask ogiltig",
|
"gateway_or_subnet_invalid": "Subnätmask ogiltig",
|
||||||
"dhcp_form_gateway_input": "Gateway-IP",
|
"dhcp_form_gateway_input": "Gateway-IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Utgivare",
|
"encryption_issuer": "Utgivare",
|
||||||
"encryption_hostnames": "Värdnamn",
|
"encryption_hostnames": "Värdnamn",
|
||||||
"encryption_reset": "Är du säker på att du vill återställa krypteringsinställningarna?",
|
"encryption_reset": "Är du säker på att du vill återställa krypteringsinställningarna?",
|
||||||
|
"encryption_warning": "Varning",
|
||||||
"topline_expiring_certificate": "Ditt SSL-certifikat håller på att gå ut. <0>Krypteringsinställningar</0>.",
|
"topline_expiring_certificate": "Ditt SSL-certifikat håller på att gå ut. <0>Krypteringsinställningar</0>.",
|
||||||
"topline_expired_certificate": "Ditt SSL-certifikat har gått ut. Uppdatera <0>Krypteringsinställningar</0>-",
|
"topline_expired_certificate": "Ditt SSL-certifikat har gått ut. Uppdatera <0>Krypteringsinställningar</0>-",
|
||||||
"form_error_port_range": "Ange ett portnummer inom värdena 80-65535",
|
"form_error_port_range": "Ange ett portnummer inom värdena 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Säker surfning",
|
"safe_browsing": "Säker surfning",
|
||||||
"served_from_cache": "{{value}} <i>(levereras från cache)</i>",
|
"served_from_cache": "{{value}} <i>(levereras från cache)</i>",
|
||||||
"form_error_password_length": "Lösenordet måste vara minst {{value}} tecken långt",
|
"form_error_password_length": "Lösenordet måste vara minst {{value}} tecken långt",
|
||||||
"anonymizer_notification": "<0>Observera:</0> IP-anonymisering är aktiverad. Du kan inaktivera den i <1>Allmänna inställningar</1>."
|
"anonymizer_notification": "<0>Observera:</0> IP-anonymisering är aktiverad. Du kan inaktivera den i <1>Allmänna inställningar</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Är du säker på att du vill rensa DNS-cache?",
|
||||||
|
"cache_cleared": "DNS-cacheminnet har rensats",
|
||||||
|
"clear_cache": "Rensa cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,6 +262,7 @@
|
|||||||
"encryption_issuer": "ผู้ออกใบรับรอง:",
|
"encryption_issuer": "ผู้ออกใบรับรอง:",
|
||||||
"encryption_hostnames": "ชื่อโฮส",
|
"encryption_hostnames": "ชื่อโฮส",
|
||||||
"encryption_reset": "คุณแน่ใจนะว่าจะล้างค่าการเข้ารหัส?",
|
"encryption_reset": "คุณแน่ใจนะว่าจะล้างค่าการเข้ารหัส?",
|
||||||
|
"encryption_warning": "คำเตือน",
|
||||||
"topline_expiring_certificate": "ใบรับรอง SSL ของคุณกำลังจะหมดอายุ กรุณาอัปเดท <0>การตั้งค่าเข้ารหัส</0>.",
|
"topline_expiring_certificate": "ใบรับรอง SSL ของคุณกำลังจะหมดอายุ กรุณาอัปเดท <0>การตั้งค่าเข้ารหัส</0>.",
|
||||||
"topline_expired_certificate": "ใบรับรอง SSL ของคุณหมดอายุแล้ว กรุณาอัปเดท <0>การตั้งค่าเข้ารหัส</0>.",
|
"topline_expired_certificate": "ใบรับรอง SSL ของคุณหมดอายุแล้ว กรุณาอัปเดท <0>การตั้งค่าเข้ารหัส</0>.",
|
||||||
"form_error_port_unsafe": "เป็นพอร์ทที่ไม่ปลอดภัย",
|
"form_error_port_unsafe": "เป็นพอร์ทที่ไม่ปลอดภัย",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 Ayarları",
|
"dhcp_ipv6_settings": "DHCP IPv6 Ayarları",
|
||||||
"form_error_required": "Gerekli alan",
|
"form_error_required": "Gerekli alan",
|
||||||
"form_error_ip4_format": "Geçersiz IPv4 adresi",
|
"form_error_ip4_format": "Geçersiz IPv4 adresi",
|
||||||
"form_error_ip4_range_start_format": "Geçersiz başlangıç aralığı IPv4 biçimi",
|
|
||||||
"form_error_ip4_range_end_format": "Geçersiz bitiş aralığı IPv4 adresi",
|
|
||||||
"form_error_ip4_gateway_format": "Geçersiz ağ geçidi IPv4 adresi",
|
"form_error_ip4_gateway_format": "Geçersiz ağ geçidi IPv4 adresi",
|
||||||
"form_error_ip6_format": "Geçersiz IPv6 adresi",
|
"form_error_ip6_format": "Geçersiz IPv6 adresi",
|
||||||
"form_error_ip_format": "Geçersiz IP adresi",
|
"form_error_ip_format": "Geçersiz IP adresi",
|
||||||
@@ -51,9 +49,8 @@
|
|||||||
"out_of_range_error": "\"{{start}}\"-\"{{end}}\" aralığının dışında olmalıdır",
|
"out_of_range_error": "\"{{start}}\"-\"{{end}}\" aralığının dışında olmalıdır",
|
||||||
"lower_range_start_error": "Başlangıç aralığından daha düşük olmalıdır",
|
"lower_range_start_error": "Başlangıç aralığından daha düşük olmalıdır",
|
||||||
"greater_range_start_error": "Başlangıç aralığından daha büyük olmalıdır",
|
"greater_range_start_error": "Başlangıç aralığından daha büyük olmalıdır",
|
||||||
"greater_range_end_error": "Bitiş aralığından daha büyük olmalıdır",
|
|
||||||
"subnet_error": "Adresler bir alt ağda olmalıdır",
|
"subnet_error": "Adresler bir alt ağda olmalıdır",
|
||||||
"gateway_or_subnet_invalid": "Alt ağ maskesi geçersiz",
|
"gateway_or_subnet_invalid": "Geçersiz alt ağ maskesi",
|
||||||
"dhcp_form_gateway_input": "Ağ geçidi IP",
|
"dhcp_form_gateway_input": "Ağ geçidi IP",
|
||||||
"dhcp_form_subnet_input": "Alt ağ maskesi",
|
"dhcp_form_subnet_input": "Alt ağ maskesi",
|
||||||
"dhcp_form_range_title": "IP adresi aralığı",
|
"dhcp_form_range_title": "IP adresi aralığı",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Sağlayan",
|
"encryption_issuer": "Sağlayan",
|
||||||
"encryption_hostnames": "Ana makine adları",
|
"encryption_hostnames": "Ana makine adları",
|
||||||
"encryption_reset": "Şifreleme ayarlarını sıfırlamak istediğinizden emin misiniz?",
|
"encryption_reset": "Şifreleme ayarlarını sıfırlamak istediğinizden emin misiniz?",
|
||||||
|
"encryption_warning": "Uyarı",
|
||||||
"topline_expiring_certificate": "SSL sertifikanızın süresi sona üzere. <0>Şifreleme ayarlarını</0> güncelleyin.",
|
"topline_expiring_certificate": "SSL sertifikanızın süresi sona üzere. <0>Şifreleme ayarlarını</0> güncelleyin.",
|
||||||
"topline_expired_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını</0> güncelleyin.",
|
"topline_expired_certificate": "SSL sertifikanızın süresi sona erdi. <0>Şifreleme ayarlarını</0> güncelleyin.",
|
||||||
"form_error_port_range": "80-65535 aralığında geçerli bir bağlantı noktası değeri girin",
|
"form_error_port_range": "80-65535 aralığında geçerli bir bağlantı noktası değeri girin",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Güvenli Gezinti",
|
"safe_browsing": "Güvenli Gezinti",
|
||||||
"served_from_cache": "{{value}} <i>(önbellekten kullanıldı)</i>",
|
"served_from_cache": "{{value}} <i>(önbellekten kullanıldı)</i>",
|
||||||
"form_error_password_length": "Parola en az {{value}} karakter uzunluğunda olmalıdır",
|
"form_error_password_length": "Parola en az {{value}} karakter uzunluğunda olmalıdır",
|
||||||
"anonymizer_notification": "<0>Not:</0> IP anonimleştirme etkinleştirildi. Bunu <1>Genel ayarlardan</1> devre dışı bırakabilirsiniz."
|
"anonymizer_notification": "<0>Not:</0> IP anonimleştirme etkinleştirildi. Bunu <1>Genel ayarlardan</1> devre dışı bırakabilirsiniz.",
|
||||||
|
"confirm_dns_cache_clear": "DNS önbelleğini temizlemek istediğinizden emin misiniz?",
|
||||||
|
"cache_cleared": "DNS önbelleği başarıyla temizlendi",
|
||||||
|
"clear_cache": "Önbelleği temizle"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Налаштування DHCP IPv6",
|
"dhcp_ipv6_settings": "Налаштування DHCP IPv6",
|
||||||
"form_error_required": "Обов'язкове поле",
|
"form_error_required": "Обов'язкове поле",
|
||||||
"form_error_ip4_format": "Неправильна IPv4-адреса",
|
"form_error_ip4_format": "Неправильна IPv4-адреса",
|
||||||
"form_error_ip4_range_start_format": "Неправильна IPv4-адреса початку діапазону",
|
|
||||||
"form_error_ip4_range_end_format": "Неправильна IPv4-адреса кінця діапазону",
|
|
||||||
"form_error_ip4_gateway_format": "Неправильна IPv4-адреса шлюзу",
|
"form_error_ip4_gateway_format": "Неправильна IPv4-адреса шлюзу",
|
||||||
"form_error_ip6_format": "Неправильна IPv6-адреса",
|
"form_error_ip6_format": "Неправильна IPv6-адреса",
|
||||||
"form_error_ip_format": "Неправильна IP-адреса",
|
"form_error_ip_format": "Неправильна IP-адреса",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Не повинна бути в діапазоні «{{start}}»−«{{end}}»",
|
"out_of_range_error": "Не повинна бути в діапазоні «{{start}}»−«{{end}}»",
|
||||||
"lower_range_start_error": "Має бути меншим за початкову адресу",
|
"lower_range_start_error": "Має бути меншим за початкову адресу",
|
||||||
"greater_range_start_error": "Має бути більшим за початкову адресу",
|
"greater_range_start_error": "Має бути більшим за початкову адресу",
|
||||||
"greater_range_end_error": "Має бути більшим за кінцеву адресу",
|
|
||||||
"subnet_error": "Адреси повинні бути в одній підмережі",
|
"subnet_error": "Адреси повинні бути в одній підмережі",
|
||||||
"gateway_or_subnet_invalid": "Неправильна маска підмережі",
|
"gateway_or_subnet_invalid": "Неправильна маска підмережі",
|
||||||
"dhcp_form_gateway_input": "IP-адреса шлюзу",
|
"dhcp_form_gateway_input": "IP-адреса шлюзу",
|
||||||
@@ -371,7 +368,7 @@
|
|||||||
"encryption_redirect": "Автоматично перенаправляти на HTTPS",
|
"encryption_redirect": "Автоматично перенаправляти на HTTPS",
|
||||||
"encryption_redirect_desc": "Якщо встановлено, AdGuard Home автоматично перенаправить вас з HTTP на адреси HTTPS.",
|
"encryption_redirect_desc": "Якщо встановлено, AdGuard Home автоматично перенаправить вас з HTTP на адреси HTTPS.",
|
||||||
"encryption_https": "Порт HTTPS",
|
"encryption_https": "Порт HTTPS",
|
||||||
"encryption_https_desc": "Якщо HTTPS-порт налаштовано, інтерфейс адміністратора AdGuard Home буде доступний через HTTPS, а також DNS-over-HTTPS-сервер буде доступний за адресою /dns-query.",
|
"encryption_https_desc": "Якщо HTTPS-порт налаштовано, інтерфейс адміністратора AdGuard Home буде доступний через HTTPS, а також сервер DNS-over-HTTPS буде доступний за адресою '/dns-query'.",
|
||||||
"encryption_dot": "Порт DNS-over-TLS",
|
"encryption_dot": "Порт DNS-over-TLS",
|
||||||
"encryption_dot_desc": "Якщо цей порт налаштовано, AdGuard Home запустить на цьому порту сервер DNS-over-TLS.",
|
"encryption_dot_desc": "Якщо цей порт налаштовано, AdGuard Home запустить на цьому порту сервер DNS-over-TLS.",
|
||||||
"encryption_doq": "Порт DNS-over-QUIC",
|
"encryption_doq": "Порт DNS-over-QUIC",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Видавець",
|
"encryption_issuer": "Видавець",
|
||||||
"encryption_hostnames": "Назви вузлів",
|
"encryption_hostnames": "Назви вузлів",
|
||||||
"encryption_reset": "Ви впевнені, що хочете скинути налаштування шифрування?",
|
"encryption_reset": "Ви впевнені, що хочете скинути налаштування шифрування?",
|
||||||
|
"encryption_warning": "Попередження",
|
||||||
"topline_expiring_certificate": "Ваш сертифікат SSL скоро закінчиться. Оновіть <0>Налаштування шифрування</0>.",
|
"topline_expiring_certificate": "Ваш сертифікат SSL скоро закінчиться. Оновіть <0>Налаштування шифрування</0>.",
|
||||||
"topline_expired_certificate": "Термін дії вашого сертифіката SSL закінчився. Оновіть <0>Налаштування шифрування</0>.",
|
"topline_expired_certificate": "Термін дії вашого сертифіката SSL закінчився. Оновіть <0>Налаштування шифрування</0>.",
|
||||||
"form_error_port_range": "Введіть значення порту в діапазоні 80−65535",
|
"form_error_port_range": "Введіть значення порту в діапазоні 80−65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Безпечний перегляд",
|
"safe_browsing": "Безпечний перегляд",
|
||||||
"served_from_cache": "{{value}} <i>(отримано з кешу)</i>",
|
"served_from_cache": "{{value}} <i>(отримано з кешу)</i>",
|
||||||
"form_error_password_length": "Пароль мусить мати принаймні {{value}} символів",
|
"form_error_password_length": "Пароль мусить мати принаймні {{value}} символів",
|
||||||
"anonymizer_notification": "<0>Примітка:</0> IP-анонімізацію ввімкнено. Ви можете вимкнути його в <1>Загальні налаштування</1> ."
|
"anonymizer_notification": "<0>Примітка:</0> IP-анонімізацію ввімкнено. Ви можете вимкнути його в <1>Загальні налаштування</1> .",
|
||||||
|
"confirm_dns_cache_clear": "Ви впевнені, що бажаєте очистити кеш DNS?",
|
||||||
|
"cache_cleared": "Кеш DNS успішно очищено",
|
||||||
|
"clear_cache": "Очистити кеш"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "Cài đặt DHCP IPv6",
|
"dhcp_ipv6_settings": "Cài đặt DHCP IPv6",
|
||||||
"form_error_required": "Trường bắt buộc",
|
"form_error_required": "Trường bắt buộc",
|
||||||
"form_error_ip4_format": "Địa chỉ IPv4 không hợp lệ",
|
"form_error_ip4_format": "Địa chỉ IPv4 không hợp lệ",
|
||||||
"form_error_ip4_range_start_format": "Địa chỉ IPv4 không hợp lệ của phạm vi bắt đầu",
|
|
||||||
"form_error_ip4_range_end_format": "Địa chỉ IPv4 không hợp lệ của cuối phạm vi",
|
|
||||||
"form_error_ip4_gateway_format": "Địa chỉ IPv4 không hợp lệ của cổng kết nối",
|
"form_error_ip4_gateway_format": "Địa chỉ IPv4 không hợp lệ của cổng kết nối",
|
||||||
"form_error_ip6_format": "Địa chỉ IPv6 không hợp lệ",
|
"form_error_ip6_format": "Địa chỉ IPv6 không hợp lệ",
|
||||||
"form_error_ip_format": "Địa chỉ IP không hợp lệ",
|
"form_error_ip_format": "Địa chỉ IP không hợp lệ",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "Phải nằm ngoài phạm vi \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "Phải nằm ngoài phạm vi \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "Phải thấp hơn khởi động phạm vi",
|
"lower_range_start_error": "Phải thấp hơn khởi động phạm vi",
|
||||||
"greater_range_start_error": "Phải lớn hơn khoảng bắt đầu",
|
"greater_range_start_error": "Phải lớn hơn khoảng bắt đầu",
|
||||||
"greater_range_end_error": "Phải lớn hơn phạm vi kết thúc",
|
|
||||||
"subnet_error": "Địa chỉ phải nằm trong một mạng con",
|
"subnet_error": "Địa chỉ phải nằm trong một mạng con",
|
||||||
"gateway_or_subnet_invalid": "Mặt nạ mạng con không hợp lệ",
|
"gateway_or_subnet_invalid": "Mặt nạ mạng con không hợp lệ",
|
||||||
"dhcp_form_gateway_input": "Cổng IP",
|
"dhcp_form_gateway_input": "Cổng IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "Phát hành",
|
"encryption_issuer": "Phát hành",
|
||||||
"encryption_hostnames": "Tên máy chủ",
|
"encryption_hostnames": "Tên máy chủ",
|
||||||
"encryption_reset": "Bạn có chắc chắn muốn đặt lại cài đặt mã hóa?",
|
"encryption_reset": "Bạn có chắc chắn muốn đặt lại cài đặt mã hóa?",
|
||||||
|
"encryption_warning": "Cảnh báo",
|
||||||
"topline_expiring_certificate": "Chứng chỉ SSL của bạn sắp hết hạn. Cập nhật <0>Cài đặt mã hóa</0>.",
|
"topline_expiring_certificate": "Chứng chỉ SSL của bạn sắp hết hạn. Cập nhật <0>Cài đặt mã hóa</0>.",
|
||||||
"topline_expired_certificate": "Chứng chỉ SSL của bạn đã hết hạn. Cập nhật <0>Cài đặt mã hóa</0>.",
|
"topline_expired_certificate": "Chứng chỉ SSL của bạn đã hết hạn. Cập nhật <0>Cài đặt mã hóa</0>.",
|
||||||
"form_error_port_range": "Nhập giá trị cổng trong phạm vi 80-65535",
|
"form_error_port_range": "Nhập giá trị cổng trong phạm vi 80-65535",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "Duyệt web an toàn",
|
"safe_browsing": "Duyệt web an toàn",
|
||||||
"served_from_cache": "{{value}} <i>(được phục vụ từ bộ nhớ cache)</i>",
|
"served_from_cache": "{{value}} <i>(được phục vụ từ bộ nhớ cache)</i>",
|
||||||
"form_error_password_length": "Mật khẩu phải có ít nhất {{value}} ký tự",
|
"form_error_password_length": "Mật khẩu phải có ít nhất {{value}} ký tự",
|
||||||
"anonymizer_notification": "<0> Lưu ý:</0> Tính năng ẩn danh IP được bật. Bạn có thể tắt nó trong <1> Cài đặt chung</1>."
|
"anonymizer_notification": "<0> Lưu ý:</0> Tính năng ẩn danh IP được bật. Bạn có thể tắt nó trong <1> Cài đặt chung</1>.",
|
||||||
|
"confirm_dns_cache_clear": "Bạn có chắc chắn muốn xóa bộ đệm ẩn DNS không?",
|
||||||
|
"cache_cleared": "Đã xóa thành công bộ đệm DNS",
|
||||||
|
"clear_cache": "Xóa bộ nhớ cache"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6设置",
|
"dhcp_ipv6_settings": "DHCP IPv6设置",
|
||||||
"form_error_required": "必填字段",
|
"form_error_required": "必填字段",
|
||||||
"form_error_ip4_format": "无效的 IPv4 地址",
|
"form_error_ip4_format": "无效的 IPv4 地址",
|
||||||
"form_error_ip4_range_start_format": "范围起始值的 IPv4 地址无效",
|
|
||||||
"form_error_ip4_range_end_format": "范围终值的 IPv4 地址无效",
|
|
||||||
"form_error_ip4_gateway_format": "网关 IPv4 地址无效",
|
"form_error_ip4_gateway_format": "网关 IPv4 地址无效",
|
||||||
"form_error_ip6_format": "无效的 IPv6 地址",
|
"form_error_ip6_format": "无效的 IPv6 地址",
|
||||||
"form_error_ip_format": "无效的 IP 地址",
|
"form_error_ip_format": "无效的 IP 地址",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "必定超出了范围 \"{{start}}\"-\"{{end}}\"",
|
"out_of_range_error": "必定超出了范围 \"{{start}}\"-\"{{end}}\"",
|
||||||
"lower_range_start_error": "必须小于范围起始值",
|
"lower_range_start_error": "必须小于范围起始值",
|
||||||
"greater_range_start_error": "必须大于范围起始值",
|
"greater_range_start_error": "必须大于范围起始值",
|
||||||
"greater_range_end_error": "必须大于范围终值",
|
|
||||||
"subnet_error": "地址必须在一个子网内",
|
"subnet_error": "地址必须在一个子网内",
|
||||||
"gateway_or_subnet_invalid": "子网掩码无效",
|
"gateway_or_subnet_invalid": "子网掩码无效",
|
||||||
"dhcp_form_gateway_input": "网关 IP",
|
"dhcp_form_gateway_input": "网关 IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "颁发者",
|
"encryption_issuer": "颁发者",
|
||||||
"encryption_hostnames": "主机名",
|
"encryption_hostnames": "主机名",
|
||||||
"encryption_reset": "您确定想要重置加密设置?",
|
"encryption_reset": "您确定想要重置加密设置?",
|
||||||
|
"encryption_warning": "警告",
|
||||||
"topline_expiring_certificate": "您的 SSL 证书即将过期。请更新 <0>加密设置</0> 。",
|
"topline_expiring_certificate": "您的 SSL 证书即将过期。请更新 <0>加密设置</0> 。",
|
||||||
"topline_expired_certificate": "您的 SSL 证书已过期。请更新 <0>加密设置</0> 。",
|
"topline_expired_certificate": "您的 SSL 证书已过期。请更新 <0>加密设置</0> 。",
|
||||||
"form_error_port_range": "输入 80 - 65535 范围内的端口值",
|
"form_error_port_range": "输入 80 - 65535 范围内的端口值",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "安全浏览",
|
"safe_browsing": "安全浏览",
|
||||||
"served_from_cache": "{{value}}<i>(由缓存提供)</i>",
|
"served_from_cache": "{{value}}<i>(由缓存提供)</i>",
|
||||||
"form_error_password_length": "密码必须至少有 {{value}} 个字符",
|
"form_error_password_length": "密码必须至少有 {{value}} 个字符",
|
||||||
"anonymizer_notification": "<0>注意:</0> IP 匿名化已启用。您可以在<1>常规设置</1>中禁用它。"
|
"anonymizer_notification": "<0>注意:</0> IP 匿名化已启用。您可以在<1>常规设置</1>中禁用它。",
|
||||||
|
"confirm_dns_cache_clear": "您确定要清除 DNS 缓存吗?",
|
||||||
|
"cache_cleared": "已成功清除 DNS 缓存",
|
||||||
|
"clear_cache": "清除缓存"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,6 +381,7 @@
|
|||||||
"encryption_issuer": "簽發者",
|
"encryption_issuer": "簽發者",
|
||||||
"encryption_hostnames": "主機名稱",
|
"encryption_hostnames": "主機名稱",
|
||||||
"encryption_reset": "您確定要重設加密設定嗎?",
|
"encryption_reset": "您確定要重設加密設定嗎?",
|
||||||
|
"encryption_warning": "警告",
|
||||||
"topline_expiring_certificate": "您的 SSL 憑證即將到期。請前往<0>加密設定</0>更新。",
|
"topline_expiring_certificate": "您的 SSL 憑證即將到期。請前往<0>加密設定</0>更新。",
|
||||||
"topline_expired_certificate": "您的 SSL 憑證已到期。請前往<0>加密設定</0>更新。",
|
"topline_expired_certificate": "您的 SSL 憑證已到期。請前往<0>加密設定</0>更新。",
|
||||||
"form_error_port_range": "輸入範圍 80-65535 中的值",
|
"form_error_port_range": "輸入範圍 80-65535 中的值",
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
"dhcp_ipv6_settings": "DHCP IPv6 設定",
|
"dhcp_ipv6_settings": "DHCP IPv6 設定",
|
||||||
"form_error_required": "必填的欄位",
|
"form_error_required": "必填的欄位",
|
||||||
"form_error_ip4_format": "無效的 IPv4 位址",
|
"form_error_ip4_format": "無效的 IPv4 位址",
|
||||||
"form_error_ip4_range_start_format": "無效起始範圍的 IPv4 位址",
|
|
||||||
"form_error_ip4_range_end_format": "無效結束範圍的 IPv4 位址",
|
|
||||||
"form_error_ip4_gateway_format": "無效閘道的 IPv4 位址",
|
"form_error_ip4_gateway_format": "無效閘道的 IPv4 位址",
|
||||||
"form_error_ip6_format": "無效的 IPv6 位址",
|
"form_error_ip6_format": "無效的 IPv6 位址",
|
||||||
"form_error_ip_format": "無效的 IP 位址",
|
"form_error_ip_format": "無效的 IP 位址",
|
||||||
@@ -51,7 +49,6 @@
|
|||||||
"out_of_range_error": "必須在\"{{start}}\"-\"{{end}}\"範圍之外",
|
"out_of_range_error": "必須在\"{{start}}\"-\"{{end}}\"範圍之外",
|
||||||
"lower_range_start_error": "必須低於起始範圍",
|
"lower_range_start_error": "必須低於起始範圍",
|
||||||
"greater_range_start_error": "必須大於起始範圍",
|
"greater_range_start_error": "必須大於起始範圍",
|
||||||
"greater_range_end_error": "必須大於結束範圍",
|
|
||||||
"subnet_error": "位址必須在子網路中",
|
"subnet_error": "位址必須在子網路中",
|
||||||
"gateway_or_subnet_invalid": "無效的子網路遮罩",
|
"gateway_or_subnet_invalid": "無效的子網路遮罩",
|
||||||
"dhcp_form_gateway_input": "閘道 IP",
|
"dhcp_form_gateway_input": "閘道 IP",
|
||||||
@@ -393,6 +390,7 @@
|
|||||||
"encryption_issuer": "簽發者",
|
"encryption_issuer": "簽發者",
|
||||||
"encryption_hostnames": "主機名稱",
|
"encryption_hostnames": "主機名稱",
|
||||||
"encryption_reset": "您確定您想要重置加密設定嗎?",
|
"encryption_reset": "您確定您想要重置加密設定嗎?",
|
||||||
|
"encryption_warning": "警告",
|
||||||
"topline_expiring_certificate": "您的安全通訊端層(SSL)憑證即將到期。更新<0>加密設定</0>。",
|
"topline_expiring_certificate": "您的安全通訊端層(SSL)憑證即將到期。更新<0>加密設定</0>。",
|
||||||
"topline_expired_certificate": "您的安全通訊端層(SSL)憑證為已到期的。更新<0>加密設定</0>。",
|
"topline_expired_certificate": "您的安全通訊端層(SSL)憑證為已到期的。更新<0>加密設定</0>。",
|
||||||
"form_error_port_range": "輸入在 80-65535 之範圍內的連接埠號碼",
|
"form_error_port_range": "輸入在 80-65535 之範圍內的連接埠號碼",
|
||||||
@@ -637,5 +635,8 @@
|
|||||||
"safe_browsing": "安全瀏覽",
|
"safe_browsing": "安全瀏覽",
|
||||||
"served_from_cache": "{{value}} <i>(由快取提供)</i>",
|
"served_from_cache": "{{value}} <i>(由快取提供)</i>",
|
||||||
"form_error_password_length": "密碼必須為至少長 {{value}} 個字元",
|
"form_error_password_length": "密碼必須為至少長 {{value}} 個字元",
|
||||||
"anonymizer_notification": "<0>注意:</0>IP 匿名化被啟用。您可在<1>一般設定</1>中禁用它。"
|
"anonymizer_notification": "<0>注意:</0>IP 匿名化被啟用。您可在<1>一般設定</1>中禁用它。",
|
||||||
|
"confirm_dns_cache_clear": "您確定您想要清除 DNS 快取嗎?",
|
||||||
|
"cache_cleared": "DNS 快取被成功地清除",
|
||||||
|
"clear_cache": "清除快取"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { splitByNewLine } from '../helpers/helpers';
|
import { splitByNewLine } from '../helpers/helpers';
|
||||||
@@ -19,6 +20,22 @@ export const getDnsConfig = () => async (dispatch) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const clearDnsCacheRequest = createAction('CLEAR_DNS_CACHE_REQUEST');
|
||||||
|
export const clearDnsCacheFailure = createAction('CLEAR_DNS_CACHE_FAILURE');
|
||||||
|
export const clearDnsCacheSuccess = createAction('CLEAR_DNS_CACHE_SUCCESS');
|
||||||
|
|
||||||
|
export const clearDnsCache = () => async (dispatch) => {
|
||||||
|
dispatch(clearDnsCacheRequest());
|
||||||
|
try {
|
||||||
|
const data = await apiClient.clearCache();
|
||||||
|
dispatch(clearDnsCacheSuccess(data));
|
||||||
|
dispatch(addSuccessToast(i18next.t('cache_cleared')));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(clearDnsCacheFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST');
|
export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST');
|
||||||
export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE');
|
export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE');
|
||||||
export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');
|
export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ export const setTlsConfig = (config) => async (dispatch, getState) => {
|
|||||||
response.certificate_chain = atob(response.certificate_chain);
|
response.certificate_chain = atob(response.certificate_chain);
|
||||||
response.private_key = atob(response.private_key);
|
response.private_key = atob(response.private_key);
|
||||||
|
|
||||||
|
if (values.enabled && values.force_https && window.location.protocol === 'http:') {
|
||||||
|
window.location.reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
redirectToCurrentProtocol(response, httpPort);
|
||||||
|
|
||||||
const dnsStatus = await apiClient.getGlobalStatus();
|
const dnsStatus = await apiClient.getGlobalStatus();
|
||||||
if (dnsStatus) {
|
if (dnsStatus) {
|
||||||
dispatch(dnsStatusSuccess(dnsStatus));
|
dispatch(dnsStatusSuccess(dnsStatus));
|
||||||
@@ -48,7 +54,6 @@ export const setTlsConfig = (config) => async (dispatch, getState) => {
|
|||||||
|
|
||||||
dispatch(setTlsConfigSuccess(response));
|
dispatch(setTlsConfigSuccess(response));
|
||||||
dispatch(addSuccessToast('encryption_config_saved'));
|
dispatch(addSuccessToast('encryption_config_saved'));
|
||||||
redirectToCurrentProtocol(response, httpPort);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(addErrorToast({ error }));
|
dispatch(addErrorToast({ error }));
|
||||||
dispatch(setTlsConfigFailure());
|
dispatch(setTlsConfigFailure());
|
||||||
|
|||||||
@@ -32,6 +32,21 @@ export const getBlockedServices = () => async (dispatch) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getAllBlockedServicesRequest = createAction('GET_ALL_BLOCKED_SERVICES_REQUEST');
|
||||||
|
export const getAllBlockedServicesFailure = createAction('GET_ALL_BLOCKED_SERVICES_FAILURE');
|
||||||
|
export const getAllBlockedServicesSuccess = createAction('GET_ALL_BLOCKED_SERVICES_SUCCESS');
|
||||||
|
|
||||||
|
export const getAllBlockedServices = () => async (dispatch) => {
|
||||||
|
dispatch(getAllBlockedServicesRequest());
|
||||||
|
try {
|
||||||
|
const data = await apiClient.getAllBlockedServices();
|
||||||
|
dispatch(getAllBlockedServicesSuccess(data));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(getAllBlockedServicesFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const setBlockedServicesRequest = createAction('SET_BLOCKED_SERVICES_REQUEST');
|
export const setBlockedServicesRequest = createAction('SET_BLOCKED_SERVICES_REQUEST');
|
||||||
export const setBlockedServicesFailure = createAction('SET_BLOCKED_SERVICES_FAILURE');
|
export const setBlockedServicesFailure = createAction('SET_BLOCKED_SERVICES_FAILURE');
|
||||||
export const setBlockedServicesSuccess = createAction('SET_BLOCKED_SERVICES_SUCCESS');
|
export const setBlockedServicesSuccess = createAction('SET_BLOCKED_SERVICES_SUCCESS');
|
||||||
|
|||||||
@@ -465,11 +465,18 @@ class Api {
|
|||||||
|
|
||||||
BLOCKED_SERVICES_SET = { path: 'blocked_services/set', method: 'POST' };
|
BLOCKED_SERVICES_SET = { path: 'blocked_services/set', method: 'POST' };
|
||||||
|
|
||||||
|
BLOCKED_SERVICES_ALL = { path: 'blocked_services/all', method: 'GET' };
|
||||||
|
|
||||||
getBlockedServicesAvailableServices() {
|
getBlockedServicesAvailableServices() {
|
||||||
const { path, method } = this.BLOCKED_SERVICES_SERVICES;
|
const { path, method } = this.BLOCKED_SERVICES_SERVICES;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllBlockedServices() {
|
||||||
|
const { path, method } = this.BLOCKED_SERVICES_ALL;
|
||||||
|
return this.makeRequest(path, method);
|
||||||
|
}
|
||||||
|
|
||||||
getBlockedServices() {
|
getBlockedServices() {
|
||||||
const { path, method } = this.BLOCKED_SERVICES_LIST;
|
const { path, method } = this.BLOCKED_SERVICES_LIST;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
@@ -586,6 +593,14 @@ class Api {
|
|||||||
};
|
};
|
||||||
return this.makeRequest(path, method, config);
|
return this.makeRequest(path, method, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
CLEAR_CACHE = { path: 'cache_clear', method: 'POST' };
|
||||||
|
|
||||||
|
clearCache() {
|
||||||
|
const { path, method } = this.CLEAR_CACHE;
|
||||||
|
return this.makeRequest(path, method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiClient = new Api();
|
const apiClient = new Api();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
getObjDiff,
|
getObjDiff,
|
||||||
} from '../../helpers/helpers';
|
} from '../../helpers/helpers';
|
||||||
|
|
||||||
const filtersCatalog = require('../../helpers/filters/filters.json');
|
import filtersCatalog from '../../helpers/filters/filters';
|
||||||
|
|
||||||
class DnsBlocklist extends Component {
|
class DnsBlocklist extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import classNames from 'classnames';
|
|||||||
import { validatePath, validateRequiredValue } from '../../helpers/validators';
|
import { validatePath, validateRequiredValue } from '../../helpers/validators';
|
||||||
import { CheckboxField, renderInputField } from '../../helpers/form';
|
import { CheckboxField, renderInputField } from '../../helpers/form';
|
||||||
import { MODAL_OPEN_TIMEOUT, MODAL_TYPE, FORM_NAME } from '../../helpers/constants';
|
import { MODAL_OPEN_TIMEOUT, MODAL_TYPE, FORM_NAME } from '../../helpers/constants';
|
||||||
|
import filtersCatalog from '../../helpers/filters/filters';
|
||||||
const filtersCatalog = require('../../helpers/filters/filters.json');
|
|
||||||
|
|
||||||
const getIconsData = (homepage, source) => ([
|
const getIconsData = (homepage, source) => ([
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ import flow from 'lodash/flow';
|
|||||||
|
|
||||||
import { toggleAllServices } from '../../../helpers/helpers';
|
import { toggleAllServices } from '../../../helpers/helpers';
|
||||||
import { renderServiceField } from '../../../helpers/form';
|
import { renderServiceField } from '../../../helpers/form';
|
||||||
import { FORM_NAME, SERVICES } from '../../../helpers/constants';
|
import { FORM_NAME } from '../../../helpers/constants';
|
||||||
|
|
||||||
const Form = (props) => {
|
const Form = (props) => {
|
||||||
const {
|
const {
|
||||||
|
blockedServices,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
change,
|
change,
|
||||||
pristine,
|
pristine,
|
||||||
@@ -27,7 +28,7 @@ const Form = (props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={processing || processingSet}
|
disabled={processing || processingSet}
|
||||||
onClick={() => toggleAllServices(SERVICES, change, true)}
|
onClick={() => toggleAllServices(blockedServices, change, true)}
|
||||||
>
|
>
|
||||||
<Trans>block_all</Trans>
|
<Trans>block_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
@@ -37,17 +38,17 @@ const Form = (props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={processing || processingSet}
|
disabled={processing || processingSet}
|
||||||
onClick={() => toggleAllServices(SERVICES, change, false)}
|
onClick={() => toggleAllServices(blockedServices, change, false)}
|
||||||
>
|
>
|
||||||
<Trans>unblock_all</Trans>
|
<Trans>unblock_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="services">
|
<div className="services">
|
||||||
{SERVICES.map((service) => (
|
{blockedServices.map((service) => (
|
||||||
<Field
|
<Field
|
||||||
key={service.id}
|
key={service.id}
|
||||||
icon={`service_${service.id}`}
|
icon={service.icon_svg}
|
||||||
name={`blocked_services.${service.id}`}
|
name={`blocked_services.${service.id}`}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
component={renderServiceField}
|
component={renderServiceField}
|
||||||
@@ -72,6 +73,7 @@ const Form = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Form.propTypes = {
|
Form.propTypes = {
|
||||||
|
blockedServices: PropTypes.array.isRequired,
|
||||||
pristine: PropTypes.bool.isRequired,
|
pristine: PropTypes.bool.isRequired,
|
||||||
handleSubmit: PropTypes.func.isRequired,
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
change: PropTypes.func.isRequired,
|
change: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import Form from './Form';
|
import Form from './Form';
|
||||||
import Card from '../../ui/Card';
|
import Card from '../../ui/Card';
|
||||||
import { getBlockedServices, setBlockedServices } from '../../../actions/services';
|
import { getBlockedServices, getAllBlockedServices, setBlockedServices } from '../../../actions/services';
|
||||||
import PageTitle from '../../ui/PageTitle';
|
import PageTitle from '../../ui/PageTitle';
|
||||||
|
|
||||||
const getInitialDataForServices = (initial) => (initial ? initial.reduce(
|
const getInitialDataForServices = (initial) => (initial ? initial.reduce(
|
||||||
@@ -21,6 +21,7 @@ const Services = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getBlockedServices());
|
dispatch(getBlockedServices());
|
||||||
|
dispatch(getAllBlockedServices());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSubmit = (values) => {
|
const handleSubmit = (values) => {
|
||||||
@@ -49,6 +50,7 @@ const Services = () => {
|
|||||||
<div className="form">
|
<div className="form">
|
||||||
<Form
|
<Form
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
|
blockedServices={services.allServices}
|
||||||
processing={services.processing}
|
processing={services.processing}
|
||||||
processingSet={services.processingSet}
|
processingSet={services.processingSet}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const ResponseCell = ({
|
|||||||
const filters = useSelector((state) => state.filtering.filters, shallowEqual);
|
const filters = useSelector((state) => state.filtering.filters, shallowEqual);
|
||||||
const whitelistFilters = useSelector((state) => state.filtering.whitelistFilters, shallowEqual);
|
const whitelistFilters = useSelector((state) => state.filtering.whitelistFilters, shallowEqual);
|
||||||
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
|
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
|
||||||
|
const services = useSelector((store) => store?.services);
|
||||||
|
|
||||||
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
||||||
|
|
||||||
@@ -60,8 +61,8 @@ const ResponseCell = ({
|
|||||||
install_settings_dns: upstreamString,
|
install_settings_dns: upstreamString,
|
||||||
elapsed: formattedElapsedMs,
|
elapsed: formattedElapsedMs,
|
||||||
response_code: status,
|
response_code: status,
|
||||||
...(service_name
|
...(service_name && services.allServices
|
||||||
&& { service_name: getServiceName(service_name) }
|
&& { service_name: getServiceName(services.allServices, service_name) }
|
||||||
),
|
),
|
||||||
...(rules.length > 0
|
...(rules.length > 0
|
||||||
&& { rule_label: getRulesToFilterList(rules, filters, whitelistFilters) }
|
&& { rule_label: getRulesToFilterList(rules, filters, whitelistFilters) }
|
||||||
@@ -80,10 +81,10 @@ const ResponseCell = ({
|
|||||||
const getDetailedInfo = (reason) => {
|
const getDetailedInfo = (reason) => {
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case FILTERED_STATUS.FILTERED_BLOCKED_SERVICE:
|
case FILTERED_STATUS.FILTERED_BLOCKED_SERVICE:
|
||||||
if (!service_name) {
|
if (!service_name || !services.allServices) {
|
||||||
return formattedElapsedMs;
|
return formattedElapsedMs;
|
||||||
}
|
}
|
||||||
return getServiceName(service_name);
|
return getServiceName(services.allServices, service_name);
|
||||||
case FILTERED_STATUS.FILTERED_BLACK_LIST:
|
case FILTERED_STATUS.FILTERED_BLACK_LIST:
|
||||||
case FILTERED_STATUS.NOT_FILTERED_WHITE_LIST:
|
case FILTERED_STATUS.NOT_FILTERED_WHITE_LIST:
|
||||||
return getFilterNames(rules, filters, whitelistFilters).join(', ');
|
return getFilterNames(rules, filters, whitelistFilters).join(', ');
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ const Row = memo(({
|
|||||||
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
||||||
const processingSet = useSelector((state) => state.access.processingSet);
|
const processingSet = useSelector((state) => state.access.processingSet);
|
||||||
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||||
|
const services = useSelector((store) => store?.services);
|
||||||
|
|
||||||
const clients = useSelector((state) => state.dashboard.clients);
|
const clients = useSelector((state) => state.dashboard.clients);
|
||||||
|
|
||||||
@@ -175,8 +176,8 @@ const Row = memo(({
|
|||||||
date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS),
|
date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS),
|
||||||
encryption_status: isBlocked
|
encryption_status: isBlocked
|
||||||
? <div className="bg--danger">{requestStatus}</div> : requestStatus,
|
? <div className="bg--danger">{requestStatus}</div> : requestStatus,
|
||||||
...(FILTERED_STATUS.FILTERED_BLOCKED_SERVICE && service_name
|
...(FILTERED_STATUS.FILTERED_BLOCKED_SERVICE && service_name && services.allServices
|
||||||
&& { service_name: getServiceName(service_name) }),
|
&& { service_name: getServiceName(services.allServices, service_name) }),
|
||||||
domain,
|
domain,
|
||||||
type_table_header: type,
|
type_table_header: type,
|
||||||
protocol,
|
protocol,
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ const Form = (props) => {
|
|||||||
name={FORM_NAMES.search}
|
name={FORM_NAMES.search}
|
||||||
component={renderFilterField}
|
component={renderFilterField}
|
||||||
type="text"
|
type="text"
|
||||||
className={classNames('form-control--search form-control--transparent', className)}
|
className={classNames('form-control form-control--search form-control--transparent', className)}
|
||||||
placeholder={t('domain_or_client')}
|
placeholder={t('domain_or_client')}
|
||||||
tooltip={t('query_log_strict_search')}
|
tooltip={t('query_log_strict_search')}
|
||||||
onClearInputClick={onInputClear}
|
onClearInputClick={onInputClear}
|
||||||
|
|||||||
@@ -103,14 +103,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-control--search {
|
.form-control--search {
|
||||||
box-shadow: 0 1px 0 #ddd;
|
|
||||||
padding: 0 2.5rem;
|
padding: 0 2.5rem;
|
||||||
height: 2.25rem;
|
height: 2.25rem;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control--transparent {
|
.form-control--transparent {
|
||||||
border: 0 solid transparent !important;
|
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,10 +172,8 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
width: 2.5rem;
|
||||||
--size: 2.5rem;
|
height: 2.5rem;
|
||||||
width: var(--size);
|
|
||||||
height: var(--size);
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-left: 0.9375rem;
|
margin-left: 0.9375rem;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@@ -474,7 +470,7 @@
|
|||||||
|
|
||||||
.filteringRules__filter {
|
.filteringRules__filter {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: normal;
|
font-weight: 400;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { getFilteringStatus } from '../../actions/filtering';
|
|||||||
import { getClients } from '../../actions';
|
import { getClients } from '../../actions';
|
||||||
import { getDnsConfig } from '../../actions/dnsConfig';
|
import { getDnsConfig } from '../../actions/dnsConfig';
|
||||||
import { getAccessList } from '../../actions/access';
|
import { getAccessList } from '../../actions/access';
|
||||||
|
import { getAllBlockedServices } from '../../actions/services';
|
||||||
import {
|
import {
|
||||||
getLogsConfig,
|
getLogsConfig,
|
||||||
resetFilteredLogs,
|
resetFilteredLogs,
|
||||||
@@ -130,6 +131,7 @@ const Logs = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
dispatch(getFilteringStatus());
|
dispatch(getFilteringStatus());
|
||||||
dispatch(getClients());
|
dispatch(getClients());
|
||||||
|
dispatch(getAllBlockedServices());
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
dispatch(getLogsConfig()),
|
dispatch(getLogsConfig()),
|
||||||
|
|||||||
@@ -1,25 +1,57 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
/* eslint-disable react/display-name */
|
||||||
|
/* eslint-disable react/prop-types */
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans, withTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
|
|
||||||
import { MODAL_TYPE } from '../../../helpers/constants';
|
import { getAllBlockedServices } from '../../../../actions/services';
|
||||||
import { splitByNewLine, countClientsStatistics, sortIp } from '../../../helpers/helpers';
|
import {
|
||||||
import Card from '../../ui/Card';
|
splitByNewLine,
|
||||||
import Modal from './Modal';
|
countClientsStatistics,
|
||||||
import CellWrap from '../../ui/CellWrap';
|
sortIp,
|
||||||
import LogsSearchLink from '../../ui/LogsSearchLink';
|
getService,
|
||||||
|
} from '../../../../helpers/helpers';
|
||||||
|
import { MODAL_TYPE } from '../../../../helpers/constants';
|
||||||
|
import Card from '../../../ui/Card';
|
||||||
|
import CellWrap from '../../../ui/CellWrap';
|
||||||
|
import LogsSearchLink from '../../../ui/LogsSearchLink';
|
||||||
|
import Modal from '../Modal';
|
||||||
|
|
||||||
class ClientsTable extends Component {
|
const ClientsTable = ({
|
||||||
handleFormAdd = (values) => {
|
clients,
|
||||||
this.props.addClient(values);
|
normalizedTopClients,
|
||||||
|
isModalOpen,
|
||||||
|
modalClientName,
|
||||||
|
modalType,
|
||||||
|
addClient,
|
||||||
|
updateClient,
|
||||||
|
deleteClient,
|
||||||
|
toggleClientModal,
|
||||||
|
processingAdding,
|
||||||
|
processingDeleting,
|
||||||
|
processingUpdating,
|
||||||
|
getStats,
|
||||||
|
supportedTags,
|
||||||
|
}) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const services = useSelector((store) => store?.services);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(getAllBlockedServices());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleFormAdd = (values) => {
|
||||||
|
addClient(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleFormUpdate = (values, name) => {
|
const handleFormUpdate = (values, name) => {
|
||||||
this.props.updateClient(values, name);
|
updateClient(values, name);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSubmit = (values) => {
|
const handleSubmit = (values) => {
|
||||||
const config = values;
|
const config = values;
|
||||||
|
|
||||||
if (values) {
|
if (values) {
|
||||||
@@ -42,21 +74,21 @@ class ClientsTable extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.modalType === MODAL_TYPE.EDIT_FILTERS) {
|
if (modalType === MODAL_TYPE.EDIT_FILTERS) {
|
||||||
this.handleFormUpdate(config, this.props.modalClientName);
|
handleFormUpdate(config, modalClientName);
|
||||||
} else {
|
} else {
|
||||||
this.handleFormAdd(config);
|
handleFormAdd(config);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getOptionsWithLabels = (options) => (
|
const getOptionsWithLabels = (options) => (
|
||||||
options.map((option) => ({
|
options.map((option) => ({
|
||||||
value: option,
|
value: option,
|
||||||
label: option,
|
label: option,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
getClient = (name, clients) => {
|
const getClient = (name, clients) => {
|
||||||
const client = clients.find((item) => name === item.name);
|
const client = clients.find((item) => name === item.name);
|
||||||
|
|
||||||
if (client) {
|
if (client) {
|
||||||
@@ -65,7 +97,7 @@ class ClientsTable extends Component {
|
|||||||
} = client;
|
} = client;
|
||||||
return {
|
return {
|
||||||
upstreams: (upstreams && upstreams.join('\n')) || '',
|
upstreams: (upstreams && upstreams.join('\n')) || '',
|
||||||
tags: (tags && this.getOptionsWithLabels(tags)) || [],
|
tags: (tags && getOptionsWithLabels(tags)) || [],
|
||||||
...values,
|
...values,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -78,17 +110,17 @@ class ClientsTable extends Component {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDelete = (data) => {
|
const handleDelete = (data) => {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
if (window.confirm(this.props.t('client_confirm_delete', { key: data.name }))) {
|
if (window.confirm(t('client_confirm_delete', { key: data.name }))) {
|
||||||
this.props.deleteClient(data);
|
deleteClient(data);
|
||||||
this.props.getStats();
|
getStats();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
Header: this.props.t('table_client'),
|
Header: t('table_client'),
|
||||||
accessor: 'ids',
|
accessor: 'ids',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
Cell: (row) => {
|
Cell: (row) => {
|
||||||
@@ -109,13 +141,13 @@ class ClientsTable extends Component {
|
|||||||
sortMethod: sortIp,
|
sortMethod: sortIp,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('table_name'),
|
Header: t('table_name'),
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
Cell: CellWrap,
|
Cell: CellWrap,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('settings'),
|
Header: t('settings'),
|
||||||
accessor: 'use_global_settings',
|
accessor: 'use_global_settings',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
Cell: ({ value }) => {
|
Cell: ({ value }) => {
|
||||||
@@ -133,7 +165,7 @@ class ClientsTable extends Component {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('blocked_services'),
|
Header: t('blocked_services'),
|
||||||
accessor: 'blocked_services',
|
accessor: 'blocked_services',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
Cell: (row) => {
|
Cell: (row) => {
|
||||||
@@ -143,25 +175,40 @@ class ClientsTable extends Component {
|
|||||||
return <Trans>settings_global</Trans>;
|
return <Trans>settings_global</Trans>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value && services.allServices) {
|
||||||
|
return (
|
||||||
|
<div className="logs__row logs__row--icons">
|
||||||
|
{value.map((service) => {
|
||||||
|
const serviceInfo = getService(services.allServices, service);
|
||||||
|
|
||||||
|
if (serviceInfo?.icon_svg) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={serviceInfo.name}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: window.atob(serviceInfo.icon_svg),
|
||||||
|
}}
|
||||||
|
className="service__icon service__icon--table"
|
||||||
|
title={serviceInfo.name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs__row logs__row--icons">
|
<div className="logs__row logs__row--icons">
|
||||||
{value && value.length > 0
|
–
|
||||||
? value.map((service) => (
|
|
||||||
<svg
|
|
||||||
className="service__icon service__icon--table"
|
|
||||||
title={service}
|
|
||||||
key={service}
|
|
||||||
>
|
|
||||||
<use xlinkHref={`#service_${service}`} />
|
|
||||||
</svg>
|
|
||||||
))
|
|
||||||
: '–'}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('upstreams'),
|
Header: t('upstreams'),
|
||||||
accessor: 'upstreams',
|
accessor: 'upstreams',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
Cell: ({ value }) => {
|
Cell: ({ value }) => {
|
||||||
@@ -179,7 +226,7 @@ class ClientsTable extends Component {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('tags_title'),
|
Header: t('tags_title'),
|
||||||
accessor: 'tags',
|
accessor: 'tags',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
Cell: (row) => {
|
Cell: (row) => {
|
||||||
@@ -203,11 +250,11 @@ class ClientsTable extends Component {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('requests_count'),
|
Header: t('requests_count'),
|
||||||
id: 'statistics',
|
id: 'statistics',
|
||||||
accessor: (row) => countClientsStatistics(
|
accessor: (row) => countClientsStatistics(
|
||||||
row.ids,
|
row.ids,
|
||||||
this.props.normalizedTopClients.auto,
|
normalizedTopClients.auto,
|
||||||
),
|
),
|
||||||
sortMethod: (a, b) => b - a,
|
sortMethod: (a, b) => b - a,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
@@ -222,16 +269,13 @@ class ClientsTable extends Component {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: this.props.t('actions_table_header'),
|
Header: t('actions_table_header'),
|
||||||
accessor: 'actions',
|
accessor: 'actions',
|
||||||
maxWidth: 100,
|
maxWidth: 100,
|
||||||
sortable: false,
|
sortable: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
Cell: (row) => {
|
Cell: (row) => {
|
||||||
const clientName = row.original.name;
|
const clientName = row.original.name;
|
||||||
const {
|
|
||||||
toggleClientModal, processingDeleting, processingUpdating, t,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs__row logs__row--center">
|
<div className="logs__row logs__row--center">
|
||||||
@@ -253,7 +297,7 @@ class ClientsTable extends Component {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-icon btn-outline-secondary btn-sm"
|
className="btn btn-icon btn-outline-secondary btn-sm"
|
||||||
onClick={() => this.handleDelete({ name: clientName })}
|
onClick={() => handleDelete({ name: clientName })}
|
||||||
disabled={processingDeleting}
|
disabled={processingDeleting}
|
||||||
title={t('delete_table_action')}
|
title={t('delete_table_action')}
|
||||||
>
|
>
|
||||||
@@ -267,76 +311,61 @@ class ClientsTable extends Component {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
render() {
|
const currentClientData = getClient(modalClientName, clients);
|
||||||
const {
|
const tagsOptions = getOptionsWithLabels(supportedTags);
|
||||||
t,
|
|
||||||
clients,
|
|
||||||
isModalOpen,
|
|
||||||
modalType,
|
|
||||||
modalClientName,
|
|
||||||
toggleClientModal,
|
|
||||||
processingAdding,
|
|
||||||
processingUpdating,
|
|
||||||
supportedTags,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const currentClientData = this.getClient(modalClientName, clients);
|
return (
|
||||||
const tagsOptions = this.getOptionsWithLabels(supportedTags);
|
<Card
|
||||||
|
title={t('clients_title')}
|
||||||
return (
|
subtitle={t('clients_desc')}
|
||||||
<Card
|
bodyType="card-body box-body--settings"
|
||||||
title={t('clients_title')}
|
>
|
||||||
subtitle={t('clients_desc')}
|
<>
|
||||||
bodyType="card-body box-body--settings"
|
<ReactTable
|
||||||
>
|
data={clients || []}
|
||||||
<Fragment>
|
columns={columns}
|
||||||
<ReactTable
|
defaultSorted={[
|
||||||
data={clients || []}
|
{
|
||||||
columns={this.columns}
|
id: 'statistics',
|
||||||
defaultSorted={[
|
asc: true,
|
||||||
{
|
},
|
||||||
id: 'statistics',
|
]}
|
||||||
asc: true,
|
className="-striped -highlight card-table-overflow"
|
||||||
},
|
showPagination
|
||||||
]}
|
defaultPageSize={10}
|
||||||
className="-striped -highlight card-table-overflow"
|
minRows={5}
|
||||||
showPagination
|
ofText="/"
|
||||||
defaultPageSize={10}
|
previousText={t('previous_btn')}
|
||||||
minRows={5}
|
nextText={t('next_btn')}
|
||||||
ofText="/"
|
pageText={t('page_table_footer_text')}
|
||||||
previousText={t('previous_btn')}
|
rowsText={t('rows_table_footer_text')}
|
||||||
nextText={t('next_btn')}
|
loadingText={t('loading_table_status')}
|
||||||
pageText={t('page_table_footer_text')}
|
noDataText={t('clients_not_found')}
|
||||||
rowsText={t('rows_table_footer_text')}
|
/>
|
||||||
loadingText={t('loading_table_status')}
|
<button
|
||||||
noDataText={t('clients_not_found')}
|
type="button"
|
||||||
/>
|
className="btn btn-success btn-standard mt-3"
|
||||||
<button
|
onClick={() => toggleClientModal(MODAL_TYPE.ADD_FILTERS)}
|
||||||
type="button"
|
disabled={processingAdding}
|
||||||
className="btn btn-success btn-standard mt-3"
|
>
|
||||||
onClick={() => toggleClientModal(MODAL_TYPE.ADD_FILTERS)}
|
<Trans>client_add</Trans>
|
||||||
disabled={processingAdding}
|
</button>
|
||||||
>
|
<Modal
|
||||||
<Trans>client_add</Trans>
|
isModalOpen={isModalOpen}
|
||||||
</button>
|
modalType={modalType}
|
||||||
<Modal
|
toggleClientModal={toggleClientModal}
|
||||||
isModalOpen={isModalOpen}
|
currentClientData={currentClientData}
|
||||||
modalType={modalType}
|
handleSubmit={handleSubmit}
|
||||||
toggleClientModal={toggleClientModal}
|
processingAdding={processingAdding}
|
||||||
currentClientData={currentClientData}
|
processingUpdating={processingUpdating}
|
||||||
handleSubmit={this.handleSubmit}
|
tagsOptions={tagsOptions}
|
||||||
processingAdding={processingAdding}
|
/>
|
||||||
processingUpdating={processingUpdating}
|
</>
|
||||||
tagsOptions={tagsOptions}
|
</Card>
|
||||||
/>
|
);
|
||||||
</Fragment>
|
};
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientsTable.propTypes = {
|
ClientsTable.propTypes = {
|
||||||
t: PropTypes.func.isRequired,
|
|
||||||
clients: PropTypes.array.isRequired,
|
clients: PropTypes.array.isRequired,
|
||||||
normalizedTopClients: PropTypes.object.isRequired,
|
normalizedTopClients: PropTypes.object.isRequired,
|
||||||
toggleClientModal: PropTypes.func.isRequired,
|
toggleClientModal: PropTypes.func.isRequired,
|
||||||
@@ -353,4 +382,4 @@ ClientsTable.propTypes = {
|
|||||||
supportedTags: PropTypes.array.isRequired,
|
supportedTags: PropTypes.array.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withTranslation()(ClientsTable);
|
export default ClientsTable;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default as ClientsTable } from './ClientsTable';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect, useSelector } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
Field, FieldArray, reduxForm, formValueSelector,
|
Field, FieldArray, reduxForm, formValueSelector,
|
||||||
@@ -11,15 +11,16 @@ import Select from 'react-select';
|
|||||||
import i18n from '../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import Tabs from '../../ui/Tabs';
|
import Tabs from '../../ui/Tabs';
|
||||||
import Examples from '../Dns/Upstream/Examples';
|
import Examples from '../Dns/Upstream/Examples';
|
||||||
import { toggleAllServices } from '../../../helpers/helpers';
|
import { toggleAllServices, trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
|
||||||
import {
|
import {
|
||||||
renderInputField,
|
renderInputField,
|
||||||
renderGroupField,
|
renderGroupField,
|
||||||
CheckboxField,
|
CheckboxField,
|
||||||
renderServiceField,
|
renderServiceField,
|
||||||
|
renderTextareaField,
|
||||||
} from '../../../helpers/form';
|
} from '../../../helpers/form';
|
||||||
import { validateClientId, validateRequiredValue } from '../../../helpers/validators';
|
import { validateClientId, validateRequiredValue } from '../../../helpers/validators';
|
||||||
import { CLIENT_ID_LINK, FORM_NAME, SERVICES } from '../../../helpers/constants';
|
import { CLIENT_ID_LINK, FORM_NAME } from '../../../helpers/constants';
|
||||||
import './Service.css';
|
import './Service.css';
|
||||||
|
|
||||||
const settingsCheckboxes = [
|
const settingsCheckboxes = [
|
||||||
@@ -139,6 +140,7 @@ let Form = (props) => {
|
|||||||
invalid,
|
invalid,
|
||||||
tagsOptions,
|
tagsOptions,
|
||||||
} = props;
|
} = props;
|
||||||
|
const services = useSelector((store) => store?.services);
|
||||||
|
|
||||||
const [activeTabLabel, setActiveTabLabel] = useState('settings');
|
const [activeTabLabel, setActiveTabLabel] = useState('settings');
|
||||||
|
|
||||||
@@ -180,7 +182,9 @@ let Form = (props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={useGlobalServices}
|
disabled={useGlobalServices}
|
||||||
onClick={() => toggleAllServices(SERVICES, change, true)}
|
onClick={() => (
|
||||||
|
toggleAllServices(services.allServices, change, true)
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<Trans>block_all</Trans>
|
<Trans>block_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
@@ -190,25 +194,29 @@ let Form = (props) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={useGlobalServices}
|
disabled={useGlobalServices}
|
||||||
onClick={() => toggleAllServices(SERVICES, change, false)}
|
onClick={() => (
|
||||||
|
toggleAllServices(services.allServices, change, false)
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<Trans>unblock_all</Trans>
|
<Trans>unblock_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="services">
|
{services.allServices.length > 0 && (
|
||||||
{SERVICES.map((service) => (
|
<div className="services">
|
||||||
<Field
|
{services.allServices.map((service) => (
|
||||||
key={service.id}
|
<Field
|
||||||
icon={`service_${service.id}`}
|
key={service.id}
|
||||||
name={`blocked_services.${service.id}`}
|
icon={service.icon_svg}
|
||||||
type="checkbox"
|
name={`blocked_services.${service.id}`}
|
||||||
component={renderServiceField}
|
type="checkbox"
|
||||||
placeholder={service.name}
|
component={renderServiceField}
|
||||||
disabled={useGlobalServices}
|
placeholder={service.name}
|
||||||
/>
|
disabled={useGlobalServices}
|
||||||
))}
|
/>
|
||||||
</div>
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
},
|
},
|
||||||
@@ -223,10 +231,11 @@ let Form = (props) => {
|
|||||||
<Field
|
<Field
|
||||||
id="upstreams"
|
id="upstreams"
|
||||||
name="upstreams"
|
name="upstreams"
|
||||||
component="textarea"
|
component={renderTextareaField}
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control--textarea mb-5"
|
className="form-control form-control--textarea mb-5"
|
||||||
placeholder={t('upstream_dns')}
|
placeholder={t('upstream_dns')}
|
||||||
|
normalizeOnBlur={trimLinesAndRemoveEmpty}
|
||||||
/>
|
/>
|
||||||
<Examples />
|
<Examples />
|
||||||
</div>,
|
</div>,
|
||||||
|
|||||||
@@ -9,6 +9,12 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.service__text {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
.services {
|
.services {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -33,7 +39,7 @@
|
|||||||
margin-right: 30px;
|
margin-right: 30px;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service:nth-child(3n) {
|
.service:nth-child(3n) {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { Component, Fragment } from 'react';
|
|||||||
import { withTranslation } from 'react-i18next';
|
import { withTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import ClientsTable from './ClientsTable';
|
import { ClientsTable } from './ClientsTable';
|
||||||
import AutoClients from './AutoClients';
|
import AutoClients from './AutoClients';
|
||||||
import PageTitle from '../../ui/PageTitle';
|
import PageTitle from '../../ui/PageTitle';
|
||||||
import Loading from '../../ui/Loading';
|
import Loading from '../../ui/Loading';
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ const FormDHCPv4 = ({
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder={t(ipv4placeholders.subnet_mask)}
|
placeholder={t(ipv4placeholders.subnet_mask)}
|
||||||
validate={[
|
validate={[
|
||||||
validateIpv4,
|
|
||||||
validateRequired,
|
validateRequired,
|
||||||
validateGatewaySubnetMask,
|
validateGatewaySubnetMask,
|
||||||
]}
|
]}
|
||||||
@@ -97,7 +96,6 @@ const FormDHCPv4 = ({
|
|||||||
placeholder={t(ipv4placeholders.range_start)}
|
placeholder={t(ipv4placeholders.range_start)}
|
||||||
validate={[
|
validate={[
|
||||||
validateIpv4,
|
validateIpv4,
|
||||||
validateGatewaySubnetMask,
|
|
||||||
validateIpForGatewaySubnetMask,
|
validateIpForGatewaySubnetMask,
|
||||||
]}
|
]}
|
||||||
disabled={!isInterfaceIncludesIpv4}
|
disabled={!isInterfaceIncludesIpv4}
|
||||||
@@ -113,7 +111,6 @@ const FormDHCPv4 = ({
|
|||||||
validate={[
|
validate={[
|
||||||
validateIpv4,
|
validateIpv4,
|
||||||
validateIpv4RangeEnd,
|
validateIpv4RangeEnd,
|
||||||
validateGatewaySubnetMask,
|
|
||||||
validateIpForGatewaySubnetMask,
|
validateIpForGatewaySubnetMask,
|
||||||
]}
|
]}
|
||||||
disabled={!isInterfaceIncludesIpv4}
|
disabled={!isInterfaceIncludesIpv4}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Field, reduxForm } from 'redux-form';
|
import { Field, reduxForm } from 'redux-form';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { shallowEqual, useSelector } from 'react-redux';
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { renderInputField, toNumber, CheckboxField } from '../../../../helpers/form';
|
import { renderInputField, toNumber, CheckboxField } from '../../../../helpers/form';
|
||||||
import { CACHE_CONFIG_FIELDS, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants';
|
import { CACHE_CONFIG_FIELDS, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants';
|
||||||
import { replaceZeroWithEmptyString } from '../../../../helpers/helpers';
|
import { replaceZeroWithEmptyString } from '../../../../helpers/helpers';
|
||||||
|
import { clearDnsCache } from '../../../../actions/dnsConfig';
|
||||||
|
|
||||||
const INPUTS_FIELDS = [
|
const INPUTS_FIELDS = [
|
||||||
{
|
{
|
||||||
@@ -32,6 +34,7 @@ const Form = ({
|
|||||||
handleSubmit, submitting, invalid,
|
handleSubmit, submitting, invalid,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const { processingSetConfig } = useSelector((state) => state.dnsConfig, shallowEqual);
|
const { processingSetConfig } = useSelector((state) => state.dnsConfig, shallowEqual);
|
||||||
const {
|
const {
|
||||||
@@ -40,6 +43,12 @@ const Form = ({
|
|||||||
|
|
||||||
const minExceedsMax = cache_ttl_min > cache_ttl_max;
|
const minExceedsMax = cache_ttl_min > cache_ttl_max;
|
||||||
|
|
||||||
|
const handleClearCache = () => {
|
||||||
|
if (window.confirm(t('confirm_dns_cache_clear'))) {
|
||||||
|
dispatch(clearDnsCache());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return <form onSubmit={handleSubmit}>
|
return <form onSubmit={handleSubmit}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{INPUTS_FIELDS.map(({
|
{INPUTS_FIELDS.map(({
|
||||||
@@ -97,6 +106,13 @@ const Form = ({
|
|||||||
>
|
>
|
||||||
<Trans>save_btn</Trans>
|
<Trans>save_btn</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-secondary btn-standard form__button"
|
||||||
|
onClick={handleClearCache}
|
||||||
|
>
|
||||||
|
<Trans>clear_cache</Trans>
|
||||||
|
</button>
|
||||||
</form>;
|
</form>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,26 @@ const clearFields = (change, setTlsConfig, t) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validationMessage = (warningValidation, isWarning) => {
|
||||||
|
if (!warningValidation) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWarning) {
|
||||||
|
return (
|
||||||
|
<div className="col-12">
|
||||||
|
<p><Trans>encryption_warning</Trans>: {warningValidation}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="col-12">
|
||||||
|
<p className="text-danger">{warningValidation}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
let Form = (props) => {
|
let Form = (props) => {
|
||||||
const {
|
const {
|
||||||
t,
|
t,
|
||||||
@@ -95,6 +115,8 @@ let Form = (props) => {
|
|||||||
|| !valid_cert
|
|| !valid_cert
|
||||||
|| !valid_pair;
|
|| !valid_pair;
|
||||||
|
|
||||||
|
const isWarning = valid_key && valid_cert && valid_pair;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@@ -382,11 +404,7 @@ let Form = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{warning_validation && (
|
{validationMessage(warning_validation, isWarning)}
|
||||||
<div className="col-12">
|
|
||||||
<p className="text-danger">{warning_validation}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="btn-list mt-2">
|
<div className="btn-list mt-2">
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -15452,6 +15452,7 @@ a.tag-addon:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.custom-switch-indicator {
|
.custom-switch-indicator {
|
||||||
|
flex-shrink: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
width: 2.25rem;
|
width: 2.25rem;
|
||||||
|
|||||||
@@ -202,158 +202,6 @@ export const FILTERS_URLS = {
|
|||||||
blocked_services: '/blocked_services',
|
blocked_services: '/blocked_services',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SERVICES = [
|
|
||||||
{
|
|
||||||
id: '9gag',
|
|
||||||
name: '9GAG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'amazon',
|
|
||||||
name: 'Amazon',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'bilibili',
|
|
||||||
name: 'Bilibili',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'cloudflare',
|
|
||||||
name: 'CloudFlare',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'dailymotion',
|
|
||||||
name: 'Dailymotion',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'discord',
|
|
||||||
name: 'Discord',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'disneyplus',
|
|
||||||
name: 'Disney+',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ebay',
|
|
||||||
name: 'EBay',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'epic_games',
|
|
||||||
name: 'Epic Games',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'facebook',
|
|
||||||
name: 'Facebook',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'hulu',
|
|
||||||
name: 'Hulu',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'imgur',
|
|
||||||
name: 'Imgur',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instagram',
|
|
||||||
name: 'Instagram',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'mail_ru',
|
|
||||||
name: 'Mail.ru',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'netflix',
|
|
||||||
name: 'Netflix',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ok',
|
|
||||||
name: 'OK.ru',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'origin',
|
|
||||||
name: 'Origin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'pinterest',
|
|
||||||
name: 'Pinterest',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'qq',
|
|
||||||
name: 'QQ',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'reddit',
|
|
||||||
name: 'Reddit',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'skype',
|
|
||||||
name: 'Skype',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'snapchat',
|
|
||||||
name: 'Snapchat',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'spotify',
|
|
||||||
name: 'Spotify',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'steam',
|
|
||||||
name: 'Steam',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'telegram',
|
|
||||||
name: 'Telegram',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'tiktok',
|
|
||||||
name: 'TikTok',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'tinder',
|
|
||||||
name: 'Tinder',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'twitch',
|
|
||||||
name: 'Twitch',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'twitter',
|
|
||||||
name: 'Twitter',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'viber',
|
|
||||||
name: 'Viber',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'vimeo',
|
|
||||||
name: 'Vimeo',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'vk',
|
|
||||||
name: 'VK.com',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'wechat',
|
|
||||||
name: 'WeChat',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'weibo',
|
|
||||||
name: 'Weibo',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'whatsapp',
|
|
||||||
name: 'WhatsApp',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'youtube',
|
|
||||||
name: 'YouTube',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const SERVICES_ID_NAME_MAP = SERVICES.reduce((acc, { id, name }) => {
|
|
||||||
acc[id] = name;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
export const ENCRYPTION_SOURCE = {
|
export const ENCRYPTION_SOURCE = {
|
||||||
PATH: 'path',
|
PATH: 'path',
|
||||||
CONTENT: 'content',
|
CONTENT: 'content',
|
||||||
@@ -542,6 +390,7 @@ export const SPECIAL_FILTER_ID = {
|
|||||||
PARENTAL: -3,
|
PARENTAL: -3,
|
||||||
SAFE_BROWSING: -4,
|
SAFE_BROWSING: -4,
|
||||||
SAFE_SEARCH: -5,
|
SAFE_SEARCH: -5,
|
||||||
|
REWRITES: -6,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BLOCK_ACTIONS = {
|
export const BLOCK_ACTIONS = {
|
||||||
|
|||||||
254
client/src/helpers/filters/filters.js
Normal file
254
client/src/helpers/filters/filters.js
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
// Code generated by go run ./scripts/vetted-filters/main.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
/* eslint quote-props: 'off', quotes: 'off', comma-dangle: 'off', semi: 'off' */
|
||||||
|
|
||||||
|
export default {
|
||||||
|
"categories": {
|
||||||
|
"general": {
|
||||||
|
"name": "filter_category_general",
|
||||||
|
"description": "filter_category_general_desc"
|
||||||
|
},
|
||||||
|
"other": {
|
||||||
|
"name": "filter_category_other",
|
||||||
|
"description": "filter_category_other_desc"
|
||||||
|
},
|
||||||
|
"regional": {
|
||||||
|
"name": "filter_category_regional",
|
||||||
|
"description": "filter_category_regional_desc"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"name": "filter_category_security",
|
||||||
|
"description": "filter_category_security_desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"1hosts_lite": {
|
||||||
|
"name": "1Hosts (Lite)",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://badmojr.github.io/1Hosts/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_24.txt"
|
||||||
|
},
|
||||||
|
"1hosts_mini": {
|
||||||
|
"name": "1Hosts (mini)",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://badmojr.github.io/1Hosts/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_38.txt"
|
||||||
|
},
|
||||||
|
"CHN_adrules": {
|
||||||
|
"name": "CHN: AdRules DNS List",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/Cats-Team/AdRules",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_29.txt"
|
||||||
|
},
|
||||||
|
"CHN_anti_ad": {
|
||||||
|
"name": "CHN: anti-AD",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://anti-ad.net/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_21.txt"
|
||||||
|
},
|
||||||
|
"HUN_hufilter": {
|
||||||
|
"name": "HUN: Hufilter",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/hufilter/hufilter",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_35.txt"
|
||||||
|
},
|
||||||
|
"IDN_abpindo": {
|
||||||
|
"name": "IDN: ABPindo",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/ABPindo/indonesianadblockrules",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_22.txt"
|
||||||
|
},
|
||||||
|
"IRN_unwanted_iranian_domains": {
|
||||||
|
"name": "IRN: PersianBlocker list",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/MasterKia/PersianBlocker",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_19.txt"
|
||||||
|
},
|
||||||
|
"ITA_filtri_dns": {
|
||||||
|
"name": "ITA: Filtri-DNS",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://filtri-dns.ga/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_18.txt"
|
||||||
|
},
|
||||||
|
"KOR_list_kr": {
|
||||||
|
"name": "KOR: List-KR DNS",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/List-KR/List-KR",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_25.txt"
|
||||||
|
},
|
||||||
|
"KOR_youslist": {
|
||||||
|
"name": "KOR: YousList",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/yous/YousList",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_15.txt"
|
||||||
|
},
|
||||||
|
"LIT_easylist_lithuania": {
|
||||||
|
"name": "LIT: EasyList Lithuania",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/EasyList-Lithuania/easylist_lithuania",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_36.txt"
|
||||||
|
},
|
||||||
|
"MKD_macedonian_pi_hole_blocklist": {
|
||||||
|
"name": "MKD: Macedonian Pi-hole Blocklist",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/cchevy/macedonian-pi-hole-blocklist",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_20.txt"
|
||||||
|
},
|
||||||
|
"NOR_dandelion_sprouts_anti_malware_list": {
|
||||||
|
"name": "NOR: Dandelion Sprouts nordiske filtre",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/DandelionSprout/adfilt",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_13.txt"
|
||||||
|
},
|
||||||
|
"POL_polish_filters_for_pi_hole": {
|
||||||
|
"name": "POL: Polish filters for Pi hole",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://www.certyficate.it/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_14.txt"
|
||||||
|
},
|
||||||
|
"SWE_frellwit_swedish_hosts_file": {
|
||||||
|
"name": "SWE: Frellwit's Swedish Hosts File",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/lassekongo83/Frellwits-filter-lists/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_17.txt"
|
||||||
|
},
|
||||||
|
"TUR_turk_adlist": {
|
||||||
|
"name": "TUR: turk-adlist",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "https://github.com/bkrucarci/turk-adlist",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_26.txt"
|
||||||
|
},
|
||||||
|
"VNM_abpvn": {
|
||||||
|
"name": "VNM: ABPVN List",
|
||||||
|
"categoryId": "regional",
|
||||||
|
"homepage": "http://abpvn.com/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_16.txt"
|
||||||
|
},
|
||||||
|
"adguard_dns_filter": {
|
||||||
|
"name": "AdGuard DNS filter",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"
|
||||||
|
},
|
||||||
|
"adway_default_blocklist": {
|
||||||
|
"name": "AdAway Default Blocklist",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://github.com/AdAway/adaway.github.io/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt"
|
||||||
|
},
|
||||||
|
"curben_phishing_filter": {
|
||||||
|
"name": "Phishing URL Blocklist (PhishTank and OpenPhish)",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://gitlab.com/malware-filter/phishing-filter",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_30.txt"
|
||||||
|
},
|
||||||
|
"dan_pollocks_list": {
|
||||||
|
"name": "Dan Pollock's List",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://someonewhocares.org/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_4.txt"
|
||||||
|
},
|
||||||
|
"dandelion_sprouts_anti_malware_list": {
|
||||||
|
"name": "Dandelion Sprout's Anti-Malware List",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://github.com/DandelionSprout/adfilt",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_12.txt"
|
||||||
|
},
|
||||||
|
"dandelion_sprouts_game_console_adblock_list": {
|
||||||
|
"name": "Dandelion Sprout's Game Console Adblock List",
|
||||||
|
"categoryId": "other",
|
||||||
|
"homepage": "https://github.com/DandelionSprout/adfilt",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_6.txt"
|
||||||
|
},
|
||||||
|
"energized_spark": {
|
||||||
|
"name": "Energized Spark",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://energized.pro/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_28.txt"
|
||||||
|
},
|
||||||
|
"hagezi_personal": {
|
||||||
|
"name": "HaGeZi Personal Black \u0026 White",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_34.txt"
|
||||||
|
},
|
||||||
|
"no_google": {
|
||||||
|
"name": "No Google",
|
||||||
|
"categoryId": "other",
|
||||||
|
"homepage": "https://github.com/nickspaargaren/no-google",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_37.txt"
|
||||||
|
},
|
||||||
|
"nocoin_filter_list": {
|
||||||
|
"name": "NoCoin Filter List",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://github.com/hoshsadiq/adblock-nocoin-list/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_8.txt"
|
||||||
|
},
|
||||||
|
"notracking_hosts_blocklists": {
|
||||||
|
"name": "The NoTracking blocklist",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://github.com/notracking/hosts-blocklists",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_32.txt"
|
||||||
|
},
|
||||||
|
"oisd_basic": {
|
||||||
|
"name": "OISD Blocklist Basic",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://oisd.nl/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_5.txt"
|
||||||
|
},
|
||||||
|
"oisd_full": {
|
||||||
|
"name": "OISD Blocklist Full",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://oisd.nl/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_27.txt"
|
||||||
|
},
|
||||||
|
"perflyst_dandelion_sprout_smart_tv_blocklist_for_adguard_home": {
|
||||||
|
"name": "Perflyst and Dandelion Sprout's Smart-TV Blocklist",
|
||||||
|
"categoryId": "other",
|
||||||
|
"homepage": "https://github.com/Perflyst/PiHoleBlocklist",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_7.txt"
|
||||||
|
},
|
||||||
|
"peter_lowe_list": {
|
||||||
|
"name": "Peter Lowe's Blocklist",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://pgl.yoyo.org/adservers/",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_3.txt"
|
||||||
|
},
|
||||||
|
"scam_blocklist_by_durablenapkin": {
|
||||||
|
"name": "Scam Blocklist by DurableNapkin",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://github.com/durablenapkin/scamblocklist",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_10.txt"
|
||||||
|
},
|
||||||
|
"staklerware_indicators_list": {
|
||||||
|
"name": "Stalkerware Indicators List",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://github.com/AssoEchap/stalkerware-indicators",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_31.txt"
|
||||||
|
},
|
||||||
|
"steven_blacks_list": {
|
||||||
|
"name": "Steven Black's List",
|
||||||
|
"categoryId": "general",
|
||||||
|
"homepage": "https://github.com/StevenBlack/hosts",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_33.txt"
|
||||||
|
},
|
||||||
|
"the_big_list_of_hacked_malware_web_sites": {
|
||||||
|
"name": "The Big List of Hacked Malware Web Sites",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://github.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt"
|
||||||
|
},
|
||||||
|
"urlhaus_filter_online": {
|
||||||
|
"name": "Malicious URL Blocklist (URLHaus)",
|
||||||
|
"categoryId": "security",
|
||||||
|
"homepage": "https://gitlab.com/malware-filter/urlhaus-filter",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt"
|
||||||
|
},
|
||||||
|
"windowsspyblocker_hosts_spy_rules": {
|
||||||
|
"name": "WindowsSpyBlocker - Hosts spy rules",
|
||||||
|
"categoryId": "other",
|
||||||
|
"homepage": "https://github.com/crazy-max/WindowsSpyBlocker",
|
||||||
|
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_23.txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
{
|
|
||||||
"categories": {
|
|
||||||
"general": {
|
|
||||||
"name": "filter_category_general",
|
|
||||||
"description": "filter_category_general_desc"
|
|
||||||
},
|
|
||||||
"security": {
|
|
||||||
"name": "filter_category_security",
|
|
||||||
"description": "filter_category_security_desc"
|
|
||||||
},
|
|
||||||
"regional": {
|
|
||||||
"name": "filter_category_regional",
|
|
||||||
"description": "filter_category_regional_desc"
|
|
||||||
},
|
|
||||||
"other": {
|
|
||||||
"name": "filter_category_other",
|
|
||||||
"description": "filter_category_other_desc"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"filters": {
|
|
||||||
"adguard-dns-filter": {
|
|
||||||
"name": "AdGuard DNS filter",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter",
|
|
||||||
"source": "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"
|
|
||||||
},
|
|
||||||
"adaway-default-blocklist": {
|
|
||||||
"name": "AdAway Default Blocklist",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://github.com/AdAway/adaway.github.io/",
|
|
||||||
"source": "https://adaway.org/hosts.txt"
|
|
||||||
},
|
|
||||||
"peter-lowe-list": {
|
|
||||||
"name": "Peter Lowe's List",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://pgl.yoyo.org/adservers/",
|
|
||||||
"source": "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&showintro=1&mimetype=plaintext"
|
|
||||||
},
|
|
||||||
"dan-pollock-list": {
|
|
||||||
"name": "Dan Pollock's List",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://someonewhocares.org/",
|
|
||||||
"source": "https://someonewhocares.org/hosts/zero/hosts"
|
|
||||||
},
|
|
||||||
"oisd": {
|
|
||||||
"name": "OISD Blocklist Basic",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://oisd.nl/",
|
|
||||||
"source": "https://abp.oisd.nl/basic/"
|
|
||||||
},
|
|
||||||
"game-console-adblock-list": {
|
|
||||||
"name": "Game Console Adblock List",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://github.com/DandelionSprout/adfilt",
|
|
||||||
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/GameConsoleAdblockList.txt"
|
|
||||||
},
|
|
||||||
"perflyst-dandelion-sprout-smart-tv-blocklist-for-adguard-home": {
|
|
||||||
"name": "Perflyst and Dandelion Sprout's Smart-TV Blocklist",
|
|
||||||
"categoryId": "general",
|
|
||||||
"homepage": "https://github.com/Perflyst/PiHoleBlocklist",
|
|
||||||
"source": "https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV-AGH.txt"
|
|
||||||
},
|
|
||||||
"nocoin-filter-list": {
|
|
||||||
"name": "NoCoin Filter List",
|
|
||||||
"categoryId": "security",
|
|
||||||
"homepage": "https://github.com/hoshsadiq/adblock-nocoin-list/",
|
|
||||||
"source": "https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt"
|
|
||||||
},
|
|
||||||
"the-big-list-of-hacked-malware-web-sites": {
|
|
||||||
"name": "The Big List of Hacked Malware Web Sites",
|
|
||||||
"categoryId": "security",
|
|
||||||
"homepage": "https://github.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites",
|
|
||||||
"source": "https://raw.githubusercontent.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites/master/hosts"
|
|
||||||
},
|
|
||||||
"scam-blocklist-by-durable-napkin": {
|
|
||||||
"name": "Scam Blocklist by DurableNapkin",
|
|
||||||
"categoryId": "security",
|
|
||||||
"homepage": "https://github.com/durablenapkin/scamblocklist",
|
|
||||||
"source": "https://raw.githubusercontent.com/durablenapkin/scamblocklist/master/adguard.txt"
|
|
||||||
},
|
|
||||||
"urlhaus-filter-online": {
|
|
||||||
"name": "Online Malicious URL Blocklist",
|
|
||||||
"categoryId": "security",
|
|
||||||
"homepage": "https://gitlab.com/malware-filter/urlhaus-filter",
|
|
||||||
"source": "https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-agh-online.txt"
|
|
||||||
},
|
|
||||||
"dandelion-sprouts-anti-malware-list": {
|
|
||||||
"name": "Dandelion Sprout's Anti-Malware List",
|
|
||||||
"categoryId": "security",
|
|
||||||
"homepage": "https://github.com/DandelionSprout/adfilt",
|
|
||||||
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareAdGuardHome.txt"
|
|
||||||
},
|
|
||||||
"NOR-dandelion-sprouts-nordiske-filtre": {
|
|
||||||
"name": "NOR: Dandelion Sprouts nordiske filtre",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/DandelionSprout/adfilt",
|
|
||||||
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/NorwegianExperimentalList%20alternate%20versions/NordicFiltersAdGuardHome.txt"
|
|
||||||
},
|
|
||||||
"POL-polish-filters-for-pihole": {
|
|
||||||
"name": "POL: Polish filters for Pi hole",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://www.certyficate.it/",
|
|
||||||
"source": "https://raw.githubusercontent.com/MajkiIT/polish-ads-filter/master/polish-pihole-filters/hostfile.txt"
|
|
||||||
},
|
|
||||||
"KOR-youslist": {
|
|
||||||
"name": "KOR: YousList",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/yous/YousList",
|
|
||||||
"source": "https://raw.githubusercontent.com/yous/YousList/master/hosts.txt"
|
|
||||||
},
|
|
||||||
"VNM-abpvn-list": {
|
|
||||||
"name": "VNM: ABPVN List",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "http://abpvn.com/",
|
|
||||||
"source": "https://abpvn.com/android/abpvn.txt"
|
|
||||||
},
|
|
||||||
"SWE-frellwit-swedish-hosts-file": {
|
|
||||||
"name": "SWE: Frellwit's Swedish Hosts File",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/lassekongo83/Frellwits-filter-lists/",
|
|
||||||
"source": "https://raw.githubusercontent.com/lassekongo83/Frellwits-filter-lists/master/Frellwits-Swedish-Hosts-File.txt"
|
|
||||||
},
|
|
||||||
"ITA-filtri-dns": {
|
|
||||||
"name": "ITA: Filtri-DNS",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://filtri-dns.ga/",
|
|
||||||
"source": "https://filtri-dns.ga/filtri.txt"
|
|
||||||
},
|
|
||||||
"IRN-unwanted-iranian-domains": {
|
|
||||||
"name": "IRN: Unwanted Iranian domains",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/DRSDavidSoft/additional-hosts",
|
|
||||||
"source": "https://raw.githubusercontent.com/DRSDavidSoft/additional-hosts/master/domains/blacklist/unwanted-iranian.txt"
|
|
||||||
},
|
|
||||||
"MKD-macedonian-pi-hole-blocklist": {
|
|
||||||
"name": "MKD: Macedonian Pi-hole Blocklist",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/cchevy/macedonian-pi-hole-blocklist",
|
|
||||||
"source": "https://raw.githubusercontent.com/cchevy/macedonian-pi-hole-blocklist/master/hosts.txt"
|
|
||||||
},
|
|
||||||
"CHN-anti-ad" : {
|
|
||||||
"name": "CHN: anti-AD",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://anti-ad.net/",
|
|
||||||
"source": "https://anti-ad.net/easylist.txt"
|
|
||||||
},
|
|
||||||
"IDN-abpindo": {
|
|
||||||
"name": "IDN: ABPindo",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://github.com/ABPindo/indonesianadblockrules/",
|
|
||||||
"source": "https://raw.githubusercontent.com/ABPindo/indonesianadblockrules/master/subscriptions/abpindo.txt"
|
|
||||||
},
|
|
||||||
"NLD-Easylist": {
|
|
||||||
"name": "NLD: Easylist",
|
|
||||||
"categoryId": "regional",
|
|
||||||
"homepage": "https://forums.lanik.us/viewforum.php?f=100",
|
|
||||||
"source": "https://easylist-downloads.adblockplus.org/easylistdutch.txt"
|
|
||||||
},
|
|
||||||
"windows-spy-blocker" : {
|
|
||||||
"name": "WindowsSpyBlocker - Hosts spy rules",
|
|
||||||
"categoryId": "other",
|
|
||||||
"homepage": "https://github.com/crazy-max/WindowsSpyBlocker",
|
|
||||||
"source": "https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
|
import cn from 'classnames';
|
||||||
|
|
||||||
import { createOnBlurHandler } from './helpers';
|
import { createOnBlurHandler } from './helpers';
|
||||||
import { R_MAC_WITHOUT_COLON, R_UNIX_ABSOLUTE_PATH, R_WIN_ABSOLUTE_PATH } from './constants';
|
import { R_MAC_WITHOUT_COLON, R_UNIX_ABSOLUTE_PATH, R_WIN_ABSOLUTE_PATH } from './constants';
|
||||||
|
|
||||||
@@ -229,24 +231,34 @@ export const renderServiceField = ({
|
|||||||
modifier,
|
modifier,
|
||||||
icon,
|
icon,
|
||||||
meta: { touched, error },
|
meta: { touched, error },
|
||||||
}) => <Fragment>
|
}) => (
|
||||||
<label className={`service custom-switch ${modifier}`}>
|
<>
|
||||||
<input
|
<label className={cn('service custom-switch', { [modifier]: modifier })}>
|
||||||
{...input}
|
<input
|
||||||
type="checkbox"
|
{...input}
|
||||||
className="custom-switch-input"
|
type="checkbox"
|
||||||
value={placeholder.toLowerCase()}
|
className="custom-switch-input"
|
||||||
disabled={disabled}
|
value={placeholder.toLowerCase()}
|
||||||
/>
|
disabled={disabled}
|
||||||
<span className="service__switch custom-switch-indicator"></span>
|
/>
|
||||||
<span className="service__text">{placeholder}</span>
|
<span className="service__switch custom-switch-indicator"></span>
|
||||||
<svg className="service__icon">
|
<span className="service__text" title={placeholder}>
|
||||||
<use xlinkHref={`#${icon}`} />
|
{placeholder}
|
||||||
</svg>
|
</span>
|
||||||
</label>
|
{icon && (
|
||||||
{!disabled && touched && error
|
<div
|
||||||
&& <span className="form__message form__message--error"><Trans>{error}</Trans></span>}
|
dangerouslySetInnerHTML={{ __html: window.atob(icon) }}
|
||||||
</Fragment>;
|
className="service__icon"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
{!disabled && touched && error && (
|
||||||
|
<span className="form__message form__message--error">
|
||||||
|
<Trans>{error}</Trans>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
renderServiceField.propTypes = {
|
renderServiceField.propTypes = {
|
||||||
input: PropTypes.object.isRequired,
|
input: PropTypes.object.isRequired,
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import {
|
|||||||
FILTERED,
|
FILTERED,
|
||||||
FILTERED_STATUS,
|
FILTERED_STATUS,
|
||||||
R_CLIENT_ID,
|
R_CLIENT_ID,
|
||||||
SERVICES_ID_NAME_MAP,
|
|
||||||
STANDARD_DNS_PORT,
|
STANDARD_DNS_PORT,
|
||||||
STANDARD_HTTPS_PORT,
|
STANDARD_HTTPS_PORT,
|
||||||
STANDARD_WEB_PORT,
|
STANDARD_WEB_PORT,
|
||||||
@@ -991,7 +990,22 @@ export const filterOutComments = (lines) => lines
|
|||||||
.filter((line) => !line.startsWith(COMMENT_LINE_DEFAULT_TOKEN));
|
.filter((line) => !line.startsWith(COMMENT_LINE_DEFAULT_TOKEN));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} serviceId
|
* @param {array} services
|
||||||
|
* @param {string} id
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export const getServiceName = (serviceId) => SERVICES_ID_NAME_MAP[serviceId] || serviceId;
|
export const getService = (services, id) => services.find((s) => s.id === id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {array} services
|
||||||
|
* @param {string} id
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const getServiceName = (services, id) => getService(services, id)?.name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {array} services
|
||||||
|
* @param {string} id
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const getServiceIcon = (services, id) => getService(services, id)?.icon_svg;
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ export const validateNotInRange = (value, allValues) => {
|
|||||||
const { range_start, range_end } = allValues.v4;
|
const { range_start, range_end } = allValues.v4;
|
||||||
|
|
||||||
if (range_start && validateIpv4(range_start)) {
|
if (range_start && validateIpv4(range_start)) {
|
||||||
return 'form_error_ip4_range_start_format';
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range_end && validateIpv4(range_end)) {
|
if (range_end && validateIpv4(range_end)) {
|
||||||
return 'form_error_ip4_range_end_format';
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAboveMin = range_start && ip4ToInt(value) >= ip4ToInt(range_start);
|
const isAboveMin = range_start && ip4ToInt(value) >= ip4ToInt(range_start);
|
||||||
@@ -94,14 +94,6 @@ export const validateNotInRange = (value, allValues) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!range_end && isAboveMin) {
|
|
||||||
return 'lower_range_start_error';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!range_start && isBelowMax) {
|
|
||||||
return 'greater_range_end_error';
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +110,7 @@ export const validateGatewaySubnetMask = (_, allValues) => {
|
|||||||
const { subnet_mask, gateway_ip } = allValues.v4;
|
const { subnet_mask, gateway_ip } = allValues.v4;
|
||||||
|
|
||||||
if (validateIpv4(gateway_ip)) {
|
if (validateIpv4(gateway_ip)) {
|
||||||
return 'form_error_ip4_gateway_format';
|
return 'gateway_or_subnet_invalid';
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseSubnetMask(subnet_mask) ? undefined : 'gateway_or_subnet_invalid';
|
return parseSubnetMask(subnet_mask) ? undefined : 'gateway_or_subnet_invalid';
|
||||||
@@ -138,6 +130,10 @@ export const validateIpForGatewaySubnetMask = (value, allValues) => {
|
|||||||
gateway_ip, subnet_mask,
|
gateway_ip, subnet_mask,
|
||||||
} = allValues.v4;
|
} = allValues.v4;
|
||||||
|
|
||||||
|
if ((gateway_ip && validateIpv4(gateway_ip)) || (subnet_mask && validateIpv4(subnet_mask))) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const subnetPrefix = parseSubnetMask(subnet_mask);
|
const subnetPrefix = parseSubnetMask(subnet_mask);
|
||||||
|
|
||||||
if (!isIpInCidr(value, `${gateway_ip}/${subnetPrefix}`)) {
|
if (!isIpInCidr(value, `${gateway_ip}/${subnetPrefix}`)) {
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ const services = handleActions(
|
|||||||
processing: false,
|
processing: false,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
[actions.getAllBlockedServicesRequest]: (state) => ({ ...state, processingAll: true }),
|
||||||
|
[actions.getAllBlockedServicesFailure]: (state) => ({ ...state, processingAll: false }),
|
||||||
|
[actions.getAllBlockedServicesSuccess]: (state, { payload }) => ({
|
||||||
|
...state,
|
||||||
|
allServices: payload.blocked_services,
|
||||||
|
processingAll: false,
|
||||||
|
}),
|
||||||
|
|
||||||
[actions.setBlockedServicesRequest]: (state) => ({ ...state, processingSet: true }),
|
[actions.setBlockedServicesRequest]: (state) => ({ ...state, processingSet: true }),
|
||||||
[actions.setBlockedServicesFailure]: (state) => ({ ...state, processingSet: false }),
|
[actions.setBlockedServicesFailure]: (state) => ({ ...state, processingSet: false }),
|
||||||
[actions.setBlockedServicesSuccess]: (state) => ({
|
[actions.setBlockedServicesSuccess]: (state) => ({
|
||||||
@@ -21,8 +29,10 @@ const services = handleActions(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
processing: true,
|
processing: true,
|
||||||
|
processingAll: true,
|
||||||
processingSet: false,
|
processingSet: false,
|
||||||
list: [],
|
list: [],
|
||||||
|
allServices: [],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
41
go.mod
41
go.mod
@@ -3,24 +3,24 @@ module github.com/AdguardTeam/AdGuardHome
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/dnsproxy v0.46.1
|
github.com/AdguardTeam/dnsproxy v0.46.5
|
||||||
github.com/AdguardTeam/golibs v0.10.9
|
github.com/AdguardTeam/golibs v0.11.3
|
||||||
github.com/AdguardTeam/urlfilter v0.16.0
|
github.com/AdguardTeam/urlfilter v0.16.0
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.5
|
github.com/ameshkov/dnscrypt/v2 v2.2.5
|
||||||
github.com/digineo/go-ipset/v2 v2.2.1
|
github.com/digineo/go-ipset/v2 v2.2.1
|
||||||
github.com/dimfeld/httptreemux/v5 v5.4.0
|
github.com/dimfeld/httptreemux/v5 v5.5.0
|
||||||
github.com/fsnotify/fsnotify v1.5.4
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/go-ping/ping v1.1.0
|
github.com/go-ping/ping v1.1.0
|
||||||
github.com/google/go-cmp v0.5.8
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/google/renameio v1.0.1
|
github.com/google/renameio v1.0.1
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84
|
github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c
|
||||||
github.com/kardianos/service v1.2.1
|
github.com/kardianos/service v1.2.2
|
||||||
github.com/lucas-clemente/quic-go v0.29.2
|
github.com/lucas-clemente/quic-go v0.31.0
|
||||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
||||||
github.com/mdlayher/netlink v1.6.0
|
github.com/mdlayher/netlink v1.6.2
|
||||||
// TODO(a.garipov): This package is deprecated; find a new one or use
|
// TODO(a.garipov): This package is deprecated; find a new one or use
|
||||||
// our own code for that. Perhaps, use gopacket.
|
// our own code for that. Perhaps, use gopacket.
|
||||||
github.com/mdlayher/raw v0.1.0
|
github.com/mdlayher/raw v0.1.0
|
||||||
@@ -28,10 +28,10 @@ require (
|
|||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/ti-mo/netfilter v0.4.0
|
github.com/ti-mo/netfilter v0.4.0
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
|
golang.org/x/crypto v0.1.0
|
||||||
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9
|
golang.org/x/exp v0.0.0-20221106115401-f9659909a136
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc
|
golang.org/x/net v0.4.0
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec
|
golang.org/x/sys v0.3.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
howett.net/plist v1.0.0
|
howett.net/plist v1.0.0
|
||||||
@@ -47,21 +47,20 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/josharian/native v1.0.0 // indirect
|
github.com/josharian/native v1.0.0 // indirect
|
||||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
github.com/marten-seemann/qpack v0.3.0 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||||
github.com/mdlayher/packet v1.0.0 // indirect
|
github.com/mdlayher/packet v1.0.0 // indirect
|
||||||
github.com/mdlayher/socket v0.2.3 // indirect
|
github.com/mdlayher/socket v0.2.3 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/onsi/ginkgo/v2 v2.5.0 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect
|
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220922195421-2adab6b8c60e // indirect
|
golang.org/x/mod v0.6.0 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
145
go.sum
145
go.sum
@@ -1,9 +1,9 @@
|
|||||||
github.com/AdguardTeam/dnsproxy v0.46.1 h1:ej9iRorG+vekaXGYB854waAiS+q8OfswYZ1MQRZolHk=
|
github.com/AdguardTeam/dnsproxy v0.46.5 h1:TiJZhwaIDDaKkqEfJ9AD9aroFjcHN8oEbKB8WfTjSIs=
|
||||||
github.com/AdguardTeam/dnsproxy v0.46.1/go.mod h1:PAmRzFqls0E92XTglyY2ESAqMAzZJhHKErG1ZpRnpjA=
|
github.com/AdguardTeam/dnsproxy v0.46.5/go.mod h1:yKBVgFlE6CqTQtye++3e7SATaMPc4Ixij+KkHsM6HhM=
|
||||||
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||||
github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
github.com/AdguardTeam/golibs v0.10.4/go.mod h1:rSfQRGHIdgfxriDDNgNJ7HmE5zRoURq8R+VdR81Zuzw=
|
||||||
github.com/AdguardTeam/golibs v0.10.9 h1:F9oP2da0dQ9RQDM1lGR7LxUTfUWu8hEFOs4icwAkKM0=
|
github.com/AdguardTeam/golibs v0.11.3 h1:Oif+REq2WLycQ2Xm3ZPmJdfftptss0HbGWbxdFaC310=
|
||||||
github.com/AdguardTeam/golibs v0.10.9/go.mod h1:W+5rznZa1cSNSFt+gPS7f4Wytnr9fOrd5ZYqwadPw14=
|
github.com/AdguardTeam/golibs v0.11.3/go.mod h1:87bN2x4VsTritptE3XZg9l8T6gznWsIxHBcQ1DeRIXA=
|
||||||
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
||||||
github.com/AdguardTeam/urlfilter v0.16.0 h1:IO29m+ZyQuuOnPLTzHuXj35V1DZOp1Dcryl576P2syg=
|
github.com/AdguardTeam/urlfilter v0.16.0 h1:IO29m+ZyQuuOnPLTzHuXj35V1DZOp1Dcryl576P2syg=
|
||||||
github.com/AdguardTeam/urlfilter v0.16.0/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI=
|
github.com/AdguardTeam/urlfilter v0.16.0/go.mod h1:46YZDOV1+qtdRDuhZKVPSSp7JWWes0KayqHrKAFBdEI=
|
||||||
@@ -25,19 +25,21 @@ github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 h1:0b2vaepXIfMsG+
|
|||||||
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
|
||||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/digineo/go-ipset/v2 v2.2.1 h1:k6skY+0fMqeUjjeWO/m5OuWPSZUAn7AucHMnQ1MX77g=
|
github.com/digineo/go-ipset/v2 v2.2.1 h1:k6skY+0fMqeUjjeWO/m5OuWPSZUAn7AucHMnQ1MX77g=
|
||||||
github.com/digineo/go-ipset/v2 v2.2.1/go.mod h1:wBsNzJlZlABHUITkesrggFnZQtgW5wkqw1uo8Qxe0VU=
|
github.com/digineo/go-ipset/v2 v2.2.1/go.mod h1:wBsNzJlZlABHUITkesrggFnZQtgW5wkqw1uo8Qxe0VU=
|
||||||
github.com/dimfeld/httptreemux/v5 v5.4.0 h1:IiHYEjh+A7pYbhWyjmGnj5HZK6gpOOvyBXCJ+BE8/Gs=
|
github.com/dimfeld/httptreemux/v5 v5.5.0 h1:p8jkiMrCuZ0CmhwYLcbNbl7DDo21fozhKHQ2PccwOFQ=
|
||||||
github.com/dimfeld/httptreemux/v5 v5.4.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw=
|
github.com/dimfeld/httptreemux/v5 v5.5.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw=
|
||||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
|
||||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
||||||
@@ -46,14 +48,7 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd
|
|||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -61,21 +56,23 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
|
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
|
||||||
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
||||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
|
||||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
||||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84 h1:MJTy6H+EpXLeAn0P5WAWeLk6dJA3V0ik6S3VJfUyQuI=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c h1:OCFM4+DXTWfNlyeoddrTwdup/ztkGSyAMR2UGcPckNQ=
|
||||||
|
github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
||||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
@@ -84,16 +81,16 @@ github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGu
|
|||||||
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/kardianos/service v1.2.1 h1:AYndMsehS+ywIS6RB9KOlcXzteWUzxgMgBymJD7+BYk=
|
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
|
||||||
github.com/kardianos/service v1.2.1/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
|
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lucas-clemente/quic-go v0.29.2 h1:O8Mt0O6LpvEW+wfC40vZdcw0DngwYzoxq5xULZNzSI8=
|
github.com/lucas-clemente/quic-go v0.31.0 h1:MfNp3fk0wjWRajw6quMFA3ap1AVtlU+2mtwmbVogB2M=
|
||||||
github.com/lucas-clemente/quic-go v0.29.2/go.mod h1:g6/h9YMmLuU54tL1gW25uIi3VlBp3uv+sBihplIuskE=
|
github.com/lucas-clemente/quic-go v0.31.0/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||||
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
|
github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
|
||||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
||||||
@@ -107,15 +104,14 @@ github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqc
|
|||||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||||
github.com/mdlayher/netlink v1.1.2-0.20201013204415-ded538f7f4be/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
github.com/mdlayher/netlink v1.1.2-0.20201013204415-ded538f7f4be/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||||
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
|
github.com/mdlayher/netlink v1.6.2 h1:D2zGSkvYsJ6NreeED3JiVTu1lj2sIYATqSaZlhPzUgQ=
|
||||||
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
|
github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU=
|
||||||
github.com/mdlayher/packet v1.0.0 h1:InhZJbdShQYt6XV2GPj5XHxChzOfhJJOMbvnGAmOfQ8=
|
github.com/mdlayher/packet v1.0.0 h1:InhZJbdShQYt6XV2GPj5XHxChzOfhJJOMbvnGAmOfQ8=
|
||||||
github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU=
|
github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU=
|
||||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
|
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
|
||||||
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
|
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
|
||||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
|
||||||
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||||
github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM=
|
github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM=
|
||||||
github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY=
|
github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY=
|
||||||
@@ -124,17 +120,9 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
|||||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
|
||||||
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/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.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@@ -166,24 +154,21 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy
|
|||||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME=
|
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME=
|
||||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A=
|
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
|
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw=
|
||||||
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220922195421-2adab6b8c60e h1:WhB000cGjOfbJiedMGvJkMTclI18VD69w27k+sceql8=
|
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220922195421-2adab6b8c60e/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -193,28 +178,22 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ=
|
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -223,14 +202,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -238,7 +213,6 @@ golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -250,53 +224,42 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
|
golang.org/x/sys v0.3.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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||||
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
|
||||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ARPDB: The Network Neighborhood Database
|
// ARPDB: The Network Neighborhood Database
|
||||||
@@ -54,7 +55,7 @@ type Neighbor struct {
|
|||||||
Name string
|
Name string
|
||||||
|
|
||||||
// IP contains either IPv4 or IPv6.
|
// IP contains either IPv4 or IPv6.
|
||||||
IP net.IP
|
IP netip.Addr
|
||||||
|
|
||||||
// MAC contains the hardware address.
|
// MAC contains the hardware address.
|
||||||
MAC net.HardwareAddr
|
MAC net.HardwareAddr
|
||||||
@@ -64,8 +65,8 @@ type Neighbor struct {
|
|||||||
func (n Neighbor) Clone() (clone Neighbor) {
|
func (n Neighbor) Clone() (clone Neighbor) {
|
||||||
return Neighbor{
|
return Neighbor{
|
||||||
Name: n.Name,
|
Name: n.Name,
|
||||||
IP: netutil.CloneIP(n.IP),
|
IP: n.IP,
|
||||||
MAC: netutil.CloneMAC(n.MAC),
|
MAC: slices.Clone(n.MAC),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package aghnet
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -47,22 +48,28 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
if ipStr := fields[1]; len(ipStr) < 2 {
|
if ipStr := fields[1]; len(ipStr) < 2 {
|
||||||
continue
|
continue
|
||||||
} else if ip := net.ParseIP(ipStr[1 : len(ipStr)-1]); ip == nil {
|
} else if ip, err := netip.ParseAddr(ipStr[1 : len(ipStr)-1]); err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: ip: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
hwStr := fields[3]
|
hwStr := fields[3]
|
||||||
if mac, err := net.ParseMAC(hwStr); err != nil {
|
mac, err := net.ParseMAC(hwStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: mac: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.MAC = mac
|
n.MAC = mac
|
||||||
}
|
}
|
||||||
|
|
||||||
host := fields[0]
|
host := fields[0]
|
||||||
if err := netutil.ValidateDomainName(host); err != nil {
|
err = netutil.ValidateDomainName(host)
|
||||||
log.Debug("parsing arp output: %s", err)
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: host: %s", err)
|
||||||
} else {
|
} else {
|
||||||
n.Name = host
|
n.Name = host
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package aghnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
const arpAOutput = `
|
const arpAOutput = `
|
||||||
@@ -17,14 +18,14 @@ hostname.two (::ffff:ffff) at ef:cd:ab:ef:cd:ab on em0 expires in 1198 seconds [
|
|||||||
|
|
||||||
var wantNeighs = []Neighbor{{
|
var wantNeighs = []Neighbor{{
|
||||||
Name: "hostname.one",
|
Name: "hostname.one",
|
||||||
IP: net.IPv4(192, 168, 1, 2),
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
||||||
}, {
|
}, {
|
||||||
Name: "hostname.two",
|
Name: "hostname.two",
|
||||||
IP: net.ParseIP("::ffff:ffff"),
|
IP: netip.MustParseAddr("::ffff:ffff"),
|
||||||
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
||||||
}, {
|
}, {
|
||||||
Name: "",
|
Name: "",
|
||||||
IP: net.ParseIP("::1234"),
|
IP: netip.MustParseAddr("::1234"),
|
||||||
MAC: net.HardwareAddr{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
|
MAC: net.HardwareAddr{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -94,7 +95,8 @@ func (arp *fsysARPDB) Refresh() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := Neighbor{}
|
n := Neighbor{}
|
||||||
if n.IP = net.ParseIP(fields[0]); n.IP == nil || n.IP.IsUnspecified() {
|
n.IP, err = netip.ParseAddr(fields[0])
|
||||||
|
if err != nil || n.IP.IsUnspecified() {
|
||||||
continue
|
continue
|
||||||
} else if n.MAC, err = net.ParseMAC(fields[3]); err != nil {
|
} else if n.MAC, err = net.ParseMAC(fields[3]); err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -135,15 +137,19 @@ func parseArpAWrt(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
n := Neighbor{}
|
n := Neighbor{}
|
||||||
|
|
||||||
if ip := net.ParseIP(fields[0]); ip == nil || n.IP.IsUnspecified() {
|
ip, err := netip.ParseAddr(fields[0])
|
||||||
|
if err != nil || n.IP.IsUnspecified() {
|
||||||
|
log.Debug("arpdb: parsing arp output: ip: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
hwStr := fields[3]
|
hwStr := fields[3]
|
||||||
if mac, err := net.ParseMAC(hwStr); err != nil {
|
mac, err := net.ParseMAC(hwStr)
|
||||||
log.Debug("parsing arp output: %s", err)
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: mac: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
@@ -174,7 +180,9 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
if ipStr := fields[1]; len(ipStr) < 2 {
|
if ipStr := fields[1]; len(ipStr) < 2 {
|
||||||
continue
|
continue
|
||||||
} else if ip := net.ParseIP(ipStr[1 : len(ipStr)-1]); ip == nil {
|
} else if ip, err := netip.ParseAddr(ipStr[1 : len(ipStr)-1]); err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: ip: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
@@ -182,7 +190,7 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
hwStr := fields[3]
|
hwStr := fields[3]
|
||||||
if mac, err := net.ParseMAC(hwStr); err != nil {
|
if mac, err := net.ParseMAC(hwStr); err != nil {
|
||||||
log.Debug("parsing arp output: %s", err)
|
log.Debug("arpdb: parsing arp output: mac: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
@@ -191,7 +199,7 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
host := fields[0]
|
host := fields[0]
|
||||||
if verr := netutil.ValidateDomainName(host); verr != nil {
|
if verr := netutil.ValidateDomainName(host); verr != nil {
|
||||||
log.Debug("parsing arp output: %s", verr)
|
log.Debug("arpdb: parsing arp output: host: %s", verr)
|
||||||
} else {
|
} else {
|
||||||
n.Name = host
|
n.Name = host
|
||||||
}
|
}
|
||||||
@@ -218,14 +226,18 @@ func parseIPNeigh(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
n := Neighbor{}
|
n := Neighbor{}
|
||||||
|
|
||||||
if ip := net.ParseIP(fields[0]); ip == nil {
|
ip, err := netip.ParseAddr(fields[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: ip: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if mac, err := net.ParseMAC(fields[4]); err != nil {
|
mac, err := net.ParseMAC(fields[4])
|
||||||
log.Debug("parsing arp output: %s", err)
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: mac: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package aghnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/fstest"
|
"testing/fstest"
|
||||||
@@ -33,10 +34,10 @@ const ipNeighOutput = `
|
|||||||
::ffff:ffff dev enp0s3 lladdr ef:cd:ab:ef:cd:ab router STALE`
|
::ffff:ffff dev enp0s3 lladdr ef:cd:ab:ef:cd:ab router STALE`
|
||||||
|
|
||||||
var wantNeighs = []Neighbor{{
|
var wantNeighs = []Neighbor{{
|
||||||
IP: net.IPv4(192, 168, 1, 2),
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
||||||
}, {
|
}, {
|
||||||
IP: net.ParseIP("::ffff:ffff"),
|
IP: netip.MustParseAddr("::ffff:ffff"),
|
||||||
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package aghnet
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -50,14 +51,18 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
n := Neighbor{}
|
n := Neighbor{}
|
||||||
|
|
||||||
if ip := net.ParseIP(fields[0]); ip == nil {
|
ip, err := netip.ParseAddr(fields[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: ip: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if mac, err := net.ParseMAC(fields[1]); err != nil {
|
mac, err := net.ParseMAC(fields[1])
|
||||||
log.Debug("parsing arp output: %s", err)
|
if err != nil {
|
||||||
|
log.Debug("arpdb: parsing arp output: mac: %s", err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package aghnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
const arpAOutput = `
|
const arpAOutput = `
|
||||||
@@ -15,9 +16,9 @@ Host Ethernet Address Netif Expire Flags
|
|||||||
`
|
`
|
||||||
|
|
||||||
var wantNeighs = []Neighbor{{
|
var wantNeighs = []Neighbor{{
|
||||||
IP: net.IPv4(192, 168, 1, 2),
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
||||||
}, {
|
}, {
|
||||||
IP: net.ParseIP("::ffff:ffff"),
|
IP: netip.MustParseAddr("::ffff:ffff"),
|
||||||
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package aghnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ func (arp *TestARPDB) Neighbors() (ns []Neighbor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestARPDBS(t *testing.T) {
|
func TestARPDBS(t *testing.T) {
|
||||||
knownIP := net.IP{1, 2, 3, 4}
|
knownIP := netip.MustParseAddr("1.2.3.4")
|
||||||
knownMAC := net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF}
|
knownMAC := net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF}
|
||||||
|
|
||||||
succRefrCount, failRefrCount := 0, 0
|
succRefrCount, failRefrCount := 0, 0
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package aghnet
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -43,13 +44,15 @@ func parseArpA(sc *bufio.Scanner, lenHint int) (ns []Neighbor) {
|
|||||||
|
|
||||||
n := Neighbor{}
|
n := Neighbor{}
|
||||||
|
|
||||||
if ip := net.ParseIP(fields[0]); ip == nil {
|
ip, err := netip.ParseAddr(fields[0])
|
||||||
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.IP = ip
|
n.IP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if mac, err := net.ParseMAC(fields[1]); err != nil {
|
mac, err := net.ParseMAC(fields[1])
|
||||||
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
n.MAC = mac
|
n.MAC = mac
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package aghnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
const arpAOutput = `
|
const arpAOutput = `
|
||||||
@@ -14,9 +15,9 @@ Interface: 192.168.1.1 --- 0x7
|
|||||||
::ffff:ffff ef-cd-ab-ef-cd-ab static`
|
::ffff:ffff ef-cd-ab-ef-cd-ab static`
|
||||||
|
|
||||||
var wantNeighs = []Neighbor{{
|
var wantNeighs = []Neighbor{{
|
||||||
IP: net.IPv4(192, 168, 1, 2),
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
MAC: net.HardwareAddr{0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF},
|
||||||
}, {
|
}, {
|
||||||
IP: net.ParseIP("::ffff:ffff"),
|
IP: netip.MustParseAddr("::ffff:ffff"),
|
||||||
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
MAC: net.HardwareAddr{0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net"
|
"net/netip"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/AdguardTeam/urlfilter/filterlist"
|
"github.com/AdguardTeam/urlfilter/filterlist"
|
||||||
"github.com/AdguardTeam/urlfilter/rules"
|
"github.com/AdguardTeam/urlfilter/rules"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultHostsPaths returns the slice of paths default for the operating system
|
// DefaultHostsPaths returns the slice of paths default for the operating system
|
||||||
@@ -106,14 +107,10 @@ type HostsContainer struct {
|
|||||||
done chan struct{}
|
done chan struct{}
|
||||||
|
|
||||||
// updates is the channel for receiving updated hosts.
|
// updates is the channel for receiving updated hosts.
|
||||||
//
|
updates chan HostsRecords
|
||||||
// TODO(e.burkov): Use map[netip.Addr]struct{} instead.
|
|
||||||
updates chan *netutil.IPMap
|
|
||||||
|
|
||||||
// last is the set of hosts that was cached within last detected change.
|
// last is the set of hosts that was cached within last detected change.
|
||||||
//
|
last HostsRecords
|
||||||
// TODO(e.burkov): Use map[netip.Addr]struct{} instead.
|
|
||||||
last *netutil.IPMap
|
|
||||||
|
|
||||||
// fsys is the working file system to read hosts files from.
|
// fsys is the working file system to read hosts files from.
|
||||||
fsys fs.FS
|
fsys fs.FS
|
||||||
@@ -128,6 +125,27 @@ type HostsContainer struct {
|
|||||||
listID int
|
listID int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostsRecords is a mapping of an IP address to its hosts data.
|
||||||
|
type HostsRecords map[netip.Addr]*HostsRecord
|
||||||
|
|
||||||
|
// HostsRecord represents a single hosts file record.
|
||||||
|
type HostsRecord struct {
|
||||||
|
Aliases *stringutil.Set
|
||||||
|
Canonical string
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal returns true if all fields of rec are equal to field in other or they
|
||||||
|
// both are nil.
|
||||||
|
func (rec *HostsRecord) equal(other *HostsRecord) (ok bool) {
|
||||||
|
if rec == nil {
|
||||||
|
return other == nil
|
||||||
|
} else if other == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return rec.Canonical == other.Canonical && rec.Aliases.Equal(other.Aliases)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrNoHostsPaths is returned when there are no valid paths to watch passed to
|
// ErrNoHostsPaths is returned when there are no valid paths to watch passed to
|
||||||
// the HostsContainer.
|
// the HostsContainer.
|
||||||
const ErrNoHostsPaths errors.Error = "no valid paths to hosts files provided"
|
const ErrNoHostsPaths errors.Error = "no valid paths to hosts files provided"
|
||||||
@@ -162,7 +180,7 @@ func NewHostsContainer(
|
|||||||
},
|
},
|
||||||
listID: listID,
|
listID: listID,
|
||||||
done: make(chan struct{}, 1),
|
done: make(chan struct{}, 1),
|
||||||
updates: make(chan *netutil.IPMap, 1),
|
updates: make(chan HostsRecords, 1),
|
||||||
fsys: fsys,
|
fsys: fsys,
|
||||||
w: w,
|
w: w,
|
||||||
patterns: patterns,
|
patterns: patterns,
|
||||||
@@ -200,9 +218,8 @@ func (hc *HostsContainer) Close() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upd returns the channel into which the updates are sent. The receivable
|
// Upd returns the channel into which the updates are sent.
|
||||||
// map's values are guaranteed to be of type of *HostsRecord.
|
func (hc *HostsContainer) Upd() (updates <-chan HostsRecords) {
|
||||||
func (hc *HostsContainer) Upd() (updates <-chan *netutil.IPMap) {
|
|
||||||
return hc.updates
|
return hc.updates
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +285,7 @@ type hostsParser struct {
|
|||||||
|
|
||||||
// table stores only the unique IP-hostname pairs. It's also sent to the
|
// table stores only the unique IP-hostname pairs. It's also sent to the
|
||||||
// updates channel afterwards.
|
// updates channel afterwards.
|
||||||
table *netutil.IPMap
|
table HostsRecords
|
||||||
}
|
}
|
||||||
|
|
||||||
// newHostsParser creates a new *hostsParser with buffers of size taken from the
|
// newHostsParser creates a new *hostsParser with buffers of size taken from the
|
||||||
@@ -277,7 +294,7 @@ func (hc *HostsContainer) newHostsParser() (hp *hostsParser) {
|
|||||||
return &hostsParser{
|
return &hostsParser{
|
||||||
rulesBuilder: &strings.Builder{},
|
rulesBuilder: &strings.Builder{},
|
||||||
translations: map[string]string{},
|
translations: map[string]string{},
|
||||||
table: netutil.NewIPMap(hc.last.Len()),
|
table: make(HostsRecords, len(hc.last)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +306,7 @@ func (hp *hostsParser) parseFile(r io.Reader) (patterns []string, cont bool, err
|
|||||||
s := bufio.NewScanner(r)
|
s := bufio.NewScanner(r)
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
ip, hosts := hp.parseLine(s.Text())
|
ip, hosts := hp.parseLine(s.Text())
|
||||||
if ip == nil || len(hosts) == 0 {
|
if ip == (netip.Addr{}) || len(hosts) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,14 +317,15 @@ func (hp *hostsParser) parseFile(r io.Reader) (patterns []string, cont bool, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseLine parses the line having the hosts syntax ignoring invalid ones.
|
// parseLine parses the line having the hosts syntax ignoring invalid ones.
|
||||||
func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
|
func (hp *hostsParser) parseLine(line string) (ip netip.Addr, hosts []string) {
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
if len(fields) < 2 {
|
if len(fields) < 2 {
|
||||||
return nil, nil
|
return netip.Addr{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if ip = net.ParseIP(fields[0]); ip == nil {
|
ip, err := netip.ParseAddr(fields[0])
|
||||||
return nil, nil
|
if err != nil {
|
||||||
|
return netip.Addr{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range fields[1:] {
|
for _, f := range fields[1:] {
|
||||||
@@ -325,7 +343,7 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
|
|||||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
|
||||||
//
|
//
|
||||||
// TODO(e.burkov): Investigate if hosts may contain DNS-SD domains.
|
// TODO(e.burkov): Investigate if hosts may contain DNS-SD domains.
|
||||||
err := netutil.ValidateDomainName(f)
|
err = netutil.ValidateDomainName(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("%s: host %q is invalid, ignoring", hostsContainerPref, f)
|
log.Error("%s: host %q is invalid, ignoring", hostsContainerPref, f)
|
||||||
|
|
||||||
@@ -338,30 +356,13 @@ func (hp *hostsParser) parseLine(line string) (ip net.IP, hosts []string) {
|
|||||||
return ip, hosts
|
return ip, hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostsRecord represents a single hosts file record.
|
|
||||||
type HostsRecord struct {
|
|
||||||
Aliases *stringutil.Set
|
|
||||||
Canonical string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal returns true if all fields of rec are equal to field in other or they
|
|
||||||
// both are nil.
|
|
||||||
func (rec *HostsRecord) Equal(other *HostsRecord) (ok bool) {
|
|
||||||
if rec == nil {
|
|
||||||
return other == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return rec.Canonical == other.Canonical && rec.Aliases.Equal(other.Aliases)
|
|
||||||
}
|
|
||||||
|
|
||||||
// addRecord puts the record for the IP address to the rules builder if needed.
|
// addRecord puts the record for the IP address to the rules builder if needed.
|
||||||
// The first host is considered to be the canonical name for the IP address.
|
// The first host is considered to be the canonical name for the IP address.
|
||||||
// hosts must have at least one name.
|
// hosts must have at least one name.
|
||||||
func (hp *hostsParser) addRecord(ip net.IP, hosts []string) {
|
func (hp *hostsParser) addRecord(ip netip.Addr, hosts []string) {
|
||||||
line := strings.Join(append([]string{ip.String()}, hosts...), " ")
|
line := strings.Join(append([]string{ip.String()}, hosts...), " ")
|
||||||
|
|
||||||
var rec *HostsRecord
|
rec, ok := hp.table[ip]
|
||||||
v, ok := hp.table.Get(ip)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
rec = &HostsRecord{
|
rec = &HostsRecord{
|
||||||
Aliases: stringutil.NewSet(),
|
Aliases: stringutil.NewSet(),
|
||||||
@@ -369,14 +370,7 @@ func (hp *hostsParser) addRecord(ip net.IP, hosts []string) {
|
|||||||
|
|
||||||
rec.Canonical, hosts = hosts[0], hosts[1:]
|
rec.Canonical, hosts = hosts[0], hosts[1:]
|
||||||
hp.addRules(ip, rec.Canonical, line)
|
hp.addRules(ip, rec.Canonical, line)
|
||||||
hp.table.Set(ip, rec)
|
hp.table[ip] = rec
|
||||||
} else {
|
|
||||||
rec, ok = v.(*HostsRecord)
|
|
||||||
if !ok {
|
|
||||||
log.Error("%s: adding pairs: unexpected type %T", hostsContainerPref, v)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, host := range hosts {
|
for _, host := range hosts {
|
||||||
@@ -391,7 +385,7 @@ func (hp *hostsParser) addRecord(ip net.IP, hosts []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addRules adds rules and rule translations for the line.
|
// addRules adds rules and rule translations for the line.
|
||||||
func (hp *hostsParser) addRules(ip net.IP, host, line string) {
|
func (hp *hostsParser) addRules(ip netip.Addr, host, line string) {
|
||||||
rule, rulePtr := hp.writeRules(host, ip)
|
rule, rulePtr := hp.writeRules(host, ip)
|
||||||
hp.translations[rule], hp.translations[rulePtr] = line, line
|
hp.translations[rule], hp.translations[rulePtr] = line, line
|
||||||
|
|
||||||
@@ -400,8 +394,9 @@ func (hp *hostsParser) addRules(ip net.IP, host, line string) {
|
|||||||
|
|
||||||
// writeRules writes the actual rule for the qtype and the PTR for the host-ip
|
// writeRules writes the actual rule for the qtype and the PTR for the host-ip
|
||||||
// pair into internal builders.
|
// pair into internal builders.
|
||||||
func (hp *hostsParser) writeRules(host string, ip net.IP) (rule, rulePtr string) {
|
func (hp *hostsParser) writeRules(host string, ip netip.Addr) (rule, rulePtr string) {
|
||||||
arpa, err := netutil.IPToReversedAddr(ip)
|
// TODO(a.garipov): Add a netip.Addr version to netutil.
|
||||||
|
arpa, err := netutil.IPToReversedAddr(ip.AsSlice())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
@@ -419,7 +414,7 @@ func (hp *hostsParser) writeRules(host string, ip net.IP) (rule, rulePtr string)
|
|||||||
var qtype string
|
var qtype string
|
||||||
// The validation of the IP address has been performed earlier so it is
|
// The validation of the IP address has been performed earlier so it is
|
||||||
// guaranteed to be either an IPv4 or an IPv6.
|
// guaranteed to be either an IPv4 or an IPv6.
|
||||||
if ip.To4() != nil {
|
if ip.Is4() {
|
||||||
qtype = "A"
|
qtype = "A"
|
||||||
} else {
|
} else {
|
||||||
qtype = "AAAA"
|
qtype = "AAAA"
|
||||||
@@ -446,51 +441,8 @@ func (hp *hostsParser) writeRules(host string, ip net.IP) (rule, rulePtr string)
|
|||||||
return rule, rulePtr
|
return rule, rulePtr
|
||||||
}
|
}
|
||||||
|
|
||||||
// equalSet returns true if the internal hosts table just parsed equals target.
|
|
||||||
// target's values must be of type *HostsRecord.
|
|
||||||
func (hp *hostsParser) equalSet(target *netutil.IPMap) (ok bool) {
|
|
||||||
if target == nil {
|
|
||||||
// hp.table shouldn't appear nil since it's initialized on each refresh.
|
|
||||||
return target == hp.table
|
|
||||||
}
|
|
||||||
|
|
||||||
if hp.table.Len() != target.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
hp.table.Range(func(ip net.IP, recVal any) (cont bool) {
|
|
||||||
var targetVal any
|
|
||||||
targetVal, ok = target.Get(ip)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var rec *HostsRecord
|
|
||||||
rec, ok = recVal.(*HostsRecord)
|
|
||||||
if !ok {
|
|
||||||
log.Error("%s: comparing: unexpected type %T", hostsContainerPref, recVal)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetRec *HostsRecord
|
|
||||||
targetRec, ok = targetVal.(*HostsRecord)
|
|
||||||
if !ok {
|
|
||||||
log.Error("%s: comparing: target: unexpected type %T", hostsContainerPref, targetVal)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = rec.Equal(targetRec)
|
|
||||||
|
|
||||||
return ok
|
|
||||||
})
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendUpd tries to send the parsed data to the ch.
|
// sendUpd tries to send the parsed data to the ch.
|
||||||
func (hp *hostsParser) sendUpd(ch chan *netutil.IPMap) {
|
func (hp *hostsParser) sendUpd(ch chan HostsRecords) {
|
||||||
log.Debug("%s: sending upd", hostsContainerPref)
|
log.Debug("%s: sending upd", hostsContainerPref)
|
||||||
|
|
||||||
upd := hp.table
|
upd := hp.table
|
||||||
@@ -528,14 +480,18 @@ func (hc *HostsContainer) refresh() (err error) {
|
|||||||
return fmt.Errorf("refreshing : %w", err)
|
return fmt.Errorf("refreshing : %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hp.equalSet(hc.last) {
|
// hc.last is nil on the first refresh, so let that one through.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Once https://github.com/golang/go/issues/56621 is
|
||||||
|
// resolved, remove the first condition.
|
||||||
|
if hc.last != nil && maps.EqualFunc(hp.table, hc.last, (*HostsRecord).equal) {
|
||||||
log.Debug("%s: no changes detected", hostsContainerPref)
|
log.Debug("%s: no changes detected", hostsContainerPref)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer hp.sendUpd(hc.updates)
|
defer hp.sendUpd(hc.updates)
|
||||||
|
|
||||||
hc.last = hp.table.ShallowClone()
|
hc.last = maps.Clone(hp.table)
|
||||||
|
|
||||||
var rulesStrg *filterlist.RuleStorage
|
var rulesStrg *filterlist.RuleStorage
|
||||||
if rulesStrg, err = hp.newStrg(hc.listID); err != nil {
|
if rulesStrg, err = hp.newStrg(hc.listID); err != nil {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package aghnet
|
|||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghchan"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghchan"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
"github.com/AdguardTeam/golibs/stringutil"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/AdguardTeam/urlfilter"
|
"github.com/AdguardTeam/urlfilter"
|
||||||
@@ -135,7 +137,7 @@ func TestNewHostsContainer(t *testing.T) {
|
|||||||
func TestHostsContainer_refresh(t *testing.T) {
|
func TestHostsContainer_refresh(t *testing.T) {
|
||||||
// TODO(e.burkov): Test the case with no actual updates.
|
// TODO(e.burkov): Test the case with no actual updates.
|
||||||
|
|
||||||
ip := net.IP{127, 0, 0, 1}
|
ip := netutil.IPv4Localhost()
|
||||||
ipStr := ip.String()
|
ipStr := ip.String()
|
||||||
|
|
||||||
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}}
|
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}}
|
||||||
@@ -167,17 +169,13 @@ func TestHostsContainer_refresh(t *testing.T) {
|
|||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.NotNil(t, upd)
|
require.NotNil(t, upd)
|
||||||
|
|
||||||
assert.Equal(t, 1, upd.Len())
|
assert.Len(t, upd, 1)
|
||||||
|
|
||||||
v, ok := upd.Get(ip)
|
rec, ok := upd[ip]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
require.IsType(t, (*HostsRecord)(nil), v)
|
|
||||||
|
|
||||||
rec, _ := v.(*HostsRecord)
|
|
||||||
require.NotNil(t, rec)
|
require.NotNil(t, rec)
|
||||||
|
|
||||||
assert.Truef(t, rec.Equal(want), "%+v != %+v", rec, want)
|
assert.Truef(t, rec.equal(want), "%+v != %+v", rec, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("initial_refresh", func(t *testing.T) {
|
t.Run("initial_refresh", func(t *testing.T) {
|
||||||
@@ -562,13 +560,13 @@ func TestHostsContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUniqueRules_ParseLine(t *testing.T) {
|
func TestUniqueRules_ParseLine(t *testing.T) {
|
||||||
ip := net.IP{127, 0, 0, 1}
|
ip := netutil.IPv4Localhost()
|
||||||
ipStr := ip.String()
|
ipStr := ip.String()
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
line string
|
line string
|
||||||
wantIP net.IP
|
wantIP netip.Addr
|
||||||
wantHosts []string
|
wantHosts []string
|
||||||
}{{
|
}{{
|
||||||
name: "simple",
|
name: "simple",
|
||||||
@@ -583,7 +581,7 @@ func TestUniqueRules_ParseLine(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
name: "invalid_line",
|
name: "invalid_line",
|
||||||
line: ipStr,
|
line: ipStr,
|
||||||
wantIP: nil,
|
wantIP: netip.Addr{},
|
||||||
wantHosts: nil,
|
wantHosts: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "invalid_line_hostname",
|
name: "invalid_line_hostname",
|
||||||
@@ -598,7 +596,7 @@ func TestUniqueRules_ParseLine(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
name: "whole_comment",
|
name: "whole_comment",
|
||||||
line: `# ` + ipStr + ` hostname`,
|
line: `# ` + ipStr + ` hostname`,
|
||||||
wantIP: nil,
|
wantIP: netip.Addr{},
|
||||||
wantHosts: nil,
|
wantHosts: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "partial_comment",
|
name: "partial_comment",
|
||||||
@@ -608,7 +606,7 @@ func TestUniqueRules_ParseLine(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
name: "empty",
|
name: "empty",
|
||||||
line: ``,
|
line: ``,
|
||||||
wantIP: nil,
|
wantIP: netip.Addr{},
|
||||||
wantHosts: nil,
|
wantHosts: nil,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@@ -616,7 +614,7 @@ func TestUniqueRules_ParseLine(t *testing.T) {
|
|||||||
hp := hostsParser{}
|
hp := hostsParser{}
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got, hosts := hp.parseLine(tc.line)
|
got, hosts := hp.parseLine(tc.line)
|
||||||
assert.True(t, tc.wantIP.Equal(got))
|
assert.Equal(t, tc.wantIP, got)
|
||||||
assert.Equal(t, tc.wantHosts, hosts)
|
assert.Equal(t, tc.wantHosts, hosts)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
func defaultHostsPaths() (paths []string) {
|
func defaultHostsPaths() (paths []string) {
|
||||||
sysDir, err := windows.GetSystemDirectory()
|
sysDir, err := windows.GetSystemDirectory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("getting system directory: %s", err)
|
log.Error("aghnet: getting system directory: %s", err)
|
||||||
|
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,12 +31,6 @@ var (
|
|||||||
// the IP being static is available.
|
// the IP being static is available.
|
||||||
const ErrNoStaticIPInfo errors.Error = "no information about static ip"
|
const ErrNoStaticIPInfo errors.Error = "no information about static ip"
|
||||||
|
|
||||||
// IPv4Localhost returns 127.0.0.1, which returns true for [netip.Addr.Is4].
|
|
||||||
func IPv4Localhost() (ip netip.Addr) { return netip.AddrFrom4([4]byte{127, 0, 0, 1}) }
|
|
||||||
|
|
||||||
// IPv6Localhost returns ::1, which returns true for [netip.Addr.Is6].
|
|
||||||
func IPv6Localhost() (ip netip.Addr) { return netip.AddrFrom16([16]byte{15: 1}) }
|
|
||||||
|
|
||||||
// IfaceHasStaticIP checks if interface is configured to have static IP address.
|
// IfaceHasStaticIP checks if interface is configured to have static IP address.
|
||||||
// If it can't give a definitive answer, it returns false and an error for which
|
// If it can't give a definitive answer, it returns false and an error for which
|
||||||
// errors.Is(err, ErrNoStaticIPInfo) is true.
|
// errors.Is(err, ErrNoStaticIPInfo) is true.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
@@ -20,7 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
aghtest.DiscardLogOutput(m)
|
testutil.DiscardLogOutput(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testdata is the filesystem containing data for testing the package.
|
// testdata is the filesystem containing data for testing the package.
|
||||||
@@ -189,17 +188,14 @@ func TestBroadcastFromIPNet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckPort(t *testing.T) {
|
func TestCheckPort(t *testing.T) {
|
||||||
laddr := netip.AddrPortFrom(IPv4Localhost(), 0)
|
laddr := netip.AddrPortFrom(netutil.IPv4Localhost(), 0)
|
||||||
|
|
||||||
t.Run("tcp_bound", func(t *testing.T) {
|
t.Run("tcp_bound", func(t *testing.T) {
|
||||||
l, err := net.Listen("tcp", laddr.String())
|
l, err := net.Listen("tcp", laddr.String())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, l.Close)
|
testutil.CleanupAndRequireSuccess(t, l.Close)
|
||||||
|
|
||||||
addr := l.Addr()
|
ipp := testutil.RequireTypeAssert[*net.TCPAddr](t, l.Addr()).AddrPort()
|
||||||
require.IsType(t, new(net.TCPAddr), addr)
|
|
||||||
|
|
||||||
ipp := addr.(*net.TCPAddr).AddrPort()
|
|
||||||
require.Equal(t, laddr.Addr(), ipp.Addr())
|
require.Equal(t, laddr.Addr(), ipp.Addr())
|
||||||
require.NotZero(t, ipp.Port())
|
require.NotZero(t, ipp.Port())
|
||||||
|
|
||||||
@@ -215,10 +211,7 @@ func TestCheckPort(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
||||||
|
|
||||||
addr := conn.LocalAddr()
|
ipp := testutil.RequireTypeAssert[*net.UDPAddr](t, conn.LocalAddr()).AddrPort()
|
||||||
require.IsType(t, new(net.UDPAddr), addr)
|
|
||||||
|
|
||||||
ipp := addr.(*net.UDPAddr).AddrPort()
|
|
||||||
require.Equal(t, laddr.Addr(), ipp.Addr())
|
require.Equal(t, laddr.Addr(), ipp.Addr())
|
||||||
require.NotZero(t, ipp.Port())
|
require.NotZero(t, ipp.Port())
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -17,9 +18,8 @@ func createTestSystemResolversImpl(
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
sr := createTestSystemResolvers(t, hostGenFunc)
|
sr := createTestSystemResolvers(t, hostGenFunc)
|
||||||
require.IsType(t, (*systemResolvers)(nil), sr)
|
|
||||||
|
|
||||||
return sr.(*systemResolvers)
|
return testutil.RequireTypeAssert[*systemResolvers](t, sr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSystemResolvers_Refresh(t *testing.T) {
|
func TestSystemResolvers_Refresh(t *testing.T) {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package aghos_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
aghtest.DiscardLogOutput(m)
|
testutil.DiscardLogOutput(m)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,11 +168,11 @@ func IsOpenWrt() (ok bool) {
|
|||||||
return isOpenWrt()
|
return isOpenWrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootDirFS returns the fs.FS rooted at the operating system's root.
|
// RootDirFS returns the [fs.FS] rooted at the operating system's root. On
|
||||||
|
// Windows it returns the fs.FS rooted at the volume of the system directory
|
||||||
|
// (usually, C:).
|
||||||
func RootDirFS() (fsys fs.FS) {
|
func RootDirFS() (fsys fs.FS) {
|
||||||
// Use empty string since os.DirFS implicitly prepends a slash to it. This
|
return rootDirFS()
|
||||||
// behavior is undocumented but it currently works.
|
|
||||||
return os.DirFS("")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyReconfigureSignal notifies c on receiving reconfigure signals.
|
// NotifyReconfigureSignal notifies c on receiving reconfigure signals.
|
||||||
|
|||||||
@@ -3,12 +3,17 @@
|
|||||||
package aghos
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func rootDirFS() (fsys fs.FS) {
|
||||||
|
return os.DirFS("/")
|
||||||
|
}
|
||||||
|
|
||||||
func notifyReconfigureSignal(c chan<- os.Signal) {
|
func notifyReconfigureSignal(c chan<- os.Signal) {
|
||||||
signal.Notify(c, unix.SIGHUP)
|
signal.Notify(c, unix.SIGHUP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,29 @@
|
|||||||
package aghos
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func rootDirFS() (fsys fs.FS) {
|
||||||
|
// TODO(a.garipov): Use a better way if golang/go#44279 is ever resolved.
|
||||||
|
sysDir, err := windows.GetSystemDirectory()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("aghos: getting root filesystem: %s; using C:", err)
|
||||||
|
|
||||||
|
// Assume that C: is the safe default.
|
||||||
|
return os.DirFS("C:")
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.DirFS(filepath.VolumeName(sysDir))
|
||||||
|
}
|
||||||
|
|
||||||
func setRlimit(val uint64) (err error) {
|
func setRlimit(val uint64) (err error) {
|
||||||
return Unsupported("setrlimit")
|
return Unsupported("setrlimit")
|
||||||
}
|
}
|
||||||
@@ -55,9 +71,7 @@ func isReconfigureSignal(sig os.Signal) (ok bool) {
|
|||||||
|
|
||||||
func isShutdownSignal(sig os.Signal) (ok bool) {
|
func isShutdownSignal(sig os.Signal) (ok bool) {
|
||||||
switch sig {
|
switch sig {
|
||||||
case
|
case os.Interrupt, syscall.SIGTERM:
|
||||||
os.Interrupt,
|
|
||||||
syscall.SIGTERM:
|
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -3,21 +3,11 @@ package aghtest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DiscardLogOutput runs tests with discarded logger output.
|
|
||||||
func DiscardLogOutput(m *testing.M) {
|
|
||||||
// TODO(e.burkov): Refactor code and tests to not use the global mutable
|
|
||||||
// logger.
|
|
||||||
log.SetOutput(io.Discard)
|
|
||||||
|
|
||||||
os.Exit(m.Run())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplaceLogWriter moves logger output to w and uses Cleanup method of t to
|
// ReplaceLogWriter moves logger output to w and uses Cleanup method of t to
|
||||||
// revert changes.
|
// revert changes.
|
||||||
func ReplaceLogWriter(t testing.TB, w io.Writer) {
|
func ReplaceLogWriter(t testing.TB, w io.Writer) {
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Additional Upstream Testing Utilities
|
// Additional Upstream Testing Utilities
|
||||||
@@ -26,51 +25,10 @@ type Upstream struct {
|
|||||||
IPv4 map[string][]net.IP
|
IPv4 map[string][]net.IP
|
||||||
// IPv6 is a map of hostname to IPv6.
|
// IPv6 is a map of hostname to IPv6.
|
||||||
IPv6 map[string][]net.IP
|
IPv6 map[string][]net.IP
|
||||||
// Reverse is a map of address to domain name.
|
|
||||||
Reverse map[string][]string
|
|
||||||
// Addr is the address for Address method.
|
|
||||||
Addr string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ upstream.Upstream = (*Upstream)(nil)
|
var _ upstream.Upstream = (*Upstream)(nil)
|
||||||
|
|
||||||
// RespondTo returns a response with answer if req has class cl, question type
|
|
||||||
// qt, and target targ.
|
|
||||||
func RespondTo(t testing.TB, req *dns.Msg, cl, qt uint16, targ, answer string) (resp *dns.Msg) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
require.NotNil(t, req)
|
|
||||||
require.Len(t, req.Question, 1)
|
|
||||||
|
|
||||||
q := req.Question[0]
|
|
||||||
targ = dns.Fqdn(targ)
|
|
||||||
if q.Qclass != cl || q.Qtype != qt || q.Name != targ {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
respHdr := dns.RR_Header{
|
|
||||||
Name: targ,
|
|
||||||
Rrtype: qt,
|
|
||||||
Class: cl,
|
|
||||||
Ttl: 60,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp = new(dns.Msg).SetReply(req)
|
|
||||||
switch qt {
|
|
||||||
case dns.TypePTR:
|
|
||||||
resp.Answer = []dns.RR{
|
|
||||||
&dns.PTR{
|
|
||||||
Hdr: respHdr,
|
|
||||||
Ptr: answer,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Fatalf("unsupported question type: %s", dns.Type(qt))
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exchange implements the [upstream.Upstream] interface for *Upstream.
|
// Exchange implements the [upstream.Upstream] interface for *Upstream.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Split further into handlers.
|
// TODO(a.garipov): Split further into handlers.
|
||||||
@@ -105,10 +63,6 @@ func (u *Upstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
|
|||||||
for _, ip := range u.IPv6[name] {
|
for _, ip := range u.IPv6[name] {
|
||||||
resp.Answer = append(resp.Answer, &dns.AAAA{Hdr: hdr, AAAA: ip})
|
resp.Answer = append(resp.Answer, &dns.AAAA{Hdr: hdr, AAAA: ip})
|
||||||
}
|
}
|
||||||
case dns.TypePTR:
|
|
||||||
for _, name := range u.Reverse[name] {
|
|
||||||
resp.Answer = append(resp.Answer, &dns.PTR{Hdr: hdr, Ptr: name})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(resp.Answer) == 0 {
|
if len(resp.Answer) == 0 {
|
||||||
resp.SetRcode(m, dns.RcodeNameError)
|
resp.SetRcode(m, dns.RcodeNameError)
|
||||||
@@ -119,7 +73,7 @@ func (u *Upstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
|
|||||||
|
|
||||||
// Address implements [upstream.Upstream] interface for *Upstream.
|
// Address implements [upstream.Upstream] interface for *Upstream.
|
||||||
func (u *Upstream) Address() string {
|
func (u *Upstream) Address() string {
|
||||||
return u.Addr
|
return "todo.upstream.example"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implements [upstream.Upstream] interface for *Upstream.
|
// Close implements [upstream.Upstream] interface for *Upstream.
|
||||||
@@ -127,6 +81,98 @@ func (u *Upstream) Close() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchedResponse is a test helper that returns a response with answer if req
|
||||||
|
// has question type qt, and target targ. Otherwise, it returns nil.
|
||||||
|
//
|
||||||
|
// req must not be nil and req.Question must have a length of 1. Answer is
|
||||||
|
// interpreted in the following ways:
|
||||||
|
//
|
||||||
|
// - For A and AAAA queries, answer must be an IP address of the corresponding
|
||||||
|
// protocol version.
|
||||||
|
//
|
||||||
|
// - For PTR queries, answer should be a domain name in the response.
|
||||||
|
//
|
||||||
|
// If the answer does not correspond to the question type, MatchedResponse panics.
|
||||||
|
// Panics are used instead of [testing.TB], because the helper is intended to
|
||||||
|
// use in [UpstreamMock.OnExchange] callbacks, which are usually called in a
|
||||||
|
// separate goroutine.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Consider adding version with DNS class as well.
|
||||||
|
func MatchedResponse(req *dns.Msg, qt uint16, targ, answer string) (resp *dns.Msg) {
|
||||||
|
if req == nil || len(req.Question) != 1 {
|
||||||
|
panic(fmt.Errorf("bad req: %+v", req))
|
||||||
|
}
|
||||||
|
|
||||||
|
q := req.Question[0]
|
||||||
|
targ = dns.Fqdn(targ)
|
||||||
|
if q.Qclass != dns.ClassINET || q.Qtype != qt || q.Name != targ {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
respHdr := dns.RR_Header{
|
||||||
|
Name: targ,
|
||||||
|
Rrtype: qt,
|
||||||
|
Class: dns.ClassINET,
|
||||||
|
Ttl: 60,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = new(dns.Msg).SetReply(req)
|
||||||
|
switch qt {
|
||||||
|
case dns.TypeA:
|
||||||
|
resp.Answer = mustAnsA(respHdr, answer)
|
||||||
|
case dns.TypeAAAA:
|
||||||
|
resp.Answer = mustAnsAAAA(respHdr, answer)
|
||||||
|
case dns.TypePTR:
|
||||||
|
resp.Answer = []dns.RR{&dns.PTR{
|
||||||
|
Hdr: respHdr,
|
||||||
|
Ptr: answer,
|
||||||
|
}}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("aghtest: bad question type: %s", dns.Type(qt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustAnsA returns valid answer records if s is a valid IPv4 address.
|
||||||
|
// Otherwise, mustAnsA panics.
|
||||||
|
func mustAnsA(respHdr dns.RR_Header, s string) (ans []dns.RR) {
|
||||||
|
ip, err := netip.ParseAddr(s)
|
||||||
|
if err != nil || !ip.Is4() {
|
||||||
|
panic(fmt.Errorf("aghtest: bad A answer: %+v", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
return []dns.RR{&dns.A{
|
||||||
|
Hdr: respHdr,
|
||||||
|
A: ip.AsSlice(),
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustAnsAAAA returns valid answer records if s is a valid IPv6 address.
|
||||||
|
// Otherwise, mustAnsAAAA panics.
|
||||||
|
func mustAnsAAAA(respHdr dns.RR_Header, s string) (ans []dns.RR) {
|
||||||
|
ip, err := netip.ParseAddr(s)
|
||||||
|
if err != nil || !ip.Is6() {
|
||||||
|
panic(fmt.Errorf("aghtest: bad AAAA answer: %+v", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
return []dns.RR{&dns.AAAA{
|
||||||
|
Hdr: respHdr,
|
||||||
|
AAAA: ip.AsSlice(),
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUpstreamMock returns an [*UpstreamMock], fields OnAddress and OnClose of
|
||||||
|
// which are set to stubs that return "upstream.example" and nil respectively.
|
||||||
|
// The field OnExchange is set to onExc.
|
||||||
|
func NewUpstreamMock(onExc func(req *dns.Msg) (resp *dns.Msg, err error)) (u *UpstreamMock) {
|
||||||
|
return &UpstreamMock{
|
||||||
|
OnAddress: func() (addr string) { return "upstream.example" },
|
||||||
|
OnExchange: onExc,
|
||||||
|
OnClose: func() (err error) { return nil },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewBlockUpstream returns an [*UpstreamMock] that works like an upstream that
|
// NewBlockUpstream returns an [*UpstreamMock] that works like an upstream that
|
||||||
// supports hash-based safe-browsing/adult-blocking feature. If shouldBlock is
|
// supports hash-based safe-browsing/adult-blocking feature. If shouldBlock is
|
||||||
// true, hostname's actual hash is returned, blocking it. Otherwise, it returns
|
// true, hostname's actual hash is returned, blocking it. Otherwise, it returns
|
||||||
@@ -152,9 +198,7 @@ func NewBlockUpstream(hostname string, shouldBlock bool) (u *UpstreamMock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &UpstreamMock{
|
return &UpstreamMock{
|
||||||
OnAddress: func() (addr string) {
|
OnAddress: func() (addr string) { return "sbpc.upstream.example" },
|
||||||
return "sbpc.upstream.example"
|
|
||||||
},
|
|
||||||
OnExchange: func(req *dns.Msg) (resp *dns.Msg, err error) {
|
OnExchange: func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||||
resp = respTmpl.Copy()
|
resp = respTmpl.Copy()
|
||||||
resp.SetReply(req)
|
resp.SetReply(req)
|
||||||
@@ -162,6 +206,7 @@ func NewBlockUpstream(hostname string, shouldBlock bool) (u *UpstreamMock) {
|
|||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
},
|
},
|
||||||
|
OnClose: func() (err error) { return nil },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +218,10 @@ const ErrUpstream errors.Error = "test upstream error"
|
|||||||
// its Exchange method.
|
// its Exchange method.
|
||||||
func NewErrorUpstream() (u *UpstreamMock) {
|
func NewErrorUpstream() (u *UpstreamMock) {
|
||||||
return &UpstreamMock{
|
return &UpstreamMock{
|
||||||
OnAddress: func() (addr string) {
|
OnAddress: func() (addr string) { return "error.upstream.example" },
|
||||||
return "error.upstream.example"
|
|
||||||
},
|
|
||||||
OnExchange: func(_ *dns.Msg) (resp *dns.Msg, err error) {
|
OnExchange: func(_ *dns.Msg) (resp *dns.Msg, err error) {
|
||||||
return nil, errors.Error("test upstream error")
|
return nil, errors.Error("test upstream error")
|
||||||
},
|
},
|
||||||
|
OnClose: func() (err error) { return nil },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package aghtls
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
@@ -69,3 +71,19 @@ func SaferCipherSuites() (safe []uint16) {
|
|||||||
|
|
||||||
return safe
|
return safe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertificateHasIP returns true if cert has at least a single IP address among
|
||||||
|
// its subjectAltNames.
|
||||||
|
func CertificateHasIP(cert *x509.Certificate) (ok bool) {
|
||||||
|
if len(cert.IPAddresses) > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range cert.DNSNames {
|
||||||
|
if _, err := netip.ParseAddr(name); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
aghtest.DiscardLogOutput(m)
|
testutil.DiscardLogOutput(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseCiphers(t *testing.T) {
|
func TestParseCiphers(t *testing.T) {
|
||||||
|
|||||||
@@ -137,14 +137,14 @@ func (c *V4ServerConf) Validate() (err error) {
|
|||||||
|
|
||||||
gatewayIP, err := ensureV4(c.GatewayIP, "address")
|
gatewayIP, err := ensureV4(c.GatewayIP, "address")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap an errors since it's informative enough as is and there is
|
// Don't wrap the error since it's informative enough as is and there is
|
||||||
// an annotation deferred already.
|
// an annotation deferred already.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
subnetMask, err := ensureV4(c.SubnetMask, "subnet mask")
|
subnetMask, err := ensureV4(c.SubnetMask, "subnet mask")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap an errors since it's informative enough as is and there is
|
// Don't wrap the error since it's informative enough as is and there is
|
||||||
// an annotation deferred already.
|
// an annotation deferred already.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -155,20 +155,21 @@ func (c *V4ServerConf) Validate() (err error) {
|
|||||||
|
|
||||||
rangeStart, err := ensureV4(c.RangeStart, "address")
|
rangeStart, err := ensureV4(c.RangeStart, "address")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap an errors since it's informative enough as is and there is
|
// Don't wrap the error since it's informative enough as is and there is
|
||||||
// an annotation deferred already.
|
// an annotation deferred already.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
rangeEnd, err := ensureV4(c.RangeEnd, "address")
|
rangeEnd, err := ensureV4(c.RangeEnd, "address")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap an errors since it's informative enough as is and there is
|
// Don't wrap the error since it's informative enough as is and there is
|
||||||
// an annotation deferred already.
|
// an annotation deferred already.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ipRange, err = newIPRange(rangeStart.AsSlice(), rangeEnd.AsSlice())
|
c.ipRange, err = newIPRange(rangeStart.AsSlice(), rangeEnd.AsSlice())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap an errors since it's informative enough as is and there is
|
// Don't wrap the error since it's informative enough as is and there is
|
||||||
// an annotation deferred already.
|
// an annotation deferred already.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -54,8 +54,8 @@ func (l *Lease) Clone() (clone *Lease) {
|
|||||||
return &Lease{
|
return &Lease{
|
||||||
Expiry: l.Expiry,
|
Expiry: l.Expiry,
|
||||||
Hostname: l.Hostname,
|
Hostname: l.Hostname,
|
||||||
HWAddr: netutil.CloneMAC(l.HWAddr),
|
HWAddr: slices.Clone(l.HWAddr),
|
||||||
IP: netutil.CloneIP(l.IP),
|
IP: slices.Clone(l.IP),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,8 +219,6 @@ var _ Interface = (*server)(nil)
|
|||||||
|
|
||||||
// Create initializes and returns the DHCP server handling both address
|
// Create initializes and returns the DHCP server handling both address
|
||||||
// families. It also registers the corresponding HTTP API endpoints.
|
// families. It also registers the corresponding HTTP API endpoints.
|
||||||
//
|
|
||||||
// TODO(e.burkov): Don't register handlers, see TODO on [aghhttp.RegisterFunc].
|
|
||||||
func Create(conf *ServerConfig) (s *server, err error) {
|
func Create(conf *ServerConfig) (s *server, err error) {
|
||||||
s = &server{
|
s = &server{
|
||||||
conf: &ServerConfig{
|
conf: &ServerConfig{
|
||||||
@@ -237,6 +235,8 @@ func Create(conf *ServerConfig) (s *server, err error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(e.burkov): Don't register handlers, see TODO on
|
||||||
|
// [aghhttp.RegisterFunc].
|
||||||
s.registerHandlers()
|
s.registerHandlers()
|
||||||
|
|
||||||
v4conf := conf.Conf4
|
v4conf := conf.Conf4
|
||||||
@@ -250,7 +250,7 @@ func Create(conf *ServerConfig) (s *server, err error) {
|
|||||||
return nil, fmt.Errorf("creating dhcpv4 srv: %w", err)
|
return nil, fmt.Errorf("creating dhcpv4 srv: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Error("creating dhcpv4 srv: %s", err)
|
log.Debug("dhcpd: warning: creating dhcpv4 srv: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v6conf := conf.Conf6
|
v6conf := conf.Conf6
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user