*: merge with master
This commit is contained in:
commit
1d213d53c8
|
@ -7,29 +7,29 @@
|
||||||
"da": "Dansk",
|
"da": "Dansk",
|
||||||
"de": "Deutsch",
|
"de": "Deutsch",
|
||||||
"nl": "Dutch",
|
"nl": "Dutch",
|
||||||
"no": "Norsk",
|
|
||||||
"en": "English",
|
"en": "English",
|
||||||
"es": "Español",
|
"es": "Español",
|
||||||
"fr": "Français",
|
"fr": "Français",
|
||||||
|
"hr": "Hrvatski",
|
||||||
"id": "Indonesian",
|
"id": "Indonesian",
|
||||||
"it": "Italiano",
|
"it": "Italiano",
|
||||||
|
"no": "Norsk",
|
||||||
"pl": "Polski",
|
"pl": "Polski",
|
||||||
"pt-br": "Portuguese (BR)",
|
"pt-br": "Portuguese (BR)",
|
||||||
"pt-pt": "Portuguese (PT)",
|
"pt-pt": "Portuguese (PT)",
|
||||||
"sk": "Slovenčina",
|
"sk": "Slovenčina",
|
||||||
"sl": "Slovenščina",
|
"sl": "Slovenščina",
|
||||||
|
"sr-cs": "Srpski",
|
||||||
"sv": "Svenska",
|
"sv": "Svenska",
|
||||||
"vi": "Tiếng Việt",
|
"vi": "Tiếng Việt",
|
||||||
"tr": "Türkçe",
|
"tr": "Türkçe",
|
||||||
"cs": "Český",
|
"cs": "Český",
|
||||||
"bg": "Български",
|
"bg": "Български",
|
||||||
"ru": "Русский",
|
"ru": "Русский",
|
||||||
|
"fa": "فارسی",
|
||||||
"ja": "日本語",
|
"ja": "日本語",
|
||||||
"zh-tw": "正體中文",
|
"zh-tw": "正體中文",
|
||||||
"zh-cn": "简体中文",
|
"zh-cn": "简体中文",
|
||||||
"sr-cs": "Srpski",
|
|
||||||
"hr": "Hrvatski",
|
|
||||||
"fa": "فارسی",
|
|
||||||
"ko": "한국어"
|
"ko": "한국어"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -5,7 +5,6 @@ GOPATH := $(shell go env GOPATH)
|
||||||
JSFILES = $(shell find client -path client/node_modules -prune -o -type f -name '*.js')
|
JSFILES = $(shell find client -path client/node_modules -prune -o -type f -name '*.js')
|
||||||
STATIC = build/static/index.html
|
STATIC = build/static/index.html
|
||||||
CHANNEL ?= release
|
CHANNEL ?= release
|
||||||
GOARM_VER :=
|
|
||||||
|
|
||||||
TARGET=AdGuardHome
|
TARGET=AdGuardHome
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ $(STATIC): $(JSFILES) client/node_modules
|
||||||
$(TARGET): $(STATIC) *.go home/*.go dhcpd/*.go dnsfilter/*.go dnsforward/*.go
|
$(TARGET): $(STATIC) *.go home/*.go dhcpd/*.go dnsfilter/*.go dnsforward/*.go
|
||||||
GOOS=$(NATIVE_GOOS) GOARCH=$(NATIVE_GOARCH) GO111MODULE=off go get -v github.com/gobuffalo/packr/...
|
GOOS=$(NATIVE_GOOS) GOARCH=$(NATIVE_GOARCH) GO111MODULE=off go get -v github.com/gobuffalo/packr/...
|
||||||
PATH=$(GOPATH)/bin:$(PATH) packr -z
|
PATH=$(GOPATH)/bin:$(PATH) packr -z
|
||||||
CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=$(GIT_VERSION) -X main.channel=$(CHANNEL) -X main.goarm=$(GOARM_VER)" -asmflags="-trimpath=$(PWD)" -gcflags="-trimpath=$(PWD)"
|
CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=$(GIT_VERSION) -X main.channel=$(CHANNEL) -X main.goarm=$(GOARM)" -asmflags="-trimpath=$(PWD)" -gcflags="-trimpath=$(PWD)"
|
||||||
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
PATH=$(GOPATH)/bin:$(PATH) packr clean
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
"react": {
|
"react": {
|
||||||
"pragma": "React",
|
"pragma": "React",
|
||||||
"version": "16.4"
|
"version": "16.4"
|
||||||
|
},
|
||||||
|
"import/resolver": {
|
||||||
|
"webpack": {
|
||||||
|
"config": "webpack.common.js"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -821,6 +821,7 @@
|
||||||
"version": "6.5.3",
|
"version": "6.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
|
||||||
"integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
|
"integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^2.0.1",
|
"fast-deep-equal": "^2.0.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
@ -837,7 +838,8 @@
|
||||||
"ajv-keywords": {
|
"ajv-keywords": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
|
||||||
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
|
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"align-text": {
|
"align-text": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
|
@ -925,6 +927,12 @@
|
||||||
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
|
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"array-find": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"array-find-index": {
|
"array-find-index": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||||
|
@ -2272,7 +2280,8 @@
|
||||||
"big.js": {
|
"big.js": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
|
||||||
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
|
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "1.11.0",
|
"version": "1.11.0",
|
||||||
|
@ -4212,7 +4221,8 @@
|
||||||
"emojis-list": {
|
"emojis-list": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
|
||||||
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
|
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"encodeurl": {
|
"encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -4548,6 +4558,79 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-import-resolver-webpack": {
|
||||||
|
"version": "0.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.12.1.tgz",
|
||||||
|
"integrity": "sha512-O/sUAXk6GWrICiN8JUkkjdt9uZpqZHP+FVnTxtEILL6EZMaPSrnP4lGPSFwcKsv7O211maqq4Nz60+dh236hVg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"array-find": "^1.0.0",
|
||||||
|
"debug": "^2.6.9",
|
||||||
|
"enhanced-resolve": "^0.9.1",
|
||||||
|
"find-root": "^1.1.0",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"interpret": "^1.2.0",
|
||||||
|
"lodash": "^4.17.15",
|
||||||
|
"node-libs-browser": "^1.0.0 || ^2.0.0",
|
||||||
|
"resolve": "^1.13.1",
|
||||||
|
"semver": "^5.7.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enhanced-resolve": {
|
||||||
|
"version": "0.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz",
|
||||||
|
"integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"memory-fs": "^0.2.0",
|
||||||
|
"tapable": "^0.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"interpret": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"memory-fs": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz",
|
||||||
|
"integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tapable": {
|
||||||
|
"version": "0.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
|
||||||
|
"integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-loader": {
|
"eslint-loader": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.9.0.tgz",
|
||||||
|
@ -5152,7 +5235,8 @@
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "2.2.6",
|
"version": "2.2.6",
|
||||||
|
@ -5171,7 +5255,8 @@
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-levenshtein": {
|
"fast-levenshtein": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
|
@ -7472,7 +7557,8 @@
|
||||||
"json-schema-traverse": {
|
"json-schema-traverse": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"json-stable-stringify-without-jsonify": {
|
"json-stable-stringify-without-jsonify": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -7489,7 +7575,8 @@
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
|
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"jsx-ast-utils": {
|
"jsx-ast-utils": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
|
@ -7627,6 +7714,7 @@
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
|
||||||
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
|
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"big.js": "^3.1.3",
|
"big.js": "^3.1.3",
|
||||||
"emojis-list": "^2.0.0",
|
"emojis-list": "^2.0.0",
|
||||||
|
@ -10208,7 +10296,8 @@
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"q": {
|
"q": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
|
@ -11058,6 +11147,7 @@
|
||||||
"version": "0.4.7",
|
"version": "0.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
||||||
"integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
|
"integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.1.0",
|
"ajv": "^6.1.0",
|
||||||
"ajv-keywords": "^3.1.0"
|
"ajv-keywords": "^3.1.0"
|
||||||
|
@ -12485,6 +12575,7 @@
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-2.3.2.tgz",
|
||||||
"integrity": "sha1-3YaybBn+O5FPBOoQ7zlZTq3gRGQ=",
|
"integrity": "sha1-3YaybBn+O5FPBOoQ7zlZTq3gRGQ=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"file-loader": "1.1.11",
|
"file-loader": "1.1.11",
|
||||||
"loader-utils": "1.1.0"
|
"loader-utils": "1.1.0"
|
||||||
|
@ -12494,6 +12585,7 @@
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
||||||
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loader-utils": "^1.0.2",
|
"loader-utils": "^1.0.2",
|
||||||
"schema-utils": "^0.4.5"
|
"schema-utils": "^0.4.5"
|
||||||
|
@ -12965,6 +13057,7 @@
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
"redux-actions": "^2.4.0",
|
"redux-actions": "^2.4.0",
|
||||||
"redux-form": "^7.4.2",
|
"redux-form": "^7.4.2",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"svg-url-loader": "^2.3.2",
|
|
||||||
"url-polyfill": "^1.1.7"
|
"url-polyfill": "^1.1.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -54,6 +53,7 @@
|
||||||
"eslint": "^4.19.1",
|
"eslint": "^4.19.1",
|
||||||
"eslint-config-airbnb-base": "^12.1.0",
|
"eslint-config-airbnb-base": "^12.1.0",
|
||||||
"eslint-config-react-app": "^2.1.0",
|
"eslint-config-react-app": "^2.1.0",
|
||||||
|
"eslint-import-resolver-webpack": "^0.12.1",
|
||||||
"eslint-loader": "1.9.0",
|
"eslint-loader": "1.9.0",
|
||||||
"eslint-plugin-import": "^2.12.0",
|
"eslint-plugin-import": "^2.12.0",
|
||||||
"eslint-plugin-jsx-a11y": "5.1.1",
|
"eslint-plugin-jsx-a11y": "5.1.1",
|
||||||
|
@ -74,6 +74,7 @@
|
||||||
"url-loader": "^1.0.1",
|
"url-loader": "^1.0.1",
|
||||||
"webpack": "3.8.1",
|
"webpack": "3.8.1",
|
||||||
"webpack-dev-server": "^3.1.14",
|
"webpack-dev-server": "^3.1.14",
|
||||||
"webpack-merge": "^4.1.3"
|
"webpack-merge": "^4.1.3",
|
||||||
|
"svg-url-loader": "^2.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { t } from 'i18next';
|
||||||
|
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { addErrorToast, addSuccessToast } from './index';
|
import { addErrorToast, addSuccessToast } from './index';
|
||||||
import { getStats, getStatsConfig } from './stats';
|
|
||||||
import { normalizeTextarea } from '../helpers/helpers';
|
import { normalizeTextarea } from '../helpers/helpers';
|
||||||
import { ACTION } from '../helpers/constants';
|
import { ACTION } from '../helpers/constants';
|
||||||
|
|
||||||
|
@ -50,11 +49,13 @@ export const toggleClientBlockRequest = createAction('TOGGLE_CLIENT_BLOCK_REQUES
|
||||||
export const toggleClientBlockFailure = createAction('TOGGLE_CLIENT_BLOCK_FAILURE');
|
export const toggleClientBlockFailure = createAction('TOGGLE_CLIENT_BLOCK_FAILURE');
|
||||||
export const toggleClientBlockSuccess = createAction('TOGGLE_CLIENT_BLOCK_SUCCESS');
|
export const toggleClientBlockSuccess = createAction('TOGGLE_CLIENT_BLOCK_SUCCESS');
|
||||||
|
|
||||||
export const toggleClientBlock = (type, ip) => async (dispatch, getState) => {
|
export const toggleClientBlock = (type, ip) => async (dispatch) => {
|
||||||
dispatch(toggleClientBlockRequest());
|
dispatch(toggleClientBlockRequest());
|
||||||
try {
|
try {
|
||||||
const { allowed_clients, disallowed_clients, blocked_hosts } = getState().access;
|
const {
|
||||||
let updatedDisallowedClients = normalizeTextarea(disallowed_clients);
|
allowed_clients, disallowed_clients, blocked_hosts,
|
||||||
|
} = await apiClient.getAccessList();
|
||||||
|
let updatedDisallowedClients = disallowed_clients;
|
||||||
|
|
||||||
if (type === ACTION.unblock && updatedDisallowedClients.includes(ip)) {
|
if (type === ACTION.unblock && updatedDisallowedClients.includes(ip)) {
|
||||||
updatedDisallowedClients = updatedDisallowedClients.filter(client => client !== ip);
|
updatedDisallowedClients = updatedDisallowedClients.filter(client => client !== ip);
|
||||||
|
@ -63,23 +64,19 @@ export const toggleClientBlock = (type, ip) => async (dispatch, getState) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
allowed_clients: normalizeTextarea(allowed_clients),
|
allowed_clients,
|
||||||
blocked_hosts: normalizeTextarea(blocked_hosts),
|
blocked_hosts,
|
||||||
disallowed_clients: updatedDisallowedClients,
|
disallowed_clients: updatedDisallowedClients,
|
||||||
};
|
};
|
||||||
|
|
||||||
await apiClient.setAccessList(values);
|
await apiClient.setAccessList(values);
|
||||||
dispatch(toggleClientBlockSuccess());
|
dispatch(toggleClientBlockSuccess(values));
|
||||||
|
|
||||||
if (type === ACTION.unblock) {
|
if (type === ACTION.unblock) {
|
||||||
dispatch(addSuccessToast(t('client_unblocked', { ip })));
|
dispatch(addSuccessToast(t('client_unblocked', { ip })));
|
||||||
} else if (type === ACTION.block) {
|
} else if (type === ACTION.block) {
|
||||||
dispatch(addSuccessToast(t('client_blocked', { ip })));
|
dispatch(addSuccessToast(t('client_blocked', { ip })));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(getStats());
|
|
||||||
dispatch(getStatsConfig());
|
|
||||||
dispatch(getAccessList());
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(addErrorToast({ error }));
|
dispatch(addErrorToast({ error }));
|
||||||
dispatch(toggleClientBlockFailure());
|
dispatch(toggleClientBlockFailure());
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createAction } from 'redux-actions';
|
||||||
|
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { addErrorToast, addSuccessToast } from './index';
|
import { addErrorToast, addSuccessToast } from './index';
|
||||||
import { normalizeTopStats, secondsToMilliseconds, getParamsForClientsSearch, addClientInfo, addClientStatus } from '../helpers/helpers';
|
import { normalizeTopStats, secondsToMilliseconds, getParamsForClientsSearch, addClientInfo } from '../helpers/helpers';
|
||||||
|
|
||||||
export const getStatsConfigRequest = createAction('GET_STATS_CONFIG_REQUEST');
|
export const getStatsConfigRequest = createAction('GET_STATS_CONFIG_REQUEST');
|
||||||
export const getStatsConfigFailure = createAction('GET_STATS_CONFIG_FAILURE');
|
export const getStatsConfigFailure = createAction('GET_STATS_CONFIG_FAILURE');
|
||||||
|
@ -46,15 +46,12 @@ export const getStats = () => async (dispatch) => {
|
||||||
const normalizedTopClients = normalizeTopStats(stats.top_clients);
|
const normalizedTopClients = normalizeTopStats(stats.top_clients);
|
||||||
const clientsParams = getParamsForClientsSearch(normalizedTopClients, 'name');
|
const clientsParams = getParamsForClientsSearch(normalizedTopClients, 'name');
|
||||||
const clients = await apiClient.findClients(clientsParams);
|
const clients = await apiClient.findClients(clientsParams);
|
||||||
const accessData = await apiClient.getAccessList();
|
|
||||||
const { disallowed_clients } = accessData;
|
|
||||||
const topClientsWithInfo = addClientInfo(normalizedTopClients, clients, 'name');
|
const topClientsWithInfo = addClientInfo(normalizedTopClients, clients, 'name');
|
||||||
const topClientsWithStatus = addClientStatus(topClientsWithInfo, disallowed_clients, 'name');
|
|
||||||
|
|
||||||
const normalizedStats = {
|
const normalizedStats = {
|
||||||
...stats,
|
...stats,
|
||||||
top_blocked_domains: normalizeTopStats(stats.top_blocked_domains),
|
top_blocked_domains: normalizeTopStats(stats.top_blocked_domains),
|
||||||
top_clients: topClientsWithStatus,
|
top_clients: topClientsWithInfo,
|
||||||
top_queried_domains: normalizeTopStats(stats.top_queried_domains),
|
top_queried_domains: normalizeTopStats(stats.top_queried_domains),
|
||||||
avg_processing_time: secondsToMilliseconds(stats.avg_processing_time),
|
avg_processing_time: secondsToMilliseconds(stats.avg_processing_time),
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,10 +57,12 @@ const renderBlockingButton = (blocked, ip, handleClick, processing) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const clientCell = (t, toggleClientStatus, processing) =>
|
const isBlockedClient = (clients, ip) => !!(clients && clients.includes(ip));
|
||||||
|
|
||||||
|
const clientCell = (t, toggleClientStatus, processing, disallowedClients) =>
|
||||||
function cell(row) {
|
function cell(row) {
|
||||||
const { original, value } = row;
|
const { value } = row;
|
||||||
const { blocked } = original;
|
const blocked = isBlockedClient(disallowedClients, value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -80,6 +82,7 @@ const Clients = ({
|
||||||
dnsQueries,
|
dnsQueries,
|
||||||
toggleClientStatus,
|
toggleClientStatus,
|
||||||
processingAccessSet,
|
processingAccessSet,
|
||||||
|
disallowedClients,
|
||||||
}) => (
|
}) => (
|
||||||
<Card
|
<Card
|
||||||
title={t('top_clients')}
|
title={t('top_clients')}
|
||||||
|
@ -102,7 +105,7 @@ const Clients = ({
|
||||||
accessor: 'ip',
|
accessor: 'ip',
|
||||||
sortMethod: (a, b) =>
|
sortMethod: (a, b) =>
|
||||||
parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10),
|
parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10),
|
||||||
Cell: clientCell(t, toggleClientStatus, processingAccessSet),
|
Cell: clientCell(t, toggleClientStatus, processingAccessSet, disallowedClients),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: <Trans>requests_count</Trans>,
|
Header: <Trans>requests_count</Trans>,
|
||||||
|
@ -122,9 +125,9 @@ const Clients = ({
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { blocked } = rowInfo.original;
|
const { ip } = rowInfo.original;
|
||||||
|
|
||||||
if (blocked) {
|
if (isBlockedClient(disallowedClients, ip)) {
|
||||||
return {
|
return {
|
||||||
className: 'red',
|
className: 'red',
|
||||||
};
|
};
|
||||||
|
@ -148,6 +151,7 @@ Clients.propTypes = {
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
toggleClientStatus: PropTypes.func.isRequired,
|
toggleClientStatus: PropTypes.func.isRequired,
|
||||||
processingAccessSet: PropTypes.bool.isRequired,
|
processingAccessSet: PropTypes.bool.isRequired,
|
||||||
|
disallowedClients: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withNamespaces()(Clients);
|
export default withNamespaces()(Clients);
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Dashboard extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllStats = () => {
|
getAllStats = () => {
|
||||||
|
this.props.getAccessList();
|
||||||
this.props.getStats();
|
this.props.getStats();
|
||||||
this.props.getStatsConfig();
|
this.props.getStatsConfig();
|
||||||
};
|
};
|
||||||
|
@ -53,7 +54,8 @@ class Dashboard extends Component {
|
||||||
dashboard, stats, access, t,
|
dashboard, stats, access, t,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const statsProcessing = stats.processingStats
|
const statsProcessing = stats.processingStats
|
||||||
|| stats.processingGetConfig;
|
|| stats.processingGetConfig
|
||||||
|
|| access.processing;
|
||||||
|
|
||||||
const subtitle =
|
const subtitle =
|
||||||
stats.interval === 1
|
stats.interval === 1
|
||||||
|
@ -130,6 +132,7 @@ class Dashboard extends Component {
|
||||||
refreshButton={refreshButton}
|
refreshButton={refreshButton}
|
||||||
toggleClientStatus={this.toggleClientStatus}
|
toggleClientStatus={this.toggleClientStatus}
|
||||||
processingAccessSet={access.processingSet}
|
processingAccessSet={access.processingSet}
|
||||||
|
disallowedClients={access.disallowed_clients}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-6">
|
<div className="col-lg-6">
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans, withNamespaces } from 'react-i18next';
|
import { Trans, withNamespaces } from 'react-i18next';
|
||||||
import { REPOSITORY, LANGUAGES, PRIVACY_POLICY_LINK } from '../../helpers/constants';
|
|
||||||
|
import { REPOSITORY, PRIVACY_POLICY_LINK } from '../../helpers/constants';
|
||||||
|
import { LANGUAGES } from '../../helpers/twosky';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
|
|
||||||
import Version from './Version';
|
import Version from './Version';
|
||||||
|
@ -68,9 +70,9 @@ class Footer extends Component {
|
||||||
value={i18n.language}
|
value={i18n.language}
|
||||||
onChange={this.changeLanguage}
|
onChange={this.changeLanguage}
|
||||||
>
|
>
|
||||||
{LANGUAGES.map(language => (
|
{Object.keys(LANGUAGES).map(lang => (
|
||||||
<option key={language.key} value={language.key}>
|
<option key={lang} value={lang}>
|
||||||
{language.name}
|
{LANGUAGES[lang]}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -31,117 +31,6 @@ export const REPOSITORY = {
|
||||||
|
|
||||||
export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html';
|
export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html';
|
||||||
|
|
||||||
export const LANGUAGES = [
|
|
||||||
{
|
|
||||||
key: 'da',
|
|
||||||
name: 'Dansk',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'de',
|
|
||||||
name: 'Deutsch',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'nl',
|
|
||||||
name: 'Dutch',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'en',
|
|
||||||
name: 'English',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'es',
|
|
||||||
name: 'Español',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fr',
|
|
||||||
name: 'Français',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'id',
|
|
||||||
name: 'Indonesian',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'it',
|
|
||||||
name: 'Italiano',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'pl',
|
|
||||||
name: 'Polski',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'pt-br',
|
|
||||||
name: 'Portuguese (BR)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'pt-pt',
|
|
||||||
name: 'Portuguese (PT)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sk',
|
|
||||||
name: 'Slovenčina',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sl',
|
|
||||||
name: 'Slovenščina',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sv',
|
|
||||||
name: 'Svenska',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'vi',
|
|
||||||
name: 'Tiếng Việt',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'tr',
|
|
||||||
name: 'Türkçe',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'cs',
|
|
||||||
name: 'Český',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bg',
|
|
||||||
name: 'Български',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'ru',
|
|
||||||
name: 'Русский',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'ja',
|
|
||||||
name: '日本語',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zh-tw',
|
|
||||||
name: '正體中文',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zh-cn',
|
|
||||||
name: '简体中文',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'no',
|
|
||||||
name: 'Norsk',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'sr-cs',
|
|
||||||
name: 'Srpski',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'hr',
|
|
||||||
name: 'Hrvatski',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fa',
|
|
||||||
name: 'فارسی',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'ko',
|
|
||||||
name: '한국어',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const INSTALL_FIRST_STEP = 1;
|
export const INSTALL_FIRST_STEP = 1;
|
||||||
export const INSTALL_TOTAL_STEPS = 5;
|
export const INSTALL_TOTAL_STEPS = 5;
|
||||||
|
|
||||||
|
|
|
@ -122,17 +122,6 @@ export const addClientInfo = (data, clients, param) => (
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export const addClientStatus = (data, disallowedClients, param) => (
|
|
||||||
data.map((row) => {
|
|
||||||
const clientIp = row[param];
|
|
||||||
const blocked = !!(disallowedClients && disallowedClients.includes(clientIp));
|
|
||||||
return {
|
|
||||||
...row,
|
|
||||||
blocked,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export const normalizeFilteringStatus = (filteringStatus) => {
|
export const normalizeFilteringStatus = (filteringStatus) => {
|
||||||
const {
|
const {
|
||||||
enabled, filters, user_rules: userRules, interval,
|
enabled, filters, user_rules: userRules, interval,
|
||||||
|
|
|
@ -96,6 +96,11 @@
|
||||||
"name": "Microsoft Azure",
|
"name": "Microsoft Azure",
|
||||||
"categoryId": 10,
|
"categoryId": 10,
|
||||||
"url": "https://azure.microsoft.com/"
|
"url": "https://azure.microsoft.com/"
|
||||||
|
},
|
||||||
|
"button": {
|
||||||
|
"name": "Button",
|
||||||
|
"categoryId": 4,
|
||||||
|
"url": "https://www.usebutton.com/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"trackerDomains": {
|
"trackerDomains": {
|
||||||
|
@ -119,6 +124,7 @@
|
||||||
"edgecastcdn.net": "markmonitor",
|
"edgecastcdn.net": "markmonitor",
|
||||||
"appcenter.ms": "appcenter",
|
"appcenter.ms": "appcenter",
|
||||||
"unityads.unity3d.com": "unity_ads",
|
"unityads.unity3d.com": "unity_ads",
|
||||||
"azure.com": "azure"
|
"azure.com": "azure",
|
||||||
|
"bttn.io": "button"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -696,11 +696,6 @@
|
||||||
"categoryId": 4,
|
"categoryId": 4,
|
||||||
"url": "http://adgoto.com/"
|
"url": "http://adgoto.com/"
|
||||||
},
|
},
|
||||||
"adguard": {
|
|
||||||
"name": "Adguard",
|
|
||||||
"categoryId": 12,
|
|
||||||
"url": "https://adguard.com/"
|
|
||||||
},
|
|
||||||
"adhands": {
|
"adhands": {
|
||||||
"name": "AdHands",
|
"name": "AdHands",
|
||||||
"categoryId": 4,
|
"categoryId": 4,
|
||||||
|
@ -16201,7 +16196,6 @@
|
||||||
"smartredirect.de": "adgoal",
|
"smartredirect.de": "adgoal",
|
||||||
"adgorithms.com": "adgorithms",
|
"adgorithms.com": "adgorithms",
|
||||||
"adgoto.com": "adgoto",
|
"adgoto.com": "adgoto",
|
||||||
"adguard.com": "adguard",
|
|
||||||
"adhands.ru": "adhands",
|
"adhands.ru": "adhands",
|
||||||
"adhese.be": "adhese",
|
"adhese.be": "adhese",
|
||||||
"adhese.com": "adhese",
|
"adhese.com": "adhese",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import twosky from 'MainRoot/.twosky.json';
|
||||||
|
|
||||||
|
export const {
|
||||||
|
languages: LANGUAGES,
|
||||||
|
base_locale: BASE_LOCALE,
|
||||||
|
} = twosky[0];
|
|
@ -3,7 +3,7 @@ import { reactI18nextModule } from 'react-i18next';
|
||||||
import { initReactI18n } from 'react-i18next/hooks';
|
import { initReactI18n } from 'react-i18next/hooks';
|
||||||
import langDetect from 'i18next-browser-languagedetector';
|
import langDetect from 'i18next-browser-languagedetector';
|
||||||
|
|
||||||
import { DEFAULT_LANGUAGE } from './helpers/constants';
|
import { LANGUAGES, BASE_LOCALE } from './helpers/twosky';
|
||||||
|
|
||||||
import vi from './__locales/vi.json';
|
import vi from './__locales/vi.json';
|
||||||
import en from './__locales/en.json';
|
import en from './__locales/en.json';
|
||||||
|
@ -117,7 +117,7 @@ const resources = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const availableLanguages = Object.keys(resources);
|
const availableLanguages = Object.keys(LANGUAGES);
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(langDetect)
|
.use(langDetect)
|
||||||
|
@ -126,7 +126,7 @@ i18n
|
||||||
.init({
|
.init({
|
||||||
resources,
|
resources,
|
||||||
lowerCaseLng: true,
|
lowerCaseLng: true,
|
||||||
fallbackLng: DEFAULT_LANGUAGE,
|
fallbackLng: BASE_LOCALE,
|
||||||
keySeparator: false,
|
keySeparator: false,
|
||||||
nsSeparator: false,
|
nsSeparator: false,
|
||||||
returnEmptyString: false,
|
returnEmptyString: false,
|
||||||
|
@ -136,9 +136,10 @@ i18n
|
||||||
react: {
|
react: {
|
||||||
wait: true,
|
wait: true,
|
||||||
},
|
},
|
||||||
|
whitelist: availableLanguages,
|
||||||
}, () => {
|
}, () => {
|
||||||
if (!availableLanguages.includes(i18n.language)) {
|
if (!availableLanguages.includes(i18n.language)) {
|
||||||
i18n.changeLanguage(DEFAULT_LANGUAGE);
|
i18n.changeLanguage(BASE_LOCALE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,21 @@ const access = handleActions(
|
||||||
|
|
||||||
[actions.toggleClientBlockRequest]: state => ({ ...state, processingSet: true }),
|
[actions.toggleClientBlockRequest]: state => ({ ...state, processingSet: true }),
|
||||||
[actions.toggleClientBlockFailure]: state => ({ ...state, processingSet: false }),
|
[actions.toggleClientBlockFailure]: state => ({ ...state, processingSet: false }),
|
||||||
[actions.toggleClientBlockSuccess]: state => ({ ...state, processingSet: false }),
|
[actions.toggleClientBlockSuccess]: (state, { payload }) => {
|
||||||
|
const {
|
||||||
|
allowed_clients,
|
||||||
|
disallowed_clients,
|
||||||
|
blocked_hosts,
|
||||||
|
} = payload;
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '',
|
||||||
|
disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '',
|
||||||
|
blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '',
|
||||||
|
processingSet: false,
|
||||||
|
};
|
||||||
|
return newState;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
processing: true,
|
processing: true,
|
||||||
|
|
|
@ -32,6 +32,10 @@ const config = {
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
modules: ['node_modules'],
|
modules: ['node_modules'],
|
||||||
|
alias: {
|
||||||
|
MainRoot: path.resolve(__dirname, '../'),
|
||||||
|
ClientRoot: path.resolve(__dirname, './src'),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
@ -101,7 +105,7 @@ const config = {
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||||
}),
|
}),
|
||||||
new CleanWebpackPlugin(['*.*'], {
|
new CleanWebpackPlugin(['**/*.*'], {
|
||||||
root: PUBLIC_PATH,
|
root: PUBLIC_PATH,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
dry: false,
|
dry: false,
|
||||||
|
|
|
@ -225,7 +225,7 @@ func (d *Dnsfilter) filtersInitializer() {
|
||||||
// Close - close the object
|
// Close - close the object
|
||||||
func (d *Dnsfilter) Close() {
|
func (d *Dnsfilter) Close() {
|
||||||
if d.rulesStorage != nil {
|
if d.rulesStorage != nil {
|
||||||
d.rulesStorage.Close()
|
_ = d.rulesStorage.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,8 +127,8 @@ func (d *Dnsfilter) checkSafeSearch(host string) (Result, error) {
|
||||||
res := Result{IsFiltered: true, Reason: FilteredSafeSearch}
|
res := Result{IsFiltered: true, Reason: FilteredSafeSearch}
|
||||||
if ip := net.ParseIP(safeHost); ip != nil {
|
if ip := net.ParseIP(safeHost); ip != nil {
|
||||||
res.IP = ip
|
res.IP = ip
|
||||||
len := d.setCacheResult(gctx.safeSearchCache, host, res)
|
valLen := d.setCacheResult(gctx.safeSearchCache, host, res)
|
||||||
log.Debug("SafeSearch: stored in cache: %s (%d bytes)", host, len)
|
log.Debug("SafeSearch: stored in cache: %s (%d bytes)", host, valLen)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,8 +151,8 @@ func (d *Dnsfilter) checkSafeSearch(host string) (Result, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache result
|
// Cache result
|
||||||
len := d.setCacheResult(gctx.safeSearchCache, host, res)
|
valLen := d.setCacheResult(gctx.safeSearchCache, host, res)
|
||||||
log.Debug("SafeSearch: stored in cache: %s (%d bytes)", host, len)
|
log.Debug("SafeSearch: stored in cache: %s (%d bytes)", host, valLen)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +243,8 @@ func (d *Dnsfilter) checkSafeBrowsing(host string) (Result, error) {
|
||||||
result.Rule = "adguard-malware-shavar"
|
result.Rule = "adguard-malware-shavar"
|
||||||
}
|
}
|
||||||
|
|
||||||
len := d.setCacheResult(gctx.safebrowsingCache, host, result)
|
valLen := d.setCacheResult(gctx.safebrowsingCache, host, result)
|
||||||
log.Debug("SafeBrowsing: stored in cache: %s (%d bytes)", host, len)
|
log.Debug("SafeBrowsing: stored in cache: %s (%d bytes)", host, valLen)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,8 +283,8 @@ func (d *Dnsfilter) checkParental(host string) (Result, error) {
|
||||||
result.Rule = "parental CATEGORY_BLACKLISTED"
|
result.Rule = "parental CATEGORY_BLACKLISTED"
|
||||||
}
|
}
|
||||||
|
|
||||||
len := d.setCacheResult(gctx.parentalCache, host, result)
|
valLen := d.setCacheResult(gctx.parentalCache, host, result)
|
||||||
log.Debug("Parental: stored in cache: %s (%d bytes)", host, len)
|
log.Debug("Parental: stored in cache: %s (%d bytes)", host, valLen)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -883,7 +883,16 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu
|
||||||
case dnsfilter.FilteredParental:
|
case dnsfilter.FilteredParental:
|
||||||
return s.genBlockedHost(m, s.conf.ParentalBlockHost, d)
|
return s.genBlockedHost(m, s.conf.ParentalBlockHost, d)
|
||||||
default:
|
default:
|
||||||
|
// If the query was filtered by "Safe search", dnsfilter also must return
|
||||||
|
// the IP address that must be used in response.
|
||||||
|
// In this case regardless of the filtering method, we should return it
|
||||||
|
if result.Reason == dnsfilter.FilteredSafeSearch && result.IP != nil {
|
||||||
|
return s.genResponseWithIP(m, result.IP)
|
||||||
|
}
|
||||||
|
|
||||||
if s.conf.BlockingMode == "null_ip" {
|
if s.conf.BlockingMode == "null_ip" {
|
||||||
|
// it means that we should return 0.0.0.0 or :: for any blocked request
|
||||||
|
|
||||||
switch m.Question[0].Qtype {
|
switch m.Question[0].Qtype {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
return s.genARecord(m, []byte{0, 0, 0, 0})
|
return s.genARecord(m, []byte{0, 0, 0, 0})
|
||||||
|
@ -892,6 +901,8 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if s.conf.BlockingMode == "custom_ip" {
|
} else if s.conf.BlockingMode == "custom_ip" {
|
||||||
|
// means that we should return custom IP for any blocked request
|
||||||
|
|
||||||
switch m.Question[0].Qtype {
|
switch m.Question[0].Qtype {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
return s.genARecord(m, s.conf.BlockingIPAddrv4)
|
return s.genARecord(m, s.conf.BlockingIPAddrv4)
|
||||||
|
@ -900,9 +911,14 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if s.conf.BlockingMode == "nxdomain" {
|
} else if s.conf.BlockingMode == "nxdomain" {
|
||||||
|
// means that we should return NXDOMAIN for any blocked request
|
||||||
|
|
||||||
return s.genNXDomain(m)
|
return s.genNXDomain(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default blocking mode
|
||||||
|
// If there's an IP specified in the rule, return it
|
||||||
|
// If there is no IP, return NXDOMAIN
|
||||||
if result.IP != nil {
|
if result.IP != nil {
|
||||||
return s.genResponseWithIP(m, result.IP)
|
return s.genResponseWithIP(m, result.IP)
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,7 +379,8 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if r.URL.Path == "/favicon.png" ||
|
} else if r.URL.Path == "/favicon.png" ||
|
||||||
strings.HasPrefix(r.URL.Path, "/login.") {
|
strings.HasPrefix(r.URL.Path, "/login.") ||
|
||||||
|
strings.HasPrefix(r.URL.Path, "/__locales/") {
|
||||||
// process as usual
|
// process as usual
|
||||||
|
|
||||||
} else if config.auth != nil && config.auth.AuthRequired() {
|
} else if config.auth != nil && config.auth.AuthRequired() {
|
||||||
|
|
|
@ -42,8 +42,10 @@ func getVersionResp(data []byte) []byte {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the key is download_linux_arm or download_linux_arm64 for regular ARM versions
|
||||||
dloadName := fmt.Sprintf("download_%s_%s", runtime.GOOS, runtime.GOARCH)
|
dloadName := fmt.Sprintf("download_%s_%s", runtime.GOOS, runtime.GOARCH)
|
||||||
if runtime.GOARCH == "arm" && ARMVersion != "6" {
|
if runtime.GOARCH == "arm" && ARMVersion == "5" {
|
||||||
|
// the key is download_linux_armv5 for ARMv5
|
||||||
dloadName = fmt.Sprintf("download_%s_%sv%s", runtime.GOOS, runtime.GOARCH, ARMVersion)
|
dloadName = fmt.Sprintf("download_%s_%sv%s", runtime.GOOS, runtime.GOARCH, ARMVersion)
|
||||||
}
|
}
|
||||||
_, ok := versionJSON[dloadName]
|
_, ok := versionJSON[dloadName]
|
||||||
|
@ -152,15 +154,6 @@ type updateInfo struct {
|
||||||
newBinName string // Full path to the new executable file
|
newBinName string // Full path to the new executable file
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return TRUE if file exists
|
|
||||||
func fileExists(fn string) bool {
|
|
||||||
_, err := os.Stat(fn)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in updateInfo object
|
// Fill in updateInfo object
|
||||||
func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
func getUpdateInfo(jsonData []byte) (*updateInfo, error) {
|
||||||
var u updateInfo
|
var u updateInfo
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -190,6 +191,30 @@ func customDialContext(ctx context.Context, network, addr string) (net.Conn, err
|
||||||
return nil, errorx.DecorateMany(fmt.Sprintf("couldn't dial to %s", addr), dialErrs...)
|
return nil, errorx.DecorateMany(fmt.Sprintf("couldn't dial to %s", addr), dialErrs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------
|
||||||
|
// general helpers
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
// fileExists returns TRUE if file exists
|
||||||
|
func fileExists(fn string) bool {
|
||||||
|
_, err := os.Stat(fn)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// runCommand runs shell command
|
||||||
|
func runCommand(command string, arguments ...string) (int, string, error) {
|
||||||
|
cmd := exec.Command(command, arguments...)
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return 1, "", fmt.Errorf("exec.Command(%s) failed: %s", command, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd.ProcessState.ExitCode(), string(out), nil
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// debug logging helpers
|
// debug logging helpers
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
|
|
@ -101,7 +101,11 @@ func run(args options) {
|
||||||
configureLogger(args)
|
configureLogger(args)
|
||||||
|
|
||||||
// print the first message after logger is configured
|
// print the first message after logger is configured
|
||||||
log.Printf("AdGuard Home, version %s, channel %s\n", versionString, updateChannel)
|
msg := "AdGuard Home, version %s, channel %s\n, arch %s %s"
|
||||||
|
if ARMVersion != "" {
|
||||||
|
msg = msg + " v" + ARMVersion
|
||||||
|
}
|
||||||
|
log.Printf(msg, versionString, updateChannel, runtime.GOOS, runtime.GOARCH, ARMVersion)
|
||||||
log.Debug("Current working directory is %s", config.ourWorkingDir)
|
log.Debug("Current working directory is %s", config.ourWorkingDir)
|
||||||
if args.runningAsService {
|
if args.runningAsService {
|
||||||
log.Info("AdGuard Home is running as a service")
|
log.Info("AdGuard Home is running as a service")
|
||||||
|
|
237
home/service.go
237
home/service.go
|
@ -1,10 +1,10 @@
|
||||||
package home
|
package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
@ -41,23 +41,12 @@ func (p *program) Stop(s service.Service) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommand(command string, arguments ...string) (int, string, error) {
|
|
||||||
cmd := exec.Command(command, arguments...)
|
|
||||||
out, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return 1, "", fmt.Errorf("exec.Command(%s) failed: %s", command, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd.ProcessState.ExitCode(), string(out), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the service's status
|
// Check the service's status
|
||||||
// Note: on OpenWrt 'service' utility may not exist - we use our service script directly in this case.
|
// Note: on OpenWrt 'service' utility may not exist - we use our service script directly in this case.
|
||||||
func svcStatus(s service.Service) (service.Status, error) {
|
func svcStatus(s service.Service) (service.Status, error) {
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if err != nil && service.Platform() == "unix-systemv" {
|
if err != nil && service.Platform() == "unix-systemv" {
|
||||||
confPath := "/etc/init.d/" + serviceName
|
code, err := runInitdCommand("status")
|
||||||
code, _, err := runCommand("sh", "-c", confPath+" status")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return service.StatusStopped, nil
|
return service.StatusStopped, nil
|
||||||
}
|
}
|
||||||
|
@ -75,8 +64,7 @@ func svcAction(s service.Service, action string) error {
|
||||||
err := service.Control(s, action)
|
err := service.Control(s, action)
|
||||||
if err != nil && service.Platform() == "unix-systemv" &&
|
if err != nil && service.Platform() == "unix-systemv" &&
|
||||||
(action == "start" || action == "stop" || action == "restart") {
|
(action == "start" || action == "stop" || action == "restart") {
|
||||||
confPath := "/etc/init.d/" + serviceName
|
_, err := runInitdCommand(action)
|
||||||
_, _, err := runCommand("sh", "-c", confPath+" "+action)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -114,61 +102,100 @@ func handleServiceControlAction(action string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if action == "status" {
|
if action == "status" {
|
||||||
status, errSt := svcStatus(s)
|
handleServiceStatusCommand(s)
|
||||||
if errSt != nil {
|
|
||||||
log.Fatalf("failed to get service status: %s", errSt)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch status {
|
|
||||||
case service.StatusUnknown:
|
|
||||||
log.Printf("Service status is unknown")
|
|
||||||
case service.StatusStopped:
|
|
||||||
log.Printf("Service is stopped")
|
|
||||||
case service.StatusRunning:
|
|
||||||
log.Printf("Service is running")
|
|
||||||
}
|
|
||||||
} else if action == "run" {
|
} else if action == "run" {
|
||||||
err = s.Run()
|
err = s.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to run service: %s", err)
|
log.Fatalf("Failed to run service: %s", err)
|
||||||
}
|
}
|
||||||
|
} else if action == "install" {
|
||||||
|
handleServiceInstallCommand(s)
|
||||||
|
} else if action == "uninstall" {
|
||||||
|
handleServiceUninstallCommand(s)
|
||||||
} else {
|
} else {
|
||||||
if action == "uninstall" {
|
|
||||||
// In case of Windows and Linux when a running service is being uninstalled,
|
|
||||||
// it is just marked for deletion but not stopped
|
|
||||||
// So we explicitly stop it here
|
|
||||||
_ = svcAction(s, "stop")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = svcAction(s, action)
|
err = svcAction(s, action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Printf("Action %s has been done successfully on %s", action, service.ChosenSystem().String())
|
}
|
||||||
|
|
||||||
if action == "install" {
|
log.Printf("Action %s has been done successfully on %s", action, service.ChosenSystem().String())
|
||||||
err := afterInstall()
|
}
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start automatically after install
|
// handleServiceStatusCommand handles service "status" command
|
||||||
err = svcAction(s, "start")
|
func handleServiceStatusCommand(s service.Service) {
|
||||||
if err != nil {
|
status, errSt := svcStatus(s)
|
||||||
log.Fatalf("Failed to start the service: %s", err)
|
if errSt != nil {
|
||||||
}
|
log.Fatalf("failed to get service status: %s", errSt)
|
||||||
log.Printf("Service has been started")
|
}
|
||||||
|
|
||||||
if detectFirstRun() {
|
switch status {
|
||||||
log.Printf(`Almost ready!
|
case service.StatusUnknown:
|
||||||
|
log.Printf("Service status is unknown")
|
||||||
|
case service.StatusStopped:
|
||||||
|
log.Printf("Service is stopped")
|
||||||
|
case service.StatusRunning:
|
||||||
|
log.Printf("Service is running")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleServiceStatusCommand handles service "install" command
|
||||||
|
func handleServiceInstallCommand(s service.Service) {
|
||||||
|
err := svcAction(s, "install")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if isOpenWrt() {
|
||||||
|
// On OpenWrt it is important to run enable after the service installation
|
||||||
|
// Otherwise, the service won't start on the system startup
|
||||||
|
_, err := runInitdCommand("enable")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start automatically after install
|
||||||
|
err = svcAction(s, "start")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to start the service: %s", err)
|
||||||
|
}
|
||||||
|
log.Printf("Service has been started")
|
||||||
|
|
||||||
|
if detectFirstRun() {
|
||||||
|
log.Printf(`Almost ready!
|
||||||
AdGuard Home is successfully installed and will automatically start on boot.
|
AdGuard Home is successfully installed and will automatically start on boot.
|
||||||
There are a few more things that must be configured before you can use it.
|
There are a few more things that must be configured before you can use it.
|
||||||
Click on the link below and follow the Installation Wizard steps to finish setup.`)
|
Click on the link below and follow the Installation Wizard steps to finish setup.`)
|
||||||
printHTTPAddresses("http")
|
printHTTPAddresses("http")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if action == "uninstall" {
|
// handleServiceStatusCommand handles service "uninstall" command
|
||||||
cleanupService()
|
func handleServiceUninstallCommand(s service.Service) {
|
||||||
|
if isOpenWrt() {
|
||||||
|
// On OpenWrt it is important to run disable command first
|
||||||
|
// as it will remove the symlink
|
||||||
|
_, err := runInitdCommand("disable")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := svcAction(s, "uninstall")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
// Removing log files on cleanup and ignore errors
|
||||||
|
err := os.Remove(launchdStdoutPath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
log.Printf("cannot remove %s", launchdStdoutPath)
|
||||||
|
}
|
||||||
|
err = os.Remove(launchdStderrPath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
log.Printf("cannot remove %s", launchdStderrPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,43 +218,33 @@ func configureService(c *service.Config) {
|
||||||
// Use modified service file templates
|
// Use modified service file templates
|
||||||
c.Option["SystemdScript"] = systemdScript
|
c.Option["SystemdScript"] = systemdScript
|
||||||
c.Option["SysvScript"] = sysvScript
|
c.Option["SysvScript"] = sysvScript
|
||||||
|
|
||||||
|
// On OpenWrt we're using a different type of sysvScript
|
||||||
|
if isOpenWrt() {
|
||||||
|
c.Option["SysvScript"] = openWrtScript
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On SysV systems supported by kardianos/service package, there must be multiple /etc/rc{N}.d directories.
|
// runInitdCommand runs init.d service command
|
||||||
// On OpenWrt, however, there is only /etc/rc.d - we handle this case ourselves.
|
// returns command code or error if any
|
||||||
// We also use relative path, because this is how all other service files are set up.
|
func runInitdCommand(action string) (int, error) {
|
||||||
func afterInstall() error {
|
confPath := "/etc/init.d/" + serviceName
|
||||||
if service.Platform() == "unix-systemv" && fileExists("/etc/rc.d") {
|
code, _, err := runCommand("sh", "-c", confPath+" "+action)
|
||||||
confPath := "../init.d/" + serviceName
|
return code, err
|
||||||
err := os.Symlink(confPath, "/etc/rc.d/S99"+serviceName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanupService called on the service uninstall, cleans up additional files if needed
|
// isOpenWrt checks if OS is OpenWRT
|
||||||
func cleanupService() {
|
func isOpenWrt() bool {
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS != "linux" {
|
||||||
// Removing log files on cleanup and ignore errors
|
return false
|
||||||
err := os.Remove(launchdStdoutPath)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
log.Printf("cannot remove %s", launchdStdoutPath)
|
|
||||||
}
|
|
||||||
err = os.Remove(launchdStderrPath)
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
log.Printf("cannot remove %s", launchdStderrPath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.Platform() == "unix-systemv" {
|
body, err := ioutil.ReadFile("/etc/os-release")
|
||||||
fn := "/etc/rc.d/S99" + serviceName
|
if err != nil {
|
||||||
err := os.Remove(fn)
|
return false
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
log.Printf("os.Remove: %s: %s", fn, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return strings.Contains(string(body), "OpenWrt")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basically the same template as the one defined in github.com/kardianos/service
|
// Basically the same template as the one defined in github.com/kardianos/service
|
||||||
|
@ -388,3 +405,55 @@ case "$1" in
|
||||||
esac
|
esac
|
||||||
exit 0
|
exit 0
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// OpenWrt procd init script
|
||||||
|
// https://github.com/AdguardTeam/AdGuardHome/issues/1386
|
||||||
|
const openWrtScript = `#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
USE_PROCD=1
|
||||||
|
|
||||||
|
START=95
|
||||||
|
STOP=01
|
||||||
|
|
||||||
|
cmd="{{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}"
|
||||||
|
name="{{.Name}}"
|
||||||
|
pid_file="/var/run/${name}.pid"
|
||||||
|
|
||||||
|
start_service() {
|
||||||
|
echo "Starting ${name}"
|
||||||
|
|
||||||
|
procd_open_instance
|
||||||
|
procd_set_param command ${cmd}
|
||||||
|
procd_set_param respawn # respawn automatically if something died
|
||||||
|
procd_set_param stdout 1 # forward stdout of the command to logd
|
||||||
|
procd_set_param stderr 1 # same for stderr
|
||||||
|
procd_set_param pidfile ${pid_file} # write a pid file on instance start and remove it on stop
|
||||||
|
|
||||||
|
procd_close_instance
|
||||||
|
echo "${name} has been started"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_service() {
|
||||||
|
echo "Stopping ${name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTRA_COMMANDS="status"
|
||||||
|
EXTRA_HELP=" status Print the service status"
|
||||||
|
|
||||||
|
get_pid() {
|
||||||
|
cat "${pid_file}"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_running() {
|
||||||
|
[ -f "${pid_file}" ] && ps | grep -v grep | grep $(get_pid) >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
if is_running; then
|
||||||
|
echo "Running"
|
||||||
|
else
|
||||||
|
echo "Stopped"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
2
main.go
2
main.go
|
@ -12,7 +12,7 @@ var version = "undefined"
|
||||||
// channel can be set via ldflags
|
// channel can be set via ldflags
|
||||||
var channel = "release"
|
var channel = "release"
|
||||||
|
|
||||||
// ARM version number. Set via linker flags.
|
// GOARM value - set via ldflags
|
||||||
var goarm = ""
|
var goarm = ""
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
Loading…
Reference in New Issue